1: #ifndef lint
   2: static char sccsid[] = "@(#)m4.c	1.3 (Berkeley) 8/11/83";
   3: #endif
   4: 
   5: #include <stdio.h>
   6: #include <signal.h>
   7: 
   8: #define ERROR NULL
   9: #define READ    "r"
  10: #define WRITE   "w"
  11: 
  12: #define EOS 0
  13: int lpar    = '(';
  14: #define LPAR    lpar
  15: #define RPAR    ')'
  16: #define COMMA   ','
  17: #define GRAVE   '`'
  18: #define ACUTE   '\''
  19: #define LBRAK   '['
  20: #define RBRAK   ']'
  21: #ifdef  M4
  22: char    lquote  LBRAK;
  23: char    rquote  RBRAK;
  24: #endif
  25: #ifndef M4
  26: char    lquote  = GRAVE;
  27: char    rquote  = ACUTE;
  28: #endif
  29: #define COMMENT '#'
  30: #define ALPH    1
  31: #define DIG 2
  32: 
  33: #define HSHSIZ  199 /* prime */
  34: #define STACKS  50
  35: #define SAVS    4096
  36: #define TOKS    128
  37: 
  38: #define putbak(c)   *ip++ = c;
  39: #define getchr()    (ip>cur_ip?*--ip: getc(infile[infptr]))
  40: #define putchr(c)   if (cp==NULL) {if (curfile)putc(c,curfile);} else *op++ = c
  41: char    type[] = {
  42:     0,  0,  0,  0,  0,  0,  0,  0,
  43:     0,  0,  0,  0,  0,  0,  0,  0,
  44:     0,  0,  0,  0,  0,  0,  0,  0,
  45:     0,  0,  0,  0,  0,  0,  0,  0,
  46:     0,  0,  0,  0,  0,  0,  0,  0,
  47:     0,  0,  0,  0,  0,  0,  0,  0,
  48:     DIG,    DIG,    DIG,    DIG,    DIG,    DIG,    DIG,    DIG,
  49:     DIG,    DIG,    0,  0,  0,  0,  0,  0,
  50:     0,  ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
  51:     ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
  52:     ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
  53:     ALPH,   ALPH,   ALPH,   0,  0,  0,  0,  ALPH,
  54:     0,  ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
  55:     ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
  56:     ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
  57:     ALPH,   ALPH,   ALPH,   0,  0,  0,  0,  0,
  58: };
  59: 
  60: char    token[TOKS];
  61: char    eoa[]   = "\0";
  62: 
  63: #define RESERVED    01  /* This is a reserved word with side action */
  64: struct  nlist {
  65:     char    *name;
  66:     char    *def;
  67:     char    flag;
  68:     struct  nlist *next;
  69: };
  70: 
  71: struct  nlist   *hshtab[HSHSIZ];
  72: char    ibuf[SAVS+TOKS];
  73: char    obuf[SAVS+TOKS];
  74: char    *op = obuf;
  75: char    *ip = ibuf;
  76: char *ip_stk[10] = {ibuf};
  77: char *cur_ip = ibuf;
  78: struct call {
  79:     char    **argp;
  80:     int plev;
  81: };
  82: struct  call    *cp = NULL;
  83: 
  84: char    *makeloc;
  85: char    *ifdefloc;
  86: char    *lenloc;
  87: char    *undefloc;
  88: char    *shiftloc;
  89: char    *cqloc;
  90: char    *defloc;
  91: char    *evaloc;
  92: char    *incrloc;
  93: char    *substrloc;
  94: char    *indexloc;
  95: char    *transloc;
  96: char    *ifloc;
  97: char    *divloc;
  98: char    *divnumloc;
  99: char    *undivloc;
 100: char    *dnlloc;
 101: char    *inclloc;
 102: char    *sinclloc;
 103: char    *syscmdloc;
 104: char    *dumploc;
 105: char    *errploc;
 106: 
 107: char    *tempname;
 108: struct nlist    *lookup();
 109: char    *install();
 110: char    *malloc();
 111: char    *mktemp();
 112: char    *copy();
 113: long    ctol();
 114: int hshval;
 115: FILE    *olist[11] = { stdout };
 116: int okret;
 117: int curout  = 0;
 118: FILE    *curfile = { stdout };
 119: FILE    *infile[10] = { stdin };
 120: int infptr  = 0;
 121: 
 122: main(argc, argv)
 123: char **argv;
 124: {
 125:     char *argstk[STACKS+10];
 126:     struct call callst[STACKS];
 127:     register char *tp, **ap;
 128:     int delexit(), catchsig();
 129:     register t;
 130:     int i;
 131: 
 132: #ifdef gcos
 133: #ifdef M4
 134:     install("GCOS", eoa, 0);
 135: #endif
 136: #ifndef M4
 137:     install("gcos", eoa, 0);
 138: #endif
 139: #endif
 140: #ifdef unix
 141: #ifdef M4
 142:     install("UNIX", eoa, 0);
 143: #endif
 144: #ifndef M4
 145:     install("unix", eoa, 0);
 146: #endif
 147: #endif
 148: 
 149: #ifdef M4
 150:     makeloc = install("MAKETEMP", eoa, RESERVED);
 151:     ifdefloc = install("IFDEF", eoa, RESERVED);
 152:     lenloc = install("LEN", eoa, RESERVED);
 153:     undefloc = install("UNDEFINE", eoa, RESERVED);
 154:     shiftloc = install("SHIFT", eoa, RESERVED);
 155:     cqloc = install("CHANGEQUOTE", eoa, RESERVED);
 156:     defloc = install("DEFINE", eoa, RESERVED);
 157:     evaloc = install("EVAL", eoa, RESERVED);
 158:     inclloc = install("INCLUDE", eoa, RESERVED);
 159:     sinclloc = install("SINCLUDE", eoa, RESERVED);
 160:     syscmdloc = install("SYSCMD", eoa, RESERVED);
 161:     dumploc = install("DUMPDEF", eoa, RESERVED);
 162:     errploc = install("ERRPRINT", eoa, RESERVED);
 163:     incrloc = install("INCR", eoa, RESERVED);
 164:     substrloc = install("SUBSTR", eoa, RESERVED);
 165:     indexloc = install("INDEX", eoa, RESERVED);
 166:     transloc = install("TRANSLIT", eoa, RESERVED);
 167:     ifloc = install("IFELSE", eoa, RESERVED);
 168:     divloc = install("DIVERT", eoa, RESERVED);
 169:     divnumloc = install("DIVNUM", eoa, RESERVED);
 170:     undivloc = install("UNDIVERT", eoa, RESERVED);
 171:     dnlloc = install("DNL", eoa, RESERVED);
 172: #endif
 173: 
 174: #ifndef M4
 175:     makeloc = install("maketemp", eoa, RESERVED);
 176:     ifdefloc = install("ifdef", eoa, RESERVED);
 177:     lenloc = install("len", eoa, RESERVED);
 178:     undefloc = install("undefine", eoa, RESERVED);
 179:     shiftloc = install("shift", eoa, RESERVED);
 180:     cqloc = install("changequote", eoa, RESERVED);
 181:     defloc = install("define", eoa, RESERVED);
 182:     evaloc = install("eval", eoa, RESERVED);
 183:     inclloc = install("include", eoa, RESERVED);
 184:     sinclloc = install("sinclude", eoa, RESERVED);
 185:     syscmdloc = install("syscmd", eoa, RESERVED);
 186:     dumploc = install("dumpdef", eoa, RESERVED);
 187:     errploc = install("errprint", eoa, RESERVED);
 188:     incrloc = install("incr", eoa, RESERVED);
 189:     substrloc = install("substr", eoa, RESERVED);
 190:     indexloc = install("index", eoa, RESERVED);
 191:     transloc = install("translit", eoa, RESERVED);
 192:     ifloc = install("ifelse", eoa, RESERVED);
 193:     divloc = install("divert", eoa, RESERVED);
 194:     divnumloc = install("divnum", eoa, RESERVED);
 195:     undivloc = install("undivert", eoa, RESERVED);
 196:     dnlloc = install("dnl", eoa, RESERVED);
 197: #endif
 198:     ap = argstk;
 199: #ifndef gcos
 200:     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 201:         signal(SIGHUP, catchsig);
 202:     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 203:         signal(SIGINT, catchsig);
 204:     tempname = mktemp("/tmp/m4aXXXXX");
 205:     close(creat(tempname, 0));
 206: #endif
 207: #ifdef gcos
 208:     tempname = "m4.tempa";
 209: #endif
 210:     if (argc>1)
 211:         putbak(0);
 212:     for (;;) {
 213:         tp = token;
 214:         *tp++ = t = getchr();
 215:         *tp = EOS;
 216:         if (t<=0) {
 217:             if (infptr > 0) {
 218:                 fclose(infile[infptr]);
 219:                 infptr--;
 220:                 cur_ip = ip_stk[infptr];
 221:                 continue;
 222:             }
 223:             if (argc<=1)
 224:                 break;
 225:             argc--;
 226:             argv++;
 227:             if (infile[infptr]!=stdin)
 228:                 fclose(infile[infptr]);
 229:             if (**argv=='-')
 230:                 infile[infptr] = stdin;
 231:             else if ((infile[infptr]=fopen(argv[0], READ))==ERROR) {
 232:                 fprintf(stderr, "m4: file not found: %s\n", argv[0]);
 233:                 delexit();
 234:             }
 235:             continue;
 236:         }
 237:         if (type[t]==ALPH) {
 238:             while ((t=type[*tp++=getchr()])==ALPH||t==DIG);
 239:             putbak(*--tp);
 240:             *tp = EOS;
 241:             if (*ap = lookup(token)->def) {
 242:                 if (++ap >= &argstk[STACKS]) {
 243:                     fprintf(stderr, "m4: arg stack overflow\n");
 244:                     delexit();
 245:                 }
 246:                 if (cp==NULL)
 247:                     cp = callst;
 248:                 else if (++cp > &callst[STACKS]) {
 249:                     fprintf(stderr, "m4: call stack overflow\n");
 250:                     delexit();
 251:                 }
 252:                 cp->argp = ap;
 253:                 *ap++ = op;
 254:                 puttok();
 255:                 *op++ = '\0';
 256:                 t = getchr();
 257:                 putbak(t);
 258:                 if (t!=LPAR) {
 259:                     /* if (t!=' ' && t!='\t') */
 260:                         putbak(')');
 261:                     putbak('(');
 262:                 }
 263:                 else    /* try to fix arg count */
 264:                     *ap++ = op;
 265:                 cp->plev = 0;
 266:             } else
 267:                 puttok();
 268:         } else if (t==lquote) {
 269:             i = 1;
 270:             for (;;) {
 271:                 t = getchr();
 272:                 if (t==rquote) {
 273:                     i--;
 274:                     if (i==0)
 275:                         break;
 276:                 } else if (t==lquote)
 277:                     i++;
 278:                 else if (t<0) {
 279:                     fprintf(stderr, "m4: EOF in string\n");
 280:                     delexit();
 281:                 }
 282:                 putchr(t);
 283:             }
 284:         } else if (t==COMMENT) {
 285:             putbak(t);
 286:             while ((t = getchr())!='\n'&& t>=0)
 287:                 if (cp==NULL)
 288:                     putchr(t);
 289:             putbak(t);
 290:         } else if (cp==NULL) {
 291:             puttok();
 292:         } else if (t==LPAR) {
 293:             if (cp->plev)
 294:                 *op++ = t;
 295:             cp->plev++;
 296:             while ( (t=getchr())==' ' || t=='\t' || t=='\n')
 297:                 ;   /* skip leading white space during arg collection */
 298:             putbak(t);
 299: /*
 300: 		} else if (t==' ' || t=='\t' || t=='\n') {
 301: 			continue;
 302: */
 303:         } else if (t==RPAR) {
 304:             cp->plev--;
 305:             if (cp->plev==0) {
 306:                 *op++ = '\0';
 307:                 expand(cp->argp, ap-cp->argp-1);
 308:                 op = *cp->argp;
 309:                 ap = cp->argp-1;
 310:                 cp--;
 311:                 if (cp < callst)
 312:                     cp = NULL;
 313:             } else
 314:                 *op++ = t;
 315:         } else if (t==COMMA && cp->plev<=1) {
 316:             *op++ = '\0';
 317:             *ap++ = op;
 318:             while ((t=getchr())==' ' || t=='\t' || t=='\n')
 319:                 ;   /* skip leading white space during arg collection */
 320:             putbak(t);
 321:         } else
 322:             *op++ = t;
 323:     }
 324:     if (cp!=NULL) {
 325:         fprintf(stderr, "m4: unexpected EOF\n");
 326:         delexit();
 327:     }
 328:     okret = 1;
 329:     delexit();
 330: }
 331: 
 332: catchsig()
 333: {
 334:     okret = 0;
 335:     delexit();
 336: }
 337: 
 338: delexit()
 339: {
 340:     register FILE *fp;
 341:     register i, c;
 342: 
 343:     if (!okret) {
 344:         signal(SIGHUP, SIG_IGN);
 345:         signal(SIGINT, SIG_IGN);
 346:     }
 347:     for (i=1; i<10; i++) {
 348:         if (olist[i]==NULL)
 349:             continue;
 350:         fclose(olist[i]);
 351:         tempname[7] = 'a'+i;
 352:         if (okret) {
 353:             fp = fopen(tempname, READ);
 354:             while ((c = getc(fp)) > 0)
 355:                 putchar(c);
 356:             fclose(fp);
 357:         }
 358:         unlink(tempname);
 359:     }
 360:     tempname[7] = 'a';
 361:     unlink(tempname);
 362:     exit(1-okret);
 363: }
 364: 
 365: puttok()
 366: {
 367:     register char *tp;
 368: 
 369:     tp = token;
 370:     if (cp) {
 371:         if (op >= &obuf[SAVS]) {
 372:             fprintf(stderr, "m4: argument overflow\n");
 373:             delexit();
 374:         }
 375:         while (*tp)
 376:             *op++ = *tp++;
 377:     } else if (curfile)
 378:         while (*tp)
 379:             putc(*tp++, curfile);
 380: }
 381: 
 382: pbstr(str)
 383: register char *str;
 384: {
 385:     register char *p;
 386: 
 387:     p = str;
 388:     while (*p++);
 389:     --p;
 390:     if (ip >= &ibuf[SAVS]) {
 391:         fprintf(stderr, "m4: pushback overflow\n");
 392:         delexit();
 393:     }
 394:     while (p > str)
 395:         putbak(*--p);
 396: }
 397: 
 398: expand(a1, c)
 399: register char **a1;
 400: {
 401:     register char *dp;
 402:     register n;
 403: 
 404:     dp = a1[-1];
 405:     if (dp==defloc)
 406:         dodef(a1, c);
 407:     else if (dp==evaloc)
 408:         doeval(a1, c);
 409:     else if (dp==inclloc)
 410:         doincl(a1, c, 1);
 411:     else if (dp==sinclloc)
 412:         doincl(a1, c, 0);
 413:     else if (dp==makeloc)
 414:         domake(a1, c);
 415:     else if (dp==syscmdloc)
 416:         dosyscmd(a1, c);
 417:     else if (dp==incrloc)
 418:         doincr(a1, c);
 419:     else if (dp==substrloc)
 420:         dosubstr(a1, c);
 421:     else if (dp==indexloc)
 422:         doindex(a1, c);
 423:     else if (dp==transloc)
 424:         dotransl(a1, c);
 425:     else if (dp==ifloc)
 426:         doif(a1, c);
 427:     else if (dp==divloc)
 428:         dodiv(a1, c);
 429:     else if (dp==divnumloc)
 430:         dodivnum(a1, c);
 431:     else if (dp==undivloc)
 432:         doundiv(a1, c);
 433:     else if (dp==dnlloc)
 434:         dodnl(a1, c);
 435:     else if (dp==dumploc)
 436:         dodump(a1, c);
 437:     else if (dp==errploc)
 438:         doerrp(a1, c);
 439:     else if (dp==lenloc)
 440:         dolen(a1, c);
 441:     else if (dp==ifdefloc)
 442:         doifdef(a1, c);
 443:     else if (dp==undefloc)
 444:         doundef(a1, c);
 445:     else if (dp==shiftloc)
 446:         doshift(a1, c);
 447:     else if (dp==cqloc)
 448:         docq(a1, c);
 449:     else {
 450:         while (*dp++);
 451:         for (dp--; dp>a1[-1]; ) {
 452:             if (--dp>a1[-1] && dp[-1]=='$') {
 453:                 n = *dp-'0';
 454:                 if (n>=0 && n<=9) {
 455:                     if (n <= c)
 456:                         pbstr(a1[n]);
 457:                     dp--;
 458:                 } else
 459:                     putbak(*dp);
 460:             } else
 461:                 putbak(*dp);
 462:         }
 463:     }
 464: }
 465: 
 466: struct nlist *lookup(str)
 467: char *str;
 468: {
 469:     register char *s1, *s2;
 470:     register struct nlist *np;
 471:     static struct nlist nodef;
 472: 
 473:     s1 = str;
 474:     for (hshval = 0; *s1; )
 475:         hshval += *s1++;
 476:     hshval %= HSHSIZ;
 477:     for (np = hshtab[hshval]; np!=NULL; np = np->next) {
 478:         s1 = str;
 479:         s2 = np->name;
 480:         while (*s1++ == *s2)
 481:             if (*s2++ == EOS)
 482:                 return(np);
 483:     }
 484:     return(&nodef);
 485: }
 486: 
 487: char *install(nam, val, flag)
 488: char *nam, *val;
 489: char flag;
 490: {
 491:     register struct nlist *np;
 492: 
 493:     if ((np = lookup(nam))->name == NULL) {
 494:         np = (struct nlist *)malloc(sizeof(*np));
 495:         if (np == NULL) {
 496:             fprintf(stderr, "m4: no space for alloc\n");
 497:             exit(1);
 498:         }
 499:         np->name = copy(nam);
 500:         np->def = copy(val);
 501:         np->next = hshtab[hshval];
 502:         np->flag = flag;
 503:         hshtab[hshval] = np;
 504:         return(np->def);
 505:     }
 506:     free(np->def);
 507:     np->flag = flag;
 508:     np->def = copy(val);
 509:     return(np->def);
 510: }
 511: 
 512: doundef(ap, c)
 513: char **ap;
 514: {
 515:     register struct nlist *np, *tnp;
 516: 
 517:     if (c < 1 || (np = lookup(ap[1]))->name == NULL)
 518:         return;
 519:     tnp = hshtab[hshval];   /* lookup sets hshval */
 520:     if (tnp == np)  /* it's in first place */
 521:         hshtab[hshval] = np->next;
 522:     else {
 523:         for ( ; tnp->next != np; tnp = tnp->next)
 524:             ;
 525:         tnp->next = np->next;
 526:     }
 527:     /*
 528: 	 * If this is a reserved word, it has been removed from the
 529: 	 * hastable.  We do not want to actually free the space because
 530: 	 * of the code in expand.  Expand wants to to pointer compairs
 531: 	 * to tell if this is a reserved word (e.g a special action
 532: 	 * needs to take place).  Thus if we do not free the space,
 533: 	 * expand will still work, but the name will never be found
 534: 	 * because it out of the symbol table!
 535: 	 */
 536:     if (np->flag&RESERVED == 0) { /* If not reserved free it */
 537:         free(np->name);
 538:         free(np->def);
 539:         free((char *)np);
 540:     }
 541: }
 542: 
 543: char *copy(s)
 544: register char *s;
 545: {
 546:     register char *p, *s1;
 547: 
 548:     p = s1 = malloc((unsigned)strlen(s)+1);
 549:     if (p == NULL) {
 550:         fprintf(stderr, "m4: no space for alloc\n");
 551:         exit(1);
 552:     }
 553:     while (*s1++ = *s++);
 554:     return(p);
 555: }
 556: 
 557: dodef(ap, c)
 558: char **ap;
 559: {
 560:     if (c >= 2) {
 561:         if (strcmp(ap[1], ap[2]) == 0) {
 562:             fprintf(stderr, "m4: %s defined as itself\n", ap[1]);
 563:             delexit();
 564:         }
 565:         install(ap[1], ap[2], 0);
 566:     }
 567:     else if (c == 1)
 568:         install(ap[1], "", 0);
 569: }
 570: 
 571: doifdef(ap, c)
 572: char **ap;
 573: {
 574:     register struct nlist *np;
 575: 
 576:     if (c < 2)
 577:         return;
 578:     if (lookup(ap[1])->name != NULL)
 579:         pbstr(ap[2]);
 580:     else if (c >= 3)
 581:         pbstr(ap[3]);
 582: }
 583: 
 584: dolen(ap, c)
 585: char **ap;
 586: {
 587:     putnum((long) strlen(ap[1]));
 588: }
 589: 
 590: docq(ap, c)
 591: char **ap;
 592: {
 593:     if (c > 1) {
 594:         lquote = *ap[1];
 595:         rquote = *ap[2];
 596:     } else if (c == 1) {
 597:         lquote = rquote = *ap[1];
 598:     } else {
 599: #ifndef M4
 600:         lquote = GRAVE;
 601:         rquote = ACUTE;
 602: #endif
 603: #ifdef M4
 604:         lquote = LBRAK;
 605:         rquote = RBRAK;
 606: #endif
 607:     }
 608: }
 609: 
 610: doshift(ap, c)
 611: char **ap;
 612: {
 613:     fprintf(stderr, "m4: shift not yet implemented\n");
 614: }
 615: 
 616: dodump(ap, c)
 617: char **ap;
 618: {
 619:     int i;
 620:     register struct nlist *np;
 621: 
 622:     if (c > 0)
 623:         while (c--) {
 624:             if ((np = lookup(*++ap))->name != NULL)
 625:                 fprintf(stderr, "`%s'	`%s'\n", np->name, np->def);
 626:         }
 627:     else
 628:         for (i=0; i<HSHSIZ; i++)
 629:             for (np=hshtab[i]; np!=NULL; np=np->next)
 630:                 fprintf(stderr, "`%s'	`%s'\n", np->name, np->def);
 631: }
 632: 
 633: doerrp(ap, c)
 634: char **ap;
 635: {
 636:     if (c > 0) {
 637:         fprintf(stderr, ap[1], ap[2], ap[3], ap[4], ap[5], ap[6]);
 638:         fprintf(stderr, "\n");
 639:     }
 640: }
 641: 
 642: 
 643: long    evalval;    /* return value from yacc stuff */
 644: char    *pe;    /* used by grammar */
 645: 
 646: doeval(ap, c)
 647: char **ap;
 648: {
 649: 
 650:     if (c > 0) {
 651:         pe = ap[1];
 652:         if (yyparse() == 0)
 653:             putnum(evalval);
 654:         else
 655:             fprintf(stderr, "m4: invalid expression in eval: %s\n", ap[1]);
 656:     }
 657: }
 658: 
 659: doincl(ap, c, noisy)
 660: char **ap;
 661: {
 662:     if (c > 0 && strlen(ap[1]) > 0) {
 663:         infptr++;
 664:         ip_stk[infptr] = cur_ip = ip;
 665:         if ((infile[infptr] = fopen(ap[1], READ))==ERROR) {
 666:             if (noisy) {
 667:                 fprintf(stderr, "m4: file not found: %s\n", ap[1]);
 668:                 delexit();
 669:             }
 670:             else
 671:                 infptr--;
 672:         }
 673:     }
 674: }
 675: 
 676: dosyscmd(ap, c)
 677: char **ap;
 678: {
 679:     if (c > 0)
 680:         system(ap[1]);
 681: }
 682: 
 683: domake(ap, c)
 684: char **ap;
 685: {
 686:     if (c > 0)
 687:         pbstr(mktemp(ap[1]));
 688: }
 689: 
 690: doincr(ap, c)
 691: char **ap;
 692: {
 693:     if (c >= 1)
 694:         putnum(ctol(ap[1])+1);
 695: }
 696: 
 697: putnum(num)
 698: long num;
 699: {
 700:     register sign;
 701: 
 702:     sign = (num < 0) ? '-' : '\0';
 703:     if (num < 0)
 704:         num = -num;
 705:     do {
 706:         putbak(num%10+'0');
 707:         num = num/10;
 708:     } while (num!=0);
 709:     if (sign == '-')
 710:         putbak('-');
 711: }
 712: 
 713: dosubstr(ap, c)
 714: char **ap;
 715: {
 716:     int nc;
 717:     register char *sp, *fc;
 718: 
 719:     if (c<2)
 720:         return;
 721:     if (c<3)
 722:         nc = TOKS;
 723:     else
 724:         nc = ctoi(ap[3]);
 725:     fc = ap[1] + max(0, min(ctoi(ap[2]), strlen(ap[1])));
 726:     sp = fc + min(nc, strlen(fc));
 727:     while (sp > fc)
 728:         putbak(*--sp);
 729: }
 730: 
 731: doindex(ap, c)
 732: char **ap;
 733: {
 734:     if (c >= 2)
 735:         putnum((long) strindex(ap[1], ap[2]));
 736: }
 737: 
 738: strindex(p1, p2)
 739: char *p1, *p2;
 740: {
 741:     register m;
 742:     register char *s, *t, *p;
 743: 
 744:     for (p=p1; *p; p++) {
 745:         s = p;
 746:         m = 1;
 747:         for (t=p2; *t; )
 748:             if (*t++ != *s++)
 749:                 m = 0;
 750:         if (m == 1)
 751:             return(p-p1);
 752:     }
 753:     return(-1);
 754: }
 755: 
 756: dotransl(ap, c)
 757: char **ap;
 758: {
 759:     register char *s, *fr, *to;
 760: 
 761:     if (c <= 1) return;
 762: 
 763:     if (c == 2) {
 764:         register int i;
 765:         to = ap[1];
 766:         for (s = ap[1]; *s; s++) {
 767:             i = 0;
 768:             for (fr = ap[2]; *fr; fr++)
 769:                 if (*s == *fr) {
 770:                     i++;
 771:                     break;
 772:                 }
 773:             if (i == 0)
 774:                 *to++ = *s;
 775:         }
 776:         *to = '\0';
 777:     }
 778: 
 779:     if (c >= 3) {
 780:         for (s = ap[1]; *s; s++)
 781:             for (fr = ap[2], to = ap[3]; *fr && *to; fr++, to++)
 782:                 if (*s == *fr)
 783:                     *s = *to;
 784:     }
 785: 
 786:     pbstr(ap[1]);
 787: }
 788: 
 789: doif(ap, c)
 790: register char **ap;
 791: {
 792:     if (c < 3)
 793:         return;
 794:     while (c >= 3) {
 795:         if (strcmp(ap[1], ap[2]) == 0) {
 796:             pbstr(ap[3]);
 797:             return;
 798:         }
 799:         c -= 3;
 800:         ap += 3;
 801:     }
 802:     if (c > 0)
 803:         pbstr(ap[1]);
 804: }
 805: 
 806: dodiv(ap, c)
 807: register char **ap;
 808: {
 809:     register int f;
 810: 
 811:     if (c<1)
 812:         f = 0;
 813:     else
 814:         f = ctoi(ap[1]);
 815:     if (f>=10 || f<0) {
 816:         curfile = NULL;
 817:         return;
 818:     }
 819:     tempname[7] = 'a' + f;
 820:     if (olist[f] || (olist[f]=fopen(tempname, WRITE))) {
 821:         curout = f;
 822:         curfile = olist[f];
 823:     }
 824: }
 825: 
 826: doundiv(ap, c)
 827: char **ap;
 828: {
 829:     register FILE *fp;
 830:     register int i, ch;
 831:     int j;
 832: 
 833:     if (c == 0) {
 834:         for (i=1; i<10; i++) {
 835:             if (i==curout || olist[i]==NULL)
 836:                 continue;
 837:             fclose(olist[i]);
 838:             tempname[7] = 'a'+i;
 839:             fp = fopen(tempname, READ);
 840:             if (curfile != NULL)
 841:                 while ((ch = getc(fp)) > 0)
 842:                     putc(ch, curfile);
 843:             fclose(fp);
 844:             unlink(tempname);
 845:             olist[i] = NULL;
 846:         }
 847: 
 848:     }
 849:     else {
 850:         for (j = 1; j <= c; j++) {
 851:             i = ctoi(*++ap);
 852:             if (i<1 || i>9 || i==curout || olist[i]==NULL)
 853:                 continue;
 854:             fclose(olist[i]);
 855:             tempname[7] = 'a'+i;
 856:             fp = fopen(tempname, READ);
 857:             if (curfile != NULL)
 858:                 while ((ch = getc(fp)) > 0)
 859:                     putc(ch, curfile);
 860:             fclose(fp);
 861:             unlink(tempname);
 862:             olist[i] = NULL;
 863:         }
 864:     }
 865: }
 866: 
 867: dodivnum(ap, c)
 868: char **ap;
 869: {
 870:     putnum((long) curout);
 871: }
 872: 
 873: dodnl(ap, c)
 874: char **ap;
 875: {
 876:     register t;
 877: 
 878:     while ((t=getchr())!='\n' && t>=0)
 879:         ;
 880: }
 881: 
 882: long ctol(str)
 883: register char *str;
 884: {
 885:     register sign;
 886:     long num;
 887: 
 888:     while (*str==' ' || *str=='\t' || *str=='\n')
 889:         str++;
 890:     num = 0;
 891:     if (*str == '-') {
 892:         sign = -1;
 893:         str++;
 894:     }
 895:     else
 896:         sign = 1;
 897:     while (*str>='0' && *str<='9')
 898:         num = num*10 + *str++ - '0';
 899:     return(sign * num);
 900: }
 901: 
 902: ctoi(s)
 903: char *s;
 904: {
 905:     return(ctol(s));
 906: }
 907: 
 908: min(a, b)
 909: {
 910:     if (a>b)
 911:         return(b);
 912:     return(a);
 913: }
 914: 
 915: max(a, b)
 916: {
 917:     if (a>b)
 918:         return(a);
 919:     return(b);
 920: }

