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