From f3505f82c0fdc9daac85d2cb2c6338a0292033e7 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 2 Mar 2009 14:28:08 +1030 Subject: [PATCH] From: "Timothy B. Terriberry" Makes the idempotent header check more liberal, and specifically allows it to also recognize #if !defined(someheader) #define someheader (1) or other similar variants. --- tools/ccanlint/idempotent.c | 71 +++++++++++++++++++++++++++++++++---- tools/tools.h | 2 ++ 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/tools/ccanlint/idempotent.c b/tools/ccanlint/idempotent.c index 81984ec7..38d48d83 100644 --- a/tools/ccanlint/idempotent.c +++ b/tools/ccanlint/idempotent.c @@ -11,6 +11,8 @@ #include #include #include +#include +#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; } diff --git a/tools/tools.h b/tools/tools.h index 44951255..84b1fb8a 100644 --- a/tools/tools.h +++ b/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. */ -- 2.39.2