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
39 * @(#)eval.c 8.2 (Berkeley) 4/27/95
40 * $OpenBSD: eval.c,v 1.44 2002/04/26 16:15:16 espie Exp $
41 * $FreeBSD: src/usr.bin/m4/eval.c,v 1.22 2004/08/16 14:18:21 tjr Exp $
42 * $DragonFly: src/usr.bin/m4/eval.c,v 1.3 2006/12/27 21:29:02 pavalos Exp $
47 * Facility: m4 macro processor
51 #include <sys/types.h>
63 #include "pathnames.h"
65 #define BUILTIN_MARKER "__builtin_"
67 static void dodefn(const char *);
68 static void dopushdef(const char *, const char *);
69 static void dodump(const char *[], int);
70 static void dotrace(const char *[], int, int);
71 static void doifelse(const char *[], int);
72 static int doincl(const char *);
73 static int dopaste(const char *);
74 static void gnu_dochq(const char *[], int);
75 static void dochq(const char *[], int);
76 static void gnu_dochc(const char *[], int);
77 static void dochc(const char *[], int);
78 static void dodiv(int);
79 static void doundiv(const char *[], int);
80 static void dosub(const char *[], int);
81 static void map(char *, const char *, const char *, const char *);
82 static const char *handledash(char *, char *, const char *);
83 static void expand_builtin(const char *[], int, int);
84 static void expand_macro(const char *[], int);
85 static void dump_one_def(ndptr
);
87 unsigned long expansion_id
;
90 * eval - eval all macros and builtins calls
91 * argc - number of elements in argv.
92 * argv - element vector :
93 * argv[0] = definition of a user
94 * macro or nil if built-in.
95 * argv[1] = name of the macro or
97 * argv[2] = parameters to user-defined
98 * . macro or built-in.
101 * A call in the form of macro-or-builtin() will result in:
103 * argv[1] = macro-or-builtin
106 * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
109 eval(const char *argv
[], int argc
, int td
)
115 errx(1, "%s at line %lu: expanding recursive definition for %s",
116 CURRENT_NAME
, CURRENT_LINE
, argv
[1]);
117 if (traced_macros
&& is_traced(argv
[1]))
118 mark
= trace(argv
, argc
, infile
+ilevel
);
120 expand_macro(argv
, argc
);
122 expand_builtin(argv
, argc
, td
);
128 * expand_builtin - evaluate built-in macros.
131 expand_builtin(const char *argv
[], int argc
, int td
)
135 static int sysval
= 0;
138 printf("argc = %d\n", argc
);
139 for (n
= 0; n
< argc
; n
++)
140 printf("argv[%d] = %s\n", n
, argv
[n
]);
145 * if argc == 3 and argv[2] is null, then we
146 * have macro-or-builtin() type call. We adjust
147 * argc to avoid further checking..
151 if (argc
== 3 && !*(argv
[2]))
154 switch (td
& TYPEMASK
) {
158 dodefine(argv
[2], (argc
> 3) ? argv
[3] : null
);
163 dopushdef(argv
[2], (argc
> 3) ? argv
[3] : null
);
171 dotrace(argv
, argc
, 1);
175 dotrace(argv
, argc
, 0);
180 * doexpr - evaluate arithmetic
184 pbnum(expr(argv
[2]));
189 doifelse(argv
, argc
);
194 * doifdef - select one of two
195 * alternatives based on the existence of
199 if (lookup(argv
[2]) != nil
)
208 * dolen - find the length of the
211 pbnum((argc
> 2) ? strlen(argv
[2]) : 0);
216 * doincr - increment the value of the
220 pbnum(atoi(argv
[2]) + 1);
225 * dodecr - decrement the value of the
229 pbnum(atoi(argv
[2]) - 1);
234 * dosys - execute system command
238 sysval
= system(argv
[2]);
244 * dosysval - return value of the last
257 if (!doincl(argv
[2]))
258 err(1, "%s at line %lu: include(%s)",
259 CURRENT_NAME
, CURRENT_LINE
, argv
[2]);
264 (void) doincl(argv
[2]);
269 if (!dopaste(argv
[2]))
270 err(1, "%s at line %lu: paste(%s)",
271 CURRENT_NAME
, CURRENT_LINE
, argv
[2]);
276 (void) dopaste(argv
[2]);
295 * dosub - select substring
304 * doshift - push back all arguments
305 * except the first one (i.e. skip
309 for (n
= argc
- 1; n
> 3; n
--) {
322 if (argc
> 2 && (n
= atoi(argv
[2])) != 0)
336 * dodivnum - return the number of
337 * current output diversion
344 * doundefine - undefine a previously
345 * defined macro(s) or m4 keyword(s).
348 for (n
= 2; n
< argc
; n
++)
349 remhash(argv
[n
], ALL
);
354 * dopopdef - remove the topmost
355 * definitions of macro(s) or m4
359 for (n
= 2; n
< argc
; n
++)
360 remhash(argv
[n
], TOP
);
365 * dotemp - create a temporary file
371 temp
= xstrdup(argv
[2]);
376 "%s at line %lu: couldn't make temp file %s",
377 CURRENT_NAME
, CURRENT_LINE
, argv
[2]);
386 * dotranslit - replace all characters in
387 * the source string that appears in the
388 * "from" string with the corresponding
389 * characters in the "to" string.
394 temp
= xalloc(strlen(argv
[2])+1);
396 map(temp
, argv
[2], argv
[3], argv
[4]);
398 map(temp
, argv
[2], argv
[3], null
);
407 * doindex - find the index of the second
408 * argument string in the first argument
409 * string. -1 if not present.
411 pbnum((argc
> 3) ? indx(argv
[2], argv
[3]) : -1);
416 * doerrp - print the arguments to stderr
420 for (n
= 2; n
< argc
; n
++)
421 fprintf(stderr
, "%s ", argv
[n
]);
422 fprintf(stderr
, "\n");
428 * dodnl - eat-up-to and including
431 while ((c
= gpbc()) != '\n' && c
!= EOF
)
437 * dom4wrap - set up for
438 * wrap-up/wind-down activity
440 m4wraps
= (argc
> 2) ? xstrdup(argv
[2]) : null
;
445 * doexit - immediate exit from m4.
448 exit((argc
> 2) ? atoi(argv
[2]) : 0);
453 for (n
= 2; n
< argc
; n
++)
457 case INDIRTYPE
: /* Indirect call */
462 case BUILTINTYPE
: /* Builtins only */
464 dobuiltin(argv
, argc
);
469 dopatsubst(argv
, argc
);
473 doregexp(argv
, argc
);
476 doprintlineno(infile
+ilevel
);
479 doprintfilename(infile
+ilevel
);
487 errx(1, "%s at line %lu: eval: major botch.",
488 CURRENT_NAME
, CURRENT_LINE
);
494 * expand_macro - user-defined macro expansion
497 expand_macro(const char *argv
[], int argc
)
504 t
= argv
[0]; /* defn string as a whole */
508 p
--; /* last character of defn */
510 if (*(p
- 1) != ARGFLAG
)
528 if ((argno
= *p
- '0') < argc
- 1)
529 pbstr(argv
[argno
+ 1]);
533 for (n
= argc
- 1; n
> 2; n
--) {
542 for (n
= argc
- 1; n
> 2; n
--) {
562 if (p
== t
) /* do last character */
567 * dodefine - install definition in the table
570 dodefine(const char *name
, const char *defn
)
576 errx(1, "%s at line %lu: null definition.", CURRENT_NAME
,
578 if ((p
= lookup(name
)) == nil
)
580 else if (p
->defn
!= null
)
581 free((char *) p
->defn
);
582 if (strncmp(defn
, BUILTIN_MARKER
, sizeof(BUILTIN_MARKER
)-1) == 0) {
583 n
= builtin_type(defn
+sizeof(BUILTIN_MARKER
)-1);
585 p
->type
= n
& TYPEMASK
;
586 if ((n
& NOARGS
) == 0)
595 p
->defn
= xstrdup(defn
);
597 if (STREQ(name
, defn
))
602 * dodefn - push back a quoted definition of
606 dodefn(const char *name
)
611 if ((p
= lookup(name
)) != nil
) {
612 if (p
->defn
!= null
) {
616 } else if ((real
= builtin_realname(p
->type
)) != NULL
) {
618 pbstr(BUILTIN_MARKER
);
624 * dopushdef - install a definition in the hash table
625 * without removing a previous definition. Since
626 * each new entry is entered in *front* of the
627 * hash bucket, it hides a previous definition from
631 dopushdef(const char *name
, const char *defn
)
636 errx(1, "%s at line %lu: null definition", CURRENT_NAME
,
642 p
->defn
= xstrdup(defn
);
644 if (STREQ(name
, defn
))
649 * dump_one_def - dump the specified definition.
652 dump_one_def(ndptr p
)
657 if ((p
->type
& TYPEMASK
) == MACRTYPE
)
658 fprintf(traceout
, "%s:\t%s\n", p
->name
, p
->defn
);
660 real
= builtin_realname(p
->type
);
663 fprintf(traceout
, "%s:\t<%s>\n", p
->name
, real
);
666 fprintf(traceout
, "`%s'\t`%s'\n", p
->name
, p
->defn
);
670 * dodumpdef - dump the specified definitions in the hash
671 * table to stderr. If nothing is specified, the entire
672 * hash table is dumped.
675 dodump(const char *argv
[], int argc
)
681 for (n
= 2; n
< argc
; n
++)
682 if ((p
= lookup(argv
[n
])) != nil
)
685 for (n
= 0; n
< HASHSIZE
; n
++)
686 for (p
= hashtab
[n
]; p
!= nil
; p
= p
->nxtptr
)
692 * dotrace - mark some macros as traced/untraced depending upon on.
695 dotrace(const char *argv
[], int argc
, int on
)
700 for (n
= 2; n
< argc
; n
++)
701 mark_traced(argv
[n
], on
);
703 mark_traced(NULL
, on
);
707 * doifelse - select one of two alternatives - loop.
710 doifelse(const char *argv
[], int argc
)
713 if (STREQ(argv
[2], argv
[3]))
727 * doinclude - include a given file.
730 doincl(const char *ifile
)
732 if (ilevel
+ 1 == MAXINP
)
733 errx(1, "%s at line %lu: too many include files.",
734 CURRENT_NAME
, CURRENT_LINE
);
735 if (fopen_trypath(infile
+ilevel
+1, ifile
) != NULL
) {
737 if ((inname
[ilevel
] = strdup(ifile
)) == NULL
)
739 inlineno
[ilevel
] = 1;
740 bbase
[ilevel
] = bufbase
= bp
;
749 * dopaste - include a given file without any
753 dopaste(const char *pfile
)
758 if ((pf
= fopen(pfile
, "r")) != NULL
) {
759 fprintf(active
, "#line 1 \"%s\"\n", pfile
);
760 while ((c
= getc(pf
)) != EOF
)
771 gnu_dochq(const char *argv
[], int ac
)
773 /* In gnu-m4 mode, the only way to restore quotes is to have no
774 * arguments at all. */
776 lquote
[0] = LQUOTE
, lquote
[1] = EOS
;
777 rquote
[0] = RQUOTE
, rquote
[1] = EOS
;
779 strlcpy(lquote
, argv
[2], sizeof(lquote
));
781 strlcpy(rquote
, argv
[3], sizeof(rquote
));
788 * dochq - change quote characters
791 dochq(const char *argv
[], int argc
)
795 strlcpy(lquote
, argv
[2], sizeof(lquote
));
802 strlcpy(rquote
, argv
[3], sizeof(rquote
));
804 strcpy(rquote
, lquote
);
806 lquote
[0] = LQUOTE
, lquote
[1] = EOS
;
807 rquote
[0] = RQUOTE
, rquote
[1] = EOS
;
812 gnu_dochc(const char *argv
[], int ac
)
814 /* In gnu-m4 mode, no arguments mean no comment
815 * arguments at all. */
821 strlcpy(scommt
, argv
[2], sizeof(scommt
));
823 scommt
[0] = SCOMMT
, scommt
[1] = EOS
;
824 if(ac
> 3 && *argv
[3])
825 strlcpy(ecommt
, argv
[3], sizeof(ecommt
));
827 ecommt
[0] = ECOMMT
, ecommt
[1] = EOS
;
831 * dochc - change comment characters
834 dochc(const char *argv
[], int argc
)
838 strlcpy(scommt
, argv
[2], sizeof(scommt
));
841 strlcpy(ecommt
, argv
[3], sizeof(ecommt
));
844 ecommt
[0] = ECOMMT
, ecommt
[1] = EOS
;
847 scommt
[0] = SCOMMT
, scommt
[1] = EOS
;
848 ecommt
[0] = ECOMMT
, ecommt
[1] = EOS
;
853 * dodivert - divert the output to a temporary file
865 n
= 0; /* bitbucket */
869 n
= 0; /* bitbucket */
870 if (outfile
[n
] == NULL
) {
871 char fname
[] = _PATH_DIVNAME
;
873 if ((fd
= mkstemp(fname
)) < 0 ||
874 (outfile
[n
] = fdopen(fd
, "w+")) == NULL
)
875 err(1, "%s: cannot divert", fname
);
876 if (unlink(fname
) == -1)
877 err(1, "%s: cannot unlink", fname
);
883 * doundivert - undivert a specified output, or all
884 * other outputs, in numerical order.
887 doundiv(const char *argv
[], int argc
)
893 for (ind
= 2; ind
< argc
; ind
++) {
895 if (n
> 0 && n
< maxout
&& outfile
[n
] != NULL
)
901 for (n
= 1; n
< maxout
; n
++)
902 if (outfile
[n
] != NULL
)
907 * dosub - select substring
910 dosub(const char *argv
[], int argc
)
912 const char *ap
, *fc
, *k
;
915 ap
= argv
[2]; /* target string */
917 fc
= ap
+ expr(argv
[3]); /* first char */
919 fc
= ap
+ atoi(argv
[3]); /* first char */
924 nc
= min(nc
, expr(argv
[4]));
926 nc
= min(nc
, atoi(argv
[4]));
928 if (fc
>= ap
&& fc
< ap
+ strlen(ap
))
929 for (k
= fc
+ nc
- 1; k
>= fc
; k
--)
935 * map every character of s1 that is specified in from
936 * into s3 and replace in s. (source s1 remains untouched)
938 * This is a standard implementation of map(s,from,to) function of ICON
939 * language. Within mapvec, we replace every character of "from" with
940 * the corresponding character in "to". If "to" is shorter than "from",
941 * than the corresponding entries are null, which means that those
942 * characters dissapear altogether. Furthermore, imagine
943 * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
944 * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
945 * ultimately maps to `*'. In order to achieve this effect in an efficient
946 * manner (i.e. without multiple passes over the destination string), we
947 * loop over mapvec, starting with the initial source character. if the
948 * character value (dch) in this location is different than the source
949 * character (sch), sch becomes dch, once again to index into mapvec, until
950 * the character value stabilizes (i.e. sch = dch, in other words
951 * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
952 * character, it will stabilize, since mapvec[0] == 0 at all times. At the
953 * end, we restore mapvec* back to normal where mapvec[n] == n for
954 * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
955 * about 5 times faster than any algorithm that makes multiple passes over
956 * destination string.
959 map(char *dest
, const char *src
, const char *from
, const char *to
)
962 unsigned char sch
, dch
;
963 static char frombis
[257];
964 static char tobis
[257];
965 static unsigned char mapvec
[256] = {
966 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
967 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
968 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
969 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
970 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
971 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
972 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
973 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
974 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
975 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
976 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
977 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
978 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
979 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
980 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
981 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
982 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
983 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
989 * expand character ranges on the fly
991 from
= handledash(frombis
, frombis
+ 256, from
);
992 to
= handledash(tobis
, tobis
+ 256, to
);
996 * create a mapping between "from" and
1000 mapvec
[(unsigned char)(*from
++)] = (*to
) ?
1001 (unsigned char)(*to
++) : 0;
1004 sch
= (unsigned char)(*src
++);
1006 while (dch
!= sch
) {
1010 if ((*dest
= (char)dch
))
1014 * restore all the changed characters
1017 mapvec
[(unsigned char)(*tmp
)] = (unsigned char)(*tmp
);
1027 * use buffer to copy the src string, expanding character ranges
1031 handledash(char *buffer
, char *end
, const char *src
)
1037 if (src
[1] == '-' && src
[2]) {
1039 for (i
= (unsigned char)src
[0];
1040 i
<= (unsigned char)src
[2]; i
++) {