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