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