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