1*e0f4e041SBaptiste Daroussin /* $OpenBSD: eval.c,v 1.76 2017/10/23 15:21:19 espie Exp $ */ 2acc9d408SJuli Mallett /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */ 3acc9d408SJuli Mallett 48a16b7a1SPedro F. Giffuni /*- 58a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 68a16b7a1SPedro F. Giffuni * 79b50d902SRodney W. Grimes * Copyright (c) 1989, 1993 89b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 99b50d902SRodney W. Grimes * 109b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by 119b50d902SRodney W. Grimes * Ozan Yigit at York University. 129b50d902SRodney W. Grimes * 139b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 149b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 159b50d902SRodney W. Grimes * are met: 169b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 179b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 189b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 199b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 209b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 21a841e1ebSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors 229b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 239b50d902SRodney W. Grimes * without specific prior written permission. 249b50d902SRodney W. Grimes * 259b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 269b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 279b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 289b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 299b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 309b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 319b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 329b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 339b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 349b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 359b50d902SRodney W. Grimes * SUCH DAMAGE. 369b50d902SRodney W. Grimes */ 379b50d902SRodney W. Grimes 38acc9d408SJuli Mallett #include <sys/cdefs.h> 39acc9d408SJuli Mallett __FBSDID("$FreeBSD$"); 409b50d902SRodney W. Grimes 41a841e1ebSBaptiste Daroussin 429b50d902SRodney W. Grimes /* 439b50d902SRodney W. Grimes * eval.c 449b50d902SRodney W. Grimes * Facility: m4 macro processor 459b50d902SRodney W. Grimes * by: oz 469b50d902SRodney W. Grimes */ 479b50d902SRodney W. Grimes 489b50d902SRodney W. Grimes #include <sys/types.h> 49a841e1ebSBaptiste Daroussin #include <err.h> 50acc9d408SJuli Mallett #include <errno.h> 51a841e1ebSBaptiste Daroussin #include <limits.h> 52acc9d408SJuli Mallett #include <unistd.h> 539b50d902SRodney W. Grimes #include <stdio.h> 5446ef9581SBaptiste Daroussin #include <stdint.h> 559b50d902SRodney W. Grimes #include <stdlib.h> 56acc9d408SJuli Mallett #include <stddef.h> 579b50d902SRodney W. Grimes #include <string.h> 58acc9d408SJuli Mallett #include <fcntl.h> 599b50d902SRodney W. Grimes #include "mdef.h" 609b50d902SRodney W. Grimes #include "stdd.h" 619b50d902SRodney W. Grimes #include "extern.h" 629b50d902SRodney W. Grimes #include "pathnames.h" 639b50d902SRodney W. Grimes 64acc9d408SJuli Mallett static void dodefn(const char *); 65acc9d408SJuli Mallett static void dopushdef(const char *, const char *); 66acc9d408SJuli Mallett static void dodump(const char *[], int); 67acc9d408SJuli Mallett static void dotrace(const char *[], int, int); 68acc9d408SJuli Mallett static void doifelse(const char *[], int); 69acc9d408SJuli Mallett static int doincl(const char *); 70acc9d408SJuli Mallett static int dopaste(const char *); 71acc9d408SJuli Mallett static void dochq(const char *[], int); 72acc9d408SJuli Mallett static void dochc(const char *[], int); 73a841e1ebSBaptiste Daroussin static void dom4wrap(const char *); 74acc9d408SJuli Mallett static void dodiv(int); 75acc9d408SJuli Mallett static void doundiv(const char *[], int); 76acc9d408SJuli Mallett static void dosub(const char *[], int); 77acc9d408SJuli Mallett static void map(char *, const char *, const char *, const char *); 78acc9d408SJuli Mallett static const char *handledash(char *, char *, const char *); 79acc9d408SJuli Mallett static void expand_builtin(const char *[], int, int); 80acc9d408SJuli Mallett static void expand_macro(const char *[], int); 81a841e1ebSBaptiste Daroussin static void dump_one_def(const char *, struct macro_definition *); 82acc9d408SJuli Mallett 83acc9d408SJuli Mallett unsigned long expansion_id; 84acc9d408SJuli Mallett 859b50d902SRodney W. Grimes /* 86acc9d408SJuli Mallett * eval - eval all macros and builtins calls 879b50d902SRodney W. Grimes * argc - number of elements in argv. 889b50d902SRodney W. Grimes * argv - element vector : 899b50d902SRodney W. Grimes * argv[0] = definition of a user 90a841e1ebSBaptiste Daroussin * macro or NULL if built-in. 919b50d902SRodney W. Grimes * argv[1] = name of the macro or 929b50d902SRodney W. Grimes * built-in. 939b50d902SRodney W. Grimes * argv[2] = parameters to user-defined 949b50d902SRodney W. Grimes * . macro or built-in. 959b50d902SRodney W. Grimes * . 969b50d902SRodney W. Grimes * 97acc9d408SJuli Mallett * A call in the form of macro-or-builtin() will result in: 989b50d902SRodney W. Grimes * argv[0] = nullstr 999b50d902SRodney W. Grimes * argv[1] = macro-or-builtin 1009b50d902SRodney W. Grimes * argv[2] = nullstr 101acc9d408SJuli Mallett * 102acc9d408SJuli Mallett * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin 1039b50d902SRodney W. Grimes */ 1049b50d902SRodney W. Grimes void 105a841e1ebSBaptiste Daroussin eval(const char *argv[], int argc, int td, int is_traced) 1069b50d902SRodney W. Grimes { 107a841e1ebSBaptiste Daroussin size_t mark = SIZE_MAX; 108acc9d408SJuli Mallett 109acc9d408SJuli Mallett expansion_id++; 110acc9d408SJuli Mallett if (td & RECDEF) 111a841e1ebSBaptiste Daroussin m4errx(1, "expanding recursive definition for %s.", argv[1]); 112a841e1ebSBaptiste Daroussin if (is_traced) 113acc9d408SJuli Mallett mark = trace(argv, argc, infile+ilevel); 114acc9d408SJuli Mallett if (td == MACRTYPE) 115acc9d408SJuli Mallett expand_macro(argv, argc); 116acc9d408SJuli Mallett else 117acc9d408SJuli Mallett expand_builtin(argv, argc, td); 118a841e1ebSBaptiste Daroussin if (mark != SIZE_MAX) 119acc9d408SJuli Mallett finish_trace(mark); 120acc9d408SJuli Mallett } 121acc9d408SJuli Mallett 122acc9d408SJuli Mallett /* 123acc9d408SJuli Mallett * expand_builtin - evaluate built-in macros. 124acc9d408SJuli Mallett */ 125acc9d408SJuli Mallett void 126bd2bfb58SJuli Mallett expand_builtin(const char *argv[], int argc, int td) 127acc9d408SJuli Mallett { 128acc9d408SJuli Mallett int c, n; 129acc9d408SJuli Mallett int ac; 1309b50d902SRodney W. Grimes static int sysval = 0; 1319b50d902SRodney W. Grimes 1329b50d902SRodney W. Grimes #ifdef DEBUG 1339b50d902SRodney W. Grimes printf("argc = %d\n", argc); 1349b50d902SRodney W. Grimes for (n = 0; n < argc; n++) 1359b50d902SRodney W. Grimes printf("argv[%d] = %s\n", n, argv[n]); 136acc9d408SJuli Mallett fflush(stdout); 1379b50d902SRodney W. Grimes #endif 138acc9d408SJuli Mallett 1399b50d902SRodney W. Grimes /* 1409b50d902SRodney W. Grimes * if argc == 3 and argv[2] is null, then we 1419b50d902SRodney W. Grimes * have macro-or-builtin() type call. We adjust 1429b50d902SRodney W. Grimes * argc to avoid further checking.. 1439b50d902SRodney W. Grimes */ 144a841e1ebSBaptiste Daroussin /* we keep the initial value for those built-ins that differentiate 145a841e1ebSBaptiste Daroussin * between builtin() and builtin. 146a841e1ebSBaptiste Daroussin */ 147acc9d408SJuli Mallett ac = argc; 148acc9d408SJuli Mallett 149a841e1ebSBaptiste Daroussin if (argc == 3 && !*(argv[2]) && !mimic_gnu) 1509b50d902SRodney W. Grimes argc--; 1519b50d902SRodney W. Grimes 152acc9d408SJuli Mallett switch (td & TYPEMASK) { 1539b50d902SRodney W. Grimes 1549b50d902SRodney W. Grimes case DEFITYPE: 1559b50d902SRodney W. Grimes if (argc > 2) 1569b50d902SRodney W. Grimes dodefine(argv[2], (argc > 3) ? argv[3] : null); 1579b50d902SRodney W. Grimes break; 1589b50d902SRodney W. Grimes 1599b50d902SRodney W. Grimes case PUSDTYPE: 1609b50d902SRodney W. Grimes if (argc > 2) 1619b50d902SRodney W. Grimes dopushdef(argv[2], (argc > 3) ? argv[3] : null); 1629b50d902SRodney W. Grimes break; 1639b50d902SRodney W. Grimes 1649b50d902SRodney W. Grimes case DUMPTYPE: 1659b50d902SRodney W. Grimes dodump(argv, argc); 1669b50d902SRodney W. Grimes break; 1679b50d902SRodney W. Grimes 168acc9d408SJuli Mallett case TRACEONTYPE: 169acc9d408SJuli Mallett dotrace(argv, argc, 1); 170acc9d408SJuli Mallett break; 171acc9d408SJuli Mallett 172acc9d408SJuli Mallett case TRACEOFFTYPE: 173acc9d408SJuli Mallett dotrace(argv, argc, 0); 174acc9d408SJuli Mallett break; 175acc9d408SJuli Mallett 1769b50d902SRodney W. Grimes case EXPRTYPE: 1779b50d902SRodney W. Grimes /* 1789b50d902SRodney W. Grimes * doexpr - evaluate arithmetic 1799b50d902SRodney W. Grimes * expression 1809b50d902SRodney W. Grimes */ 181a841e1ebSBaptiste Daroussin { 182a841e1ebSBaptiste Daroussin int base = 10; 183a841e1ebSBaptiste Daroussin int maxdigits = 0; 184a841e1ebSBaptiste Daroussin const char *errstr; 185a841e1ebSBaptiste Daroussin 186a841e1ebSBaptiste Daroussin if (argc > 3) { 187a841e1ebSBaptiste Daroussin base = strtonum(argv[3], 2, 36, &errstr); 188a841e1ebSBaptiste Daroussin if (errstr) { 189a841e1ebSBaptiste Daroussin m4errx(1, "expr: base %s invalid.", argv[3]); 190a841e1ebSBaptiste Daroussin } 191a841e1ebSBaptiste Daroussin } 192a841e1ebSBaptiste Daroussin if (argc > 4) { 193a841e1ebSBaptiste Daroussin maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr); 194a841e1ebSBaptiste Daroussin if (errstr) { 195a841e1ebSBaptiste Daroussin m4errx(1, "expr: maxdigits %s invalid.", argv[4]); 196a841e1ebSBaptiste Daroussin } 197a841e1ebSBaptiste Daroussin } 1989b50d902SRodney W. Grimes if (argc > 2) 199a841e1ebSBaptiste Daroussin pbnumbase(expr(argv[2]), base, maxdigits); 2009b50d902SRodney W. Grimes break; 201a841e1ebSBaptiste Daroussin } 2029b50d902SRodney W. Grimes 2039b50d902SRodney W. Grimes case IFELTYPE: 2049b50d902SRodney W. Grimes doifelse(argv, argc); 2059b50d902SRodney W. Grimes break; 2069b50d902SRodney W. Grimes 2079b50d902SRodney W. Grimes case IFDFTYPE: 2089b50d902SRodney W. Grimes /* 2099b50d902SRodney W. Grimes * doifdef - select one of two 2109b50d902SRodney W. Grimes * alternatives based on the existence of 2119b50d902SRodney W. Grimes * another definition 2129b50d902SRodney W. Grimes */ 2139b50d902SRodney W. Grimes if (argc > 3) { 214a841e1ebSBaptiste Daroussin if (lookup_macro_definition(argv[2]) != NULL) 2159b50d902SRodney W. Grimes pbstr(argv[3]); 2169b50d902SRodney W. Grimes else if (argc > 4) 2179b50d902SRodney W. Grimes pbstr(argv[4]); 2189b50d902SRodney W. Grimes } 2199b50d902SRodney W. Grimes break; 2209b50d902SRodney W. Grimes 2219b50d902SRodney W. Grimes case LENGTYPE: 2229b50d902SRodney W. Grimes /* 2239b50d902SRodney W. Grimes * dolen - find the length of the 2249b50d902SRodney W. Grimes * argument 2259b50d902SRodney W. Grimes */ 2269b50d902SRodney W. Grimes pbnum((argc > 2) ? strlen(argv[2]) : 0); 2279b50d902SRodney W. Grimes break; 2289b50d902SRodney W. Grimes 2299b50d902SRodney W. Grimes case INCRTYPE: 2309b50d902SRodney W. Grimes /* 2319b50d902SRodney W. Grimes * doincr - increment the value of the 2329b50d902SRodney W. Grimes * argument 2339b50d902SRodney W. Grimes */ 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 DECRTYPE: 2399b50d902SRodney W. Grimes /* 2409b50d902SRodney W. Grimes * dodecr - decrement the value of the 2419b50d902SRodney W. Grimes * argument 2429b50d902SRodney W. Grimes */ 2439b50d902SRodney W. Grimes if (argc > 2) 2449b50d902SRodney W. Grimes pbnum(atoi(argv[2]) - 1); 2459b50d902SRodney W. Grimes break; 2469b50d902SRodney W. Grimes 2479b50d902SRodney W. Grimes case SYSCTYPE: 2489b50d902SRodney W. Grimes /* 2499b50d902SRodney W. Grimes * dosys - execute system command 2509b50d902SRodney W. Grimes */ 251aef4bb33STim J. Robbins if (argc > 2) { 252a841e1ebSBaptiste Daroussin fflush(stdout); 2539b50d902SRodney W. Grimes sysval = system(argv[2]); 254aef4bb33STim J. Robbins } 2559b50d902SRodney W. Grimes break; 2569b50d902SRodney W. Grimes 2579b50d902SRodney W. Grimes case SYSVTYPE: 2589b50d902SRodney W. Grimes /* 2599b50d902SRodney W. Grimes * dosysval - return value of the last 2609b50d902SRodney W. Grimes * system call. 2619b50d902SRodney W. Grimes * 2629b50d902SRodney W. Grimes */ 2639b50d902SRodney W. Grimes pbnum(sysval); 2649b50d902SRodney W. Grimes break; 2659b50d902SRodney W. Grimes 266acc9d408SJuli Mallett case ESYSCMDTYPE: 267acc9d408SJuli Mallett if (argc > 2) 268acc9d408SJuli Mallett doesyscmd(argv[2]); 269acc9d408SJuli Mallett break; 2709b50d902SRodney W. Grimes case INCLTYPE: 27188497f0cSBaptiste Daroussin if (argc > 2) { 2722cce1b69SBjoern A. Zeeb if (!doincl(argv[2])) { 273fb3f3d7cSBaptiste Daroussin if (mimic_gnu) { 2744fff7a14SBaptiste Daroussin warn("%s at line %lu: include(%s)", 2754fff7a14SBaptiste Daroussin CURRENT_NAME, CURRENT_LINE, argv[2]); 276fb3f3d7cSBaptiste Daroussin exit_code = 1; 277c560b67cSBaptiste Daroussin if (fatal_warns) { 278c560b67cSBaptiste Daroussin killdiv(); 279c560b67cSBaptiste Daroussin exit(exit_code); 280c560b67cSBaptiste Daroussin } 281fb3f3d7cSBaptiste Daroussin } else 282acc9d408SJuli Mallett err(1, "%s at line %lu: include(%s)", 283acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 2842cce1b69SBjoern A. Zeeb } 28588497f0cSBaptiste Daroussin } 2869b50d902SRodney W. Grimes break; 2879b50d902SRodney W. Grimes 2889b50d902SRodney W. Grimes case SINCTYPE: 2899b50d902SRodney W. Grimes if (argc > 2) 2909b50d902SRodney W. Grimes (void) doincl(argv[2]); 2919b50d902SRodney W. Grimes break; 2929b50d902SRodney W. Grimes #ifdef EXTENDED 2939b50d902SRodney W. Grimes case PASTTYPE: 2949b50d902SRodney W. Grimes if (argc > 2) 2959b50d902SRodney W. Grimes if (!dopaste(argv[2])) 296acc9d408SJuli Mallett err(1, "%s at line %lu: paste(%s)", 297acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 2989b50d902SRodney W. Grimes break; 2999b50d902SRodney W. Grimes 3009b50d902SRodney W. Grimes case SPASTYPE: 3019b50d902SRodney W. Grimes if (argc > 2) 3029b50d902SRodney W. Grimes (void) dopaste(argv[2]); 3039b50d902SRodney W. Grimes break; 304a841e1ebSBaptiste Daroussin case FORMATTYPE: 305a841e1ebSBaptiste Daroussin doformat(argv, argc); 306a841e1ebSBaptiste Daroussin break; 3079b50d902SRodney W. Grimes #endif 3089b50d902SRodney W. Grimes case CHNQTYPE: 309a841e1ebSBaptiste Daroussin dochq(argv, ac); 3109b50d902SRodney W. Grimes break; 3119b50d902SRodney W. Grimes 3129b50d902SRodney W. Grimes case CHNCTYPE: 3139b50d902SRodney W. Grimes dochc(argv, argc); 3149b50d902SRodney W. Grimes break; 3159b50d902SRodney W. Grimes 3169b50d902SRodney W. Grimes case SUBSTYPE: 3179b50d902SRodney W. Grimes /* 3189b50d902SRodney W. Grimes * dosub - select substring 3199b50d902SRodney W. Grimes * 3209b50d902SRodney W. Grimes */ 3219b50d902SRodney W. Grimes if (argc > 3) 3229b50d902SRodney W. Grimes dosub(argv, argc); 3239b50d902SRodney W. Grimes break; 3249b50d902SRodney W. Grimes 3259b50d902SRodney W. Grimes case SHIFTYPE: 3269b50d902SRodney W. Grimes /* 3279b50d902SRodney W. Grimes * doshift - push back all arguments 3289b50d902SRodney W. Grimes * except the first one (i.e. skip 3299b50d902SRodney W. Grimes * argv[2]) 3309b50d902SRodney W. Grimes */ 3319b50d902SRodney W. Grimes if (argc > 3) { 3329b50d902SRodney W. Grimes for (n = argc - 1; n > 3; n--) { 333acc9d408SJuli Mallett pbstr(rquote); 3349b50d902SRodney W. Grimes pbstr(argv[n]); 335acc9d408SJuli Mallett pbstr(lquote); 336a841e1ebSBaptiste Daroussin pushback(COMMA); 3379b50d902SRodney W. Grimes } 338acc9d408SJuli Mallett pbstr(rquote); 3399b50d902SRodney W. Grimes pbstr(argv[3]); 340acc9d408SJuli Mallett pbstr(lquote); 3419b50d902SRodney W. Grimes } 3429b50d902SRodney W. Grimes break; 3439b50d902SRodney W. Grimes 3449b50d902SRodney W. Grimes case DIVRTYPE: 3459b50d902SRodney W. Grimes if (argc > 2 && (n = atoi(argv[2])) != 0) 3469b50d902SRodney W. Grimes dodiv(n); 3479b50d902SRodney W. Grimes else { 3489b50d902SRodney W. Grimes active = stdout; 3499b50d902SRodney W. Grimes oindex = 0; 3509b50d902SRodney W. Grimes } 3519b50d902SRodney W. Grimes break; 3529b50d902SRodney W. Grimes 3539b50d902SRodney W. Grimes case UNDVTYPE: 3549b50d902SRodney W. Grimes doundiv(argv, argc); 3559b50d902SRodney W. Grimes break; 3569b50d902SRodney W. Grimes 3579b50d902SRodney W. Grimes case DIVNTYPE: 3589b50d902SRodney W. Grimes /* 3599b50d902SRodney W. Grimes * dodivnum - return the number of 3609b50d902SRodney W. Grimes * current output diversion 3619b50d902SRodney W. Grimes */ 3629b50d902SRodney W. Grimes pbnum(oindex); 3639b50d902SRodney W. Grimes break; 3649b50d902SRodney W. Grimes 3659b50d902SRodney W. Grimes case UNDFTYPE: 3669b50d902SRodney W. Grimes /* 3679b50d902SRodney W. Grimes * doundefine - undefine a previously 3689b50d902SRodney W. Grimes * defined macro(s) or m4 keyword(s). 3699b50d902SRodney W. Grimes */ 3709b50d902SRodney W. Grimes if (argc > 2) 3719b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 372a841e1ebSBaptiste Daroussin macro_undefine(argv[n]); 3739b50d902SRodney W. Grimes break; 3749b50d902SRodney W. Grimes 3759b50d902SRodney W. Grimes case POPDTYPE: 3769b50d902SRodney W. Grimes /* 3779b50d902SRodney W. Grimes * dopopdef - remove the topmost 3789b50d902SRodney W. Grimes * definitions of macro(s) or m4 3799b50d902SRodney W. Grimes * keyword(s). 3809b50d902SRodney W. Grimes */ 3819b50d902SRodney W. Grimes if (argc > 2) 3829b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 383a841e1ebSBaptiste Daroussin macro_popdef(argv[n]); 3849b50d902SRodney W. Grimes break; 3859b50d902SRodney W. Grimes 3869b50d902SRodney W. Grimes case MKTMTYPE: 3879b50d902SRodney W. Grimes /* 3889b50d902SRodney W. Grimes * dotemp - create a temporary file 3899b50d902SRodney W. Grimes */ 390acc9d408SJuli Mallett if (argc > 2) { 391acc9d408SJuli Mallett int fd; 392acc9d408SJuli Mallett char *temp; 393acc9d408SJuli Mallett 394acc9d408SJuli Mallett temp = xstrdup(argv[2]); 395acc9d408SJuli Mallett 396acc9d408SJuli Mallett fd = mkstemp(temp); 397acc9d408SJuli Mallett if (fd == -1) 398acc9d408SJuli Mallett err(1, 399acc9d408SJuli Mallett "%s at line %lu: couldn't make temp file %s", 400acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 401acc9d408SJuli Mallett close(fd); 402acc9d408SJuli Mallett pbstr(temp); 403acc9d408SJuli Mallett free(temp); 404acc9d408SJuli Mallett } 4059b50d902SRodney W. Grimes break; 4069b50d902SRodney W. Grimes 4079b50d902SRodney W. Grimes case TRNLTYPE: 4089b50d902SRodney W. Grimes /* 4099b50d902SRodney W. Grimes * dotranslit - replace all characters in 4109b50d902SRodney W. Grimes * the source string that appears in the 4119b50d902SRodney W. Grimes * "from" string with the corresponding 4129b50d902SRodney W. Grimes * characters in the "to" string. 4139b50d902SRodney W. Grimes */ 4149b50d902SRodney W. Grimes if (argc > 3) { 415acc9d408SJuli Mallett char *temp; 416acc9d408SJuli Mallett 417a841e1ebSBaptiste Daroussin temp = xalloc(strlen(argv[2])+1, NULL); 4189b50d902SRodney W. Grimes if (argc > 4) 4199b50d902SRodney W. Grimes map(temp, argv[2], argv[3], argv[4]); 4209b50d902SRodney W. Grimes else 4219b50d902SRodney W. Grimes map(temp, argv[2], argv[3], null); 4229b50d902SRodney W. Grimes pbstr(temp); 423acc9d408SJuli Mallett free(temp); 424acc9d408SJuli Mallett } else if (argc > 2) 4259b50d902SRodney W. Grimes pbstr(argv[2]); 4269b50d902SRodney W. Grimes break; 4279b50d902SRodney W. Grimes 4289b50d902SRodney W. Grimes case INDXTYPE: 4299b50d902SRodney W. Grimes /* 4309b50d902SRodney W. Grimes * doindex - find the index of the second 4319b50d902SRodney W. Grimes * argument string in the first argument 4329b50d902SRodney W. Grimes * string. -1 if not present. 4339b50d902SRodney W. Grimes */ 4349b50d902SRodney W. Grimes pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 4359b50d902SRodney W. Grimes break; 4369b50d902SRodney W. Grimes 4379b50d902SRodney W. Grimes case ERRPTYPE: 4389b50d902SRodney W. Grimes /* 4399b50d902SRodney W. Grimes * doerrp - print the arguments to stderr 4409b50d902SRodney W. Grimes * file 4419b50d902SRodney W. Grimes */ 4429b50d902SRodney W. Grimes if (argc > 2) { 4439b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 4449b50d902SRodney W. Grimes fprintf(stderr, "%s ", argv[n]); 4459b50d902SRodney W. Grimes fprintf(stderr, "\n"); 4469b50d902SRodney W. Grimes } 4479b50d902SRodney W. Grimes break; 4489b50d902SRodney W. Grimes 4499b50d902SRodney W. Grimes case DNLNTYPE: 4509b50d902SRodney W. Grimes /* 4519b50d902SRodney W. Grimes * dodnl - eat-up-to and including 4529b50d902SRodney W. Grimes * newline 4539b50d902SRodney W. Grimes */ 4549b50d902SRodney W. Grimes while ((c = gpbc()) != '\n' && c != EOF) 4559b50d902SRodney W. Grimes ; 4569b50d902SRodney W. Grimes break; 4579b50d902SRodney W. Grimes 4589b50d902SRodney W. Grimes case M4WRTYPE: 4599b50d902SRodney W. Grimes /* 4609b50d902SRodney W. Grimes * dom4wrap - set up for 4619b50d902SRodney W. Grimes * wrap-up/wind-down activity 4629b50d902SRodney W. Grimes */ 463a841e1ebSBaptiste Daroussin if (argc > 2) 464a841e1ebSBaptiste Daroussin dom4wrap(argv[2]); 4659b50d902SRodney W. Grimes break; 4669b50d902SRodney W. Grimes 4679b50d902SRodney W. Grimes case EXITTYPE: 4689b50d902SRodney W. Grimes /* 4699b50d902SRodney W. Grimes * doexit - immediate exit from m4. 4709b50d902SRodney W. Grimes */ 471cac6992aSAndrey A. Chernov killdiv(); 4729b50d902SRodney W. Grimes exit((argc > 2) ? atoi(argv[2]) : 0); 4739b50d902SRodney W. Grimes break; 4749b50d902SRodney W. Grimes 4759b50d902SRodney W. Grimes case DEFNTYPE: 4769b50d902SRodney W. Grimes if (argc > 2) 4779b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 4789b50d902SRodney W. Grimes dodefn(argv[n]); 4799b50d902SRodney W. Grimes break; 4809b50d902SRodney W. Grimes 481acc9d408SJuli Mallett case INDIRTYPE: /* Indirect call */ 482acc9d408SJuli Mallett if (argc > 2) 483acc9d408SJuli Mallett doindir(argv, argc); 484bbfd1447SSteve Price break; 485bbfd1447SSteve Price 486acc9d408SJuli Mallett case BUILTINTYPE: /* Builtins only */ 487acc9d408SJuli Mallett if (argc > 2) 488acc9d408SJuli Mallett dobuiltin(argv, argc); 489acc9d408SJuli Mallett break; 490acc9d408SJuli Mallett 491acc9d408SJuli Mallett case PATSTYPE: 492acc9d408SJuli Mallett if (argc > 2) 493acc9d408SJuli Mallett dopatsubst(argv, argc); 494acc9d408SJuli Mallett break; 495acc9d408SJuli Mallett case REGEXPTYPE: 496acc9d408SJuli Mallett if (argc > 2) 497acc9d408SJuli Mallett doregexp(argv, argc); 498acc9d408SJuli Mallett break; 499acc9d408SJuli Mallett case LINETYPE: 500acc9d408SJuli Mallett doprintlineno(infile+ilevel); 501acc9d408SJuli Mallett break; 502acc9d408SJuli Mallett case FILENAMETYPE: 503acc9d408SJuli Mallett doprintfilename(infile+ilevel); 504acc9d408SJuli Mallett break; 505acc9d408SJuli Mallett case SELFTYPE: 506acc9d408SJuli Mallett pbstr(rquote); 507acc9d408SJuli Mallett pbstr(argv[1]); 508acc9d408SJuli Mallett pbstr(lquote); 509acc9d408SJuli Mallett break; 5109b50d902SRodney W. Grimes default: 511a841e1ebSBaptiste Daroussin m4errx(1, "eval: major botch."); 5129b50d902SRodney W. Grimes break; 5139b50d902SRodney W. Grimes } 5149b50d902SRodney W. Grimes } 5159b50d902SRodney W. Grimes 5169b50d902SRodney W. Grimes /* 517acc9d408SJuli Mallett * expand_macro - user-defined macro expansion 5189b50d902SRodney W. Grimes */ 5199b50d902SRodney W. Grimes void 520bd2bfb58SJuli Mallett expand_macro(const char *argv[], int argc) 5219b50d902SRodney W. Grimes { 522acc9d408SJuli Mallett const char *t; 523acc9d408SJuli Mallett const char *p; 524acc9d408SJuli Mallett int n; 525acc9d408SJuli Mallett int argno; 5269b50d902SRodney W. Grimes 5279b50d902SRodney W. Grimes t = argv[0]; /* defn string as a whole */ 5289b50d902SRodney W. Grimes p = t; 5299b50d902SRodney W. Grimes while (*p) 5309b50d902SRodney W. Grimes p++; 5319b50d902SRodney W. Grimes p--; /* last character of defn */ 5329b50d902SRodney W. Grimes while (p > t) { 5339b50d902SRodney W. Grimes if (*(p - 1) != ARGFLAG) 534a841e1ebSBaptiste Daroussin PUSHBACK(*p); 5359b50d902SRodney W. Grimes else { 5369b50d902SRodney W. Grimes switch (*p) { 5379b50d902SRodney W. Grimes 5389b50d902SRodney W. Grimes case '#': 5399b50d902SRodney W. Grimes pbnum(argc - 2); 5409b50d902SRodney W. Grimes break; 5419b50d902SRodney W. Grimes case '0': 5429b50d902SRodney W. Grimes case '1': 5439b50d902SRodney W. Grimes case '2': 5449b50d902SRodney W. Grimes case '3': 5459b50d902SRodney W. Grimes case '4': 5469b50d902SRodney W. Grimes case '5': 5479b50d902SRodney W. Grimes case '6': 5489b50d902SRodney W. Grimes case '7': 5499b50d902SRodney W. Grimes case '8': 5509b50d902SRodney W. Grimes case '9': 5519b50d902SRodney W. Grimes if ((argno = *p - '0') < argc - 1) 5529b50d902SRodney W. Grimes pbstr(argv[argno + 1]); 5539b50d902SRodney W. Grimes break; 5549b50d902SRodney W. Grimes case '*': 555acc9d408SJuli Mallett if (argc > 2) { 5569b50d902SRodney W. Grimes for (n = argc - 1; n > 2; n--) { 5579b50d902SRodney W. Grimes pbstr(argv[n]); 558a841e1ebSBaptiste Daroussin pushback(COMMA); 5599b50d902SRodney W. Grimes } 5609b50d902SRodney W. Grimes pbstr(argv[2]); 561acc9d408SJuli Mallett } 5629b50d902SRodney W. Grimes break; 563232eaee6SJoerg Wunsch case '@': 564acc9d408SJuli Mallett if (argc > 2) { 565acc9d408SJuli Mallett for (n = argc - 1; n > 2; n--) { 566acc9d408SJuli Mallett pbstr(rquote); 567232eaee6SJoerg Wunsch pbstr(argv[n]); 568acc9d408SJuli Mallett pbstr(lquote); 569a841e1ebSBaptiste Daroussin pushback(COMMA); 570acc9d408SJuli Mallett } 571acc9d408SJuli Mallett pbstr(rquote); 572acc9d408SJuli Mallett pbstr(argv[2]); 573acc9d408SJuli Mallett pbstr(lquote); 574232eaee6SJoerg Wunsch } 575232eaee6SJoerg Wunsch break; 5769b50d902SRodney W. Grimes default: 577a841e1ebSBaptiste Daroussin PUSHBACK(*p); 578a841e1ebSBaptiste Daroussin PUSHBACK('$'); 5799b50d902SRodney W. Grimes break; 5809b50d902SRodney W. Grimes } 5819b50d902SRodney W. Grimes p--; 5829b50d902SRodney W. Grimes } 5839b50d902SRodney W. Grimes p--; 5849b50d902SRodney W. Grimes } 5859b50d902SRodney W. Grimes if (p == t) /* do last character */ 586a841e1ebSBaptiste Daroussin PUSHBACK(*p); 5879b50d902SRodney W. Grimes } 5889b50d902SRodney W. Grimes 589a841e1ebSBaptiste Daroussin 5909b50d902SRodney W. Grimes /* 5919b50d902SRodney W. Grimes * dodefine - install definition in the table 5929b50d902SRodney W. Grimes */ 5939b50d902SRodney W. Grimes void 594bd2bfb58SJuli Mallett dodefine(const char *name, const char *defn) 5959b50d902SRodney W. Grimes { 596a841e1ebSBaptiste Daroussin if (!*name && !mimic_gnu) 597a841e1ebSBaptiste Daroussin m4errx(1, "null definition."); 5989b50d902SRodney W. Grimes else 599a841e1ebSBaptiste Daroussin macro_define(name, defn); 6009b50d902SRodney W. Grimes } 6019b50d902SRodney W. Grimes 6029b50d902SRodney W. Grimes /* 6039b50d902SRodney W. Grimes * dodefn - push back a quoted definition of 6049b50d902SRodney W. Grimes * the given name. 6059b50d902SRodney W. Grimes */ 606acc9d408SJuli Mallett static void 607bd2bfb58SJuli Mallett dodefn(const char *name) 6089b50d902SRodney W. Grimes { 609a841e1ebSBaptiste Daroussin struct macro_definition *p; 6109b50d902SRodney W. Grimes 611a841e1ebSBaptiste Daroussin if ((p = lookup_macro_definition(name)) != NULL) { 612a841e1ebSBaptiste Daroussin if ((p->type & TYPEMASK) == MACRTYPE) { 613acc9d408SJuli Mallett pbstr(rquote); 6149b50d902SRodney W. Grimes pbstr(p->defn); 615acc9d408SJuli Mallett pbstr(lquote); 616a841e1ebSBaptiste Daroussin } else { 617a841e1ebSBaptiste Daroussin pbstr(p->defn); 618acc9d408SJuli Mallett pbstr(BUILTIN_MARKER); 619acc9d408SJuli Mallett } 6209b50d902SRodney W. Grimes } 6219b50d902SRodney W. Grimes } 6229b50d902SRodney W. Grimes 6239b50d902SRodney W. Grimes /* 6249b50d902SRodney W. Grimes * dopushdef - install a definition in the hash table 6259b50d902SRodney W. Grimes * without removing a previous definition. Since 6269b50d902SRodney W. Grimes * each new entry is entered in *front* of the 6279b50d902SRodney W. Grimes * hash bucket, it hides a previous definition from 6289b50d902SRodney W. Grimes * lookup. 6299b50d902SRodney W. Grimes */ 630acc9d408SJuli Mallett static void 631bd2bfb58SJuli Mallett dopushdef(const char *name, const char *defn) 6329b50d902SRodney W. Grimes { 633a841e1ebSBaptiste Daroussin if (!*name && !mimic_gnu) 634a841e1ebSBaptiste Daroussin m4errx(1, "null definition."); 6359b50d902SRodney W. Grimes else 636a841e1ebSBaptiste Daroussin macro_pushdef(name, defn); 637acc9d408SJuli Mallett } 638acc9d408SJuli Mallett 639acc9d408SJuli Mallett /* 640acc9d408SJuli Mallett * dump_one_def - dump the specified definition. 641acc9d408SJuli Mallett */ 642acc9d408SJuli Mallett static void 643a841e1ebSBaptiste Daroussin dump_one_def(const char *name, struct macro_definition *p) 644acc9d408SJuli Mallett { 645a841e1ebSBaptiste Daroussin if (!traceout) 646a841e1ebSBaptiste Daroussin traceout = stderr; 647acc9d408SJuli Mallett if (mimic_gnu) { 648acc9d408SJuli Mallett if ((p->type & TYPEMASK) == MACRTYPE) 649a841e1ebSBaptiste Daroussin fprintf(traceout, "%s:\t%s\n", name, p->defn); 650acc9d408SJuli Mallett else { 651a841e1ebSBaptiste Daroussin fprintf(traceout, "%s:\t<%s>\n", name, p->defn); 652acc9d408SJuli Mallett } 653acc9d408SJuli Mallett } else 654a841e1ebSBaptiste Daroussin fprintf(traceout, "`%s'\t`%s'\n", name, p->defn); 6559b50d902SRodney W. Grimes } 6569b50d902SRodney W. Grimes 6579b50d902SRodney W. Grimes /* 6589b50d902SRodney W. Grimes * dodumpdef - dump the specified definitions in the hash 6599b50d902SRodney W. Grimes * table to stderr. If nothing is specified, the entire 6609b50d902SRodney W. Grimes * hash table is dumped. 6619b50d902SRodney W. Grimes */ 662acc9d408SJuli Mallett static void 663bd2bfb58SJuli Mallett dodump(const char *argv[], int argc) 6649b50d902SRodney W. Grimes { 665acc9d408SJuli Mallett int n; 666a841e1ebSBaptiste Daroussin struct macro_definition *p; 6679b50d902SRodney W. Grimes 6689b50d902SRodney W. Grimes if (argc > 2) { 6699b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 670a841e1ebSBaptiste Daroussin if ((p = lookup_macro_definition(argv[n])) != NULL) 671a841e1ebSBaptiste Daroussin dump_one_def(argv[n], p); 672a841e1ebSBaptiste Daroussin } else 673a841e1ebSBaptiste Daroussin macro_for_all(dump_one_def); 6749b50d902SRodney W. Grimes } 6759b50d902SRodney W. Grimes 6769b50d902SRodney W. Grimes /* 677acc9d408SJuli Mallett * dotrace - mark some macros as traced/untraced depending upon on. 678acc9d408SJuli Mallett */ 679acc9d408SJuli Mallett static void 680bd2bfb58SJuli Mallett dotrace(const char *argv[], int argc, int on) 681acc9d408SJuli Mallett { 682acc9d408SJuli Mallett int n; 683acc9d408SJuli Mallett 684acc9d408SJuli Mallett if (argc > 2) { 685acc9d408SJuli Mallett for (n = 2; n < argc; n++) 686acc9d408SJuli Mallett mark_traced(argv[n], on); 687acc9d408SJuli Mallett } else 688acc9d408SJuli Mallett mark_traced(NULL, on); 689acc9d408SJuli Mallett } 690acc9d408SJuli Mallett 691acc9d408SJuli Mallett /* 6929b50d902SRodney W. Grimes * doifelse - select one of two alternatives - loop. 6939b50d902SRodney W. Grimes */ 694acc9d408SJuli Mallett static void 695bd2bfb58SJuli Mallett doifelse(const char *argv[], int argc) 6969b50d902SRodney W. Grimes { 697*e0f4e041SBaptiste Daroussin while (argc > 4) { 698*e0f4e041SBaptiste Daroussin if (STREQ(argv[2], argv[3])) { 6999b50d902SRodney W. Grimes pbstr(argv[4]); 700*e0f4e041SBaptiste Daroussin break; 701*e0f4e041SBaptiste Daroussin } else if (argc == 6) { 7029b50d902SRodney W. Grimes pbstr(argv[5]); 703*e0f4e041SBaptiste Daroussin break; 704*e0f4e041SBaptiste Daroussin } else { 7059b50d902SRodney W. Grimes argv += 3; 7069b50d902SRodney W. Grimes argc -= 3; 7079b50d902SRodney W. Grimes } 7089b50d902SRodney W. Grimes } 7099b50d902SRodney W. Grimes } 7109b50d902SRodney W. Grimes 7119b50d902SRodney W. Grimes /* 7129b50d902SRodney W. Grimes * doinclude - include a given file. 7139b50d902SRodney W. Grimes */ 714acc9d408SJuli Mallett static int 715bd2bfb58SJuli Mallett doincl(const char *ifile) 7169b50d902SRodney W. Grimes { 7179b50d902SRodney W. Grimes if (ilevel + 1 == MAXINP) 718a841e1ebSBaptiste Daroussin m4errx(1, "too many include files."); 719acc9d408SJuli Mallett if (fopen_trypath(infile+ilevel+1, ifile) != NULL) { 7209b50d902SRodney W. Grimes ilevel++; 7219b50d902SRodney W. Grimes bbase[ilevel] = bufbase = bp; 7229b50d902SRodney W. Grimes return (1); 723acc9d408SJuli Mallett } else 7249b50d902SRodney W. Grimes return (0); 7259b50d902SRodney W. Grimes } 7269b50d902SRodney W. Grimes 7279b50d902SRodney W. Grimes #ifdef EXTENDED 7289b50d902SRodney W. Grimes /* 7299b50d902SRodney W. Grimes * dopaste - include a given file without any 7309b50d902SRodney W. Grimes * macro processing. 7319b50d902SRodney W. Grimes */ 732acc9d408SJuli Mallett static int 733bd2bfb58SJuli Mallett dopaste(const char *pfile) 7349b50d902SRodney W. Grimes { 7359b50d902SRodney W. Grimes FILE *pf; 736acc9d408SJuli Mallett int c; 7379b50d902SRodney W. Grimes 7389b50d902SRodney W. Grimes if ((pf = fopen(pfile, "r")) != NULL) { 739a841e1ebSBaptiste Daroussin if (synch_lines) 740b1ea3d46SJuli Mallett fprintf(active, "#line 1 \"%s\"\n", pfile); 7419b50d902SRodney W. Grimes while ((c = getc(pf)) != EOF) 7429b50d902SRodney W. Grimes putc(c, active); 7439b50d902SRodney W. Grimes (void) fclose(pf); 744a841e1ebSBaptiste Daroussin emit_synchline(); 7459b50d902SRodney W. Grimes return (1); 746acc9d408SJuli Mallett } else 7479b50d902SRodney W. Grimes return (0); 7489b50d902SRodney W. Grimes } 7499b50d902SRodney W. Grimes #endif 7509b50d902SRodney W. Grimes 7519b50d902SRodney W. Grimes /* 752acc9d408SJuli Mallett * dochq - change quote characters 7539b50d902SRodney W. Grimes */ 754acc9d408SJuli Mallett static void 755a841e1ebSBaptiste Daroussin dochq(const char *argv[], int ac) 7569b50d902SRodney W. Grimes { 757a841e1ebSBaptiste Daroussin if (ac == 2) { 758a841e1ebSBaptiste Daroussin lquote[0] = LQUOTE; lquote[1] = EOS; 759a841e1ebSBaptiste Daroussin rquote[0] = RQUOTE; rquote[1] = EOS; 760acc9d408SJuli Mallett } else { 761a841e1ebSBaptiste Daroussin strlcpy(lquote, argv[2], sizeof(lquote)); 762a841e1ebSBaptiste Daroussin if (ac > 3) { 763a841e1ebSBaptiste Daroussin strlcpy(rquote, argv[3], sizeof(rquote)); 764a841e1ebSBaptiste Daroussin } else { 765a841e1ebSBaptiste Daroussin rquote[0] = ECOMMT; rquote[1] = EOS; 766a841e1ebSBaptiste Daroussin } 767acc9d408SJuli Mallett } 768acc9d408SJuli Mallett } 769acc9d408SJuli Mallett 770acc9d408SJuli Mallett /* 771acc9d408SJuli Mallett * dochc - change comment characters 772acc9d408SJuli Mallett */ 773acc9d408SJuli Mallett static void 774bd2bfb58SJuli Mallett dochc(const char *argv[], int argc) 775acc9d408SJuli Mallett { 776a841e1ebSBaptiste Daroussin /* XXX Note that there is no difference between no argument and a single 777a841e1ebSBaptiste Daroussin * empty argument. 778a841e1ebSBaptiste Daroussin */ 779a841e1ebSBaptiste Daroussin if (argc == 2) { 780a841e1ebSBaptiste Daroussin scommt[0] = EOS; 781a841e1ebSBaptiste Daroussin ecommt[0] = EOS; 782a841e1ebSBaptiste Daroussin } else { 783acc9d408SJuli Mallett strlcpy(scommt, argv[2], sizeof(scommt)); 784a841e1ebSBaptiste Daroussin if (argc == 3) { 785a841e1ebSBaptiste Daroussin ecommt[0] = ECOMMT; ecommt[1] = EOS; 786a841e1ebSBaptiste Daroussin } else { 787acc9d408SJuli Mallett strlcpy(ecommt, argv[3], sizeof(ecommt)); 7889b50d902SRodney W. Grimes } 789a841e1ebSBaptiste Daroussin } 790a841e1ebSBaptiste Daroussin } 791a841e1ebSBaptiste Daroussin 792a841e1ebSBaptiste Daroussin /* 793a841e1ebSBaptiste Daroussin * dom4wrap - expand text at EOF 794a841e1ebSBaptiste Daroussin */ 795a841e1ebSBaptiste Daroussin static void 796a841e1ebSBaptiste Daroussin dom4wrap(const char *text) 797a841e1ebSBaptiste Daroussin { 798a841e1ebSBaptiste Daroussin if (wrapindex >= maxwraps) { 799a841e1ebSBaptiste Daroussin if (maxwraps == 0) 800a841e1ebSBaptiste Daroussin maxwraps = 16; 8019b50d902SRodney W. Grimes else 802a841e1ebSBaptiste Daroussin maxwraps *= 2; 80388497f0cSBaptiste Daroussin m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps), 804a841e1ebSBaptiste Daroussin "too many m4wraps"); 8059b50d902SRodney W. Grimes } 806a841e1ebSBaptiste Daroussin m4wraps[wrapindex++] = xstrdup(text); 8079b50d902SRodney W. Grimes } 8089b50d902SRodney W. Grimes 8099b50d902SRodney W. Grimes /* 8109b50d902SRodney W. Grimes * dodivert - divert the output to a temporary file 8119b50d902SRodney W. Grimes */ 812acc9d408SJuli Mallett static void 813bd2bfb58SJuli Mallett dodiv(int n) 8149b50d902SRodney W. Grimes { 815acc9d408SJuli Mallett int fd; 816acc9d408SJuli Mallett 817ef2cea81SJonathan Lemon oindex = n; 818acc9d408SJuli Mallett if (n >= maxout) { 819acc9d408SJuli Mallett if (mimic_gnu) 820acc9d408SJuli Mallett resizedivs(n + 10); 821acc9d408SJuli Mallett else 822acc9d408SJuli Mallett n = 0; /* bitbucket */ 823acc9d408SJuli Mallett } 824acc9d408SJuli Mallett 825acc9d408SJuli Mallett if (n < 0) 8269b50d902SRodney W. Grimes n = 0; /* bitbucket */ 8279b50d902SRodney W. Grimes if (outfile[n] == NULL) { 828acc9d408SJuli Mallett char fname[] = _PATH_DIVNAME; 829acc9d408SJuli Mallett 830acc9d408SJuli Mallett if ((fd = mkstemp(fname)) < 0 || 83188497f0cSBaptiste Daroussin unlink(fname) == -1 || 832acc9d408SJuli Mallett (outfile[n] = fdopen(fd, "w+")) == NULL) 833acc9d408SJuli Mallett err(1, "%s: cannot divert", fname); 8349b50d902SRodney W. Grimes } 8359b50d902SRodney W. Grimes active = outfile[n]; 8369b50d902SRodney W. Grimes } 8379b50d902SRodney W. Grimes 8389b50d902SRodney W. Grimes /* 8399b50d902SRodney W. Grimes * doundivert - undivert a specified output, or all 8409b50d902SRodney W. Grimes * other outputs, in numerical order. 8419b50d902SRodney W. Grimes */ 842acc9d408SJuli Mallett static void 843bd2bfb58SJuli Mallett doundiv(const char *argv[], int argc) 8449b50d902SRodney W. Grimes { 845acc9d408SJuli Mallett int ind; 846acc9d408SJuli Mallett int n; 8479b50d902SRodney W. Grimes 8489b50d902SRodney W. Grimes if (argc > 2) { 8499b50d902SRodney W. Grimes for (ind = 2; ind < argc; ind++) { 850a841e1ebSBaptiste Daroussin const char *errstr; 851a841e1ebSBaptiste Daroussin n = strtonum(argv[ind], 1, INT_MAX, &errstr); 852a841e1ebSBaptiste Daroussin if (errstr) { 853a841e1ebSBaptiste Daroussin if (errno == EINVAL && mimic_gnu) 854a841e1ebSBaptiste Daroussin getdivfile(argv[ind]); 855a841e1ebSBaptiste Daroussin } else { 856a841e1ebSBaptiste Daroussin if (n < maxout && outfile[n] != NULL) 8579b50d902SRodney W. Grimes getdiv(n); 858a841e1ebSBaptiste Daroussin } 8599b50d902SRodney W. Grimes } 8609b50d902SRodney W. Grimes } 8619b50d902SRodney W. Grimes else 862acc9d408SJuli Mallett for (n = 1; n < maxout; n++) 8639b50d902SRodney W. Grimes if (outfile[n] != NULL) 8649b50d902SRodney W. Grimes getdiv(n); 8659b50d902SRodney W. Grimes } 8669b50d902SRodney W. Grimes 8679b50d902SRodney W. Grimes /* 8689b50d902SRodney W. Grimes * dosub - select substring 8699b50d902SRodney W. Grimes */ 870acc9d408SJuli Mallett static void 871bd2bfb58SJuli Mallett dosub(const char *argv[], int argc) 8729b50d902SRodney W. Grimes { 873acc9d408SJuli Mallett const char *ap, *fc, *k; 874acc9d408SJuli Mallett int nc; 8759b50d902SRodney W. Grimes 8769b50d902SRodney W. Grimes ap = argv[2]; /* target string */ 8779b50d902SRodney W. Grimes #ifdef EXPR 8789b50d902SRodney W. Grimes fc = ap + expr(argv[3]); /* first char */ 8799b50d902SRodney W. Grimes #else 8809b50d902SRodney W. Grimes fc = ap + atoi(argv[3]); /* first char */ 8819b50d902SRodney W. Grimes #endif 8824ba4d387SGregory Neil Shapiro nc = strlen(fc); 883acc9d408SJuli Mallett if (argc >= 5) 8844ba4d387SGregory Neil Shapiro #ifdef EXPR 885acc9d408SJuli Mallett nc = min(nc, expr(argv[4])); 8864ba4d387SGregory Neil Shapiro #else 887acc9d408SJuli Mallett nc = min(nc, atoi(argv[4])); 8884ba4d387SGregory Neil Shapiro #endif 8899b50d902SRodney W. Grimes if (fc >= ap && fc < ap + strlen(ap)) 8904ba4d387SGregory Neil Shapiro for (k = fc + nc - 1; k >= fc; k--) 891a841e1ebSBaptiste Daroussin pushback(*k); 8929b50d902SRodney W. Grimes } 8939b50d902SRodney W. Grimes 8949b50d902SRodney W. Grimes /* 8959b50d902SRodney W. Grimes * map: 8969b50d902SRodney W. Grimes * map every character of s1 that is specified in from 8979b50d902SRodney W. Grimes * into s3 and replace in s. (source s1 remains untouched) 8989b50d902SRodney W. Grimes * 899a841e1ebSBaptiste Daroussin * This is derived from the a standard implementation of map(s,from,to) 900a841e1ebSBaptiste Daroussin * function of ICON language. Within mapvec, we replace every character 901a841e1ebSBaptiste Daroussin * of "from" with the corresponding character in "to". 902a841e1ebSBaptiste Daroussin * If "to" is shorter than "from", than the corresponding entries are null, 903af7ca7c8SPedro F. Giffuni * which means that those characters disappear altogether. 9049b50d902SRodney W. Grimes */ 905acc9d408SJuli Mallett static void 906bd2bfb58SJuli Mallett map(char *dest, const char *src, const char *from, const char *to) 9079b50d902SRodney W. Grimes { 908acc9d408SJuli Mallett const char *tmp; 909acc9d408SJuli Mallett unsigned char sch, dch; 910acc9d408SJuli Mallett static char frombis[257]; 911acc9d408SJuli Mallett static char tobis[257]; 912a841e1ebSBaptiste Daroussin int i; 913a841e1ebSBaptiste Daroussin char seen[256]; 914acc9d408SJuli Mallett static unsigned char mapvec[256] = { 915acc9d408SJuli Mallett 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 916acc9d408SJuli Mallett 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 917acc9d408SJuli Mallett 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 918acc9d408SJuli Mallett 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 919acc9d408SJuli Mallett 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 920acc9d408SJuli Mallett 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 921acc9d408SJuli Mallett 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 922acc9d408SJuli Mallett 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 923acc9d408SJuli Mallett 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 924acc9d408SJuli Mallett 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 925acc9d408SJuli Mallett 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 926acc9d408SJuli Mallett 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 927acc9d408SJuli Mallett 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 928acc9d408SJuli Mallett 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 929acc9d408SJuli Mallett 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 930acc9d408SJuli Mallett 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 931acc9d408SJuli Mallett 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 932acc9d408SJuli Mallett 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 9339b50d902SRodney W. Grimes }; 9349b50d902SRodney W. Grimes 9359b50d902SRodney W. Grimes if (*src) { 936acc9d408SJuli Mallett if (mimic_gnu) { 937acc9d408SJuli Mallett /* 938acc9d408SJuli Mallett * expand character ranges on the fly 939acc9d408SJuli Mallett */ 940acc9d408SJuli Mallett from = handledash(frombis, frombis + 256, from); 941acc9d408SJuli Mallett to = handledash(tobis, tobis + 256, to); 942acc9d408SJuli Mallett } 9439b50d902SRodney W. Grimes tmp = from; 9449b50d902SRodney W. Grimes /* 9459b50d902SRodney W. Grimes * create a mapping between "from" and 9469b50d902SRodney W. Grimes * "to" 9479b50d902SRodney W. Grimes */ 948a841e1ebSBaptiste Daroussin for (i = 0; i < 256; i++) 949a841e1ebSBaptiste Daroussin seen[i] = 0; 950a841e1ebSBaptiste Daroussin while (*from) { 951a841e1ebSBaptiste Daroussin if (!seen[(unsigned char)(*from)]) { 952a841e1ebSBaptiste Daroussin mapvec[(unsigned char)(*from)] = (unsigned char)(*to); 953a841e1ebSBaptiste Daroussin seen[(unsigned char)(*from)] = 1; 954a841e1ebSBaptiste Daroussin } 955a841e1ebSBaptiste Daroussin from++; 956a841e1ebSBaptiste Daroussin if (*to) 957a841e1ebSBaptiste Daroussin to++; 958a841e1ebSBaptiste Daroussin } 9599b50d902SRodney W. Grimes 9609b50d902SRodney W. Grimes while (*src) { 961acc9d408SJuli Mallett sch = (unsigned char)(*src++); 9629b50d902SRodney W. Grimes dch = mapvec[sch]; 963acc9d408SJuli Mallett if ((*dest = (char)dch)) 9649b50d902SRodney W. Grimes dest++; 9659b50d902SRodney W. Grimes } 9669b50d902SRodney W. Grimes /* 9679b50d902SRodney W. Grimes * restore all the changed characters 9689b50d902SRodney W. Grimes */ 9699b50d902SRodney W. Grimes while (*tmp) { 970acc9d408SJuli Mallett mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp); 9719b50d902SRodney W. Grimes tmp++; 9729b50d902SRodney W. Grimes } 9739b50d902SRodney W. Grimes } 974acc9d408SJuli Mallett *dest = '\0'; 9759b50d902SRodney W. Grimes } 976acc9d408SJuli Mallett 977acc9d408SJuli Mallett 978acc9d408SJuli Mallett /* 979acc9d408SJuli Mallett * handledash: 980acc9d408SJuli Mallett * use buffer to copy the src string, expanding character ranges 981acc9d408SJuli Mallett * on the way. 982acc9d408SJuli Mallett */ 983acc9d408SJuli Mallett static const char * 984bd2bfb58SJuli Mallett handledash(char *buffer, char *end, const char *src) 985acc9d408SJuli Mallett { 986acc9d408SJuli Mallett char *p; 987acc9d408SJuli Mallett 988acc9d408SJuli Mallett p = buffer; 989acc9d408SJuli Mallett while(*src) { 990acc9d408SJuli Mallett if (src[1] == '-' && src[2]) { 991acc9d408SJuli Mallett unsigned char i; 992a841e1ebSBaptiste Daroussin if ((unsigned char)src[0] <= (unsigned char)src[2]) { 993acc9d408SJuli Mallett for (i = (unsigned char)src[0]; 994acc9d408SJuli Mallett i <= (unsigned char)src[2]; i++) { 995acc9d408SJuli Mallett *p++ = i; 996acc9d408SJuli Mallett if (p == end) { 997acc9d408SJuli Mallett *p = '\0'; 998acc9d408SJuli Mallett return buffer; 999acc9d408SJuli Mallett } 1000acc9d408SJuli Mallett } 1001a841e1ebSBaptiste Daroussin } else { 1002a841e1ebSBaptiste Daroussin for (i = (unsigned char)src[0]; 1003a841e1ebSBaptiste Daroussin i >= (unsigned char)src[2]; i--) { 1004a841e1ebSBaptiste Daroussin *p++ = i; 1005a841e1ebSBaptiste Daroussin if (p == end) { 1006a841e1ebSBaptiste Daroussin *p = '\0'; 1007a841e1ebSBaptiste Daroussin return buffer; 1008a841e1ebSBaptiste Daroussin } 1009a841e1ebSBaptiste Daroussin } 1010a841e1ebSBaptiste Daroussin } 1011acc9d408SJuli Mallett src += 3; 1012acc9d408SJuli Mallett } else 1013acc9d408SJuli Mallett *p++ = *src++; 1014acc9d408SJuli Mallett if (p == end) 1015acc9d408SJuli Mallett break; 1016acc9d408SJuli Mallett } 1017acc9d408SJuli Mallett *p = '\0'; 1018acc9d408SJuli Mallett return buffer; 1019acc9d408SJuli Mallett } 1020