main.c revision 1.2 1 /* File : main.c
2 Author : Ozan Yigit
3 Updated: 4 May 1992
4 Defines: M4 macro processor.
5 */
6
7 #include "mdef.h"
8 #include "extr.h"
9 #include "ourlims.h"
10
11 char chtype[1 - EOF + UCHAR_MAX];
12
13 #define is_sym1(c) (chtype[(c)-EOF] > 10)
14 #define is_sym2(c) (chtype[(c)-EOF] > 0)
15 #define is_blnk(c) ((unsigned)((c)-1) < ' ')
16
17 /*
18 * m4 - macro processor
19 *
20 * PD m4 is based on the macro tool distributed with the software
21 * tools (VOS) package, and described in the "SOFTWARE TOOLS" and
22 * "SOFTWARE TOOLS IN PASCAL" books. It has been expanded to include
23 * most of the command set of SysV m4, the standard UN*X macro processor.
24 *
25 * Since both PD m4 and UN*X m4 are based on SOFTWARE TOOLS macro,
26 * there may be certain implementation similarities between
27 * the two. The PD m4 was produced without ANY references to m4
28 * sources.
29 *
30 * References:
31 *
32 * Software Tools distribution: macro
33 *
34 * Kernighan, Brian W. and P. J. Plauger, SOFTWARE
35 * TOOLS IN PASCAL, Addison-Wesley, Mass. 1981
36 *
37 * Kernighan, Brian W. and P. J. Plauger, SOFTWARE
38 * TOOLS, Addison-Wesley, Mass. 1976
39 *
40 * Kernighan, Brian W. and Dennis M. Ritchie,
41 * THE M4 MACRO PROCESSOR, Unix Programmer's Manual,
42 * Seventh Edition, Vol. 2, Bell Telephone Labs, 1979
43 *
44 * System V man page for M4
45 *
46 * Modification History:
47 *
48 * Mar 26 1992 RAOK 1. Eliminated magic numbers 8, 255, 256 in favour
49 * of the standard limits CHAR_BIT, UCHAR_MAX, which
50 * are in the new header ourlims.h. This is part of
51 * the "8-bit-clean M4" project. To the best of my
52 * belief, all of the code should work in EBCDIC,
53 * ASCII, DEC MNCS, ISO 8859/n, or the Mac character
54 * set, as long as chars are unsigned. There are
55 * still some places where signed bytes can cause
56 * trouble.
57 *
58 * 2. Changed expr() to use long int rather than int.
59 * This is so that we'd get 32-bit arithmetic on a Sun,
60 * Encore, PC, Mac &c. As part of this, the code for
61 * shifts has been elaborated to yield signed shifts
62 * on all machines. The charcon() function didn't work
63 * with multi-character literals, although it was meant
64 * to. Now it does. pbrad() has been changed so that
65 * eval('abcd',0) => abcd, not dcba, which was useless.
66 *
67 * 3. I finally got sick of the fact that &&, ||, and
68 * ?: always evaluate all their arguments. This is
69 * consistent with UNIX System V Release 3, but I for
70 * one don't see anything to gain by having eval(0&&1/0)
71 * crash when it would simply yield 0 in C. Now these
72 * operators are more consistent with the C preprocessor.
73 *
74 * Nov 13 1992 RAOK Added the quoter facility. The purpose of this is
75 * to make it easier to generate data for a variety of
76 * programming languages, including sh, awk, Lisp, C.
77 * There are two holes in the implementation: dumpdef
78 * prints junk and undefine doesn't release everything.
79 * This was mainly intended as a prototype to show that
80 * it could be done.
81 *
82 * Jun 16 1992 RAOK Added vquote and gave changequote a 3rd argument.
83 * The idea of this is to make it possible to quote
84 * ANY string, including one with unbalanced ` or '.
85 * I also made eval(c,0) convert decimal->ASCII, so
86 * that eval(39,0) yields ' and eval(96,0) yields `.
87 *
88 * Apr 28 1992 RAOK Used gcc to find and fix ANSI clashes, so that
89 * PD M4 could be ported to MS-DOS (Turbo C 3).
90 * Main known remaining problem: use of mktemp().
91 * Also, command line handling needs to be worked out.
92 *
93 * Mar 26 1992 RAOK PD M4 now accepts file names on the command line
94 * just like UNIX M4. Warning: macro calls must NOT
95 * cross file boundaries. UNIX M4 doesn't mind;
96 * (m4 a b c) and (cat a b c | m4) are just the same
97 * except for error messages. PD M4 will report an
98 * unexpected EOF if a file ends while a macro call or
99 * string is still being parsed. When there is one
100 * file name argument, or none, you can't tell the
101 * difference, and that's all I need.
102 *
103 * May 15 1991 RAOK DIVNAM was a string constant, but was changed!
104 * Fixed that and a couple of other things to make
105 * GCC happy. (Also made "foo$bar" get through.)
106 *
107 * Apr 17 1991 RAOK There was a major mistake. If you did
108 * define(foo, `1 include(bar) 2') where
109 * file bar held "-bar-" you would naturally
110 * expect "1 -bar- 2" as the output, but you
111 * got "1 2-bar-". That is, include file
112 * processing was postponed until all macros
113 * had been expanded. The macro gpbc() was
114 * at fault. I added bb, bbstack[], and the
115 * code in main.c and serv.c that maintains
116 * them, in order to work around this bug.
117 *
118 * Apr 12 1991 RAOK inspect() didn't handle overflow well.
119 * Added the automatically maintained macro
120 * __FILE__, just as in C. To suppress it,
121 * define NO__FILE. At some point, $# had
122 * been made to return a value that was off
123 * by one; it now agrees with SysV M4.
124 *
125 * Aug 13 1990 RAOK The System V expr() has three arguments:
126 * expression [, radix:10 [, mindigits: 1]]
127 * Brought in my int2str() and wrote pbrad()
128 * to make this work here. With the wrong #
129 * of args, acts like System V.
130 *
131 * Aug 11 1990 RAOK Told expr.c about the Pascal operators
132 * not, div, mod, and, or
133 * so that Pascal constant expressions could
134 * be evaluated. (It still doesn't handle
135 * floats.) Fixed a mistake in 'character's.
136 *
137 * Apr 23 1988 RAOK Sped it up, mainly by making putback() and
138 * chrsave() into macros.
139 * Finished the -o option (was half done).
140 * Added the System V -e (interactive) option.
141 *
142 * Jan 28 1986 Oz Break the whole thing into little
143 * pieces, for easier (?) maintenance.
144 *
145 * Dec 12 1985 Oz Optimize the code, try to squeeze
146 * few microseconds out.. [didn't try very hard]
147 *
148 * Dec 05 1985 Oz Add getopt interface, define (-D),
149 * undefine (-U) options.
150 *
151 * Oct 21 1985 Oz Clean up various bugs, add comment handling.
152 *
153 * June 7 1985 Oz Add some of SysV m4 stuff (m4wrap, pushdef,
154 * popdef, decr, shift etc.).
155 *
156 * June 5 1985 Oz Initial cut.
157 *
158 * Implementation Notes:
159 *
160 * [1] PD m4 uses a different (and simpler) stack mechanism than the one
161 * described in Software Tools and Software Tools in Pascal books.
162 * The triple stack nonsense is replaced with a single stack containing
163 * the call frames and the arguments. Each frame is back-linked to a
164 * previous stack frame, which enables us to rewind the stack after
165 * each nested call is completed. Each argument is a character pointer
166 * to the beginning of the argument string within the string space.
167 * The only exceptions to this are (*) arg 0 and arg 1, which are
168 * the macro definition and macro name strings, stored dynamically
169 * for the hash table.
170 *
171 * . .
172 * | . | <-- sp | . |
173 * +-------+ +-----+
174 * | arg 3 ------------------------------->| str |
175 * +-------+ | . |
176 * | arg 2 --------------+ .
177 * +-------+ |
178 * * | | |
179 * +-------+ | +-----+
180 * | plev | <-- fp +---------------->| str |
181 * +-------+ | . |
182 * | type | .
183 * +-------+
184 * | prcf -----------+ plev: paren level
185 * +-------+ | type: call type
186 * | . | | prcf: prev. call frame
187 * . |
188 * +-------+ |
189 * | <----------+
190 * +-------+
191 *
192 * [2] We have three types of null values:
193 *
194 * nil - nodeblock pointer type 0
195 * null - null string ("")
196 * NULL - Stdio-defined NULL
197 *
198 */
199
200 char buf[BUFSIZE]; /* push-back buffer */
201 char *bp = buf; /* first available character */
202 char *bb = buf; /* buffer beginning */
203 char *endpbb = buf+BUFSIZE; /* end of push-back buffer */
204 stae mstack[STACKMAX+1]; /* stack of m4 machine */
205 char strspace[STRSPMAX+1]; /* string space for evaluation */
206 char *ep = strspace; /* first free char in strspace */
207 char *endest= strspace+STRSPMAX;/* end of string space */
208 int sp; /* current m4 stack pointer */
209 int fp; /* m4 call frame pointer */
210 char *bbstack[MAXINP]; /* stack where bb is saved */
211 FILE *infile[MAXINP]; /* input file stack (0=stdin) */
212 FILE *outfile[MAXOUT]; /* diversion array(0=bitbucket)*/
213 FILE *active; /* active output file pointer */
214 int ilevel = 0; /* input file stack pointer */
215 int oindex = 0; /* diversion index.. */
216 char *null = ""; /* as it says.. just a null.. */
217 char *m4wraps = ""; /* m4wrap string default.. */
218 char lquote = LQUOTE; /* left quote character (`) */
219 char rquote = RQUOTE; /* right quote character (') */
220 char vquote = VQUOTE; /* verbatim quote character ^V */
221 char scommt = SCOMMT; /* start character for comment */
222 char ecommt = ECOMMT; /* end character for comment */
223 int strip = 0; /* throw away comments? */
224
225 /* Definitions of diversion files. The last 6 characters MUST be
226 "XXXXXX" -- that is a requirement of mktemp(). The character
227 '0' is to be replaced by the diversion number; we assume here
228 that it is just before the Xs. If not, you will have to alter
229 the definition of UNIQUE.
230 */
231
232 #if unix
233 static char DIVNAM[] = "/usr/tmp/m40XXXXXX";
234 #else
235 #if vms
236 static char DIVNAM[] = "sys$login:m40XXXXXX";
237 #else
238 static char DIVNAM[] = "M40XXXXXX"; /* was \M4, should it be \\M4? */
239 #endif
240 #endif
241 int UNIQUE = sizeof DIVNAM - 7; /* where to change m4temp. */
242 char *m4temp; /* filename for diversions */
243 extern char *mktemp();
244
245
246 void cantread(s)
247 char *s;
248 {
249 fprintf(stderr, "m4: %s: ", s);
250 error("cannot open for input.");
251 }
252
253
254 /* initkwds()
255 initialises the hash table to contain all the m4 built-in functions.
256 The original version breached module boundaries, but there did not
257 seem to be any benefit in that.
258 */
259 static void initkwds()
260 {
261 register int i;
262 static struct { char *name; int type; } keyword[] =
263 {
264 "include", INCLTYPE,
265 "sinclude", SINCTYPE,
266 "define", DEFITYPE,
267 "defn", DEFNTYPE,
268 "divert", DIVRTYPE,
269 "expr", EXPRTYPE,
270 "eval", EXPRTYPE,
271 "substr", SUBSTYPE,
272 "ifelse", IFELTYPE,
273 "ifdef", IFDFTYPE,
274 "len", LENGTYPE,
275 "incr", INCRTYPE,
276 "decr", DECRTYPE,
277 "dnl", DNLNTYPE,
278 "changequote", CHNQTYPE,
279 "changecom", CHNCTYPE,
280 "index", INDXTYPE,
281 #ifdef EXTENDED
282 "paste", PASTTYPE,
283 "spaste", SPASTYPE,
284 "m4trim", TRIMTYPE,
285 "defquote", DEFQTYPE,
286 #endif
287 "popdef", POPDTYPE,
288 "pushdef", PUSDTYPE,
289 "dumpdef", DUMPTYPE,
290 "shift", SHIFTYPE,
291 "translit", TRNLTYPE,
292 "undefine", UNDFTYPE,
293 "undivert", UNDVTYPE,
294 "divnum", DIVNTYPE,
295 "maketemp", MKTMTYPE,
296 "errprint", ERRPTYPE,
297 "m4wrap", M4WRTYPE,
298 "m4exit", EXITTYPE,
299 #if unix || vms
300 "syscmd", SYSCTYPE,
301 "sysval", SYSVTYPE,
302 #endif
303 #if unix
304 "unix", MACRTYPE,
305 #else
306 #if vms
307 "vms", MACRTYPE,
308 #endif
309 #endif
310 (char*)0, 0
311 };
312
313 for (i = 0; keyword[i].type != 0; i++)
314 addkywd(keyword[i].name, keyword[i].type);
315 }
316
317
318 /* inspect(Name)
319 Build an input token.., considering only those which start with
320 [A-Za-z_]. This is fused with lookup() to speed things up.
321 name must point to an array of at least MAXTOK characters.
322 */
323 ndptr inspect(name)
324 char *name;
325 {
326 register char *tp = name;
327 register char *etp = name+(MAXTOK-1);
328 register int c;
329 register unsigned long h = 0;
330 register ndptr p;
331
332 while (is_sym2(c = gpbc())) {
333 if (tp == etp) error("m4: token too long");
334 *tp++ = c, h = (h << 5) + h + c;
335 }
336 putback(c);
337 *tp = EOS;
338 for (p = hashtab[h%HASHSIZE]; p != nil; p = p->nxtptr)
339 if (strcmp(name, p->name) == 0)
340 return p;
341 return nil;
342 }
343
344
345 /*
346 * macro - the work horse..
347 *
348 */
349 void macro()
350 {
351 char token[MAXTOK];
352 register int t;
353 register FILE *op = active;
354 static char ovmsg[] = "m4: internal stack overflow";
355
356 for (;;) {
357 t = gpbc();
358 if (is_sym1(t)) {
359 register char *s;
360 register ndptr p;
361
362 putback(t);
363 if ((p = inspect(s = token)) == nil) {
364 if (sp < 0) {
365 while (t = *s++) putc(t, op);
366 } else {
367 while (t = *s++) chrsave(t);
368 }
369 } else {
370 /* real thing.. First build a call frame */
371 if (sp >= STACKMAX-6) error(ovmsg);
372 mstack[1+sp].sfra = fp; /* previous call frm */
373 mstack[2+sp].sfra = p->type; /* type of the call */
374 mstack[3+sp].sfra = 0; /* parenthesis level */
375 fp = sp+3; /* new frame pointer */
376 /* now push the string arguments */
377 mstack[4+sp].sstr = p->defn; /* defn string */
378 mstack[5+sp].sstr = p->name; /* macro name */
379 mstack[6+sp].sstr = ep; /* start next.. */
380 sp += 6;
381
382 t = gpbc();
383 putback(t);
384 if (t != LPAREN) { putback(RPAREN); putback(LPAREN); }
385 }
386 } else
387 if (t == EOF) {
388 if (sp >= 0) error("m4: unexpected end of input");
389 if (--ilevel < 0) break; /* all done thanks */
390 #ifndef NO__FILE
391 remhash("__FILE__", TOP);
392 #endif
393 bb = bbstack[ilevel+1];
394 (void) fclose(infile[ilevel+1]);
395 } else
396 /* non-alpha single-char token seen..
397 [the order of else if .. stmts is important.]
398 */
399 if (t == lquote) { /* strip quotes */
400 register int nlpar;
401
402 for (nlpar = 1; ; ) {
403 t = gpbc();
404 if (t == rquote) {
405 if (--nlpar == 0) break;
406 } else
407 if (t == lquote) {
408 nlpar++;
409 } else {
410 if (t == vquote) t = gpbc();
411 if (t == EOF) {
412 error("m4: missing right quote");
413 }
414 }
415 if (sp < 0) {
416 putc(t, op);
417 } else {
418 chrsave(t);
419 }
420 }
421 } else
422 if (sp < 0) { /* not in a macro at all */
423 if (t != scommt) { /* not a comment, so */
424 putc(t, op); /* copy it to output */
425 } else
426 if (strip) { /* discard a comment */
427 do {
428 t = gpbc();
429 } while (t != ecommt && t != EOF);
430 } else { /* copy comment to output */
431 do {
432 putc(t, op);
433 t = gpbc();
434 } while (t != ecommt && t != EOF);
435 putc(t, op);
436 /* A note on comment handling: this is NOT robust.
437 | We should do something safe with comments that
438 | are missing their ecommt termination.
439 */
440 }
441 } else
442 switch (t) {
443 /* There is a peculiar detail to notice here.
444 Layout is _always_ discarded after left parentheses,
445 but it is only discarded after commas if they separate
446 arguments. For example,
447 define(foo,`|$1|$2|')
448 foo( a, b) => |a|b|
449 foo(( a ), ( b )) => |(a )|(b )|
450 foo((a, x), (b, y)) => |(a, x)|(b, y)|
451 I find this counter-intuitive, and would expect the code
452 for LPAREN to read something like this:
453
454 if (PARLEV == 0) {
455 (* top level left parenthesis: skip layout *)
456 do t = gpbc(); while (is_blnk(t));
457 putback(t);
458 } else {
459 (* left parenthesis inside an argument *)
460 chrsave(t);
461 }
462 PARLEV++;
463
464 However, it turned out that Oz wrote the actual code
465 very carefully to mimic the behaviour of "real" m4;
466 UNIX m4 really does skip layout after all left parens
467 but only some commas in just this fashion. Sigh.
468 */
469 case LPAREN:
470 if (PARLEV > 0) chrsave(t);
471 do t = gpbc(); while (is_blnk(t)); /* skip layout */
472 putback(t);
473 PARLEV++;
474 break;
475
476 case COMMA:
477 if (PARLEV == 1) {
478 chrsave(EOS); /* new argument */
479 if (sp >= STACKMAX) error(ovmsg);
480 do t = gpbc(); while (is_blnk(t)); /* skip layout */
481 putback(t);
482 mstack[++sp].sstr = ep;
483 } else {
484 chrsave(t);
485 }
486 break;
487
488 case RPAREN:
489 if (--PARLEV > 0) {
490 chrsave(t);
491 } else {
492 char **argv = (char **)(mstack+fp+1);
493 int argc = sp-fp;
494 #if unix | vms
495 static int sysval;
496 #endif
497
498 chrsave(EOS); /* last argument */
499 if (sp >= STACKMAX) error(ovmsg);
500 #ifdef DEBUG
501 fprintf(stderr, "argc = %d\n", argc);
502 for (t = 0; t < argc; t++)
503 fprintf(stderr, "argv[%d] = %s\n", t, argv[t]);
504 #endif
505 /* If argc == 3 and argv[2] is null, then we
506 have a call like `macro_or_builtin()'. We
507 adjust argc to avoid further checking..
508 */
509 if (argc == 3 && !argv[2][0]) argc--;
510
511 switch (CALTYP & ~STATIC) {
512 case MACRTYPE:
513 expand(argv, argc);
514 break;
515
516 case DEFITYPE: /* define(..) */
517 for (; argc > 2; argc -= 2, argv += 2)
518 dodefine(argv[2], argc > 3 ? argv[3] : null);
519 break;
520
521 case PUSDTYPE: /* pushdef(..) */
522 for (; argc > 2; argc -= 2, argv += 2)
523 dopushdef(argv[2], argc > 3 ? argv[3] : null);
524 break;
525
526 case DUMPTYPE:
527 dodump(argv, argc);
528 break;
529
530 case EXPRTYPE: /* eval(Expr) */
531 { /* evaluate arithmetic expression */
532 /* eval([val: 0[, radix:10 [,min: 1]]]) */
533 /* excess arguments are ignored */
534 /* eval() with no arguments returns 0 */
535 /* this is based on V.3 behaviour */
536 int min_digits = 1;
537 int radix = 10;
538 long int value = 0;
539
540 switch (argc) {
541 default:
542 /* ignore excess arguments */
543 case 5:
544 min_digits = expr(argv[4]);
545 case 4:
546 radix = expr(argv[3]);
547 case 3:
548 value = expr(argv[2]);
549 case 2:
550 break;
551 }
552 pbrad(value, radix, min_digits);
553 }
554 break;
555
556 case IFELTYPE: /* ifelse(X,Y,IFX=Y,Else) */
557 doifelse(argv, argc);
558 break;
559
560 case IFDFTYPE: /* ifdef(Mac,IfDef[,IfNotDef]) */
561 /* select one of two alternatives based on the existence */
562 /* of another definition */
563 if (argc > 3) {
564 if (lookup(argv[2]) != nil) {
565 pbstr(argv[3]);
566 } else
567 if (argc > 4) {
568 pbstr(argv[4]);
569 }
570 }
571 break;
572
573 case LENGTYPE: /* len(Arg) */
574 /* find the length of the argument */
575 pbnum(argc > 2 ? strlen(argv[2]) : 0);
576 break;
577
578 case INCRTYPE: /* incr(Expr) */
579 /* increment the value of the argument */
580 if (argc > 2) pbnum(expr(argv[2]) + 1);
581 break;
582
583 case DECRTYPE: /* decr(Expr) */
584 /* decrement the value of the argument */
585 if (argc > 2) pbnum(expr(argv[2]) - 1);
586 break;
587
588 #if unix || vms
589 case SYSCTYPE: /* syscmd(Command) */
590 /* execute system command */
591 /* Make sure m4 output is NOT interrupted */
592 fflush(stdout);
593 fflush(stderr);
594
595 if (argc > 2) sysval = system(argv[2]);
596 break;
597
598 case SYSVTYPE: /* sysval() */
599 /* return value of the last system call. */
600 pbnum(sysval);
601 break;
602 #endif
603
604 case INCLTYPE: /* include(File) */
605 for (t = 2; t < argc; t++)
606 if (!doincl(argv[t])) cantread(argv[t]);
607 break;
608
609 case SINCTYPE: /* sinclude(File) */
610 for (t = 2; t < argc; t++)
611 (void) doincl(argv[t]);
612 break;
613
614 #ifdef EXTENDED
615 case PASTTYPE: /* paste(File) */
616 for (t = 2; t < argc; t++)
617 if (!dopaste(argv[t])) cantread(argv[t]);
618 break;
619
620 case SPASTYPE: /* spaste(File) */
621 for (t = 2; t < argc; t++)
622 (void) dopaste(argv[t]);
623 break;
624
625 case TRIMTYPE: /* m4trim(Source,..) */
626 if (argc > 2) m4trim(argv, argc);
627 break;
628
629 case DEFQTYPE: /* defquote(Mac,...) */
630 dodefqt(argv, argc);
631 break;
632
633 case QUTRTYPE: /* <quote>(text...) */
634 doqutr(argv, argc);
635 break;
636 #endif
637
638 case CHNQTYPE: /* changequote([Left[,Right]]) */
639 dochq(argv, argc);
640 break;
641
642 case CHNCTYPE: /* changecom([Left[,Right]]) */
643 dochc(argv, argc);
644 break;
645
646 case SUBSTYPE: /* substr(Source[,Offset[,Length]]) */
647 /* select substring */
648 if (argc > 3) dosub(argv, argc);
649 break;
650
651 case SHIFTYPE: /* shift(~args~) */
652 /* push back all arguments except the first one */
653 /* (i.e. skip argv[2]) */
654 if (argc > 3) {
655 for (t = argc-1; t > 3; t--) {
656 pbqtd(argv[t]);
657 putback(',');
658 }
659 pbqtd(argv[3]);
660 }
661 break;
662
663 case DIVRTYPE: /* divert(N) */
664 if (argc > 2 && (t = expr(argv[2])) != 0) {
665 dodiv(t);
666 } else {
667 active = stdout;
668 oindex = 0;
669 }
670 op = active;
671 break;
672
673 case UNDVTYPE: /* undivert(N...) */
674 doundiv(argv, argc);
675 op = active;
676 break;
677
678 case DIVNTYPE: /* divnum() */
679 /* return the number of current output diversion */
680 pbnum(oindex);
681 break;
682
683 case UNDFTYPE: /* undefine(..) */
684 /* undefine a previously defined macro(s) or m4 keyword(s). */
685 for (t = 2; t < argc; t++) remhash(argv[t], ALL);
686 break;
687
688 case POPDTYPE: /* popdef(Mac...) */
689 /* remove the topmost definitions of macro(s) or m4 keyword(s). */
690 for (t = 2; t < argc; t++) remhash(argv[t], TOP);
691 break;
692
693 case MKTMTYPE: /* maketemp(Pattern) */
694 /* create a temporary file */
695 if (argc > 2) pbstr(mktemp(argv[2]));
696 break;
697
698 case TRNLTYPE: /* translit(Source,Dom,Rng) */
699 /* replace all characters in the source string that */
700 /* appears in the "from" string with the corresponding */
701 /* characters in the "to" string. */
702
703 if (argc > 3) {
704 char temp[MAXTOK];
705
706 if (argc > 4)
707 map(temp, argv[2], argv[3], argv[4]);
708 else
709 map(temp, argv[2], argv[3], null);
710 pbstr(temp);
711 } else if (argc > 2)
712 pbstr(argv[2]);
713 break;
714
715 case INDXTYPE: /* index(Source,Target) */
716 /* find the index of the second argument string in */
717 /* the first argument string. -1 if not present. */
718 pbnum(argc > 3 ? indx(argv[2], argv[3]) : -1);
719 break;
720
721 case ERRPTYPE: /* errprint(W,...,W) */
722 /* print the arguments to stderr file */
723 for (t = 2; t < argc; t++) fprintf(stderr, "%s ", argv[t]);
724 fprintf(stderr, "\n");
725 break;
726
727 case DNLNTYPE: /* dnl() */
728 /* eat upto and including newline */
729 while ((t = gpbc()) != '\n' && t != EOF) ;
730 break;
731
732 case M4WRTYPE: /* m4wrap(AtExit) */
733 /* set up for wrap-up/wind-down activity. */
734 /* NB: if there are several calls to m4wrap */
735 /* only the last is effective; strange, but */
736 /* that's what System V does. */
737 m4wraps = argc > 2 ? strsave(argv[2]) : null;
738 break;
739
740 case EXITTYPE: /* m4exit(Expr) */
741 /* immediate exit from m4. */
742 killdiv(); /* mustn't forget that one! */
743 exit(argc > 2 ? expr(argv[2]) : 0);
744 break;
745
746 case DEFNTYPE: /* defn(Mac) */
747 for (t = 2; t < argc; t++)
748 dodefn(argv[t]);
749 break;
750
751 default:
752 error("m4: major botch in eval.");
753 break;
754 }
755
756 ep = PREVEP; /* flush strspace */
757 sp = PREVSP; /* previous sp.. */
758 fp = PREVFP; /* rewind stack... */
759 }
760 break;
761
762 default:
763 chrsave(t); /* stack the char */
764 break;
765 }
766 }
767 }
768
769
770 int main(argc, argv)
771 int argc;
772 char **argv;
773 {
774 register int c;
775 register int n;
776 char *p;
777
778 #ifdef SIGINT
779 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
780 signal(SIGINT, onintr);
781 #endif
782
783 /* Initialise the chtype[] table.
784 '0' .. '9' -> 1..10
785 'A' .. 'Z' -> 11..37
786 'a' .. 'z' -> 11..37
787 '_' -> 38
788 all other characters -> 0
789 */
790 for (c = EOF; c <= UCHAR_MAX; c++) chtype[c - EOF] = 0;
791 for (c = 1, p = "0123456789"; *p; p++, c++)
792 chtype[*(unsigned char *)p - EOF] = c;
793 for (c = 11, p = "abcdefghijklmnopqrstuvwxyz"; *p; p++, c++)
794 chtype[*(unsigned char *)p - EOF] = c;
795 for (c = 11, p = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; *p; p++, c++)
796 chtype[*(unsigned char *)p - EOF] = c;
797 chtype['_' - EOF] = 38;
798
799 #ifdef NONZEROPAGES
800 /* If your system does not initialise global variables to */
801 /* 0 bits, do it here. */
802 for (n = 0; n < HASHSIZE; n++) hashtab[n] = nil;
803 for (n = 0; n < MAXOUT; n++) outfile[n] = NULL;
804 #endif
805 initkwds();
806
807 while ((c = getopt(argc, argv, "cetD:U:o:B:H:S:T:")) != EOF) {
808 switch (c) {
809 #if 0
810 case 's': /* enable #line sync in output */
811 fprintf(stderr, "m4: this version does not support -s\n");
812 exit(2);
813 #endif
814
815 case 'c': /* strip comments */
816 strip ^= 1;
817 break;
818
819 case 'e': /* interactive */
820 (void) signal(SIGINT, SIG_IGN);
821 setbuf(stdout, NULL);
822 break;
823
824 case 'D': /* define something..*/
825 for (p = optarg; *p && *p != '='; p++) ;
826 if (*p) *p++ = EOS;
827 dodefine(optarg, p);
828 break;
829
830 case 'U': /* undefine... */
831 remhash(optarg, TOP);
832 break;
833
834 case 'B': case 'H': /* System V compatibility */
835 case 'S': case 'T': /* ignore them */
836 break;
837
838 case 'o': /* specific output */
839 if (!freopen(optarg, "w", stdout)) {
840 perror(optarg);
841 exit(1);
842 }
843 break;
844
845 case '?':
846 default:
847 usage();
848 }
849 }
850
851 active = stdout; /* default active output */
852 m4temp = mktemp(DIVNAM); /* filename for diversions */
853
854 sp = -1; /* stack pointer initialized */
855 fp = 0; /* frame pointer initialized */
856
857 if (optind == argc) { /* no more args; read stdin */
858 infile[0] = stdin; /* default input (naturally) */
859 #ifndef NO__FILE
860 dodefine("__FILE__", "-"); /* Helas */
861 #endif
862 macro(); /* process that file */
863 } else /* file names in commandline */
864 for (; optind < argc; optind++) {
865 char *name = argv[optind]; /* next file name */
866 infile[0] = fopen(name, "r");
867 if (!infile[0]) cantread(name);
868 #ifndef NO__FILE
869 dodefine("__FILE__", name);
870 #endif
871 macro();
872 fclose(infile[0]);
873 }
874
875 if (*m4wraps) { /* anything for rundown ?? */
876 ilevel = 0; /* in case m4wrap includes.. */
877 putback(EOF); /* eof is a must !! */
878 pbstr(m4wraps); /* user-defined wrapup act */
879 macro(); /* last will and testament */
880 } else { /* default wrap-up: undivert */
881 for (n = 1; n < MAXOUT; n++)
882 if (outfile[n] != NULL) getdiv(n);
883 }
884
885 if (outfile[0] != NULL) { /* remove bitbucket if used */
886 (void) fclose(outfile[0]);
887 m4temp[UNIQUE] = '0';
888 #if unix
889 (void) unlink(m4temp);
890 #else
891 (void) remove(m4temp);
892 #endif
893 }
894 exit(0);
895 return 0;
896 }
897
898