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
main(argc,argv)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
catchsig()333 catchsig()
334 {
335 okret = 0;
336 delexit();
337 }
338
delexit()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
puttok()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
pbstr(str)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
expand(a1,c)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
lookup(str)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
install(nam,val,flag)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
doundef(ap,c)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
copy(s)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
dodef(ap,c)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
doifdef(ap,c)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
dolen(ap,c)585 dolen(ap, c)
586 char **ap;
587 {
588 putnum((long) strlen(ap[1]));
589 }
590
docq(ap,c)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
doshift(ap,c)611 doshift(ap, c)
612 char **ap;
613 {
614 fprintf(stderr, "m4: shift not yet implemented\n");
615 }
616
dodump(ap,c)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
doerrp(ap,c)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
doeval(ap,c)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
doincl(ap,c,noisy)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
dosyscmd(ap,c)677 dosyscmd(ap, c)
678 char **ap;
679 {
680 if (c > 0)
681 system(ap[1]);
682 }
683
domake(ap,c)684 domake(ap, c)
685 char **ap;
686 {
687 if (c > 0)
688 pbstr(mktemp(ap[1]));
689 }
690
doincr(ap,c)691 doincr(ap, c)
692 char **ap;
693 {
694 if (c >= 1)
695 putnum(ctol(ap[1])+1);
696 }
697
putnum(num)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
dosubstr(ap,c)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
doindex(ap,c)732 doindex(ap, c)
733 char **ap;
734 {
735 if (c >= 2)
736 putnum((long) strindex(ap[1], ap[2]));
737 }
738
strindex(p1,p2)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
dotransl(ap,c)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
doif(ap,c)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
dodiv(ap,c)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
doundiv(ap,c)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
dodivnum(ap,c)868 dodivnum(ap, c)
869 char **ap;
870 {
871 putnum((long) curout);
872 }
873
dodnl(ap,c)874 dodnl(ap, c)
875 char **ap;
876 {
877 register t;
878
879 while ((t=getchr())!='\n' && t>=0)
880 ;
881 }
882
ctol(str)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
ctoi(s)903 ctoi(s)
904 char *s;
905 {
906 return(ctol(s));
907 }
908
min(a,b)909 min(a, b)
910 {
911 if (a>b)
912 return(b);
913 return(a);
914 }
915
max(a,b)916 max(a, b)
917 {
918 if (a>b)
919 return(a);
920 return(b);
921 }
922