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