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