1acc9d408SJuli Mallett /* $OpenBSD: eval.c,v 1.43 2002/02/16 21:27:48 millert Exp $ */ 2acc9d408SJuli Mallett /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */ 3acc9d408SJuli Mallett 49b50d902SRodney W. Grimes /* 59b50d902SRodney W. Grimes * Copyright (c) 1989, 1993 69b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 79b50d902SRodney W. Grimes * 89b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by 99b50d902SRodney W. Grimes * Ozan Yigit at York University. 109b50d902SRodney W. Grimes * 119b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 129b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 139b50d902SRodney W. Grimes * are met: 149b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 159b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 169b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 179b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 189b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 199b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 209b50d902SRodney W. Grimes * must display the following acknowledgement: 219b50d902SRodney W. Grimes * This product includes software developed by the University of 229b50d902SRodney W. Grimes * California, Berkeley and its contributors. 239b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 249b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 259b50d902SRodney W. Grimes * without specific prior written permission. 269b50d902SRodney W. Grimes * 279b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 289b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 299b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 309b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 319b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 329b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 339b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 349b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 359b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 369b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 379b50d902SRodney W. Grimes * SUCH DAMAGE. 389b50d902SRodney W. Grimes */ 399b50d902SRodney W. Grimes 40acc9d408SJuli Mallett #include <sys/cdefs.h> 41acc9d408SJuli Mallett __SCCSID("@(#)eval.c 8.2 (Berkeley) 4/27/95"); 42acc9d408SJuli Mallett __RCSID_SOURCE("$OpenBSD: eval.c,v 1.43 2002/02/16 21:27:48 millert Exp $"); 43acc9d408SJuli Mallett __FBSDID("$FreeBSD$"); 449b50d902SRodney W. Grimes 459b50d902SRodney W. Grimes /* 469b50d902SRodney W. Grimes * eval.c 479b50d902SRodney W. Grimes * Facility: m4 macro processor 489b50d902SRodney W. Grimes * by: oz 499b50d902SRodney W. Grimes */ 509b50d902SRodney W. Grimes 519b50d902SRodney W. Grimes #include <sys/types.h> 52acc9d408SJuli Mallett #include <errno.h> 53acc9d408SJuli Mallett #include <unistd.h> 549b50d902SRodney W. Grimes #include <stdio.h> 559b50d902SRodney W. Grimes #include <stdlib.h> 56acc9d408SJuli Mallett #include <stddef.h> 579b50d902SRodney W. Grimes #include <string.h> 58acc9d408SJuli Mallett #include <fcntl.h> 59acc9d408SJuli Mallett #include <err.h> 609b50d902SRodney W. Grimes #include "mdef.h" 619b50d902SRodney W. Grimes #include "stdd.h" 629b50d902SRodney W. Grimes #include "extern.h" 639b50d902SRodney W. Grimes #include "pathnames.h" 649b50d902SRodney W. Grimes 65acc9d408SJuli Mallett #define BUILTIN_MARKER "__builtin_" 66acc9d408SJuli Mallett 67acc9d408SJuli Mallett static void dodefn(const char *); 68acc9d408SJuli Mallett static void dopushdef(const char *, const char *); 69acc9d408SJuli Mallett static void dodump(const char *[], int); 70acc9d408SJuli Mallett static void dotrace(const char *[], int, int); 71acc9d408SJuli Mallett static void doifelse(const char *[], int); 72acc9d408SJuli Mallett static int doincl(const char *); 73acc9d408SJuli Mallett static int dopaste(const char *); 74acc9d408SJuli Mallett static void gnu_dochq(const char *[], int); 75acc9d408SJuli Mallett static void dochq(const char *[], int); 76acc9d408SJuli Mallett static void gnu_dochc(const char *[], int); 77acc9d408SJuli Mallett static void dochc(const char *[], int); 78acc9d408SJuli Mallett static void dodiv(int); 79acc9d408SJuli Mallett static void doundiv(const char *[], int); 80acc9d408SJuli Mallett static void dosub(const char *[], int); 81acc9d408SJuli Mallett static void map(char *, const char *, const char *, const char *); 82acc9d408SJuli Mallett static const char *handledash(char *, char *, const char *); 83acc9d408SJuli Mallett static void expand_builtin(const char *[], int, int); 84acc9d408SJuli Mallett static void expand_macro(const char *[], int); 85acc9d408SJuli Mallett static void dump_one_def(ndptr); 86acc9d408SJuli Mallett 87acc9d408SJuli Mallett unsigned long expansion_id; 88acc9d408SJuli Mallett 899b50d902SRodney W. Grimes /* 90acc9d408SJuli Mallett * eval - eval all macros and builtins calls 919b50d902SRodney W. Grimes * argc - number of elements in argv. 929b50d902SRodney W. Grimes * argv - element vector : 939b50d902SRodney W. Grimes * argv[0] = definition of a user 949b50d902SRodney W. Grimes * macro or nil if built-in. 959b50d902SRodney W. Grimes * argv[1] = name of the macro or 969b50d902SRodney W. Grimes * built-in. 979b50d902SRodney W. Grimes * argv[2] = parameters to user-defined 989b50d902SRodney W. Grimes * . macro or built-in. 999b50d902SRodney W. Grimes * . 1009b50d902SRodney W. Grimes * 101acc9d408SJuli Mallett * A call in the form of macro-or-builtin() will result in: 1029b50d902SRodney W. Grimes * argv[0] = nullstr 1039b50d902SRodney W. Grimes * argv[1] = macro-or-builtin 1049b50d902SRodney W. Grimes * argv[2] = nullstr 105acc9d408SJuli Mallett * 106acc9d408SJuli Mallett * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin 1079b50d902SRodney W. Grimes */ 1089b50d902SRodney W. Grimes void 1099b50d902SRodney W. Grimes eval(argv, argc, td) 110acc9d408SJuli Mallett const char *argv[]; 111acc9d408SJuli Mallett int argc; 112acc9d408SJuli Mallett int td; 1139b50d902SRodney W. Grimes { 114acc9d408SJuli Mallett ssize_t mark = -1; 115acc9d408SJuli Mallett 116acc9d408SJuli Mallett expansion_id++; 117acc9d408SJuli Mallett if (td & RECDEF) 118acc9d408SJuli Mallett errx(1, "%s at line %lu: expanding recursive definition for %s", 119acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[1]); 120acc9d408SJuli Mallett if (traced_macros && is_traced(argv[1])) 121acc9d408SJuli Mallett mark = trace(argv, argc, infile+ilevel); 122acc9d408SJuli Mallett if (td == MACRTYPE) 123acc9d408SJuli Mallett expand_macro(argv, argc); 124acc9d408SJuli Mallett else 125acc9d408SJuli Mallett expand_builtin(argv, argc, td); 126acc9d408SJuli Mallett if (mark != -1) 127acc9d408SJuli Mallett finish_trace(mark); 128acc9d408SJuli Mallett } 129acc9d408SJuli Mallett 130acc9d408SJuli Mallett /* 131acc9d408SJuli Mallett * expand_builtin - evaluate built-in macros. 132acc9d408SJuli Mallett */ 133acc9d408SJuli Mallett void 134acc9d408SJuli Mallett expand_builtin(argv, argc, td) 135acc9d408SJuli Mallett const char *argv[]; 136acc9d408SJuli Mallett int argc; 137acc9d408SJuli Mallett int td; 138acc9d408SJuli Mallett { 139acc9d408SJuli Mallett int c, n; 140acc9d408SJuli Mallett int ac; 1419b50d902SRodney W. Grimes static int sysval = 0; 1429b50d902SRodney W. Grimes 1439b50d902SRodney W. Grimes #ifdef DEBUG 1449b50d902SRodney W. Grimes printf("argc = %d\n", argc); 1459b50d902SRodney W. Grimes for (n = 0; n < argc; n++) 1469b50d902SRodney W. Grimes printf("argv[%d] = %s\n", n, argv[n]); 147acc9d408SJuli Mallett fflush(stdout); 1489b50d902SRodney W. Grimes #endif 149acc9d408SJuli Mallett 1509b50d902SRodney W. Grimes /* 1519b50d902SRodney W. Grimes * if argc == 3 and argv[2] is null, then we 1529b50d902SRodney W. Grimes * have macro-or-builtin() type call. We adjust 1539b50d902SRodney W. Grimes * argc to avoid further checking.. 1549b50d902SRodney W. Grimes */ 155acc9d408SJuli Mallett ac = argc; 156acc9d408SJuli Mallett 1579b50d902SRodney W. Grimes if (argc == 3 && !*(argv[2])) 1589b50d902SRodney W. Grimes argc--; 1599b50d902SRodney W. Grimes 160acc9d408SJuli Mallett switch (td & TYPEMASK) { 1619b50d902SRodney W. Grimes 1629b50d902SRodney W. Grimes case DEFITYPE: 1639b50d902SRodney W. Grimes if (argc > 2) 1649b50d902SRodney W. Grimes dodefine(argv[2], (argc > 3) ? argv[3] : null); 1659b50d902SRodney W. Grimes break; 1669b50d902SRodney W. Grimes 1679b50d902SRodney W. Grimes case PUSDTYPE: 1689b50d902SRodney W. Grimes if (argc > 2) 1699b50d902SRodney W. Grimes dopushdef(argv[2], (argc > 3) ? argv[3] : null); 1709b50d902SRodney W. Grimes break; 1719b50d902SRodney W. Grimes 1729b50d902SRodney W. Grimes case DUMPTYPE: 1739b50d902SRodney W. Grimes dodump(argv, argc); 1749b50d902SRodney W. Grimes break; 1759b50d902SRodney W. Grimes 176acc9d408SJuli Mallett case TRACEONTYPE: 177acc9d408SJuli Mallett dotrace(argv, argc, 1); 178acc9d408SJuli Mallett break; 179acc9d408SJuli Mallett 180acc9d408SJuli Mallett case TRACEOFFTYPE: 181acc9d408SJuli Mallett dotrace(argv, argc, 0); 182acc9d408SJuli Mallett break; 183acc9d408SJuli Mallett 1849b50d902SRodney W. Grimes case EXPRTYPE: 1859b50d902SRodney W. Grimes /* 1869b50d902SRodney W. Grimes * doexpr - evaluate arithmetic 1879b50d902SRodney W. Grimes * expression 1889b50d902SRodney W. Grimes */ 1899b50d902SRodney W. Grimes if (argc > 2) 1909b50d902SRodney W. Grimes pbnum(expr(argv[2])); 1919b50d902SRodney W. Grimes break; 1929b50d902SRodney W. Grimes 1939b50d902SRodney W. Grimes case IFELTYPE: 1949b50d902SRodney W. Grimes if (argc > 4) 1959b50d902SRodney W. Grimes doifelse(argv, argc); 1969b50d902SRodney W. Grimes break; 1979b50d902SRodney W. Grimes 1989b50d902SRodney W. Grimes case IFDFTYPE: 1999b50d902SRodney W. Grimes /* 2009b50d902SRodney W. Grimes * doifdef - select one of two 2019b50d902SRodney W. Grimes * alternatives based on the existence of 2029b50d902SRodney W. Grimes * another definition 2039b50d902SRodney W. Grimes */ 2049b50d902SRodney W. Grimes if (argc > 3) { 2059b50d902SRodney W. Grimes if (lookup(argv[2]) != nil) 2069b50d902SRodney W. Grimes pbstr(argv[3]); 2079b50d902SRodney W. Grimes else if (argc > 4) 2089b50d902SRodney W. Grimes pbstr(argv[4]); 2099b50d902SRodney W. Grimes } 2109b50d902SRodney W. Grimes break; 2119b50d902SRodney W. Grimes 2129b50d902SRodney W. Grimes case LENGTYPE: 2139b50d902SRodney W. Grimes /* 2149b50d902SRodney W. Grimes * dolen - find the length of the 2159b50d902SRodney W. Grimes * argument 2169b50d902SRodney W. Grimes */ 2179b50d902SRodney W. Grimes pbnum((argc > 2) ? strlen(argv[2]) : 0); 2189b50d902SRodney W. Grimes break; 2199b50d902SRodney W. Grimes 2209b50d902SRodney W. Grimes case INCRTYPE: 2219b50d902SRodney W. Grimes /* 2229b50d902SRodney W. Grimes * doincr - increment the value of the 2239b50d902SRodney W. Grimes * argument 2249b50d902SRodney W. Grimes */ 2259b50d902SRodney W. Grimes if (argc > 2) 2269b50d902SRodney W. Grimes pbnum(atoi(argv[2]) + 1); 2279b50d902SRodney W. Grimes break; 2289b50d902SRodney W. Grimes 2299b50d902SRodney W. Grimes case DECRTYPE: 2309b50d902SRodney W. Grimes /* 2319b50d902SRodney W. Grimes * dodecr - decrement the value of the 2329b50d902SRodney W. Grimes * argument 2339b50d902SRodney W. Grimes */ 2349b50d902SRodney W. Grimes if (argc > 2) 2359b50d902SRodney W. Grimes pbnum(atoi(argv[2]) - 1); 2369b50d902SRodney W. Grimes break; 2379b50d902SRodney W. Grimes 2389b50d902SRodney W. Grimes case SYSCTYPE: 2399b50d902SRodney W. Grimes /* 2409b50d902SRodney W. Grimes * dosys - execute system command 2419b50d902SRodney W. Grimes */ 2429b50d902SRodney W. Grimes if (argc > 2) 2439b50d902SRodney W. Grimes sysval = system(argv[2]); 2449b50d902SRodney W. Grimes break; 2459b50d902SRodney W. Grimes 2469b50d902SRodney W. Grimes case SYSVTYPE: 2479b50d902SRodney W. Grimes /* 2489b50d902SRodney W. Grimes * dosysval - return value of the last 2499b50d902SRodney W. Grimes * system call. 2509b50d902SRodney W. Grimes * 2519b50d902SRodney W. Grimes */ 2529b50d902SRodney W. Grimes pbnum(sysval); 2539b50d902SRodney W. Grimes break; 2549b50d902SRodney W. Grimes 255acc9d408SJuli Mallett case ESYSCMDTYPE: 256acc9d408SJuli Mallett if (argc > 2) 257acc9d408SJuli Mallett doesyscmd(argv[2]); 258acc9d408SJuli Mallett break; 2599b50d902SRodney W. Grimes case INCLTYPE: 2609b50d902SRodney W. Grimes if (argc > 2) 2619b50d902SRodney W. Grimes if (!doincl(argv[2])) 262acc9d408SJuli Mallett err(1, "%s at line %lu: include(%s)", 263acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 2649b50d902SRodney W. Grimes break; 2659b50d902SRodney W. Grimes 2669b50d902SRodney W. Grimes case SINCTYPE: 2679b50d902SRodney W. Grimes if (argc > 2) 2689b50d902SRodney W. Grimes (void) doincl(argv[2]); 2699b50d902SRodney W. Grimes break; 2709b50d902SRodney W. Grimes #ifdef EXTENDED 2719b50d902SRodney W. Grimes case PASTTYPE: 2729b50d902SRodney W. Grimes if (argc > 2) 2739b50d902SRodney W. Grimes if (!dopaste(argv[2])) 274acc9d408SJuli Mallett err(1, "%s at line %lu: paste(%s)", 275acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 2769b50d902SRodney W. Grimes break; 2779b50d902SRodney W. Grimes 2789b50d902SRodney W. Grimes case SPASTYPE: 2799b50d902SRodney W. Grimes if (argc > 2) 2809b50d902SRodney W. Grimes (void) dopaste(argv[2]); 2819b50d902SRodney W. Grimes break; 2829b50d902SRodney W. Grimes #endif 2839b50d902SRodney W. Grimes case CHNQTYPE: 284acc9d408SJuli Mallett if (mimic_gnu) 285acc9d408SJuli Mallett gnu_dochq(argv, ac); 286acc9d408SJuli Mallett else 2879b50d902SRodney W. Grimes dochq(argv, argc); 2889b50d902SRodney W. Grimes break; 2899b50d902SRodney W. Grimes 2909b50d902SRodney W. Grimes case CHNCTYPE: 291acc9d408SJuli Mallett if (mimic_gnu) 292acc9d408SJuli Mallett gnu_dochc(argv, ac); 293acc9d408SJuli Mallett else 2949b50d902SRodney W. Grimes dochc(argv, argc); 2959b50d902SRodney W. Grimes break; 2969b50d902SRodney W. Grimes 2979b50d902SRodney W. Grimes case SUBSTYPE: 2989b50d902SRodney W. Grimes /* 2999b50d902SRodney W. Grimes * dosub - select substring 3009b50d902SRodney W. Grimes * 3019b50d902SRodney W. Grimes */ 3029b50d902SRodney W. Grimes if (argc > 3) 3039b50d902SRodney W. Grimes dosub(argv, argc); 3049b50d902SRodney W. Grimes break; 3059b50d902SRodney W. Grimes 3069b50d902SRodney W. Grimes case SHIFTYPE: 3079b50d902SRodney W. Grimes /* 3089b50d902SRodney W. Grimes * doshift - push back all arguments 3099b50d902SRodney W. Grimes * except the first one (i.e. skip 3109b50d902SRodney W. Grimes * argv[2]) 3119b50d902SRodney W. Grimes */ 3129b50d902SRodney W. Grimes if (argc > 3) { 3139b50d902SRodney W. Grimes for (n = argc - 1; n > 3; n--) { 314acc9d408SJuli Mallett pbstr(rquote); 3159b50d902SRodney W. Grimes pbstr(argv[n]); 316acc9d408SJuli Mallett pbstr(lquote); 317acc9d408SJuli Mallett putback(COMMA); 3189b50d902SRodney W. Grimes } 319acc9d408SJuli Mallett pbstr(rquote); 3209b50d902SRodney W. Grimes pbstr(argv[3]); 321acc9d408SJuli Mallett pbstr(lquote); 3229b50d902SRodney W. Grimes } 3239b50d902SRodney W. Grimes break; 3249b50d902SRodney W. Grimes 3259b50d902SRodney W. Grimes case DIVRTYPE: 3269b50d902SRodney W. Grimes if (argc > 2 && (n = atoi(argv[2])) != 0) 3279b50d902SRodney W. Grimes dodiv(n); 3289b50d902SRodney W. Grimes else { 3299b50d902SRodney W. Grimes active = stdout; 3309b50d902SRodney W. Grimes oindex = 0; 3319b50d902SRodney W. Grimes } 3329b50d902SRodney W. Grimes break; 3339b50d902SRodney W. Grimes 3349b50d902SRodney W. Grimes case UNDVTYPE: 3359b50d902SRodney W. Grimes doundiv(argv, argc); 3369b50d902SRodney W. Grimes break; 3379b50d902SRodney W. Grimes 3389b50d902SRodney W. Grimes case DIVNTYPE: 3399b50d902SRodney W. Grimes /* 3409b50d902SRodney W. Grimes * dodivnum - return the number of 3419b50d902SRodney W. Grimes * current output diversion 3429b50d902SRodney W. Grimes */ 3439b50d902SRodney W. Grimes pbnum(oindex); 3449b50d902SRodney W. Grimes break; 3459b50d902SRodney W. Grimes 3469b50d902SRodney W. Grimes case UNDFTYPE: 3479b50d902SRodney W. Grimes /* 3489b50d902SRodney W. Grimes * doundefine - undefine a previously 3499b50d902SRodney W. Grimes * defined macro(s) or m4 keyword(s). 3509b50d902SRodney W. Grimes */ 3519b50d902SRodney W. Grimes if (argc > 2) 3529b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 3539b50d902SRodney W. Grimes remhash(argv[n], ALL); 3549b50d902SRodney W. Grimes break; 3559b50d902SRodney W. Grimes 3569b50d902SRodney W. Grimes case POPDTYPE: 3579b50d902SRodney W. Grimes /* 3589b50d902SRodney W. Grimes * dopopdef - remove the topmost 3599b50d902SRodney W. Grimes * definitions of macro(s) or m4 3609b50d902SRodney W. Grimes * keyword(s). 3619b50d902SRodney W. Grimes */ 3629b50d902SRodney W. Grimes if (argc > 2) 3639b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 3649b50d902SRodney W. Grimes remhash(argv[n], TOP); 3659b50d902SRodney W. Grimes break; 3669b50d902SRodney W. Grimes 3679b50d902SRodney W. Grimes case MKTMTYPE: 3689b50d902SRodney W. Grimes /* 3699b50d902SRodney W. Grimes * dotemp - create a temporary file 3709b50d902SRodney W. Grimes */ 371acc9d408SJuli Mallett if (argc > 2) { 372acc9d408SJuli Mallett int fd; 373acc9d408SJuli Mallett char *temp; 374acc9d408SJuli Mallett 375acc9d408SJuli Mallett temp = xstrdup(argv[2]); 376acc9d408SJuli Mallett 377acc9d408SJuli Mallett fd = mkstemp(temp); 378acc9d408SJuli Mallett if (fd == -1) 379acc9d408SJuli Mallett err(1, 380acc9d408SJuli Mallett "%s at line %lu: couldn't make temp file %s", 381acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 382acc9d408SJuli Mallett close(fd); 383acc9d408SJuli Mallett pbstr(temp); 384acc9d408SJuli Mallett free(temp); 385acc9d408SJuli Mallett } 3869b50d902SRodney W. Grimes break; 3879b50d902SRodney W. Grimes 3889b50d902SRodney W. Grimes case TRNLTYPE: 3899b50d902SRodney W. Grimes /* 3909b50d902SRodney W. Grimes * dotranslit - replace all characters in 3919b50d902SRodney W. Grimes * the source string that appears in the 3929b50d902SRodney W. Grimes * "from" string with the corresponding 3939b50d902SRodney W. Grimes * characters in the "to" string. 3949b50d902SRodney W. Grimes */ 3959b50d902SRodney W. Grimes if (argc > 3) { 396acc9d408SJuli Mallett char *temp; 397acc9d408SJuli Mallett 398acc9d408SJuli Mallett temp = xalloc(strlen(argv[2])+1); 3999b50d902SRodney W. Grimes if (argc > 4) 4009b50d902SRodney W. Grimes map(temp, argv[2], argv[3], argv[4]); 4019b50d902SRodney W. Grimes else 4029b50d902SRodney W. Grimes map(temp, argv[2], argv[3], null); 4039b50d902SRodney W. Grimes pbstr(temp); 404acc9d408SJuli Mallett free(temp); 405acc9d408SJuli Mallett } else if (argc > 2) 4069b50d902SRodney W. Grimes pbstr(argv[2]); 4079b50d902SRodney W. Grimes break; 4089b50d902SRodney W. Grimes 4099b50d902SRodney W. Grimes case INDXTYPE: 4109b50d902SRodney W. Grimes /* 4119b50d902SRodney W. Grimes * doindex - find the index of the second 4129b50d902SRodney W. Grimes * argument string in the first argument 4139b50d902SRodney W. Grimes * string. -1 if not present. 4149b50d902SRodney W. Grimes */ 4159b50d902SRodney W. Grimes pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 4169b50d902SRodney W. Grimes break; 4179b50d902SRodney W. Grimes 4189b50d902SRodney W. Grimes case ERRPTYPE: 4199b50d902SRodney W. Grimes /* 4209b50d902SRodney W. Grimes * doerrp - print the arguments to stderr 4219b50d902SRodney W. Grimes * file 4229b50d902SRodney W. Grimes */ 4239b50d902SRodney W. Grimes if (argc > 2) { 4249b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 4259b50d902SRodney W. Grimes fprintf(stderr, "%s ", argv[n]); 4269b50d902SRodney W. Grimes fprintf(stderr, "\n"); 4279b50d902SRodney W. Grimes } 4289b50d902SRodney W. Grimes break; 4299b50d902SRodney W. Grimes 4309b50d902SRodney W. Grimes case DNLNTYPE: 4319b50d902SRodney W. Grimes /* 4329b50d902SRodney W. Grimes * dodnl - eat-up-to and including 4339b50d902SRodney W. Grimes * newline 4349b50d902SRodney W. Grimes */ 4359b50d902SRodney W. Grimes while ((c = gpbc()) != '\n' && c != EOF) 4369b50d902SRodney W. Grimes ; 4379b50d902SRodney W. Grimes break; 4389b50d902SRodney W. Grimes 4399b50d902SRodney W. Grimes case M4WRTYPE: 4409b50d902SRodney W. Grimes /* 4419b50d902SRodney W. Grimes * dom4wrap - set up for 4429b50d902SRodney W. Grimes * wrap-up/wind-down activity 4439b50d902SRodney W. Grimes */ 444acc9d408SJuli Mallett m4wraps = (argc > 2) ? xstrdup(argv[2]) : null; 4459b50d902SRodney W. Grimes break; 4469b50d902SRodney W. Grimes 4479b50d902SRodney W. Grimes case EXITTYPE: 4489b50d902SRodney W. Grimes /* 4499b50d902SRodney W. Grimes * doexit - immediate exit from m4. 4509b50d902SRodney W. Grimes */ 451cac6992aSAndrey A. Chernov killdiv(); 4529b50d902SRodney W. Grimes exit((argc > 2) ? atoi(argv[2]) : 0); 4539b50d902SRodney W. Grimes break; 4549b50d902SRodney W. Grimes 4559b50d902SRodney W. Grimes case DEFNTYPE: 4569b50d902SRodney W. Grimes if (argc > 2) 4579b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 4589b50d902SRodney W. Grimes dodefn(argv[n]); 4599b50d902SRodney W. Grimes break; 4609b50d902SRodney W. Grimes 461acc9d408SJuli Mallett case INDIRTYPE: /* Indirect call */ 462acc9d408SJuli Mallett if (argc > 2) 463acc9d408SJuli Mallett doindir(argv, argc); 464bbfd1447SSteve Price break; 465bbfd1447SSteve Price 466acc9d408SJuli Mallett case BUILTINTYPE: /* Builtins only */ 467acc9d408SJuli Mallett if (argc > 2) 468acc9d408SJuli Mallett dobuiltin(argv, argc); 469acc9d408SJuli Mallett break; 470acc9d408SJuli Mallett 471acc9d408SJuli Mallett case PATSTYPE: 472acc9d408SJuli Mallett if (argc > 2) 473acc9d408SJuli Mallett dopatsubst(argv, argc); 474acc9d408SJuli Mallett break; 475acc9d408SJuli Mallett case REGEXPTYPE: 476acc9d408SJuli Mallett if (argc > 2) 477acc9d408SJuli Mallett doregexp(argv, argc); 478acc9d408SJuli Mallett break; 479acc9d408SJuli Mallett case LINETYPE: 480acc9d408SJuli Mallett doprintlineno(infile+ilevel); 481acc9d408SJuli Mallett break; 482acc9d408SJuli Mallett case FILENAMETYPE: 483acc9d408SJuli Mallett doprintfilename(infile+ilevel); 484acc9d408SJuli Mallett break; 485acc9d408SJuli Mallett case SELFTYPE: 486acc9d408SJuli Mallett pbstr(rquote); 487acc9d408SJuli Mallett pbstr(argv[1]); 488acc9d408SJuli Mallett pbstr(lquote); 489acc9d408SJuli Mallett break; 4909b50d902SRodney W. Grimes default: 491acc9d408SJuli Mallett errx(1, "%s at line %lu: eval: major botch.", 492acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE); 4939b50d902SRodney W. Grimes break; 4949b50d902SRodney W. Grimes } 4959b50d902SRodney W. Grimes } 4969b50d902SRodney W. Grimes 4979b50d902SRodney W. Grimes /* 498acc9d408SJuli Mallett * expand_macro - user-defined macro expansion 4999b50d902SRodney W. Grimes */ 5009b50d902SRodney W. Grimes void 501acc9d408SJuli Mallett expand_macro(argv, argc) 502acc9d408SJuli Mallett const char *argv[]; 503acc9d408SJuli Mallett int argc; 5049b50d902SRodney W. Grimes { 505acc9d408SJuli Mallett const char *t; 506acc9d408SJuli Mallett const char *p; 507acc9d408SJuli Mallett int n; 508acc9d408SJuli Mallett int argno; 5099b50d902SRodney W. Grimes 5109b50d902SRodney W. Grimes t = argv[0]; /* defn string as a whole */ 5119b50d902SRodney W. Grimes p = t; 5129b50d902SRodney W. Grimes while (*p) 5139b50d902SRodney W. Grimes p++; 5149b50d902SRodney W. Grimes p--; /* last character of defn */ 5159b50d902SRodney W. Grimes while (p > t) { 5169b50d902SRodney W. Grimes if (*(p - 1) != ARGFLAG) 517acc9d408SJuli Mallett PUTBACK(*p); 5189b50d902SRodney W. Grimes else { 5199b50d902SRodney W. Grimes switch (*p) { 5209b50d902SRodney W. Grimes 5219b50d902SRodney W. Grimes case '#': 5229b50d902SRodney W. Grimes pbnum(argc - 2); 5239b50d902SRodney W. Grimes break; 5249b50d902SRodney W. Grimes case '0': 5259b50d902SRodney W. Grimes case '1': 5269b50d902SRodney W. Grimes case '2': 5279b50d902SRodney W. Grimes case '3': 5289b50d902SRodney W. Grimes case '4': 5299b50d902SRodney W. Grimes case '5': 5309b50d902SRodney W. Grimes case '6': 5319b50d902SRodney W. Grimes case '7': 5329b50d902SRodney W. Grimes case '8': 5339b50d902SRodney W. Grimes case '9': 5349b50d902SRodney W. Grimes if ((argno = *p - '0') < argc - 1) 5359b50d902SRodney W. Grimes pbstr(argv[argno + 1]); 5369b50d902SRodney W. Grimes break; 5379b50d902SRodney W. Grimes case '*': 538acc9d408SJuli Mallett if (argc > 2) { 5399b50d902SRodney W. Grimes for (n = argc - 1; n > 2; n--) { 5409b50d902SRodney W. Grimes pbstr(argv[n]); 541acc9d408SJuli Mallett putback(COMMA); 5429b50d902SRodney W. Grimes } 5439b50d902SRodney W. Grimes pbstr(argv[2]); 544acc9d408SJuli Mallett } 5459b50d902SRodney W. Grimes break; 546232eaee6SJoerg Wunsch case '@': 547acc9d408SJuli Mallett if (argc > 2) { 548acc9d408SJuli Mallett for (n = argc - 1; n > 2; n--) { 549acc9d408SJuli Mallett pbstr(rquote); 550232eaee6SJoerg Wunsch pbstr(argv[n]); 551acc9d408SJuli Mallett pbstr(lquote); 552acc9d408SJuli Mallett putback(COMMA); 553acc9d408SJuli Mallett } 554acc9d408SJuli Mallett pbstr(rquote); 555acc9d408SJuli Mallett pbstr(argv[2]); 556acc9d408SJuli Mallett pbstr(lquote); 557232eaee6SJoerg Wunsch } 558232eaee6SJoerg Wunsch break; 5599b50d902SRodney W. Grimes default: 560acc9d408SJuli Mallett PUTBACK(*p); 561acc9d408SJuli Mallett PUTBACK('$'); 5629b50d902SRodney W. Grimes break; 5639b50d902SRodney W. Grimes } 5649b50d902SRodney W. Grimes p--; 5659b50d902SRodney W. Grimes } 5669b50d902SRodney W. Grimes p--; 5679b50d902SRodney W. Grimes } 5689b50d902SRodney W. Grimes if (p == t) /* do last character */ 569acc9d408SJuli Mallett PUTBACK(*p); 5709b50d902SRodney W. Grimes } 5719b50d902SRodney W. Grimes 5729b50d902SRodney W. Grimes /* 5739b50d902SRodney W. Grimes * dodefine - install definition in the table 5749b50d902SRodney W. Grimes */ 5759b50d902SRodney W. Grimes void 5769b50d902SRodney W. Grimes dodefine(name, defn) 577acc9d408SJuli Mallett const char *name; 578acc9d408SJuli Mallett const char *defn; 5799b50d902SRodney W. Grimes { 580acc9d408SJuli Mallett ndptr p; 581acc9d408SJuli Mallett int n; 5829b50d902SRodney W. Grimes 5839b50d902SRodney W. Grimes if (!*name) 584acc9d408SJuli Mallett errx(1, "%s at line %lu: null definition.", CURRENT_NAME, 585acc9d408SJuli Mallett CURRENT_LINE); 5869b50d902SRodney W. Grimes if ((p = lookup(name)) == nil) 5879b50d902SRodney W. Grimes p = addent(name); 5889b50d902SRodney W. Grimes else if (p->defn != null) 5899b50d902SRodney W. Grimes free((char *) p->defn); 590acc9d408SJuli Mallett if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0) { 591acc9d408SJuli Mallett n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1); 592acc9d408SJuli Mallett if (n != -1) { 593acc9d408SJuli Mallett p->type = n & TYPEMASK; 594acc9d408SJuli Mallett if ((n & NOARGS) == 0) 595acc9d408SJuli Mallett p->type |= NEEDARGS; 596acc9d408SJuli Mallett p->defn = null; 597acc9d408SJuli Mallett return; 598acc9d408SJuli Mallett } 599acc9d408SJuli Mallett } 6009b50d902SRodney W. Grimes if (!*defn) 6019b50d902SRodney W. Grimes p->defn = null; 6029b50d902SRodney W. Grimes else 603acc9d408SJuli Mallett p->defn = xstrdup(defn); 6049b50d902SRodney W. Grimes p->type = MACRTYPE; 605acc9d408SJuli Mallett if (STREQ(name, defn)) 606acc9d408SJuli Mallett p->type |= RECDEF; 6079b50d902SRodney W. Grimes } 6089b50d902SRodney W. Grimes 6099b50d902SRodney W. Grimes /* 6109b50d902SRodney W. Grimes * dodefn - push back a quoted definition of 6119b50d902SRodney W. Grimes * the given name. 6129b50d902SRodney W. Grimes */ 613acc9d408SJuli Mallett static void 6149b50d902SRodney W. Grimes dodefn(name) 615acc9d408SJuli Mallett const char *name; 6169b50d902SRodney W. Grimes { 617acc9d408SJuli Mallett ndptr p; 618acc9d408SJuli Mallett char *real; 6199b50d902SRodney W. Grimes 620acc9d408SJuli Mallett if ((p = lookup(name)) != nil) { 621acc9d408SJuli Mallett if (p->defn != null) { 622acc9d408SJuli Mallett pbstr(rquote); 6239b50d902SRodney W. Grimes pbstr(p->defn); 624acc9d408SJuli Mallett pbstr(lquote); 625acc9d408SJuli Mallett } else if ((real = builtin_realname(p->type)) != NULL) { 626acc9d408SJuli Mallett pbstr(real); 627acc9d408SJuli Mallett pbstr(BUILTIN_MARKER); 628acc9d408SJuli Mallett } 6299b50d902SRodney W. Grimes } 6309b50d902SRodney W. Grimes } 6319b50d902SRodney W. Grimes 6329b50d902SRodney W. Grimes /* 6339b50d902SRodney W. Grimes * dopushdef - install a definition in the hash table 6349b50d902SRodney W. Grimes * without removing a previous definition. Since 6359b50d902SRodney W. Grimes * each new entry is entered in *front* of the 6369b50d902SRodney W. Grimes * hash bucket, it hides a previous definition from 6379b50d902SRodney W. Grimes * lookup. 6389b50d902SRodney W. Grimes */ 639acc9d408SJuli Mallett static void 6409b50d902SRodney W. Grimes dopushdef(name, defn) 641acc9d408SJuli Mallett const char *name; 642acc9d408SJuli Mallett const char *defn; 6439b50d902SRodney W. Grimes { 644acc9d408SJuli Mallett ndptr p; 6459b50d902SRodney W. Grimes 6469b50d902SRodney W. Grimes if (!*name) 647acc9d408SJuli Mallett errx(1, "%s at line %lu: null definition", CURRENT_NAME, 648acc9d408SJuli Mallett CURRENT_LINE); 6499b50d902SRodney W. Grimes p = addent(name); 6509b50d902SRodney W. Grimes if (!*defn) 6519b50d902SRodney W. Grimes p->defn = null; 6529b50d902SRodney W. Grimes else 653acc9d408SJuli Mallett p->defn = xstrdup(defn); 6549b50d902SRodney W. Grimes p->type = MACRTYPE; 655acc9d408SJuli Mallett if (STREQ(name, defn)) 656acc9d408SJuli Mallett p->type |= RECDEF; 657acc9d408SJuli Mallett } 658acc9d408SJuli Mallett 659acc9d408SJuli Mallett /* 660acc9d408SJuli Mallett * dump_one_def - dump the specified definition. 661acc9d408SJuli Mallett */ 662acc9d408SJuli Mallett static void 663acc9d408SJuli Mallett dump_one_def(p) 664acc9d408SJuli Mallett ndptr p; 665acc9d408SJuli Mallett { 666acc9d408SJuli Mallett char *real; 667acc9d408SJuli Mallett 668acc9d408SJuli Mallett if (mimic_gnu) { 669acc9d408SJuli Mallett if ((p->type & TYPEMASK) == MACRTYPE) 670acc9d408SJuli Mallett fprintf(traceout, "%s:\t%s\n", p->name, p->defn); 671acc9d408SJuli Mallett else { 672acc9d408SJuli Mallett real = builtin_realname(p->type); 673acc9d408SJuli Mallett if (real == NULL) 674acc9d408SJuli Mallett real = null; 675acc9d408SJuli Mallett fprintf(traceout, "%s:\t<%s>\n", p->name, real); 676acc9d408SJuli Mallett } 677acc9d408SJuli Mallett } else 678acc9d408SJuli Mallett fprintf(traceout, "`%s'\t`%s'\n", p->name, p->defn); 6799b50d902SRodney W. Grimes } 6809b50d902SRodney W. Grimes 6819b50d902SRodney W. Grimes /* 6829b50d902SRodney W. Grimes * dodumpdef - dump the specified definitions in the hash 6839b50d902SRodney W. Grimes * table to stderr. If nothing is specified, the entire 6849b50d902SRodney W. Grimes * hash table is dumped. 6859b50d902SRodney W. Grimes */ 686acc9d408SJuli Mallett static void 6879b50d902SRodney W. Grimes dodump(argv, argc) 688acc9d408SJuli Mallett const char *argv[]; 689acc9d408SJuli Mallett int argc; 6909b50d902SRodney W. Grimes { 691acc9d408SJuli Mallett int n; 6929b50d902SRodney W. Grimes ndptr p; 6939b50d902SRodney W. Grimes 6949b50d902SRodney W. Grimes if (argc > 2) { 6959b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 6969b50d902SRodney W. Grimes if ((p = lookup(argv[n])) != nil) 697acc9d408SJuli Mallett dump_one_def(p); 698acc9d408SJuli Mallett } else { 6999b50d902SRodney W. Grimes for (n = 0; n < HASHSIZE; n++) 7009b50d902SRodney W. Grimes for (p = hashtab[n]; p != nil; p = p->nxtptr) 701acc9d408SJuli Mallett dump_one_def(p); 7029b50d902SRodney W. Grimes } 7039b50d902SRodney W. Grimes } 7049b50d902SRodney W. Grimes 7059b50d902SRodney W. Grimes /* 706acc9d408SJuli Mallett * dotrace - mark some macros as traced/untraced depending upon on. 707acc9d408SJuli Mallett */ 708acc9d408SJuli Mallett static void 709acc9d408SJuli Mallett dotrace(argv, argc, on) 710acc9d408SJuli Mallett const char *argv[]; 711acc9d408SJuli Mallett int argc; 712acc9d408SJuli Mallett int on; 713acc9d408SJuli Mallett { 714acc9d408SJuli Mallett int n; 715acc9d408SJuli Mallett 716acc9d408SJuli Mallett if (argc > 2) { 717acc9d408SJuli Mallett for (n = 2; n < argc; n++) 718acc9d408SJuli Mallett mark_traced(argv[n], on); 719acc9d408SJuli Mallett } else 720acc9d408SJuli Mallett mark_traced(NULL, on); 721acc9d408SJuli Mallett } 722acc9d408SJuli Mallett 723acc9d408SJuli Mallett /* 7249b50d902SRodney W. Grimes * doifelse - select one of two alternatives - loop. 7259b50d902SRodney W. Grimes */ 726acc9d408SJuli Mallett static void 7279b50d902SRodney W. Grimes doifelse(argv, argc) 728acc9d408SJuli Mallett const char *argv[]; 729acc9d408SJuli Mallett int argc; 7309b50d902SRodney W. Grimes { 7319b50d902SRodney W. Grimes cycle { 7329b50d902SRodney W. Grimes if (STREQ(argv[2], argv[3])) 7339b50d902SRodney W. Grimes pbstr(argv[4]); 7349b50d902SRodney W. Grimes else if (argc == 6) 7359b50d902SRodney W. Grimes pbstr(argv[5]); 7369b50d902SRodney W. Grimes else if (argc > 6) { 7379b50d902SRodney W. Grimes argv += 3; 7389b50d902SRodney W. Grimes argc -= 3; 7399b50d902SRodney W. Grimes continue; 7409b50d902SRodney W. Grimes } 7419b50d902SRodney W. Grimes break; 7429b50d902SRodney W. Grimes } 7439b50d902SRodney W. Grimes } 7449b50d902SRodney W. Grimes 7459b50d902SRodney W. Grimes /* 7469b50d902SRodney W. Grimes * doinclude - include a given file. 7479b50d902SRodney W. Grimes */ 748acc9d408SJuli Mallett static int 7499b50d902SRodney W. Grimes doincl(ifile) 750acc9d408SJuli Mallett const char *ifile; 7519b50d902SRodney W. Grimes { 7529b50d902SRodney W. Grimes if (ilevel + 1 == MAXINP) 753acc9d408SJuli Mallett errx(1, "%s at line %lu: too many include files.", 754acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE); 755acc9d408SJuli Mallett if (fopen_trypath(infile+ilevel+1, ifile) != NULL) { 7569b50d902SRodney W. Grimes ilevel++; 757b1ea3d46SJuli Mallett if ((inname[ilevel] = strdup(ifile)) == NULL) 758b1ea3d46SJuli Mallett err(1, NULL); 759b1ea3d46SJuli Mallett inlineno[ilevel] = 1; 7609b50d902SRodney W. Grimes bbase[ilevel] = bufbase = bp; 761b1ea3d46SJuli Mallett emitline(); 7629b50d902SRodney W. Grimes return (1); 763acc9d408SJuli Mallett } else 7649b50d902SRodney W. Grimes return (0); 7659b50d902SRodney W. Grimes } 7669b50d902SRodney W. Grimes 7679b50d902SRodney W. Grimes #ifdef EXTENDED 7689b50d902SRodney W. Grimes /* 7699b50d902SRodney W. Grimes * dopaste - include a given file without any 7709b50d902SRodney W. Grimes * macro processing. 7719b50d902SRodney W. Grimes */ 772acc9d408SJuli Mallett static int 7739b50d902SRodney W. Grimes dopaste(pfile) 774acc9d408SJuli Mallett const char *pfile; 7759b50d902SRodney W. Grimes { 7769b50d902SRodney W. Grimes FILE *pf; 777acc9d408SJuli Mallett int c; 7789b50d902SRodney W. Grimes 7799b50d902SRodney W. Grimes if ((pf = fopen(pfile, "r")) != NULL) { 780b1ea3d46SJuli Mallett fprintf(active, "#line 1 \"%s\"\n", pfile); 7819b50d902SRodney W. Grimes while ((c = getc(pf)) != EOF) 7829b50d902SRodney W. Grimes putc(c, active); 7839b50d902SRodney W. Grimes (void) fclose(pf); 784b1ea3d46SJuli Mallett emitline(); 7859b50d902SRodney W. Grimes return (1); 786acc9d408SJuli Mallett } else 7879b50d902SRodney W. Grimes return (0); 7889b50d902SRodney W. Grimes } 7899b50d902SRodney W. Grimes #endif 7909b50d902SRodney W. Grimes 791acc9d408SJuli Mallett static void 792acc9d408SJuli Mallett gnu_dochq(argv, ac) 793acc9d408SJuli Mallett const char *argv[]; 794acc9d408SJuli Mallett int ac; 7959b50d902SRodney W. Grimes { 796acc9d408SJuli Mallett /* In gnu-m4 mode, the only way to restore quotes is to have no 797acc9d408SJuli Mallett * arguments at all. */ 798acc9d408SJuli Mallett if (ac == 2) { 799acc9d408SJuli Mallett lquote[0] = LQUOTE, lquote[1] = EOS; 800acc9d408SJuli Mallett rquote[0] = RQUOTE, rquote[1] = EOS; 801acc9d408SJuli Mallett } else { 802acc9d408SJuli Mallett strlcpy(lquote, argv[2], sizeof(lquote)); 803acc9d408SJuli Mallett if(ac > 3) 804acc9d408SJuli Mallett strlcpy(rquote, argv[3], sizeof(rquote)); 805ef2cea81SJonathan Lemon else 806acc9d408SJuli Mallett rquote[0] = EOS; 8079b50d902SRodney W. Grimes } 8089b50d902SRodney W. Grimes } 8099b50d902SRodney W. Grimes 8109b50d902SRodney W. Grimes /* 811acc9d408SJuli Mallett * dochq - change quote characters 8129b50d902SRodney W. Grimes */ 813acc9d408SJuli Mallett static void 814acc9d408SJuli Mallett dochq(argv, argc) 815acc9d408SJuli Mallett const char *argv[]; 816acc9d408SJuli Mallett int argc; 8179b50d902SRodney W. Grimes { 8189b50d902SRodney W. Grimes if (argc > 2) { 8199b50d902SRodney W. Grimes if (*argv[2]) 820acc9d408SJuli Mallett strlcpy(lquote, argv[2], sizeof(lquote)); 821acc9d408SJuli Mallett else { 822acc9d408SJuli Mallett lquote[0] = LQUOTE; 823acc9d408SJuli Mallett lquote[1] = EOS; 824acc9d408SJuli Mallett } 8259b50d902SRodney W. Grimes if (argc > 3) { 8269b50d902SRodney W. Grimes if (*argv[3]) 827acc9d408SJuli Mallett strlcpy(rquote, argv[3], sizeof(rquote)); 828acc9d408SJuli Mallett } else 829acc9d408SJuli Mallett strcpy(rquote, lquote); 830acc9d408SJuli Mallett } else { 831acc9d408SJuli Mallett lquote[0] = LQUOTE, lquote[1] = EOS; 832acc9d408SJuli Mallett rquote[0] = RQUOTE, rquote[1] = EOS; 833acc9d408SJuli Mallett } 834acc9d408SJuli Mallett } 835acc9d408SJuli Mallett 836acc9d408SJuli Mallett static void 837acc9d408SJuli Mallett gnu_dochc(argv, ac) 838acc9d408SJuli Mallett const char *argv[]; 839acc9d408SJuli Mallett int ac; 840acc9d408SJuli Mallett { 841acc9d408SJuli Mallett /* In gnu-m4 mode, no arguments mean no comment 842acc9d408SJuli Mallett * arguments at all. */ 843acc9d408SJuli Mallett if (ac == 2) { 844acc9d408SJuli Mallett scommt[0] = EOS; 845acc9d408SJuli Mallett ecommt[0] = EOS; 846acc9d408SJuli Mallett } else { 847acc9d408SJuli Mallett if (*argv[2]) 848acc9d408SJuli Mallett strlcpy(scommt, argv[2], sizeof(scommt)); 849acc9d408SJuli Mallett else 850acc9d408SJuli Mallett scommt[0] = SCOMMT, scommt[1] = EOS; 851acc9d408SJuli Mallett if(ac > 3 && *argv[3]) 852acc9d408SJuli Mallett strlcpy(ecommt, argv[3], sizeof(ecommt)); 853acc9d408SJuli Mallett else 854acc9d408SJuli Mallett ecommt[0] = ECOMMT, ecommt[1] = EOS; 855acc9d408SJuli Mallett } 856acc9d408SJuli Mallett } 857acc9d408SJuli Mallett /* 858acc9d408SJuli Mallett * dochc - change comment characters 859acc9d408SJuli Mallett */ 860acc9d408SJuli Mallett static void 861acc9d408SJuli Mallett dochc(argv, argc) 862acc9d408SJuli Mallett const char *argv[]; 863acc9d408SJuli Mallett int argc; 864acc9d408SJuli Mallett { 865acc9d408SJuli Mallett if (argc > 2) { 866acc9d408SJuli Mallett if (*argv[2]) 867acc9d408SJuli Mallett strlcpy(scommt, argv[2], sizeof(scommt)); 868acc9d408SJuli Mallett if (argc > 3) { 869acc9d408SJuli Mallett if (*argv[3]) 870acc9d408SJuli Mallett strlcpy(ecommt, argv[3], sizeof(ecommt)); 8719b50d902SRodney W. Grimes } 8729b50d902SRodney W. Grimes else 873acc9d408SJuli Mallett ecommt[0] = ECOMMT, ecommt[1] = EOS; 8749b50d902SRodney W. Grimes } 8759b50d902SRodney W. Grimes else { 876acc9d408SJuli Mallett scommt[0] = SCOMMT, scommt[1] = EOS; 877acc9d408SJuli Mallett ecommt[0] = ECOMMT, ecommt[1] = EOS; 8789b50d902SRodney W. Grimes } 8799b50d902SRodney W. Grimes } 8809b50d902SRodney W. Grimes 8819b50d902SRodney W. Grimes /* 8829b50d902SRodney W. Grimes * dodivert - divert the output to a temporary file 8839b50d902SRodney W. Grimes */ 884acc9d408SJuli Mallett static void 8859b50d902SRodney W. Grimes dodiv(n) 886acc9d408SJuli Mallett int n; 8879b50d902SRodney W. Grimes { 888acc9d408SJuli Mallett int fd; 889acc9d408SJuli Mallett 890ef2cea81SJonathan Lemon oindex = n; 891acc9d408SJuli Mallett if (n >= maxout) { 892acc9d408SJuli Mallett if (mimic_gnu) 893acc9d408SJuli Mallett resizedivs(n + 10); 894acc9d408SJuli Mallett else 895acc9d408SJuli Mallett n = 0; /* bitbucket */ 896acc9d408SJuli Mallett } 897acc9d408SJuli Mallett 898acc9d408SJuli Mallett if (n < 0) 8999b50d902SRodney W. Grimes n = 0; /* bitbucket */ 9009b50d902SRodney W. Grimes if (outfile[n] == NULL) { 901acc9d408SJuli Mallett char fname[] = _PATH_DIVNAME; 902acc9d408SJuli Mallett 903acc9d408SJuli Mallett if ((fd = mkstemp(fname)) < 0 || 904acc9d408SJuli Mallett (outfile[n] = fdopen(fd, "w+")) == NULL) 905acc9d408SJuli Mallett err(1, "%s: cannot divert", fname); 906acc9d408SJuli Mallett if (unlink(fname) == -1) 907acc9d408SJuli Mallett err(1, "%s: cannot unlink", fname); 9089b50d902SRodney W. Grimes } 9099b50d902SRodney W. Grimes active = outfile[n]; 9109b50d902SRodney W. Grimes } 9119b50d902SRodney W. Grimes 9129b50d902SRodney W. Grimes /* 9139b50d902SRodney W. Grimes * doundivert - undivert a specified output, or all 9149b50d902SRodney W. Grimes * other outputs, in numerical order. 9159b50d902SRodney W. Grimes */ 916acc9d408SJuli Mallett static void 9179b50d902SRodney W. Grimes doundiv(argv, argc) 918acc9d408SJuli Mallett const char *argv[]; 919acc9d408SJuli Mallett int argc; 9209b50d902SRodney W. Grimes { 921acc9d408SJuli Mallett int ind; 922acc9d408SJuli Mallett int n; 9239b50d902SRodney W. Grimes 9249b50d902SRodney W. Grimes if (argc > 2) { 9259b50d902SRodney W. Grimes for (ind = 2; ind < argc; ind++) { 9269b50d902SRodney W. Grimes n = atoi(argv[ind]); 927acc9d408SJuli Mallett if (n > 0 && n < maxout && outfile[n] != NULL) 9289b50d902SRodney W. Grimes getdiv(n); 9299b50d902SRodney W. Grimes 9309b50d902SRodney W. Grimes } 9319b50d902SRodney W. Grimes } 9329b50d902SRodney W. Grimes else 933acc9d408SJuli Mallett for (n = 1; n < maxout; n++) 9349b50d902SRodney W. Grimes if (outfile[n] != NULL) 9359b50d902SRodney W. Grimes getdiv(n); 9369b50d902SRodney W. Grimes } 9379b50d902SRodney W. Grimes 9389b50d902SRodney W. Grimes /* 9399b50d902SRodney W. Grimes * dosub - select substring 9409b50d902SRodney W. Grimes */ 941acc9d408SJuli Mallett static void 9429b50d902SRodney W. Grimes dosub(argv, argc) 943acc9d408SJuli Mallett const char *argv[]; 944acc9d408SJuli Mallett int argc; 9459b50d902SRodney W. Grimes { 946acc9d408SJuli Mallett const char *ap, *fc, *k; 947acc9d408SJuli Mallett int nc; 9489b50d902SRodney W. Grimes 9499b50d902SRodney W. Grimes ap = argv[2]; /* target string */ 9509b50d902SRodney W. Grimes #ifdef EXPR 9519b50d902SRodney W. Grimes fc = ap + expr(argv[3]); /* first char */ 9529b50d902SRodney W. Grimes #else 9539b50d902SRodney W. Grimes fc = ap + atoi(argv[3]); /* first char */ 9549b50d902SRodney W. Grimes #endif 9554ba4d387SGregory Neil Shapiro nc = strlen(fc); 956acc9d408SJuli Mallett if (argc >= 5) 9574ba4d387SGregory Neil Shapiro #ifdef EXPR 958acc9d408SJuli Mallett nc = min(nc, expr(argv[4])); 9594ba4d387SGregory Neil Shapiro #else 960acc9d408SJuli Mallett nc = min(nc, atoi(argv[4])); 9614ba4d387SGregory Neil Shapiro #endif 9629b50d902SRodney W. Grimes if (fc >= ap && fc < ap + strlen(ap)) 9634ba4d387SGregory Neil Shapiro for (k = fc + nc - 1; k >= fc; k--) 9649b50d902SRodney W. Grimes putback(*k); 9659b50d902SRodney W. Grimes } 9669b50d902SRodney W. Grimes 9679b50d902SRodney W. Grimes /* 9689b50d902SRodney W. Grimes * map: 9699b50d902SRodney W. Grimes * map every character of s1 that is specified in from 9709b50d902SRodney W. Grimes * into s3 and replace in s. (source s1 remains untouched) 9719b50d902SRodney W. Grimes * 9729b50d902SRodney W. Grimes * This is a standard implementation of map(s,from,to) function of ICON 9739b50d902SRodney W. Grimes * language. Within mapvec, we replace every character of "from" with 9749b50d902SRodney W. Grimes * the corresponding character in "to". If "to" is shorter than "from", 9759b50d902SRodney W. Grimes * than the corresponding entries are null, which means that those 9769b50d902SRodney W. Grimes * characters dissapear altogether. Furthermore, imagine 9779b50d902SRodney W. Grimes * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case, 9789b50d902SRodney W. Grimes * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s' 9799b50d902SRodney W. Grimes * ultimately maps to `*'. In order to achieve this effect in an efficient 9809b50d902SRodney W. Grimes * manner (i.e. without multiple passes over the destination string), we 9819b50d902SRodney W. Grimes * loop over mapvec, starting with the initial source character. if the 9829b50d902SRodney W. Grimes * character value (dch) in this location is different than the source 9839b50d902SRodney W. Grimes * character (sch), sch becomes dch, once again to index into mapvec, until 9849b50d902SRodney W. Grimes * the character value stabilizes (i.e. sch = dch, in other words 9859b50d902SRodney W. Grimes * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary 9869b50d902SRodney W. Grimes * character, it will stabilize, since mapvec[0] == 0 at all times. At the 9879b50d902SRodney W. Grimes * end, we restore mapvec* back to normal where mapvec[n] == n for 9889b50d902SRodney W. Grimes * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is 9899b50d902SRodney W. Grimes * about 5 times faster than any algorithm that makes multiple passes over 9909b50d902SRodney W. Grimes * destination string. 9919b50d902SRodney W. Grimes */ 992acc9d408SJuli Mallett static void 9939b50d902SRodney W. Grimes map(dest, src, from, to) 994acc9d408SJuli Mallett char *dest; 995acc9d408SJuli Mallett const char *src; 996acc9d408SJuli Mallett const char *from; 997acc9d408SJuli Mallett const char *to; 9989b50d902SRodney W. Grimes { 999acc9d408SJuli Mallett const char *tmp; 1000acc9d408SJuli Mallett unsigned char sch, dch; 1001acc9d408SJuli Mallett static char frombis[257]; 1002acc9d408SJuli Mallett static char tobis[257]; 1003acc9d408SJuli Mallett static unsigned char mapvec[256] = { 1004acc9d408SJuli Mallett 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1005acc9d408SJuli Mallett 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 1006acc9d408SJuli Mallett 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 1007acc9d408SJuli Mallett 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 1008acc9d408SJuli Mallett 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 1009acc9d408SJuli Mallett 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 1010acc9d408SJuli Mallett 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 1011acc9d408SJuli Mallett 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 1012acc9d408SJuli Mallett 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 1013acc9d408SJuli Mallett 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 1014acc9d408SJuli Mallett 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 1015acc9d408SJuli Mallett 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 1016acc9d408SJuli Mallett 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 1017acc9d408SJuli Mallett 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 1018acc9d408SJuli Mallett 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 1019acc9d408SJuli Mallett 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 1020acc9d408SJuli Mallett 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 1021acc9d408SJuli Mallett 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 10229b50d902SRodney W. Grimes }; 10239b50d902SRodney W. Grimes 10249b50d902SRodney W. Grimes if (*src) { 1025acc9d408SJuli Mallett if (mimic_gnu) { 1026acc9d408SJuli Mallett /* 1027acc9d408SJuli Mallett * expand character ranges on the fly 1028acc9d408SJuli Mallett */ 1029acc9d408SJuli Mallett from = handledash(frombis, frombis + 256, from); 1030acc9d408SJuli Mallett to = handledash(tobis, tobis + 256, to); 1031acc9d408SJuli Mallett } 10329b50d902SRodney W. Grimes tmp = from; 10339b50d902SRodney W. Grimes /* 10349b50d902SRodney W. Grimes * create a mapping between "from" and 10359b50d902SRodney W. Grimes * "to" 10369b50d902SRodney W. Grimes */ 10379b50d902SRodney W. Grimes while (*from) 1038acc9d408SJuli Mallett mapvec[(unsigned char)(*from++)] = (*to) ? 1039acc9d408SJuli Mallett (unsigned char)(*to++) : 0; 10409b50d902SRodney W. Grimes 10419b50d902SRodney W. Grimes while (*src) { 1042acc9d408SJuli Mallett sch = (unsigned char)(*src++); 10439b50d902SRodney W. Grimes dch = mapvec[sch]; 10449b50d902SRodney W. Grimes while (dch != sch) { 10459b50d902SRodney W. Grimes sch = dch; 10469b50d902SRodney W. Grimes dch = mapvec[sch]; 10479b50d902SRodney W. Grimes } 1048acc9d408SJuli Mallett if ((*dest = (char)dch)) 10499b50d902SRodney W. Grimes dest++; 10509b50d902SRodney W. Grimes } 10519b50d902SRodney W. Grimes /* 10529b50d902SRodney W. Grimes * restore all the changed characters 10539b50d902SRodney W. Grimes */ 10549b50d902SRodney W. Grimes while (*tmp) { 1055acc9d408SJuli Mallett mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp); 10569b50d902SRodney W. Grimes tmp++; 10579b50d902SRodney W. Grimes } 10589b50d902SRodney W. Grimes } 1059acc9d408SJuli Mallett *dest = '\0'; 10609b50d902SRodney W. Grimes } 1061acc9d408SJuli Mallett 1062acc9d408SJuli Mallett 1063acc9d408SJuli Mallett /* 1064acc9d408SJuli Mallett * handledash: 1065acc9d408SJuli Mallett * use buffer to copy the src string, expanding character ranges 1066acc9d408SJuli Mallett * on the way. 1067acc9d408SJuli Mallett */ 1068acc9d408SJuli Mallett static const char * 1069acc9d408SJuli Mallett handledash(buffer, end, src) 1070acc9d408SJuli Mallett char *buffer; 1071acc9d408SJuli Mallett char *end; 1072acc9d408SJuli Mallett const char *src; 1073acc9d408SJuli Mallett { 1074acc9d408SJuli Mallett char *p; 1075acc9d408SJuli Mallett 1076acc9d408SJuli Mallett p = buffer; 1077acc9d408SJuli Mallett while(*src) { 1078acc9d408SJuli Mallett if (src[1] == '-' && src[2]) { 1079acc9d408SJuli Mallett unsigned char i; 1080acc9d408SJuli Mallett for (i = (unsigned char)src[0]; 1081acc9d408SJuli Mallett i <= (unsigned char)src[2]; i++) { 1082acc9d408SJuli Mallett *p++ = i; 1083acc9d408SJuli Mallett if (p == end) { 1084acc9d408SJuli Mallett *p = '\0'; 1085acc9d408SJuli Mallett return buffer; 1086acc9d408SJuli Mallett } 1087acc9d408SJuli Mallett } 1088acc9d408SJuli Mallett src += 3; 1089acc9d408SJuli Mallett } else 1090acc9d408SJuli Mallett *p++ = *src++; 1091acc9d408SJuli Mallett if (p == end) 1092acc9d408SJuli Mallett break; 1093acc9d408SJuli Mallett } 1094acc9d408SJuli Mallett *p = '\0'; 1095acc9d408SJuli Mallett return buffer; 1096acc9d408SJuli Mallett } 1097acc9d408SJuli Mallett 1098