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