Annotation of src/usr.bin/xstr/xstr.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: xstr.c,v 1.5 1994/12/24 16:57:59 cgd Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1980, 1993
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * 4. Neither the name of the University nor the names of its contributors
! 20: * may be used to endorse or promote products derived from this software
! 21: * without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: */
! 35:
! 36: #ifndef lint
! 37: static char copyright[] =
! 38: "@(#) Copyright (c) 1980, 1993\n\
! 39: The Regents of the University of California. All rights reserved.\n";
! 40: #endif /* not lint */
! 41:
! 42: #ifndef lint
! 43: #if 0
! 44: static char sccsid[] = "@(#)xstr.c 8.1 (Berkeley) 6/9/93";
! 45: #endif
! 46: static char rcsid[] = "$NetBSD: xstr.c,v 1.5 1994/12/24 16:57:59 cgd Exp $";
! 47: #endif /* not lint */
! 48:
! 49: #include <sys/types.h>
! 50: #include <signal.h>
! 51: #include <errno.h>
! 52: #include <unistd.h>
! 53: #include <stdio.h>
! 54: #include <ctype.h>
! 55: #include <string.h>
! 56: #include <stdlib.h>
! 57: #include "pathnames.h"
! 58:
! 59: /*
! 60: * xstr - extract and hash strings in a C program
! 61: *
! 62: * Bill Joy UCB
! 63: * November, 1978
! 64: */
! 65:
! 66: #define ignore(a) ((void) a)
! 67:
! 68: off_t tellpt;
! 69: off_t hashit();
! 70: void onintr();
! 71: char *savestr();
! 72: off_t yankstr();
! 73:
! 74: off_t mesgpt;
! 75: char *strings = "strings";
! 76:
! 77: char *array = 0;
! 78:
! 79: int cflg;
! 80: int vflg;
! 81: int readstd;
! 82:
! 83: main(argc, argv)
! 84: int argc;
! 85: char *argv[];
! 86: {
! 87: int c;
! 88:
! 89: while ((c = getopt(argc, argv, "-cvl:")) != -1)
! 90: switch (c) {
! 91: case '-':
! 92: readstd++;
! 93: break;
! 94: case 'c':
! 95: cflg++;
! 96: break;
! 97: case 'v':
! 98: vflg++;
! 99: break;
! 100: case 'l':
! 101: array = optarg;
! 102: break;
! 103: default:
! 104: fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ -l array ] [ - ] [ name ... ]\n");
! 105: exit (1);
! 106: }
! 107: argc -= optind;
! 108: argv += optind;
! 109:
! 110: if (array == 0)
! 111: array = "xstr";
! 112:
! 113: if (signal(SIGINT, SIG_IGN) == SIG_DFL)
! 114: signal(SIGINT, onintr);
! 115: if (cflg || argc == 0 && !readstd)
! 116: inithash();
! 117: else
! 118: strings = mktemp(strdup(_PATH_TMP));
! 119: while (readstd || argc > 0) {
! 120: if (freopen("x.c", "w", stdout) == NULL)
! 121: perror("x.c"), exit(1);
! 122: if (!readstd && freopen(argv[0], "r", stdin) == NULL)
! 123: perror(argv[0]), exit(2);
! 124: process("x.c");
! 125: if (readstd == 0)
! 126: argc--, argv++;
! 127: else
! 128: readstd = 0;
! 129: };
! 130: flushsh();
! 131: if (cflg == 0)
! 132: xsdotc();
! 133: if (strings[0] == '/')
! 134: ignore(unlink(strings));
! 135: exit(0);
! 136: }
! 137:
! 138: char linebuf[BUFSIZ];
! 139:
! 140: process(name)
! 141: char *name;
! 142: {
! 143: char *cp;
! 144: register int c;
! 145: register int incomm = 0;
! 146: int ret;
! 147:
! 148: printf("extern char\t%s[];\n", array);
! 149: for (;;) {
! 150: if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
! 151: if (ferror(stdin)) {
! 152: perror(name);
! 153: exit(3);
! 154: }
! 155: break;
! 156: }
! 157: if (linebuf[0] == '#') {
! 158: if (linebuf[1] == ' ' && isdigit(linebuf[2]))
! 159: printf("#line%s", &linebuf[1]);
! 160: else
! 161: printf("%s", linebuf);
! 162: continue;
! 163: }
! 164: for (cp = linebuf; c = *cp++;) switch (c) {
! 165:
! 166: case '"':
! 167: if (incomm)
! 168: goto def;
! 169: if ((ret = (int) yankstr(&cp)) == -1)
! 170: goto out;
! 171: printf("(&%s[%d])", array, ret);
! 172: break;
! 173:
! 174: case '\'':
! 175: if (incomm)
! 176: goto def;
! 177: putchar(c);
! 178: if (*cp)
! 179: putchar(*cp++);
! 180: break;
! 181:
! 182: case '/':
! 183: if (incomm || *cp != '*')
! 184: goto def;
! 185: incomm = 1;
! 186: cp++;
! 187: printf("/*");
! 188: continue;
! 189:
! 190: case '*':
! 191: if (incomm && *cp == '/') {
! 192: incomm = 0;
! 193: cp++;
! 194: printf("*/");
! 195: continue;
! 196: }
! 197: goto def;
! 198:
! 199: def:
! 200: default:
! 201: putchar(c);
! 202: break;
! 203: }
! 204: }
! 205: out:
! 206: if (ferror(stdout))
! 207: perror("x.c"), onintr();
! 208: }
! 209:
! 210: off_t
! 211: yankstr(cpp)
! 212: register char **cpp;
! 213: {
! 214: register char *cp = *cpp;
! 215: register int c, ch;
! 216: char dbuf[BUFSIZ];
! 217: register char *dp = dbuf;
! 218: register char *tp;
! 219:
! 220: while (c = *cp++) {
! 221: switch (c) {
! 222:
! 223: case '"':
! 224: cp++;
! 225: goto out;
! 226:
! 227: case '\\':
! 228: c = *cp++;
! 229: if (c == 0)
! 230: break;
! 231: if (c == '\n') {
! 232: if (fgets(linebuf, sizeof linebuf, stdin)
! 233: == NULL) {
! 234: if (ferror(stdin)) {
! 235: perror("x.c");
! 236: exit(3);
! 237: }
! 238: return(-1);
! 239: }
! 240: cp = linebuf;
! 241: continue;
! 242: }
! 243: for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++)
! 244: if (c == ch) {
! 245: c = *tp;
! 246: goto gotc;
! 247: }
! 248: if (!octdigit(c)) {
! 249: *dp++ = '\\';
! 250: break;
! 251: }
! 252: c -= '0';
! 253: if (!octdigit(*cp))
! 254: break;
! 255: c <<= 3, c += *cp++ - '0';
! 256: if (!octdigit(*cp))
! 257: break;
! 258: c <<= 3, c += *cp++ - '0';
! 259: break;
! 260: }
! 261: gotc:
! 262: *dp++ = c;
! 263: }
! 264: out:
! 265: *cpp = --cp;
! 266: *dp = 0;
! 267: return (hashit(dbuf, 1));
! 268: }
! 269:
! 270: octdigit(c)
! 271: char c;
! 272: {
! 273:
! 274: return (isdigit(c) && c != '8' && c != '9');
! 275: }
! 276:
! 277: inithash()
! 278: {
! 279: char buf[BUFSIZ];
! 280: register FILE *mesgread = fopen(strings, "r");
! 281:
! 282: if (mesgread == NULL)
! 283: return;
! 284: for (;;) {
! 285: mesgpt = tellpt;
! 286: if (fgetNUL(buf, sizeof buf, mesgread) == NULL)
! 287: break;
! 288: ignore(hashit(buf, 0));
! 289: }
! 290: ignore(fclose(mesgread));
! 291: }
! 292:
! 293: fgetNUL(obuf, rmdr, file)
! 294: char *obuf;
! 295: register int rmdr;
! 296: FILE *file;
! 297: {
! 298: register c;
! 299: register char *buf = obuf;
! 300:
! 301: while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
! 302: *buf++ = c;
! 303: *buf++ = 0;
! 304: return ((feof(file) || ferror(file)) ? NULL : 1);
! 305: }
! 306:
! 307: xgetc(file)
! 308: FILE *file;
! 309: {
! 310:
! 311: tellpt++;
! 312: return (getc(file));
! 313: }
! 314:
! 315: #define BUCKETS 128
! 316:
! 317: struct hash {
! 318: off_t hpt;
! 319: char *hstr;
! 320: struct hash *hnext;
! 321: short hnew;
! 322: } bucket[BUCKETS];
! 323:
! 324: off_t
! 325: hashit(str, new)
! 326: char *str;
! 327: int new;
! 328: {
! 329: int i;
! 330: register struct hash *hp, *hp0;
! 331:
! 332: hp = hp0 = &bucket[lastchr(str) & 0177];
! 333: while (hp->hnext) {
! 334: hp = hp->hnext;
! 335: i = istail(str, hp->hstr);
! 336: if (i >= 0)
! 337: return (hp->hpt + i);
! 338: }
! 339: if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) {
! 340: perror("xstr");
! 341: exit(8);
! 342: }
! 343: hp->hpt = mesgpt;
! 344: if (!(hp->hstr = strdup(str))) {
! 345: (void)fprintf(stderr, "xstr: %s\n", strerror(errno));
! 346: exit(1);
! 347: }
! 348: mesgpt += strlen(hp->hstr) + 1;
! 349: hp->hnext = hp0->hnext;
! 350: hp->hnew = new;
! 351: hp0->hnext = hp;
! 352: return (hp->hpt);
! 353: }
! 354:
! 355: flushsh()
! 356: {
! 357: register int i;
! 358: register struct hash *hp;
! 359: register FILE *mesgwrit;
! 360: register int old = 0, new = 0;
! 361:
! 362: for (i = 0; i < BUCKETS; i++)
! 363: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
! 364: if (hp->hnew)
! 365: new++;
! 366: else
! 367: old++;
! 368: if (new == 0 && old != 0)
! 369: return;
! 370: mesgwrit = fopen(strings, old ? "r+" : "w");
! 371: if (mesgwrit == NULL)
! 372: perror(strings), exit(4);
! 373: for (i = 0; i < BUCKETS; i++)
! 374: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
! 375: found(hp->hnew, hp->hpt, hp->hstr);
! 376: if (hp->hnew) {
! 377: fseek(mesgwrit, hp->hpt, 0);
! 378: ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
! 379: if (ferror(mesgwrit))
! 380: perror(strings), exit(4);
! 381: }
! 382: }
! 383: if (fclose(mesgwrit) == EOF)
! 384: perror(strings), exit(4);
! 385: }
! 386:
! 387: found(new, off, str)
! 388: int new;
! 389: off_t off;
! 390: char *str;
! 391: {
! 392: if (vflg == 0)
! 393: return;
! 394: if (!new)
! 395: fprintf(stderr, "found at %d:", (int) off);
! 396: else
! 397: fprintf(stderr, "new at %d:", (int) off);
! 398: prstr(str);
! 399: fprintf(stderr, "\n");
! 400: }
! 401:
! 402: prstr(cp)
! 403: register char *cp;
! 404: {
! 405: register int c;
! 406:
! 407: while (c = (*cp++ & 0377))
! 408: if (c < ' ')
! 409: fprintf(stderr, "^%c", c + '`');
! 410: else if (c == 0177)
! 411: fprintf(stderr, "^?");
! 412: else if (c > 0200)
! 413: fprintf(stderr, "\\%03o", c);
! 414: else
! 415: fprintf(stderr, "%c", c);
! 416: }
! 417:
! 418: xsdotc()
! 419: {
! 420: register FILE *strf = fopen(strings, "r");
! 421: register FILE *xdotcf;
! 422:
! 423: if (strf == NULL)
! 424: perror(strings), exit(5);
! 425: xdotcf = fopen("xs.c", "w");
! 426: if (xdotcf == NULL)
! 427: perror("xs.c"), exit(6);
! 428: fprintf(xdotcf, "char\t%s[] = {\n", array);
! 429: for (;;) {
! 430: register int i, c;
! 431:
! 432: for (i = 0; i < 8; i++) {
! 433: c = getc(strf);
! 434: if (ferror(strf)) {
! 435: perror(strings);
! 436: onintr();
! 437: }
! 438: if (feof(strf)) {
! 439: fprintf(xdotcf, "\n");
! 440: goto out;
! 441: }
! 442: fprintf(xdotcf, "0x%02x,", c);
! 443: }
! 444: fprintf(xdotcf, "\n");
! 445: }
! 446: out:
! 447: fprintf(xdotcf, "};\n");
! 448: ignore(fclose(xdotcf));
! 449: ignore(fclose(strf));
! 450: }
! 451:
! 452: lastchr(cp)
! 453: register char *cp;
! 454: {
! 455:
! 456: while (cp[0] && cp[1])
! 457: cp++;
! 458: return (*cp);
! 459: }
! 460:
! 461: istail(str, of)
! 462: register char *str, *of;
! 463: {
! 464: register int d = strlen(of) - strlen(str);
! 465:
! 466: if (d < 0 || strcmp(&of[d], str) != 0)
! 467: return (-1);
! 468: return (d);
! 469: }
! 470:
! 471: void
! 472: onintr()
! 473: {
! 474:
! 475: ignore(signal(SIGINT, SIG_IGN));
! 476: if (strings[0] == '/')
! 477: ignore(unlink(strings));
! 478: ignore(unlink("x.c"));
! 479: ignore(unlink("xs.c"));
! 480: exit(7);
! 481: }