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