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