1a841e1ebSBaptiste Daroussin /* $OpenBSD: eval.c,v 1.69 2011/03/24 11:23:08 espie 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. 19a841e1ebSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors 209b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 219b50d902SRodney W. Grimes * without specific prior written permission. 229b50d902SRodney W. Grimes * 239b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 249b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 259b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 269b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 279b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 289b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 299b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 309b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 319b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 329b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 339b50d902SRodney W. Grimes * SUCH DAMAGE. 349b50d902SRodney W. Grimes */ 359b50d902SRodney W. Grimes 36acc9d408SJuli Mallett #include <sys/cdefs.h> 37acc9d408SJuli Mallett __FBSDID("$FreeBSD$"); 389b50d902SRodney W. Grimes 39a841e1ebSBaptiste Daroussin 409b50d902SRodney W. Grimes /* 419b50d902SRodney W. Grimes * eval.c 429b50d902SRodney W. Grimes * Facility: m4 macro processor 439b50d902SRodney W. Grimes * by: oz 449b50d902SRodney W. Grimes */ 459b50d902SRodney W. Grimes 469b50d902SRodney W. Grimes #include <sys/types.h> 47a841e1ebSBaptiste Daroussin #include <err.h> 48acc9d408SJuli Mallett #include <errno.h> 49a841e1ebSBaptiste Daroussin #include <limits.h> 50acc9d408SJuli Mallett #include <unistd.h> 51a841e1ebSBaptiste Daroussin #include <stdint.h> 529b50d902SRodney W. Grimes #include <stdio.h> 539b50d902SRodney W. Grimes #include <stdlib.h> 54acc9d408SJuli Mallett #include <stddef.h> 559b50d902SRodney W. Grimes #include <string.h> 56acc9d408SJuli Mallett #include <fcntl.h> 579b50d902SRodney W. Grimes #include "mdef.h" 589b50d902SRodney W. Grimes #include "stdd.h" 599b50d902SRodney W. Grimes #include "extern.h" 609b50d902SRodney W. Grimes #include "pathnames.h" 619b50d902SRodney W. Grimes 62acc9d408SJuli Mallett static void dodefn(const char *); 63acc9d408SJuli Mallett static void dopushdef(const char *, const char *); 64acc9d408SJuli Mallett static void dodump(const char *[], int); 65acc9d408SJuli Mallett static void dotrace(const char *[], int, int); 66acc9d408SJuli Mallett static void doifelse(const char *[], int); 67acc9d408SJuli Mallett static int doincl(const char *); 68acc9d408SJuli Mallett static int dopaste(const char *); 69acc9d408SJuli Mallett static void dochq(const char *[], int); 70acc9d408SJuli Mallett static void dochc(const char *[], int); 71a841e1ebSBaptiste Daroussin static void dom4wrap(const char *); 72acc9d408SJuli Mallett static void dodiv(int); 73acc9d408SJuli Mallett static void doundiv(const char *[], int); 74acc9d408SJuli Mallett static void dosub(const char *[], int); 75acc9d408SJuli Mallett static void map(char *, const char *, const char *, const char *); 76acc9d408SJuli Mallett static const char *handledash(char *, char *, const char *); 77acc9d408SJuli Mallett static void expand_builtin(const char *[], int, int); 78acc9d408SJuli Mallett static void expand_macro(const char *[], int); 79a841e1ebSBaptiste Daroussin static void dump_one_def(const char *, struct macro_definition *); 80acc9d408SJuli Mallett 81acc9d408SJuli Mallett unsigned long expansion_id; 82acc9d408SJuli Mallett 839b50d902SRodney W. Grimes /* 84acc9d408SJuli Mallett * eval - eval all macros and builtins calls 859b50d902SRodney W. Grimes * argc - number of elements in argv. 869b50d902SRodney W. Grimes * argv - element vector : 879b50d902SRodney W. Grimes * argv[0] = definition of a user 88a841e1ebSBaptiste Daroussin * macro or NULL if built-in. 899b50d902SRodney W. Grimes * argv[1] = name of the macro or 909b50d902SRodney W. Grimes * built-in. 919b50d902SRodney W. Grimes * argv[2] = parameters to user-defined 929b50d902SRodney W. Grimes * . macro or built-in. 939b50d902SRodney W. Grimes * . 949b50d902SRodney W. Grimes * 95acc9d408SJuli Mallett * A call in the form of macro-or-builtin() will result in: 969b50d902SRodney W. Grimes * argv[0] = nullstr 979b50d902SRodney W. Grimes * argv[1] = macro-or-builtin 989b50d902SRodney W. Grimes * argv[2] = nullstr 99acc9d408SJuli Mallett * 100acc9d408SJuli Mallett * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin 1019b50d902SRodney W. Grimes */ 1029b50d902SRodney W. Grimes void 103a841e1ebSBaptiste Daroussin eval(const char *argv[], int argc, int td, int is_traced) 1049b50d902SRodney W. Grimes { 105a841e1ebSBaptiste Daroussin size_t mark = SIZE_MAX; 106acc9d408SJuli Mallett 107acc9d408SJuli Mallett expansion_id++; 108acc9d408SJuli Mallett if (td & RECDEF) 109a841e1ebSBaptiste Daroussin m4errx(1, "expanding recursive definition for %s.", argv[1]); 110a841e1ebSBaptiste Daroussin if (is_traced) 111acc9d408SJuli Mallett mark = trace(argv, argc, infile+ilevel); 112acc9d408SJuli Mallett if (td == MACRTYPE) 113acc9d408SJuli Mallett expand_macro(argv, argc); 114acc9d408SJuli Mallett else 115acc9d408SJuli Mallett expand_builtin(argv, argc, td); 116a841e1ebSBaptiste Daroussin if (mark != SIZE_MAX) 117acc9d408SJuli Mallett finish_trace(mark); 118acc9d408SJuli Mallett } 119acc9d408SJuli Mallett 120acc9d408SJuli Mallett /* 121acc9d408SJuli Mallett * expand_builtin - evaluate built-in macros. 122acc9d408SJuli Mallett */ 123acc9d408SJuli Mallett void 124bd2bfb58SJuli Mallett expand_builtin(const char *argv[], int argc, int td) 125acc9d408SJuli Mallett { 126acc9d408SJuli Mallett int c, n; 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) { 187a841e1ebSBaptiste Daroussin m4errx(1, "expr: base %s invalid.", argv[3]); 188a841e1ebSBaptiste Daroussin } 189a841e1ebSBaptiste Daroussin } 190a841e1ebSBaptiste Daroussin if (argc > 4) { 191a841e1ebSBaptiste Daroussin maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr); 192a841e1ebSBaptiste Daroussin if (errstr) { 193a841e1ebSBaptiste Daroussin m4errx(1, "expr: maxdigits %s invalid.", argv[4]); 194a841e1ebSBaptiste Daroussin } 195a841e1ebSBaptiste Daroussin } 1969b50d902SRodney W. Grimes if (argc > 2) 197a841e1ebSBaptiste Daroussin pbnumbase(expr(argv[2]), base, maxdigits); 1989b50d902SRodney W. Grimes break; 199a841e1ebSBaptiste Daroussin } 2009b50d902SRodney W. Grimes 2019b50d902SRodney W. Grimes case IFELTYPE: 2029b50d902SRodney W. Grimes if (argc > 4) 2039b50d902SRodney W. Grimes doifelse(argv, argc); 2049b50d902SRodney W. Grimes break; 2059b50d902SRodney W. Grimes 2069b50d902SRodney W. Grimes case IFDFTYPE: 2079b50d902SRodney W. Grimes /* 2089b50d902SRodney W. Grimes * doifdef - select one of two 2099b50d902SRodney W. Grimes * alternatives based on the existence of 2109b50d902SRodney W. Grimes * another definition 2119b50d902SRodney W. Grimes */ 2129b50d902SRodney W. Grimes if (argc > 3) { 213a841e1ebSBaptiste Daroussin if (lookup_macro_definition(argv[2]) != NULL) 2149b50d902SRodney W. Grimes pbstr(argv[3]); 2159b50d902SRodney W. Grimes else if (argc > 4) 2169b50d902SRodney W. Grimes pbstr(argv[4]); 2179b50d902SRodney W. Grimes } 2189b50d902SRodney W. Grimes break; 2199b50d902SRodney W. Grimes 2209b50d902SRodney W. Grimes case LENGTYPE: 2219b50d902SRodney W. Grimes /* 2229b50d902SRodney W. Grimes * dolen - find the length of the 2239b50d902SRodney W. Grimes * argument 2249b50d902SRodney W. Grimes */ 2259b50d902SRodney W. Grimes pbnum((argc > 2) ? strlen(argv[2]) : 0); 2269b50d902SRodney W. Grimes break; 2279b50d902SRodney W. Grimes 2289b50d902SRodney W. Grimes case INCRTYPE: 2299b50d902SRodney W. Grimes /* 2309b50d902SRodney W. Grimes * doincr - increment the value of the 2319b50d902SRodney W. Grimes * argument 2329b50d902SRodney W. Grimes */ 2339b50d902SRodney W. Grimes if (argc > 2) 2349b50d902SRodney W. Grimes pbnum(atoi(argv[2]) + 1); 2359b50d902SRodney W. Grimes break; 2369b50d902SRodney W. Grimes 2379b50d902SRodney W. Grimes case DECRTYPE: 2389b50d902SRodney W. Grimes /* 2399b50d902SRodney W. Grimes * dodecr - decrement the value of the 2409b50d902SRodney W. Grimes * argument 2419b50d902SRodney W. Grimes */ 2429b50d902SRodney W. Grimes if (argc > 2) 2439b50d902SRodney W. Grimes pbnum(atoi(argv[2]) - 1); 2449b50d902SRodney W. Grimes break; 2459b50d902SRodney W. Grimes 2469b50d902SRodney W. Grimes case SYSCTYPE: 2479b50d902SRodney W. Grimes /* 2489b50d902SRodney W. Grimes * dosys - execute system command 2499b50d902SRodney W. Grimes */ 250aef4bb33STim J. Robbins if (argc > 2) { 251a841e1ebSBaptiste Daroussin fflush(stdout); 2529b50d902SRodney W. Grimes sysval = system(argv[2]); 253aef4bb33STim J. Robbins } 2549b50d902SRodney W. Grimes break; 2559b50d902SRodney W. Grimes 2569b50d902SRodney W. Grimes case SYSVTYPE: 2579b50d902SRodney W. Grimes /* 2589b50d902SRodney W. Grimes * dosysval - return value of the last 2599b50d902SRodney W. Grimes * system call. 2609b50d902SRodney W. Grimes * 2619b50d902SRodney W. Grimes */ 2629b50d902SRodney W. Grimes pbnum(sysval); 2639b50d902SRodney W. Grimes break; 2649b50d902SRodney W. Grimes 265acc9d408SJuli Mallett case ESYSCMDTYPE: 266acc9d408SJuli Mallett if (argc > 2) 267acc9d408SJuli Mallett doesyscmd(argv[2]); 268acc9d408SJuli Mallett break; 2699b50d902SRodney W. Grimes case INCLTYPE: 2709b50d902SRodney W. Grimes if (argc > 2) 2712cce1b69SBjoern A. Zeeb if (!doincl(argv[2])) { 272*fb3f3d7cSBaptiste Daroussin if (mimic_gnu) { 2734fff7a14SBaptiste Daroussin warn("%s at line %lu: include(%s)", 2744fff7a14SBaptiste Daroussin CURRENT_NAME, CURRENT_LINE, argv[2]); 275*fb3f3d7cSBaptiste Daroussin exit_code = 1; 276*fb3f3d7cSBaptiste Daroussin } else 277acc9d408SJuli Mallett err(1, "%s at line %lu: include(%s)", 278acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 2792cce1b69SBjoern A. Zeeb } 2809b50d902SRodney W. Grimes break; 2819b50d902SRodney W. Grimes 2829b50d902SRodney W. Grimes case SINCTYPE: 2839b50d902SRodney W. Grimes if (argc > 2) 2849b50d902SRodney W. Grimes (void) doincl(argv[2]); 2859b50d902SRodney W. Grimes break; 2869b50d902SRodney W. Grimes #ifdef EXTENDED 2879b50d902SRodney W. Grimes case PASTTYPE: 2889b50d902SRodney W. Grimes if (argc > 2) 2899b50d902SRodney W. Grimes if (!dopaste(argv[2])) 290acc9d408SJuli Mallett err(1, "%s at line %lu: paste(%s)", 291acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 2929b50d902SRodney W. Grimes break; 2939b50d902SRodney W. Grimes 2949b50d902SRodney W. Grimes case SPASTYPE: 2959b50d902SRodney W. Grimes if (argc > 2) 2969b50d902SRodney W. Grimes (void) dopaste(argv[2]); 2979b50d902SRodney W. Grimes break; 298a841e1ebSBaptiste Daroussin case FORMATTYPE: 299a841e1ebSBaptiste Daroussin doformat(argv, argc); 300a841e1ebSBaptiste Daroussin break; 3019b50d902SRodney W. Grimes #endif 3029b50d902SRodney W. Grimes case CHNQTYPE: 303a841e1ebSBaptiste Daroussin dochq(argv, ac); 3049b50d902SRodney W. Grimes break; 3059b50d902SRodney W. Grimes 3069b50d902SRodney W. Grimes case CHNCTYPE: 3079b50d902SRodney W. Grimes dochc(argv, argc); 3089b50d902SRodney W. Grimes break; 3099b50d902SRodney W. Grimes 3109b50d902SRodney W. Grimes case SUBSTYPE: 3119b50d902SRodney W. Grimes /* 3129b50d902SRodney W. Grimes * dosub - select substring 3139b50d902SRodney W. Grimes * 3149b50d902SRodney W. Grimes */ 3159b50d902SRodney W. Grimes if (argc > 3) 3169b50d902SRodney W. Grimes dosub(argv, argc); 3179b50d902SRodney W. Grimes break; 3189b50d902SRodney W. Grimes 3199b50d902SRodney W. Grimes case SHIFTYPE: 3209b50d902SRodney W. Grimes /* 3219b50d902SRodney W. Grimes * doshift - push back all arguments 3229b50d902SRodney W. Grimes * except the first one (i.e. skip 3239b50d902SRodney W. Grimes * argv[2]) 3249b50d902SRodney W. Grimes */ 3259b50d902SRodney W. Grimes if (argc > 3) { 3269b50d902SRodney W. Grimes for (n = argc - 1; n > 3; n--) { 327acc9d408SJuli Mallett pbstr(rquote); 3289b50d902SRodney W. Grimes pbstr(argv[n]); 329acc9d408SJuli Mallett pbstr(lquote); 330a841e1ebSBaptiste Daroussin pushback(COMMA); 3319b50d902SRodney W. Grimes } 332acc9d408SJuli Mallett pbstr(rquote); 3339b50d902SRodney W. Grimes pbstr(argv[3]); 334acc9d408SJuli Mallett pbstr(lquote); 3359b50d902SRodney W. Grimes } 3369b50d902SRodney W. Grimes break; 3379b50d902SRodney W. Grimes 3389b50d902SRodney W. Grimes case DIVRTYPE: 3399b50d902SRodney W. Grimes if (argc > 2 && (n = atoi(argv[2])) != 0) 3409b50d902SRodney W. Grimes dodiv(n); 3419b50d902SRodney W. Grimes else { 3429b50d902SRodney W. Grimes active = stdout; 3439b50d902SRodney W. Grimes oindex = 0; 3449b50d902SRodney W. Grimes } 3459b50d902SRodney W. Grimes break; 3469b50d902SRodney W. Grimes 3479b50d902SRodney W. Grimes case UNDVTYPE: 3489b50d902SRodney W. Grimes doundiv(argv, argc); 3499b50d902SRodney W. Grimes break; 3509b50d902SRodney W. Grimes 3519b50d902SRodney W. Grimes case DIVNTYPE: 3529b50d902SRodney W. Grimes /* 3539b50d902SRodney W. Grimes * dodivnum - return the number of 3549b50d902SRodney W. Grimes * current output diversion 3559b50d902SRodney W. Grimes */ 3569b50d902SRodney W. Grimes pbnum(oindex); 3579b50d902SRodney W. Grimes break; 3589b50d902SRodney W. Grimes 3599b50d902SRodney W. Grimes case UNDFTYPE: 3609b50d902SRodney W. Grimes /* 3619b50d902SRodney W. Grimes * doundefine - undefine a previously 3629b50d902SRodney W. Grimes * defined macro(s) or m4 keyword(s). 3639b50d902SRodney W. Grimes */ 3649b50d902SRodney W. Grimes if (argc > 2) 3659b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 366a841e1ebSBaptiste Daroussin macro_undefine(argv[n]); 3679b50d902SRodney W. Grimes break; 3689b50d902SRodney W. Grimes 3699b50d902SRodney W. Grimes case POPDTYPE: 3709b50d902SRodney W. Grimes /* 3719b50d902SRodney W. Grimes * dopopdef - remove the topmost 3729b50d902SRodney W. Grimes * definitions of macro(s) or m4 3739b50d902SRodney W. Grimes * keyword(s). 3749b50d902SRodney W. Grimes */ 3759b50d902SRodney W. Grimes if (argc > 2) 3769b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 377a841e1ebSBaptiste Daroussin macro_popdef(argv[n]); 3789b50d902SRodney W. Grimes break; 3799b50d902SRodney W. Grimes 3809b50d902SRodney W. Grimes case MKTMTYPE: 3819b50d902SRodney W. Grimes /* 3829b50d902SRodney W. Grimes * dotemp - create a temporary file 3839b50d902SRodney W. Grimes */ 384acc9d408SJuli Mallett if (argc > 2) { 385acc9d408SJuli Mallett int fd; 386acc9d408SJuli Mallett char *temp; 387acc9d408SJuli Mallett 388acc9d408SJuli Mallett temp = xstrdup(argv[2]); 389acc9d408SJuli Mallett 390acc9d408SJuli Mallett fd = mkstemp(temp); 391acc9d408SJuli Mallett if (fd == -1) 392acc9d408SJuli Mallett err(1, 393acc9d408SJuli Mallett "%s at line %lu: couldn't make temp file %s", 394acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 395acc9d408SJuli Mallett close(fd); 396acc9d408SJuli Mallett pbstr(temp); 397acc9d408SJuli Mallett free(temp); 398acc9d408SJuli Mallett } 3999b50d902SRodney W. Grimes break; 4009b50d902SRodney W. Grimes 4019b50d902SRodney W. Grimes case TRNLTYPE: 4029b50d902SRodney W. Grimes /* 4039b50d902SRodney W. Grimes * dotranslit - replace all characters in 4049b50d902SRodney W. Grimes * the source string that appears in the 4059b50d902SRodney W. Grimes * "from" string with the corresponding 4069b50d902SRodney W. Grimes * characters in the "to" string. 4079b50d902SRodney W. Grimes */ 4089b50d902SRodney W. Grimes if (argc > 3) { 409acc9d408SJuli Mallett char *temp; 410acc9d408SJuli Mallett 411a841e1ebSBaptiste Daroussin temp = xalloc(strlen(argv[2])+1, NULL); 4129b50d902SRodney W. Grimes if (argc > 4) 4139b50d902SRodney W. Grimes map(temp, argv[2], argv[3], argv[4]); 4149b50d902SRodney W. Grimes else 4159b50d902SRodney W. Grimes map(temp, argv[2], argv[3], null); 4169b50d902SRodney W. Grimes pbstr(temp); 417acc9d408SJuli Mallett free(temp); 418acc9d408SJuli Mallett } else if (argc > 2) 4199b50d902SRodney W. Grimes pbstr(argv[2]); 4209b50d902SRodney W. Grimes break; 4219b50d902SRodney W. Grimes 4229b50d902SRodney W. Grimes case INDXTYPE: 4239b50d902SRodney W. Grimes /* 4249b50d902SRodney W. Grimes * doindex - find the index of the second 4259b50d902SRodney W. Grimes * argument string in the first argument 4269b50d902SRodney W. Grimes * string. -1 if not present. 4279b50d902SRodney W. Grimes */ 4289b50d902SRodney W. Grimes pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 4299b50d902SRodney W. Grimes break; 4309b50d902SRodney W. Grimes 4319b50d902SRodney W. Grimes case ERRPTYPE: 4329b50d902SRodney W. Grimes /* 4339b50d902SRodney W. Grimes * doerrp - print the arguments to stderr 4349b50d902SRodney W. Grimes * file 4359b50d902SRodney W. Grimes */ 4369b50d902SRodney W. Grimes if (argc > 2) { 4379b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 4389b50d902SRodney W. Grimes fprintf(stderr, "%s ", argv[n]); 4399b50d902SRodney W. Grimes fprintf(stderr, "\n"); 4409b50d902SRodney W. Grimes } 4419b50d902SRodney W. Grimes break; 4429b50d902SRodney W. Grimes 4439b50d902SRodney W. Grimes case DNLNTYPE: 4449b50d902SRodney W. Grimes /* 4459b50d902SRodney W. Grimes * dodnl - eat-up-to and including 4469b50d902SRodney W. Grimes * newline 4479b50d902SRodney W. Grimes */ 4489b50d902SRodney W. Grimes while ((c = gpbc()) != '\n' && c != EOF) 4499b50d902SRodney W. Grimes ; 4509b50d902SRodney W. Grimes break; 4519b50d902SRodney W. Grimes 4529b50d902SRodney W. Grimes case M4WRTYPE: 4539b50d902SRodney W. Grimes /* 4549b50d902SRodney W. Grimes * dom4wrap - set up for 4559b50d902SRodney W. Grimes * wrap-up/wind-down activity 4569b50d902SRodney W. Grimes */ 457a841e1ebSBaptiste Daroussin if (argc > 2) 458a841e1ebSBaptiste Daroussin dom4wrap(argv[2]); 4599b50d902SRodney W. Grimes break; 4609b50d902SRodney W. Grimes 4619b50d902SRodney W. Grimes case EXITTYPE: 4629b50d902SRodney W. Grimes /* 4639b50d902SRodney W. Grimes * doexit - immediate exit from m4. 4649b50d902SRodney W. Grimes */ 465cac6992aSAndrey A. Chernov killdiv(); 4669b50d902SRodney W. Grimes exit((argc > 2) ? atoi(argv[2]) : 0); 4679b50d902SRodney W. Grimes break; 4689b50d902SRodney W. Grimes 4699b50d902SRodney W. Grimes case DEFNTYPE: 4709b50d902SRodney W. Grimes if (argc > 2) 4719b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 4729b50d902SRodney W. Grimes dodefn(argv[n]); 4739b50d902SRodney W. Grimes break; 4749b50d902SRodney W. Grimes 475acc9d408SJuli Mallett case INDIRTYPE: /* Indirect call */ 476acc9d408SJuli Mallett if (argc > 2) 477acc9d408SJuli Mallett doindir(argv, argc); 478bbfd1447SSteve Price break; 479bbfd1447SSteve Price 480acc9d408SJuli Mallett case BUILTINTYPE: /* Builtins only */ 481acc9d408SJuli Mallett if (argc > 2) 482acc9d408SJuli Mallett dobuiltin(argv, argc); 483acc9d408SJuli Mallett break; 484acc9d408SJuli Mallett 485acc9d408SJuli Mallett case PATSTYPE: 486acc9d408SJuli Mallett if (argc > 2) 487acc9d408SJuli Mallett dopatsubst(argv, argc); 488acc9d408SJuli Mallett break; 489acc9d408SJuli Mallett case REGEXPTYPE: 490acc9d408SJuli Mallett if (argc > 2) 491acc9d408SJuli Mallett doregexp(argv, argc); 492acc9d408SJuli Mallett break; 493acc9d408SJuli Mallett case LINETYPE: 494acc9d408SJuli Mallett doprintlineno(infile+ilevel); 495acc9d408SJuli Mallett break; 496acc9d408SJuli Mallett case FILENAMETYPE: 497acc9d408SJuli Mallett doprintfilename(infile+ilevel); 498acc9d408SJuli Mallett break; 499acc9d408SJuli Mallett case SELFTYPE: 500acc9d408SJuli Mallett pbstr(rquote); 501acc9d408SJuli Mallett pbstr(argv[1]); 502acc9d408SJuli Mallett pbstr(lquote); 503acc9d408SJuli Mallett break; 5049b50d902SRodney W. Grimes default: 505a841e1ebSBaptiste Daroussin m4errx(1, "eval: major botch."); 5069b50d902SRodney W. Grimes break; 5079b50d902SRodney W. Grimes } 5089b50d902SRodney W. Grimes } 5099b50d902SRodney W. Grimes 5109b50d902SRodney W. Grimes /* 511acc9d408SJuli Mallett * expand_macro - user-defined macro expansion 5129b50d902SRodney W. Grimes */ 5139b50d902SRodney W. Grimes void 514bd2bfb58SJuli Mallett expand_macro(const char *argv[], int argc) 5159b50d902SRodney W. Grimes { 516acc9d408SJuli Mallett const char *t; 517acc9d408SJuli Mallett const char *p; 518acc9d408SJuli Mallett int n; 519acc9d408SJuli Mallett int argno; 5209b50d902SRodney W. Grimes 5219b50d902SRodney W. Grimes t = argv[0]; /* defn string as a whole */ 5229b50d902SRodney W. Grimes p = t; 5239b50d902SRodney W. Grimes while (*p) 5249b50d902SRodney W. Grimes p++; 5259b50d902SRodney W. Grimes p--; /* last character of defn */ 5269b50d902SRodney W. Grimes while (p > t) { 5279b50d902SRodney W. Grimes if (*(p - 1) != ARGFLAG) 528a841e1ebSBaptiste Daroussin PUSHBACK(*p); 5299b50d902SRodney W. Grimes else { 5309b50d902SRodney W. Grimes switch (*p) { 5319b50d902SRodney W. Grimes 5329b50d902SRodney W. Grimes case '#': 5339b50d902SRodney W. Grimes pbnum(argc - 2); 5349b50d902SRodney W. Grimes break; 5359b50d902SRodney W. Grimes case '0': 5369b50d902SRodney W. Grimes case '1': 5379b50d902SRodney W. Grimes case '2': 5389b50d902SRodney W. Grimes case '3': 5399b50d902SRodney W. Grimes case '4': 5409b50d902SRodney W. Grimes case '5': 5419b50d902SRodney W. Grimes case '6': 5429b50d902SRodney W. Grimes case '7': 5439b50d902SRodney W. Grimes case '8': 5449b50d902SRodney W. Grimes case '9': 5459b50d902SRodney W. Grimes if ((argno = *p - '0') < argc - 1) 5469b50d902SRodney W. Grimes pbstr(argv[argno + 1]); 5479b50d902SRodney W. Grimes break; 5489b50d902SRodney W. Grimes case '*': 549acc9d408SJuli Mallett if (argc > 2) { 5509b50d902SRodney W. Grimes for (n = argc - 1; n > 2; n--) { 5519b50d902SRodney W. Grimes pbstr(argv[n]); 552a841e1ebSBaptiste Daroussin pushback(COMMA); 5539b50d902SRodney W. Grimes } 5549b50d902SRodney W. Grimes pbstr(argv[2]); 555acc9d408SJuli Mallett } 5569b50d902SRodney W. Grimes break; 557232eaee6SJoerg Wunsch case '@': 558acc9d408SJuli Mallett if (argc > 2) { 559acc9d408SJuli Mallett for (n = argc - 1; n > 2; n--) { 560acc9d408SJuli Mallett pbstr(rquote); 561232eaee6SJoerg Wunsch pbstr(argv[n]); 562acc9d408SJuli Mallett pbstr(lquote); 563a841e1ebSBaptiste Daroussin pushback(COMMA); 564acc9d408SJuli Mallett } 565acc9d408SJuli Mallett pbstr(rquote); 566acc9d408SJuli Mallett pbstr(argv[2]); 567acc9d408SJuli Mallett pbstr(lquote); 568232eaee6SJoerg Wunsch } 569232eaee6SJoerg Wunsch break; 5709b50d902SRodney W. Grimes default: 571a841e1ebSBaptiste Daroussin PUSHBACK(*p); 572a841e1ebSBaptiste Daroussin PUSHBACK('$'); 5739b50d902SRodney W. Grimes break; 5749b50d902SRodney W. Grimes } 5759b50d902SRodney W. Grimes p--; 5769b50d902SRodney W. Grimes } 5779b50d902SRodney W. Grimes p--; 5789b50d902SRodney W. Grimes } 5799b50d902SRodney W. Grimes if (p == t) /* do last character */ 580a841e1ebSBaptiste Daroussin PUSHBACK(*p); 5819b50d902SRodney W. Grimes } 5829b50d902SRodney W. Grimes 583a841e1ebSBaptiste Daroussin 5849b50d902SRodney W. Grimes /* 5859b50d902SRodney W. Grimes * dodefine - install definition in the table 5869b50d902SRodney W. Grimes */ 5879b50d902SRodney W. Grimes void 588bd2bfb58SJuli Mallett dodefine(const char *name, const char *defn) 5899b50d902SRodney W. Grimes { 590a841e1ebSBaptiste Daroussin if (!*name && !mimic_gnu) 591a841e1ebSBaptiste Daroussin m4errx(1, "null definition."); 5929b50d902SRodney W. Grimes else 593a841e1ebSBaptiste Daroussin macro_define(name, defn); 5949b50d902SRodney W. Grimes } 5959b50d902SRodney W. Grimes 5969b50d902SRodney W. Grimes /* 5979b50d902SRodney W. Grimes * dodefn - push back a quoted definition of 5989b50d902SRodney W. Grimes * the given name. 5999b50d902SRodney W. Grimes */ 600acc9d408SJuli Mallett static void 601bd2bfb58SJuli Mallett dodefn(const char *name) 6029b50d902SRodney W. Grimes { 603a841e1ebSBaptiste Daroussin struct macro_definition *p; 6049b50d902SRodney W. Grimes 605a841e1ebSBaptiste Daroussin if ((p = lookup_macro_definition(name)) != NULL) { 606a841e1ebSBaptiste Daroussin if ((p->type & TYPEMASK) == MACRTYPE) { 607acc9d408SJuli Mallett pbstr(rquote); 6089b50d902SRodney W. Grimes pbstr(p->defn); 609acc9d408SJuli Mallett pbstr(lquote); 610a841e1ebSBaptiste Daroussin } else { 611a841e1ebSBaptiste Daroussin pbstr(p->defn); 612acc9d408SJuli Mallett pbstr(BUILTIN_MARKER); 613acc9d408SJuli Mallett } 6149b50d902SRodney W. Grimes } 6159b50d902SRodney W. Grimes } 6169b50d902SRodney W. Grimes 6179b50d902SRodney W. Grimes /* 6189b50d902SRodney W. Grimes * dopushdef - install a definition in the hash table 6199b50d902SRodney W. Grimes * without removing a previous definition. Since 6209b50d902SRodney W. Grimes * each new entry is entered in *front* of the 6219b50d902SRodney W. Grimes * hash bucket, it hides a previous definition from 6229b50d902SRodney W. Grimes * lookup. 6239b50d902SRodney W. Grimes */ 624acc9d408SJuli Mallett static void 625bd2bfb58SJuli Mallett dopushdef(const char *name, const char *defn) 6269b50d902SRodney W. Grimes { 627a841e1ebSBaptiste Daroussin if (!*name && !mimic_gnu) 628a841e1ebSBaptiste Daroussin m4errx(1, "null definition."); 6299b50d902SRodney W. Grimes else 630a841e1ebSBaptiste Daroussin macro_pushdef(name, defn); 631acc9d408SJuli Mallett } 632acc9d408SJuli Mallett 633acc9d408SJuli Mallett /* 634acc9d408SJuli Mallett * dump_one_def - dump the specified definition. 635acc9d408SJuli Mallett */ 636acc9d408SJuli Mallett static void 637a841e1ebSBaptiste Daroussin dump_one_def(const char *name, struct macro_definition *p) 638acc9d408SJuli Mallett { 639a841e1ebSBaptiste Daroussin if (!traceout) 640a841e1ebSBaptiste Daroussin traceout = stderr; 641acc9d408SJuli Mallett if (mimic_gnu) { 642acc9d408SJuli Mallett if ((p->type & TYPEMASK) == MACRTYPE) 643a841e1ebSBaptiste Daroussin fprintf(traceout, "%s:\t%s\n", name, p->defn); 644acc9d408SJuli Mallett else { 645a841e1ebSBaptiste Daroussin fprintf(traceout, "%s:\t<%s>\n", name, p->defn); 646acc9d408SJuli Mallett } 647acc9d408SJuli Mallett } else 648a841e1ebSBaptiste Daroussin fprintf(traceout, "`%s'\t`%s'\n", name, p->defn); 6499b50d902SRodney W. Grimes } 6509b50d902SRodney W. Grimes 6519b50d902SRodney W. Grimes /* 6529b50d902SRodney W. Grimes * dodumpdef - dump the specified definitions in the hash 6539b50d902SRodney W. Grimes * table to stderr. If nothing is specified, the entire 6549b50d902SRodney W. Grimes * hash table is dumped. 6559b50d902SRodney W. Grimes */ 656acc9d408SJuli Mallett static void 657bd2bfb58SJuli Mallett dodump(const char *argv[], int argc) 6589b50d902SRodney W. Grimes { 659acc9d408SJuli Mallett int n; 660a841e1ebSBaptiste Daroussin struct macro_definition *p; 6619b50d902SRodney W. Grimes 6629b50d902SRodney W. Grimes if (argc > 2) { 6639b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 664a841e1ebSBaptiste Daroussin if ((p = lookup_macro_definition(argv[n])) != NULL) 665a841e1ebSBaptiste Daroussin dump_one_def(argv[n], p); 666a841e1ebSBaptiste Daroussin } else 667a841e1ebSBaptiste Daroussin macro_for_all(dump_one_def); 6689b50d902SRodney W. Grimes } 6699b50d902SRodney W. Grimes 6709b50d902SRodney W. Grimes /* 671acc9d408SJuli Mallett * dotrace - mark some macros as traced/untraced depending upon on. 672acc9d408SJuli Mallett */ 673acc9d408SJuli Mallett static void 674bd2bfb58SJuli Mallett dotrace(const char *argv[], int argc, int on) 675acc9d408SJuli Mallett { 676acc9d408SJuli Mallett int n; 677acc9d408SJuli Mallett 678acc9d408SJuli Mallett if (argc > 2) { 679acc9d408SJuli Mallett for (n = 2; n < argc; n++) 680acc9d408SJuli Mallett mark_traced(argv[n], on); 681acc9d408SJuli Mallett } else 682acc9d408SJuli Mallett mark_traced(NULL, on); 683acc9d408SJuli Mallett } 684acc9d408SJuli Mallett 685acc9d408SJuli Mallett /* 6869b50d902SRodney W. Grimes * doifelse - select one of two alternatives - loop. 6879b50d902SRodney W. Grimes */ 688acc9d408SJuli Mallett static void 689bd2bfb58SJuli Mallett doifelse(const char *argv[], int argc) 6909b50d902SRodney W. Grimes { 6919b50d902SRodney W. Grimes cycle { 6929b50d902SRodney W. Grimes if (STREQ(argv[2], argv[3])) 6939b50d902SRodney W. Grimes pbstr(argv[4]); 6949b50d902SRodney W. Grimes else if (argc == 6) 6959b50d902SRodney W. Grimes pbstr(argv[5]); 6969b50d902SRodney W. Grimes else if (argc > 6) { 6979b50d902SRodney W. Grimes argv += 3; 6989b50d902SRodney W. Grimes argc -= 3; 6999b50d902SRodney W. Grimes continue; 7009b50d902SRodney W. Grimes } 7019b50d902SRodney W. Grimes break; 7029b50d902SRodney W. Grimes } 7039b50d902SRodney W. Grimes } 7049b50d902SRodney W. Grimes 7059b50d902SRodney W. Grimes /* 7069b50d902SRodney W. Grimes * doinclude - include a given file. 7079b50d902SRodney W. Grimes */ 708acc9d408SJuli Mallett static int 709bd2bfb58SJuli Mallett doincl(const char *ifile) 7109b50d902SRodney W. Grimes { 7119b50d902SRodney W. Grimes if (ilevel + 1 == MAXINP) 712a841e1ebSBaptiste Daroussin m4errx(1, "too many include files."); 713acc9d408SJuli Mallett if (fopen_trypath(infile+ilevel+1, ifile) != NULL) { 7149b50d902SRodney W. Grimes ilevel++; 7159b50d902SRodney W. Grimes bbase[ilevel] = bufbase = bp; 7169b50d902SRodney W. Grimes return (1); 717acc9d408SJuli Mallett } else 7189b50d902SRodney W. Grimes return (0); 7199b50d902SRodney W. Grimes } 7209b50d902SRodney W. Grimes 7219b50d902SRodney W. Grimes #ifdef EXTENDED 7229b50d902SRodney W. Grimes /* 7239b50d902SRodney W. Grimes * dopaste - include a given file without any 7249b50d902SRodney W. Grimes * macro processing. 7259b50d902SRodney W. Grimes */ 726acc9d408SJuli Mallett static int 727bd2bfb58SJuli Mallett dopaste(const char *pfile) 7289b50d902SRodney W. Grimes { 7299b50d902SRodney W. Grimes FILE *pf; 730acc9d408SJuli Mallett int c; 7319b50d902SRodney W. Grimes 7329b50d902SRodney W. Grimes if ((pf = fopen(pfile, "r")) != NULL) { 733a841e1ebSBaptiste Daroussin if (synch_lines) 734b1ea3d46SJuli Mallett fprintf(active, "#line 1 \"%s\"\n", pfile); 7359b50d902SRodney W. Grimes while ((c = getc(pf)) != EOF) 7369b50d902SRodney W. Grimes putc(c, active); 7379b50d902SRodney W. Grimes (void) fclose(pf); 738a841e1ebSBaptiste Daroussin emit_synchline(); 7399b50d902SRodney W. Grimes return (1); 740acc9d408SJuli Mallett } else 7419b50d902SRodney W. Grimes return (0); 7429b50d902SRodney W. Grimes } 7439b50d902SRodney W. Grimes #endif 7449b50d902SRodney W. Grimes 7459b50d902SRodney W. Grimes /* 746acc9d408SJuli Mallett * dochq - change quote characters 7479b50d902SRodney W. Grimes */ 748acc9d408SJuli Mallett static void 749a841e1ebSBaptiste Daroussin dochq(const char *argv[], int ac) 7509b50d902SRodney W. Grimes { 751a841e1ebSBaptiste Daroussin if (ac == 2) { 752a841e1ebSBaptiste Daroussin lquote[0] = LQUOTE; lquote[1] = EOS; 753a841e1ebSBaptiste Daroussin rquote[0] = RQUOTE; rquote[1] = EOS; 754acc9d408SJuli Mallett } else { 755a841e1ebSBaptiste Daroussin strlcpy(lquote, argv[2], sizeof(lquote)); 756a841e1ebSBaptiste Daroussin if (ac > 3) { 757a841e1ebSBaptiste Daroussin strlcpy(rquote, argv[3], sizeof(rquote)); 758a841e1ebSBaptiste Daroussin } else { 759a841e1ebSBaptiste Daroussin rquote[0] = ECOMMT; rquote[1] = EOS; 760a841e1ebSBaptiste Daroussin } 761acc9d408SJuli Mallett } 762acc9d408SJuli Mallett } 763acc9d408SJuli Mallett 764acc9d408SJuli Mallett /* 765acc9d408SJuli Mallett * dochc - change comment characters 766acc9d408SJuli Mallett */ 767acc9d408SJuli Mallett static void 768bd2bfb58SJuli Mallett dochc(const char *argv[], int argc) 769acc9d408SJuli Mallett { 770a841e1ebSBaptiste Daroussin /* XXX Note that there is no difference between no argument and a single 771a841e1ebSBaptiste Daroussin * empty argument. 772a841e1ebSBaptiste Daroussin */ 773a841e1ebSBaptiste Daroussin if (argc == 2) { 774a841e1ebSBaptiste Daroussin scommt[0] = EOS; 775a841e1ebSBaptiste Daroussin ecommt[0] = EOS; 776a841e1ebSBaptiste Daroussin } else { 777acc9d408SJuli Mallett strlcpy(scommt, argv[2], sizeof(scommt)); 778a841e1ebSBaptiste Daroussin if (argc == 3) { 779a841e1ebSBaptiste Daroussin ecommt[0] = ECOMMT; ecommt[1] = EOS; 780a841e1ebSBaptiste Daroussin } else { 781acc9d408SJuli Mallett strlcpy(ecommt, argv[3], sizeof(ecommt)); 7829b50d902SRodney W. Grimes } 783a841e1ebSBaptiste Daroussin } 784a841e1ebSBaptiste Daroussin } 785a841e1ebSBaptiste Daroussin 786a841e1ebSBaptiste Daroussin /* 787a841e1ebSBaptiste Daroussin * dom4wrap - expand text at EOF 788a841e1ebSBaptiste Daroussin */ 789a841e1ebSBaptiste Daroussin static void 790a841e1ebSBaptiste Daroussin dom4wrap(const char *text) 791a841e1ebSBaptiste Daroussin { 792a841e1ebSBaptiste Daroussin if (wrapindex >= maxwraps) { 793a841e1ebSBaptiste Daroussin if (maxwraps == 0) 794a841e1ebSBaptiste Daroussin maxwraps = 16; 7959b50d902SRodney W. Grimes else 796a841e1ebSBaptiste Daroussin maxwraps *= 2; 797a841e1ebSBaptiste Daroussin m4wraps = xrealloc(m4wraps, maxwraps * sizeof(*m4wraps), 798a841e1ebSBaptiste Daroussin "too many m4wraps"); 7999b50d902SRodney W. Grimes } 800a841e1ebSBaptiste Daroussin m4wraps[wrapindex++] = xstrdup(text); 8019b50d902SRodney W. Grimes } 8029b50d902SRodney W. Grimes 8039b50d902SRodney W. Grimes /* 8049b50d902SRodney W. Grimes * dodivert - divert the output to a temporary file 8059b50d902SRodney W. Grimes */ 806acc9d408SJuli Mallett static void 807bd2bfb58SJuli Mallett dodiv(int n) 8089b50d902SRodney W. Grimes { 809acc9d408SJuli Mallett int fd; 810acc9d408SJuli Mallett 811ef2cea81SJonathan Lemon oindex = n; 812acc9d408SJuli Mallett if (n >= maxout) { 813acc9d408SJuli Mallett if (mimic_gnu) 814acc9d408SJuli Mallett resizedivs(n + 10); 815acc9d408SJuli Mallett else 816acc9d408SJuli Mallett n = 0; /* bitbucket */ 817acc9d408SJuli Mallett } 818acc9d408SJuli Mallett 819acc9d408SJuli Mallett if (n < 0) 8209b50d902SRodney W. Grimes n = 0; /* bitbucket */ 8219b50d902SRodney W. Grimes if (outfile[n] == NULL) { 822acc9d408SJuli Mallett char fname[] = _PATH_DIVNAME; 823acc9d408SJuli Mallett 824acc9d408SJuli Mallett if ((fd = mkstemp(fname)) < 0 || 825acc9d408SJuli Mallett (outfile[n] = fdopen(fd, "w+")) == NULL) 826acc9d408SJuli Mallett err(1, "%s: cannot divert", fname); 827acc9d408SJuli Mallett if (unlink(fname) == -1) 828acc9d408SJuli Mallett err(1, "%s: cannot unlink", fname); 8299b50d902SRodney W. Grimes } 8309b50d902SRodney W. Grimes active = outfile[n]; 8319b50d902SRodney W. Grimes } 8329b50d902SRodney W. Grimes 8339b50d902SRodney W. Grimes /* 8349b50d902SRodney W. Grimes * doundivert - undivert a specified output, or all 8359b50d902SRodney W. Grimes * other outputs, in numerical order. 8369b50d902SRodney W. Grimes */ 837acc9d408SJuli Mallett static void 838bd2bfb58SJuli Mallett doundiv(const char *argv[], int argc) 8399b50d902SRodney W. Grimes { 840acc9d408SJuli Mallett int ind; 841acc9d408SJuli Mallett int n; 8429b50d902SRodney W. Grimes 8439b50d902SRodney W. Grimes if (argc > 2) { 8449b50d902SRodney W. Grimes for (ind = 2; ind < argc; ind++) { 845a841e1ebSBaptiste Daroussin const char *errstr; 846a841e1ebSBaptiste Daroussin n = strtonum(argv[ind], 1, INT_MAX, &errstr); 847a841e1ebSBaptiste Daroussin if (errstr) { 848a841e1ebSBaptiste Daroussin if (errno == EINVAL && mimic_gnu) 849a841e1ebSBaptiste Daroussin getdivfile(argv[ind]); 850a841e1ebSBaptiste Daroussin } else { 851a841e1ebSBaptiste Daroussin if (n < maxout && outfile[n] != NULL) 8529b50d902SRodney W. Grimes getdiv(n); 853a841e1ebSBaptiste Daroussin } 8549b50d902SRodney W. Grimes } 8559b50d902SRodney W. Grimes } 8569b50d902SRodney W. Grimes else 857acc9d408SJuli Mallett for (n = 1; n < maxout; n++) 8589b50d902SRodney W. Grimes if (outfile[n] != NULL) 8599b50d902SRodney W. Grimes getdiv(n); 8609b50d902SRodney W. Grimes } 8619b50d902SRodney W. Grimes 8629b50d902SRodney W. Grimes /* 8639b50d902SRodney W. Grimes * dosub - select substring 8649b50d902SRodney W. Grimes */ 865acc9d408SJuli Mallett static void 866bd2bfb58SJuli Mallett dosub(const char *argv[], int argc) 8679b50d902SRodney W. Grimes { 868acc9d408SJuli Mallett const char *ap, *fc, *k; 869acc9d408SJuli Mallett int nc; 8709b50d902SRodney W. Grimes 8719b50d902SRodney W. Grimes ap = argv[2]; /* target string */ 8729b50d902SRodney W. Grimes #ifdef EXPR 8739b50d902SRodney W. Grimes fc = ap + expr(argv[3]); /* first char */ 8749b50d902SRodney W. Grimes #else 8759b50d902SRodney W. Grimes fc = ap + atoi(argv[3]); /* first char */ 8769b50d902SRodney W. Grimes #endif 8774ba4d387SGregory Neil Shapiro nc = strlen(fc); 878acc9d408SJuli Mallett if (argc >= 5) 8794ba4d387SGregory Neil Shapiro #ifdef EXPR 880acc9d408SJuli Mallett nc = min(nc, expr(argv[4])); 8814ba4d387SGregory Neil Shapiro #else 882acc9d408SJuli Mallett nc = min(nc, atoi(argv[4])); 8834ba4d387SGregory Neil Shapiro #endif 8849b50d902SRodney W. Grimes if (fc >= ap && fc < ap + strlen(ap)) 8854ba4d387SGregory Neil Shapiro for (k = fc + nc - 1; k >= fc; k--) 886a841e1ebSBaptiste Daroussin pushback(*k); 8879b50d902SRodney W. Grimes } 8889b50d902SRodney W. Grimes 8899b50d902SRodney W. Grimes /* 8909b50d902SRodney W. Grimes * map: 8919b50d902SRodney W. Grimes * map every character of s1 that is specified in from 8929b50d902SRodney W. Grimes * into s3 and replace in s. (source s1 remains untouched) 8939b50d902SRodney W. Grimes * 894a841e1ebSBaptiste Daroussin * This is derived from the a standard implementation of map(s,from,to) 895a841e1ebSBaptiste Daroussin * function of ICON language. Within mapvec, we replace every character 896a841e1ebSBaptiste Daroussin * of "from" with the corresponding character in "to". 897a841e1ebSBaptiste Daroussin * If "to" is shorter than "from", than the corresponding entries are null, 898a841e1ebSBaptiste Daroussin * which means that those characters dissapear altogether. 8999b50d902SRodney W. Grimes */ 900acc9d408SJuli Mallett static void 901bd2bfb58SJuli Mallett map(char *dest, const char *src, const char *from, const char *to) 9029b50d902SRodney W. Grimes { 903acc9d408SJuli Mallett const char *tmp; 904acc9d408SJuli Mallett unsigned char sch, dch; 905acc9d408SJuli Mallett static char frombis[257]; 906acc9d408SJuli Mallett static char tobis[257]; 907a841e1ebSBaptiste Daroussin int i; 908a841e1ebSBaptiste Daroussin char seen[256]; 909acc9d408SJuli Mallett static unsigned char mapvec[256] = { 910acc9d408SJuli Mallett 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 911acc9d408SJuli Mallett 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 912acc9d408SJuli Mallett 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 913acc9d408SJuli Mallett 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 914acc9d408SJuli Mallett 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 915acc9d408SJuli Mallett 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 916acc9d408SJuli Mallett 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 917acc9d408SJuli Mallett 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 918acc9d408SJuli Mallett 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 919acc9d408SJuli Mallett 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 920acc9d408SJuli Mallett 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 921acc9d408SJuli Mallett 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 922acc9d408SJuli Mallett 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 923acc9d408SJuli Mallett 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 924acc9d408SJuli Mallett 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 925acc9d408SJuli Mallett 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 926acc9d408SJuli Mallett 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 927acc9d408SJuli Mallett 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 9289b50d902SRodney W. Grimes }; 9299b50d902SRodney W. Grimes 9309b50d902SRodney W. Grimes if (*src) { 931acc9d408SJuli Mallett if (mimic_gnu) { 932acc9d408SJuli Mallett /* 933acc9d408SJuli Mallett * expand character ranges on the fly 934acc9d408SJuli Mallett */ 935acc9d408SJuli Mallett from = handledash(frombis, frombis + 256, from); 936acc9d408SJuli Mallett to = handledash(tobis, tobis + 256, to); 937acc9d408SJuli Mallett } 9389b50d902SRodney W. Grimes tmp = from; 9399b50d902SRodney W. Grimes /* 9409b50d902SRodney W. Grimes * create a mapping between "from" and 9419b50d902SRodney W. Grimes * "to" 9429b50d902SRodney W. Grimes */ 943a841e1ebSBaptiste Daroussin for (i = 0; i < 256; i++) 944a841e1ebSBaptiste Daroussin seen[i] = 0; 945a841e1ebSBaptiste Daroussin while (*from) { 946a841e1ebSBaptiste Daroussin if (!seen[(unsigned char)(*from)]) { 947a841e1ebSBaptiste Daroussin mapvec[(unsigned char)(*from)] = (unsigned char)(*to); 948a841e1ebSBaptiste Daroussin seen[(unsigned char)(*from)] = 1; 949a841e1ebSBaptiste Daroussin } 950a841e1ebSBaptiste Daroussin from++; 951a841e1ebSBaptiste Daroussin if (*to) 952a841e1ebSBaptiste Daroussin to++; 953a841e1ebSBaptiste Daroussin } 9549b50d902SRodney W. Grimes 9559b50d902SRodney W. Grimes while (*src) { 956acc9d408SJuli Mallett sch = (unsigned char)(*src++); 9579b50d902SRodney W. Grimes dch = mapvec[sch]; 958acc9d408SJuli Mallett if ((*dest = (char)dch)) 9599b50d902SRodney W. Grimes dest++; 9609b50d902SRodney W. Grimes } 9619b50d902SRodney W. Grimes /* 9629b50d902SRodney W. Grimes * restore all the changed characters 9639b50d902SRodney W. Grimes */ 9649b50d902SRodney W. Grimes while (*tmp) { 965acc9d408SJuli Mallett mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp); 9669b50d902SRodney W. Grimes tmp++; 9679b50d902SRodney W. Grimes } 9689b50d902SRodney W. Grimes } 969acc9d408SJuli Mallett *dest = '\0'; 9709b50d902SRodney W. Grimes } 971acc9d408SJuli Mallett 972acc9d408SJuli Mallett 973acc9d408SJuli Mallett /* 974acc9d408SJuli Mallett * handledash: 975acc9d408SJuli Mallett * use buffer to copy the src string, expanding character ranges 976acc9d408SJuli Mallett * on the way. 977acc9d408SJuli Mallett */ 978acc9d408SJuli Mallett static const char * 979bd2bfb58SJuli Mallett handledash(char *buffer, char *end, const char *src) 980acc9d408SJuli Mallett { 981acc9d408SJuli Mallett char *p; 982acc9d408SJuli Mallett 983acc9d408SJuli Mallett p = buffer; 984acc9d408SJuli Mallett while(*src) { 985acc9d408SJuli Mallett if (src[1] == '-' && src[2]) { 986acc9d408SJuli Mallett unsigned char i; 987a841e1ebSBaptiste Daroussin if ((unsigned char)src[0] <= (unsigned char)src[2]) { 988acc9d408SJuli Mallett for (i = (unsigned char)src[0]; 989acc9d408SJuli Mallett i <= (unsigned char)src[2]; i++) { 990acc9d408SJuli Mallett *p++ = i; 991acc9d408SJuli Mallett if (p == end) { 992acc9d408SJuli Mallett *p = '\0'; 993acc9d408SJuli Mallett return buffer; 994acc9d408SJuli Mallett } 995acc9d408SJuli Mallett } 996a841e1ebSBaptiste Daroussin } else { 997a841e1ebSBaptiste Daroussin for (i = (unsigned char)src[0]; 998a841e1ebSBaptiste Daroussin i >= (unsigned char)src[2]; i--) { 999a841e1ebSBaptiste Daroussin *p++ = i; 1000a841e1ebSBaptiste Daroussin if (p == end) { 1001a841e1ebSBaptiste Daroussin *p = '\0'; 1002a841e1ebSBaptiste Daroussin return buffer; 1003a841e1ebSBaptiste Daroussin } 1004a841e1ebSBaptiste Daroussin } 1005a841e1ebSBaptiste Daroussin } 1006acc9d408SJuli Mallett src += 3; 1007acc9d408SJuli Mallett } else 1008acc9d408SJuli Mallett *p++ = *src++; 1009acc9d408SJuli Mallett if (p == end) 1010acc9d408SJuli Mallett break; 1011acc9d408SJuli Mallett } 1012acc9d408SJuli Mallett *p = '\0'; 1013acc9d408SJuli Mallett return buffer; 1014acc9d408SJuli Mallett } 1015