1 #ifndef lint 2 static char sccsid[] = "@(#)m4.c 1.4 (Berkeley) 07/22/88"; 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[] = "/tmp/m4aXXXXX"; 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 mktemp(tempname); 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 } 921