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