| /* | |
| * TADS vocabulary checker | |
| * 23-May-94 Dave Baggett <dmb@ai.mit.edu> | |
| * | |
| * This program examines TADS code vocabulary properties and gives warnings | |
| * when multiple vocabulary words are identical given six characters of | |
| * significance and case-independence. E.g., the definition | |
| * | |
| * noun = 'transmogrifier' 'Transmogrifyer' | |
| * | |
| * will trigger a warning because, ignoring case, the two words do not | |
| * differ in the first six characters as the TADS parser requires. | |
| * | |
| * Definitions like the above cause the now-infamous | |
| * | |
| * Which transmogrifier do you mean: the transmogrifier, or the transmogrifier? | |
| * | |
| * problem, where TADS assigns two different (but identical to six characters) | |
| * vocabulary items to the same object. | |
| * | |
| * ---------------------------------------------------------------------- | |
| * HOW TO USE THIS PROGRAM | |
| * | |
| * This is a Unix filter. You pipe stuff to it and it outputs warnings | |
| * if it sees things wrong. E.g., | |
| * | |
| * % vocab < cheez.t > errors.out | |
| * | |
| * or | |
| * | |
| * % cat cheez.t | something | vocab | more | |
| * | |
| * etc. | |
| * ---------------------------------------------------------------------- | |
| * HOW TO COMPILE THIS PROGRAM | |
| * | |
| * To compile this program, you need either the "lex" or "flex" lexical | |
| * anaylzer generators. Fortunately, these are standard Unix tools, so | |
| * on most machines the following should work: | |
| * | |
| * % flex vocab.l *OR* % lex vocab.l | |
| * | |
| * Then run your system's C compiler on the resulting lex.yy.c file. One | |
| * of the following commands should accomplish this: | |
| * | |
| * % cc lex.yy.c -o vocab -ll *OR* % gcc lex.yy.c -o vocab -ll | |
| * | |
| * That oughta do it! If it doesn't, ask your system administrator | |
| * for help, or send me email. | |
| * | |
| * ---------------------------------------------------------------------- | |
| * BUT I DON'T HAVE UNIX! | |
| * | |
| * Well, too bad. This would have been a pain to write in straight C, | |
| * so you get what you pay for. However, if you want to run this program | |
| * on a 386 or later PC compatible, you're in luck -- send me email for | |
| * details. Otherwise, you'll have to ask people who know how to get | |
| * flex running on your computer how to do it. | |
| * ---------------------------------------------------------------------- | |
| * TERMS | |
| * | |
| * This program is in the public domain. | |
| * | |
| */ | |
| BW [ \n] | |
| SQ ['] | |
| CO (("//".*\n)|("/*"([^*]|"\n"|("*"[^/]))*"*"+"/")) | |
| CH ([^\n\t']|(\\')) | |
| PROP ("noun"|"plural") | |
| %{ | |
| int line = 1; | |
| %} | |
| %% | |
| {PROP}{BW}+"="(({BW}|{CO})*{SQ}{CH}+{SQ})+ { | |
| check(yytext); | |
| } | |
| \n { | |
| line++; | |
| } | |
| . { | |
| } | |
| %% | |
| #define MAX_WORDS 256 /* max # vocabulary words for single property */ | |
| #define MAX_LENGTH 128 /* max vocab word length */ | |
| #define quote(c) ((c) == '\"' ? '\"' : ((c) == '\'' ? '\'' : (c) - 'a')) | |
| check(s) | |
| char *s; | |
| { | |
| static char word[MAX_WORDS][7]; | |
| static char orig[MAX_WORDS][MAX_LENGTH]; | |
| char *sbase = s; | |
| int i, j, w = 0; | |
| int lineadd = 0; | |
| /* | |
| * Count newlines in this string | |
| */ | |
| for (; *s; s++) | |
| if (*s == '\n') | |
| lineadd++; | |
| /* | |
| * Erase comments | |
| */ | |
| for (s = sbase; *s;) { | |
| /* | |
| * Find next / | |
| */ | |
| for (; *s && *s != '/'; s++) | |
| ; | |
| if (!*s) | |
| break; | |
| /* | |
| * If followed by /, skip to newline. | |
| * If followed by *, skip to end-comment (star-slash). | |
| */ | |
| if (s[1] == '/') { | |
| for (; *s && *s != '\n'; s++) | |
| *s = ' '; | |
| if (*s) | |
| *s = ' '; | |
| } | |
| else if (s[1] == '*') { | |
| for (; *s && s[1] && !(*s == '*' && s[1] == '/'); s++) | |
| *s = ' '; | |
| *s = ' '; | |
| if (s[1]) | |
| s[1] = ' '; | |
| } | |
| else | |
| s++; | |
| } | |
| /* | |
| * Build word list, significant to six characters. | |
| */ | |
| for (s = sbase; *s; ) { | |
| /* | |
| * Find start of next word (= single quoted string). | |
| */ | |
| for (; *s && *s != '\''; s++) | |
| ; | |
| if (!*s) | |
| break; | |
| /* | |
| * Copy characters from string to current word list entry. | |
| */ | |
| s++; | |
| for (i = 0; *s; i++, s++) { | |
| char c; | |
| if (*s == '\'') { | |
| s++; | |
| break; | |
| } | |
| else if (*s == '\\') { | |
| c = quote(s[1]); | |
| s++; | |
| } | |
| else | |
| c = *s; | |
| orig[w][i] = c; | |
| if (i < 6) { | |
| if (isupper(c)) | |
| word[w][i] = tolower(c); | |
| else | |
| word[w][i] = c; | |
| } | |
| } | |
| orig[w][i] = 0; | |
| word[w][i <= 6 ? i : 6] = 0; | |
| w++; | |
| } | |
| /* | |
| * Compare each word to every other word. O(n^2) | |
| * | |
| * You could do this faster [O(n lg n)] by first sorting and | |
| * then checking only adjacent words for similarity. I | |
| * didn't feel like bothering with it. | |
| */ | |
| for (i = 0; i < w - 1; i++) { | |
| for (j = i + 1; j < w; j++) { | |
| if (!strcmp(word[i], word[j])) { | |
| printf("line %d: duplicate vocabulary:", line); | |
| printf(" [%s], [%s] -> [%s]\n", orig[i], orig[j], word[i]); | |
| break; | |
| } | |
| } | |
| } | |
| line += lineadd; | |
| } | |
| main() | |
| { | |
| yylex(); | |
| } | |
Xet Storage Details
- Size:
- 4.61 kB
- Xet hash:
- 3da2b0dd3428394101947538035966b5800dd58d3753a51f6e48966f8b28a179
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.