Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!sparky!kent From: kent@sparky.IMD.Sterling.COM (Kent Landfield) Newsgroups: comp.sources.wanted Subject: Re: Need Non-commentary Sources Line Counter Message-ID: <1990Nov25.223059.3933@sparky.IMD.Sterling.COM> Date: 25 Nov 90 22:30:59 GMT References: <4603@tellab5.tellabs.com> Organization: Sterling Software, Bellevue, NE. Lines: 433 In article <4603@tellab5.tellabs.com> Darryl writes: > > I need a program, shell script, awk program, etc... that > will count lines of C source code that are not exclusively > comments. I thought I saw a couple of these go by but I looked > at the indexes for comp.sources.misc and comp.sources.unix and > couldn't find one in there. Does anyone have one? Can you point > one out in one of the archived groups? Thanks. >-- > __ _ __ > / ) // / ) / > / / __. __ __ __ , // /--< __. /_ _ __ Darryl Baker >/__/_(_/|_/ (_/ (_/ (_/_ #include #define EMBED_ERROR(a) (void) printf("Embeded comment,line %ld\n",a); #define DELIM_ERROR(a) (void) printf("Delimiter mismatch, line %ld\n",a); char *progname; /* executable name */ char *flname; /* input file name */ int strip = 0; /* strip comments flag */ int remove_multiple = 0; /* strip and remove multiple blank lines */ int remove_all = 0; /* strip and remove all blank lines */ int countit = 0; /* count code/comment/total flag */ int verbose = 0; /* verbose output flag for header lines */ int justify = 0; /* left justify comments flag */ main(argc, argv) int argc; char **argv; { register int i; FILE *fp; flname = "STDIN"; /* assume input as standard input */ progname = argv[0]; /* save the program executable name */ while (argc > 1 && argv[1][0] == '-') { switch (argv[1][1]) { case 'R': /* strip comments removing all blank lines */ remove_all = 1; strip = 1; countit = 0; break; case 'r': /* strip comments removing multiple blank lines */ remove_multiple = 1; case 's': /* strip comments leaving all blank lines */ strip = 1; countit = 0; break; case 'c': /* produce code/comment/total statistics */ strip = 0; countit = 1; break; case 'v': /* print out the header for count function */ verbose = 1; break; case 'j': /* left justify the comments printed */ justify = 1; break; case 't': /* the filename if taken from standard input */ flname = argv[2]; argc--, argv++; break; default: (void) fprintf(stderr,"%s: unknown arg %s\n",progname,argv[1]); return(1); } argc--, argv++; } if (argc == 1) /* input coming from standard input */ comments(stdin); else { for (i = 1; i < argc; i++) { flname = argv[i]; if ((fp = fopen(flname, "r")) == NULL) { (void) fprintf(stderr, "%s: can't open %s\n", argv[0], flname); return(1); } else { comments(fp); (void) fclose(fp); } } } return(0); } comments(stream) FILE *stream; { register char *bp; /* current character pointer */ register long lineno = 0L; /* current line counter */ char buf[BUFSIZ]; /* input buffer, contains record read */ int end_comment = 0; /* boolean indicating comment just ended */ int print_line = 0; /* boolean indicating line is to print */ int incomment = 0; /* boolean indicating if in a comment */ int inliteral = 0; /* boolean indicating if in a literal */ int last_char = ' '; /* holds the last item bp pointed at */ /* ** Determine if the strip or count function is requested to be ** applied to the stream. If so, call the appropriate function ** and return to main. */ if (strip) { strip_comments(stream); return; } else if (countit) { count(stream); return; } /* ** Comments only will be printed. */ while (fgets(buf, sizeof(buf), stream) != NULL) { bp = buf; lineno++; for (; *bp != '\n'; bp++) { if (*bp == '/' && !inliteral) { if (*(bp+1) == '*') { /* begin comment */ if (!incomment) /* am I already in one */ incomment = 1; /* no - indicate i am now */ else /* yes - print an error */ EMBED_ERROR(lineno); } else if (last_char == '*') { /* end comment */ if (incomment) { /* I should be in a comment */ incomment = 0; /* turn off comment flag */ end_comment = 1; /* indicate turnoff */ print_line = 1; /* indicate print needed. */ } else /* not in a comment - error */ DELIM_ERROR(lineno); } } else if (*bp == '"' && !incomment && /* turn on and */ (last_char != '\'' && *(bp+1) != '\'')) /* off the */ inliteral = !inliteral; /* literal flag */ if (!incomment && !end_comment) *bp = ' '; /* blank out non-comments */ last_char = *bp; /* store the last char value */ end_comment = 0; } /* newline found, loop terminated */ if (incomment || print_line) { /* printable comment line */ bp = buf; /* point at start of record */ if (justify) { /* if justify, strip leading */ while(*bp == ' ' || *bp == '\t') /* tabs and spaces */ bp++; } (void) fputs(bp, stdout); /* print the comment line */ print_line = 0; /* turn off the print flag */ } } return; } strip_comments(stream) FILE *stream; { register char *bp; /* current character pointer */ register long lineno = 0L; /* current line counter */ char buf[BUFSIZ]; /* input buffer, contains record read */ int incomment = 0; /* boolean indicating if in a comment */ int inliteral = 0; /* boolean indicating if in a literal */ int data_inline = 0; /* boolean indicating if data in line */ int last_line_blank = 0; /* boolean indicating if last line blank */ int last_char = ' '; /* holds the last item bp pointed at */ /* ** Strip comments from the stream and print according the ** the options set by the user. */ while (fgets(buf, sizeof(buf), stream) != NULL) { bp = buf; lineno++; for (; *bp != '\n'; bp++) { if (*bp == '/' && !inliteral) { if (*(bp+1) == '*') { /* begin comment */ if (!incomment) /* am I already in one */ incomment = 1; /* no - indicate i am now */ else /* yes - print an error */ EMBED_ERROR(lineno); } else if (last_char == '*') { /* end comment */ if (incomment) { /* I should be in a comment */ incomment = 0; /* turn off comment flag */ *bp = ' '; /* blank out the comment */ } else /* not in a comment - error */ DELIM_ERROR(lineno); } } else if (*bp == '"' && !incomment && /* turn on and */ (last_char != '\'' && *(bp+1) != '\'')) /* off the */ inliteral = !inliteral; /* literal flag */ last_char = *bp; /* store last char value */ if (incomment) *bp = ' '; /* blank out the comment */ } /* newline found, loop terminated */ if (!incomment) { /* time to check for data */ bp = buf; data_inline = 0; while (*bp && !data_inline) { /* determine if a blank line */ if (*bp != '\t' && *bp != ' ' && *bp != '\n' && *bp != '\f') data_inline = 1; bp++; } if (data_inline) { /* was real data found ? */ (void) fputs(buf, stdout); /* print out the line */ last_line_blank = 0; /* indicate last line not blank */ } else if (!remove_all) { /* did user want blank lines ? */ if (!remove_multiple) /* squash multiple blank lines? */ (void) fputs(buf, stdout); /* no print the line */ else if (!last_line_blank) { /* yes - was last blank ? */ (void) fputs(buf, stdout); /* print the line */ last_line_blank = 1; /* indicate last line blank */ } } } } } count(stream) FILE *stream; { register char *bp; /* current character pointer */ register long code_chars = 0L; /* number of characters of code */ register long code_lines = 0L; /* number of lines of code */ register long comment_chars = 0L; /* number of characters of comments */ register long comment_lines = 0L; /* # of lines containing comments */ register long chars = 0L; /* total number of characters */ register long lineno = 0L; /* total number of lines */ char buf[BUFSIZ]; /* input buffer, contains record read */ int end_comment = 0; /* boolean indicating comment just ended */ int incomment = 0; /* boolean indicating if in a comment */ int inliteral = 0; /* boolean indicating if in a literal */ int had_comment = 0; /* boolean indicating line had a comment */ int had_data = 0; /* boolean indicating line had data on it*/ int last_char = ' '; /* holds the last item bp pointed at */ while (fgets(buf, sizeof(buf), stream) != NULL) { lineno++; for (bp = buf; *bp != '\n'; bp++) { chars++; /* check for valid data on line */ if (*bp != '/' && *bp != '*' && !incomment && *bp != '\t' && *bp != ' ' && *bp != '\f') had_data = 1; /* set data on line flag */ /* encountered a possible comment delimiter */ if (*bp == '/' && !inliteral && (*(bp+1) == '*' || last_char == '*')) { incomment = !incomment; if (!incomment) { had_comment = 1; /* indicate comment on line */ end_comment = 1; /* indicate comment stopped */ comment_chars++; /* count last '/' */ } } /* encountered a possible literal delimiter */ else if (*bp == '"' && !incomment && (last_char != '\'' && *(bp+1) != '\'')) inliteral = !inliteral; last_char = *bp; if (incomment) comment_chars++; else if (!end_comment) code_chars++; end_comment = 0; } /* newline found - loop terminated */ chars++; /* add the newline character to the total */ #ifdef COUNT_NEWLINES if (incomment) comment_chars++; else code_chars++; #endif if (incomment || had_comment) comment_lines++; if (had_data) code_lines++; had_comment = 0; had_data = 0; } if (verbose) (void) printf(" Code Comment Total\n"); (void) printf("%5ld%10ld%10ld\n%5ld%10ld%10ld %s\n", code_chars, comment_chars, chars, code_lines, comment_lines, lineno, flname); } /* this is the last line of the file */