Defined functions

catchsig defined in line 332; used 3 times
copy defined in line 543; used 4 times
ctoi defined in line 902; used 4 times
ctol defined in line 882; used 3 times
delexit defined in line 338; used 12 times
docq defined in line 590; used 1 times
dodef defined in line 557; used 1 times
dodiv defined in line 806; used 1 times
dodivnum defined in line 867; used 1 times
dodnl defined in line 873; used 1 times
dodump defined in line 616; used 1 times
doerrp defined in line 633; used 1 times
doeval defined in line 646; used 1 times
doif defined in line 789; used 1 times
doifdef defined in line 571; used 1 times
doincl defined in line 659; used 2 times
doincr defined in line 690; used 1 times
doindex defined in line 731; used 1 times
dolen defined in line 584; used 1 times
domake defined in line 683; used 1 times
doshift defined in line 610; used 1 times
dosubstr defined in line 713; used 1 times
dosyscmd defined in line 676; used 1 times
dotransl defined in line 756; used 1 times
doundef defined in line 512; used 1 times
doundiv defined in line 826; used 1 times
expand defined in line 398; used 1 times
install defined in line 487; used 51 times
lookup defined in line 466; used 6 times
main defined in line 122; never used
max defined in line 915; used 1 times
min defined in line 908; used 2 times
pbstr defined in line 382; used 7 times
putnum defined in line 697; used 5 times
puttok defined in line 365; used 3 times
strindex defined in line 738; used 1 times

