xref: /original-bsd/usr.bin/m4/eval.c (revision 0842ddeb)
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.2 (Berkeley) 04/27/95";
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 		killdiv();
331 		exit((argc > 2) ? atoi(argv[2]) : 0);
332 		break;
333 
334 	case DEFNTYPE:
335 		if (argc > 2)
336 			for (n = 2; n < argc; n++)
337 				dodefn(argv[n]);
338 		break;
339 
340 	default:
341 		oops("%s: major botch.", "eval");
342 		break;
343 	}
344 }
345 
346 char *dumpfmt = "`%s'\t`%s'\n";	       /* format string for dumpdef   */
347 
348 /*
349  * expand - user-defined macro expansion
350  */
351 void
352 expand(argv, argc)
353 register char *argv[];
354 register int argc;
355 {
356 	register char *t;
357 	register char *p;
358 	register int n;
359 	register int argno;
360 
361 	t = argv[0];		       /* defn string as a whole */
362 	p = t;
363 	while (*p)
364 		p++;
365 	p--;			       /* last character of defn */
366 	while (p > t) {
367 		if (*(p - 1) != ARGFLAG)
368 			putback(*p);
369 		else {
370 			switch (*p) {
371 
372 			case '#':
373 				pbnum(argc - 2);
374 				break;
375 			case '0':
376 			case '1':
377 			case '2':
378 			case '3':
379 			case '4':
380 			case '5':
381 			case '6':
382 			case '7':
383 			case '8':
384 			case '9':
385 				if ((argno = *p - '0') < argc - 1)
386 					pbstr(argv[argno + 1]);
387 				break;
388 			case '*':
389 				for (n = argc - 1; n > 2; n--) {
390 					pbstr(argv[n]);
391 					putback(',');
392 				}
393 				pbstr(argv[2]);
394 				break;
395 			default:
396 				putback(*p);
397 				putback('$');
398 				break;
399 			}
400 			p--;
401 		}
402 		p--;
403 	}
404 	if (p == t)		       /* do last character */
405 		putback(*p);
406 }
407 
408 /*
409  * dodefine - install definition in the table
410  */
411 void
412 dodefine(name, defn)
413 register char *name;
414 register char *defn;
415 {
416 	register ndptr p;
417 
418 	if (!*name)
419 		oops("null definition.");
420 	if (STREQ(name, defn))
421 		oops("%s: recursive definition.", name);
422 	if ((p = lookup(name)) == nil)
423 		p = addent(name);
424 	else if (p->defn != null)
425 		free((char *) p->defn);
426 	if (!*defn)
427 		p->defn = null;
428 	else
429 		p->defn = xstrdup(defn);
430 	p->type = MACRTYPE;
431 }
432 
433 /*
434  * dodefn - push back a quoted definition of
435  *      the given name.
436  */
437 void
438 dodefn(name)
439 char *name;
440 {
441 	register ndptr p;
442 
443 	if ((p = lookup(name)) != nil && p->defn != null) {
444 		putback(rquote);
445 		pbstr(p->defn);
446 		putback(lquote);
447 	}
448 }
449 
450 /*
451  * dopushdef - install a definition in the hash table
452  *      without removing a previous definition. Since
453  *      each new entry is entered in *front* of the
454  *      hash bucket, it hides a previous definition from
455  *      lookup.
456  */
457 void
458 dopushdef(name, defn)
459 register char *name;
460 register char *defn;
461 {
462 	register ndptr p;
463 
464 	if (!*name)
465 		oops("null definition");
466 	if (STREQ(name, defn))
467 		oops("%s: recursive definition.", name);
468 	p = addent(name);
469 	if (!*defn)
470 		p->defn = null;
471 	else
472 		p->defn = xstrdup(defn);
473 	p->type = MACRTYPE;
474 }
475 
476 /*
477  * dodumpdef - dump the specified definitions in the hash
478  *      table to stderr. If nothing is specified, the entire
479  *      hash table is dumped.
480  */
481 void
482 dodump(argv, argc)
483 register char *argv[];
484 register int argc;
485 {
486 	register int n;
487 	ndptr p;
488 
489 	if (argc > 2) {
490 		for (n = 2; n < argc; n++)
491 			if ((p = lookup(argv[n])) != nil)
492 				fprintf(stderr, dumpfmt, p->name,
493 					p->defn);
494 	}
495 	else {
496 		for (n = 0; n < HASHSIZE; n++)
497 			for (p = hashtab[n]; p != nil; p = p->nxtptr)
498 				fprintf(stderr, dumpfmt, p->name,
499 					p->defn);
500 	}
501 }
502 
503 /*
504  * doifelse - select one of two alternatives - loop.
505  */
506 void
507 doifelse(argv, argc)
508 register char *argv[];
509 register int argc;
510 {
511 	cycle {
512 		if (STREQ(argv[2], argv[3]))
513 			pbstr(argv[4]);
514 		else if (argc == 6)
515 			pbstr(argv[5]);
516 		else if (argc > 6) {
517 			argv += 3;
518 			argc -= 3;
519 			continue;
520 		}
521 		break;
522 	}
523 }
524 
525 /*
526  * doinclude - include a given file.
527  */
528 int
529 doincl(ifile)
530 char *ifile;
531 {
532 	if (ilevel + 1 == MAXINP)
533 		oops("too many include files.");
534 	if ((infile[ilevel + 1] = fopen(ifile, "r")) != NULL) {
535 		ilevel++;
536 		bbase[ilevel] = bufbase = bp;
537 		return (1);
538 	}
539 	else
540 		return (0);
541 }
542 
543 #ifdef EXTENDED
544 /*
545  * dopaste - include a given file without any
546  *           macro processing.
547  */
548 int
549 dopaste(pfile)
550 char *pfile;
551 {
552 	FILE *pf;
553 	register int c;
554 
555 	if ((pf = fopen(pfile, "r")) != NULL) {
556 		while ((c = getc(pf)) != EOF)
557 			putc(c, active);
558 		(void) fclose(pf);
559 		return (1);
560 	}
561 	else
562 		return (0);
563 }
564 #endif
565 
566 /*
567  * dochq - change quote characters
568  */
569 void
570 dochq(argv, argc)
571 register char *argv[];
572 register int argc;
573 {
574 	if (argc > 2) {
575 		if (*argv[2])
576 			lquote = *argv[2];
577 		if (argc > 3) {
578 			if (*argv[3])
579 				rquote = *argv[3];
580 		}
581 		else
582 			rquote = lquote;
583 	}
584 	else {
585 		lquote = LQUOTE;
586 		rquote = RQUOTE;
587 	}
588 }
589 
590 /*
591  * dochc - change comment characters
592  */
593 void
594 dochc(argv, argc)
595 register char *argv[];
596 register int argc;
597 {
598 	if (argc > 2) {
599 		if (*argv[2])
600 			scommt = *argv[2];
601 		if (argc > 3) {
602 			if (*argv[3])
603 				ecommt = *argv[3];
604 		}
605 		else
606 			ecommt = ECOMMT;
607 	}
608 	else {
609 		scommt = SCOMMT;
610 		ecommt = ECOMMT;
611 	}
612 }
613 
614 /*
615  * dodivert - divert the output to a temporary file
616  */
617 void
618 dodiv(n)
619 register int n;
620 {
621 	if (n < 0 || n >= MAXOUT)
622 		n = 0;		       /* bitbucket */
623 	if (outfile[n] == NULL) {
624 		m4temp[UNIQUE] = n + '0';
625 		if ((outfile[n] = fopen(m4temp, "w")) == NULL)
626 			oops("%s: cannot divert.", m4temp);
627 	}
628 	oindex = n;
629 	active = outfile[n];
630 }
631 
632 /*
633  * doundivert - undivert a specified output, or all
634  *              other outputs, in numerical order.
635  */
636 void
637 doundiv(argv, argc)
638 register char *argv[];
639 register int argc;
640 {
641 	register int ind;
642 	register int n;
643 
644 	if (argc > 2) {
645 		for (ind = 2; ind < argc; ind++) {
646 			n = atoi(argv[ind]);
647 			if (n > 0 && n < MAXOUT && outfile[n] != NULL)
648 				getdiv(n);
649 
650 		}
651 	}
652 	else
653 		for (n = 1; n < MAXOUT; n++)
654 			if (outfile[n] != NULL)
655 				getdiv(n);
656 }
657 
658 /*
659  * dosub - select substring
660  */
661 void
662 dosub(argv, argc)
663 register char *argv[];
664 register int argc;
665 {
666 	register char *ap, *fc, *k;
667 	register int nc;
668 
669 	if (argc < 5)
670 		nc = MAXTOK;
671 	else
672 #ifdef EXPR
673 		nc = expr(argv[4]);
674 #else
675 		nc = atoi(argv[4]);
676 #endif
677 	ap = argv[2];		       /* target string */
678 #ifdef EXPR
679 	fc = ap + expr(argv[3]);       /* first char */
680 #else
681 	fc = ap + atoi(argv[3]);       /* first char */
682 #endif
683 	if (fc >= ap && fc < ap + strlen(ap))
684 		for (k = fc + min(nc, strlen(fc)) - 1; k >= fc; k--)
685 			putback(*k);
686 }
687 
688 /*
689  * map:
690  * map every character of s1 that is specified in from
691  * into s3 and replace in s. (source s1 remains untouched)
692  *
693  * This is a standard implementation of map(s,from,to) function of ICON
694  * language. Within mapvec, we replace every character of "from" with
695  * the corresponding character in "to". If "to" is shorter than "from",
696  * than the corresponding entries are null, which means that those
697  * characters dissapear altogether. Furthermore, imagine
698  * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
699  * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
700  * ultimately maps to `*'. In order to achieve this effect in an efficient
701  * manner (i.e. without multiple passes over the destination string), we
702  * loop over mapvec, starting with the initial source character. if the
703  * character value (dch) in this location is different than the source
704  * character (sch), sch becomes dch, once again to index into mapvec, until
705  * the character value stabilizes (i.e. sch = dch, in other words
706  * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
707  * character, it will stabilize, since mapvec[0] == 0 at all times. At the
708  * end, we restore mapvec* back to normal where mapvec[n] == n for
709  * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
710  * about 5 times faster than any algorithm that makes multiple passes over
711  * destination string.
712  */
713 void
714 map(dest, src, from, to)
715 register char *dest;
716 register char *src;
717 register char *from;
718 register char *to;
719 {
720 	register char *tmp;
721 	register char sch, dch;
722 	static char mapvec[128] = {
723 		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
724 		12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
725 		24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
726 		36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
727 		48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
728 		60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
729 		72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
730 		84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
731 		96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
732 		108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
733 		120, 121, 122, 123, 124, 125, 126, 127
734 	};
735 
736 	if (*src) {
737 		tmp = from;
738 	/*
739 	 * create a mapping between "from" and
740 	 * "to"
741 	 */
742 		while (*from)
743 			mapvec[*from++] = (*to) ? *to++ : (char) 0;
744 
745 		while (*src) {
746 			sch = *src++;
747 			dch = mapvec[sch];
748 			while (dch != sch) {
749 				sch = dch;
750 				dch = mapvec[sch];
751 			}
752 			if (*dest = dch)
753 				dest++;
754 		}
755 	/*
756 	 * restore all the changed characters
757 	 */
758 		while (*tmp) {
759 			mapvec[*tmp] = *tmp;
760 			tmp++;
761 		}
762 	}
763 	*dest = (char) 0;
764 }
765