xstr.c revision 1590
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 35static 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 41static 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 62off_t tellpt; 63off_t hashit(); 64void onintr(); 65char *savestr(); 66off_t yankstr(); 67 68off_t mesgpt; 69char *strings = "strings"; 70 71int cflg; 72int vflg; 73int readstd; 74 75main(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 128char linebuf[BUFSIZ]; 129 130process(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 189def: 190 default: 191 putchar(c); 192 break; 193 } 194 } 195out: 196 if (ferror(stdout)) 197 perror("x.c"), onintr(); 198} 199 200off_t 201yankstr(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 } 251gotc: 252 *dp++ = c; 253 } 254out: 255 *cpp = --cp; 256 *dp = 0; 257 return (hashit(dbuf, 1)); 258} 259 260octdigit(c) 261 char c; 262{ 263 264 return (isdigit(c) && c != '8' && c != '9'); 265} 266 267inithash() 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 283fgetNUL(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 297xgetc(file) 298 FILE *file; 299{ 300 301 tellpt++; 302 return (getc(file)); 303} 304 305#define BUCKETS 128 306 307struct hash { 308 off_t hpt; 309 char *hstr; 310 struct hash *hnext; 311 short hnew; 312} bucket[BUCKETS]; 313 314off_t 315hashit(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 345flushsh() 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 377found(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 392prstr(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 408xsdotc() 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 } 436out: 437 fprintf(xdotcf, "};\n"); 438 ignore(fclose(xdotcf)); 439 ignore(fclose(strf)); 440} 441 442lastchr(cp) 443 register char *cp; 444{ 445 446 while (cp[0] && cp[1]) 447 cp++; 448 return (*cp); 449} 450 451istail(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 461void 462onintr() 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