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