added "more" command
[unix-history] / usr / src / usr.bin / m4 / m4.c
CommitLineData
5e785920 1Virgin BTL M4 as sent out in 4.1
17d1455f
SL
2#ifndef lint
3static char sccsid[] = "@(#)m4.c 1.3 (Berkeley) %G%";
4#endif
5
5e785920
CC
6#include <stdio.h>
7#include <signal.h>
8
9#define ERROR NULL
10#define READ "r"
11#define WRITE "w"
12
13#define EOS 0
14int 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
23char lquote LBRAK;
24char rquote RBRAK;
25#endif
26#ifndef M4
27char lquote = GRAVE;
28char 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
42char 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
61char token[TOKS];
62char eoa[] = "\0";
ecc33553
CC
63
64#define RESERVED 01 /* This is a reserved word with side action */
5e785920
CC
65struct nlist {
66 char *name;
67 char *def;
ecc33553 68 char flag;
5e785920
CC
69 struct nlist *next;
70};
71
72struct nlist *hshtab[HSHSIZ];
73char ibuf[SAVS+TOKS];
74char obuf[SAVS+TOKS];
75char *op = obuf;
76char *ip = ibuf;
77char *ip_stk[10] = {ibuf};
78char *cur_ip = ibuf;
79struct call {
80 char **argp;
81 int plev;
82};
83struct call *cp = NULL;
84
85char *makeloc;
86char *ifdefloc;
87char *lenloc;
88char *undefloc;
89char *shiftloc;
90char *cqloc;
91char *defloc;
92char *evaloc;
93char *incrloc;
94char *substrloc;
95char *indexloc;
96char *transloc;
97char *ifloc;
98char *divloc;
99char *divnumloc;
100char *undivloc;
101char *dnlloc;
102char *inclloc;
103char *sinclloc;
104char *syscmdloc;
105char *dumploc;
106char *errploc;
107
108char *tempname;
109struct nlist *lookup();
110char *install();
111char *malloc();
112char *mktemp();
113char *copy();
114long ctol();
115int hshval;
116FILE *olist[11] = { stdout };
117int okret;
118int curout = 0;
119FILE *curfile = { stdout };
120FILE *infile[10] = { stdin };
121int infptr = 0;
122
123main(argc, argv)
124char **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
ecc33553 135 install("GCOS", eoa, 0);
5e785920
CC
136#endif
137#ifndef M4
ecc33553 138 install("gcos", eoa, 0);
5e785920
CC
139#endif
140#endif
141#ifdef unix
142#ifdef M4
ecc33553 143 install("UNIX", eoa, 0);
5e785920
CC
144#endif
145#ifndef M4
ecc33553 146 install("unix", eoa, 0);
5e785920
CC
147#endif
148#endif
149
150#ifdef M4
ecc33553
CC
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);
5e785920
CC
173#endif
174
175#ifndef M4
ecc33553
CC
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);
5e785920
CC
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 tempname = mktemp("/tmp/m4aXXXXX");
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
333catchsig()
334{
335 okret = 0;
336 delexit();
337}
338
339delexit()
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
366puttok()
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
383pbstr(str)
384register 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
399expand(a1, c)
400register 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
467struct nlist *lookup(str)
468char *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
ecc33553 488char *install(nam, val, flag)
5e785920 489char *nam, *val;
ecc33553 490char flag;
5e785920
CC
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];
ecc33553 503 np->flag = flag;
5e785920
CC
504 hshtab[hshval] = np;
505 return(np->def);
506 }
507 free(np->def);
ecc33553 508 np->flag = flag;
5e785920
CC
509 np->def = copy(val);
510 return(np->def);
511}
512
513doundef(ap, c)
514char **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 }
ecc33553
CC
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 }
5e785920
CC
542}
543
544char *copy(s)
545register 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
558dodef(ap, c)
559char **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 }
ecc33553 566 install(ap[1], ap[2], 0);
5e785920
CC
567 }
568 else if (c == 1)
ecc33553 569 install(ap[1], "", 0);
5e785920
CC
570}
571
572doifdef(ap, c)
573char **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
585dolen(ap, c)
586char **ap;
587{
588 putnum((long) strlen(ap[1]));
589}
590
591docq(ap, c)
592char **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
611doshift(ap, c)
612char **ap;
613{
614 fprintf(stderr, "m4: shift not yet implemented\n");
615}
616
617dodump(ap, c)
618char **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
634doerrp(ap, c)
635char **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
644long evalval; /* return value from yacc stuff */
645char *pe; /* used by grammar */
646
647doeval(ap, c)
648char **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
660doincl(ap, c, noisy)
661char **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
677dosyscmd(ap, c)
678char **ap;
679{
680 if (c > 0)
681 system(ap[1]);
682}
683
684domake(ap, c)
685char **ap;
686{
687 if (c > 0)
688 pbstr(mktemp(ap[1]));
689}
690
691doincr(ap, c)
692char **ap;
693{
694 if (c >= 1)
695 putnum(ctol(ap[1])+1);
696}
697
698putnum(num)
699long 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
714dosubstr(ap, c)
715char **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
732doindex(ap, c)
733char **ap;
734{
735 if (c >= 2)
736 putnum((long) strindex(ap[1], ap[2]));
737}
738
739strindex(p1, p2)
740char *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
757dotransl(ap, c)
758char **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
790doif(ap, c)
791register 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
807dodiv(ap, c)
808register 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
827doundiv(ap, c)
828char **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
868dodivnum(ap, c)
869char **ap;
870{
871 putnum((long) curout);
872}
873
874dodnl(ap, c)
875char **ap;
876{
877 register t;
878
879 while ((t=getchr())!='\n' && t>=0)
880 ;
881}
882
883long ctol(str)
884register 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
903ctoi(s)
904char *s;
905{
906 return(ctol(s));
907}
908
909min(a, b)
910{
911 if (a>b)
912 return(b);
913 return(a);
914}
915
916max(a, b)
917{
918 if (a>b)
919 return(a);
920 return(b);
921}