2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Ozan Yigit at York University.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 static char sccsid[] = "@(#)eval.c 8.1 (Berkeley) 6/6/93";
41 static const char rcsid[] =
47 * Facility: m4 macro processor
51 #include <sys/types.h>
60 #include "pathnames.h"
63 * eval - evaluate built-in macros.
64 * argc - number of elements in argv.
65 * argv - element vector :
66 * argv[0] = definition of a user
67 * macro or nil if built-in.
68 * argv[1] = name of the macro or
70 * argv[2] = parameters to user-defined
71 * . macro or built-in.
74 * Note that the minimum value for argc is 3. A call in the form
75 * of macro-or-builtin() will result in:
77 * argv[1] = macro-or-builtin
83 register char *argv[];
88 static int sysval = 0;
91 printf("argc = %d\n", argc);
92 for (n = 0; n < argc; n++)
93 printf("argv[%d] = %s\n", n, argv[n]);
96 * if argc == 3 and argv[2] is null, then we
97 * have macro-or-builtin() type call. We adjust
98 * argc to avoid further checking..
100 if (argc == 3 && !*(argv[2]))
103 switch (td & ~STATIC) {
107 dodefine(argv[2], (argc > 3) ? argv[3] : null);
112 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
121 * doexpr - evaluate arithmetic
125 pbnum(expr(argv[2]));
130 doifelse(argv, argc);
135 * doifdef - select one of two
136 * alternatives based on the existence of
140 if (lookup(argv[2]) != nil)
149 * dolen - find the length of the
153 pbnum((argc > 2) ? strlen(argv[2]) : 0);
158 * doincr - increment the value of the
162 pbnum(atoi(argv[2]) + 1);
167 * dodecr - decrement the value of the
171 pbnum(atoi(argv[2]) - 1);
176 * dosys - execute system command
178 /* Make sure m4 output is NOT interrupted */
182 sysval = system(argv[2]);
187 * dosysval - return value of the last
196 if (!doincl(argv[2]))
197 err(1, "%s", argv[2]);
202 (void) doincl(argv[2]);
207 if (!dopaste(argv[2]))
208 err(1, "%s", argv[2]);
213 (void) dopaste(argv[2]);
226 * dosub - select substring
235 * doshift - push back all arguments
236 * except the first one (i.e. skip
240 for (n = argc - 1; n > 3; n--) {
253 if (argc > 2 && (n = atoi(argv[2])) != 0)
267 * dodivnum - return the number of
268 * current output diversion
275 * doundefine - undefine a previously
276 * defined macro(s) or m4 keyword(s).
279 for (n = 2; n < argc; n++)
280 remhash(argv[n], ALL);
285 * dopopdef - remove the topmost
286 * definitions of macro(s) or m4
290 for (n = 2; n < argc; n++)
291 remhash(argv[n], TOP);
296 * dotemp - create a temporary file
299 pbstr(mktemp(argv[2]));
304 * dotranslit - replace all characters in
305 * the source string that appears in the
306 * "from" string with the corresponding
307 * characters in the "to" string.
310 char temp[STRSPMAX+1];
312 map(temp, argv[2], argv[3], argv[4]);
314 map(temp, argv[2], argv[3], null);
323 * doindex - find the index of the second
324 * argument string in the first argument
325 * string. -1 if not present.
327 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
332 * doerrp - print the arguments to stderr
336 for (n = 2; n < argc; n++)
337 fprintf(stderr, "%s ", argv[n]);
338 fprintf(stderr, "\n");
344 * dodnl - eat-up-to and including
347 while ((c = gpbc()) != '\n' && c != EOF)
353 * dom4wrap - set up for
354 * wrap-up/wind-down activity
356 m4wraps = (argc > 2) ? xstrdup(argv[2]) : null;
361 * doexit - immediate exit from m4.
364 exit((argc > 2) ? atoi(argv[2]) : 0);
369 for (n = 2; n < argc; n++)
378 errx(1, "eval: major botch");
383 char *dumpfmt = "`%s'\t`%s'\n"; /* format string for dumpdef */
386 * expand - user-defined macro expansion
390 register char *argv[];
393 register unsigned char *t;
394 register unsigned char *p;
398 t = argv[0]; /* defn string as a whole */
402 p--; /* last character of defn */
404 if (*(p - 1) != ARGFLAG)
422 if ((argno = *p - '0') < argc - 1)
423 pbstr(argv[argno + 1]);
426 for (n = argc - 1; n > 2; n--) {
433 for( n = argc - 1; n >= 2; n-- )
451 if (p == t) /* do last character */
456 * dodefine - install definition in the table
466 errx(1, "null definition");
467 if (STREQ(name, defn))
468 errx(1, "%s: recursive definition", name);
469 if ((p = lookup(name)) == nil)
471 else if (p->defn != null)
472 free((char *) p->defn);
476 p->defn = xstrdup(defn);
481 * dodefn - push back a quoted definition of
490 if ((p = lookup(name)) != nil && p->defn != null) {
498 * dopushdef - install a definition in the hash table
499 * without removing a previous definition. Since
500 * each new entry is entered in *front* of the
501 * hash bucket, it hides a previous definition from
505 dopushdef(name, defn)
512 errx(1, "null definition");
513 if (STREQ(name, defn))
514 errx(1, "%s: recursive definition", name);
519 p->defn = xstrdup(defn);
524 * dodumpdef - dump the specified definitions in the hash
525 * table to stderr. If nothing is specified, the entire
526 * hash table is dumped.
530 register char *argv[];
537 for (n = 2; n < argc; n++)
538 if ((p = lookup(argv[n])) != nil)
539 fprintf(stderr, dumpfmt, p->name,
543 for (n = 0; n < HASHSIZE; n++)
544 for (p = hashtab[n]; p != nil; p = p->nxtptr)
545 fprintf(stderr, dumpfmt, p->name,
551 * doifelse - select one of two alternatives - loop.
555 register char *argv[];
559 if (STREQ(argv[2], argv[3]))
573 * doinclude - include a given file.
579 if (ilevel + 1 == MAXINP)
580 errx(1, "too many include files");
581 if ((infile[ilevel + 1] = fopen(ifile, "r")) != NULL) {
583 bbase[ilevel] = bufbase = bp;
592 * dopaste - include a given file without any
602 if ((pf = fopen(pfile, "r")) != NULL) {
603 while ((c = getc(pf)) != EOF)
614 * dochq - change quote characters
618 register char *argv[];
642 * dochc - change comment characters
646 register char *argv[];
666 * dodivert - divert the output to a temporary file
673 if (n < 0 || n >= MAXOUT)
674 n = 0; /* bitbucket */
675 if (outfile[n] == NULL) {
676 m4temp[UNIQUE] = n + '0';
677 if ((outfile[n] = fopen(m4temp, "w")) == NULL)
678 errx(1, "%s: cannot divert", m4temp);
684 * doundivert - undivert a specified output, or all
685 * other outputs, in numerical order.
689 register char *argv[];
696 for (ind = 2; ind < argc; ind++) {
698 if (n > 0 && n < MAXOUT && outfile[n] != NULL)
704 for (n = 1; n < MAXOUT; n++)
705 if (outfile[n] != NULL)
710 * dosub - select substring
714 register char *argv[];
717 register unsigned char *ap, *fc, *k;
728 ap = argv[2]; /* target string */
730 fc = ap + expr(argv[3]); /* first char */
732 fc = ap + atoi(argv[3]); /* first char */
734 if (fc >= ap && fc < ap + strlen(ap))
735 for (k = fc + min(nc, strlen(fc)) - 1; k >= fc; k--)
741 * map every character of s1 that is specified in from
742 * into s3 and replace in s. (source s1 remains untouched)
744 * This is a standard implementation of map(s,from,to) function of ICON
745 * language. Within mapvec, we replace every character of "from" with
746 * the corresponding character in "to". If "to" is shorter than "from",
747 * than the corresponding entries are null, which means that those
748 * characters dissapear altogether. Furthermore, imagine
749 * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
750 * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
751 * ultimately maps to `*'. In order to achieve this effect in an efficient
752 * manner (i.e. without multiple passes over the destination string), we
753 * loop over mapvec, starting with the initial source character. if the
754 * character value (dch) in this location is different than the source
755 * character (sch), sch becomes dch, once again to index into mapvec, until
756 * the character value stabilizes (i.e. sch = dch, in other words
757 * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
758 * character, it will stabilize, since mapvec[0] == 0 at all times. At the
759 * end, we restore mapvec* back to normal where mapvec[n] == n for
760 * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
761 * about 5 times faster than any algorithm that makes multiple passes over
762 * destination string.
765 map(dest, src, from, to)
772 register char sch, dch;
773 static char mapvec[128] = {
774 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
775 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
776 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
777 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
778 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
779 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
780 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
781 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
782 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
783 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
784 120, 121, 122, 123, 124, 125, 126, 127
790 * create a mapping between "from" and
794 mapvec[*from++] = (*to) ? *to++ : (char) 0;
807 * restore all the changed characters