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[] = "@(#)xstr.c 8.1 (Berkeley) 6/9/93"; 42 #endif /* not lint */ 43 44 #include <sys/types.h> 45 #include <signal.h> 46 #include <errno.h> 47 #include <unistd.h> 48 #include <stdio.h> 49 #include <ctype.h> 50 #include <string.h> 51 #include "pathnames.h" 52 53 /* 54 * xstr - extract and hash strings in a C program 55 * 56 * Bill Joy UCB 57 * November, 1978 58 */ 59 60 #define ignore(a) ((void) a) 61 62 off_t tellpt; 63 off_t hashit(); 64 void onintr(); 65 char *savestr(); 66 off_t yankstr(); 67 68 off_t mesgpt; 69 char *strings = "strings"; 70 71 int cflg; 72 int vflg; 73 int readstd; 74 75 main(argc, argv) 76 int argc; 77 char *argv[]; 78 { 79 80 argc--, argv++; 81 while (argc > 0 && argv[0][0] == '-') { 82 register char *cp = &(*argv++)[1]; 83 84 argc--; 85 if (*cp == 0) { 86 readstd++; 87 continue; 88 } 89 do switch (*cp++) { 90 91 case 'c': 92 cflg++; 93 continue; 94 95 case 'v': 96 vflg++; 97 continue; 98 99 default: 100 fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n"); 101 } while (*cp); 102 } 103 if (signal(SIGINT, SIG_IGN) == SIG_DFL) 104 signal(SIGINT, onintr); 105 if (cflg || argc == 0 && !readstd) 106 inithash(); 107 else 108 strings = mktemp(strdup(_PATH_TMP)); 109 while (readstd || argc > 0) { 110 if (freopen("x.c", "w", stdout) == NULL) 111 perror("x.c"), exit(1); 112 if (!readstd && freopen(argv[0], "r", stdin) == NULL) 113 perror(argv[0]), exit(2); 114 process("x.c"); 115 if (readstd == 0) 116 argc--, argv++; 117 else 118 readstd = 0; 119 }; 120 flushsh(); 121 if (cflg == 0) 122 xsdotc(); 123 if (strings[0] == '/') 124 ignore(unlink(strings)); 125 exit(0); 126 } 127 128 char linebuf[BUFSIZ]; 129 130 process(name) 131 char *name; 132 { 133 char *cp; 134 register int c; 135 register int incomm = 0; 136 int ret; 137 138 printf("extern char\txstr[];\n"); 139 for (;;) { 140 if (fgets(linebuf, sizeof linebuf, stdin) == NULL) { 141 if (ferror(stdin)) { 142 perror(name); 143 exit(3); 144 } 145 break; 146 } 147 if (linebuf[0] == '#') { 148 if (linebuf[1] == ' ' && isdigit(linebuf[2])) 149 printf("#line%s", &linebuf[1]); 150 else 151 printf("%s", linebuf); 152 continue; 153 } 154 for (cp = linebuf; c = *cp++;) switch (c) { 155 156 case '"': 157 if (incomm) 158 goto def; 159 if ((ret = (int) yankstr(&cp)) == -1) 160 goto out; 161 printf("(&xstr[%d])", ret); 162 break; 163 164 case '\'': 165 if (incomm) 166 goto def; 167 putchar(c); 168 if (*cp) 169 putchar(*cp++); 170 break; 171 172 case '/': 173 if (incomm || *cp != '*') 174 goto def; 175 incomm = 1; 176 cp++; 177 printf("/*"); 178 continue; 179 180 case '*': 181 if (incomm && *cp == '/') { 182 incomm = 0; 183 cp++; 184 printf("*/"); 185 continue; 186 } 187 goto def; 188 189 def: 190 default: 191 putchar(c); 192 break; 193 } 194 } 195 out: 196 if (ferror(stdout)) 197 perror("x.c"), onintr(); 198 } 199 200 off_t 201 yankstr(cpp) 202 register char **cpp; 203 { 204 register char *cp = *cpp; 205 register int c, ch; 206 char dbuf[BUFSIZ]; 207 register char *dp = dbuf; 208 register char *tp; 209 210 while (c = *cp++) { 211 switch (c) { 212 213 case '"': 214 cp++; 215 goto out; 216 217 case '\\': 218 c = *cp++; 219 if (c == 0) 220 break; 221 if (c == '\n') { 222 if (fgets(linebuf, sizeof linebuf, stdin) 223 == NULL) { 224 if (ferror(stdin)) { 225 perror("x.c"); 226 exit(3); 227 } 228 return(-1); 229 } 230 cp = linebuf; 231 continue; 232 } 233 for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++) 234 if (c == ch) { 235 c = *tp; 236 goto gotc; 237 } 238 if (!octdigit(c)) { 239 *dp++ = '\\'; 240 break; 241 } 242 c -= '0'; 243 if (!octdigit(*cp)) 244 break; 245 c <<= 3, c += *cp++ - '0'; 246 if (!octdigit(*cp)) 247 break; 248 c <<= 3, c += *cp++ - '0'; 249 break; 250 } 251 gotc: 252 *dp++ = c; 253 } 254 out: 255 *cpp = --cp; 256 *dp = 0; 257 return (hashit(dbuf, 1)); 258 } 259 260 octdigit(c) 261 char c; 262 { 263 264 return (isdigit(c) && c != '8' && c != '9'); 265 } 266 267 inithash() 268 { 269 char buf[BUFSIZ]; 270 register FILE *mesgread = fopen(strings, "r"); 271 272 if (mesgread == NULL) 273 return; 274 for (;;) { 275 mesgpt = tellpt; 276 if (fgetNUL(buf, sizeof buf, mesgread) == NULL) 277 break; 278 ignore(hashit(buf, 0)); 279 } 280 ignore(fclose(mesgread)); 281 } 282 283 fgetNUL(obuf, rmdr, file) 284 char *obuf; 285 register int rmdr; 286 FILE *file; 287 { 288 register c; 289 register char *buf = obuf; 290 291 while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF) 292 *buf++ = c; 293 *buf++ = 0; 294 return ((feof(file) || ferror(file)) ? NULL : 1); 295 } 296 297 xgetc(file) 298 FILE *file; 299 { 300 301 tellpt++; 302 return (getc(file)); 303 } 304 305 #define BUCKETS 128 306 307 struct hash { 308 off_t hpt; 309 char *hstr; 310 struct hash *hnext; 311 short hnew; 312 } bucket[BUCKETS]; 313 314 off_t 315 hashit(str, new) 316 char *str; 317 int new; 318 { 319 int i; 320 register struct hash *hp, *hp0; 321 322 hp = hp0 = &bucket[lastchr(str) & 0177]; 323 while (hp->hnext) { 324 hp = hp->hnext; 325 i = istail(str, hp->hstr); 326 if (i >= 0) 327 return (hp->hpt + i); 328 } 329 if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) { 330 perror("xstr"); 331 exit(8); 332 } 333 hp->hpt = mesgpt; 334 if (!(hp->hstr = strdup(str))) { 335 (void)fprintf(stderr, "xstr: %s\n", strerror(errno)); 336 exit(1); 337 } 338 mesgpt += strlen(hp->hstr) + 1; 339 hp->hnext = hp0->hnext; 340 hp->hnew = new; 341 hp0->hnext = hp; 342 return (hp->hpt); 343 } 344 345 flushsh() 346 { 347 register int i; 348 register struct hash *hp; 349 register FILE *mesgwrit; 350 register int old = 0, new = 0; 351 352 for (i = 0; i < BUCKETS; i++) 353 for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) 354 if (hp->hnew) 355 new++; 356 else 357 old++; 358 if (new == 0 && old != 0) 359 return; 360 mesgwrit = fopen(strings, old ? "r+" : "w"); 361 if (mesgwrit == NULL) 362 perror(strings), exit(4); 363 for (i = 0; i < BUCKETS; i++) 364 for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) { 365 found(hp->hnew, hp->hpt, hp->hstr); 366 if (hp->hnew) { 367 fseek(mesgwrit, hp->hpt, 0); 368 ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit)); 369 if (ferror(mesgwrit)) 370 perror(strings), exit(4); 371 } 372 } 373 if (fclose(mesgwrit) == EOF) 374 perror(strings), exit(4); 375 } 376 377 found(new, off, str) 378 int new; 379 off_t off; 380 char *str; 381 { 382 if (vflg == 0) 383 return; 384 if (!new) 385 fprintf(stderr, "found at %d:", (int) off); 386 else 387 fprintf(stderr, "new at %d:", (int) off); 388 prstr(str); 389 fprintf(stderr, "\n"); 390 } 391 392 prstr(cp) 393 register char *cp; 394 { 395 register int c; 396 397 while (c = (*cp++ & 0377)) 398 if (c < ' ') 399 fprintf(stderr, "^%c", c + '`'); 400 else if (c == 0177) 401 fprintf(stderr, "^?"); 402 else if (c > 0200) 403 fprintf(stderr, "\\%03o", c); 404 else 405 fprintf(stderr, "%c", c); 406 } 407 408 xsdotc() 409 { 410 register FILE *strf = fopen(strings, "r"); 411 register FILE *xdotcf; 412 413 if (strf == NULL) 414 perror(strings), exit(5); 415 xdotcf = fopen("xs.c", "w"); 416 if (xdotcf == NULL) 417 perror("xs.c"), exit(6); 418 fprintf(xdotcf, "char\txstr[] = {\n"); 419 for (;;) { 420 register int i, c; 421 422 for (i = 0; i < 8; i++) { 423 c = getc(strf); 424 if (ferror(strf)) { 425 perror(strings); 426 onintr(); 427 } 428 if (feof(strf)) { 429 fprintf(xdotcf, "\n"); 430 goto out; 431 } 432 fprintf(xdotcf, "0x%02x,", c); 433 } 434 fprintf(xdotcf, "\n"); 435 } 436 out: 437 fprintf(xdotcf, "};\n"); 438 ignore(fclose(xdotcf)); 439 ignore(fclose(strf)); 440 } 441 442 lastchr(cp) 443 register char *cp; 444 { 445 446 while (cp[0] && cp[1]) 447 cp++; 448 return (*cp); 449 } 450 451 istail(str, of) 452 register char *str, *of; 453 { 454 register int d = strlen(of) - strlen(str); 455 456 if (d < 0 || strcmp(&of[d], str) != 0) 457 return (-1); 458 return (d); 459 } 460 461 void 462 onintr() 463 { 464 465 ignore(signal(SIGINT, SIG_IGN)); 466 if (strings[0] == '/') 467 ignore(unlink(strings)); 468 ignore(unlink("x.c")); 469 ignore(unlink("xs.c")); 470 exit(7); 471 } 472