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>
41 * Facility: m4 macro processor
45 #include <sys/types.h>
59 #include "pathnames.h"
61 static void dodefn(const char *);
62 static void dopushdef(const char *, const char *);
63 static void dodump(const char *[], int);
64 static void dotrace(const char *[], int, int);
65 static void doifelse(const char *[], int);
66 static int doincl(const char *);
67 static int dopaste(const char *);
68 static void dochq(const char *[], int);
69 static void dochc(const char *[], int);
70 static void dom4wrap(const char *);
71 static void dodiv(int);
72 static void doundiv(const char *[], int);
73 static void dosub(const char *[], int);
74 static void map(char *, const char *, const char *, const char *);
75 static const char *handledash(char *, char *, const char *);
76 static void expand_builtin(const char *[], int, int);
77 static void expand_macro(const char *[], int);
78 static void dump_one_def(const char *, struct macro_definition *);
80 unsigned long expansion_id;
83 * eval - eval all macros and builtins calls
84 * argc - number of elements in argv.
85 * argv - element vector :
86 * argv[0] = definition of a user
87 * macro or NULL if built-in.
88 * argv[1] = name of the macro or
90 * argv[2] = parameters to user-defined
91 * . macro or built-in.
94 * A call in the form of macro-or-builtin() will result in:
96 * argv[1] = macro-or-builtin
99 * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
102 eval(const char *argv[], int argc, int td, int is_traced)
104 size_t mark = SIZE_MAX;
108 m4errx(1, "expanding recursive definition for %s.", argv[1]);
110 mark = trace(argv, argc, infile+ilevel);
112 expand_macro(argv, argc);
114 expand_builtin(argv, argc, td);
115 if (mark != SIZE_MAX)
120 * expand_builtin - evaluate built-in macros.
123 expand_builtin(const char *argv[], int argc, int td)
128 static int sysval = 0;
131 printf("argc = %d\n", argc);
132 for (n = 0; n < argc; n++)
133 printf("argv[%d] = %s\n", n, argv[n]);
138 * if argc == 3 and argv[2] is null, then we
139 * have macro-or-builtin() type call. We adjust
140 * argc to avoid further checking..
142 /* we keep the initial value for those built-ins that differentiate
143 * between builtin() and builtin.
147 if (argc == 3 && !*(argv[2]) && !mimic_gnu)
150 switch (td & TYPEMASK) {
154 dodefine(argv[2], (argc > 3) ? argv[3] : null);
159 dopushdef(argv[2], (argc > 3) ? argv[3] : null);
167 dotrace(argv, argc, 1);
171 dotrace(argv, argc, 0);
176 * doexpr - evaluate arithmetic
185 base = strtonum(argv[3], 2, 36, &errstr);
187 m4errx(1, "expr: base is %s: %s.",
192 maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr);
194 m4errx(1, "expr: maxdigits is %s: %s.",
199 pbnumbase(expr(argv[2]), base, maxdigits);
204 doifelse(argv, argc);
209 * doifdef - select one of two
210 * alternatives based on the existence of
214 if (lookup_macro_definition(argv[2]) != NULL)
223 * dolen - find the length of the
226 pbnum((argc > 2) ? strlen(argv[2]) : 0);
231 * doincr - increment the value of the
235 n = strtonum(argv[2], INT_MIN, INT_MAX-1, &errstr);
237 m4errx(1, "incr: argument is %s: %s.",
245 * dodecr - decrement the value of the
249 n = strtonum(argv[2], INT_MIN+1, INT_MAX, &errstr);
251 m4errx(1, "decr: argument is %s: %s.",
259 * dosys - execute system command
263 sysval = system(argv[2]);
269 * dosysval - return value of the last
282 if (!doincl(argv[2])) {
284 warn("%s at line %lu: include(%s)",
285 CURRENT_NAME, CURRENT_LINE, argv[2]);
292 err(1, "%s at line %lu: include(%s)",
293 CURRENT_NAME, CURRENT_LINE, argv[2]);
300 (void) doincl(argv[2]);
305 if (!dopaste(argv[2]))
306 err(1, "%s at line %lu: paste(%s)",
307 CURRENT_NAME, CURRENT_LINE, argv[2]);
312 (void) dopaste(argv[2]);
315 doformat(argv, argc);
328 * dosub - select substring
337 * doshift - push back all arguments
338 * except the first one (i.e. skip
342 for (n = argc - 1; n > 3; n--) {
356 n = strtonum(argv[2], INT_MIN, INT_MAX, &errstr);
358 m4errx(1, "divert: argument is %s: %s.",
375 * dodivnum - return the number of
376 * current output diversion
383 * doundefine - undefine a previously
384 * defined macro(s) or m4 keyword(s).
387 for (n = 2; n < argc; n++)
388 macro_undefine(argv[n]);
393 * dopopdef - remove the topmost
394 * definitions of macro(s) or m4
398 for (n = 2; n < argc; n++)
399 macro_popdef(argv[n]);
404 * dotemp - create a temporary file
410 temp = xstrdup(argv[2]);
415 "%s at line %lu: couldn't make temp file %s",
416 CURRENT_NAME, CURRENT_LINE, argv[2]);
425 * dotranslit - replace all characters in
426 * the source string that appears in the
427 * "from" string with the corresponding
428 * characters in the "to" string.
433 temp = xalloc(strlen(argv[2])+1, NULL);
435 map(temp, argv[2], argv[3], argv[4]);
437 map(temp, argv[2], argv[3], null);
446 * doindex - find the index of the second
447 * argument string in the first argument
448 * string. -1 if not present.
450 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
455 * doerrp - print the arguments to stderr
459 for (n = 2; n < argc; n++)
460 fprintf(stderr, "%s ", argv[n]);
461 fprintf(stderr, "\n");
467 * dodnl - eat-up-to and including
470 while ((c = gpbc()) != '\n' && c != EOF)
476 * dom4wrap - set up for
477 * wrap-up/wind-down activity
485 * doexit - immediate exit from m4.
488 exit((argc > 2) ? atoi(argv[2]) : 0);
493 for (n = 2; n < argc; n++)
497 case INDIRTYPE: /* Indirect call */
502 case BUILTINTYPE: /* Builtins only */
504 dobuiltin(argv, argc);
509 dopatsubst(argv, argc);
513 doregexp(argv, argc);
516 doprintlineno(infile+ilevel);
519 doprintfilename(infile+ilevel);
527 m4errx(1, "eval: major botch.");
533 * expand_macro - user-defined macro expansion
536 expand_macro(const char *argv[], int argc)
543 t = argv[0]; /* defn string as a whole */
547 p--; /* last character of defn */
549 if (*(p - 1) != ARGFLAG)
567 if ((argno = *p - '0') < argc - 1)
568 pbstr(argv[argno + 1]);
572 for (n = argc - 1; n > 2; n--) {
581 for (n = argc - 1; n > 2; n--) {
601 if (p == t) /* do last character */
607 * dodefine - install definition in the table
610 dodefine(const char *name, const char *defn)
612 if (!*name && !mimic_gnu)
613 m4errx(1, "null definition.");
615 macro_define(name, defn);
619 * dodefn - push back a quoted definition of
623 dodefn(const char *name)
625 struct macro_definition *p;
627 if ((p = lookup_macro_definition(name)) != NULL) {
628 if ((p->type & TYPEMASK) == MACRTYPE) {
634 pbstr(BUILTIN_MARKER);
640 * dopushdef - install a definition in the hash table
641 * without removing a previous definition. Since
642 * each new entry is entered in *front* of the
643 * hash bucket, it hides a previous definition from
647 dopushdef(const char *name, const char *defn)
649 if (!*name && !mimic_gnu)
650 m4errx(1, "null definition.");
652 macro_pushdef(name, defn);
656 * dump_one_def - dump the specified definition.
659 dump_one_def(const char *name, struct macro_definition *p)
664 if ((p->type & TYPEMASK) == MACRTYPE)
665 fprintf(traceout, "%s:\t%s\n", name, p->defn);
667 fprintf(traceout, "%s:\t<%s>\n", name, p->defn);
670 fprintf(traceout, "`%s'\t`%s'\n", name, p->defn);
674 * dodumpdef - dump the specified definitions in the hash
675 * table to stderr. If nothing is specified, the entire
676 * hash table is dumped.
679 dodump(const char *argv[], int argc)
682 struct macro_definition *p;
685 for (n = 2; n < argc; n++)
686 if ((p = lookup_macro_definition(argv[n])) != NULL)
687 dump_one_def(argv[n], p);
689 macro_for_all(dump_one_def);
693 * dotrace - mark some macros as traced/untraced depending upon on.
696 dotrace(const char *argv[], int argc, int on)
701 for (n = 2; n < argc; n++)
702 mark_traced(argv[n], on);
704 mark_traced(NULL, on);
708 * doifelse - select one of two alternatives - loop.
711 doifelse(const char *argv[], int argc)
714 if (STREQ(argv[2], argv[3])) {
717 } else if (argc == 6) {
728 * doinclude - include a given file.
731 doincl(const char *ifile)
733 if (ilevel + 1 == MAXINP)
734 m4errx(1, "too many include files.");
735 if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
737 bbase[ilevel] = bufbase = bp;
745 * dopaste - include a given file without any
749 dopaste(const char *pfile)
754 if ((pf = fopen(pfile, "r")) != NULL) {
756 fprintf(active, "#line 1 \"%s\"\n", pfile);
757 while ((c = getc(pf)) != EOF)
768 * dochq - change quote characters
771 dochq(const char *argv[], int ac)
774 lquote[0] = LQUOTE; lquote[1] = EOS;
775 rquote[0] = RQUOTE; rquote[1] = EOS;
777 strlcpy(lquote, argv[2], sizeof(lquote));
779 strlcpy(rquote, argv[3], sizeof(rquote));
781 rquote[0] = ECOMMT; rquote[1] = EOS;
787 * dochc - change comment characters
790 dochc(const char *argv[], int argc)
792 /* XXX Note that there is no difference between no argument and a single
799 strlcpy(scommt, argv[2], sizeof(scommt));
801 ecommt[0] = ECOMMT; ecommt[1] = EOS;
803 strlcpy(ecommt, argv[3], sizeof(ecommt));
809 * dom4wrap - expand text at EOF
812 dom4wrap(const char *text)
814 if (wrapindex >= maxwraps) {
819 m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps),
822 m4wraps[wrapindex++] = xstrdup(text);
826 * dodivert - divert the output to a temporary file
838 n = 0; /* bitbucket */
842 n = 0; /* bitbucket */
843 if (outfile[n] == NULL) {
844 char fname[] = _PATH_DIVNAME;
846 if ((fd = mkstemp(fname)) == -1 ||
847 unlink(fname) == -1 ||
848 (outfile[n] = fdopen(fd, "w+")) == NULL)
849 err(1, "%s: cannot divert", fname);
855 * doundivert - undivert a specified output, or all
856 * other outputs, in numerical order.
859 doundiv(const char *argv[], int argc)
865 for (ind = 2; ind < argc; ind++) {
867 n = strtonum(argv[ind], 1, INT_MAX, &errstr);
869 if (errno == EINVAL && mimic_gnu)
870 getdivfile(argv[ind]);
872 if (n < maxout && outfile[n] != NULL)
878 for (n = 1; n < maxout; n++)
879 if (outfile[n] != NULL)
884 * dosub - select substring
887 dosub(const char *argv[], int argc)
889 const char *ap, *fc, *k;
892 ap = argv[2]; /* target string */
894 fc = ap + expr(argv[3]); /* first char */
896 fc = ap + atoi(argv[3]); /* first char */
901 nc = min(nc, expr(argv[4]));
903 nc = min(nc, atoi(argv[4]));
905 if (fc >= ap && fc < ap + strlen(ap))
906 for (k = fc + nc - 1; k >= fc; k--)
912 * map every character of s1 that is specified in from
913 * into s3 and replace in s. (source s1 remains untouched)
915 * This is derived from the a standard implementation of map(s,from,to)
916 * function of ICON language. Within mapvec, we replace every character
917 * of "from" with the corresponding character in "to".
918 * If "to" is shorter than "from", than the corresponding entries are null,
919 * which means that those characters disappear altogether.
922 map(char *dest, const char *src, const char *from, const char *to)
925 unsigned char sch, dch;
926 static char frombis[257];
927 static char tobis[257];
930 static unsigned char mapvec[256] = {
931 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
932 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
933 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
934 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
935 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
936 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
937 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
938 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
939 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
940 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
941 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
942 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
943 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
944 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
945 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
946 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
947 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
948 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
954 * expand character ranges on the fly
956 from = handledash(frombis, frombis + 256, from);
957 to = handledash(tobis, tobis + 256, to);
961 * create a mapping between "from" and
964 for (i = 0; i < 256; i++)
967 if (!seen[(unsigned char)(*from)]) {
968 mapvec[(unsigned char)(*from)] = (unsigned char)(*to);
969 seen[(unsigned char)(*from)] = 1;
977 sch = (unsigned char)(*src++);
979 if ((*dest = (char)dch))
983 * restore all the changed characters
986 mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
996 * use buffer to copy the src string, expanding character ranges
1000 handledash(char *buffer, char *end, const char *src)
1006 if (src[1] == '-' && src[2]) {
1008 if ((unsigned char)src[0] <= (unsigned char)src[2]) {
1009 for (i = (unsigned char)src[0];
1010 i <= (unsigned char)src[2]; i++) {
1018 for (i = (unsigned char)src[0];
1019 i >= (unsigned char)src[2]; i--) {