X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=tools%2Fccanlint%2Ffile_analysis.c;h=63d22b8f129513420101f618f459ed4878a34c54;hp=7b2565a983377826fe1f8a9195744b83bbb713cb;hb=163daaf4813b2061b106b9b0077202724e3dca04;hpb=a1585d5b6833783d104acecadce4574115f97cea diff --git a/tools/ccanlint/file_analysis.c b/tools/ccanlint/file_analysis.c index 7b2565a9..63d22b8f 100644 --- a/tools/ccanlint/file_analysis.c +++ b/tools/ccanlint/file_analysis.c @@ -1,3 +1,4 @@ +#include "config.h" #include "ccanlint.h" #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #include "../tools.h" #include #include @@ -33,12 +35,13 @@ static const char *manifest_name(const struct manifest *m) return m->dir; } -static bool dir_cmp(const char *dir1, const char *dir2) +static bool dir_cmp(const struct manifest *m, const char *dir) { - return strcmp(dir1, dir2) == 0; + return strcmp(m->dir, dir) == 0; } -HTABLE_DEFINE_TYPE(struct manifest, manifest_name, dir_hash, dir_cmp, manifest); +HTABLE_DEFINE_TYPE(struct manifest, manifest_name, dir_hash, dir_cmp, + htable_manifest); static struct htable_manifest *manifests; const char *get_ccan_file_contents(struct ccan_file *f) @@ -54,9 +57,10 @@ const char *get_ccan_file_contents(struct ccan_file *f) char **get_ccan_file_lines(struct ccan_file *f) { if (!f->lines) - f->lines = strsplit(f, get_ccan_file_contents(f), - "\n", &f->num_lines); + f->lines = strsplit(f, get_ccan_file_contents(f), "\n"); + /* FIXME: is f->num_lines necessary? */ + f->num_lines = talloc_array_length(f->lines) - 1; return f->lines; } @@ -64,7 +68,7 @@ struct list_head *get_ccan_file_docs(struct ccan_file *f) { if (!f->doc_sections) { get_ccan_file_lines(f); - f->doc_sections = extract_doc_sections(f->lines, f->num_lines); + f->doc_sections = extract_doc_sections(f->lines); } return f->doc_sections; } @@ -72,6 +76,7 @@ struct list_head *get_ccan_file_docs(struct ccan_file *f) struct ccan_file *new_ccan_file(const void *ctx, const char *dir, char *name) { struct ccan_file *f; + unsigned int i; assert(dir[0] == '/'); @@ -79,11 +84,12 @@ struct ccan_file *new_ccan_file(const void *ctx, const char *dir, char *name) f->lines = NULL; f->line_info = NULL; f->doc_sections = NULL; - f->compiled = NULL; + for (i = 0; i < ARRAY_SIZE(f->compiled); i++) + f->compiled[i] = NULL; f->name = talloc_steal(f, name); f->fullname = talloc_asprintf(f, "%s/%s", dir, f->name); f->contents = NULL; - f->cov_compiled = NULL; + f->simplified = NULL; return f; } @@ -91,6 +97,7 @@ static void add_files(struct manifest *m, const char *dir) { DIR *d; struct dirent *ent; + char **subs = NULL; if (dir[0]) d = opendir(dir); @@ -115,8 +122,9 @@ static void add_files(struct manifest *m, const char *dir) err(1, "lstat %s", f->name); if (S_ISDIR(st.st_mode)) { - f->name = talloc_append_string(f->name, "/"); - add_files(m, f->name); + size_t len = talloc_array_length(subs); + subs = talloc_realloc(m, subs, char *, len+1); + subs[len] = talloc_append_string(f->name, "/"); continue; } if (!S_ISREG(st.st_mode)) { @@ -132,10 +140,7 @@ static void add_files(struct manifest *m, const char *dir) is_c_src = strends(f->name, ".c"); if (!is_c_src && !strends(f->name, ".h")) { dest = &m->other_files; - continue; - } - - if (!strchr(f->name, '/')) { + } else if (!strchr(f->name, '/')) { if (is_c_src) dest = &m->c_files; else @@ -160,6 +165,20 @@ static void add_files(struct manifest *m, const char *dir) list_add(dest, &f->list); } closedir(d); + + /* Before we recurse, sanity check this is a ccan module. */ + if (!dir[0]) { + size_t i; + + if (!m->info_file + && list_empty(&m->c_files) + && list_empty(&m->h_files)) + errx(1, "No _info, C or H files found here!"); + + for (i = 0; i < talloc_array_length(subs); i++) + add_files(m, subs[i]); + } + talloc_free(subs); } static int cmp_names(struct ccan_file *const *a, struct ccan_file *const *b, @@ -193,8 +212,10 @@ struct manifest *get_manifest(const void *ctx, const char *dir) unsigned int len; struct list_head *list; - if (!manifests) - manifests = htable_manifest_new(); + if (!manifests) { + manifests = talloc(NULL, struct htable_manifest); + htable_manifest_init(manifests); + } olddir = talloc_getcwd(NULL); if (!olddir) @@ -213,7 +234,7 @@ struct manifest *get_manifest(const void *ctx, const char *dir) m = talloc_linked(ctx, talloc(NULL, struct manifest)); m->info_file = NULL; - m->compiled = NULL; + m->compiled[COMPILE_NORMAL] = m->compiled[COMPILE_NOFEAT] = NULL; m->dir = talloc_steal(m, canon_dir); list_head_init(&m->c_files); list_head_init(&m->h_files); @@ -239,12 +260,17 @@ struct manifest *get_manifest(const void *ctx, const char *dir) /* We expect the ccan dir to be two levels above module dir. */ if (!ccan_dir) { - char *p; - ccan_dir = talloc_strdup(NULL, m->dir); - p = strrchr(ccan_dir, '/'); + char *p, *dir; + dir = talloc_strdup(NULL, m->dir); + p = strrchr(dir, '/'); + if (!p) + errx(1, "I expect the ccan root directory in ../.."); *p = '\0'; - p = strrchr(ccan_dir, '/'); + p = strrchr(dir, '/'); + if (!p) + errx(1, "I expect the ccan root directory in ../.."); *p = '\0'; + ccan_dir = dir; } add_files(m, ""); @@ -328,7 +354,7 @@ static char *remove_comments(const char *line, bool in_comment, static bool is_empty(const char *line) { - return strspn(line, " \t") == strlen(line); + return strspn(line, " \r\t") == strlen(line); } static bool continues(const char *line) @@ -343,7 +369,7 @@ bool get_token(const char **line, const char *token) unsigned int toklen; *line += strspn(*line, " \t"); - if (isalnum(token[0]) || token[0] == '_') + if (cisalnum(token[0]) || token[0] == '_') toklen = strspn(*line, IDENT_CHARS); else { /* FIXME: real tokenizer handles ++ and other multi-chars. */ @@ -385,6 +411,17 @@ static bool parse_hash_if(struct pp_conditions *cond, const char **line) return false; if (!defined) cond->type = PP_COND_IF; + + /* FIXME: We just chain them, ignoring operators. */ + if (get_token(line, "||") || get_token(line, "&&")) { + struct pp_conditions *sub = talloc(cond, struct pp_conditions); + + sub->parent = cond->parent; + sub->type = PP_COND_IFDEF; + if (parse_hash_if(sub, line)) + cond->parent = sub; + } + return true; } @@ -617,11 +654,35 @@ enum line_compiled get_ccan_line_pp(struct pp_conditions *cond, } void score_file_error(struct score *score, struct ccan_file *f, unsigned line, - const char *error) + const char *errorfmt, ...) { + va_list ap; + struct file_error *fe = talloc(score, struct file_error); fe->file = f; fe->line = line; - fe->error = error; list_add_tail(&score->per_file_errors, &fe->list); + + if (!score->error) + score->error = talloc_strdup(score, ""); + + if (verbose < 2 && strcount(score->error, "\n") > 5) + return; + + if (line) + score->error = talloc_asprintf_append(score->error, + "%s:%u:", + f->fullname, line); + else + score->error = talloc_asprintf_append(score->error, + "%s:", f->fullname); + + va_start(ap, errorfmt); + score->error = talloc_vasprintf_append(score->error, errorfmt, ap); + va_end(ap); + score->error = talloc_append_string(score->error, "\n"); + + if (verbose < 2 && strcount(score->error, "\n") > 5) + score->error = talloc_append_string(score->error, + "... more (use -vv to see them all)\n"); }