1: #ifndef lint 2: static char *sccsid = "@(#)mkstr.c 4.1 (Berkeley) 10/1/80"; 3: #endif 4: #include <sys/types.h> 5: #include <stdio.h> 6: #include <sys/stat.h> 7: 8: #define ungetchar(c) ungetc(c, stdin) 9: 10: long ftell(); 11: char *calloc(); 12: /* 13: * mkstr - create a string error message file by massaging C source 14: * 15: * Bill Joy UCB August 1977 16: * 17: * Modified March 1978 to hash old messages to be able to recompile 18: * without addding messages to the message file (usually) 19: * 20: * Based on an earlier program conceived by Bill Joy and Chuck Haley 21: * 22: * Program to create a string error message file 23: * from a group of C programs. Arguments are the name 24: * of the file where the strings are to be placed, the 25: * prefix of the new files where the processed source text 26: * is to be placed, and the files to be processed. 27: * 28: * The program looks for 'error("' in the source stream. 29: * Whenever it finds this, the following characters from the '"' 30: * to a '"' are replaced by 'seekpt' where seekpt is a 31: * pointer into the error message file. 32: * If the '(' is not immediately followed by a '"' no change occurs. 33: * 34: * The optional '-' causes strings to be added at the end of the 35: * existing error message file for recompilation of single routines. 36: */ 37: 38: 39: FILE *mesgread, *mesgwrite; 40: char *progname; 41: char usagestr[] = "usage: %s [ - ] mesgfile prefix file ...\n"; 42: char name[100], *np; 43: 44: main(argc, argv) 45: int argc; 46: char *argv[]; 47: { 48: char addon = 0; 49: 50: argc--, progname = *argv++; 51: if (argc > 1 && argv[0][0] == '-') 52: addon++, argc--, argv++; 53: if (argc < 3) 54: fprintf(stderr, usagestr, progname), exit(1); 55: mesgwrite = fopen(argv[0], addon ? "a" : "w"); 56: if (mesgwrite == NULL) 57: perror(argv[0]), exit(1); 58: mesgread = fopen(argv[0], "r"); 59: if (mesgread == NULL) 60: perror(argv[0]), exit(1); 61: inithash(); 62: argc--, argv++; 63: strcpy(name, argv[0]); 64: np = name + strlen(name); 65: argc--, argv++; 66: do { 67: strcpy(np, argv[0]); 68: if (freopen(name, "w", stdout) == NULL) 69: perror(name), exit(1); 70: if (freopen(argv[0], "r", stdin) == NULL) 71: perror(argv[0]), exit(1); 72: process(); 73: argc--, argv++; 74: } while (argc > 0); 75: exit(0); 76: } 77: 78: process() 79: { 80: register c; 81: 82: for (;;) { 83: c = getchar(); 84: if (c == EOF) 85: return; 86: if (c != 'e') { 87: putchar(c); 88: continue; 89: } 90: if (match("error(")) { 91: printf("error("); 92: c = getchar(); 93: if (c != '"') 94: putchar(c); 95: else 96: copystr(); 97: } 98: } 99: } 100: 101: match(ocp) 102: char *ocp; 103: { 104: register char *cp; 105: register c; 106: 107: for (cp = ocp + 1; *cp; cp++) { 108: c = getchar(); 109: if (c != *cp) { 110: while (ocp < cp) 111: putchar(*ocp++); 112: ungetchar(c); 113: return (0); 114: } 115: } 116: return (1); 117: } 118: 119: copystr() 120: { 121: register c, ch; 122: char buf[512]; 123: register char *cp = buf; 124: 125: for (;;) { 126: c = getchar(); 127: if (c == EOF) 128: break; 129: switch (c) { 130: 131: case '"': 132: *cp++ = 0; 133: goto out; 134: case '\\': 135: c = getchar(); 136: switch (c) { 137: 138: case 'b': 139: c = '\b'; 140: break; 141: case 't': 142: c = '\t'; 143: break; 144: case 'r': 145: c = '\r'; 146: break; 147: case 'n': 148: c = '\n'; 149: break; 150: case '\n': 151: continue; 152: case 'f': 153: c = '\f'; 154: break; 155: case '0': 156: c = 0; 157: break; 158: case '\\': 159: break; 160: default: 161: if (!octdigit(c)) 162: break; 163: c -= '0'; 164: ch = getchar(); 165: if (!octdigit(ch)) 166: break; 167: c <<= 7, c += ch - '0'; 168: ch = getchar(); 169: if (!octdigit(ch)) 170: break; 171: c <<= 3, c+= ch - '0', ch = -1; 172: break; 173: } 174: } 175: *cp++ = c; 176: } 177: out: 178: *cp = 0; 179: printf("%d", hashit(buf, 1, NULL)); 180: } 181: 182: octdigit(c) 183: char c; 184: { 185: 186: return (c >= '0' && c <= '7'); 187: } 188: 189: inithash() 190: { 191: char buf[512]; 192: int mesgpt = 0; 193: 194: rewind(mesgread); 195: while (fgetNUL(buf, sizeof buf, mesgread) != NULL) { 196: (void) hashit(buf, 0, (unsigned) mesgpt); 197: mesgpt += strlen(buf) + 2; 198: } 199: } 200: 201: #define NBUCKETS 511 202: 203: struct hash { 204: long hval; 205: unsigned hpt; 206: struct hash *hnext; 207: } *bucket[NBUCKETS]; 208: 209: hashit(str, really, fakept) 210: char *str; 211: char really; 212: unsigned fakept; 213: { 214: int i; 215: register struct hash *hp; 216: char buf[512]; 217: long hashval = 0; 218: register char *cp; 219: 220: if (really) 221: fflush(mesgwrite); 222: for (cp = str; *cp;) 223: hashval = (hashval << 1) + *cp++; 224: i = /*NOSTRICT*/ hashval % NBUCKETS; 225: if (i < 0) 226: i += NBUCKETS; 227: if (really != 0) 228: for (hp = bucket[i]; hp != 0; hp = hp->hnext) 229: if (hp->hval == hashval) { 230: fseek(mesgread, (long) hp->hpt, 0); 231: (void) fgetNUL(buf, sizeof buf, mesgread); 232: /* 233: fprintf(stderr, "Got (from %d) %s\n", hp->hpt, buf); 234: */ 235: if (strcmp(buf, str) == 0) 236: break; 237: } 238: if (!really || hp == 0) { 239: hp = (struct hash *) calloc(1, sizeof *hp); 240: hp->hnext = bucket[i]; 241: hp->hval = hashval; 242: hp->hpt = (unsigned) (really ? ftell(mesgwrite) : fakept); 243: if (really) { 244: fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite); 245: fwrite("\n", sizeof (char), 1, mesgwrite); 246: } 247: bucket[i] = hp; 248: } 249: /* 250: fprintf(stderr, "%s hashed to %ld at %d\n", str, hp->hval, hp->hpt); 251: */ 252: return (hp->hpt); 253: } 254: 255: fgetNUL(obuf, rmdr, file) 256: char *obuf; 257: register int rmdr; 258: FILE *file; 259: { 260: register c; 261: register char *buf = obuf; 262: 263: while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF) 264: *buf++ = c; 265: *buf++ = 0; 266: getc(file); 267: return ((feof(file) || ferror(file)) ? NULL : 1); 268: }