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