xref: /original-bsd/usr.bin/m4/eval.c (revision ae45e3e8)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ozan Yigit at York University.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)eval.c	8.1 (Berkeley) 06/06/93";
13 #endif /* not lint */
14 
15 /*
16  * eval.c
17  * Facility: m4 macro processor
18  * by: oz
19  */
20 
21 #include <sys/types.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "mdef.h"
28 #include "stdd.h"
29 #include "extern.h"
30 #include "pathnames.h"
31 
32 /*
33  * eval - evaluate built-in macros.
34  *	  argc - number of elements in argv.
35  *	  argv - element vector :
36  *			argv[0] = definition of a user
37  *				  macro or nil if built-in.
38  *			argv[1] = name of the macro or
39  *				  built-in.
40  *			argv[2] = parameters to user-defined
41  *			   .	  macro or built-in.
42  *			   .
43  *
44  * Note that the minimum value for argc is 3. A call in the form
45  * of macro-or-builtin() will result in:
46  *			argv[0] = nullstr
47  *			argv[1] = macro-or-builtin
48  *			argv[2] = nullstr
49  */
50 
51 void
52 eval(argv, argc, td)
53 register char *argv[];
54 register int argc;
55 register int td;
56 {
57 	register int c, n;
58 	static int sysval = 0;
59 
60 #ifdef DEBUG
61 	printf("argc = %d\n", argc);
62 	for (n = 0; n < argc; n++)
63 		printf("argv[%d] = %s\n", n, argv[n]);
64 #endif
65  /*
66   * if argc == 3 and argv[2] is null, then we
67   * have macro-or-builtin() type call. We adjust
68   * argc to avoid further checking..
69   */
70 	if (argc == 3 && !*(argv[2]))
71 		argc--;
72 
73 	switch (td & ~STATIC) {
74 
75 	case DEFITYPE:
76 		if (argc > 2)
77 			dodefine(argv[2], (argc > 3) ? argv[3] : null);
78 		break;
79 
80 	case PUSDTYPE:
81 		if (argc > 2)
82 			dopushdef(argv[2], (argc > 3) ? argv[3] : null);
83 		break;
84 
85 	case DUMPTYPE:
86 		dodump(argv, argc);
87 		break;
88 
89 	case EXPRTYPE:
90 	/*
91 	 * doexpr - evaluate arithmetic
92 	 * expression
93 	 */
94 		if (argc > 2)
95 			pbnum(expr(argv[2]));
96 		break;
97 
98 	case IFELTYPE:
99 		if (argc > 4)
100 			doifelse(argv, argc);
101 		break;
102 
103 	case IFDFTYPE:
104 	/*
105 	 * doifdef - select one of two
106 	 * alternatives based on the existence of
107 	 * another definition
108 	 */
109 		if (argc > 3) {
110 			if (lookup(argv[2]) != nil)
111 				pbstr(argv[3]);
112 			else if (argc > 4)
113 				pbstr(argv[4]);
114 		}
115 		break;
116 
117 	case LENGTYPE:
118 	/*
119 	 * dolen - find the length of the
120 	 * argument
121 	 */
122 		if (argc > 2)
123 			pbnum((argc > 2) ? strlen(argv[2]) : 0);
124 		break;
125 
126 	case INCRTYPE:
127 	/*
128 	 * doincr - increment the value of the
129 	 * argument
130 	 */
131 		if (argc > 2)
132 			pbnum(atoi(argv[2]) + 1);
133 		break;
134 
135 	case DECRTYPE:
136 	/*
137 	 * dodecr - decrement the value of the
138 	 * argument
139 	 */
140 		if (argc > 2)
141 			pbnum(atoi(argv[2]) - 1);
142 		break;
143 
144 	case SYSCTYPE:
145 	/*
146 	 * dosys - execute system command
147 	 */
148 		if (argc > 2)
149 			sysval = system(argv[2]);
150 		break;
151 
152 	case SYSVTYPE:
153 	/*
154 	 * dosysval - return value of the last
155 	 * system call.
156 	 *
157 	 */
158 		pbnum(sysval);
159 		break;
160 
161 	case INCLTYPE:
162 		if (argc > 2)
163 			if (!doincl(argv[2]))
164 				oops("%s: %s", argv[2], strerror(errno));
165 		break;
166 
167 	case SINCTYPE:
168 		if (argc > 2)
169 			(void) doincl(argv[2]);
170 		break;
171 #ifdef EXTENDED
172 	case PASTTYPE:
173 		if (argc > 2)
174 			if (!dopaste(argv[2]))
175 				oops("%s: %s", argv[2], strerror(errno));
176 		break;
177 
178 	case SPASTYPE:
179 		if (argc > 2)
180 			(void) dopaste(argv[2]);
181 		break;
182 #endif
183 	case CHNQTYPE:
184 		dochq(argv, argc);
185 		break;
186 
187 	case CHNCTYPE:
188 		dochc(argv, argc);
189 		break;
190 
191 	case SUBSTYPE:
192 	/*
193 	 * dosub - select substring
194 	 *
195 	 */
196 		if (argc > 3)
197 			dosub(argv, argc);
198 		break;
199 
200 	case SHIFTYPE:
201 	/*
202 	 * doshift - push back all arguments
203 	 * except the first one (i.e. skip
204 	 * argv[2])
205 	 */
206 		if (argc > 3) {
207 			for (n = argc - 1; n > 3; n--) {
208 				putback(rquote);
209 				pbstr(argv[n]);
210 				putback(lquote);
211 				putback(',');
212 			}
213 			putback(rquote);
214 			pbstr(argv[3]);
215 			putback(lquote);
216 		}
217 		break;
218 
219 	case DIVRTYPE:
220 		if (argc > 2 && (n = atoi(argv[2])) != 0)
221 			dodiv(n);
222 		else {
223 			active = stdout;
224 			oindex = 0;
225 		}
226 		break;
227 
228 	case UNDVTYPE:
229 		doundiv(argv, argc);
230 		break;
231 
232 	case DIVNTYPE:
233 	/*
234 	 * dodivnum - return the number of
235 	 * current output diversion
236 	 */
237 		pbnum(oindex);
238 		break;
239 
240 	case UNDFTYPE:
241 	/*
242 	 * doundefine - undefine a previously
243 	 * defined macro(s) or m4 keyword(s).
244 	 */
245 		if (argc > 2)
246 			for (n = 2; n < argc; n++)
247 				remhash(argv[n], ALL);
248 		break;
249 
250 	case POPDTYPE:
251 	/*
252 	 * dopopdef - remove the topmost
253 	 * definitions of macro(s) or m4
254 	 * keyword(s).
255 	 */
256 		if (argc > 2)
257 			for (n = 2; n < argc; n++)
258 				remhash(argv[n], TOP);
259 		break;
260 
261 	case MKTMTYPE:
262 	/*
263 	 * dotemp - create a temporary file
264 	 */
265 		if (argc > 2)
266 			pbstr(mktemp(argv[2]));
267 		break;
268 
269 	case TRNLTYPE:
270 	/*
271 	 * dotranslit - replace all characters in
272 	 * the source string that appears in the
273 	 * "from" string with the corresponding
274 	 * characters in the "to" string.
275 	 */
276 		if (argc > 3) {
277 			char temp[MAXTOK];
278 			if (argc > 4)
279 				map(temp, argv[2], argv[3], argv[4]);
280 			else
281 				map(temp, argv[2], argv[3], null);
282 			pbstr(temp);
283 		}
284 		else if (argc > 2)
285 			pbstr(argv[2]);
286 		break;
287 
288 	case INDXTYPE:
289 	/*
290 	 * doindex - find the index of the second
291 	 * argument string in the first argument
292 	 * string. -1 if not present.
293 	 */
294 		pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
295 		break;
296 
297 	case ERRPTYPE:
298 	/*
299 	 * doerrp - print the arguments to stderr
300 	 * file
301 	 */
302 		if (argc > 2) {
303 			for (n = 2; n < argc; n++)
304 				fprintf(stderr, "%s ", argv[n]);
305 			fprintf(stderr, "\n");
306 		}
307 		break;
308 
309 	case DNLNTYPE:
310 	/*
311 	 * dodnl - eat-up-to and including
312 	 * newline
313 	 */
314 		while ((c = gpbc()) != '\n' && c != EOF)
315 			;
316 		break;
317 
318 	case M4WRTYPE:
319 	/*
320 	 * dom4wrap - set up for
321 	 * wrap-up/wind-down activity
322 	 */
323 		m4wraps = (argc > 2) ? xstrdup(argv[2]) : null;
324 		break;
325 
326 	case EXITTYPE:
327 	/*
328 	 * doexit - immediate exit from m4.
329 	 */
330 		exit((argc > 2) ? atoi(argv[2]) : 0);
331 		break;
332 
333 	case DEFNTYPE:
334 		if (argc > 2)
335 			for (n = 2; n < argc; n++)
336 				dodefn(argv[n]);
337 		break;
338 
339 	default:
340 		oops("%s: major botch.", "eval");
341 		break;
342 	}
343 }
344 
345 char *dumpfmt = "`%s'\t`%s'\n";	       /* format string for dumpdef   */
346 
347 /*
348  * expand - user-defined macro expansion
349  */
350 void
351 expand(argv, argc)
352 register char *argv[];
353 register int argc;
354 {
355 	register char *t;
356 	register char *p;
357 	register int n;
358 	register int argno;
359 
360 	t = argv[0];		       /* defn string as a whole */
361 	p = t;
362 	while (*p)
363 		p++;
364 	p--;			       /* last character of defn */
365 	while (p > t) {
366 		if (*(p - 1) != ARGFLAG)
367 			putback(*p);
368 		else {
369 			switch (*p) {
370 
371 			case '#':
372 				pbnum(argc - 2);
373 				break;
374 			case '0':
375 			case '1':
376 			case '2':
377 			case '3':
378 			case '4':
379 			case '5':
380 			case '6':
381 			case '7':
382 			case '8':
383 			case '9':
384 				if ((argno = *p - '0') < argc - 1)
385 					pbstr(argv[argno + 1]);
386 				break;
387 			case '*':
388 				for (n = argc - 1; n > 2; n--) {
389 					pbstr(argv[n]);
390 					putback(',');
391 				}
392 				pbstr(argv[2]);
393 				break;
394 			default:
395 				putback(*p);
396 				putback('$');
397 				break;
398 			}
399 			p--;
400 		}
401 		p--;
402 	}
403 	if (p == t)		       /* do last character */
404 		putback(*p);
405 }
406 
407 /*
408  * dodefine - install definition in the table
409  */
410 void
411 dodefine(name, defn)
412 register char *name;
413 register char *defn;
414 {
415 	register ndptr p;
416 
417 	if (!*name)
418 		oops("null definition.");
419 	if (STREQ(name, defn))
420 		oops("%s: recursive definition.", name);
421 	if ((p = lookup(name)) == nil)
422 		p = addent(name);
423 	else if (p->defn != null)
424 		free((char *) p->defn);
425 	if (!*defn)
426 		p->defn = null;
427 	else
428 		p->defn = xstrdup(defn);
429 	p->type = MACRTYPE;
430 }
431 
432 /*
433  * dodefn - push back a quoted definition of
434  *      the given name.
435  */
436 void
437 dodefn(name)
438 char *name;
439 {
440 	register ndptr p;
441 
442 	if ((p = lookup(name)) != nil && p->defn != null) {
443 		putback(rquote);
444 		pbstr(p->defn);
445 		putback(lquote);
446 	}
447 }
448 
449 /*
450  * dopushdef - install a definition in the hash table
451  *      without removing a previous definition. Since
452  *      each new entry is entered in *front* of the
453  *      hash bucket, it hides a previous definition from
454  *      lookup.
455  */
456 void
457 dopushdef(name, defn)
458 register char *name;
459 register char *defn;
460 {
461 	register ndptr p;
462 
463 	if (!*name)
464 		oops("null definition");
465 	if (STREQ(name, defn))
466 		oops("%s: recursive definition.", name);
467 	p = addent(name);
468 	if (!*defn)
469 		p->defn = null;
470 	else
471 		p->defn = xstrdup(defn);
472 	p->type = MACRTYPE;
473 }
474 
475 /*
476  * dodumpdef - dump the specified definitions in the hash
477  *      table to stderr. If nothing is specified, the entire
478  *      hash table is dumped.
479  */
480 void
481 dodump(argv, argc)
482 register char *argv[];
483 register int argc;
484 {
485 	register int n;
486 	ndptr p;
487 
488 	if (argc > 2) {
489 		for (n = 2; n < argc; n++)
490 			if ((p = lookup(argv[n])) != nil)
491 				fprintf(stderr, dumpfmt, p->name,
492 					p->defn);
493 	}
494 	else {
495 		for (n = 0; n < HASHSIZE; n++)
496 			for (p = hashtab[n]; p != nil; p = p->nxtptr)
497 				fprintf(stderr, dumpfmt, p->name,
498 					p->defn);
499 	}
500 }
501 
502 /*
503  * doifelse - select one of two alternatives - loop.
504  */
505 void
506 doifelse(argv, argc)
507 register char *argv[];
508 register int argc;
509 {
510 	cycle {
511 		if (STREQ(argv[2], argv[3]))
512 			pbstr(argv[4]);
513 		else if (argc == 6)
514 			pbstr(argv[5]);
515 		else if (argc > 6) {
516 			argv += 3;
517 			argc -= 3;
518 			continue;
519 		}
520 		break;
521 	}
522 }
523 
524 /*
525  * doinclude - include a given file.
526  */
527 int
528 doincl(ifile)
529 char *ifile;
530 {
531 	if (ilevel + 1 == MAXINP)
532 		oops("too many include files.");
533 	if ((infile[ilevel + 1] = fopen(ifile, "r")) != NULL) {
534 		ilevel++;
535 		bbase[ilevel] = bufbase = bp;
536 		return (1);
537 	}
538 	else
539 		return (0);
540 }
541 
542 #ifdef EXTENDED
543 /*
544  * dopaste - include a given file without any
545  *           macro processing.
546  */
547 int
548 dopaste(pfile)
549 char *pfile;
550 {
551 	FILE *pf;
552 	register int c;
553 
554 	if ((pf = fopen(pfile, "r")) != NULL) {
555 		while ((c = getc(pf)) != EOF)
556 			putc(c, active);
557 		(void) fclose(pf);
558 		return (1);
559 	}
560 	else
561 		return (0);
562 }
563 #endif
564 
565 /*
566  * dochq - change quote characters
567  */
568 void
569 dochq(argv, argc)
570 register char *argv[];
571 register int argc;
572 {
573 	if (argc > 2) {
574 		if (*argv[2])
575 			lquote = *argv[2];
576 		if (argc > 3) {
577 			if (*argv[3])
578 				rquote = *argv[3];
579 		}
580 		else
581 			rquote = lquote;
582 	}
583 	else {
584 		lquote = LQUOTE;
585 		rquote = RQUOTE;
586 	}
587 }
588 
589 /*
590  * dochc - change comment characters
591  */
592 void
593 dochc(argv, argc)
594 register char *argv[];
595 register int argc;
596 {
597 	if (argc > 2) {
598 		if (*argv[2])
599 			scommt = *argv[2];
600 		if (argc > 3) {
601 			if (*argv[3])
602 				ecommt = *argv[3];
603 		}
604 		else
605 			ecommt = ECOMMT;
606 	}
607 	else {
608 		scommt = SCOMMT;
609 		ecommt = ECOMMT;
610 	}
611 }
612 
613 /*
614  * dodivert - divert the output to a temporary file
615  */
616 void
617 dodiv(n)
618 register int n;
619 {
620 	if (n < 0 || n >= MAXOUT)
621 		n = 0;		       /* bitbucket */
622 	if (outfile[n] == NULL) {
623 		m4temp[UNIQUE] = n + '0';
624 		if ((outfile[n] = fopen(m4temp, "w")) == NULL)
625 			oops("%s: cannot divert.", m4temp);
626 	}
627 	oindex = n;
628 	active = outfile[n];
629 }
630 
631 /*
632  * doundivert - undivert a specified output, or all
633  *              other outputs, in numerical order.
634  */
635 void
636 doundiv(argv, argc)
637 register char *argv[];
638 register int argc;
639 {
640 	register int ind;
641 	register int n;
642 
643 	if (argc > 2) {
644 		for (ind = 2; ind < argc; ind++) {
645 			n = atoi(argv[ind]);
646 			if (n > 0 && n < MAXOUT && outfile[n] != NULL)
647 				getdiv(n);
648 
649 		}
650 	}
651 	else
652 		for (n = 1; n < MAXOUT; n++)
653 			if (outfile[n] != NULL)
654 				getdiv(n);
655 }
656 
657 /*
658  * dosub - select substring
659  */
660 void
661 dosub(argv, argc)
662 register char *argv[];
663 register int argc;
664 {
665 	register char *ap, *fc, *k;
666 	register int nc;
667 
668 	if (argc < 5)
669 		nc = MAXTOK;
670 	else
671 #ifdef EXPR
672 		nc = expr(argv[4]);
673 #else
674 		nc = atoi(argv[4]);
675 #endif
676 	ap = argv[2];		       /* target string */
677 #ifdef EXPR
678 	fc = ap + expr(argv[3]);       /* first char */
679 #else
680 	fc = ap + atoi(argv[3]);       /* first char */
681 #endif
682 	if (fc >= ap && fc < ap + strlen(ap))
683 		for (k = fc + min(nc, strlen(fc)) - 1; k >= fc; k--)
684 			putback(*k);
685 }
686 
687 /*
688  * map:
689  * map every character of s1 that is specified in from
690  * into s3 and replace in s. (source s1 remains untouched)
691  *
692  * This is a standard implementation of map(s,from,to) function of ICON
693  * language. Within mapvec, we replace every character of "from" with
694  * the corresponding character in "to". If "to" is shorter than "from",
695  * than the corresponding entries are null, which means that those
696  * characters dissapear altogether. Furthermore, imagine
697  * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
698  * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
699  * ultimately maps to `*'. In order to achieve this effect in an efficient
700  * manner (i.e. without multiple passes over the destination string), we
701  * loop over mapvec, starting with the initial source character. if the
702  * character value (dch) in this location is different than the source
703  * character (sch), sch becomes dch, once again to index into mapvec, until
704  * the character value stabilizes (i.e. sch = dch, in other words
705  * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
706  * character, it will stabilize, since mapvec[0] == 0 at all times. At the
707  * end, we restore mapvec* back to normal where mapvec[n] == n for
708  * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
709  * about 5 times faster than any algorithm that makes multiple passes over
710  * destination string.
711  */
712 void
713 map(dest, src, from, to)
714 register char *dest;
715 register char *src;
716 register char *from;
717 register char *to;
718 {
719 	register char *tmp;
720 	register char sch, dch;
721 	static char mapvec[128] = {
722 		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
723 		12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
724 		24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
725 		36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
726 		48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
727 		60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
728 		72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
729 		84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
730 		96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
731 		108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
732 		120, 121, 122, 123, 124, 125, 126, 127
733 	};
734 
735 	if (*src) {
736 		tmp = from;
737 	/*
738 	 * create a mapping between "from" and
739 	 * "to"
740 	 */
741 		while (*from)
742 			mapvec[*from++] = (*to) ? *to++ : (char) 0;
743 
744 		while (*src) {
745 			sch = *src++;
746 			dch = mapvec[sch];
747 			while (dch != sch) {
748 				sch = dch;
749 				dch = mapvec[sch];
750 			}
751 			if (*dest = dch)
752 				dest++;
753 		}
754 	/*
755 	 * restore all the changed characters
756 	 */
757 		while (*tmp) {
758 			mapvec[*tmp] = *tmp;
759 			tmp++;
760 		}
761 	}
762 	*dest = (char) 0;
763 }
764