Определение числа строк кода и комментариев
Материал из BSDHome
Имеется дерево исходных кодов на нескольких ЯП, определить число строк кода и комментариев. Для этих целей была написана программа на Си.
/* The program makes statistics * of using various programming * language constructs in source * file(s) of any type on given * location(s). * ------------------------------- * Author: MATAH * Date: Mon, 29 Mar 2006 10:34:48 * License: GNU GPL v3 * Vein: idleness => */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <unistd.h> #include <errno.h> #include <string.h> #define _GNU_SOURCE #include <string.h> #include <getopt.h> void dirtraverse (const char *); void collect (const char *); void parse (const char *, int); void parse_init (void); struct entry { char *type; char *mask; long count; long linec; char *comments_delimiters; long commc; } ents[] = { { "C++ files in the path", ".cpp", 0, 0, "/*...*/ //", 0}, { "C++ files in the path", ".cc", 0, 0, "/*...*/ //", 0}, { "C files in the path", ".c", 0, 0, "/*...*/ //", 0}, { "assembler files in the path", ".S", 0, 0, "/*...*/ // ;", 0}, { "header files in the path", ".h", 0, 0, "/*...*/ //", 0}, { "header files in the path", ".hh", 0, 0, "/*...*/ //", 0}, { "incidental files in the path", "", 0, 0, NULL, 0}, { NULL, NULL, 0, 0, NULL, 0} }; static char comdels[sizeof (ents) / sizeof (struct entry)][5][2][7]; int main (int ac, char **av) { struct { unsigned int print_comments:1; unsigned int print_code:1; unsigned int print_all:1; } opts; short i, j; short pathindex[32]; for (i = 1, j = 0; i < ac; i++) if (*av[i] != '-') pathindex[j++] = i; if (!*pathindex) { printf ("Error: Missing path string\n"); exit (1); } static const char *const shortopts = "mac"; static const struct option longopts[] = { {"code", 0, NULL, 'c'}, {"comment", 0, NULL, 'm'}, {"all", 0, NULL, 'a'}, {NULL, 0, NULL, 0} }; extern int optind; register int len; register char opt; while ((opt = getopt_long (ac, av, shortopts, longopts, NULL)) != EOF) { switch (opt) { case 'a': opts.print_all = 1; break; case 'm': opts.print_comments = 1; break; case 'c': opts.print_code = 1; break; } } parse_init (); for (; j-- > 0;) collect (av[pathindex[j]]); int longest; for (j = 0, longest = len = 0; ents[j].type != NULL; j++) if ((len = strlen (ents[j].type)) > longest) longest = len; char *banner = (char *) malloc ((longest + 27) * 3 + 1); int pos = 0; char *bantext = "Statistics:"; banner[pos] = 0x0; strncat (banner, "+", 1); pos++; for (j = 0; j < longest + 27; j++, pos++) strncat (banner, "-", 1); strncat (banner, "+\n", 2); short even = (longest % 2) ? 0 : 1; strncat (banner, "|", 1); for (j = 0; j < ((even) ? ((longest + 27) - strlen (bantext)) / 2 : ((longest + 27) - strlen (bantext) - 1) / 2); j++) strncat (banner, " ", 1); strcat (banner, bantext); for (j = 0; j < ((even) ? ((longest + 27) - strlen (bantext)) / 2 : ((longest + 27) - strlen (bantext) + 1) / 2); j++) strncat (banner, " ", 1); strncat (banner, "|\n+", 3); for (j = 0; j < longest + 14; j++) strncat (banner, "-", 1); strncat (banner, "+", 1); for (j = 0; j < 10 + 2; j++) strncat (banner, "-", 1); strncat (banner, "+\n", 1); printf ("%s\n", banner); j = 0; short entnum = 0, k; while (ents[j].type) { if (!ents[j].count) { j++; continue; } else { entnum++; printf ("| %d)For %s:", entnum, ents[j].type); for (k = 0; k < longest - strlen (ents[j].type) + 6; k++) putchar (' '); putchar ('|'); for (k = 0; k++ < 12;) putchar (' '); printf ("|\n"); printf ("| Quantity"); for (k = 0; k < longest + 5 + 6 - 10; k++) putchar ('.'); printf (" | "); printf ("%10ld", ents[j].count); printf (" |\n"); if (ents[j].linec) { printf ("| Codelines"); for (k = 0; k < longest + 5 + 6 - 11; k++) putchar ('.'); printf (" | "); printf ("%10ld", ents[j].linec); printf (" |\n"); } if (ents[j].commc) { printf ("| Commentlines"); for (k = 0; k < longest + 5 + 6 - 14; k++) putchar ('.'); printf (" | "); printf ("%10ld", ents[j].commc); printf (" |\n"); } j++; } } putchar ('+'); for (k = 0; k < longest + 14; k++) putchar ('-'); putchar ('+'); for (k = 0; k < 10 + 2; k++) putchar ('-'); printf ("+\n"); return EXIT_SUCCESS; } void collect (const char *path) { int i; struct stat *stbuf = (void *) malloc (sizeof (struct stat)); if (stat (path, stbuf) == EOF) { perror (path); return; } if (stbuf->st_mode & S_IFDIR) dirtraverse (path); else { for (i = 0; ents[i].type != NULL; ++i) { if ((unsigned) strcasestr (path, ents[i].mask) == (unsigned) path + strlen (path) - strlen (ents[i].mask)) { parse (path, i); break; } else if ((unsigned) strcasestr (path, ents[i].mask) == (unsigned) path) ++(ents[i].count); } } free (stbuf); } void dirtraverse (const char *path) { DIR *dirpnt; if (!(dirpnt = opendir (path))) perror ("Oops"); char fullpath[1024]; struct dirent *de; while ((de = readdir (dirpnt))) { if (strcmp (de->d_name, ".") == 0 || strcmp (de->d_name, "..") == 0) continue; else { sprintf (fullpath, "%s/%s", path, de->d_name); collect (fullpath); } } closedir (dirpnt); } void parse (const char *path, int pos) { (ents[pos].count)++; FILE *fptr = fopen (path, "r"); char *str = (char *) malloc (4096); int si = 0, ai; char *strpos = str, *t = NULL; long prev; short incom = 0; while (fgets (str, 4096, fptr) != NULL) { prev = ents[pos].commc; si = 0; while (str[si++] == ' ' || str[si - 1] == '\t') ; if (!incom) ai = 0; for (strpos = (str + si - 1); **comdels[pos][ai]; ai++) { if ((t = strstr (strpos, comdels[pos][ai][incom]))) { strpos = t; if (incom) { incom = 0; ai--; continue; } if (*comdels[pos][ai][1]) { if (strpos == str + si - 1) ents[pos].commc++; ai--; incom = 1; } else if (t == (str + si - 1)) { ents[pos].commc++; break; } } else if (incom) { ents[pos].commc++; break; } } if (prev == ents[pos].commc) ents[pos].linec++; } fclose (fptr); } void parse_init (void) { memset (comdels, 0, sizeof (comdels)); int pos; for (pos = 0; ents[pos].comments_delimiters; pos++) { char *p = ents[pos].comments_delimiters; int ta = 0, tb = 0, tc = 0; while (*p) { if (*p == '.') { comdels[pos][ta][tb++][tc] = '\0'; tc = 0; while (*(++p) == '.') ; } if (*p == ' ') { comdels[pos][ta++][tb][tc] = '\0'; p++; tb = tc = 0; continue; } comdels[pos][ta][tb][tc++] = *(p++); } } }
Скопировать исходник в файл locc.c Компилировать командой:
$ gcc locc.c -o locc
Запускать командой:
$ ./locc адрес дерева исходных кодов
