1 /* $OpenBSD: eval.c,v 1.78 2019/06/28 05:35:34 deraadt Exp $ */
2 /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */
5 * SPDX-License-Identifier: BSD-3-Clause
7 * Copyright (c) 1989, 1993
8 * The Regents of the University of California. All rights reserved.
10 * This code is derived from software contributed to Berkeley by
11 * Ozan Yigit at York University.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
44 * Facility: m4 macro processor
48 #include <sys/types.h>
62 #include "pathnames.h"
64 static void dodefn(const char *);
65 static void dopushdef(const char *, const char *);
66 static void dodump(const char *[], int);
67 static void dotrace(const char *[], int, int);
68 static void doifelse(const char *[], int);
69 static int doincl(const char *);
70 static int dopaste(const char *);
71 static void dochq(const char *[], int);
72 static void dochc(const char *[], int);
73 static void dom4wrap(const char *);
74 static void dodiv(int);
75 static void doundiv(const char *[], int);
76 static void dosub(const char *[], int);
77 static void map(char *, const char *, const char *, const char *);
78 static const char *handledash(char *, char *, const char *);
79 static void expand_builtin(const char *[], int, int);
80 static void expand_macro(const char *[], int);
81 static void dump_one_def(const char *, struct macro_definition *);
83 unsigned long expansion_id;
86 * eval - eval all macros and builtins calls
87 * argc - number of elements in argv.
88 * argv - element vector :
89 * argv[0] = definition of a user
90 * macro or NULL if built-in.
91 * argv[1] = name of the macro or
93 * argv[2] = parameters to user-defined
94 * . macro or built-in.
97 * A call in the form of macro-or-builtin() will result in:
99 * argv[1] = macro-or-builtin
102 * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
105 eval(const char *argv[], int argc, int td, int is_traced)
107 size_t mark = SIZE_MAX;
111 m4errx(1, "expanding recursive definition for %s.", argv[1]);
113 mark = trace(argv, argc, infile+ilevel);
115 expand_macro(argv, argc);
117 expand_builtin(argv, argc, td);
118 if (mark != SIZE_MAX)
123 * expand_builtin - evaluate built-in macros.
126 expand_builtin(const char *argv[], int argc, int td)
131 static int sysval = 0;
134 printf("argc = %d\n", argc);
135 for (n = 0; n < argc; n++)
136 printf("argv[%d] = %s\n", n, argv[n]);
141 * if argc == 3 and argv[2] is null, then we
142 * have macro-or-builtin() type call. We adjust
143 * argc to avoid further checking..
145 /* we keep the initial value for those built-ins that differentiate
146 * between builtin() and builtin.
150 if (argc == 3 && !*(argv[2]) && !mimic_gnu)
153 switch (td & TYPEMASK) {
157 dodefine(argv[2], (argc > 3) ? argv[3] : null);
162 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
170 dotrace(argv, argc, 1);
174 dotrace(argv, argc, 0);
179 * doexpr - evaluate arithmetic
188 base = strtonum(argv[3], 2, 36, &errstr);
190 m4errx(1, "expr: base is %s: %s.",
195 maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr);
197 m4errx(1, "expr: maxdigits is %s: %s.",
202 pbnumbase(expr(argv[2]), base, maxdigits);
207 doifelse(argv, argc);
212 * doifdef - select one of two
213 * alternatives based on the existence of
217 if (lookup_macro_definition(argv[2]) != NULL)
226 * dolen - find the length of the
229 pbnum((argc > 2) ? strlen(argv[2]) : 0);
234 * doincr - increment the value of the
238 n = strtonum(argv[2], INT_MIN, INT_MAX-1, &errstr);
240 m4errx(1, "incr: argument is %s: %s.",
248 * dodecr - decrement the value of the
252 n = strtonum(argv[2], INT_MIN+1, INT_MAX, &errstr);
254 m4errx(1, "decr: argument is %s: %s.",
262 * dosys - execute system command
266 sysval = system(argv[2]);
272 * dosysval - return value of the last
285 if (!doincl(argv[2])) {
287 warn("%s at line %lu: include(%s)",
288 CURRENT_NAME, CURRENT_LINE, argv[2]);
295 err(1, "%s at line %lu: include(%s)",
296 CURRENT_NAME, CURRENT_LINE, argv[2]);
303 (void) doincl(argv[2]);
308 if (!dopaste(argv[2]))
309 err(1, "%s at line %lu: paste(%s)",
310 CURRENT_NAME, CURRENT_LINE, argv[2]);
315 (void) dopaste(argv[2]);
318 doformat(argv, argc);
331 * dosub - select substring
340 * doshift - push back all arguments
341 * except the first one (i.e. skip
345 for (n = argc - 1; n > 3; n--) {
359 n = strtonum(argv[2], INT_MIN, INT_MAX, &errstr);
361 m4errx(1, "divert: argument is %s: %s.",
378 * dodivnum - return the number of
379 * current output diversion
386 * doundefine - undefine a previously
387 * defined macro(s) or m4 keyword(s).
390 for (n = 2; n < argc; n++)
391 macro_undefine(argv[n]);
396 * dopopdef - remove the topmost
397 * definitions of macro(s) or m4
401 for (n = 2; n < argc; n++)
402 macro_popdef(argv[n]);
407 * dotemp - create a temporary file
413 temp = xstrdup(argv[2]);
418 "%s at line %lu: couldn't make temp file %s",
419 CURRENT_NAME, CURRENT_LINE, argv[2]);
428 * dotranslit - replace all characters in
429 * the source string that appears in the
430 * "from" string with the corresponding
431 * characters in the "to" string.
436 temp = xalloc(strlen(argv[2])+1, NULL);
438 map(temp, argv[2], argv[3], argv[4]);
440 map(temp, argv[2], argv[3], null);
449 * doindex - find the index of the second
450 * argument string in the first argument
451 * string. -1 if not present.
453 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
458 * doerrp - print the arguments to stderr
462 for (n = 2; n < argc; n++)
463 fprintf(stderr, "%s ", argv[n]);
464 fprintf(stderr, "\n");
470 * dodnl - eat-up-to and including
473 while ((c = gpbc()) != '\n' && c != EOF)
479 * dom4wrap - set up for
480 * wrap-up/wind-down activity
488 * doexit - immediate exit from m4.
491 exit((argc > 2) ? atoi(argv[2]) : 0);
496 for (n = 2; n < argc; n++)
500 case INDIRTYPE: /* Indirect call */
505 case BUILTINTYPE: /* Builtins only */
507 dobuiltin(argv, argc);
512 dopatsubst(argv, argc);
516 doregexp(argv, argc);
519 doprintlineno(infile+ilevel);
522 doprintfilename(infile+ilevel);
530 m4errx(1, "eval: major botch.");
536 * expand_macro - user-defined macro expansion
539 expand_macro(const char *argv[], int argc)
546 t = argv[0]; /* defn string as a whole */
550 p--; /* last character of defn */
552 if (*(p - 1) != ARGFLAG)
570 if ((argno = *p - '0') < argc - 1)
571 pbstr(argv[argno + 1]);
575 for (n = argc - 1; n > 2; n--) {
584 for (n = argc - 1; n > 2; n--) {
604 if (p == t) /* do last character */
610 * dodefine - install definition in the table
613 dodefine(const char *name, const char *defn)
615 if (!*name && !mimic_gnu)
616 m4errx(1, "null definition.");
618 macro_define(name, defn);
622 * dodefn - push back a quoted definition of
626 dodefn(const char *name)
628 struct macro_definition *p;
630 if ((p = lookup_macro_definition(name)) != NULL) {
631 if ((p->type & TYPEMASK) == MACRTYPE) {
637 pbstr(BUILTIN_MARKER);
643 * dopushdef - install a definition in the hash table
644 * without removing a previous definition. Since
645 * each new entry is entered in *front* of the
646 * hash bucket, it hides a previous definition from
650 dopushdef(const char *name, const char *defn)
652 if (!*name && !mimic_gnu)
653 m4errx(1, "null definition.");
655 macro_pushdef(name, defn);
659 * dump_one_def - dump the specified definition.
662 dump_one_def(const char *name, struct macro_definition *p)
667 if ((p->type & TYPEMASK) == MACRTYPE)
668 fprintf(traceout, "%s:\t%s\n", name, p->defn);
670 fprintf(traceout, "%s:\t<%s>\n", name, p->defn);
673 fprintf(traceout, "`%s'\t`%s'\n", name, p->defn);
677 * dodumpdef - dump the specified definitions in the hash
678 * table to stderr. If nothing is specified, the entire
679 * hash table is dumped.
682 dodump(const char *argv[], int argc)
685 struct macro_definition *p;
688 for (n = 2; n < argc; n++)
689 if ((p = lookup_macro_definition(argv[n])) != NULL)
690 dump_one_def(argv[n], p);
692 macro_for_all(dump_one_def);
696 * dotrace - mark some macros as traced/untraced depending upon on.
699 dotrace(const char *argv[], int argc, int on)
704 for (n = 2; n < argc; n++)
705 mark_traced(argv[n], on);
707 mark_traced(NULL, on);
711 * doifelse - select one of two alternatives - loop.
714 doifelse(const char *argv[], int argc)
717 if (STREQ(argv[2], argv[3])) {
720 } else if (argc == 6) {
731 * doinclude - include a given file.
734 doincl(const char *ifile)
736 if (ilevel + 1 == MAXINP)
737 m4errx(1, "too many include files.");
738 if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
740 bbase[ilevel] = bufbase = bp;
748 * dopaste - include a given file without any
752 dopaste(const char *pfile)
757 if ((pf = fopen(pfile, "r")) != NULL) {
759 fprintf(active, "#line 1 \"%s\"\n", pfile);
760 while ((c = getc(pf)) != EOF)
771 * dochq - change quote characters
774 dochq(const char *argv[], int ac)
777 lquote[0] = LQUOTE; lquote[1] = EOS;
778 rquote[0] = RQUOTE; rquote[1] = EOS;
780 strlcpy(lquote, argv[2], sizeof(lquote));
782 strlcpy(rquote, argv[3], sizeof(rquote));
784 rquote[0] = ECOMMT; rquote[1] = EOS;
790 * dochc - change comment characters
793 dochc(const char *argv[], int argc)
795 /* XXX Note that there is no difference between no argument and a single
802 strlcpy(scommt, argv[2], sizeof(scommt));
804 ecommt[0] = ECOMMT; ecommt[1] = EOS;
806 strlcpy(ecommt, argv[3], sizeof(ecommt));
812 * dom4wrap - expand text at EOF
815 dom4wrap(const char *text)
817 if (wrapindex >= maxwraps) {
822 m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps),
825 m4wraps[wrapindex++] = xstrdup(text);
829 * dodivert - divert the output to a temporary file
841 n = 0; /* bitbucket */
845 n = 0; /* bitbucket */
846 if (outfile[n] == NULL) {
847 char fname[] = _PATH_DIVNAME;
849 if ((fd = mkstemp(fname)) == -1 ||
850 unlink(fname) == -1 ||
851 (outfile[n] = fdopen(fd, "w+")) == NULL)
852 err(1, "%s: cannot divert", fname);
858 * doundivert - undivert a specified output, or all
859 * other outputs, in numerical order.
862 doundiv(const char *argv[], int argc)
868 for (ind = 2; ind < argc; ind++) {
870 n = strtonum(argv[ind], 1, INT_MAX, &errstr);
872 if (errno == EINVAL && mimic_gnu)
873 getdivfile(argv[ind]);
875 if (n < maxout && outfile[n] != NULL)
881 for (n = 1; n < maxout; n++)
882 if (outfile[n] != NULL)
887 * dosub - select substring
890 dosub(const char *argv[], int argc)
892 const char *ap, *fc, *k;
895 ap = argv[2]; /* target string */
897 fc = ap + expr(argv[3]); /* first char */
899 fc = ap + atoi(argv[3]); /* first char */
904 nc = min(nc, expr(argv[4]));
906 nc = min(nc, atoi(argv[4]));
908 if (fc >= ap && fc < ap + strlen(ap))
909 for (k = fc + nc - 1; k >= fc; k--)
915 * map every character of s1 that is specified in from
916 * into s3 and replace in s. (source s1 remains untouched)
918 * This is derived from the a standard implementation of map(s,from,to)
919 * function of ICON language. Within mapvec, we replace every character
920 * of "from" with the corresponding character in "to".
921 * If "to" is shorter than "from", than the corresponding entries are null,
922 * which means that those characters disappear altogether.
925 map(char *dest, const char *src, const char *from, const char *to)
928 unsigned char sch, dch;
929 static char frombis[257];
930 static char tobis[257];
933 static unsigned char mapvec[256] = {
934 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
935 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
936 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
937 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
938 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
939 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
940 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
941 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
942 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
943 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
944 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
945 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
946 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
947 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
948 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
949 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
950 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
951 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
957 * expand character ranges on the fly
959 from = handledash(frombis, frombis + 256, from);
960 to = handledash(tobis, tobis + 256, to);
964 * create a mapping between "from" and
967 for (i = 0; i < 256; i++)
970 if (!seen[(unsigned char)(*from)]) {
971 mapvec[(unsigned char)(*from)] = (unsigned char)(*to);
972 seen[(unsigned char)(*from)] = 1;
980 sch = (unsigned char)(*src++);
982 if ((*dest = (char)dch))
986 * restore all the changed characters
989 mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
999 * use buffer to copy the src string, expanding character ranges
1003 handledash(char *buffer, char *end, const char *src)
1009 if (src[1] == '-' && src[2]) {
1011 if ((unsigned char)src[0] <= (unsigned char)src[2]) {
1012 for (i = (unsigned char)src[0];
1013 i <= (unsigned char)src[2]; i++) {
1021 for (i = (unsigned char)src[0];
1022 i >= (unsigned char)src[2]; i--) {