Defined variables

LBRAK defined in line 22; never used
RBRAK defined in line 23; never used
cp defined in line 82; used 22 times
cqloc defined in line 89; used 3 times
cur_ip defined in line 77; used 3 times
curout defined in line 117; used 4 times
defloc defined in line 90; used 3 times
divloc defined in line 97; used 3 times
divnumloc defined in line 98; used 3 times
dnlloc defined in line 100; used 3 times
dumploc defined in line 104; used 3 times
eoa defined in line 61; used 48 times
errploc defined in line 105; used 3 times
evaloc defined in line 91; used 3 times
evalval defined in line 643; used 1 times
hshtab defined in line 71; used 6 times
hshval defined in line 114; used 8 times
ibuf defined in line 72; used 4 times
ifdefloc defined in line 85; used 3 times
ifloc defined in line 96; used 3 times
inclloc defined in line 101; used 3 times
incrloc defined in line 92; used 3 times
indexloc defined in line 94; used 3 times
infptr defined in line 120; used 13 times
ip defined in line 75; used 5 times
ip_stk defined in line 76; used 2 times
lenloc defined in line 86; used 3 times
lpar defined in line 13; used 1 times
  • in line 14
lquote defined in line 26; used 6 times
makeloc defined in line 84; used 3 times
obuf defined in line 73; used 2 times
okret defined in line 116; used 5 times
op defined in line 74; used 13 times
pe defined in line 644; used 1 times
rquote defined in line 27; used 5 times
sccsid defined in line 2; never used
shiftloc defined in line 88; used 3 times
sinclloc defined in line 102; used 3 times
substrloc defined in line 93; used 3 times
syscmdloc defined in line 103; used 3 times
tempname defined in line 107; used 16 times
token defined in line 60; used 3 times
transloc defined in line 95; used 3 times
type defined in line 41; used 2 times
undefloc defined in line 87; used 3 times
undivloc defined in line 99; used 3 times

Defined struct's

call defined in line 78; used 4 times
nlist defined in line 64; used 22 times

Defined macros

ACUTE defined in line 18; used 2 times
ALPH defined in line 30; used 55 times
COMMA defined in line 16; used 1 times
COMMENT defined in line 29; used 1 times
DIG defined in line 31; used 11 times
EOS defined in line 12; used 3 times
ERROR defined in line 8; used 2 times
GRAVE defined in line 17; used 2 times
HSHSIZ defined in line 33; used 3 times
LBRAK defined in line 19; used 1 times
LPAR defined in line 14; used 2 times
RBRAK defined in line 20; used 1 times
READ defined in line 9; used 5 times
RESERVED defined in line 63; used 45 times
RPAR defined in line 15; used 1 times
SAVS defined in line 35; used 4 times
STACKS defined in line 34; used 4 times
TOKS defined in line 36; used 4 times
WRITE defined in line 10; used 1 times
getchr defined in line 39; used 8 times
putbak defined in line 38; used 15 times
putchr defined in line 40; used 2 times
Last modified: 1983-08-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4751
Valid CSS Valid XHTML 1.0 Strict