1 /* $OpenBSD: eval.c,v 1.44 2002/04/26 16:15:16 espie Exp $ */
2 /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
9 * Ozan Yigit at York University.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 static char sccsid[] = "@(#)eval.c 8.2 (Berkeley) 4/27/95";
45 static char rcsid[] = "$OpenBSD: eval.c,v 1.44 2002/04/26 16:15:16 espie Exp $";
50 #include <sys/cdefs.h>
51 __FBSDID("$FreeBSD: src/usr.bin/m4/eval.c,v 1.10.2.5 2002/07/15 02:06:15 jmallett Exp $");
55 * Facility: m4 macro processor
59 #include <sys/types.h>
71 #include "pathnames.h"
73 #define BUILTIN_MARKER "__builtin_"
75 static void dodefn(const char *);
76 static void dopushdef(const char *, const char *);
77 static void dodump(const char *[], int);
78 static void dotrace(const char *[], int, int);
79 static void doifelse(const char *[], int);
80 static int doincl(const char *);
81 static int dopaste(const char *);
82 static void gnu_dochq(const char *[], int);
83 static void dochq(const char *[], int);
84 static void gnu_dochc(const char *[], int);
85 static void dochc(const char *[], int);
86 static void dodiv(int);
87 static void doundiv(const char *[], int);
88 static void dosub(const char *[], int);
89 static void map(char *, const char *, const char *, const char *);
90 static const char *handledash(char *, char *, const char *);
91 static void expand_builtin(const char *[], int, int);
92 static void expand_macro(const char *[], int);
93 static void dump_one_def(ndptr);
95 unsigned long expansion_id;
98 * eval - eval all macros and builtins calls
99 * argc - number of elements in argv.
100 * argv - element vector :
101 * argv[0] = definition of a user
102 * macro or nil if built-in.
103 * argv[1] = name of the macro or
105 * argv[2] = parameters to user-defined
106 * . macro or built-in.
109 * A call in the form of macro-or-builtin() will result in:
111 * argv[1] = macro-or-builtin
114 * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
117 eval(const char *argv[], int argc, int td)
123 errx(1, "%s at line %lu: expanding recursive definition for %s",
124 CURRENT_NAME, CURRENT_LINE, argv[1]);
125 if (traced_macros && is_traced(argv[1]))
126 mark = trace(argv, argc, infile+ilevel);
128 expand_macro(argv, argc);
130 expand_builtin(argv, argc, td);
136 * expand_builtin - evaluate built-in macros.
139 expand_builtin(const char *argv[], int argc, int td)
143 static int sysval = 0;
146 printf("argc = %d\n", argc);
147 for (n = 0; n < argc; n++)
148 printf("argv[%d] = %s\n", n, argv[n]);
153 * if argc == 3 and argv[2] is null, then we
154 * have macro-or-builtin() type call. We adjust
155 * argc to avoid further checking..
159 if (argc == 3 && !*(argv[2]))
162 switch (td & TYPEMASK) {
166 dodefine(argv[2], (argc > 3) ? argv[3] : null);
171 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
179 dotrace(argv, argc, 1);
183 dotrace(argv, argc, 0);
188 * doexpr - evaluate arithmetic
192 pbnum(expr(argv[2]));
197 doifelse(argv, argc);
202 * doifdef - select one of two
203 * alternatives based on the existence of
207 if (lookup(argv[2]) != nil)
216 * dolen - find the length of the
219 pbnum((argc > 2) ? strlen(argv[2]) : 0);
224 * doincr - increment the value of the
228 pbnum(atoi(argv[2]) + 1);
233 * dodecr - decrement the value of the
237 pbnum(atoi(argv[2]) - 1);
242 * dosys - execute system command
245 sysval = system(argv[2]);
250 * dosysval - return value of the last
263 if (!doincl(argv[2]))
264 err(1, "%s at line %lu: include(%s)",
265 CURRENT_NAME, CURRENT_LINE, argv[2]);
270 (void) doincl(argv[2]);
275 if (!dopaste(argv[2]))
276 err(1, "%s at line %lu: paste(%s)",
277 CURRENT_NAME, CURRENT_LINE, argv[2]);
282 (void) dopaste(argv[2]);
301 * dosub - select substring
310 * doshift - push back all arguments
311 * except the first one (i.e. skip
315 for (n = argc - 1; n > 3; n--) {
328 if (argc > 2 && (n = atoi(argv[2])) != 0)
342 * dodivnum - return the number of
343 * current output diversion
350 * doundefine - undefine a previously
351 * defined macro(s) or m4 keyword(s).
354 for (n = 2; n < argc; n++)
355 remhash(argv[n], ALL);
360 * dopopdef - remove the topmost
361 * definitions of macro(s) or m4
365 for (n = 2; n < argc; n++)
366 remhash(argv[n], TOP);
371 * dotemp - create a temporary file
377 temp = xstrdup(argv[2]);
382 "%s at line %lu: couldn't make temp file %s",
383 CURRENT_NAME, CURRENT_LINE, argv[2]);
392 * dotranslit - replace all characters in
393 * the source string that appears in the
394 * "from" string with the corresponding
395 * characters in the "to" string.
400 temp = xalloc(strlen(argv[2])+1);
402 map(temp, argv[2], argv[3], argv[4]);
404 map(temp, argv[2], argv[3], null);
413 * doindex - find the index of the second
414 * argument string in the first argument
415 * string. -1 if not present.
417 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
422 * doerrp - print the arguments to stderr
426 for (n = 2; n < argc; n++)
427 fprintf(stderr, "%s ", argv[n]);
428 fprintf(stderr, "\n");
434 * dodnl - eat-up-to and including
437 while ((c = gpbc()) != '\n' && c != EOF)
443 * dom4wrap - set up for
444 * wrap-up/wind-down activity
446 m4wraps = (argc > 2) ? xstrdup(argv[2]) : null;
451 * doexit - immediate exit from m4.
454 exit((argc > 2) ? atoi(argv[2]) : 0);
459 for (n = 2; n < argc; n++)
463 case INDIRTYPE: /* Indirect call */
468 case BUILTINTYPE: /* Builtins only */
470 dobuiltin(argv, argc);
475 dopatsubst(argv, argc);
479 doregexp(argv, argc);
482 doprintlineno(infile+ilevel);
485 doprintfilename(infile+ilevel);
493 errx(1, "%s at line %lu: eval: major botch.",
494 CURRENT_NAME, CURRENT_LINE);
500 * expand_macro - user-defined macro expansion
503 expand_macro(const char *argv[], int argc)
510 t = argv[0]; /* defn string as a whole */
514 p--; /* last character of defn */
516 if (*(p - 1) != ARGFLAG)
534 if ((argno = *p - '0') < argc - 1)
535 pbstr(argv[argno + 1]);
539 for (n = argc - 1; n > 2; n--) {
548 for (n = argc - 1; n > 2; n--) {
568 if (p == t) /* do last character */
573 * dodefine - install definition in the table
576 dodefine(const char *name, const char *defn)
582 errx(1, "%s at line %lu: null definition.", CURRENT_NAME,
584 if ((p = lookup(name)) == nil)
586 else if (p->defn != null)
587 free((char *) p->defn);
588 if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0) {
589 n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1);
591 p->type = n & TYPEMASK;
592 if ((n & NOARGS) == 0)
594 p->defn = xstrdup(null);
599 p->defn = xstrdup(null);
601 p->defn = xstrdup(defn);
603 if (STREQ(name, defn))
608 * dodefn - push back a quoted definition of
612 dodefn(const char *name)
617 if ((p = lookup(name)) != nil) {
618 if (p->defn != null) {
622 } else if ((real = builtin_realname(p->type)) != NULL) {
624 pbstr(BUILTIN_MARKER);
630 * dopushdef - install a definition in the hash table
631 * without removing a previous definition. Since
632 * each new entry is entered in *front* of the
633 * hash bucket, it hides a previous definition from
637 dopushdef(const char *name, const char *defn)
642 errx(1, "%s at line %lu: null definition", CURRENT_NAME,
646 p->defn = xstrdup(null);
648 p->defn = xstrdup(defn);
650 if (STREQ(name, defn))
655 * dump_one_def - dump the specified definition.
658 dump_one_def(ndptr p)
663 if ((p->type & TYPEMASK) == MACRTYPE)
664 fprintf(traceout, "%s:\t%s\n", p->name, p->defn);
666 real = builtin_realname(p->type);
669 fprintf(traceout, "%s:\t<%s>\n", p->name, real);
672 fprintf(traceout, "`%s'\t`%s'\n", p->name, p->defn);
676 * dodumpdef - dump the specified definitions in the hash
677 * table to stderr. If nothing is specified, the entire
678 * hash table is dumped.
681 dodump(const char *argv[], int argc)
687 for (n = 2; n < argc; n++)
688 if ((p = lookup(argv[n])) != nil)
691 for (n = 0; n < HASHSIZE; n++)
692 for (p = hashtab[n]; p != nil; p = p->nxtptr)
698 * dotrace - mark some macros as traced/untraced depending upon on.
701 dotrace(const char *argv[], int argc, int on)
706 for (n = 2; n < argc; n++)
707 mark_traced(argv[n], on);
709 mark_traced(NULL, on);
713 * doifelse - select one of two alternatives - loop.
716 doifelse(const char *argv[], int argc)
719 if (STREQ(argv[2], argv[3]))
733 * doinclude - include a given file.
736 doincl(const char *ifile)
738 if (ilevel + 1 == MAXINP)
739 errx(1, "%s at line %lu: too many include files.",
740 CURRENT_NAME, CURRENT_LINE);
741 if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
743 if ((inname[ilevel] = strdup(ifile)) == NULL)
745 inlineno[ilevel] = 1;
746 bbase[ilevel] = bufbase = bp;
755 * dopaste - include a given file without any
759 dopaste(const char *pfile)
764 if ((pf = fopen(pfile, "r")) != NULL) {
765 fprintf(active, "#line 1 \"%s\"\n", pfile);
766 while ((c = getc(pf)) != EOF)
777 gnu_dochq(const char *argv[], int ac)
779 /* In gnu-m4 mode, the only way to restore quotes is to have no
780 * arguments at all. */
782 lquote[0] = LQUOTE, lquote[1] = EOS;
783 rquote[0] = RQUOTE, rquote[1] = EOS;
785 strlcpy(lquote, argv[2], sizeof(lquote));
787 strlcpy(rquote, argv[3], sizeof(rquote));
794 * dochq - change quote characters
797 dochq(const char *argv[], int argc)
801 strlcpy(lquote, argv[2], sizeof(lquote));
808 strlcpy(rquote, argv[3], sizeof(rquote));
810 strcpy(rquote, lquote);
812 lquote[0] = LQUOTE, lquote[1] = EOS;
813 rquote[0] = RQUOTE, rquote[1] = EOS;
818 gnu_dochc(const char *argv[], int ac)
820 /* In gnu-m4 mode, no arguments mean no comment
821 * arguments at all. */
827 strlcpy(scommt, argv[2], sizeof(scommt));
829 scommt[0] = SCOMMT, scommt[1] = EOS;
830 if(ac > 3 && *argv[3])
831 strlcpy(ecommt, argv[3], sizeof(ecommt));
833 ecommt[0] = ECOMMT, ecommt[1] = EOS;
837 * dochc - change comment characters
840 dochc(const char *argv[], int argc)
844 strlcpy(scommt, argv[2], sizeof(scommt));
847 strlcpy(ecommt, argv[3], sizeof(ecommt));
850 ecommt[0] = ECOMMT, ecommt[1] = EOS;
853 scommt[0] = SCOMMT, scommt[1] = EOS;
854 ecommt[0] = ECOMMT, ecommt[1] = EOS;
859 * dodivert - divert the output to a temporary file
871 n = 0; /* bitbucket */
875 n = 0; /* bitbucket */
876 if (outfile[n] == NULL) {
877 char fname[] = _PATH_DIVNAME;
879 if ((fd = mkstemp(fname)) < 0 ||
880 (outfile[n] = fdopen(fd, "w+")) == NULL)
881 err(1, "%s: cannot divert", fname);
882 if (unlink(fname) == -1)
883 err(1, "%s: cannot unlink", fname);
889 * doundivert - undivert a specified output, or all
890 * other outputs, in numerical order.
893 doundiv(const char *argv[], int argc)
899 for (ind = 2; ind < argc; ind++) {
901 if (n > 0 && n < maxout && outfile[n] != NULL)
907 for (n = 1; n < maxout; n++)
908 if (outfile[n] != NULL)
913 * dosub - select substring
916 dosub(const char *argv[], int argc)
918 const char *ap, *fc, *k;
921 ap = argv[2]; /* target string */
923 fc = ap + expr(argv[3]); /* first char */
925 fc = ap + atoi(argv[3]); /* first char */
930 nc = min(nc, expr(argv[4]));
932 nc = min(nc, atoi(argv[4]));
934 if (fc >= ap && fc < ap + strlen(ap))
935 for (k = fc + nc - 1; k >= fc; k--)
941 * map every character of s1 that is specified in from
942 * into s3 and replace in s. (source s1 remains untouched)
944 * This is a standard implementation of map(s,from,to) function of ICON
945 * language. Within mapvec, we replace every character of "from" with
946 * the corresponding character in "to". If "to" is shorter than "from",
947 * than the corresponding entries are null, which means that those
948 * characters dissapear altogether. Furthermore, imagine
949 * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
950 * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
951 * ultimately maps to `*'. In order to achieve this effect in an efficient
952 * manner (i.e. without multiple passes over the destination string), we
953 * loop over mapvec, starting with the initial source character. if the
954 * character value (dch) in this location is different than the source
955 * character (sch), sch becomes dch, once again to index into mapvec, until
956 * the character value stabilizes (i.e. sch = dch, in other words
957 * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
958 * character, it will stabilize, since mapvec[0] == 0 at all times. At the
959 * end, we restore mapvec* back to normal where mapvec[n] == n for
960 * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
961 * about 5 times faster than any algorithm that makes multiple passes over
962 * destination string.
965 map(char *dest, const char *src, const char *from, const char *to)
968 unsigned char sch, dch;
969 static char frombis[257];
970 static char tobis[257];
971 static unsigned char mapvec[256] = {
972 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
973 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
974 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
975 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
976 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
977 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
978 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
979 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
980 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
981 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
982 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
983 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
984 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
985 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
986 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
987 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
988 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
989 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
995 * expand character ranges on the fly
997 from = handledash(frombis, frombis + 256, from);
998 to = handledash(tobis, tobis + 256, to);
1002 * create a mapping between "from" and
1006 mapvec[(unsigned char)(*from++)] = (*to) ?
1007 (unsigned char)(*to++) : 0;
1010 sch = (unsigned char)(*src++);
1012 while (dch != sch) {
1016 if ((*dest = (char)dch))
1020 * restore all the changed characters
1023 mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
1033 * use buffer to copy the src string, expanding character ranges
1037 handledash(char *buffer, char *end, const char *src)
1043 if (src[1] == '-' && src[2]) {
1045 for (i = (unsigned char)src[0];
1046 i <= (unsigned char)src[2]; i++) {