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