1*c57596e1SBaptiste Daroussin /* $OpenBSD: eval.c,v 1.78 2019/06/28 05:35:34 deraadt Exp $ */
2acc9d408SJuli Mallett /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */
3acc9d408SJuli Mallett
48a16b7a1SPedro F. Giffuni /*-
58a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
68a16b7a1SPedro F. Giffuni *
79b50d902SRodney W. Grimes * Copyright (c) 1989, 1993
89b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved.
99b50d902SRodney W. Grimes *
109b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by
119b50d902SRodney W. Grimes * Ozan Yigit at York University.
129b50d902SRodney W. Grimes *
139b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
149b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions
159b50d902SRodney W. Grimes * are met:
169b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
179b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
189b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
199b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
209b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution.
21a841e1ebSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors
229b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software
239b50d902SRodney W. Grimes * without specific prior written permission.
249b50d902SRodney W. Grimes *
259b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
269b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
279b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
289b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
299b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
309b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
319b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
329b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
339b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
349b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
359b50d902SRodney W. Grimes * SUCH DAMAGE.
369b50d902SRodney W. Grimes */
379b50d902SRodney W. Grimes
38acc9d408SJuli Mallett #include <sys/cdefs.h>
399b50d902SRodney W. Grimes /*
409b50d902SRodney W. Grimes * eval.c
419b50d902SRodney W. Grimes * Facility: m4 macro processor
429b50d902SRodney W. Grimes * by: oz
439b50d902SRodney W. Grimes */
449b50d902SRodney W. Grimes
459b50d902SRodney W. Grimes #include <sys/types.h>
46a841e1ebSBaptiste Daroussin #include <err.h>
47acc9d408SJuli Mallett #include <errno.h>
48a841e1ebSBaptiste Daroussin #include <limits.h>
49acc9d408SJuli Mallett #include <unistd.h>
509b50d902SRodney W. Grimes #include <stdio.h>
5146ef9581SBaptiste Daroussin #include <stdint.h>
529b50d902SRodney W. Grimes #include <stdlib.h>
53acc9d408SJuli Mallett #include <stddef.h>
549b50d902SRodney W. Grimes #include <string.h>
55acc9d408SJuli Mallett #include <fcntl.h>
569b50d902SRodney W. Grimes #include "mdef.h"
579b50d902SRodney W. Grimes #include "stdd.h"
589b50d902SRodney W. Grimes #include "extern.h"
599b50d902SRodney W. Grimes #include "pathnames.h"
609b50d902SRodney W. Grimes
61acc9d408SJuli Mallett static void dodefn(const char *);
62acc9d408SJuli Mallett static void dopushdef(const char *, const char *);
63acc9d408SJuli Mallett static void dodump(const char *[], int);
64acc9d408SJuli Mallett static void dotrace(const char *[], int, int);
65acc9d408SJuli Mallett static void doifelse(const char *[], int);
66acc9d408SJuli Mallett static int doincl(const char *);
67acc9d408SJuli Mallett static int dopaste(const char *);
68acc9d408SJuli Mallett static void dochq(const char *[], int);
69acc9d408SJuli Mallett static void dochc(const char *[], int);
70a841e1ebSBaptiste Daroussin static void dom4wrap(const char *);
71acc9d408SJuli Mallett static void dodiv(int);
72acc9d408SJuli Mallett static void doundiv(const char *[], int);
73acc9d408SJuli Mallett static void dosub(const char *[], int);
74acc9d408SJuli Mallett static void map(char *, const char *, const char *, const char *);
75acc9d408SJuli Mallett static const char *handledash(char *, char *, const char *);
76acc9d408SJuli Mallett static void expand_builtin(const char *[], int, int);
77acc9d408SJuli Mallett static void expand_macro(const char *[], int);
78a841e1ebSBaptiste Daroussin static void dump_one_def(const char *, struct macro_definition *);
79acc9d408SJuli Mallett
80acc9d408SJuli Mallett unsigned long expansion_id;
81acc9d408SJuli Mallett
829b50d902SRodney W. Grimes /*
83acc9d408SJuli Mallett * eval - eval all macros and builtins calls
849b50d902SRodney W. Grimes * argc - number of elements in argv.
859b50d902SRodney W. Grimes * argv - element vector :
869b50d902SRodney W. Grimes * argv[0] = definition of a user
87a841e1ebSBaptiste Daroussin * macro or NULL if built-in.
889b50d902SRodney W. Grimes * argv[1] = name of the macro or
899b50d902SRodney W. Grimes * built-in.
909b50d902SRodney W. Grimes * argv[2] = parameters to user-defined
919b50d902SRodney W. Grimes * . macro or built-in.
929b50d902SRodney W. Grimes * .
939b50d902SRodney W. Grimes *
94acc9d408SJuli Mallett * A call in the form of macro-or-builtin() will result in:
959b50d902SRodney W. Grimes * argv[0] = nullstr
969b50d902SRodney W. Grimes * argv[1] = macro-or-builtin
979b50d902SRodney W. Grimes * argv[2] = nullstr
98acc9d408SJuli Mallett *
99acc9d408SJuli Mallett * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
1009b50d902SRodney W. Grimes */
1019b50d902SRodney W. Grimes void
eval(const char * argv[],int argc,int td,int is_traced)102a841e1ebSBaptiste Daroussin eval(const char *argv[], int argc, int td, int is_traced)
1039b50d902SRodney W. Grimes {
104a841e1ebSBaptiste Daroussin size_t mark = SIZE_MAX;
105acc9d408SJuli Mallett
106acc9d408SJuli Mallett expansion_id++;
107acc9d408SJuli Mallett if (td & RECDEF)
108a841e1ebSBaptiste Daroussin m4errx(1, "expanding recursive definition for %s.", argv[1]);
109a841e1ebSBaptiste Daroussin if (is_traced)
110acc9d408SJuli Mallett mark = trace(argv, argc, infile+ilevel);
111acc9d408SJuli Mallett if (td == MACRTYPE)
112acc9d408SJuli Mallett expand_macro(argv, argc);
113acc9d408SJuli Mallett else
114acc9d408SJuli Mallett expand_builtin(argv, argc, td);
115a841e1ebSBaptiste Daroussin if (mark != SIZE_MAX)
116acc9d408SJuli Mallett finish_trace(mark);
117acc9d408SJuli Mallett }
118acc9d408SJuli Mallett
119acc9d408SJuli Mallett /*
120acc9d408SJuli Mallett * expand_builtin - evaluate built-in macros.
121acc9d408SJuli Mallett */
122acc9d408SJuli Mallett void
expand_builtin(const char * argv[],int argc,int td)123bd2bfb58SJuli Mallett expand_builtin(const char *argv[], int argc, int td)
124acc9d408SJuli Mallett {
125acc9d408SJuli Mallett int c, n;
126db531a5dSBaptiste Daroussin const char *errstr;
127acc9d408SJuli Mallett int ac;
1289b50d902SRodney W. Grimes static int sysval = 0;
1299b50d902SRodney W. Grimes
1309b50d902SRodney W. Grimes #ifdef DEBUG
1319b50d902SRodney W. Grimes printf("argc = %d\n", argc);
1329b50d902SRodney W. Grimes for (n = 0; n < argc; n++)
1339b50d902SRodney W. Grimes printf("argv[%d] = %s\n", n, argv[n]);
134acc9d408SJuli Mallett fflush(stdout);
1359b50d902SRodney W. Grimes #endif
136acc9d408SJuli Mallett
1379b50d902SRodney W. Grimes /*
1389b50d902SRodney W. Grimes * if argc == 3 and argv[2] is null, then we
1399b50d902SRodney W. Grimes * have macro-or-builtin() type call. We adjust
1409b50d902SRodney W. Grimes * argc to avoid further checking..
1419b50d902SRodney W. Grimes */
142a841e1ebSBaptiste Daroussin /* we keep the initial value for those built-ins that differentiate
143a841e1ebSBaptiste Daroussin * between builtin() and builtin.
144a841e1ebSBaptiste Daroussin */
145acc9d408SJuli Mallett ac = argc;
146acc9d408SJuli Mallett
147a841e1ebSBaptiste Daroussin if (argc == 3 && !*(argv[2]) && !mimic_gnu)
1489b50d902SRodney W. Grimes argc--;
1499b50d902SRodney W. Grimes
150acc9d408SJuli Mallett switch (td & TYPEMASK) {
1519b50d902SRodney W. Grimes
1529b50d902SRodney W. Grimes case DEFITYPE:
1539b50d902SRodney W. Grimes if (argc > 2)
1549b50d902SRodney W. Grimes dodefine(argv[2], (argc > 3) ? argv[3] : null);
1559b50d902SRodney W. Grimes break;
1569b50d902SRodney W. Grimes
1579b50d902SRodney W. Grimes case PUSDTYPE:
1589b50d902SRodney W. Grimes if (argc > 2)
1599b50d902SRodney W. Grimes dopushdef(argv[2], (argc > 3) ? argv[3] : null);
1609b50d902SRodney W. Grimes break;
1619b50d902SRodney W. Grimes
1629b50d902SRodney W. Grimes case DUMPTYPE:
1639b50d902SRodney W. Grimes dodump(argv, argc);
1649b50d902SRodney W. Grimes break;
1659b50d902SRodney W. Grimes
166acc9d408SJuli Mallett case TRACEONTYPE:
167acc9d408SJuli Mallett dotrace(argv, argc, 1);
168acc9d408SJuli Mallett break;
169acc9d408SJuli Mallett
170acc9d408SJuli Mallett case TRACEOFFTYPE:
171acc9d408SJuli Mallett dotrace(argv, argc, 0);
172acc9d408SJuli Mallett break;
173acc9d408SJuli Mallett
1749b50d902SRodney W. Grimes case EXPRTYPE:
1759b50d902SRodney W. Grimes /*
1769b50d902SRodney W. Grimes * doexpr - evaluate arithmetic
1779b50d902SRodney W. Grimes * expression
1789b50d902SRodney W. Grimes */
179a841e1ebSBaptiste Daroussin {
180a841e1ebSBaptiste Daroussin int base = 10;
181a841e1ebSBaptiste Daroussin int maxdigits = 0;
182a841e1ebSBaptiste Daroussin const char *errstr;
183a841e1ebSBaptiste Daroussin
184a841e1ebSBaptiste Daroussin if (argc > 3) {
185a841e1ebSBaptiste Daroussin base = strtonum(argv[3], 2, 36, &errstr);
186a841e1ebSBaptiste Daroussin if (errstr) {
187db531a5dSBaptiste Daroussin m4errx(1, "expr: base is %s: %s.",
188db531a5dSBaptiste Daroussin errstr, argv[3]);
189a841e1ebSBaptiste Daroussin }
190a841e1ebSBaptiste Daroussin }
191a841e1ebSBaptiste Daroussin if (argc > 4) {
192a841e1ebSBaptiste Daroussin maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr);
193a841e1ebSBaptiste Daroussin if (errstr) {
194db531a5dSBaptiste Daroussin m4errx(1, "expr: maxdigits is %s: %s.",
195db531a5dSBaptiste Daroussin errstr, argv[4]);
196a841e1ebSBaptiste Daroussin }
197a841e1ebSBaptiste Daroussin }
1989b50d902SRodney W. Grimes if (argc > 2)
199a841e1ebSBaptiste Daroussin pbnumbase(expr(argv[2]), base, maxdigits);
2009b50d902SRodney W. Grimes break;
201a841e1ebSBaptiste Daroussin }
2029b50d902SRodney W. Grimes
2039b50d902SRodney W. Grimes case IFELTYPE:
2049b50d902SRodney W. Grimes doifelse(argv, argc);
2059b50d902SRodney W. Grimes break;
2069b50d902SRodney W. Grimes
2079b50d902SRodney W. Grimes case IFDFTYPE:
2089b50d902SRodney W. Grimes /*
2099b50d902SRodney W. Grimes * doifdef - select one of two
2109b50d902SRodney W. Grimes * alternatives based on the existence of
2119b50d902SRodney W. Grimes * another definition
2129b50d902SRodney W. Grimes */
2139b50d902SRodney W. Grimes if (argc > 3) {
214a841e1ebSBaptiste Daroussin if (lookup_macro_definition(argv[2]) != NULL)
2159b50d902SRodney W. Grimes pbstr(argv[3]);
2169b50d902SRodney W. Grimes else if (argc > 4)
2179b50d902SRodney W. Grimes pbstr(argv[4]);
2189b50d902SRodney W. Grimes }
2199b50d902SRodney W. Grimes break;
2209b50d902SRodney W. Grimes
2219b50d902SRodney W. Grimes case LENGTYPE:
2229b50d902SRodney W. Grimes /*
2239b50d902SRodney W. Grimes * dolen - find the length of the
2249b50d902SRodney W. Grimes * argument
2259b50d902SRodney W. Grimes */
2269b50d902SRodney W. Grimes pbnum((argc > 2) ? strlen(argv[2]) : 0);
2279b50d902SRodney W. Grimes break;
2289b50d902SRodney W. Grimes
2299b50d902SRodney W. Grimes case INCRTYPE:
2309b50d902SRodney W. Grimes /*
2319b50d902SRodney W. Grimes * doincr - increment the value of the
2329b50d902SRodney W. Grimes * argument
2339b50d902SRodney W. Grimes */
234db531a5dSBaptiste Daroussin if (argc > 2) {
235db531a5dSBaptiste Daroussin n = strtonum(argv[2], INT_MIN, INT_MAX-1, &errstr);
236db531a5dSBaptiste Daroussin if (errstr != NULL)
237db531a5dSBaptiste Daroussin m4errx(1, "incr: argument is %s: %s.",
238db531a5dSBaptiste Daroussin errstr, argv[2]);
239db531a5dSBaptiste Daroussin pbnum(n + 1);
240db531a5dSBaptiste Daroussin }
2419b50d902SRodney W. Grimes break;
2429b50d902SRodney W. Grimes
2439b50d902SRodney W. Grimes case DECRTYPE:
2449b50d902SRodney W. Grimes /*
2459b50d902SRodney W. Grimes * dodecr - decrement the value of the
2469b50d902SRodney W. Grimes * argument
2479b50d902SRodney W. Grimes */
248db531a5dSBaptiste Daroussin if (argc > 2) {
249db531a5dSBaptiste Daroussin n = strtonum(argv[2], INT_MIN+1, INT_MAX, &errstr);
250db531a5dSBaptiste Daroussin if (errstr)
251db531a5dSBaptiste Daroussin m4errx(1, "decr: argument is %s: %s.",
252db531a5dSBaptiste Daroussin errstr, argv[2]);
253db531a5dSBaptiste Daroussin pbnum(n - 1);
254db531a5dSBaptiste Daroussin }
2559b50d902SRodney W. Grimes break;
2569b50d902SRodney W. Grimes
2579b50d902SRodney W. Grimes case SYSCTYPE:
2589b50d902SRodney W. Grimes /*
2599b50d902SRodney W. Grimes * dosys - execute system command
2609b50d902SRodney W. Grimes */
261aef4bb33STim J. Robbins if (argc > 2) {
262a841e1ebSBaptiste Daroussin fflush(stdout);
2639b50d902SRodney W. Grimes sysval = system(argv[2]);
264aef4bb33STim J. Robbins }
2659b50d902SRodney W. Grimes break;
2669b50d902SRodney W. Grimes
2679b50d902SRodney W. Grimes case SYSVTYPE:
2689b50d902SRodney W. Grimes /*
2699b50d902SRodney W. Grimes * dosysval - return value of the last
2709b50d902SRodney W. Grimes * system call.
2719b50d902SRodney W. Grimes *
2729b50d902SRodney W. Grimes */
2739b50d902SRodney W. Grimes pbnum(sysval);
2749b50d902SRodney W. Grimes break;
2759b50d902SRodney W. Grimes
276acc9d408SJuli Mallett case ESYSCMDTYPE:
277acc9d408SJuli Mallett if (argc > 2)
278acc9d408SJuli Mallett doesyscmd(argv[2]);
279acc9d408SJuli Mallett break;
2809b50d902SRodney W. Grimes case INCLTYPE:
28188497f0cSBaptiste Daroussin if (argc > 2) {
2822cce1b69SBjoern A. Zeeb if (!doincl(argv[2])) {
283fb3f3d7cSBaptiste Daroussin if (mimic_gnu) {
2844fff7a14SBaptiste Daroussin warn("%s at line %lu: include(%s)",
2854fff7a14SBaptiste Daroussin CURRENT_NAME, CURRENT_LINE, argv[2]);
286fb3f3d7cSBaptiste Daroussin exit_code = 1;
287c560b67cSBaptiste Daroussin if (fatal_warns) {
288c560b67cSBaptiste Daroussin killdiv();
289c560b67cSBaptiste Daroussin exit(exit_code);
290c560b67cSBaptiste Daroussin }
291fb3f3d7cSBaptiste Daroussin } else
292acc9d408SJuli Mallett err(1, "%s at line %lu: include(%s)",
293acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]);
2942cce1b69SBjoern A. Zeeb }
29588497f0cSBaptiste Daroussin }
2969b50d902SRodney W. Grimes break;
2979b50d902SRodney W. Grimes
2989b50d902SRodney W. Grimes case SINCTYPE:
2999b50d902SRodney W. Grimes if (argc > 2)
3009b50d902SRodney W. Grimes (void) doincl(argv[2]);
3019b50d902SRodney W. Grimes break;
3029b50d902SRodney W. Grimes #ifdef EXTENDED
3039b50d902SRodney W. Grimes case PASTTYPE:
3049b50d902SRodney W. Grimes if (argc > 2)
3059b50d902SRodney W. Grimes if (!dopaste(argv[2]))
306acc9d408SJuli Mallett err(1, "%s at line %lu: paste(%s)",
307acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]);
3089b50d902SRodney W. Grimes break;
3099b50d902SRodney W. Grimes
3109b50d902SRodney W. Grimes case SPASTYPE:
3119b50d902SRodney W. Grimes if (argc > 2)
3129b50d902SRodney W. Grimes (void) dopaste(argv[2]);
3139b50d902SRodney W. Grimes break;
314a841e1ebSBaptiste Daroussin case FORMATTYPE:
315a841e1ebSBaptiste Daroussin doformat(argv, argc);
316a841e1ebSBaptiste Daroussin break;
3179b50d902SRodney W. Grimes #endif
3189b50d902SRodney W. Grimes case CHNQTYPE:
319a841e1ebSBaptiste Daroussin dochq(argv, ac);
3209b50d902SRodney W. Grimes break;
3219b50d902SRodney W. Grimes
3229b50d902SRodney W. Grimes case CHNCTYPE:
3239b50d902SRodney W. Grimes dochc(argv, argc);
3249b50d902SRodney W. Grimes break;
3259b50d902SRodney W. Grimes
3269b50d902SRodney W. Grimes case SUBSTYPE:
3279b50d902SRodney W. Grimes /*
3289b50d902SRodney W. Grimes * dosub - select substring
3299b50d902SRodney W. Grimes *
3309b50d902SRodney W. Grimes */
3319b50d902SRodney W. Grimes if (argc > 3)
3329b50d902SRodney W. Grimes dosub(argv, argc);
3339b50d902SRodney W. Grimes break;
3349b50d902SRodney W. Grimes
3359b50d902SRodney W. Grimes case SHIFTYPE:
3369b50d902SRodney W. Grimes /*
3379b50d902SRodney W. Grimes * doshift - push back all arguments
3389b50d902SRodney W. Grimes * except the first one (i.e. skip
3399b50d902SRodney W. Grimes * argv[2])
3409b50d902SRodney W. Grimes */
3419b50d902SRodney W. Grimes if (argc > 3) {
3429b50d902SRodney W. Grimes for (n = argc - 1; n > 3; n--) {
343acc9d408SJuli Mallett pbstr(rquote);
3449b50d902SRodney W. Grimes pbstr(argv[n]);
345acc9d408SJuli Mallett pbstr(lquote);
346a841e1ebSBaptiste Daroussin pushback(COMMA);
3479b50d902SRodney W. Grimes }
348acc9d408SJuli Mallett pbstr(rquote);
3499b50d902SRodney W. Grimes pbstr(argv[3]);
350acc9d408SJuli Mallett pbstr(lquote);
3519b50d902SRodney W. Grimes }
3529b50d902SRodney W. Grimes break;
3539b50d902SRodney W. Grimes
3549b50d902SRodney W. Grimes case DIVRTYPE:
355db531a5dSBaptiste Daroussin if (argc > 2) {
356db531a5dSBaptiste Daroussin n = strtonum(argv[2], INT_MIN, INT_MAX, &errstr);
357db531a5dSBaptiste Daroussin if (errstr)
358db531a5dSBaptiste Daroussin m4errx(1, "divert: argument is %s: %s.",
359db531a5dSBaptiste Daroussin errstr, argv[2]);
360db531a5dSBaptiste Daroussin if (n != 0) {
3619b50d902SRodney W. Grimes dodiv(n);
362db531a5dSBaptiste Daroussin break;
363db531a5dSBaptiste Daroussin }
364db531a5dSBaptiste Daroussin }
3659b50d902SRodney W. Grimes active = stdout;
3669b50d902SRodney W. Grimes oindex = 0;
3679b50d902SRodney W. Grimes break;
3689b50d902SRodney W. Grimes
3699b50d902SRodney W. Grimes case UNDVTYPE:
3709b50d902SRodney W. Grimes doundiv(argv, argc);
3719b50d902SRodney W. Grimes break;
3729b50d902SRodney W. Grimes
3739b50d902SRodney W. Grimes case DIVNTYPE:
3749b50d902SRodney W. Grimes /*
3759b50d902SRodney W. Grimes * dodivnum - return the number of
3769b50d902SRodney W. Grimes * current output diversion
3779b50d902SRodney W. Grimes */
3789b50d902SRodney W. Grimes pbnum(oindex);
3799b50d902SRodney W. Grimes break;
3809b50d902SRodney W. Grimes
3819b50d902SRodney W. Grimes case UNDFTYPE:
3829b50d902SRodney W. Grimes /*
3839b50d902SRodney W. Grimes * doundefine - undefine a previously
3849b50d902SRodney W. Grimes * defined macro(s) or m4 keyword(s).
3859b50d902SRodney W. Grimes */
3869b50d902SRodney W. Grimes if (argc > 2)
3879b50d902SRodney W. Grimes for (n = 2; n < argc; n++)
388a841e1ebSBaptiste Daroussin macro_undefine(argv[n]);
3899b50d902SRodney W. Grimes break;
3909b50d902SRodney W. Grimes
3919b50d902SRodney W. Grimes case POPDTYPE:
3929b50d902SRodney W. Grimes /*
3939b50d902SRodney W. Grimes * dopopdef - remove the topmost
3949b50d902SRodney W. Grimes * definitions of macro(s) or m4
3959b50d902SRodney W. Grimes * keyword(s).
3969b50d902SRodney W. Grimes */
3979b50d902SRodney W. Grimes if (argc > 2)
3989b50d902SRodney W. Grimes for (n = 2; n < argc; n++)
399a841e1ebSBaptiste Daroussin macro_popdef(argv[n]);
4009b50d902SRodney W. Grimes break;
4019b50d902SRodney W. Grimes
4029b50d902SRodney W. Grimes case MKTMTYPE:
4039b50d902SRodney W. Grimes /*
4049b50d902SRodney W. Grimes * dotemp - create a temporary file
4059b50d902SRodney W. Grimes */
406acc9d408SJuli Mallett if (argc > 2) {
407acc9d408SJuli Mallett int fd;
408acc9d408SJuli Mallett char *temp;
409acc9d408SJuli Mallett
410acc9d408SJuli Mallett temp = xstrdup(argv[2]);
411acc9d408SJuli Mallett
412acc9d408SJuli Mallett fd = mkstemp(temp);
413acc9d408SJuli Mallett if (fd == -1)
414acc9d408SJuli Mallett err(1,
415acc9d408SJuli Mallett "%s at line %lu: couldn't make temp file %s",
416acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]);
417acc9d408SJuli Mallett close(fd);
418acc9d408SJuli Mallett pbstr(temp);
419acc9d408SJuli Mallett free(temp);
420acc9d408SJuli Mallett }
4219b50d902SRodney W. Grimes break;
4229b50d902SRodney W. Grimes
4239b50d902SRodney W. Grimes case TRNLTYPE:
4249b50d902SRodney W. Grimes /*
4259b50d902SRodney W. Grimes * dotranslit - replace all characters in
4269b50d902SRodney W. Grimes * the source string that appears in the
4279b50d902SRodney W. Grimes * "from" string with the corresponding
4289b50d902SRodney W. Grimes * characters in the "to" string.
4299b50d902SRodney W. Grimes */
4309b50d902SRodney W. Grimes if (argc > 3) {
431acc9d408SJuli Mallett char *temp;
432acc9d408SJuli Mallett
433a841e1ebSBaptiste Daroussin temp = xalloc(strlen(argv[2])+1, NULL);
4349b50d902SRodney W. Grimes if (argc > 4)
4359b50d902SRodney W. Grimes map(temp, argv[2], argv[3], argv[4]);
4369b50d902SRodney W. Grimes else
4379b50d902SRodney W. Grimes map(temp, argv[2], argv[3], null);
4389b50d902SRodney W. Grimes pbstr(temp);
439acc9d408SJuli Mallett free(temp);
440acc9d408SJuli Mallett } else if (argc > 2)
4419b50d902SRodney W. Grimes pbstr(argv[2]);
4429b50d902SRodney W. Grimes break;
4439b50d902SRodney W. Grimes
4449b50d902SRodney W. Grimes case INDXTYPE:
4459b50d902SRodney W. Grimes /*
4469b50d902SRodney W. Grimes * doindex - find the index of the second
4479b50d902SRodney W. Grimes * argument string in the first argument
4489b50d902SRodney W. Grimes * string. -1 if not present.
4499b50d902SRodney W. Grimes */
4509b50d902SRodney W. Grimes pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
4519b50d902SRodney W. Grimes break;
4529b50d902SRodney W. Grimes
4539b50d902SRodney W. Grimes case ERRPTYPE:
4549b50d902SRodney W. Grimes /*
4559b50d902SRodney W. Grimes * doerrp - print the arguments to stderr
4569b50d902SRodney W. Grimes * file
4579b50d902SRodney W. Grimes */
4589b50d902SRodney W. Grimes if (argc > 2) {
4599b50d902SRodney W. Grimes for (n = 2; n < argc; n++)
4609b50d902SRodney W. Grimes fprintf(stderr, "%s ", argv[n]);
4619b50d902SRodney W. Grimes fprintf(stderr, "\n");
4629b50d902SRodney W. Grimes }
4639b50d902SRodney W. Grimes break;
4649b50d902SRodney W. Grimes
4659b50d902SRodney W. Grimes case DNLNTYPE:
4669b50d902SRodney W. Grimes /*
4679b50d902SRodney W. Grimes * dodnl - eat-up-to and including
4689b50d902SRodney W. Grimes * newline
4699b50d902SRodney W. Grimes */
4709b50d902SRodney W. Grimes while ((c = gpbc()) != '\n' && c != EOF)
4719b50d902SRodney W. Grimes ;
4729b50d902SRodney W. Grimes break;
4739b50d902SRodney W. Grimes
4749b50d902SRodney W. Grimes case M4WRTYPE:
4759b50d902SRodney W. Grimes /*
4769b50d902SRodney W. Grimes * dom4wrap - set up for
4779b50d902SRodney W. Grimes * wrap-up/wind-down activity
4789b50d902SRodney W. Grimes */
479a841e1ebSBaptiste Daroussin if (argc > 2)
480a841e1ebSBaptiste Daroussin dom4wrap(argv[2]);
4819b50d902SRodney W. Grimes break;
4829b50d902SRodney W. Grimes
4839b50d902SRodney W. Grimes case EXITTYPE:
4849b50d902SRodney W. Grimes /*
4859b50d902SRodney W. Grimes * doexit - immediate exit from m4.
4869b50d902SRodney W. Grimes */
487cac6992aSAndrey A. Chernov killdiv();
4889b50d902SRodney W. Grimes exit((argc > 2) ? atoi(argv[2]) : 0);
4899b50d902SRodney W. Grimes break;
4909b50d902SRodney W. Grimes
4919b50d902SRodney W. Grimes case DEFNTYPE:
4929b50d902SRodney W. Grimes if (argc > 2)
4939b50d902SRodney W. Grimes for (n = 2; n < argc; n++)
4949b50d902SRodney W. Grimes dodefn(argv[n]);
4959b50d902SRodney W. Grimes break;
4969b50d902SRodney W. Grimes
497acc9d408SJuli Mallett case INDIRTYPE: /* Indirect call */
498acc9d408SJuli Mallett if (argc > 2)
499acc9d408SJuli Mallett doindir(argv, argc);
500bbfd1447SSteve Price break;
501bbfd1447SSteve Price
502acc9d408SJuli Mallett case BUILTINTYPE: /* Builtins only */
503acc9d408SJuli Mallett if (argc > 2)
504acc9d408SJuli Mallett dobuiltin(argv, argc);
505acc9d408SJuli Mallett break;
506acc9d408SJuli Mallett
507acc9d408SJuli Mallett case PATSTYPE:
508acc9d408SJuli Mallett if (argc > 2)
509acc9d408SJuli Mallett dopatsubst(argv, argc);
510acc9d408SJuli Mallett break;
511acc9d408SJuli Mallett case REGEXPTYPE:
512acc9d408SJuli Mallett if (argc > 2)
513acc9d408SJuli Mallett doregexp(argv, argc);
514acc9d408SJuli Mallett break;
515acc9d408SJuli Mallett case LINETYPE:
516acc9d408SJuli Mallett doprintlineno(infile+ilevel);
517acc9d408SJuli Mallett break;
518acc9d408SJuli Mallett case FILENAMETYPE:
519acc9d408SJuli Mallett doprintfilename(infile+ilevel);
520acc9d408SJuli Mallett break;
521acc9d408SJuli Mallett case SELFTYPE:
522acc9d408SJuli Mallett pbstr(rquote);
523acc9d408SJuli Mallett pbstr(argv[1]);
524acc9d408SJuli Mallett pbstr(lquote);
525acc9d408SJuli Mallett break;
5269b50d902SRodney W. Grimes default:
527a841e1ebSBaptiste Daroussin m4errx(1, "eval: major botch.");
5289b50d902SRodney W. Grimes break;
5299b50d902SRodney W. Grimes }
5309b50d902SRodney W. Grimes }
5319b50d902SRodney W. Grimes
5329b50d902SRodney W. Grimes /*
533acc9d408SJuli Mallett * expand_macro - user-defined macro expansion
5349b50d902SRodney W. Grimes */
5359b50d902SRodney W. Grimes void
expand_macro(const char * argv[],int argc)536bd2bfb58SJuli Mallett expand_macro(const char *argv[], int argc)
5379b50d902SRodney W. Grimes {
538acc9d408SJuli Mallett const char *t;
539acc9d408SJuli Mallett const char *p;
540acc9d408SJuli Mallett int n;
541acc9d408SJuli Mallett int argno;
5429b50d902SRodney W. Grimes
5439b50d902SRodney W. Grimes t = argv[0]; /* defn string as a whole */
5449b50d902SRodney W. Grimes p = t;
5459b50d902SRodney W. Grimes while (*p)
5469b50d902SRodney W. Grimes p++;
5479b50d902SRodney W. Grimes p--; /* last character of defn */
5489b50d902SRodney W. Grimes while (p > t) {
5499b50d902SRodney W. Grimes if (*(p - 1) != ARGFLAG)
550a841e1ebSBaptiste Daroussin PUSHBACK(*p);
5519b50d902SRodney W. Grimes else {
5529b50d902SRodney W. Grimes switch (*p) {
5539b50d902SRodney W. Grimes
5549b50d902SRodney W. Grimes case '#':
5559b50d902SRodney W. Grimes pbnum(argc - 2);
5569b50d902SRodney W. Grimes break;
5579b50d902SRodney W. Grimes case '0':
5589b50d902SRodney W. Grimes case '1':
5599b50d902SRodney W. Grimes case '2':
5609b50d902SRodney W. Grimes case '3':
5619b50d902SRodney W. Grimes case '4':
5629b50d902SRodney W. Grimes case '5':
5639b50d902SRodney W. Grimes case '6':
5649b50d902SRodney W. Grimes case '7':
5659b50d902SRodney W. Grimes case '8':
5669b50d902SRodney W. Grimes case '9':
5679b50d902SRodney W. Grimes if ((argno = *p - '0') < argc - 1)
5689b50d902SRodney W. Grimes pbstr(argv[argno + 1]);
5699b50d902SRodney W. Grimes break;
5709b50d902SRodney W. Grimes case '*':
571acc9d408SJuli Mallett if (argc > 2) {
5729b50d902SRodney W. Grimes for (n = argc - 1; n > 2; n--) {
5739b50d902SRodney W. Grimes pbstr(argv[n]);
574a841e1ebSBaptiste Daroussin pushback(COMMA);
5759b50d902SRodney W. Grimes }
5769b50d902SRodney W. Grimes pbstr(argv[2]);
577acc9d408SJuli Mallett }
5789b50d902SRodney W. Grimes break;
579232eaee6SJoerg Wunsch case '@':
580acc9d408SJuli Mallett if (argc > 2) {
581acc9d408SJuli Mallett for (n = argc - 1; n > 2; n--) {
582acc9d408SJuli Mallett pbstr(rquote);
583232eaee6SJoerg Wunsch pbstr(argv[n]);
584acc9d408SJuli Mallett pbstr(lquote);
585a841e1ebSBaptiste Daroussin pushback(COMMA);
586acc9d408SJuli Mallett }
587acc9d408SJuli Mallett pbstr(rquote);
588acc9d408SJuli Mallett pbstr(argv[2]);
589acc9d408SJuli Mallett pbstr(lquote);
590232eaee6SJoerg Wunsch }
591232eaee6SJoerg Wunsch break;
5929b50d902SRodney W. Grimes default:
593a841e1ebSBaptiste Daroussin PUSHBACK(*p);
594a841e1ebSBaptiste Daroussin PUSHBACK('$');
5959b50d902SRodney W. Grimes break;
5969b50d902SRodney W. Grimes }
5979b50d902SRodney W. Grimes p--;
5989b50d902SRodney W. Grimes }
5999b50d902SRodney W. Grimes p--;
6009b50d902SRodney W. Grimes }
6019b50d902SRodney W. Grimes if (p == t) /* do last character */
602a841e1ebSBaptiste Daroussin PUSHBACK(*p);
6039b50d902SRodney W. Grimes }
6049b50d902SRodney W. Grimes
605a841e1ebSBaptiste Daroussin
6069b50d902SRodney W. Grimes /*
6079b50d902SRodney W. Grimes * dodefine - install definition in the table
6089b50d902SRodney W. Grimes */
6099b50d902SRodney W. Grimes void
dodefine(const char * name,const char * defn)610bd2bfb58SJuli Mallett dodefine(const char *name, const char *defn)
6119b50d902SRodney W. Grimes {
612a841e1ebSBaptiste Daroussin if (!*name && !mimic_gnu)
613a841e1ebSBaptiste Daroussin m4errx(1, "null definition.");
6149b50d902SRodney W. Grimes else
615a841e1ebSBaptiste Daroussin macro_define(name, defn);
6169b50d902SRodney W. Grimes }
6179b50d902SRodney W. Grimes
6189b50d902SRodney W. Grimes /*
6199b50d902SRodney W. Grimes * dodefn - push back a quoted definition of
6209b50d902SRodney W. Grimes * the given name.
6219b50d902SRodney W. Grimes */
622acc9d408SJuli Mallett static void
dodefn(const char * name)623bd2bfb58SJuli Mallett dodefn(const char *name)
6249b50d902SRodney W. Grimes {
625a841e1ebSBaptiste Daroussin struct macro_definition *p;
6269b50d902SRodney W. Grimes
627a841e1ebSBaptiste Daroussin if ((p = lookup_macro_definition(name)) != NULL) {
628a841e1ebSBaptiste Daroussin if ((p->type & TYPEMASK) == MACRTYPE) {
629acc9d408SJuli Mallett pbstr(rquote);
6309b50d902SRodney W. Grimes pbstr(p->defn);
631acc9d408SJuli Mallett pbstr(lquote);
632a841e1ebSBaptiste Daroussin } else {
633a841e1ebSBaptiste Daroussin pbstr(p->defn);
634acc9d408SJuli Mallett pbstr(BUILTIN_MARKER);
635acc9d408SJuli Mallett }
6369b50d902SRodney W. Grimes }
6379b50d902SRodney W. Grimes }
6389b50d902SRodney W. Grimes
6399b50d902SRodney W. Grimes /*
6409b50d902SRodney W. Grimes * dopushdef - install a definition in the hash table
6419b50d902SRodney W. Grimes * without removing a previous definition. Since
6429b50d902SRodney W. Grimes * each new entry is entered in *front* of the
6439b50d902SRodney W. Grimes * hash bucket, it hides a previous definition from
6449b50d902SRodney W. Grimes * lookup.
6459b50d902SRodney W. Grimes */
646acc9d408SJuli Mallett static void
dopushdef(const char * name,const char * defn)647bd2bfb58SJuli Mallett dopushdef(const char *name, const char *defn)
6489b50d902SRodney W. Grimes {
649a841e1ebSBaptiste Daroussin if (!*name && !mimic_gnu)
650a841e1ebSBaptiste Daroussin m4errx(1, "null definition.");
6519b50d902SRodney W. Grimes else
652a841e1ebSBaptiste Daroussin macro_pushdef(name, defn);
653acc9d408SJuli Mallett }
654acc9d408SJuli Mallett
655acc9d408SJuli Mallett /*
656acc9d408SJuli Mallett * dump_one_def - dump the specified definition.
657acc9d408SJuli Mallett */
658acc9d408SJuli Mallett static void
dump_one_def(const char * name,struct macro_definition * p)659a841e1ebSBaptiste Daroussin dump_one_def(const char *name, struct macro_definition *p)
660acc9d408SJuli Mallett {
661a841e1ebSBaptiste Daroussin if (!traceout)
662a841e1ebSBaptiste Daroussin traceout = stderr;
663acc9d408SJuli Mallett if (mimic_gnu) {
664acc9d408SJuli Mallett if ((p->type & TYPEMASK) == MACRTYPE)
665a841e1ebSBaptiste Daroussin fprintf(traceout, "%s:\t%s\n", name, p->defn);
666acc9d408SJuli Mallett else {
667a841e1ebSBaptiste Daroussin fprintf(traceout, "%s:\t<%s>\n", name, p->defn);
668acc9d408SJuli Mallett }
669acc9d408SJuli Mallett } else
670a841e1ebSBaptiste Daroussin fprintf(traceout, "`%s'\t`%s'\n", name, p->defn);
6719b50d902SRodney W. Grimes }
6729b50d902SRodney W. Grimes
6739b50d902SRodney W. Grimes /*
6749b50d902SRodney W. Grimes * dodumpdef - dump the specified definitions in the hash
6759b50d902SRodney W. Grimes * table to stderr. If nothing is specified, the entire
6769b50d902SRodney W. Grimes * hash table is dumped.
6779b50d902SRodney W. Grimes */
678acc9d408SJuli Mallett static void
dodump(const char * argv[],int argc)679bd2bfb58SJuli Mallett dodump(const char *argv[], int argc)
6809b50d902SRodney W. Grimes {
681acc9d408SJuli Mallett int n;
682a841e1ebSBaptiste Daroussin struct macro_definition *p;
6839b50d902SRodney W. Grimes
6849b50d902SRodney W. Grimes if (argc > 2) {
6859b50d902SRodney W. Grimes for (n = 2; n < argc; n++)
686a841e1ebSBaptiste Daroussin if ((p = lookup_macro_definition(argv[n])) != NULL)
687a841e1ebSBaptiste Daroussin dump_one_def(argv[n], p);
688a841e1ebSBaptiste Daroussin } else
689a841e1ebSBaptiste Daroussin macro_for_all(dump_one_def);
6909b50d902SRodney W. Grimes }
6919b50d902SRodney W. Grimes
6929b50d902SRodney W. Grimes /*
693acc9d408SJuli Mallett * dotrace - mark some macros as traced/untraced depending upon on.
694acc9d408SJuli Mallett */
695acc9d408SJuli Mallett static void
dotrace(const char * argv[],int argc,int on)696bd2bfb58SJuli Mallett dotrace(const char *argv[], int argc, int on)
697acc9d408SJuli Mallett {
698acc9d408SJuli Mallett int n;
699acc9d408SJuli Mallett
700acc9d408SJuli Mallett if (argc > 2) {
701acc9d408SJuli Mallett for (n = 2; n < argc; n++)
702acc9d408SJuli Mallett mark_traced(argv[n], on);
703acc9d408SJuli Mallett } else
704acc9d408SJuli Mallett mark_traced(NULL, on);
705acc9d408SJuli Mallett }
706acc9d408SJuli Mallett
707acc9d408SJuli Mallett /*
7089b50d902SRodney W. Grimes * doifelse - select one of two alternatives - loop.
7099b50d902SRodney W. Grimes */
710acc9d408SJuli Mallett static void
doifelse(const char * argv[],int argc)711bd2bfb58SJuli Mallett doifelse(const char *argv[], int argc)
7129b50d902SRodney W. Grimes {
713e0f4e041SBaptiste Daroussin while (argc > 4) {
714e0f4e041SBaptiste Daroussin if (STREQ(argv[2], argv[3])) {
7159b50d902SRodney W. Grimes pbstr(argv[4]);
716e0f4e041SBaptiste Daroussin break;
717e0f4e041SBaptiste Daroussin } else if (argc == 6) {
7189b50d902SRodney W. Grimes pbstr(argv[5]);
719e0f4e041SBaptiste Daroussin break;
720e0f4e041SBaptiste Daroussin } else {
7219b50d902SRodney W. Grimes argv += 3;
7229b50d902SRodney W. Grimes argc -= 3;
7239b50d902SRodney W. Grimes }
7249b50d902SRodney W. Grimes }
7259b50d902SRodney W. Grimes }
7269b50d902SRodney W. Grimes
7279b50d902SRodney W. Grimes /*
7289b50d902SRodney W. Grimes * doinclude - include a given file.
7299b50d902SRodney W. Grimes */
730acc9d408SJuli Mallett static int
doincl(const char * ifile)731bd2bfb58SJuli Mallett doincl(const char *ifile)
7329b50d902SRodney W. Grimes {
7339b50d902SRodney W. Grimes if (ilevel + 1 == MAXINP)
734a841e1ebSBaptiste Daroussin m4errx(1, "too many include files.");
735acc9d408SJuli Mallett if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
7369b50d902SRodney W. Grimes ilevel++;
7379b50d902SRodney W. Grimes bbase[ilevel] = bufbase = bp;
7389b50d902SRodney W. Grimes return (1);
739acc9d408SJuli Mallett } else
7409b50d902SRodney W. Grimes return (0);
7419b50d902SRodney W. Grimes }
7429b50d902SRodney W. Grimes
7439b50d902SRodney W. Grimes #ifdef EXTENDED
7449b50d902SRodney W. Grimes /*
7459b50d902SRodney W. Grimes * dopaste - include a given file without any
7469b50d902SRodney W. Grimes * macro processing.
7479b50d902SRodney W. Grimes */
748acc9d408SJuli Mallett static int
dopaste(const char * pfile)749bd2bfb58SJuli Mallett dopaste(const char *pfile)
7509b50d902SRodney W. Grimes {
7519b50d902SRodney W. Grimes FILE *pf;
752acc9d408SJuli Mallett int c;
7539b50d902SRodney W. Grimes
7549b50d902SRodney W. Grimes if ((pf = fopen(pfile, "r")) != NULL) {
755a841e1ebSBaptiste Daroussin if (synch_lines)
756b1ea3d46SJuli Mallett fprintf(active, "#line 1 \"%s\"\n", pfile);
7579b50d902SRodney W. Grimes while ((c = getc(pf)) != EOF)
7589b50d902SRodney W. Grimes putc(c, active);
7599b50d902SRodney W. Grimes (void) fclose(pf);
760a841e1ebSBaptiste Daroussin emit_synchline();
7619b50d902SRodney W. Grimes return (1);
762acc9d408SJuli Mallett } else
7639b50d902SRodney W. Grimes return (0);
7649b50d902SRodney W. Grimes }
7659b50d902SRodney W. Grimes #endif
7669b50d902SRodney W. Grimes
7679b50d902SRodney W. Grimes /*
768acc9d408SJuli Mallett * dochq - change quote characters
7699b50d902SRodney W. Grimes */
770acc9d408SJuli Mallett static void
dochq(const char * argv[],int ac)771a841e1ebSBaptiste Daroussin dochq(const char *argv[], int ac)
7729b50d902SRodney W. Grimes {
773a841e1ebSBaptiste Daroussin if (ac == 2) {
774a841e1ebSBaptiste Daroussin lquote[0] = LQUOTE; lquote[1] = EOS;
775a841e1ebSBaptiste Daroussin rquote[0] = RQUOTE; rquote[1] = EOS;
776acc9d408SJuli Mallett } else {
777a841e1ebSBaptiste Daroussin strlcpy(lquote, argv[2], sizeof(lquote));
778a841e1ebSBaptiste Daroussin if (ac > 3) {
779a841e1ebSBaptiste Daroussin strlcpy(rquote, argv[3], sizeof(rquote));
780a841e1ebSBaptiste Daroussin } else {
781a841e1ebSBaptiste Daroussin rquote[0] = ECOMMT; rquote[1] = EOS;
782a841e1ebSBaptiste Daroussin }
783acc9d408SJuli Mallett }
784acc9d408SJuli Mallett }
785acc9d408SJuli Mallett
786acc9d408SJuli Mallett /*
787acc9d408SJuli Mallett * dochc - change comment characters
788acc9d408SJuli Mallett */
789acc9d408SJuli Mallett static void
dochc(const char * argv[],int argc)790bd2bfb58SJuli Mallett dochc(const char *argv[], int argc)
791acc9d408SJuli Mallett {
792a841e1ebSBaptiste Daroussin /* XXX Note that there is no difference between no argument and a single
793a841e1ebSBaptiste Daroussin * empty argument.
794a841e1ebSBaptiste Daroussin */
795a841e1ebSBaptiste Daroussin if (argc == 2) {
796a841e1ebSBaptiste Daroussin scommt[0] = EOS;
797a841e1ebSBaptiste Daroussin ecommt[0] = EOS;
798a841e1ebSBaptiste Daroussin } else {
799acc9d408SJuli Mallett strlcpy(scommt, argv[2], sizeof(scommt));
800a841e1ebSBaptiste Daroussin if (argc == 3) {
801a841e1ebSBaptiste Daroussin ecommt[0] = ECOMMT; ecommt[1] = EOS;
802a841e1ebSBaptiste Daroussin } else {
803acc9d408SJuli Mallett strlcpy(ecommt, argv[3], sizeof(ecommt));
8049b50d902SRodney W. Grimes }
805a841e1ebSBaptiste Daroussin }
806a841e1ebSBaptiste Daroussin }
807a841e1ebSBaptiste Daroussin
808a841e1ebSBaptiste Daroussin /*
809a841e1ebSBaptiste Daroussin * dom4wrap - expand text at EOF
810a841e1ebSBaptiste Daroussin */
811a841e1ebSBaptiste Daroussin static void
dom4wrap(const char * text)812a841e1ebSBaptiste Daroussin dom4wrap(const char *text)
813a841e1ebSBaptiste Daroussin {
814a841e1ebSBaptiste Daroussin if (wrapindex >= maxwraps) {
815a841e1ebSBaptiste Daroussin if (maxwraps == 0)
816a841e1ebSBaptiste Daroussin maxwraps = 16;
8179b50d902SRodney W. Grimes else
818a841e1ebSBaptiste Daroussin maxwraps *= 2;
81988497f0cSBaptiste Daroussin m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps),
820a841e1ebSBaptiste Daroussin "too many m4wraps");
8219b50d902SRodney W. Grimes }
822a841e1ebSBaptiste Daroussin m4wraps[wrapindex++] = xstrdup(text);
8239b50d902SRodney W. Grimes }
8249b50d902SRodney W. Grimes
8259b50d902SRodney W. Grimes /*
8269b50d902SRodney W. Grimes * dodivert - divert the output to a temporary file
8279b50d902SRodney W. Grimes */
828acc9d408SJuli Mallett static void
dodiv(int n)829bd2bfb58SJuli Mallett dodiv(int n)
8309b50d902SRodney W. Grimes {
831acc9d408SJuli Mallett int fd;
832acc9d408SJuli Mallett
833ef2cea81SJonathan Lemon oindex = n;
834acc9d408SJuli Mallett if (n >= maxout) {
835acc9d408SJuli Mallett if (mimic_gnu)
836acc9d408SJuli Mallett resizedivs(n + 10);
837acc9d408SJuli Mallett else
838acc9d408SJuli Mallett n = 0; /* bitbucket */
839acc9d408SJuli Mallett }
840acc9d408SJuli Mallett
841acc9d408SJuli Mallett if (n < 0)
8429b50d902SRodney W. Grimes n = 0; /* bitbucket */
8439b50d902SRodney W. Grimes if (outfile[n] == NULL) {
844acc9d408SJuli Mallett char fname[] = _PATH_DIVNAME;
845acc9d408SJuli Mallett
846*c57596e1SBaptiste Daroussin if ((fd = mkstemp(fname)) == -1 ||
84788497f0cSBaptiste Daroussin unlink(fname) == -1 ||
848acc9d408SJuli Mallett (outfile[n] = fdopen(fd, "w+")) == NULL)
849acc9d408SJuli Mallett err(1, "%s: cannot divert", fname);
8509b50d902SRodney W. Grimes }
8519b50d902SRodney W. Grimes active = outfile[n];
8529b50d902SRodney W. Grimes }
8539b50d902SRodney W. Grimes
8549b50d902SRodney W. Grimes /*
8559b50d902SRodney W. Grimes * doundivert - undivert a specified output, or all
8569b50d902SRodney W. Grimes * other outputs, in numerical order.
8579b50d902SRodney W. Grimes */
858acc9d408SJuli Mallett static void
doundiv(const char * argv[],int argc)859bd2bfb58SJuli Mallett doundiv(const char *argv[], int argc)
8609b50d902SRodney W. Grimes {
861acc9d408SJuli Mallett int ind;
862acc9d408SJuli Mallett int n;
8639b50d902SRodney W. Grimes
8649b50d902SRodney W. Grimes if (argc > 2) {
8659b50d902SRodney W. Grimes for (ind = 2; ind < argc; ind++) {
866a841e1ebSBaptiste Daroussin const char *errstr;
867a841e1ebSBaptiste Daroussin n = strtonum(argv[ind], 1, INT_MAX, &errstr);
868a841e1ebSBaptiste Daroussin if (errstr) {
869a841e1ebSBaptiste Daroussin if (errno == EINVAL && mimic_gnu)
870a841e1ebSBaptiste Daroussin getdivfile(argv[ind]);
871a841e1ebSBaptiste Daroussin } else {
872a841e1ebSBaptiste Daroussin if (n < maxout && outfile[n] != NULL)
8739b50d902SRodney W. Grimes getdiv(n);
874a841e1ebSBaptiste Daroussin }
8759b50d902SRodney W. Grimes }
8769b50d902SRodney W. Grimes }
8779b50d902SRodney W. Grimes else
878acc9d408SJuli Mallett for (n = 1; n < maxout; n++)
8799b50d902SRodney W. Grimes if (outfile[n] != NULL)
8809b50d902SRodney W. Grimes getdiv(n);
8819b50d902SRodney W. Grimes }
8829b50d902SRodney W. Grimes
8839b50d902SRodney W. Grimes /*
8849b50d902SRodney W. Grimes * dosub - select substring
8859b50d902SRodney W. Grimes */
886acc9d408SJuli Mallett static void
dosub(const char * argv[],int argc)887bd2bfb58SJuli Mallett dosub(const char *argv[], int argc)
8889b50d902SRodney W. Grimes {
889acc9d408SJuli Mallett const char *ap, *fc, *k;
890acc9d408SJuli Mallett int nc;
8919b50d902SRodney W. Grimes
8929b50d902SRodney W. Grimes ap = argv[2]; /* target string */
8939b50d902SRodney W. Grimes #ifdef EXPR
8949b50d902SRodney W. Grimes fc = ap + expr(argv[3]); /* first char */
8959b50d902SRodney W. Grimes #else
8969b50d902SRodney W. Grimes fc = ap + atoi(argv[3]); /* first char */
8979b50d902SRodney W. Grimes #endif
8984ba4d387SGregory Neil Shapiro nc = strlen(fc);
899acc9d408SJuli Mallett if (argc >= 5)
9004ba4d387SGregory Neil Shapiro #ifdef EXPR
901acc9d408SJuli Mallett nc = min(nc, expr(argv[4]));
9024ba4d387SGregory Neil Shapiro #else
903acc9d408SJuli Mallett nc = min(nc, atoi(argv[4]));
9044ba4d387SGregory Neil Shapiro #endif
9059b50d902SRodney W. Grimes if (fc >= ap && fc < ap + strlen(ap))
9064ba4d387SGregory Neil Shapiro for (k = fc + nc - 1; k >= fc; k--)
907a841e1ebSBaptiste Daroussin pushback(*k);
9089b50d902SRodney W. Grimes }
9099b50d902SRodney W. Grimes
9109b50d902SRodney W. Grimes /*
9119b50d902SRodney W. Grimes * map:
9129b50d902SRodney W. Grimes * map every character of s1 that is specified in from
9139b50d902SRodney W. Grimes * into s3 and replace in s. (source s1 remains untouched)
9149b50d902SRodney W. Grimes *
915a841e1ebSBaptiste Daroussin * This is derived from the a standard implementation of map(s,from,to)
916a841e1ebSBaptiste Daroussin * function of ICON language. Within mapvec, we replace every character
917a841e1ebSBaptiste Daroussin * of "from" with the corresponding character in "to".
918a841e1ebSBaptiste Daroussin * If "to" is shorter than "from", than the corresponding entries are null,
919af7ca7c8SPedro F. Giffuni * which means that those characters disappear altogether.
9209b50d902SRodney W. Grimes */
921acc9d408SJuli Mallett static void
map(char * dest,const char * src,const char * from,const char * to)922bd2bfb58SJuli Mallett map(char *dest, const char *src, const char *from, const char *to)
9239b50d902SRodney W. Grimes {
924acc9d408SJuli Mallett const char *tmp;
925acc9d408SJuli Mallett unsigned char sch, dch;
926acc9d408SJuli Mallett static char frombis[257];
927acc9d408SJuli Mallett static char tobis[257];
928a841e1ebSBaptiste Daroussin int i;
929a841e1ebSBaptiste Daroussin char seen[256];
930acc9d408SJuli Mallett static unsigned char mapvec[256] = {
931acc9d408SJuli Mallett 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
932acc9d408SJuli Mallett 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
933acc9d408SJuli Mallett 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
934acc9d408SJuli Mallett 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
935acc9d408SJuli Mallett 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
936acc9d408SJuli Mallett 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
937acc9d408SJuli Mallett 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
938acc9d408SJuli Mallett 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
939acc9d408SJuli Mallett 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
940acc9d408SJuli Mallett 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
941acc9d408SJuli Mallett 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
942acc9d408SJuli Mallett 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
943acc9d408SJuli Mallett 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
944acc9d408SJuli Mallett 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
945acc9d408SJuli Mallett 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
946acc9d408SJuli Mallett 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
947acc9d408SJuli Mallett 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
948acc9d408SJuli Mallett 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
9499b50d902SRodney W. Grimes };
9509b50d902SRodney W. Grimes
9519b50d902SRodney W. Grimes if (*src) {
952acc9d408SJuli Mallett if (mimic_gnu) {
953acc9d408SJuli Mallett /*
954acc9d408SJuli Mallett * expand character ranges on the fly
955acc9d408SJuli Mallett */
956acc9d408SJuli Mallett from = handledash(frombis, frombis + 256, from);
957acc9d408SJuli Mallett to = handledash(tobis, tobis + 256, to);
958acc9d408SJuli Mallett }
9599b50d902SRodney W. Grimes tmp = from;
9609b50d902SRodney W. Grimes /*
9619b50d902SRodney W. Grimes * create a mapping between "from" and
9629b50d902SRodney W. Grimes * "to"
9639b50d902SRodney W. Grimes */
964a841e1ebSBaptiste Daroussin for (i = 0; i < 256; i++)
965a841e1ebSBaptiste Daroussin seen[i] = 0;
966a841e1ebSBaptiste Daroussin while (*from) {
967a841e1ebSBaptiste Daroussin if (!seen[(unsigned char)(*from)]) {
968a841e1ebSBaptiste Daroussin mapvec[(unsigned char)(*from)] = (unsigned char)(*to);
969a841e1ebSBaptiste Daroussin seen[(unsigned char)(*from)] = 1;
970a841e1ebSBaptiste Daroussin }
971a841e1ebSBaptiste Daroussin from++;
972a841e1ebSBaptiste Daroussin if (*to)
973a841e1ebSBaptiste Daroussin to++;
974a841e1ebSBaptiste Daroussin }
9759b50d902SRodney W. Grimes
9769b50d902SRodney W. Grimes while (*src) {
977acc9d408SJuli Mallett sch = (unsigned char)(*src++);
9789b50d902SRodney W. Grimes dch = mapvec[sch];
979acc9d408SJuli Mallett if ((*dest = (char)dch))
9809b50d902SRodney W. Grimes dest++;
9819b50d902SRodney W. Grimes }
9829b50d902SRodney W. Grimes /*
9839b50d902SRodney W. Grimes * restore all the changed characters
9849b50d902SRodney W. Grimes */
9859b50d902SRodney W. Grimes while (*tmp) {
986acc9d408SJuli Mallett mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
9879b50d902SRodney W. Grimes tmp++;
9889b50d902SRodney W. Grimes }
9899b50d902SRodney W. Grimes }
990acc9d408SJuli Mallett *dest = '\0';
9919b50d902SRodney W. Grimes }
992acc9d408SJuli Mallett
993acc9d408SJuli Mallett
994acc9d408SJuli Mallett /*
995acc9d408SJuli Mallett * handledash:
996acc9d408SJuli Mallett * use buffer to copy the src string, expanding character ranges
997acc9d408SJuli Mallett * on the way.
998acc9d408SJuli Mallett */
999acc9d408SJuli Mallett static const char *
handledash(char * buffer,char * end,const char * src)1000bd2bfb58SJuli Mallett handledash(char *buffer, char *end, const char *src)
1001acc9d408SJuli Mallett {
1002acc9d408SJuli Mallett char *p;
1003acc9d408SJuli Mallett
1004acc9d408SJuli Mallett p = buffer;
1005acc9d408SJuli Mallett while(*src) {
1006acc9d408SJuli Mallett if (src[1] == '-' && src[2]) {
1007acc9d408SJuli Mallett unsigned char i;
1008a841e1ebSBaptiste Daroussin if ((unsigned char)src[0] <= (unsigned char)src[2]) {
1009acc9d408SJuli Mallett for (i = (unsigned char)src[0];
1010acc9d408SJuli Mallett i <= (unsigned char)src[2]; i++) {
1011acc9d408SJuli Mallett *p++ = i;
1012acc9d408SJuli Mallett if (p == end) {
1013acc9d408SJuli Mallett *p = '\0';
1014acc9d408SJuli Mallett return buffer;
1015acc9d408SJuli Mallett }
1016acc9d408SJuli Mallett }
1017a841e1ebSBaptiste Daroussin } else {
1018a841e1ebSBaptiste Daroussin for (i = (unsigned char)src[0];
1019a841e1ebSBaptiste Daroussin i >= (unsigned char)src[2]; i--) {
1020a841e1ebSBaptiste Daroussin *p++ = i;
1021a841e1ebSBaptiste Daroussin if (p == end) {
1022a841e1ebSBaptiste Daroussin *p = '\0';
1023a841e1ebSBaptiste Daroussin return buffer;
1024a841e1ebSBaptiste Daroussin }
1025a841e1ebSBaptiste Daroussin }
1026a841e1ebSBaptiste Daroussin }
1027acc9d408SJuli Mallett src += 3;
1028acc9d408SJuli Mallett } else
1029acc9d408SJuli Mallett *p++ = *src++;
1030acc9d408SJuli Mallett if (p == end)
1031acc9d408SJuli Mallett break;
1032acc9d408SJuli Mallett }
1033acc9d408SJuli Mallett *p = '\0';
1034acc9d408SJuli Mallett return buffer;
1035acc9d408SJuli Mallett }
1036