1*d9a51c35Sjmc /* $OpenBSD: eval.c,v 1.79 2022/12/26 19:16:01 jmc Exp $ */
2aa676ce1Smillert /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */
3df930be7Sderaadt
4df930be7Sderaadt /*
5df930be7Sderaadt * Copyright (c) 1989, 1993
6df930be7Sderaadt * The Regents of the University of California. All rights reserved.
7df930be7Sderaadt *
8df930be7Sderaadt * This code is derived from software contributed to Berkeley by
9df930be7Sderaadt * Ozan Yigit at York University.
10df930be7Sderaadt *
11df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
12df930be7Sderaadt * modification, are permitted provided that the following conditions
13df930be7Sderaadt * are met:
14df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
15df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
16df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
17df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
18df930be7Sderaadt * documentation and/or other materials provided with the distribution.
19f75387cbSmillert * 3. Neither the name of the University nor the names of its contributors
20df930be7Sderaadt * may be used to endorse or promote products derived from this software
21df930be7Sderaadt * without specific prior written permission.
22df930be7Sderaadt *
23df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33df930be7Sderaadt * SUCH DAMAGE.
34df930be7Sderaadt */
35df930be7Sderaadt
36df930be7Sderaadt /*
37df930be7Sderaadt * eval.c
38df930be7Sderaadt * Facility: m4 macro processor
39df930be7Sderaadt * by: oz
40df930be7Sderaadt */
41df930be7Sderaadt
42df930be7Sderaadt #include <sys/types.h>
43df44a85aSespie #include <err.h>
44df930be7Sderaadt #include <errno.h>
45e79fa687Sespie #include <limits.h>
46df930be7Sderaadt #include <unistd.h>
47df930be7Sderaadt #include <stdio.h>
481357284aSmillert #include <stdint.h>
49df930be7Sderaadt #include <stdlib.h>
503f42598dSespie #include <stddef.h>
51df930be7Sderaadt #include <string.h>
52445b77f7Smillert #include <fcntl.h>
53df930be7Sderaadt #include "mdef.h"
54df930be7Sderaadt #include "stdd.h"
55df930be7Sderaadt #include "extern.h"
56df930be7Sderaadt #include "pathnames.h"
57df930be7Sderaadt
58c72b5b24Smillert static void dodefn(const char *);
59c72b5b24Smillert static void dopushdef(const char *, const char *);
60c72b5b24Smillert static void dodump(const char *[], int);
61c72b5b24Smillert static void dotrace(const char *[], int, int);
62c72b5b24Smillert static void doifelse(const char *[], int);
63c72b5b24Smillert static int doincl(const char *);
64c72b5b24Smillert static int dopaste(const char *);
65c72b5b24Smillert static void dochq(const char *[], int);
66c72b5b24Smillert static void dochc(const char *[], int);
67ad459a23Sespie static void dom4wrap(const char *);
68c72b5b24Smillert static void dodiv(int);
69c72b5b24Smillert static void doundiv(const char *[], int);
70c72b5b24Smillert static void dosub(const char *[], int);
71c72b5b24Smillert static void map(char *, const char *, const char *, const char *);
72c72b5b24Smillert static const char *handledash(char *, char *, const char *);
73c72b5b24Smillert static void expand_builtin(const char *[], int, int);
74c72b5b24Smillert static void expand_macro(const char *[], int);
753509e8ffSespie static void dump_one_def(const char *, struct macro_definition *);
7608f7f207Sespie
7799f77b33Sespie unsigned long expansion_id;
7808f7f207Sespie
79df930be7Sderaadt /*
8008f7f207Sespie * eval - eval all macros and builtins calls
81054026c0Sespie * argc - number of elements in argv.
82054026c0Sespie * argv - element vector :
83054026c0Sespie * argv[0] = definition of a user
843509e8ffSespie * macro or NULL if built-in.
85054026c0Sespie * argv[1] = name of the macro or
86054026c0Sespie * built-in.
87054026c0Sespie * argv[2] = parameters to user-defined
88054026c0Sespie * . macro or built-in.
89054026c0Sespie * .
90054026c0Sespie *
91054026c0Sespie * A call in the form of macro-or-builtin() will result in:
92054026c0Sespie * argv[0] = nullstr
93054026c0Sespie * argv[1] = macro-or-builtin
94054026c0Sespie * argv[2] = nullstr
95054026c0Sespie *
96054026c0Sespie * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
9708f7f207Sespie */
9808f7f207Sespie void
eval(const char * argv[],int argc,int td,int is_traced)99dde05c5fSespie eval(const char *argv[], int argc, int td, int is_traced)
10008f7f207Sespie {
1010b7a013eSespie size_t mark = SIZE_MAX;
1024dac505dSespie
10399f77b33Sespie expansion_id++;
10408f7f207Sespie if (td & RECDEF)
10575ebbed7Sespie m4errx(1, "expanding recursive definition for %s.", argv[1]);
106dde05c5fSespie if (is_traced)
1074dac505dSespie mark = trace(argv, argc, infile+ilevel);
10808f7f207Sespie if (td == MACRTYPE)
10908f7f207Sespie expand_macro(argv, argc);
11008f7f207Sespie else
11108f7f207Sespie expand_builtin(argv, argc, td);
1120b7a013eSespie if (mark != SIZE_MAX)
1134dac505dSespie finish_trace(mark);
11408f7f207Sespie }
11508f7f207Sespie
11608f7f207Sespie /*
11708f7f207Sespie * expand_builtin - evaluate built-in macros.
118df930be7Sderaadt */
119df930be7Sderaadt void
expand_builtin(const char * argv[],int argc,int td)1208e061d4bSespie expand_builtin(const char *argv[], int argc, int td)
121df930be7Sderaadt {
12253f6f6bfSespie int c, n;
1231818d080Sespie const char *errstr;
124054026c0Sespie int ac;
125df930be7Sderaadt static int sysval = 0;
126df930be7Sderaadt
127df930be7Sderaadt #ifdef DEBUG
128df930be7Sderaadt printf("argc = %d\n", argc);
129df930be7Sderaadt for (n = 0; n < argc; n++)
130df930be7Sderaadt printf("argv[%d] = %s\n", n, argv[n]);
13128728804Sespie fflush(stdout);
132df930be7Sderaadt #endif
133718b194dSespie
134df930be7Sderaadt /*
135df930be7Sderaadt * if argc == 3 and argv[2] is null, then we
136df930be7Sderaadt * have macro-or-builtin() type call. We adjust
137df930be7Sderaadt * argc to avoid further checking..
138df930be7Sderaadt */
139739ce124Sespie /* we keep the initial value for those built-ins that differentiate
140739ce124Sespie * between builtin() and builtin.
141739ce124Sespie */
142054026c0Sespie ac = argc;
143054026c0Sespie
14487a9001aSespie if (argc == 3 && !*(argv[2]) && !mimic_gnu)
145df930be7Sderaadt argc--;
146df930be7Sderaadt
147718b194dSespie switch (td & TYPEMASK) {
148df930be7Sderaadt
149df930be7Sderaadt case DEFITYPE:
150df930be7Sderaadt if (argc > 2)
151df930be7Sderaadt dodefine(argv[2], (argc > 3) ? argv[3] : null);
152df930be7Sderaadt break;
153df930be7Sderaadt
154df930be7Sderaadt case PUSDTYPE:
155df930be7Sderaadt if (argc > 2)
156df930be7Sderaadt dopushdef(argv[2], (argc > 3) ? argv[3] : null);
157df930be7Sderaadt break;
158df930be7Sderaadt
159df930be7Sderaadt case DUMPTYPE:
160df930be7Sderaadt dodump(argv, argc);
161df930be7Sderaadt break;
162df930be7Sderaadt
16334970243Sespie case TRACEONTYPE:
16434970243Sespie dotrace(argv, argc, 1);
16534970243Sespie break;
16634970243Sespie
16734970243Sespie case TRACEOFFTYPE:
16834970243Sespie dotrace(argv, argc, 0);
16934970243Sespie break;
17034970243Sespie
171df930be7Sderaadt case EXPRTYPE:
172df930be7Sderaadt /*
173df930be7Sderaadt * doexpr - evaluate arithmetic
174df930be7Sderaadt * expression
175df930be7Sderaadt */
176e79fa687Sespie {
177e79fa687Sespie int base = 10;
178e79fa687Sespie int maxdigits = 0;
179e79fa687Sespie
180e79fa687Sespie if (argc > 3) {
181e79fa687Sespie base = strtonum(argv[3], 2, 36, &errstr);
182e79fa687Sespie if (errstr) {
1831818d080Sespie m4errx(1, "expr: base is %s: %s.",
1841818d080Sespie errstr, argv[3]);
185e79fa687Sespie }
186e79fa687Sespie }
187e79fa687Sespie if (argc > 4) {
188e79fa687Sespie maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr);
189e79fa687Sespie if (errstr) {
1901818d080Sespie m4errx(1, "expr: maxdigits is %s: %s.",
1911818d080Sespie errstr, argv[4]);
192e79fa687Sespie }
193e79fa687Sespie }
194df930be7Sderaadt if (argc > 2)
195e79fa687Sespie pbnumbase(expr(argv[2]), base, maxdigits);
196df930be7Sderaadt break;
197e79fa687Sespie }
198df930be7Sderaadt
199df930be7Sderaadt case IFELTYPE:
200df930be7Sderaadt doifelse(argv, argc);
201df930be7Sderaadt break;
202df930be7Sderaadt
203df930be7Sderaadt case IFDFTYPE:
204df930be7Sderaadt /*
205df930be7Sderaadt * doifdef - select one of two
206df930be7Sderaadt * alternatives based on the existence of
207df930be7Sderaadt * another definition
208df930be7Sderaadt */
209df930be7Sderaadt if (argc > 3) {
2103509e8ffSespie if (lookup_macro_definition(argv[2]) != NULL)
211df930be7Sderaadt pbstr(argv[3]);
212df930be7Sderaadt else if (argc > 4)
213df930be7Sderaadt pbstr(argv[4]);
214df930be7Sderaadt }
215df930be7Sderaadt break;
216df930be7Sderaadt
217df930be7Sderaadt case LENGTYPE:
218df930be7Sderaadt /*
219df930be7Sderaadt * dolen - find the length of the
220df930be7Sderaadt * argument
221df930be7Sderaadt */
222df930be7Sderaadt pbnum((argc > 2) ? strlen(argv[2]) : 0);
223df930be7Sderaadt break;
224df930be7Sderaadt
225df930be7Sderaadt case INCRTYPE:
226df930be7Sderaadt /*
227df930be7Sderaadt * doincr - increment the value of the
228df930be7Sderaadt * argument
229df930be7Sderaadt */
2301818d080Sespie if (argc > 2) {
2311818d080Sespie n = strtonum(argv[2], INT_MIN, INT_MAX-1, &errstr);
2321818d080Sespie if (errstr != NULL)
2331818d080Sespie m4errx(1, "incr: argument is %s: %s.",
2341818d080Sespie errstr, argv[2]);
2351818d080Sespie pbnum(n + 1);
2361818d080Sespie }
237df930be7Sderaadt break;
238df930be7Sderaadt
239df930be7Sderaadt case DECRTYPE:
240df930be7Sderaadt /*
241df930be7Sderaadt * dodecr - decrement the value of the
242df930be7Sderaadt * argument
243df930be7Sderaadt */
2441818d080Sespie if (argc > 2) {
2451818d080Sespie n = strtonum(argv[2], INT_MIN+1, INT_MAX, &errstr);
2461818d080Sespie if (errstr)
2471818d080Sespie m4errx(1, "decr: argument is %s: %s.",
2481818d080Sespie errstr, argv[2]);
2491818d080Sespie pbnum(n - 1);
2501818d080Sespie }
251df930be7Sderaadt break;
252df930be7Sderaadt
253df930be7Sderaadt case SYSCTYPE:
254df930be7Sderaadt /*
255df930be7Sderaadt * dosys - execute system command
256df930be7Sderaadt */
257b3d09a36Srobert if (argc > 2) {
258b3d09a36Srobert fflush(stdout);
259df930be7Sderaadt sysval = system(argv[2]);
260b3d09a36Srobert }
261df930be7Sderaadt break;
262df930be7Sderaadt
263df930be7Sderaadt case SYSVTYPE:
264df930be7Sderaadt /*
265df930be7Sderaadt * dosysval - return value of the last
266df930be7Sderaadt * system call.
267df930be7Sderaadt *
268df930be7Sderaadt */
269df930be7Sderaadt pbnum(sysval);
270df930be7Sderaadt break;
271df930be7Sderaadt
272c91edbbbSespie case ESYSCMDTYPE:
273c91edbbbSespie if (argc > 2)
274c91edbbbSespie doesyscmd(argv[2]);
275c91edbbbSespie break;
276df930be7Sderaadt case INCLTYPE:
2772aa31d4aSderaadt if (argc > 2) {
2782aa31d4aSderaadt if (!doincl(argv[2])) {
279a45fdd0cSespie if (mimic_gnu) {
280a45fdd0cSespie warn("%s at line %lu: include(%s)",
281a45fdd0cSespie CURRENT_NAME, CURRENT_LINE, argv[2]);
282a45fdd0cSespie exit_code = 1;
283d2d86e25Sbcallah if (fatal_warns) {
284d2d86e25Sbcallah killdiv();
285d2d86e25Sbcallah exit(exit_code);
286d2d86e25Sbcallah }
287a45fdd0cSespie } else
2880d3ffe1dSespie err(1, "%s at line %lu: include(%s)",
2890d3ffe1dSespie CURRENT_NAME, CURRENT_LINE, argv[2]);
2902aa31d4aSderaadt }
2912aa31d4aSderaadt }
292df930be7Sderaadt break;
293df930be7Sderaadt
294df930be7Sderaadt case SINCTYPE:
295df930be7Sderaadt if (argc > 2)
296df930be7Sderaadt (void) doincl(argv[2]);
297df930be7Sderaadt break;
298df930be7Sderaadt #ifdef EXTENDED
299df930be7Sderaadt case PASTTYPE:
300df930be7Sderaadt if (argc > 2)
301df930be7Sderaadt if (!dopaste(argv[2]))
3020d3ffe1dSespie err(1, "%s at line %lu: paste(%s)",
3030d3ffe1dSespie CURRENT_NAME, CURRENT_LINE, argv[2]);
304df930be7Sderaadt break;
305df930be7Sderaadt
306df930be7Sderaadt case SPASTYPE:
307df930be7Sderaadt if (argc > 2)
308df930be7Sderaadt (void) dopaste(argv[2]);
309df930be7Sderaadt break;
31009d1584fSespie case FORMATTYPE:
31109d1584fSespie doformat(argv, argc);
31209d1584fSespie break;
313df930be7Sderaadt #endif
314df930be7Sderaadt case CHNQTYPE:
315739ce124Sespie dochq(argv, ac);
316df930be7Sderaadt break;
317df930be7Sderaadt
318df930be7Sderaadt case CHNCTYPE:
319df930be7Sderaadt dochc(argv, argc);
320df930be7Sderaadt break;
321df930be7Sderaadt
322df930be7Sderaadt case SUBSTYPE:
323df930be7Sderaadt /*
324df930be7Sderaadt * dosub - select substring
325df930be7Sderaadt *
326df930be7Sderaadt */
327df930be7Sderaadt if (argc > 3)
328df930be7Sderaadt dosub(argv, argc);
329df930be7Sderaadt break;
330df930be7Sderaadt
331df930be7Sderaadt case SHIFTYPE:
332df930be7Sderaadt /*
333df930be7Sderaadt * doshift - push back all arguments
334df930be7Sderaadt * except the first one (i.e. skip
335df930be7Sderaadt * argv[2])
336df930be7Sderaadt */
337df930be7Sderaadt if (argc > 3) {
338df930be7Sderaadt for (n = argc - 1; n > 3; n--) {
3393a73db8cSderaadt pbstr(rquote);
340df930be7Sderaadt pbstr(argv[n]);
3413a73db8cSderaadt pbstr(lquote);
342739ce124Sespie pushback(COMMA);
343df930be7Sderaadt }
3443a73db8cSderaadt pbstr(rquote);
345df930be7Sderaadt pbstr(argv[3]);
3463a73db8cSderaadt pbstr(lquote);
347df930be7Sderaadt }
348df930be7Sderaadt break;
349df930be7Sderaadt
350df930be7Sderaadt case DIVRTYPE:
3511818d080Sespie if (argc > 2) {
3521818d080Sespie n = strtonum(argv[2], INT_MIN, INT_MAX, &errstr);
3531818d080Sespie if (errstr)
3541818d080Sespie m4errx(1, "divert: argument is %s: %s.",
3551818d080Sespie errstr, argv[2]);
3561818d080Sespie if (n != 0) {
357df930be7Sderaadt dodiv(n);
3581818d080Sespie break;
3591818d080Sespie }
3601818d080Sespie }
361df930be7Sderaadt active = stdout;
362df930be7Sderaadt oindex = 0;
363df930be7Sderaadt break;
364df930be7Sderaadt
365df930be7Sderaadt case UNDVTYPE:
366df930be7Sderaadt doundiv(argv, argc);
367df930be7Sderaadt break;
368df930be7Sderaadt
369df930be7Sderaadt case DIVNTYPE:
370df930be7Sderaadt /*
371df930be7Sderaadt * dodivnum - return the number of
372df930be7Sderaadt * current output diversion
373df930be7Sderaadt */
374df930be7Sderaadt pbnum(oindex);
375df930be7Sderaadt break;
376df930be7Sderaadt
377df930be7Sderaadt case UNDFTYPE:
378df930be7Sderaadt /*
379df930be7Sderaadt * doundefine - undefine a previously
380df930be7Sderaadt * defined macro(s) or m4 keyword(s).
381df930be7Sderaadt */
382df930be7Sderaadt if (argc > 2)
383df930be7Sderaadt for (n = 2; n < argc; n++)
3843509e8ffSespie macro_undefine(argv[n]);
385df930be7Sderaadt break;
386df930be7Sderaadt
387df930be7Sderaadt case POPDTYPE:
388df930be7Sderaadt /*
389df930be7Sderaadt * dopopdef - remove the topmost
390df930be7Sderaadt * definitions of macro(s) or m4
391df930be7Sderaadt * keyword(s).
392df930be7Sderaadt */
393df930be7Sderaadt if (argc > 2)
394df930be7Sderaadt for (n = 2; n < argc; n++)
3953509e8ffSespie macro_popdef(argv[n]);
396df930be7Sderaadt break;
397df930be7Sderaadt
398df930be7Sderaadt case MKTMTYPE:
399df930be7Sderaadt /*
400df930be7Sderaadt * dotemp - create a temporary file
401df930be7Sderaadt */
40201e71e69Sespie if (argc > 2) {
40301e71e69Sespie int fd;
404bb34cd6cSespie char *temp;
40501e71e69Sespie
406bb34cd6cSespie temp = xstrdup(argv[2]);
407bb34cd6cSespie
408bb34cd6cSespie fd = mkstemp(temp);
40901e71e69Sespie if (fd == -1)
4100d3ffe1dSespie err(1,
4110d3ffe1dSespie "%s at line %lu: couldn't make temp file %s",
4120d3ffe1dSespie CURRENT_NAME, CURRENT_LINE, argv[2]);
41301e71e69Sespie close(fd);
414bb34cd6cSespie pbstr(temp);
415bb34cd6cSespie free(temp);
41601e71e69Sespie }
417df930be7Sderaadt break;
418df930be7Sderaadt
419df930be7Sderaadt case TRNLTYPE:
420df930be7Sderaadt /*
421df930be7Sderaadt * dotranslit - replace all characters in
422df930be7Sderaadt * the source string that appears in the
423df930be7Sderaadt * "from" string with the corresponding
424df930be7Sderaadt * characters in the "to" string.
425df930be7Sderaadt */
426df930be7Sderaadt if (argc > 3) {
42728728804Sespie char *temp;
42828728804Sespie
429f6169a2cSespie temp = xalloc(strlen(argv[2])+1, NULL);
430df930be7Sderaadt if (argc > 4)
431df930be7Sderaadt map(temp, argv[2], argv[3], argv[4]);
432df930be7Sderaadt else
433df930be7Sderaadt map(temp, argv[2], argv[3], null);
434df930be7Sderaadt pbstr(temp);
43528728804Sespie free(temp);
4367d3e0b6bSderaadt } else if (argc > 2)
437df930be7Sderaadt pbstr(argv[2]);
438df930be7Sderaadt break;
439df930be7Sderaadt
440df930be7Sderaadt case INDXTYPE:
441df930be7Sderaadt /*
442df930be7Sderaadt * doindex - find the index of the second
443df930be7Sderaadt * argument string in the first argument
444df930be7Sderaadt * string. -1 if not present.
445df930be7Sderaadt */
446df930be7Sderaadt pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
447df930be7Sderaadt break;
448df930be7Sderaadt
449df930be7Sderaadt case ERRPTYPE:
450df930be7Sderaadt /*
451df930be7Sderaadt * doerrp - print the arguments to stderr
452df930be7Sderaadt * file
453df930be7Sderaadt */
454df930be7Sderaadt if (argc > 2) {
455df930be7Sderaadt for (n = 2; n < argc; n++)
456df930be7Sderaadt fprintf(stderr, "%s ", argv[n]);
457df930be7Sderaadt fprintf(stderr, "\n");
458df930be7Sderaadt }
459df930be7Sderaadt break;
460df930be7Sderaadt
461df930be7Sderaadt case DNLNTYPE:
462df930be7Sderaadt /*
463df930be7Sderaadt * dodnl - eat-up-to and including
464df930be7Sderaadt * newline
465df930be7Sderaadt */
466df930be7Sderaadt while ((c = gpbc()) != '\n' && c != EOF)
467df930be7Sderaadt ;
468df930be7Sderaadt break;
469df930be7Sderaadt
470df930be7Sderaadt case M4WRTYPE:
471df930be7Sderaadt /*
472df930be7Sderaadt * dom4wrap - set up for
473df930be7Sderaadt * wrap-up/wind-down activity
474df930be7Sderaadt */
475ad459a23Sespie if (argc > 2)
476ad459a23Sespie dom4wrap(argv[2]);
477df930be7Sderaadt break;
478df930be7Sderaadt
479df930be7Sderaadt case EXITTYPE:
480df930be7Sderaadt /*
481df930be7Sderaadt * doexit - immediate exit from m4.
482df930be7Sderaadt */
483df930be7Sderaadt killdiv();
484df930be7Sderaadt exit((argc > 2) ? atoi(argv[2]) : 0);
485df930be7Sderaadt break;
486df930be7Sderaadt
487df930be7Sderaadt case DEFNTYPE:
488df930be7Sderaadt if (argc > 2)
489df930be7Sderaadt for (n = 2; n < argc; n++)
490df930be7Sderaadt dodefn(argv[n]);
491df930be7Sderaadt break;
492df930be7Sderaadt
493b8161682Sespie case INDIRTYPE: /* Indirect call */
494b8161682Sespie if (argc > 2)
495b8161682Sespie doindir(argv, argc);
496b8161682Sespie break;
497b8161682Sespie
498b8161682Sespie case BUILTINTYPE: /* Builtins only */
499b8161682Sespie if (argc > 2)
500b8161682Sespie dobuiltin(argv, argc);
501b8161682Sespie break;
502b8161682Sespie
503b8161682Sespie case PATSTYPE:
504b8161682Sespie if (argc > 2)
505b8161682Sespie dopatsubst(argv, argc);
506b8161682Sespie break;
507b8161682Sespie case REGEXPTYPE:
508b8161682Sespie if (argc > 2)
509b8161682Sespie doregexp(argv, argc);
510b8161682Sespie break;
511b8161682Sespie case LINETYPE:
512b8161682Sespie doprintlineno(infile+ilevel);
513b8161682Sespie break;
514b8161682Sespie case FILENAMETYPE:
515b8161682Sespie doprintfilename(infile+ilevel);
516b8161682Sespie break;
517423624b7Sespie case SELFTYPE:
518423624b7Sespie pbstr(rquote);
519423624b7Sespie pbstr(argv[1]);
520423624b7Sespie pbstr(lquote);
521423624b7Sespie break;
522df930be7Sderaadt default:
52375ebbed7Sespie m4errx(1, "eval: major botch.");
524df930be7Sderaadt break;
525df930be7Sderaadt }
526df930be7Sderaadt }
527df930be7Sderaadt
528df930be7Sderaadt /*
52908f7f207Sespie * expand_macro - user-defined macro expansion
530df930be7Sderaadt */
531df930be7Sderaadt void
expand_macro(const char * argv[],int argc)5328e061d4bSespie expand_macro(const char *argv[], int argc)
533df930be7Sderaadt {
534bb34cd6cSespie const char *t;
535bb34cd6cSespie const char *p;
53653f6f6bfSespie int n;
53753f6f6bfSespie int argno;
538df930be7Sderaadt
539df930be7Sderaadt t = argv[0]; /* defn string as a whole */
540df930be7Sderaadt p = t;
541df930be7Sderaadt while (*p)
542df930be7Sderaadt p++;
543df930be7Sderaadt p--; /* last character of defn */
544df930be7Sderaadt while (p > t) {
545df930be7Sderaadt if (*(p - 1) != ARGFLAG)
546739ce124Sespie PUSHBACK(*p);
547df930be7Sderaadt else {
548df930be7Sderaadt switch (*p) {
549df930be7Sderaadt
550df930be7Sderaadt case '#':
551df930be7Sderaadt pbnum(argc - 2);
552df930be7Sderaadt break;
553df930be7Sderaadt case '0':
554df930be7Sderaadt case '1':
555df930be7Sderaadt case '2':
556df930be7Sderaadt case '3':
557df930be7Sderaadt case '4':
558df930be7Sderaadt case '5':
559df930be7Sderaadt case '6':
560df930be7Sderaadt case '7':
561df930be7Sderaadt case '8':
562df930be7Sderaadt case '9':
563df930be7Sderaadt if ((argno = *p - '0') < argc - 1)
564df930be7Sderaadt pbstr(argv[argno + 1]);
565df930be7Sderaadt break;
566df930be7Sderaadt case '*':
567faa30e49Sespie if (argc > 2) {
568df930be7Sderaadt for (n = argc - 1; n > 2; n--) {
569df930be7Sderaadt pbstr(argv[n]);
570739ce124Sespie pushback(COMMA);
571df930be7Sderaadt }
572df930be7Sderaadt pbstr(argv[2]);
573faa30e49Sespie }
574df930be7Sderaadt break;
575aa676ce1Smillert case '@':
576faa30e49Sespie if (argc > 2) {
577aa676ce1Smillert for (n = argc - 1; n > 2; n--) {
578aa676ce1Smillert pbstr(rquote);
579aa676ce1Smillert pbstr(argv[n]);
580aa676ce1Smillert pbstr(lquote);
581739ce124Sespie pushback(COMMA);
582aa676ce1Smillert }
583aa676ce1Smillert pbstr(rquote);
584aa676ce1Smillert pbstr(argv[2]);
585aa676ce1Smillert pbstr(lquote);
586faa30e49Sespie }
587aa676ce1Smillert break;
588df930be7Sderaadt default:
589739ce124Sespie PUSHBACK(*p);
590739ce124Sespie PUSHBACK('$');
591df930be7Sderaadt break;
592df930be7Sderaadt }
593df930be7Sderaadt p--;
594df930be7Sderaadt }
595df930be7Sderaadt p--;
596df930be7Sderaadt }
597df930be7Sderaadt if (p == t) /* do last character */
598739ce124Sespie PUSHBACK(*p);
599df930be7Sderaadt }
600df930be7Sderaadt
6015ddad5ccSespie
602df930be7Sderaadt /*
6035ddad5ccSespie * dodefine - install definition in the table
6045ddad5ccSespie */
6055ddad5ccSespie void
dodefine(const char * name,const char * defn)6065ddad5ccSespie dodefine(const char *name, const char *defn)
6075ddad5ccSespie {
60887a9001aSespie if (!*name && !mimic_gnu)
60975ebbed7Sespie m4errx(1, "null definition.");
61087a9001aSespie else
6113509e8ffSespie macro_define(name, defn);
612df930be7Sderaadt }
613df930be7Sderaadt
614df930be7Sderaadt /*
615df930be7Sderaadt * dodefn - push back a quoted definition of
616df930be7Sderaadt * the given name.
617df930be7Sderaadt */
618bb34cd6cSespie static void
dodefn(const char * name)6198e061d4bSespie dodefn(const char *name)
620df930be7Sderaadt {
6213509e8ffSespie struct macro_definition *p;
622df930be7Sderaadt
6233509e8ffSespie if ((p = lookup_macro_definition(name)) != NULL) {
6245ddad5ccSespie if ((p->type & TYPEMASK) == MACRTYPE) {
6253a73db8cSderaadt pbstr(rquote);
626df930be7Sderaadt pbstr(p->defn);
6273a73db8cSderaadt pbstr(lquote);
6285ddad5ccSespie } else {
6295ddad5ccSespie pbstr(p->defn);
630f8b42d48Sespie pbstr(BUILTIN_MARKER);
631f8b42d48Sespie }
632df930be7Sderaadt }
633df930be7Sderaadt }
634df930be7Sderaadt
635df930be7Sderaadt /*
636df930be7Sderaadt * dopushdef - install a definition in the hash table
637df930be7Sderaadt * without removing a previous definition. Since
638df930be7Sderaadt * each new entry is entered in *front* of the
639df930be7Sderaadt * hash bucket, it hides a previous definition from
640df930be7Sderaadt * lookup.
641df930be7Sderaadt */
642bb34cd6cSespie static void
dopushdef(const char * name,const char * defn)6438e061d4bSespie dopushdef(const char *name, const char *defn)
644df930be7Sderaadt {
64587a9001aSespie if (!*name && !mimic_gnu)
64675ebbed7Sespie m4errx(1, "null definition.");
64787a9001aSespie else
6483509e8ffSespie macro_pushdef(name, defn);
649df930be7Sderaadt }
650df930be7Sderaadt
651df930be7Sderaadt /*
652dd0682a2Sespie * dump_one_def - dump the specified definition.
653dd0682a2Sespie */
654dd0682a2Sespie static void
dump_one_def(const char * name,struct macro_definition * p)6553509e8ffSespie dump_one_def(const char *name, struct macro_definition *p)
656dd0682a2Sespie {
657ad93774eSespie if (!traceout)
658ad93774eSespie traceout = stderr;
6595191fa0aSespie if (mimic_gnu) {
6605191fa0aSespie if ((p->type & TYPEMASK) == MACRTYPE)
6613509e8ffSespie fprintf(traceout, "%s:\t%s\n", name, p->defn);
6625191fa0aSespie else {
6633509e8ffSespie fprintf(traceout, "%s:\t<%s>\n", name, p->defn);
6645191fa0aSespie }
6655191fa0aSespie } else
6663509e8ffSespie fprintf(traceout, "`%s'\t`%s'\n", name, p->defn);
667dd0682a2Sespie }
668dd0682a2Sespie
669dd0682a2Sespie /*
670df930be7Sderaadt * dodumpdef - dump the specified definitions in the hash
671df930be7Sderaadt * table to stderr. If nothing is specified, the entire
672df930be7Sderaadt * hash table is dumped.
673df930be7Sderaadt */
674bb34cd6cSespie static void
dodump(const char * argv[],int argc)6758e061d4bSespie dodump(const char *argv[], int argc)
676df930be7Sderaadt {
67753f6f6bfSespie int n;
6783509e8ffSespie struct macro_definition *p;
679df930be7Sderaadt
680df930be7Sderaadt if (argc > 2) {
681df930be7Sderaadt for (n = 2; n < argc; n++)
6823509e8ffSespie if ((p = lookup_macro_definition(argv[n])) != NULL)
6833509e8ffSespie dump_one_def(argv[n], p);
6843509e8ffSespie } else
6853509e8ffSespie macro_for_all(dump_one_def);
686df930be7Sderaadt }
687df930be7Sderaadt
688df930be7Sderaadt /*
68934970243Sespie * dotrace - mark some macros as traced/untraced depending upon on.
69034970243Sespie */
69134970243Sespie static void
dotrace(const char * argv[],int argc,int on)6928e061d4bSespie dotrace(const char *argv[], int argc, int on)
69334970243Sespie {
69434970243Sespie int n;
69534970243Sespie
69634970243Sespie if (argc > 2) {
69734970243Sespie for (n = 2; n < argc; n++)
69834970243Sespie mark_traced(argv[n], on);
69934970243Sespie } else
70034970243Sespie mark_traced(NULL, on);
70134970243Sespie }
70234970243Sespie
70334970243Sespie /*
704df930be7Sderaadt * doifelse - select one of two alternatives - loop.
705df930be7Sderaadt */
706bb34cd6cSespie static void
doifelse(const char * argv[],int argc)7078e061d4bSespie doifelse(const char *argv[], int argc)
708df930be7Sderaadt {
709b6ff91d1Sespie while (argc > 4) {
710b6ff91d1Sespie if (STREQ(argv[2], argv[3])) {
711df930be7Sderaadt pbstr(argv[4]);
712b6ff91d1Sespie break;
713b6ff91d1Sespie } else if (argc == 6) {
714df930be7Sderaadt pbstr(argv[5]);
715b6ff91d1Sespie break;
716b6ff91d1Sespie } else {
717df930be7Sderaadt argv += 3;
718df930be7Sderaadt argc -= 3;
719df930be7Sderaadt }
720df930be7Sderaadt }
721df930be7Sderaadt }
722df930be7Sderaadt
723df930be7Sderaadt /*
724df930be7Sderaadt * doinclude - include a given file.
725df930be7Sderaadt */
726bb34cd6cSespie static int
doincl(const char * ifile)7278e061d4bSespie doincl(const char *ifile)
728df930be7Sderaadt {
729df930be7Sderaadt if (ilevel + 1 == MAXINP)
73075ebbed7Sespie m4errx(1, "too many include files.");
7310d3ffe1dSespie if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
732df930be7Sderaadt ilevel++;
733df930be7Sderaadt bbase[ilevel] = bufbase = bp;
734df930be7Sderaadt return (1);
7357d3e0b6bSderaadt } else
736df930be7Sderaadt return (0);
737df930be7Sderaadt }
738df930be7Sderaadt
739df930be7Sderaadt #ifdef EXTENDED
740df930be7Sderaadt /*
741df930be7Sderaadt * dopaste - include a given file without any
742df930be7Sderaadt * macro processing.
743df930be7Sderaadt */
744bb34cd6cSespie static int
dopaste(const char * pfile)7458e061d4bSespie dopaste(const char *pfile)
746df930be7Sderaadt {
747df930be7Sderaadt FILE *pf;
74853f6f6bfSespie int c;
749df930be7Sderaadt
750df930be7Sderaadt if ((pf = fopen(pfile, "r")) != NULL) {
751aec72266Sespie if (synch_lines)
752aec72266Sespie fprintf(active, "#line 1 \"%s\"\n", pfile);
753df930be7Sderaadt while ((c = getc(pf)) != EOF)
754df930be7Sderaadt putc(c, active);
755df930be7Sderaadt (void) fclose(pf);
756aec72266Sespie emit_synchline();
757df930be7Sderaadt return (1);
7587d3e0b6bSderaadt } else
759df930be7Sderaadt return (0);
760df930be7Sderaadt }
761df930be7Sderaadt #endif
762df930be7Sderaadt
763df930be7Sderaadt /*
764df930be7Sderaadt * dochq - change quote characters
765df930be7Sderaadt */
766bb34cd6cSespie static void
dochq(const char * argv[],int ac)767739ce124Sespie dochq(const char *argv[], int ac)
768df930be7Sderaadt {
769739ce124Sespie if (ac == 2) {
770739ce124Sespie lquote[0] = LQUOTE; lquote[1] = EOS;
771739ce124Sespie rquote[0] = RQUOTE; rquote[1] = EOS;
7727d3e0b6bSderaadt } else {
773739ce124Sespie strlcpy(lquote, argv[2], sizeof(lquote));
774739ce124Sespie if (ac > 3) {
775739ce124Sespie strlcpy(rquote, argv[3], sizeof(rquote));
776739ce124Sespie } else {
777739ce124Sespie rquote[0] = ECOMMT; rquote[1] = EOS;
778739ce124Sespie }
779df930be7Sderaadt }
780df930be7Sderaadt }
781df930be7Sderaadt
782df930be7Sderaadt /*
783df930be7Sderaadt * dochc - change comment characters
784df930be7Sderaadt */
785bb34cd6cSespie static void
dochc(const char * argv[],int argc)7868e061d4bSespie dochc(const char *argv[], int argc)
787df930be7Sderaadt {
788739ce124Sespie /* XXX Note that there is no difference between no argument and a single
789739ce124Sespie * empty argument.
790739ce124Sespie */
791739ce124Sespie if (argc == 2) {
792739ce124Sespie scommt[0] = EOS;
793739ce124Sespie ecommt[0] = EOS;
794739ce124Sespie } else {
795b81b15b2Sespie strlcpy(scommt, argv[2], sizeof(scommt));
796739ce124Sespie if (argc == 3) {
797739ce124Sespie ecommt[0] = ECOMMT; ecommt[1] = EOS;
798739ce124Sespie } else {
799b81b15b2Sespie strlcpy(ecommt, argv[3], sizeof(ecommt));
800df930be7Sderaadt }
801df930be7Sderaadt }
802df930be7Sderaadt }
803df930be7Sderaadt
804df930be7Sderaadt /*
805ad459a23Sespie * dom4wrap - expand text at EOF
806ad459a23Sespie */
807ad459a23Sespie static void
dom4wrap(const char * text)808ad459a23Sespie dom4wrap(const char *text)
809ad459a23Sespie {
810ad459a23Sespie if (wrapindex >= maxwraps) {
811ad459a23Sespie if (maxwraps == 0)
812ad459a23Sespie maxwraps = 16;
813ad459a23Sespie else
814ad459a23Sespie maxwraps *= 2;
815c608d5f4Sespie m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps),
816ad459a23Sespie "too many m4wraps");
817ad459a23Sespie }
818ad459a23Sespie m4wraps[wrapindex++] = xstrdup(text);
819ad459a23Sespie }
820ad459a23Sespie
821ad459a23Sespie /*
822df930be7Sderaadt * dodivert - divert the output to a temporary file
823df930be7Sderaadt */
824bb34cd6cSespie static void
dodiv(int n)8258e061d4bSespie dodiv(int n)
826df930be7Sderaadt {
827445b77f7Smillert int fd;
828445b77f7Smillert
8297d3e0b6bSderaadt oindex = n;
83025afcddbSespie if (n >= maxout) {
83125afcddbSespie if (mimic_gnu)
83225afcddbSespie resizedivs(n + 10);
83325afcddbSespie else
83425afcddbSespie n = 0; /* bitbucket */
83525afcddbSespie }
83625afcddbSespie
83725afcddbSespie if (n < 0)
838df930be7Sderaadt n = 0; /* bitbucket */
839df930be7Sderaadt if (outfile[n] == NULL) {
8403f42598dSespie char fname[] = _PATH_DIVNAME;
8413f42598dSespie
842c2d43ecaSderaadt if ((fd = mkstemp(fname)) == -1 ||
843f5d2852fSespie unlink(fname) == -1 ||
8443f42598dSespie (outfile[n] = fdopen(fd, "w+")) == NULL)
8453f42598dSespie err(1, "%s: cannot divert", fname);
846df930be7Sderaadt }
847df930be7Sderaadt active = outfile[n];
848df930be7Sderaadt }
849df930be7Sderaadt
850df930be7Sderaadt /*
851df930be7Sderaadt * doundivert - undivert a specified output, or all
852df930be7Sderaadt * other outputs, in numerical order.
853df930be7Sderaadt */
854bb34cd6cSespie static void
doundiv(const char * argv[],int argc)8558e061d4bSespie doundiv(const char *argv[], int argc)
856df930be7Sderaadt {
85753f6f6bfSespie int ind;
85853f6f6bfSespie int n;
859df930be7Sderaadt
860df930be7Sderaadt if (argc > 2) {
861df930be7Sderaadt for (ind = 2; ind < argc; ind++) {
862e79fa687Sespie const char *errstr;
863e79fa687Sespie n = strtonum(argv[ind], 1, INT_MAX, &errstr);
864e79fa687Sespie if (errstr) {
865e79fa687Sespie if (errno == EINVAL && mimic_gnu)
866e79fa687Sespie getdivfile(argv[ind]);
867e79fa687Sespie } else {
868e79fa687Sespie if (n < maxout && outfile[n] != NULL)
869df930be7Sderaadt getdiv(n);
870e79fa687Sespie }
871df930be7Sderaadt }
872df930be7Sderaadt }
873df930be7Sderaadt else
87425afcddbSespie for (n = 1; n < maxout; n++)
875df930be7Sderaadt if (outfile[n] != NULL)
876df930be7Sderaadt getdiv(n);
877df930be7Sderaadt }
878df930be7Sderaadt
879df930be7Sderaadt /*
880df930be7Sderaadt * dosub - select substring
881df930be7Sderaadt */
882bb34cd6cSespie static void
dosub(const char * argv[],int argc)8838e061d4bSespie dosub(const char *argv[], int argc)
884df930be7Sderaadt {
885bb34cd6cSespie const char *ap, *fc, *k;
88653f6f6bfSespie int nc;
887df930be7Sderaadt
888df930be7Sderaadt ap = argv[2]; /* target string */
889df930be7Sderaadt #ifdef EXPR
890df930be7Sderaadt fc = ap + expr(argv[3]); /* first char */
891df930be7Sderaadt #else
892df930be7Sderaadt fc = ap + atoi(argv[3]); /* first char */
893df930be7Sderaadt #endif
894bee8364eSespie nc = strlen(fc);
895bee8364eSespie if (argc >= 5)
896bee8364eSespie #ifdef EXPR
897bee8364eSespie nc = min(nc, expr(argv[4]));
898bee8364eSespie #else
899bee8364eSespie nc = min(nc, atoi(argv[4]));
900bee8364eSespie #endif
901df930be7Sderaadt if (fc >= ap && fc < ap + strlen(ap))
902bee8364eSespie for (k = fc + nc - 1; k >= fc; k--)
903739ce124Sespie pushback(*k);
904df930be7Sderaadt }
905df930be7Sderaadt
906df930be7Sderaadt /*
907df930be7Sderaadt * map:
908df930be7Sderaadt * map every character of s1 that is specified in from
909df930be7Sderaadt * into s3 and replace in s. (source s1 remains untouched)
910df930be7Sderaadt *
91187ab3cf4Sespie * This is derived from the a standard implementation of map(s,from,to)
91287ab3cf4Sespie * function of ICON language. Within mapvec, we replace every character
91387ab3cf4Sespie * of "from" with the corresponding character in "to".
91487ab3cf4Sespie * If "to" is shorter than "from", than the corresponding entries are null,
915*d9a51c35Sjmc * which means that those characters disappear altogether.
916df930be7Sderaadt */
917bb34cd6cSespie static void
map(char * dest,const char * src,const char * from,const char * to)9188e061d4bSespie map(char *dest, const char *src, const char *from, const char *to)
919df930be7Sderaadt {
920bb34cd6cSespie const char *tmp;
921ee3599c7Sespie unsigned char sch, dch;
92287c5c065Sespie static char frombis[257];
92387c5c065Sespie static char tobis[257];
92427e0c134Sespie int i;
92527e0c134Sespie char seen[256];
926ee3599c7Sespie static unsigned char mapvec[256] = {
927ee3599c7Sespie 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
928ee3599c7Sespie 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
929ee3599c7Sespie 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
930ee3599c7Sespie 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
931ee3599c7Sespie 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
932ee3599c7Sespie 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
933ee3599c7Sespie 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
934ee3599c7Sespie 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
935ee3599c7Sespie 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
936ee3599c7Sespie 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
937ee3599c7Sespie 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
938ee3599c7Sespie 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
939ee3599c7Sespie 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
940ee3599c7Sespie 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
941ee3599c7Sespie 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
942ee3599c7Sespie 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
943ee3599c7Sespie 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
944ee3599c7Sespie 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
945df930be7Sderaadt };
946df930be7Sderaadt
947df930be7Sderaadt if (*src) {
94887c5c065Sespie if (mimic_gnu) {
94987c5c065Sespie /*
95087c5c065Sespie * expand character ranges on the fly
95187c5c065Sespie */
95287c5c065Sespie from = handledash(frombis, frombis + 256, from);
95387c5c065Sespie to = handledash(tobis, tobis + 256, to);
95487c5c065Sespie }
955df930be7Sderaadt tmp = from;
956df930be7Sderaadt /*
957df930be7Sderaadt * create a mapping between "from" and
958df930be7Sderaadt * "to"
959df930be7Sderaadt */
96027e0c134Sespie for (i = 0; i < 256; i++)
96127e0c134Sespie seen[i] = 0;
96227e0c134Sespie while (*from) {
96327e0c134Sespie if (!seen[(unsigned char)(*from)]) {
96427e0c134Sespie mapvec[(unsigned char)(*from)] = (unsigned char)(*to);
96527e0c134Sespie seen[(unsigned char)(*from)] = 1;
96627e0c134Sespie }
96727e0c134Sespie from++;
96827e0c134Sespie if (*to)
96927e0c134Sespie to++;
97027e0c134Sespie }
971df930be7Sderaadt
972df930be7Sderaadt while (*src) {
973ee3599c7Sespie sch = (unsigned char)(*src++);
974df930be7Sderaadt dch = mapvec[sch];
975ee3599c7Sespie if ((*dest = (char)dch))
976df930be7Sderaadt dest++;
977df930be7Sderaadt }
978df930be7Sderaadt /*
979df930be7Sderaadt * restore all the changed characters
980df930be7Sderaadt */
981df930be7Sderaadt while (*tmp) {
982ee3599c7Sespie mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
983df930be7Sderaadt tmp++;
984df930be7Sderaadt }
985df930be7Sderaadt }
986ee3599c7Sespie *dest = '\0';
987df930be7Sderaadt }
98887c5c065Sespie
98987c5c065Sespie
99087c5c065Sespie /*
99187c5c065Sespie * handledash:
99287c5c065Sespie * use buffer to copy the src string, expanding character ranges
99387c5c065Sespie * on the way.
99487c5c065Sespie */
99587c5c065Sespie static const char *
handledash(char * buffer,char * end,const char * src)9968e061d4bSespie handledash(char *buffer, char *end, const char *src)
99787c5c065Sespie {
99887c5c065Sespie char *p;
99987c5c065Sespie
100087c5c065Sespie p = buffer;
100187c5c065Sespie while(*src) {
100287c5c065Sespie if (src[1] == '-' && src[2]) {
100387c5c065Sespie unsigned char i;
1004e79fa687Sespie if ((unsigned char)src[0] <= (unsigned char)src[2]) {
100587c5c065Sespie for (i = (unsigned char)src[0];
100687c5c065Sespie i <= (unsigned char)src[2]; i++) {
100787c5c065Sespie *p++ = i;
100887c5c065Sespie if (p == end) {
100987c5c065Sespie *p = '\0';
101087c5c065Sespie return buffer;
101187c5c065Sespie }
101287c5c065Sespie }
1013e79fa687Sespie } else {
1014e79fa687Sespie for (i = (unsigned char)src[0];
1015e79fa687Sespie i >= (unsigned char)src[2]; i--) {
1016e79fa687Sespie *p++ = i;
1017e79fa687Sespie if (p == end) {
1018e79fa687Sespie *p = '\0';
1019e79fa687Sespie return buffer;
1020e79fa687Sespie }
1021e79fa687Sespie }
1022e79fa687Sespie }
102387c5c065Sespie src += 3;
102487c5c065Sespie } else
102587c5c065Sespie *p++ = *src++;
102687c5c065Sespie if (p == end)
102787c5c065Sespie break;
102887c5c065Sespie }
102987c5c065Sespie *p = '\0';
103087c5c065Sespie return buffer;
103187c5c065Sespie }
1032