From: Eric S. Raymond Date: Wed, 17 Sep 2003 18:55:35 +0000 (+0000) Subject: Initial revision X-Git-Tag: 2.0~23 X-Git-Url: http://thyrsus.com/gitweb/?a=commitdiff_plain;h=a1004190d6efaa50a5d81d609199835e24df6c1c;p=comparator.git Initial revision --- diff --git a/linebyline.c b/linebyline.c new file mode 100644 index 0000000..3e871ff --- /dev/null +++ b/linebyline.c @@ -0,0 +1,156 @@ +/* filter.c -- filter lines for significance */ +#include +#include +#include +#include "shred.h" + +static char *c_patterns[] = { + /* Idioms that don't convey any meaning in isolation */ + "return *\\(?[a-z]+\\)? *;", "return *\\(?-?[01]+\\)? *;", + "goto +[a-z]+;", "exit *\\([01]\\);", + /* Pragmas */ + "/\\* *ARGSUSED *\\*/", + "/\\* *NOTREACHED *\\*/", + "/\\* *FALL *THRO?UG?H? *\\*/", + /* Bare C keywords */ + + "[[:<:]]break[[:>:]]", "[[:<:]]case[[:>:]]","[[:<:]]continue[[:>:]]", + "[[:<:]]default[[:>:]]", "[[:<:]]do[[:>:]]", "[[:<:]]else[[:>:]]", + "[[:<:]]enum[[:>:]]", "[[:<:]]if[[:>:]]", "[[:<:]]goto[[:>:]]", + "[[:<:]]return[[:>:]]", "[[:<:]]switch[[:>:]]", "[[:<:]]while[[:>:]]", + "[[:<:]]enum[[:>:]]", "[[:<:]]int[[:>:]]", "[[:<:]]long[[:>:]]", + "[[:<:]]short[[:>:]]", "[[:<:]]static[[:>:]]", "[[:<:]]struct[[:>:]]", + "[[:<:]]typedef[[:>:]]", "[[:<:]]union[[:>:]]", "[[:<:]]void[[:>:]]", + /* Preprocessor constructs */ + "/* *define","# *endif","# *else","# *if[[:>:]]", + "# *ifdef[[:>:]]","# *ifndef[[:>:]]", + /* Comment delimiters with no content, and line continuation */ + "/\\*+", "\\*+/", "\\*+", "^ *\\s*\\n", "\\\n", + /* Common preprocessor macros, not significant by themselves. */ + "[[:<:]]ASSERT[[:>:]]", + "[[:<:]]FALSE[[:>:]]", + "[[:<:]]NULL[[:>:]]", + "[[:<:]]STATIC[[:>:]]", + "[[:<:]]TRUE[[:>:]]", + /* Macro include lines are noise, too. */ + "\\s*#include.*","#\\s*line.*", + /* Common error macros. */ + "[[:<:]]EFAULT[[:>:]]", + "[[:<:]]EINVAL[[:>:]]", + "[[:<:]]ENOSYS[[:>:]]", +}; +static regex_t c_regexps[sizeof(c_patterns)/sizeof(*c_patterns)]; + +static char c_punct[] = { + /* Punctuation and whitespace */ + '{', '}', '(', ')', '<', '>', '[', ']', + '^', '&', '|', '*', '?', '.', '+', + ';', ':', '%', ',', '-', '/', '=', '!', + '\n', '\t', '\v', +}; + +static char *shell_patterns[] = { + /* Idioms that don't convey any meaning in isolation */ + "exit *[01];?", + /* Bare shell keywords */ + "[[:<:]]break[[:>:]]", "[[:<:]]case[[:>:]]", "[[:<:]]done[[:>:]]", + "[[:<:]]do[[:>:]]", "[[:<:]]else[[:>:]]", "[[:<:]]esac[[:>:]]", + "[[:<:]]fi[[:>:]]", "[[:<:]]if[[:>:]]", "[[:<:]]return[[:>:]]", + "[[:<:]]shift[[:>:]]", "[[:<:]]true[[:>:]]", "[[:<:]]while[[:>:]]", + /* Blank comment */ + "^#\n", +}; +static regex_t shell_regexps[sizeof(shell_patterns)/sizeof(*shell_patterns)]; + +static char shell_punct[] = { + /* Punctuation and whitespace */ + ':', ';', '\n','\t', '\v', +}; + +void filter_init(void) +/* initialize line filtering */ +{ + int i; + + for (i = 0; i < sizeof(c_patterns)/sizeof(*c_patterns); i++) + if (regcomp(c_regexps+i, c_patterns[i], REG_EXTENDED)) + { + fprintf(stderr, "comparator: error while compiling %s\n", + c_patterns[i]); + exit(1); + } + for (i = 0; i < sizeof(shell_patterns)/sizeof(*shell_patterns); i++) + if (regcomp(shell_regexps+i, shell_patterns[i], REG_EXTENDED)) + { + fprintf(stderr, "comparator: error while compiling %s\n", + shell_patterns[i]); + exit(1); + } +} + +static filtertype active = none; +static char *punct, **patterns; + +void filter_set(filtertype newfilter) +{ + active = newfilter; + + if (newfilter == c) + { + patterns = c_patterns; + punct = c_punct; + } + else + { + patterns = shell_patterns; + punct = shell_punct; + } +} + +int filter_pass(const char *line) +{ + if (active == none) + return(1); + else + { + char buf[BUFSIZ][2]; + int changed, i = 0; + + buf[0][0] = ' '; + strncpy(buf[0]+1, line, BUFSIZ-2); + + while (changed) + { + char *s, *t, *sp, *tp; + + s = buf[i]; t = buf[!i]; i ^= 1; changed = 0; + + /* remove all punctuation */ + for (sp = s, tp = t; *sp; sp++) + if (strchr(punct, *sp)) + changed++; + else + *tp++ = *sp; + if (changed) + continue; + + /* replace all regexps with the empty string */ + } + } +} + +int main(int argc, char *argv[]) +{ + char buf[BUFSIZ]; + + filter_init(); + filter_set(c); + while(fgets(buf, BUFSIZ, stdin)) + { + if (filter_pass(buf)) + fputs("!! ", stdout); + fputs(buf, stdout); + } +} + +/* filter.c ends here */