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