/* * Scan a gmake/gcc compile log, counting the number of warnings from each * file. */ #include #include #include #include #include #include #include typedef struct _list { struct _list *link; int count; char *path; } LIST; static unsigned num_files; static LIST *all_files; static void failed(char *msg) { perror(msg); exit(1); } static void count_file(char *dir, char *file) { char path[PATH_MAX]; char resolved[PATH_MAX]; LIST *p; if (!strcmp(file, "bison.simple")) { strcpy(resolved, file); } else { if (*file == '/') strcpy(path, file); else sprintf(path, "%s/%s", dir, file); if (realpath(path, resolved)) { ; } else { fprintf(stderr, "in\n\t%s\ncannot find\n\t%s\n", dir, file); } } for (p = all_files; p != 0; p = p->link) { if (!strcmp(p->path, resolved)) { p->count += 1; return; } } p = calloc(sizeof(LIST), 1); p->path = strdup(resolved); p->link = all_files; p->count = 1; all_files = p; num_files++; } static int compare(const void *a, const void *b) { const LIST **p = (const LIST **)a; const LIST **q = (const LIST **)b; return ((*q)->count - (*p)->count); } static void show_files(void) { LIST **p = calloc(sizeof(LIST *), num_files); LIST *q; unsigned n = 0; for (q = all_files; q != 0; q = q->link) p[n++] = q; qsort(p, num_files, sizeof(LIST *), compare); for (n = 0; n < num_files; n++) { printf("%d %s\n", p[n]->count, p[n]->path); } } #define BIGBUF (BUFSIZ*10)+PATH_MAX static void c_warnings(FILE *fp) { char buf[BIGBUF]; char buf2[BIGBUF]; char buf3[BIGBUF]; unsigned line = 0; unsigned wide = 0; int level; char directory[PATH_MAX]; int warnings = 0; int colons = 0; int c_dirs = 0; printf("Scanning...\n"); fflush(stdout); strcpy(directory, "."); while (fgets(buf, sizeof(buf), fp)) { size_t len = strlen(buf); line++; if (len >= sizeof(buf)-1) { fprintf(stderr, "Line %d is too long\n", line); exit(1); } if (len > wide) wide = len; if (sscanf(buf, "make[%d]: Entering directory `%[^']'", &level, buf2) == 2) { strcpy(directory, buf2); c_dirs++; } else if (sscanf(buf, "make[%d]: %s", &level, buf2)) { ; } else if (strstr(buf, "warning:")) { warnings++; if (sscanf(buf, "%[^:]:%d: warning: %s", buf2, &level, buf3) == 3) { count_file(directory, buf2); } else if (sscanf(buf, "%[^:]: warning: %s", buf2, buf3) == 2) { count_file(directory, buf2); } else { printf(">%s", buf); } } else if (strchr(buf, ':')) { colons++; //printf(">%s", buf); } } printf("%d lines processed, widest = %d\n", line, wide); printf("%d directories\n", c_dirs); printf("%d warnings\n", warnings); printf("%d other :-lines\n", colons); printf("%d files with warnings\n", num_files); if (num_files) show_files(); } int main(int argc, char *argv[]) { int n; int found = 0; FILE *fp; for (n = 1; n < argc; n++) { char *name = argv[n]; if (!strcmp(name, "-")) { c_warnings(stdin); found = 1; } else if ((fp = fopen(name, "r")) != 0) { c_warnings(fp); fclose(fp); found = 1; } else failed(name); } if (!found) c_warnings(stdin); return 0; }