|
|
1.1 ! root 1: #include "stdio.h" ! 2: #include "signal.h" ! 3: #include "m4.h" ! 4: ! 5: #define match(c,s) (c==*s && (!s[1] || inpmatch(s+1))) ! 6: ! 7: char *xcalloc(), *mktemp(); ! 8: ! 9: ! 10: main(argc,argv) ! 11: char **argv; ! 12: { ! 13: register t; ! 14: ! 15: #ifdef gcos ! 16: tempname = "m4.tempa"; ! 17: #endif ! 18: ! 19: #ifdef unix ! 20: { ! 21: static sigs[] = {SIGHUP, SIGINT, SIGPIPE, 0}; ! 22: for (t=0; sigs[t]; ++t) ! 23: if (signal(sigs[t], SIG_IGN) != SIG_IGN) ! 24: signal(sigs[t],catchsig); ! 25: } ! 26: ! 27: tempname = mktemp("/tmp/m4aXXXXX"); ! 28: close(creat(tempname,0)); ! 29: #endif ! 30: ! 31: procnam = argv[0]; ! 32: getflags(&argc,&argv); ! 33: initalloc(); ! 34: ! 35: setfname("-"); ! 36: if (argc>1) { ! 37: --argc; ! 38: ++argv; ! 39: if (strcmp(argv[0],"-")) { ! 40: ifile[ifx] = xfopen(argv[0],"r"); ! 41: setfname(argv[0]); ! 42: } ! 43: } ! 44: ! 45: for (;;) { ! 46: token[0] = t = getchr(); ! 47: token[1] = EOS; ! 48: ! 49: if (t==EOF) { ! 50: if (ifx > 0) { ! 51: fclose(ifile[ifx]); ! 52: ipflr = ipstk[--ifx]; ! 53: continue; ! 54: } ! 55: ! 56: getflags(&argc,&argv); ! 57: ! 58: if (argc<=1) ! 59: if (Wrapstr) { ! 60: pbstr(Wrapstr); ! 61: Wrapstr = NULL; ! 62: continue; ! 63: } else ! 64: break; ! 65: ! 66: --argc; ! 67: ++argv; ! 68: ! 69: if (ifile[ifx]!=stdin) ! 70: fclose(ifile[ifx]); ! 71: ! 72: if (*argv[0]=='-') ! 73: ifile[ifx] = stdin; ! 74: else ! 75: ifile[ifx] = xfopen(argv[0],"r"); ! 76: ! 77: setfname(argv[0]); ! 78: continue; ! 79: } ! 80: ! 81: if (isalpha(t)) { ! 82: register char *tp = token+1; ! 83: register tlim = toksize; ! 84: ! 85: while (alphanum(*tp++=getchr())) ! 86: if (--tlim<=0) ! 87: error2("more than %d chars in word", ! 88: toksize); ! 89: ! 90: putbak(*--tp); ! 91: *tp = EOS; ! 92: ! 93: if (((struct nlist *)(*Ap=lookup(token)))->def) { ! 94: if (++Ap >= astklm) { ! 95: --Ap; ! 96: error2(astkof,stksize); ! 97: } ! 98: ! 99: if (Cp++==NULL) ! 100: Cp = callst; ! 101: ! 102: Cp->argp = Ap; ! 103: *Ap++ = op; ! 104: puttok(token); ! 105: stkchr(EOS); ! 106: t = getchr(); ! 107: putbak(t); ! 108: ! 109: if (t!='(') ! 110: pbstr("()"); ! 111: else /* try to fix arg count */ ! 112: *Ap++ = op; ! 113: ! 114: Cp->plev = 0; ! 115: } else { ! 116: puttok(token); ! 117: } ! 118: } else if (match(t,lquote)) { ! 119: register qlev = 1; ! 120: ! 121: for (;;) { ! 122: token[0] = t = getchr(); ! 123: token[1] = EOS; ! 124: ! 125: if (match(t,rquote)) { ! 126: if (--qlev > 0) ! 127: puttok(token); ! 128: else ! 129: break; ! 130: } else if (match(t,lquote)) { ! 131: ++qlev; ! 132: puttok(token); ! 133: } else { ! 134: if (t==EOF) ! 135: error("EOF in quote"); ! 136: ! 137: putchr(t); ! 138: } ! 139: } ! 140: } else if (match(t,lcom)) { ! 141: puttok(token); ! 142: ! 143: for (;;) { ! 144: token[0] = t = getchr(); ! 145: token[1] = EOS; ! 146: ! 147: if (match(t,rcom)) { ! 148: puttok(token); ! 149: break; ! 150: } else { ! 151: if (t==EOF) ! 152: error("EOF in comment"); ! 153: putchr(t); ! 154: } ! 155: } ! 156: } else if (Cp==NULL) { ! 157: putchr(t); ! 158: } else if (t=='(') { ! 159: if (Cp->plev) ! 160: stkchr(t); ! 161: else { ! 162: /* skip white before arg */ ! 163: while (isspace(t=getchr())) ! 164: ; ! 165: ! 166: putbak(t); ! 167: } ! 168: ! 169: ++Cp->plev; ! 170: } else if (t==')') { ! 171: --Cp->plev; ! 172: ! 173: if (Cp->plev==0) { ! 174: stkchr(EOS); ! 175: expand(Cp->argp,Ap-Cp->argp-1); ! 176: op = *Cp->argp; ! 177: Ap = Cp->argp-1; ! 178: ! 179: if (--Cp < callst) ! 180: Cp = NULL; ! 181: } else ! 182: stkchr(t); ! 183: } else if (t==',' && Cp->plev<=1) { ! 184: stkchr(EOS); ! 185: *Ap = op; ! 186: ! 187: if (++Ap >= astklm) { ! 188: --Ap; ! 189: error2(astkof,stksize); ! 190: } ! 191: ! 192: while (isspace(t=getchr())) ! 193: ; ! 194: ! 195: putbak(t); ! 196: } else ! 197: stkchr(t); ! 198: } ! 199: ! 200: if (Cp!=NULL) ! 201: error("EOF in argument list"); ! 202: ! 203: delexit(OK); ! 204: } ! 205: ! 206: inpmatch(s) ! 207: register char *s; ! 208: { ! 209: register char *tp = token+1; ! 210: ! 211: while (*s) { ! 212: *tp = getchr(); ! 213: ! 214: if (*tp++ != *s++) { ! 215: *tp = EOS; ! 216: pbstr(token+1); ! 217: return 0; ! 218: } ! 219: } ! 220: ! 221: *tp = EOS; ! 222: return token; ! 223: } ! 224: ! 225: getflags(xargc,xargv) ! 226: register int *xargc; ! 227: register char ***xargv; ! 228: { ! 229: while (*xargc > 1) { ! 230: register char *arg = (*xargv)[1]; ! 231: ! 232: if (arg[0]!='-' || arg[1]==EOS) ! 233: break; ! 234: ! 235: switch (arg[1]) { ! 236: case 'B': ! 237: bufsize = atoi(&arg[2]); ! 238: break; ! 239: case 'D': ! 240: { ! 241: register char *t; ! 242: char *s[2]; ! 243: ! 244: initalloc(); ! 245: ! 246: for (t = s[0] = &arg[2]; *t; t++) ! 247: if (*t=='=') { ! 248: *t++ = EOS; ! 249: break; ! 250: } ! 251: ! 252: s[1] = t; ! 253: dodef(&s[-1],2); ! 254: break; ! 255: } ! 256: case 'H': ! 257: hshsize = atoi(&arg[2]); ! 258: break; ! 259: case 'S': ! 260: stksize = atoi(&arg[2]); ! 261: break; ! 262: case 'T': ! 263: toksize = atoi(&arg[2]); ! 264: break; ! 265: case 'U': ! 266: { ! 267: char *s[1]; ! 268: ! 269: initalloc(); ! 270: s[0] = &arg[2]; ! 271: doundef(&s[-1],1); ! 272: break; ! 273: } ! 274: case 'e': ! 275: #ifdef unix ! 276: setbuf(stdout,NULL); ! 277: signal(SIGINT,SIG_IGN); ! 278: #endif ! 279: break; ! 280: case 's': ! 281: /* turn on line sync */ ! 282: sflag = 1; ! 283: break; ! 284: default: ! 285: fprintf(stderr,"%s: bad option: %s\n", ! 286: procnam,arg); ! 287: delexit(NOT_OK); ! 288: } ! 289: ! 290: (*xargv)++; ! 291: --(*xargc); ! 292: } ! 293: ! 294: return; ! 295: } ! 296: ! 297: initalloc() ! 298: { ! 299: static done = 0; ! 300: register t; ! 301: ! 302: if (done++) ! 303: return; ! 304: ! 305: hshtab = (struct nlist **)xcalloc(hshsize,sizeof(struct nlist *)); ! 306: callst = (struct call *)xcalloc(stksize/3+1,sizeof(struct call)); ! 307: Ap = argstk = (char **)xcalloc(stksize+3,sizeof(char *)); ! 308: ipstk[0] = ipflr = ip = ibuf = xcalloc(bufsize+1,sizeof(char)); ! 309: op = obuf = xcalloc(bufsize+1,sizeof(char)); ! 310: token = xcalloc(toksize+1,sizeof(char)); ! 311: ! 312: astklm = &argstk[stksize]; ! 313: ibuflm = &ibuf[bufsize]; ! 314: obuflm = &obuf[bufsize]; ! 315: toklm = &token[toksize]; ! 316: ! 317: for (t=0; barray[t].bname; ++t) { ! 318: static char p[2] = {0, EOS}; ! 319: ! 320: p[0] = t|~LOW7; ! 321: install(barray[t].bname,p,NOPUSH); ! 322: } ! 323: ! 324: #ifdef unix ! 325: install("unix",nullstr,NOPUSH); ! 326: #endif ! 327: ! 328: #ifdef gcos ! 329: install("gcos",nullstr,NOPUSH); ! 330: #endif ! 331: } ! 332: ! 333: struct nlist * ! 334: install(nam,val,mode) ! 335: char *nam; ! 336: register char *val; ! 337: { ! 338: register struct nlist *np; ! 339: register char *cp; ! 340: int l; ! 341: ! 342: if (mode==PUSH) ! 343: lookup(nam); /* lookup sets hshval */ ! 344: else ! 345: while (undef(nam)) /* undef calls lookup */ ! 346: ; ! 347: ! 348: np = (struct nlist *)xcalloc(1,sizeof(*np)); ! 349: np->name = copy(nam); ! 350: np->next = hshtab[hshval]; ! 351: hshtab[hshval] = np; ! 352: ! 353: cp = xcalloc((l=strlen(val))+1,sizeof(*val)); ! 354: np->def = cp; ! 355: cp = &cp[l]; ! 356: ! 357: while (*val) ! 358: *--cp = *val++; ! 359: } ! 360: ! 361: struct nlist * ! 362: lookup(str) ! 363: char *str; ! 364: { ! 365: register char *s1, *s2; ! 366: register struct nlist *np; ! 367: static struct nlist nodef; ! 368: ! 369: s1 = str; ! 370: ! 371: for (hshval = 0; *s1; ) ! 372: hshval += *s1++; ! 373: ! 374: hshval %= hshsize; ! 375: ! 376: for (np = hshtab[hshval]; np!=NULL; np = np->next) { ! 377: s1 = str; ! 378: s2 = np->name; ! 379: while (*s1++==*s2) ! 380: if (*s2++==EOS) ! 381: return(np); ! 382: } ! 383: ! 384: return(&nodef); ! 385: } ! 386: ! 387: expand(a1,c) ! 388: char **a1; ! 389: { ! 390: register char *dp; ! 391: register struct nlist *sp; ! 392: ! 393: sp = a1[-1]; ! 394: ! 395: if (sp->tflag || trace) { ! 396: int i; ! 397: ! 398: fprintf(stderr,"Trace(%d): %s",Cp-callst,a1[0]); ! 399: ! 400: if (c > 0) { ! 401: fprintf(stderr,"(%s",chkbltin(a1[1])); ! 402: for (i=2; i<=c; ++i) ! 403: fprintf(stderr,",%s",chkbltin(a1[i])); ! 404: fprintf(stderr,")"); ! 405: } ! 406: ! 407: fprintf(stderr,"\n"); ! 408: } ! 409: ! 410: dp = sp->def; ! 411: ! 412: for (; *dp; ++dp) { ! 413: if (*dp&~LOW7) { ! 414: (*barray[*dp&LOW7].bfunc)(a1,c); ! 415: } else if (dp[1]=='$') { ! 416: if (isdigit(*dp)) { ! 417: register n; ! 418: if ((n = *dp-'0') <= c) ! 419: pbstr(a1[n]); ! 420: ++dp; ! 421: } else if (*dp=='#') { ! 422: pbnum((long) c); ! 423: ++dp; ! 424: } else if (*dp=='*' || *dp=='@') { ! 425: register i = c; ! 426: char **a = a1; ! 427: ! 428: if (i > 0) ! 429: for (;;) { ! 430: if (*dp=='@') ! 431: pbstr(rquote); ! 432: ! 433: pbstr(a[i--]); ! 434: ! 435: if (*dp=='@') ! 436: pbstr(lquote); ! 437: ! 438: if (i <= 0) ! 439: break; ! 440: ! 441: pbstr(","); ! 442: } ! 443: ++dp; ! 444: } else ! 445: putbak(*dp); ! 446: } else ! 447: putbak(*dp); ! 448: } ! 449: } ! 450: ! 451: setfname(s) ! 452: register char *s; ! 453: { ! 454: strcpy(fname[ifx],s); ! 455: fname[ifx+1] = fname[ifx]+strlen(s)+1; ! 456: fline[ifx] = 1; ! 457: nflag = 1; ! 458: lnsync(stdout); ! 459: } ! 460: ! 461: lnsync(iop) ! 462: register FILE *iop; ! 463: { ! 464: static int cline = 0; ! 465: static int cfile = 0; ! 466: ! 467: if (!sflag || iop!=stdout) ! 468: return; ! 469: ! 470: if (nflag || ifx!=cfile) { ! 471: nflag = 0; ! 472: cfile = ifx; ! 473: fprintf(iop,"#line %d \"",cline = fline[ifx]); ! 474: fpath(iop); ! 475: fprintf(iop,"\"\n"); ! 476: } else if (++cline != fline[ifx]) ! 477: fprintf(iop,"#line %d\n",cline = fline[ifx]); ! 478: } ! 479: ! 480: fpath(iop) ! 481: register FILE *iop; ! 482: { ! 483: register i; ! 484: ! 485: fprintf(iop,"%s",fname[0]); ! 486: ! 487: for (i=1; i<=ifx; ++i) ! 488: fprintf(iop,":%s",fname[i]); ! 489: } ! 490: ! 491: catchsig() ! 492: { ! 493: #ifdef unix ! 494: signal(SIGHUP,SIG_IGN); ! 495: signal(SIGINT,SIG_IGN); ! 496: #endif ! 497: ! 498: delexit(NOT_OK); ! 499: } ! 500: ! 501: delexit(code) ! 502: { ! 503: register i; ! 504: ! 505: cf = stdout; ! 506: ! 507: /* if (ofx != 0) { /* quitting in middle of diversion */ ! 508: /* ofx = 0; ! 509: /* code = NOT_OK; ! 510: /* } ! 511: */ ! 512: ofx = 0; /* ensure that everything comes out */ ! 513: for (i=1; i<10; i++) ! 514: undiv(i,code); ! 515: ! 516: tempname[7] = 'a'; ! 517: unlink(tempname); ! 518: ! 519: if (code==OK) ! 520: exit(code); ! 521: ! 522: _exit(code); ! 523: } ! 524: ! 525: puttok(tp) ! 526: register char *tp; ! 527: { ! 528: if (Cp) { ! 529: while (*tp) ! 530: stkchr(*tp++); ! 531: } else if (cf) ! 532: while (*tp) ! 533: sputchr(*tp++,cf); ! 534: } ! 535: ! 536: pbstr(str) ! 537: register char *str; ! 538: { ! 539: register char *p; ! 540: ! 541: p = str; ! 542: ! 543: while (*p++) ! 544: ; ! 545: ! 546: --p; ! 547: ! 548: while (p > str) ! 549: putbak(*--p); ! 550: } ! 551: ! 552: undiv(i,code) ! 553: register i; ! 554: { ! 555: register FILE *fp; ! 556: register c; ! 557: ! 558: if (i<1 || i>9 || i==ofx || !ofile[i]) ! 559: return; ! 560: ! 561: fclose(ofile[i]); ! 562: tempname[7] = 'a'+i; ! 563: ! 564: if (code==OK && cf) { ! 565: fp = xfopen(tempname,"r"); ! 566: ! 567: while ((c=getc(fp)) != EOF) ! 568: sputchr(c,cf); ! 569: ! 570: fclose(fp); ! 571: } ! 572: ! 573: unlink(tempname); ! 574: ofile[i] = NULL; ! 575: } ! 576: ! 577: char *copy(s) ! 578: register char *s; ! 579: { ! 580: register char *p, *s1; ! 581: ! 582: p = s1 = xcalloc(strlen(s)+1,1); ! 583: ! 584: while (*s1++ = *s++) ! 585: ; ! 586: ! 587: return(p); ! 588: } ! 589: ! 590: pbnum(num) ! 591: long num; ! 592: { ! 593: pbnbr(num,10,1); ! 594: } ! 595: ! 596: pbnbr(nbr,base,len) ! 597: long nbr; ! 598: register base, len; ! 599: { ! 600: register neg = 0; ! 601: ! 602: if (base<=0) ! 603: return; ! 604: ! 605: if (nbr<0) { ! 606: neg = 1; ! 607: nbr = -nbr; ! 608: } ! 609: ! 610: while (nbr>0) { ! 611: int i; ! 612: if (base>1) { ! 613: i = nbr%base; ! 614: nbr /= base; ! 615: } else { ! 616: i = 1; ! 617: --nbr; ! 618: } ! 619: putbak(itochr(i)); ! 620: --len; ! 621: } ! 622: ! 623: while (--len >= 0) ! 624: putbak('0'); ! 625: ! 626: if (neg) ! 627: putbak('-'); ! 628: } ! 629: ! 630: itochr(i) ! 631: register i; ! 632: { ! 633: if (i>9) ! 634: return i-10+'A'; ! 635: else ! 636: return i+'0'; ! 637: } ! 638: ! 639: long ctol(str) ! 640: register char *str; ! 641: { ! 642: register sign; ! 643: long num; ! 644: ! 645: while (isspace(*str)) ! 646: ++str; ! 647: num = 0; ! 648: if (*str=='-') { ! 649: sign = -1; ! 650: ++str; ! 651: } ! 652: else ! 653: sign = 1; ! 654: while (isdigit(*str)) ! 655: num = num*10 + *str++ - '0'; ! 656: return(sign * num); ! 657: } ! 658: ! 659: min(a,b) ! 660: { ! 661: if (a>b) ! 662: return(b); ! 663: return(a); ! 664: } ! 665: ! 666: FILE * ! 667: xfopen(name,mode) ! 668: char *name, ! 669: *mode; ! 670: { ! 671: FILE *fp; ! 672: ! 673: if ((fp=fopen(name,mode))==NULL) ! 674: error(badfile); ! 675: ! 676: return fp; ! 677: } ! 678: ! 679: char * ! 680: xcalloc(nbr,size) ! 681: { ! 682: register char *ptr; ! 683: ! 684: if ((ptr=calloc(nbr,size)) == NULL) ! 685: error(nocore); ! 686: ! 687: return ptr; ! 688: } ! 689: ! 690: error(str) ! 691: char *str; ! 692: { ! 693: fprintf(stderr,"\n%s:",procnam); ! 694: fpath(stderr); ! 695: fprintf(stderr,":%d %s\n",fline[ifx],str); ! 696: if (Cp) { ! 697: register struct call *mptr; ! 698: ! 699: /* fix limit */ ! 700: *op = EOS; ! 701: (Cp+1)->argp = Ap+1; ! 702: ! 703: for (mptr=callst; mptr<=Cp; ++mptr) { ! 704: register char **aptr, **lim; ! 705: ! 706: aptr = mptr->argp; ! 707: lim = (mptr+1)->argp-1; ! 708: if (mptr==callst) ! 709: fputs(*aptr,stderr); ! 710: ++aptr; ! 711: fputs("(",stderr); ! 712: if (aptr < lim) ! 713: for (;;) { ! 714: fputs(*aptr++,stderr); ! 715: if (aptr >= lim) ! 716: break; ! 717: fputs(",",stderr); ! 718: } ! 719: } ! 720: while (--mptr >= callst) ! 721: fputs(")",stderr); ! 722: ! 723: fputs("\n",stderr); ! 724: } ! 725: delexit(NOT_OK); ! 726: } ! 727: ! 728: error2(str,num) ! 729: char *str; ! 730: int num; ! 731: { ! 732: char buf[500]; ! 733: ! 734: fprintf(buf,str,num); ! 735: error(buf); ! 736: } ! 737: ! 738: chkbltin(s) ! 739: char *s; ! 740: { ! 741: static char buf[24]; ! 742: ! 743: if (*s&~LOW7) ! 744: return sprintf(buf,"<%s>",barray[*s&LOW7].bname); ! 745: ! 746: return s; ! 747: } ! 748:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.