|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <ctype.h> ! 3: ! 4: #ifdef MSDOS ! 5: #define TMPFILE "m4%dXXX" ! 6: #define TMPMIN 2 /* minimum temp file length */ ! 7: #else ! 8: #define TMPFILE "/tmp/m4%dxxxxxx" ! 9: #define TMPMIN 6 ! 10: #endif ! 11: ! 12: #define isletter(c) (isalpha(c)||c=='_') ! 13: #define BQUOTE '`' ! 14: #define EQUOTE '\'' ! 15: #define HASHSZ 199 ! 16: #define STRBLK 16 /* block size for dynamic string storage */ ! 17: #if STRBLK < 12 ! 18: need room for decimal rep of long int ! 19: #endif ! 20: ! 21: enum {FUNC, MACD, DSKF, MSTR}; ! 22: enum {EX, MY, DV, MD, AD, SB, EQ, NE, LE, GE, LT, GT, AN, OR, RP, NL}; ! 23: ! 24: typedef struct { /* for storing variable-length strings */ ! 25: int s_refc; /* references--when zero space is freed */ ! 26: int s_hash; /* raw hash value (sum of chars in body) */ ! 27: char *s_body; /* start of contents */ ! 28: char *s_next; /* end of contents */ ! 29: char *s_last; /* end of storage */ ! 30: } STRING; ! 31: ! 32: typedef union ifr { /* input-source stack frame */ ! 33: struct { ! 34: struct ifr *i_back; ! 35: char i_cbuf; /* unget buffer for lookahead */ ! 36: int i_type; /* if type is MSTRing */ ! 37: STRING *i_pstr; ! 38: char *i_pchr; /* next char */ ! 39: } ifb; ! 40: struct { ! 41: struct ifr *i_back; ! 42: char i_cbuf; ! 43: int i_type; /* if type is DSKFile */ ! 44: FILE *i_fp; ! 45: } ifdk; ! 46: } IFRAME; ! 47: ! 48: typedef struct fstk { /* file information stack frame */ ! 49: struct fstk *f_back; ! 50: STRING *f_name; /* pointer to name (NULL if stdin) */ ! 51: int f_flag; /* flag = 0 until EOF is reached */ ! 52: int f_line; /* line counter */ ! 53: } FFRAME; ! 54: ! 55: typedef struct ofr { /* argument collection stack frame */ ! 56: struct ofr *o_back; ! 57: STRING *o_pstr; ! 58: } OFRAME; ! 59: ! 60: typedef struct ent { /* symbol table entry */ ! 61: struct ent *e_next; ! 62: int e_type; /* FUNC or MACD */ ! 63: union { ! 64: int (*e_pfun)(); ! 65: STRING *e_pstr; ! 66: } e_at; ! 67: STRING *e_name; ! 68: } ENTRY; ! 69: ! 70: /* ! 71: * built in functions ! 72: */ ! 73: extern int mchangequote(), mdecr(), mdefine(), mdivert(), mdivnum(), mdnl(), ! 74: mdumpdef(), merrprint(), meval(), mifdef(), mifelse(), ! 75: minclude(), mincr(), mindex(), mlen(), mmaketemp(), msinclude(), ! 76: msubstr(), msyscmd(), mtranslit(), mundefine(), mundivert(); ! 77: ! 78: /* ! 79: * output file info ! 80: */ ! 81: struct { ! 82: char *name; ! 83: FILE *fp; ! 84: } outfile[10] = {{ NULL, stdout }}; ! 85: ! 86: /* ! 87: * op table for eval ! 88: */ ! 89: struct opdata { ! 90: int optype; ! 91: char keychar; ! 92: char secchar; ! 93: int prec; ! 94: } optable[] = { ! 95: #define SI 8 /* precedence of unary + and - */ ! 96: EX, '^', '\0', 7, EX, '*', '*', 7, ! 97: MY, '*', '\0', 6, DV, '/', '\0', 6, MD, '%', '\0', 6, ! 98: AD, '+', '\0', 5, SB, '-', '\0', 5, ! 99: EQ, '=', '=', 4, GE, '>', '=', 4, GT, '>', '\0', 4, ! 100: NE, '!', '=', 4, LE, '<', '=', 4, LT, '<', '\0', 4, ! 101: #define NT 3 /* precedence of unary ! */ ! 102: AN, '&', '&', 2, AN, '&', '\0', 2, ! 103: OR, '|', '|', 1, OR, '|', '\0', 1, ! 104: RP, ')', '\0', 10, NL, '\0', '\0', 0 ! 105: #define LP 0 /* precedence of open paren */ ! 106: }; ! 107: ! 108: ENTRY *e_root[HASHSZ]; /* pointers to symbol table hash buckets */ ! 109: OFRAME *ostkptr; /* output stack pointer */ ! 110: IFRAME *istkptr; /* input stack pointer */ ! 111: FFRAME *fstkptr; /* file info stack pointer */ ! 112: FILE *offp = stdout; /* current output file pointer */ ! 113: int ofnum; /* current diversion number */ ! 114: int lstdchr = '\n'; /* last char from stdin */ ! 115: int single; /* single argument flag */ ! 116: int dnlflag; /* delete to newline flag */ ! 117: ! 118: char bqt = BQUOTE; ! 119: char eqt = EQUOTE; ! 120: extern char *alloc(); ! 121: STRING *makestr(); ! 122: ! 123: main(argc, argv) ! 124: int argc; ! 125: char *argv[]; ! 126: { ! 127: #ifdef MSDOS ! 128: msdoscvt("m4", &argc, &argv); ! 129: #endif ! 130: buildin("changequote", mchangequote); ! 131: buildin("decr", mdecr); ! 132: buildin("define", mdefine); ! 133: buildin("divert", mdivert); ! 134: buildin("divnum", mdivnum); ! 135: buildin("dnl", mdnl); ! 136: buildin("dumpdef", mdumpdef); ! 137: buildin("errprint", merrprint); ! 138: buildin("eval", meval); ! 139: buildin("ifdef", mifdef); ! 140: buildin("ifelse", mifelse); ! 141: buildin("include", minclude); ! 142: buildin("incr", mincr); ! 143: buildin("index", mindex); ! 144: buildin("len", mlen); ! 145: buildin("maketemp", mmaketemp); ! 146: buildin("sinclude", msinclude); ! 147: buildin("substr", msubstr); ! 148: buildin("syscmd", msyscmd); ! 149: buildin("translit", mtranslit); ! 150: buildin("undefine", mundefine); ! 151: buildin("undivert", mundivert); ! 152: ! 153: single = (argc == 2); ! 154: if (argc > 1) { ! 155: while (--argc) ! 156: if (pushfile(*++argv)) ! 157: process(0); ! 158: else ! 159: errorp(0, "cannot open %s", *argv); ! 160: } else { ! 161: pushfile("-"); ! 162: process(0); ! 163: } ! 164: mdivert(NULL); ! 165: mundivert(NULL); ! 166: exit(0); ! 167: } ! 168: ! 169: process(pct) ! 170: int pct; ! 171: { ! 172: char lc = '\0'; ! 173: register int c, qct = 0; ! 174: int i; ! 175: STRING *a[10]; ! 176: register STRING *b; ! 177: ENTRY *e, *find(); ! 178: ! 179: for (c=nxch(); pct && isspace(c); c=nxch()) ! 180: ; ! 181: while (c != '\0') { ! 182: if (qct) ! 183: if (c == eqt) { ! 184: if (--qct) ! 185: outputc(c); ! 186: } else { ! 187: if (c == bqt) ! 188: ++qct; ! 189: outputc(c); ! 190: } ! 191: else if (c == bqt) ! 192: ++qct; ! 193: else if (c==')' && pct && !--pct || c==',' && pct==1) ! 194: return (c); ! 195: else if (isletter(c) && !isletter(lc) && !isdigit(lc)) { ! 196: b = makestr(); ! 197: do { ! 198: appendstr(b, c); ! 199: lc = c; ! 200: c = nxch(); ! 201: } while (isletter(c) || isdigit(c)); ! 202: if ((e=find(b)) == NULL) { ! 203: outputs(b->s_body); ! 204: decstr(b); ! 205: continue; ! 206: } ! 207: for (i=9; i; a[i--]=NULL) ! 208: ; ! 209: a[0] = b; ! 210: if (c != '(') { ! 211: istkptr->i_cbuf = c; ! 212: if (c=='\n' && istkptr->i_type==DSKF) ! 213: if (fstkptr->f_flag) ! 214: --fstkptr->f_back->f_line; ! 215: else ! 216: --fstkptr->f_line; ! 217: } else do { ! 218: pushout(b=makestr()); ! 219: c = process(1); ! 220: if (i++<9 && strlen(b->s_body)) ! 221: a[i] = b; ! 222: else ! 223: decstr(b); ! 224: popout(); ! 225: } while (c != ')'); ! 226: if (e->e_type == MACD) ! 227: macro(e->e_at.e_pstr, a); ! 228: else ! 229: (*e->e_at.e_pfun)(a); ! 230: for (i = 0; i < 10; i++) ! 231: decstr(a[i]); ! 232: c = '\0'; ! 233: } else { ! 234: if (c=='(' && pct) ! 235: ++pct; ! 236: outputc(c); ! 237: } ! 238: lc = c; ! 239: c = nxch(); ! 240: } ! 241: if (pct) ! 242: errorp(1, "unexpected EOF"); ! 243: return (c); ! 244: } ! 245: ! 246: macro(ps, pps) ! 247: STRING *ps, **pps; ! 248: { ! 249: STRING *x; ! 250: register char *b, *v; ! 251: ! 252: x = makestr(); ! 253: b = ps->s_body; ! 254: while (*b) { ! 255: if (*b != '$') ! 256: appendstr(x, *b++); ! 257: else if (!isdigit(*++b)) ! 258: appendstr(x, '$'); ! 259: else if (ps = pps[*b++ - '0']) ! 260: for (v = ps->s_body; *v; v++) ! 261: appendstr(x, *v); ! 262: } ! 263: pushstr(x); ! 264: decstr(x); ! 265: } ! 266: ! 267: pushfile(s) ! 268: char *s; ! 269: { ! 270: FILE *fp, *fopen(); ! 271: register STRING *a = NULL; ! 272: register FFRAME *ftemp = fstkptr; ! 273: char c; ! 274: ! 275: if (ftemp!=NULL && ftemp->f_flag) { ! 276: decstr(ftemp->f_name); ! 277: fstkptr = ftemp->f_back; ! 278: free(ftemp); ! 279: } ! 280: if ( strcmp(s, "-") == 0 ) ! 281: fp = stdin; ! 282: else if ( (fp = fopen(s, "r")) == NULL ) ! 283: return (0); ! 284: pushinp(DSKF); ! 285: istkptr->i_fp = fp; ! 286: ftemp = (FFRAME *)alloc(sizeof(FFRAME)); ! 287: ftemp->f_back = fstkptr; ! 288: ftemp->f_line = 1; ! 289: ftemp->f_flag = 0; ! 290: if (fp!=stdin && !(fstkptr==NULL && single)) { ! 291: a = makestr(); ! 292: while (c = *s++) ! 293: appendstr(a, c); ! 294: } ! 295: ftemp->f_name = a; ! 296: fstkptr = ftemp; ! 297: return (1); ! 298: } ! 299: ! 300: pushstr(a) ! 301: STRING *a; ! 302: { ! 303: if (a==NULL || *a->s_body=='\0') ! 304: return; ! 305: pushinp(MSTR); ! 306: istkptr->i_pstr = a; ! 307: istkptr->i_pchr = a->s_body; ! 308: ++a->s_refc; ! 309: } ! 310: ! 311: pushnum(x) ! 312: long x; ! 313: { ! 314: register STRING *a; ! 315: ! 316: a = makestr(); ! 317: sprintf(a->s_body, "%ld", x); ! 318: pushstr(a); ! 319: decstr(a); ! 320: } ! 321: ! 322: pushinp(t) ! 323: char t; ! 324: { ! 325: IFRAME *itemp; ! 326: ! 327: itemp = istkptr; ! 328: istkptr = (IFRAME *)alloc(sizeof(IFRAME)); ! 329: istkptr->i_back = itemp; ! 330: istkptr->i_type = t; ! 331: istkptr->i_cbuf = '\0'; ! 332: } ! 333: ! 334: popinp() ! 335: { ! 336: IFRAME *itemp; ! 337: ! 338: itemp = istkptr; ! 339: switch (istkptr->i_type) { ! 340: case MSTR: ! 341: decstr(istkptr->i_pstr); ! 342: break; ! 343: case DSKF: ! 344: if (istkptr->i_fp != stdin) ! 345: fclose(istkptr->i_fp); ! 346: fstkptr->f_flag = 1; ! 347: break; ! 348: } ! 349: istkptr = istkptr->i_back; ! 350: free(itemp); ! 351: return (istkptr != NULL); ! 352: } ! 353: ! 354: pushout(b) ! 355: STRING *b; ! 356: { ! 357: OFRAME *otemp; ! 358: ! 359: otemp = (OFRAME *)alloc(sizeof(OFRAME)); ! 360: otemp->o_back = ostkptr; ! 361: otemp->o_pstr = b; ! 362: ostkptr = otemp; ! 363: ++b->s_refc; ! 364: } ! 365: ! 366: popout() ! 367: { ! 368: OFRAME *otemp; ! 369: ! 370: otemp = ostkptr; ! 371: ostkptr = ostkptr->o_back; ! 372: decstr(otemp->o_pstr); ! 373: free(otemp); ! 374: } ! 375: ! 376: nxch() ! 377: { ! 378: register int c; ! 379: FFRAME *ftemp; ! 380: ! 381: if (istkptr == NULL) ! 382: return ('\0'); ! 383: if ((ftemp = fstkptr)->f_flag) { ! 384: decstr(ftemp->f_name); ! 385: fstkptr = ftemp->f_back; ! 386: free(ftemp); ! 387: } ! 388: switch (istkptr->i_type) { ! 389: case DSKF: ! 390: if (c=istkptr->i_cbuf) ! 391: istkptr->i_cbuf = '\0'; ! 392: else ! 393: c = getc(istkptr->i_fp); ! 394: if (istkptr->i_fp == stdin) ! 395: lstdchr = c; ! 396: if (c == EOF) ! 397: c = '\0'; ! 398: else if (c == '\n') ! 399: if (fstkptr->f_flag) ! 400: ++fstkptr->f_back->f_line; ! 401: else ! 402: ++fstkptr->f_line; ! 403: break; ! 404: case MSTR: ! 405: if (c=istkptr->i_cbuf) ! 406: istkptr->i_cbuf = '\0'; ! 407: else ! 408: c = *istkptr->i_pchr++; ! 409: break; ! 410: } ! 411: if (c == '\0') ! 412: return (popinp()? nxch() : c); ! 413: else if (!dnlflag) ! 414: return (c); ! 415: if (c == '\n') ! 416: dnlflag = 0; ! 417: return (nxch()); ! 418: } ! 419: ! 420: outputc(c) ! 421: char c; ! 422: { ! 423: if (ostkptr != NULL) ! 424: appendstr(ostkptr->o_pstr, c); ! 425: else ! 426: outc(c); ! 427: } ! 428: ! 429: outc(c) ! 430: char c; ! 431: { ! 432: if (offp != NULL) ! 433: putc(c, offp); ! 434: } ! 435: ! 436: ! 437: STRING * ! 438: makestr() ! 439: { ! 440: register STRING *a; ! 441: ! 442: a = (STRING *)alloc(sizeof(STRING)); ! 443: a->s_body = a->s_next = (STRING *)alloc(STRBLK); ! 444: a->s_last = a->s_body + STRBLK - 1; ! 445: a->s_refc = 1; ! 446: a->s_hash = 0; ! 447: *a->s_next = '\0'; ! 448: return (a); ! 449: } ! 450: ! 451: appendstr(a, c) ! 452: STRING *a; ! 453: char c; ! 454: { ! 455: register char *r, *s, *t; ! 456: int size; ! 457: ! 458: if (a->s_next < a->s_last) { ! 459: *a->s_next++ = c; ! 460: *a->s_next = '\0'; ! 461: } else { ! 462: r = s = alloc(size = a->s_last - (t = a->s_body) + 1 + STRBLK); ! 463: while (*s++ = *t++) ! 464: ; ! 465: *(a->s_next = s) = '\0'; ! 466: *--s = c; ! 467: free(a->s_body); ! 468: a->s_last = (a->s_body = r) + size - 1; ! 469: } ! 470: a->s_hash += c; ! 471: } ! 472: ! 473: decstr(a) ! 474: STRING *a; ! 475: { ! 476: if (a == NULL) ! 477: return; ! 478: if (--a->s_refc) ! 479: return; ! 480: free(a->s_body); ! 481: free(a); ! 482: } ! 483: ! 484: cmpstr(a, b) ! 485: STRING *a, *b; ! 486: { ! 487: if (a==NULL && b==NULL) ! 488: return (1); ! 489: if (a==NULL && b!=NULL || a!=NULL && b==NULL) ! 490: return (0); ! 491: return (!strcmp(a->s_body, b->s_body)); ! 492: } ! 493: ! 494: outputs(s) ! 495: char *s; ! 496: { ! 497: register char *t, c; ! 498: ! 499: for (t = s; c = *t++; outputc(c)) ! 500: ; ! 501: } ! 502: ! 503: ENTRY * ! 504: find(a) ! 505: STRING *a; ! 506: { ! 507: register ENTRY *e; ! 508: register int hash; ! 509: ! 510: hash = a->s_hash; ! 511: for (e = e_root[hash % HASHSZ]; e != NULL; e = e->e_next) ! 512: if (e->e_name->s_hash == hash ! 513: && strcmp(e->e_name->s_body, a->s_body) == 0) ! 514: return (e); ! 515: return (NULL); ! 516: } ! 517: ! 518: buildin(s, f) ! 519: char *s; ! 520: int (*f)(); ! 521: { ! 522: STRING *a; ! 523: register int hash; ! 524: register ENTRY *e; ! 525: ! 526: a = makestr(); ! 527: while (*s) ! 528: appendstr(a, *s++); ! 529: hash = a->s_hash % HASHSZ; ! 530: e = (ENTRY *)alloc(sizeof(ENTRY)); ! 531: e->e_next = e_root[hash]; ! 532: e->e_type = FUNC; ! 533: e->e_at.e_pfun = f; ! 534: e->e_name = a; ! 535: e_root[hash] = e; ! 536: } ! 537: ! 538: char * ! 539: alloc(n) ! 540: int n; ! 541: { ! 542: char *x; ! 543: ! 544: if ((x=malloc(n)) != NULL) ! 545: return(x); ! 546: errorp(1, "out of space"); ! 547: } ! 548: ! 549: /* VARARGS */ ! 550: errorp(f, x) ! 551: int f; ! 552: { ! 553: fprintf(stderr, "m4: "); ! 554: if (fstkptr != NULL) { ! 555: if (fstkptr->f_name != NULL) ! 556: fprintf(stderr, "%s: ", fstkptr->f_name->s_body); ! 557: fprintf(stderr, "%d: ", fstkptr->f_line); ! 558: } ! 559: fprintf(stderr, "%r", &x); ! 560: putc('\n', stderr); ! 561: if (f) { ! 562: while (lstdchr!=EOF && lstdchr!='\n') ! 563: lstdchr = getchar(); ! 564: exit(1); ! 565: } ! 566: } ! 567: ! 568: mchangequote(pps) ! 569: STRING **pps; ! 570: { ! 571: bqt = pps[1]? *pps[1]->s_body : BQUOTE; ! 572: eqt = pps[2]? *pps[2]->s_body : EQUOTE; ! 573: } ! 574: ! 575: mdefine(pps) ! 576: STRING **pps; ! 577: { ! 578: ENTRY *find(); ! 579: register ENTRY *e; ! 580: register char *s; ! 581: register int hash; ! 582: int c; ! 583: static char illmac[] = "illegal macro name: %s"; ! 584: ! 585: if (pps[1]==NULL || !isletter(*pps[1]->s_body)) { ! 586: errorp(0, illmac, pps[1]!=NULL? pps[1]->s_body : NULL); ! 587: return; ! 588: } ! 589: s = pps[1]->s_body + 1; ! 590: while (c = *s++) ! 591: if (!(isletter(c)||isdigit(c))) { ! 592: errorp(0, illmac, pps[1]->s_body); ! 593: return; ! 594: } ! 595: if (e = find(pps[1])) { ! 596: if (e->e_type == MACD) ! 597: decstr(e->e_at.e_pstr); ! 598: } else { ! 599: e = (ENTRY *)alloc(sizeof(ENTRY)); ! 600: e->e_next = e_root[hash = pps[1]->s_hash % HASHSZ]; ! 601: e->e_name = pps[1]; ! 602: ++pps[1]->s_refc; ! 603: e_root[hash] = e; ! 604: } ! 605: e->e_type = MACD; ! 606: if (pps[2]) { ! 607: e->e_at.e_pstr = pps[2]; ! 608: ++pps[2]->s_refc; ! 609: } else ! 610: e->e_at.e_pstr = makestr(); ! 611: } ! 612: ! 613: mdivert(pps) ! 614: STRING **pps; ! 615: { ! 616: char *fn; ! 617: ! 618: if (pps == NULL) ! 619: ofnum = 0; ! 620: else ! 621: ofnum = (pps[1] != NULL)? atoi(pps[1]->s_body) : 0; ! 622: if (ofnum>0 && ofnum<=9) { ! 623: if (outfile[ofnum].fp == NULL) { ! 624: outfile[ofnum].name = fn = alloc(15); ! 625: sprintf(fn, TMPFILE, ofnum); ! 626: mktemp(fn); ! 627: if ((outfile[ofnum].fp=fopen(fn,"w"))==NULL) ! 628: errorp(1, "m4: /tmp open error\n"); ! 629: } ! 630: } ! 631: if (ofnum>=0 && ofnum<=9) ! 632: offp = outfile[ofnum].fp; ! 633: else ! 634: offp = NULL; ! 635: } ! 636: ! 637: mdivnum() ! 638: { ! 639: pushnum((long)ofnum); ! 640: } ! 641: ! 642: mdnl() ! 643: { ! 644: dnlflag = 1; ! 645: } ! 646: ! 647: mdumpdef(pps) ! 648: STRING **pps; ! 649: { ! 650: ENTRY *find(); ! 651: register ENTRY *e; ! 652: register int i, f = 0; ! 653: int hash; ! 654: ! 655: for (i = 1; i <= 9; ++i) ! 656: if (pps[i] != NULL) { ! 657: if (e=find(pps[i])) ! 658: outdef(e); ! 659: f = 1; ! 660: } ! 661: if (!f) ! 662: for (hash = 0; hash < HASHSZ; ++hash) ! 663: for (e = e_root[hash]; e; e = e->e_next) { ! 664: outputc(bqt); ! 665: outputs(e->e_name->s_body); ! 666: outputc(eqt); ! 667: outputc('\t'); ! 668: outdef(e); ! 669: outputc('\n'); ! 670: } ! 671: } ! 672: ! 673: outdef(e) ! 674: ENTRY *e; ! 675: { ! 676: if (e->e_type == MACD) { ! 677: outputc(bqt); ! 678: outputs(e->e_at.e_pstr->s_body); ! 679: outputc(eqt); ! 680: } ! 681: } ! 682: ! 683: merrprint(pps) ! 684: STRING **pps; ! 685: { ! 686: register int i; ! 687: ! 688: for (i=1; i<=9; i++) ! 689: if (pps[i]) ! 690: fprintf(stderr, pps[i]->s_body); ! 691: } ! 692: ! 693: meval(pps) ! 694: STRING **pps; ! 695: { ! 696: long calc(); ! 697: char *s; ! 698: ! 699: if (pps[1] == NULL) ! 700: pushnum((long)0); ! 701: else { ! 702: s = pps[1]->s_body; ! 703: pushnum(calc(0, &s)); ! 704: } ! 705: } ! 706: ! 707: long ! 708: calc(pr, ps) ! 709: int pr; ! 710: char **ps; ! 711: { ! 712: register struct opdata *opptr; ! 713: register char c; ! 714: char *s; ! 715: long val1, val2, l; ! 716: int oplength; ! 717: ! 718: for (s = *ps; isspace(*s); ++s) ! 719: ; ! 720: if (isdigit(c=*s++)) ! 721: for (val1 = c - '0'; isdigit(c = *s); ++s) ! 722: val1 = 10 * val1 + c - '0'; ! 723: else switch (c) { ! 724: case '+': ! 725: val1 = calc(SI, &s); ! 726: break; ! 727: case '-': ! 728: val1 =-calc(SI, &s); ! 729: break; ! 730: case '!': ! 731: val1 =!calc(NT, &s); ! 732: break; ! 733: case '(': ! 734: val1 = calc(LP, &s); ! 735: break; ! 736: default: ! 737: if (c == '\0') ! 738: errorp(0, "eval: missing value"); ! 739: else ! 740: errorp(0, "eval: invalid expression"); ! 741: s = NULL; ! 742: } ! 743: if ((*ps = s) == NULL) ! 744: return (0); ! 745: for (;;) { ! 746: while (s!=NULL && isspace(c = *s)) ! 747: ++s; ! 748: oplength = 1; ! 749: for (opptr = optable; s != NULL; ++opptr) ! 750: if (c != opptr->keychar) { ! 751: if (opptr->keychar == '\0') ! 752: s = NULL; ! 753: } else if (opptr->secchar=='\0') { ! 754: break; ! 755: } else if (opptr->secchar == *(s+1)) { ! 756: ++oplength; ! 757: break; ! 758: } ! 759: if ((*ps = s) == NULL) { ! 760: errorp(0, "eval: missing or unknown operator"); ! 761: return (0); ! 762: } ! 763: if (opptr->prec <= pr) ! 764: return (val1); ! 765: *ps = s += oplength; ! 766: if (c == ')') ! 767: return (val1); ! 768: val2 = calc(opptr->prec, &s); ! 769: if ((*ps = s) == NULL) ! 770: return (0); ! 771: switch (opptr->optype) { ! 772: case EX: ! 773: if (val2 < 0) ! 774: val1 = 0; ! 775: else { ! 776: for (l = 1; val2; --val2) ! 777: l *= val1; ! 778: val1 = l; ! 779: } ! 780: break; ! 781: case MY: ! 782: val1 *= val2; ! 783: break; ! 784: case DV: ! 785: val1 /= val2; ! 786: break; ! 787: case MD: ! 788: val1 %= val2; ! 789: break; ! 790: case AD: ! 791: val1 += val2; ! 792: break; ! 793: case SB: ! 794: val1 -= val2; ! 795: break; ! 796: case EQ: ! 797: val1 = (val1 == val2); ! 798: break; ! 799: case NE: ! 800: val1 = (val1 != val2); ! 801: break; ! 802: case GE: ! 803: val1 = (val1 >= val2); ! 804: break; ! 805: case LE: ! 806: val1 = (val1 <= val2); ! 807: break; ! 808: case GT: ! 809: val1 = (val1 > val2); ! 810: break; ! 811: case LT: ! 812: val1 = (val1 < val2); ! 813: break; ! 814: case AN: ! 815: val1 = (val1 && val2); ! 816: break; ! 817: case OR: ! 818: val1 = (val1 || val2); ! 819: break; ! 820: } ! 821: } ! 822: } ! 823: ! 824: mifdef(pps) ! 825: STRING **pps; ! 826: { ! 827: ENTRY *find(); ! 828: ! 829: if (pps[1] && find(pps[1])) { ! 830: pushstr(pps[2]); ! 831: } else ! 832: pushstr(pps[3]); ! 833: } ! 834: ! 835: mifelse(pps) ! 836: STRING **pps; ! 837: { ! 838: if (cmpstr(pps[1], pps[2])) ! 839: pushstr(pps[3]); ! 840: else if (moreargs(pps, 5)) ! 841: if (cmpstr(pps[4], pps[5])) ! 842: pushstr(pps[6]); ! 843: else if (moreargs(pps, 8)) ! 844: if (cmpstr(pps[7], pps[8])) ! 845: pushstr(pps[9]); ! 846: else ! 847: return; ! 848: else ! 849: pushstr(pps[7]); ! 850: else ! 851: pushstr(pps[4]); ! 852: } ! 853: ! 854: moreargs(pps, n) ! 855: STRING **pps; ! 856: register int n; ! 857: { ! 858: register int i; ! 859: ! 860: for (i=n; i<=9; i++) ! 861: if (pps[i] != NULL) ! 862: return (1); ! 863: return (0); ! 864: } ! 865: ! 866: minclude(pps) ! 867: STRING **pps; ! 868: { ! 869: if (msinclude(pps)) ! 870: return; ! 871: errorp(1, "cannot open %s", pps[1]!=NULL? pps[1]->s_body : NULL); ! 872: } ! 873: ! 874: mincr(pps) ! 875: STRING **pps; ! 876: { ! 877: long atol(); ! 878: ! 879: pushnum((long)((pps[1] != NULL)? atol(pps[1]->s_body)+1 : 1)); ! 880: } ! 881: ! 882: mdecr(pps) ! 883: STRING **pps; ! 884: { ! 885: long atol(); ! 886: ! 887: pushnum((long)((pps[1] != NULL)? atol(pps[1]->s_body)-1 : -1)); ! 888: } ! 889: ! 890: mindex(pps) ! 891: STRING **pps; ! 892: { ! 893: register char *pc, *pf; ! 894: register int ln; ! 895: long v; ! 896: char *index(); ! 897: ! 898: if (pps[2] == NULL) ! 899: v = 0; ! 900: else if (pps[1] == NULL) ! 901: v = -1; ! 902: else { ! 903: pc = pps[1]->s_body; ! 904: ln = strlen(pf = pps[2]->s_body); ! 905: while ((pc=index(pc, *pf))!=NULL && strncmp(pc, pf, ln)) ! 906: ++pc; ! 907: v = (pc != NULL)? (long)(pc-pps[1]->s_body) : -1; ! 908: } ! 909: pushnum(v); ! 910: } ! 911: ! 912: mlen(pps) ! 913: STRING **pps; ! 914: { ! 915: pushnum((long)((pps[1] != NULL)? pps[1]->s_next-pps[1]->s_body : 0)); ! 916: } ! 917: ! 918: mmaketemp(pps) ! 919: STRING **pps; ! 920: { ! 921: register char *pc; ! 922: if (pps[1]==NULL || strlen(pc = pps[1]->s_body)<TMPMIN) ! 923: return; ! 924: mktemp(pc); ! 925: pushstr(pps[1]); ! 926: } ! 927: ! 928: msinclude(pps) ! 929: STRING **pps; ! 930: { ! 931: return (pushfile((pps[1] != NULL)? pps[1]->s_body : NULL)); ! 932: } ! 933: ! 934: msubstr(pps) ! 935: STRING **pps; ! 936: { ! 937: register char *pc, *pb, *pe; ! 938: int len, n, s; ! 939: STRING *a; ! 940: ! 941: if (pps[1] == NULL) ! 942: return; ! 943: len = strlen(pc = pps[1]->s_body); ! 944: if (pps[2] == NULL) { ! 945: n = (pps[3] != NULL)? atoi(pps[3]->s_body) : len; ! 946: s = (n>0)? 0 : -1; ! 947: } else { ! 948: s = atoi(pps[2]->s_body); ! 949: n = (pps[3] != NULL)? atoi(pps[3]->s_body) : (s>0)? len : -len; ! 950: } ! 951: if (n == 0) ! 952: return; ! 953: pe = pc + len; ! 954: if (s < 0) ! 955: s += len; ! 956: if (n < 0) { ! 957: s += n + 1; ! 958: n = -n; ! 959: } ! 960: a = makestr(); ! 961: for (pb = pc + s; n--; ++pb) ! 962: if (pb>=pc && pb<=pe) ! 963: appendstr(a, *pb); ! 964: pushstr(a); ! 965: decstr(a); ! 966: } ! 967: ! 968: msyscmd(pps) ! 969: STRING **pps; ! 970: { ! 971: if (pps[1]) ! 972: system(pps[1]->s_body); ! 973: } ! 974: ! 975: mtranslit(pps) ! 976: STRING **pps; ! 977: { ! 978: register char *pc, *pt, *pr; ! 979: char c = '\0'; ! 980: STRING *a; ! 981: ! 982: if (pps[1]==NULL || pps[2]==NULL) ! 983: return; ! 984: a = makestr(); ! 985: pc = pps[1]->s_body; ! 986: do { ! 987: pt = pps[2]->s_body; ! 988: pr = (pps[3] != NULL)? pps[3]->s_body : &c; ! 989: do { ! 990: if (*pc == *pt) ! 991: break; ! 992: ! 993: if (*pr) ! 994: ++pr; ! 995: } while (*++pt); ! 996: if (*pt) { ! 997: if (*pr) ! 998: appendstr(a, *pr); ! 999: } else ! 1000: appendstr(a, *pc); ! 1001: } while (*++pc); ! 1002: pushstr(a); ! 1003: decstr(a); ! 1004: } ! 1005: ! 1006: mundefine(pps) ! 1007: STRING **pps; ! 1008: { ! 1009: register ENTRY *e, *ep = NULL; ! 1010: register int hash; ! 1011: ! 1012: if (pps[1] == NULL) ! 1013: return; ! 1014: hash = pps[1]->s_hash; ! 1015: for (e = e_root[hash % HASHSZ]; e != NULL; e = e->e_next) ! 1016: if (e->e_name->s_hash == hash ! 1017: && strcmp(e->e_name->s_body, pps[1]->s_body) == 0) ! 1018: break; ! 1019: else ! 1020: ep = e; ! 1021: if (e == NULL) ! 1022: return; ! 1023: if (e->e_type == MACD) ! 1024: decstr(e->e_at.e_pstr); ! 1025: decstr(e->e_name); ! 1026: if (ep != NULL) ! 1027: ep->e_next = e->e_next; ! 1028: else ! 1029: e_root[hash % HASHSZ] = e->e_next; ! 1030: free(e); ! 1031: } ! 1032: ! 1033: mundivert(pps) ! 1034: STRING **pps; ! 1035: { ! 1036: register i, f = 0; ! 1037: ! 1038: if (pps) ! 1039: for (i = 1; i <= 9; i++) ! 1040: if (pps[i]) { ! 1041: undiv(atoi(pps[i]->s_body)); ! 1042: f = 1; ! 1043: } ! 1044: if (pps==NULL || f==0) ! 1045: for (i = 1; i <= 9; i++) ! 1046: undiv(i); ! 1047: } ! 1048: ! 1049: undiv(n) ! 1050: register int n; ! 1051: { ! 1052: register int c; ! 1053: register FILE *fp; ! 1054: ! 1055: if (n>0 && n<=9 && (fp=outfile[n].fp) != NULL && ofnum!=n) { ! 1056: fclose(fp); ! 1057: if ((fp=fopen(outfile[n].name, "r")) == NULL) ! 1058: errorp(1, "cannot open %s", outfile[n].name); ! 1059: while ((c=getc(fp)) != EOF) ! 1060: outc(c); ! 1061: fclose(fp); ! 1062: unlink(outfile[n].name); ! 1063: free(outfile[n].name); ! 1064: outfile[n].name = outfile[n].fp = NULL; ! 1065: } ! 1066: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.