Browse Source

From: "Timothy B. Terriberry" <tterribe@xiph.org>

Makes the idempotent header check more liberal, and
specifically allows it to also recognize

#if !defined(someheader)
#define someheader (1)

or other similar variants.
Rusty Russell 17 years ago
parent
commit
f3505f82c0
2 changed files with 66 additions and 7 deletions
  1. 64 7
      tools/ccanlint/idempotent.c
  2. 2 0
      tools/tools.h

+ 64 - 7
tools/ccanlint/idempotent.c

@@ -11,6 +11,8 @@
 #include <stdio.h>
 #include <err.h>
 #include <string.h>
+#include <ctype.h>
+#include "../tools.h"
 
 static const char explain[] 
 = "Headers usually start with the C preprocessor lines to prevent multiple\n"
@@ -20,26 +22,81 @@ static const char explain[]
   "...\n"
   "#endif /* MY_HEADER_H */\n";
 
+static char *get_ifndef_sym(char *line)
+{
+	line += strspn(line, SPACE_CHARS);
+	if (line[0] == '#')
+	{
+		line++;
+		line += strspn(line, SPACE_CHARS);
+		if (strstarts(line, "ifndef") && isspace(line[6]))
+			return line+6+strspn(line+6, SPACE_CHARS);
+		else if (strstarts(line, "if"))
+		{
+			line += 2;
+			line += strspn(line, SPACE_CHARS);
+			if (line[0] == '!')
+			{
+				line++;
+				line += strspn(line, SPACE_CHARS);
+				if (strstarts(line, "defined"))
+				{
+					line += 7;
+					line += strspn(line, SPACE_CHARS);
+					if (line[0] == '(')
+					{
+						line++;
+						line += strspn(line,
+							SPACE_CHARS);
+					}
+					return line;
+				}
+			}
+		}
+	}
+	return NULL;
+}
+
+static int is_define(char *line, char *id, size_t id_len)
+{
+	line += strspn(line, SPACE_CHARS);
+	if (line[0] == '#')
+	{
+		line++;
+		line += strspn(line, SPACE_CHARS);
+		if (strstarts(line, "define") && isspace(line[6]))
+		{
+			line += 6;
+			line += strspn(line, SPACE_CHARS);
+			if (strspn(line, IDENT_CHARS) == id_len &&
+			    memcmp(id, line, id_len) == 0)
+				return 1;
+		}
+	}
+	return 0;
+}
+
 static char *report_idem(struct ccan_file *f, char *sofar)
 {
 	char **lines;
-	char *secondline;
+	char *id;
+	size_t id_len;
 
 	lines = get_ccan_file_lines(f);
 	if (f->num_lines < 3)
 		/* FIXME: We assume small headers probably uninteresting. */
 		return NULL;
 
-	if (!strstarts(lines[0], "#ifndef "))
+	id = get_ifndef_sym(lines[0]);
+	if (!id)
 		return talloc_asprintf_append(sofar,
 			"%s:1:expect first line to be #ifndef.\n", f->name);
+	id_len = strspn(id, IDENT_CHARS);
 
-	secondline = talloc_asprintf(f, "#define %s",
-				     lines[0] + strlen("#ifndef "));
-	if (!streq(lines[1], secondline))
+	if (!is_define(lines[1], id, id_len))
 		return talloc_asprintf_append(sofar,
-			"%s:2:expect second line to be '%s'.\n",
-			f->name, secondline);
+			"%s:2:expect second line to be '#define %.*s'.\n",
+			f->name, (int)id_len, id);
 
 	return sofar;
 }

+ 2 - 0
tools/tools.h

@@ -6,6 +6,8 @@
 			"abcdefghijklmnopqrstuvwxyz" \
 			"01234567889_"
 
+#define SPACE_CHARS	" \f\n\r\t\v"
+
 #define CFLAGS "-O3 -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -Iccan/ -I."
 
 /* This actually compiles and runs the _info.c file to get dependencies. */