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 '0': 168: c = 0; 169: break; 170: case '\\': 171: break; 172: default: 173: if (!octdigit(c)) 174: break; 175: c -= '0'; 176: ch = getchar(); 177: if (!octdigit(ch)) 178: break; 179: c <<= 7, c += ch - '0'; 180: ch = getchar(); 181: if (!octdigit(ch)) 182: break; 183: c <<= 3, c+= ch - '0', ch = -1; 184: break; 185: } 186: } 187: *cp++ = c; 188: } 189: out: 190: *cp = 0; 191: printf("%d", hashit(buf, 1, NULL)); 192: } 193: 194: octdigit(c) 195: char c; 196: { 197: 198: return (c >= '0' && c <= '7'); 199: } 200: 201: inithash() 202: { 203: char buf[512]; 204: int mesgpt = 0; 205: 206: rewind(mesgread); 207: while (fgetNUL(buf, sizeof buf, mesgread) != NULL) { 208: hashit(buf, 0, mesgpt); 209: mesgpt += strlen(buf) + 2; 210: } 211: } 212: 213: #define NBUCKETS 511 214: 215: struct hash { 216: long hval; 217: unsigned hpt; 218: struct hash *hnext; 219: } *bucket[NBUCKETS]; 220: 221: hashit(str, really, fakept) 222: char *str; 223: char really; 224: unsigned fakept; 225: { 226: int i; 227: register struct hash *hp; 228: char buf[512]; 229: long hashval = 0; 230: register char *cp; 231: 232: if (really) 233: fflush(mesgwrite); 234: for (cp = str; *cp;) 235: hashval = (hashval << 1) + *cp++; 236: i = hashval % NBUCKETS; 237: if (i < 0) 238: i += NBUCKETS; 239: if (really != 0) 240: for (hp = bucket[i]; hp != 0; hp = hp->hnext) 241: if (hp->hval == hashval) { 242: fseek(mesgread, (long) hp->hpt, 0); 243: fgetNUL(buf, sizeof buf, mesgread); 244: /* 245: fprintf(stderr, "Got (from %d) %s\n", hp->hpt, buf); 246: */ 247: if (strcmp(buf, str) == 0) 248: break; 249: } 250: if (!really || hp == 0) { 251: hp = (struct hash *) calloc(1, sizeof *hp); 252: hp->hnext = bucket[i]; 253: hp->hval = hashval; 254: hp->hpt = really ? ftell(mesgwrite) : fakept; 255: if (really) { 256: fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite); 257: fwrite("\n", sizeof (char), 1, mesgwrite); 258: } 259: bucket[i] = hp; 260: } 261: /* 262: fprintf(stderr, "%s hashed to %ld at %d\n", str, hp->hval, hp->hpt); 263: */ 264: return (hp->hpt); 265: } 266: 267: #include <sys/types.h> 268: #include <sys/stat.h> 269: 270: fgetNUL(obuf, rmdr, file) 271: char *obuf; 272: register int rmdr; 273: FILE *file; 274: { 275: register c; 276: register char *buf = obuf; 277: 278: while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF) 279: *buf++ = c; 280: *buf++ = 0; 281: getc(file); 282: return ((feof(file) || ferror(file)) ? NULL : 1); 283: }