1*c560b67cSBaptiste Daroussin /* $OpenBSD: eval.c,v 1.75 2017/06/15 13:48:42 bcallah 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 if (argc > 4) 2059b50d902SRodney W. Grimes doifelse(argv, argc); 2069b50d902SRodney W. Grimes break; 2079b50d902SRodney W. Grimes 2089b50d902SRodney W. Grimes case IFDFTYPE: 2099b50d902SRodney W. Grimes /* 2109b50d902SRodney W. Grimes * doifdef - select one of two 2119b50d902SRodney W. Grimes * alternatives based on the existence of 2129b50d902SRodney W. Grimes * another definition 2139b50d902SRodney W. Grimes */ 2149b50d902SRodney W. Grimes if (argc > 3) { 215a841e1ebSBaptiste Daroussin if (lookup_macro_definition(argv[2]) != NULL) 2169b50d902SRodney W. Grimes pbstr(argv[3]); 2179b50d902SRodney W. Grimes else if (argc > 4) 2189b50d902SRodney W. Grimes pbstr(argv[4]); 2199b50d902SRodney W. Grimes } 2209b50d902SRodney W. Grimes break; 2219b50d902SRodney W. Grimes 2229b50d902SRodney W. Grimes case LENGTYPE: 2239b50d902SRodney W. Grimes /* 2249b50d902SRodney W. Grimes * dolen - find the length of the 2259b50d902SRodney W. Grimes * argument 2269b50d902SRodney W. Grimes */ 2279b50d902SRodney W. Grimes pbnum((argc > 2) ? strlen(argv[2]) : 0); 2289b50d902SRodney W. Grimes break; 2299b50d902SRodney W. Grimes 2309b50d902SRodney W. Grimes case INCRTYPE: 2319b50d902SRodney W. Grimes /* 2329b50d902SRodney W. Grimes * doincr - increment the value of the 2339b50d902SRodney W. Grimes * argument 2349b50d902SRodney W. Grimes */ 2359b50d902SRodney W. Grimes if (argc > 2) 2369b50d902SRodney W. Grimes pbnum(atoi(argv[2]) + 1); 2379b50d902SRodney W. Grimes break; 2389b50d902SRodney W. Grimes 2399b50d902SRodney W. Grimes case DECRTYPE: 2409b50d902SRodney W. Grimes /* 2419b50d902SRodney W. Grimes * dodecr - decrement the value of the 2429b50d902SRodney W. Grimes * argument 2439b50d902SRodney W. Grimes */ 2449b50d902SRodney W. Grimes if (argc > 2) 2459b50d902SRodney W. Grimes pbnum(atoi(argv[2]) - 1); 2469b50d902SRodney W. Grimes break; 2479b50d902SRodney W. Grimes 2489b50d902SRodney W. Grimes case SYSCTYPE: 2499b50d902SRodney W. Grimes /* 2509b50d902SRodney W. Grimes * dosys - execute system command 2519b50d902SRodney W. Grimes */ 252aef4bb33STim J. Robbins if (argc > 2) { 253a841e1ebSBaptiste Daroussin fflush(stdout); 2549b50d902SRodney W. Grimes sysval = system(argv[2]); 255aef4bb33STim J. Robbins } 2569b50d902SRodney W. Grimes break; 2579b50d902SRodney W. Grimes 2589b50d902SRodney W. Grimes case SYSVTYPE: 2599b50d902SRodney W. Grimes /* 2609b50d902SRodney W. Grimes * dosysval - return value of the last 2619b50d902SRodney W. Grimes * system call. 2629b50d902SRodney W. Grimes * 2639b50d902SRodney W. Grimes */ 2649b50d902SRodney W. Grimes pbnum(sysval); 2659b50d902SRodney W. Grimes break; 2669b50d902SRodney W. Grimes 267acc9d408SJuli Mallett case ESYSCMDTYPE: 268acc9d408SJuli Mallett if (argc > 2) 269acc9d408SJuli Mallett doesyscmd(argv[2]); 270acc9d408SJuli Mallett break; 2719b50d902SRodney W. Grimes case INCLTYPE: 27288497f0cSBaptiste Daroussin if (argc > 2) { 2732cce1b69SBjoern A. Zeeb if (!doincl(argv[2])) { 274fb3f3d7cSBaptiste Daroussin if (mimic_gnu) { 2754fff7a14SBaptiste Daroussin warn("%s at line %lu: include(%s)", 2764fff7a14SBaptiste Daroussin CURRENT_NAME, CURRENT_LINE, argv[2]); 277fb3f3d7cSBaptiste Daroussin exit_code = 1; 278*c560b67cSBaptiste Daroussin if (fatal_warns) { 279*c560b67cSBaptiste Daroussin killdiv(); 280*c560b67cSBaptiste Daroussin exit(exit_code); 281*c560b67cSBaptiste Daroussin } 282fb3f3d7cSBaptiste Daroussin } else 283acc9d408SJuli Mallett err(1, "%s at line %lu: include(%s)", 284acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 2852cce1b69SBjoern A. Zeeb } 28688497f0cSBaptiste Daroussin } 2879b50d902SRodney W. Grimes break; 2889b50d902SRodney W. Grimes 2899b50d902SRodney W. Grimes case SINCTYPE: 2909b50d902SRodney W. Grimes if (argc > 2) 2919b50d902SRodney W. Grimes (void) doincl(argv[2]); 2929b50d902SRodney W. Grimes break; 2939b50d902SRodney W. Grimes #ifdef EXTENDED 2949b50d902SRodney W. Grimes case PASTTYPE: 2959b50d902SRodney W. Grimes if (argc > 2) 2969b50d902SRodney W. Grimes if (!dopaste(argv[2])) 297acc9d408SJuli Mallett err(1, "%s at line %lu: paste(%s)", 298acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 2999b50d902SRodney W. Grimes break; 3009b50d902SRodney W. Grimes 3019b50d902SRodney W. Grimes case SPASTYPE: 3029b50d902SRodney W. Grimes if (argc > 2) 3039b50d902SRodney W. Grimes (void) dopaste(argv[2]); 3049b50d902SRodney W. Grimes break; 305a841e1ebSBaptiste Daroussin case FORMATTYPE: 306a841e1ebSBaptiste Daroussin doformat(argv, argc); 307a841e1ebSBaptiste Daroussin break; 3089b50d902SRodney W. Grimes #endif 3099b50d902SRodney W. Grimes case CHNQTYPE: 310a841e1ebSBaptiste Daroussin dochq(argv, ac); 3119b50d902SRodney W. Grimes break; 3129b50d902SRodney W. Grimes 3139b50d902SRodney W. Grimes case CHNCTYPE: 3149b50d902SRodney W. Grimes dochc(argv, argc); 3159b50d902SRodney W. Grimes break; 3169b50d902SRodney W. Grimes 3179b50d902SRodney W. Grimes case SUBSTYPE: 3189b50d902SRodney W. Grimes /* 3199b50d902SRodney W. Grimes * dosub - select substring 3209b50d902SRodney W. Grimes * 3219b50d902SRodney W. Grimes */ 3229b50d902SRodney W. Grimes if (argc > 3) 3239b50d902SRodney W. Grimes dosub(argv, argc); 3249b50d902SRodney W. Grimes break; 3259b50d902SRodney W. Grimes 3269b50d902SRodney W. Grimes case SHIFTYPE: 3279b50d902SRodney W. Grimes /* 3289b50d902SRodney W. Grimes * doshift - push back all arguments 3299b50d902SRodney W. Grimes * except the first one (i.e. skip 3309b50d902SRodney W. Grimes * argv[2]) 3319b50d902SRodney W. Grimes */ 3329b50d902SRodney W. Grimes if (argc > 3) { 3339b50d902SRodney W. Grimes for (n = argc - 1; n > 3; n--) { 334acc9d408SJuli Mallett pbstr(rquote); 3359b50d902SRodney W. Grimes pbstr(argv[n]); 336acc9d408SJuli Mallett pbstr(lquote); 337a841e1ebSBaptiste Daroussin pushback(COMMA); 3389b50d902SRodney W. Grimes } 339acc9d408SJuli Mallett pbstr(rquote); 3409b50d902SRodney W. Grimes pbstr(argv[3]); 341acc9d408SJuli Mallett pbstr(lquote); 3429b50d902SRodney W. Grimes } 3439b50d902SRodney W. Grimes break; 3449b50d902SRodney W. Grimes 3459b50d902SRodney W. Grimes case DIVRTYPE: 3469b50d902SRodney W. Grimes if (argc > 2 && (n = atoi(argv[2])) != 0) 3479b50d902SRodney W. Grimes dodiv(n); 3489b50d902SRodney W. Grimes else { 3499b50d902SRodney W. Grimes active = stdout; 3509b50d902SRodney W. Grimes oindex = 0; 3519b50d902SRodney W. Grimes } 3529b50d902SRodney W. Grimes break; 3539b50d902SRodney W. Grimes 3549b50d902SRodney W. Grimes case UNDVTYPE: 3559b50d902SRodney W. Grimes doundiv(argv, argc); 3569b50d902SRodney W. Grimes break; 3579b50d902SRodney W. Grimes 3589b50d902SRodney W. Grimes case DIVNTYPE: 3599b50d902SRodney W. Grimes /* 3609b50d902SRodney W. Grimes * dodivnum - return the number of 3619b50d902SRodney W. Grimes * current output diversion 3629b50d902SRodney W. Grimes */ 3639b50d902SRodney W. Grimes pbnum(oindex); 3649b50d902SRodney W. Grimes break; 3659b50d902SRodney W. Grimes 3669b50d902SRodney W. Grimes case UNDFTYPE: 3679b50d902SRodney W. Grimes /* 3689b50d902SRodney W. Grimes * doundefine - undefine a previously 3699b50d902SRodney W. Grimes * defined macro(s) or m4 keyword(s). 3709b50d902SRodney W. Grimes */ 3719b50d902SRodney W. Grimes if (argc > 2) 3729b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 373a841e1ebSBaptiste Daroussin macro_undefine(argv[n]); 3749b50d902SRodney W. Grimes break; 3759b50d902SRodney W. Grimes 3769b50d902SRodney W. Grimes case POPDTYPE: 3779b50d902SRodney W. Grimes /* 3789b50d902SRodney W. Grimes * dopopdef - remove the topmost 3799b50d902SRodney W. Grimes * definitions of macro(s) or m4 3809b50d902SRodney W. Grimes * keyword(s). 3819b50d902SRodney W. Grimes */ 3829b50d902SRodney W. Grimes if (argc > 2) 3839b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 384a841e1ebSBaptiste Daroussin macro_popdef(argv[n]); 3859b50d902SRodney W. Grimes break; 3869b50d902SRodney W. Grimes 3879b50d902SRodney W. Grimes case MKTMTYPE: 3889b50d902SRodney W. Grimes /* 3899b50d902SRodney W. Grimes * dotemp - create a temporary file 3909b50d902SRodney W. Grimes */ 391acc9d408SJuli Mallett if (argc > 2) { 392acc9d408SJuli Mallett int fd; 393acc9d408SJuli Mallett char *temp; 394acc9d408SJuli Mallett 395acc9d408SJuli Mallett temp = xstrdup(argv[2]); 396acc9d408SJuli Mallett 397acc9d408SJuli Mallett fd = mkstemp(temp); 398acc9d408SJuli Mallett if (fd == -1) 399acc9d408SJuli Mallett err(1, 400acc9d408SJuli Mallett "%s at line %lu: couldn't make temp file %s", 401acc9d408SJuli Mallett CURRENT_NAME, CURRENT_LINE, argv[2]); 402acc9d408SJuli Mallett close(fd); 403acc9d408SJuli Mallett pbstr(temp); 404acc9d408SJuli Mallett free(temp); 405acc9d408SJuli Mallett } 4069b50d902SRodney W. Grimes break; 4079b50d902SRodney W. Grimes 4089b50d902SRodney W. Grimes case TRNLTYPE: 4099b50d902SRodney W. Grimes /* 4109b50d902SRodney W. Grimes * dotranslit - replace all characters in 4119b50d902SRodney W. Grimes * the source string that appears in the 4129b50d902SRodney W. Grimes * "from" string with the corresponding 4139b50d902SRodney W. Grimes * characters in the "to" string. 4149b50d902SRodney W. Grimes */ 4159b50d902SRodney W. Grimes if (argc > 3) { 416acc9d408SJuli Mallett char *temp; 417acc9d408SJuli Mallett 418a841e1ebSBaptiste Daroussin temp = xalloc(strlen(argv[2])+1, NULL); 4199b50d902SRodney W. Grimes if (argc > 4) 4209b50d902SRodney W. Grimes map(temp, argv[2], argv[3], argv[4]); 4219b50d902SRodney W. Grimes else 4229b50d902SRodney W. Grimes map(temp, argv[2], argv[3], null); 4239b50d902SRodney W. Grimes pbstr(temp); 424acc9d408SJuli Mallett free(temp); 425acc9d408SJuli Mallett } else if (argc > 2) 4269b50d902SRodney W. Grimes pbstr(argv[2]); 4279b50d902SRodney W. Grimes break; 4289b50d902SRodney W. Grimes 4299b50d902SRodney W. Grimes case INDXTYPE: 4309b50d902SRodney W. Grimes /* 4319b50d902SRodney W. Grimes * doindex - find the index of the second 4329b50d902SRodney W. Grimes * argument string in the first argument 4339b50d902SRodney W. Grimes * string. -1 if not present. 4349b50d902SRodney W. Grimes */ 4359b50d902SRodney W. Grimes pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 4369b50d902SRodney W. Grimes break; 4379b50d902SRodney W. Grimes 4389b50d902SRodney W. Grimes case ERRPTYPE: 4399b50d902SRodney W. Grimes /* 4409b50d902SRodney W. Grimes * doerrp - print the arguments to stderr 4419b50d902SRodney W. Grimes * file 4429b50d902SRodney W. Grimes */ 4439b50d902SRodney W. Grimes if (argc > 2) { 4449b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 4459b50d902SRodney W. Grimes fprintf(stderr, "%s ", argv[n]); 4469b50d902SRodney W. Grimes fprintf(stderr, "\n"); 4479b50d902SRodney W. Grimes } 4489b50d902SRodney W. Grimes break; 4499b50d902SRodney W. Grimes 4509b50d902SRodney W. Grimes case DNLNTYPE: 4519b50d902SRodney W. Grimes /* 4529b50d902SRodney W. Grimes * dodnl - eat-up-to and including 4539b50d902SRodney W. Grimes * newline 4549b50d902SRodney W. Grimes */ 4559b50d902SRodney W. Grimes while ((c = gpbc()) != '\n' && c != EOF) 4569b50d902SRodney W. Grimes ; 4579b50d902SRodney W. Grimes break; 4589b50d902SRodney W. Grimes 4599b50d902SRodney W. Grimes case M4WRTYPE: 4609b50d902SRodney W. Grimes /* 4619b50d902SRodney W. Grimes * dom4wrap - set up for 4629b50d902SRodney W. Grimes * wrap-up/wind-down activity 4639b50d902SRodney W. Grimes */ 464a841e1ebSBaptiste Daroussin if (argc > 2) 465a841e1ebSBaptiste Daroussin dom4wrap(argv[2]); 4669b50d902SRodney W. Grimes break; 4679b50d902SRodney W. Grimes 4689b50d902SRodney W. Grimes case EXITTYPE: 4699b50d902SRodney W. Grimes /* 4709b50d902SRodney W. Grimes * doexit - immediate exit from m4. 4719b50d902SRodney W. Grimes */ 472cac6992aSAndrey A. Chernov killdiv(); 4739b50d902SRodney W. Grimes exit((argc > 2) ? atoi(argv[2]) : 0); 4749b50d902SRodney W. Grimes break; 4759b50d902SRodney W. Grimes 4769b50d902SRodney W. Grimes case DEFNTYPE: 4779b50d902SRodney W. Grimes if (argc > 2) 4789b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 4799b50d902SRodney W. Grimes dodefn(argv[n]); 4809b50d902SRodney W. Grimes break; 4819b50d902SRodney W. Grimes 482acc9d408SJuli Mallett case INDIRTYPE: /* Indirect call */ 483acc9d408SJuli Mallett if (argc > 2) 484acc9d408SJuli Mallett doindir(argv, argc); 485bbfd1447SSteve Price break; 486bbfd1447SSteve Price 487acc9d408SJuli Mallett case BUILTINTYPE: /* Builtins only */ 488acc9d408SJuli Mallett if (argc > 2) 489acc9d408SJuli Mallett dobuiltin(argv, argc); 490acc9d408SJuli Mallett break; 491acc9d408SJuli Mallett 492acc9d408SJuli Mallett case PATSTYPE: 493acc9d408SJuli Mallett if (argc > 2) 494acc9d408SJuli Mallett dopatsubst(argv, argc); 495acc9d408SJuli Mallett break; 496acc9d408SJuli Mallett case REGEXPTYPE: 497acc9d408SJuli Mallett if (argc > 2) 498acc9d408SJuli Mallett doregexp(argv, argc); 499acc9d408SJuli Mallett break; 500acc9d408SJuli Mallett case LINETYPE: 501acc9d408SJuli Mallett doprintlineno(infile+ilevel); 502acc9d408SJuli Mallett break; 503acc9d408SJuli Mallett case FILENAMETYPE: 504acc9d408SJuli Mallett doprintfilename(infile+ilevel); 505acc9d408SJuli Mallett break; 506acc9d408SJuli Mallett case SELFTYPE: 507acc9d408SJuli Mallett pbstr(rquote); 508acc9d408SJuli Mallett pbstr(argv[1]); 509acc9d408SJuli Mallett pbstr(lquote); 510acc9d408SJuli Mallett break; 5119b50d902SRodney W. Grimes default: 512a841e1ebSBaptiste Daroussin m4errx(1, "eval: major botch."); 5139b50d902SRodney W. Grimes break; 5149b50d902SRodney W. Grimes } 5159b50d902SRodney W. Grimes } 5169b50d902SRodney W. Grimes 5179b50d902SRodney W. Grimes /* 518acc9d408SJuli Mallett * expand_macro - user-defined macro expansion 5199b50d902SRodney W. Grimes */ 5209b50d902SRodney W. Grimes void 521bd2bfb58SJuli Mallett expand_macro(const char *argv[], int argc) 5229b50d902SRodney W. Grimes { 523acc9d408SJuli Mallett const char *t; 524acc9d408SJuli Mallett const char *p; 525acc9d408SJuli Mallett int n; 526acc9d408SJuli Mallett int argno; 5279b50d902SRodney W. Grimes 5289b50d902SRodney W. Grimes t = argv[0]; /* defn string as a whole */ 5299b50d902SRodney W. Grimes p = t; 5309b50d902SRodney W. Grimes while (*p) 5319b50d902SRodney W. Grimes p++; 5329b50d902SRodney W. Grimes p--; /* last character of defn */ 5339b50d902SRodney W. Grimes while (p > t) { 5349b50d902SRodney W. Grimes if (*(p - 1) != ARGFLAG) 535a841e1ebSBaptiste Daroussin PUSHBACK(*p); 5369b50d902SRodney W. Grimes else { 5379b50d902SRodney W. Grimes switch (*p) { 5389b50d902SRodney W. Grimes 5399b50d902SRodney W. Grimes case '#': 5409b50d902SRodney W. Grimes pbnum(argc - 2); 5419b50d902SRodney W. Grimes break; 5429b50d902SRodney W. Grimes case '0': 5439b50d902SRodney W. Grimes case '1': 5449b50d902SRodney W. Grimes case '2': 5459b50d902SRodney W. Grimes case '3': 5469b50d902SRodney W. Grimes case '4': 5479b50d902SRodney W. Grimes case '5': 5489b50d902SRodney W. Grimes case '6': 5499b50d902SRodney W. Grimes case '7': 5509b50d902SRodney W. Grimes case '8': 5519b50d902SRodney W. Grimes case '9': 5529b50d902SRodney W. Grimes if ((argno = *p - '0') < argc - 1) 5539b50d902SRodney W. Grimes pbstr(argv[argno + 1]); 5549b50d902SRodney W. Grimes break; 5559b50d902SRodney W. Grimes case '*': 556acc9d408SJuli Mallett if (argc > 2) { 5579b50d902SRodney W. Grimes for (n = argc - 1; n > 2; n--) { 5589b50d902SRodney W. Grimes pbstr(argv[n]); 559a841e1ebSBaptiste Daroussin pushback(COMMA); 5609b50d902SRodney W. Grimes } 5619b50d902SRodney W. Grimes pbstr(argv[2]); 562acc9d408SJuli Mallett } 5639b50d902SRodney W. Grimes break; 564232eaee6SJoerg Wunsch case '@': 565acc9d408SJuli Mallett if (argc > 2) { 566acc9d408SJuli Mallett for (n = argc - 1; n > 2; n--) { 567acc9d408SJuli Mallett pbstr(rquote); 568232eaee6SJoerg Wunsch pbstr(argv[n]); 569acc9d408SJuli Mallett pbstr(lquote); 570a841e1ebSBaptiste Daroussin pushback(COMMA); 571acc9d408SJuli Mallett } 572acc9d408SJuli Mallett pbstr(rquote); 573acc9d408SJuli Mallett pbstr(argv[2]); 574acc9d408SJuli Mallett pbstr(lquote); 575232eaee6SJoerg Wunsch } 576232eaee6SJoerg Wunsch break; 5779b50d902SRodney W. Grimes default: 578a841e1ebSBaptiste Daroussin PUSHBACK(*p); 579a841e1ebSBaptiste Daroussin PUSHBACK('$'); 5809b50d902SRodney W. Grimes break; 5819b50d902SRodney W. Grimes } 5829b50d902SRodney W. Grimes p--; 5839b50d902SRodney W. Grimes } 5849b50d902SRodney W. Grimes p--; 5859b50d902SRodney W. Grimes } 5869b50d902SRodney W. Grimes if (p == t) /* do last character */ 587a841e1ebSBaptiste Daroussin PUSHBACK(*p); 5889b50d902SRodney W. Grimes } 5899b50d902SRodney W. Grimes 590a841e1ebSBaptiste Daroussin 5919b50d902SRodney W. Grimes /* 5929b50d902SRodney W. Grimes * dodefine - install definition in the table 5939b50d902SRodney W. Grimes */ 5949b50d902SRodney W. Grimes void 595bd2bfb58SJuli Mallett dodefine(const char *name, const char *defn) 5969b50d902SRodney W. Grimes { 597a841e1ebSBaptiste Daroussin if (!*name && !mimic_gnu) 598a841e1ebSBaptiste Daroussin m4errx(1, "null definition."); 5999b50d902SRodney W. Grimes else 600a841e1ebSBaptiste Daroussin macro_define(name, defn); 6019b50d902SRodney W. Grimes } 6029b50d902SRodney W. Grimes 6039b50d902SRodney W. Grimes /* 6049b50d902SRodney W. Grimes * dodefn - push back a quoted definition of 6059b50d902SRodney W. Grimes * the given name. 6069b50d902SRodney W. Grimes */ 607acc9d408SJuli Mallett static void 608bd2bfb58SJuli Mallett dodefn(const char *name) 6099b50d902SRodney W. Grimes { 610a841e1ebSBaptiste Daroussin struct macro_definition *p; 6119b50d902SRodney W. Grimes 612a841e1ebSBaptiste Daroussin if ((p = lookup_macro_definition(name)) != NULL) { 613a841e1ebSBaptiste Daroussin if ((p->type & TYPEMASK) == MACRTYPE) { 614acc9d408SJuli Mallett pbstr(rquote); 6159b50d902SRodney W. Grimes pbstr(p->defn); 616acc9d408SJuli Mallett pbstr(lquote); 617a841e1ebSBaptiste Daroussin } else { 618a841e1ebSBaptiste Daroussin pbstr(p->defn); 619acc9d408SJuli Mallett pbstr(BUILTIN_MARKER); 620acc9d408SJuli Mallett } 6219b50d902SRodney W. Grimes } 6229b50d902SRodney W. Grimes } 6239b50d902SRodney W. Grimes 6249b50d902SRodney W. Grimes /* 6259b50d902SRodney W. Grimes * dopushdef - install a definition in the hash table 6269b50d902SRodney W. Grimes * without removing a previous definition. Since 6279b50d902SRodney W. Grimes * each new entry is entered in *front* of the 6289b50d902SRodney W. Grimes * hash bucket, it hides a previous definition from 6299b50d902SRodney W. Grimes * lookup. 6309b50d902SRodney W. Grimes */ 631acc9d408SJuli Mallett static void 632bd2bfb58SJuli Mallett dopushdef(const char *name, const char *defn) 6339b50d902SRodney W. Grimes { 634a841e1ebSBaptiste Daroussin if (!*name && !mimic_gnu) 635a841e1ebSBaptiste Daroussin m4errx(1, "null definition."); 6369b50d902SRodney W. Grimes else 637a841e1ebSBaptiste Daroussin macro_pushdef(name, defn); 638acc9d408SJuli Mallett } 639acc9d408SJuli Mallett 640acc9d408SJuli Mallett /* 641acc9d408SJuli Mallett * dump_one_def - dump the specified definition. 642acc9d408SJuli Mallett */ 643acc9d408SJuli Mallett static void 644a841e1ebSBaptiste Daroussin dump_one_def(const char *name, struct macro_definition *p) 645acc9d408SJuli Mallett { 646a841e1ebSBaptiste Daroussin if (!traceout) 647a841e1ebSBaptiste Daroussin traceout = stderr; 648acc9d408SJuli Mallett if (mimic_gnu) { 649acc9d408SJuli Mallett if ((p->type & TYPEMASK) == MACRTYPE) 650a841e1ebSBaptiste Daroussin fprintf(traceout, "%s:\t%s\n", name, p->defn); 651acc9d408SJuli Mallett else { 652a841e1ebSBaptiste Daroussin fprintf(traceout, "%s:\t<%s>\n", name, p->defn); 653acc9d408SJuli Mallett } 654acc9d408SJuli Mallett } else 655a841e1ebSBaptiste Daroussin fprintf(traceout, "`%s'\t`%s'\n", name, p->defn); 6569b50d902SRodney W. Grimes } 6579b50d902SRodney W. Grimes 6589b50d902SRodney W. Grimes /* 6599b50d902SRodney W. Grimes * dodumpdef - dump the specified definitions in the hash 6609b50d902SRodney W. Grimes * table to stderr. If nothing is specified, the entire 6619b50d902SRodney W. Grimes * hash table is dumped. 6629b50d902SRodney W. Grimes */ 663acc9d408SJuli Mallett static void 664bd2bfb58SJuli Mallett dodump(const char *argv[], int argc) 6659b50d902SRodney W. Grimes { 666acc9d408SJuli Mallett int n; 667a841e1ebSBaptiste Daroussin struct macro_definition *p; 6689b50d902SRodney W. Grimes 6699b50d902SRodney W. Grimes if (argc > 2) { 6709b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 671a841e1ebSBaptiste Daroussin if ((p = lookup_macro_definition(argv[n])) != NULL) 672a841e1ebSBaptiste Daroussin dump_one_def(argv[n], p); 673a841e1ebSBaptiste Daroussin } else 674a841e1ebSBaptiste Daroussin macro_for_all(dump_one_def); 6759b50d902SRodney W. Grimes } 6769b50d902SRodney W. Grimes 6779b50d902SRodney W. Grimes /* 678acc9d408SJuli Mallett * dotrace - mark some macros as traced/untraced depending upon on. 679acc9d408SJuli Mallett */ 680acc9d408SJuli Mallett static void 681bd2bfb58SJuli Mallett dotrace(const char *argv[], int argc, int on) 682acc9d408SJuli Mallett { 683acc9d408SJuli Mallett int n; 684acc9d408SJuli Mallett 685acc9d408SJuli Mallett if (argc > 2) { 686acc9d408SJuli Mallett for (n = 2; n < argc; n++) 687acc9d408SJuli Mallett mark_traced(argv[n], on); 688acc9d408SJuli Mallett } else 689acc9d408SJuli Mallett mark_traced(NULL, on); 690acc9d408SJuli Mallett } 691acc9d408SJuli Mallett 692acc9d408SJuli Mallett /* 6939b50d902SRodney W. Grimes * doifelse - select one of two alternatives - loop. 6949b50d902SRodney W. Grimes */ 695acc9d408SJuli Mallett static void 696bd2bfb58SJuli Mallett doifelse(const char *argv[], int argc) 6979b50d902SRodney W. Grimes { 6989b50d902SRodney W. Grimes cycle { 6999b50d902SRodney W. Grimes if (STREQ(argv[2], argv[3])) 7009b50d902SRodney W. Grimes pbstr(argv[4]); 7019b50d902SRodney W. Grimes else if (argc == 6) 7029b50d902SRodney W. Grimes pbstr(argv[5]); 7039b50d902SRodney W. Grimes else if (argc > 6) { 7049b50d902SRodney W. Grimes argv += 3; 7059b50d902SRodney W. Grimes argc -= 3; 7069b50d902SRodney W. Grimes continue; 7079b50d902SRodney W. Grimes } 7089b50d902SRodney W. Grimes break; 7099b50d902SRodney W. Grimes } 7109b50d902SRodney W. Grimes } 7119b50d902SRodney W. Grimes 7129b50d902SRodney W. Grimes /* 7139b50d902SRodney W. Grimes * doinclude - include a given file. 7149b50d902SRodney W. Grimes */ 715acc9d408SJuli Mallett static int 716bd2bfb58SJuli Mallett doincl(const char *ifile) 7179b50d902SRodney W. Grimes { 7189b50d902SRodney W. Grimes if (ilevel + 1 == MAXINP) 719a841e1ebSBaptiste Daroussin m4errx(1, "too many include files."); 720acc9d408SJuli Mallett if (fopen_trypath(infile+ilevel+1, ifile) != NULL) { 7219b50d902SRodney W. Grimes ilevel++; 7229b50d902SRodney W. Grimes bbase[ilevel] = bufbase = bp; 7239b50d902SRodney W. Grimes return (1); 724acc9d408SJuli Mallett } else 7259b50d902SRodney W. Grimes return (0); 7269b50d902SRodney W. Grimes } 7279b50d902SRodney W. Grimes 7289b50d902SRodney W. Grimes #ifdef EXTENDED 7299b50d902SRodney W. Grimes /* 7309b50d902SRodney W. Grimes * dopaste - include a given file without any 7319b50d902SRodney W. Grimes * macro processing. 7329b50d902SRodney W. Grimes */ 733acc9d408SJuli Mallett static int 734bd2bfb58SJuli Mallett dopaste(const char *pfile) 7359b50d902SRodney W. Grimes { 7369b50d902SRodney W. Grimes FILE *pf; 737acc9d408SJuli Mallett int c; 7389b50d902SRodney W. Grimes 7399b50d902SRodney W. Grimes if ((pf = fopen(pfile, "r")) != NULL) { 740a841e1ebSBaptiste Daroussin if (synch_lines) 741b1ea3d46SJuli Mallett fprintf(active, "#line 1 \"%s\"\n", pfile); 7429b50d902SRodney W. Grimes while ((c = getc(pf)) != EOF) 7439b50d902SRodney W. Grimes putc(c, active); 7449b50d902SRodney W. Grimes (void) fclose(pf); 745a841e1ebSBaptiste Daroussin emit_synchline(); 7469b50d902SRodney W. Grimes return (1); 747acc9d408SJuli Mallett } else 7489b50d902SRodney W. Grimes return (0); 7499b50d902SRodney W. Grimes } 7509b50d902SRodney W. Grimes #endif 7519b50d902SRodney W. Grimes 7529b50d902SRodney W. Grimes /* 753acc9d408SJuli Mallett * dochq - change quote characters 7549b50d902SRodney W. Grimes */ 755acc9d408SJuli Mallett static void 756a841e1ebSBaptiste Daroussin dochq(const char *argv[], int ac) 7579b50d902SRodney W. Grimes { 758a841e1ebSBaptiste Daroussin if (ac == 2) { 759a841e1ebSBaptiste Daroussin lquote[0] = LQUOTE; lquote[1] = EOS; 760a841e1ebSBaptiste Daroussin rquote[0] = RQUOTE; rquote[1] = EOS; 761acc9d408SJuli Mallett } else { 762a841e1ebSBaptiste Daroussin strlcpy(lquote, argv[2], sizeof(lquote)); 763a841e1ebSBaptiste Daroussin if (ac > 3) { 764a841e1ebSBaptiste Daroussin strlcpy(rquote, argv[3], sizeof(rquote)); 765a841e1ebSBaptiste Daroussin } else { 766a841e1ebSBaptiste Daroussin rquote[0] = ECOMMT; rquote[1] = EOS; 767a841e1ebSBaptiste Daroussin } 768acc9d408SJuli Mallett } 769acc9d408SJuli Mallett } 770acc9d408SJuli Mallett 771acc9d408SJuli Mallett /* 772acc9d408SJuli Mallett * dochc - change comment characters 773acc9d408SJuli Mallett */ 774acc9d408SJuli Mallett static void 775bd2bfb58SJuli Mallett dochc(const char *argv[], int argc) 776acc9d408SJuli Mallett { 777a841e1ebSBaptiste Daroussin /* XXX Note that there is no difference between no argument and a single 778a841e1ebSBaptiste Daroussin * empty argument. 779a841e1ebSBaptiste Daroussin */ 780a841e1ebSBaptiste Daroussin if (argc == 2) { 781a841e1ebSBaptiste Daroussin scommt[0] = EOS; 782a841e1ebSBaptiste Daroussin ecommt[0] = EOS; 783a841e1ebSBaptiste Daroussin } else { 784acc9d408SJuli Mallett strlcpy(scommt, argv[2], sizeof(scommt)); 785a841e1ebSBaptiste Daroussin if (argc == 3) { 786a841e1ebSBaptiste Daroussin ecommt[0] = ECOMMT; ecommt[1] = EOS; 787a841e1ebSBaptiste Daroussin } else { 788acc9d408SJuli Mallett strlcpy(ecommt, argv[3], sizeof(ecommt)); 7899b50d902SRodney W. Grimes } 790a841e1ebSBaptiste Daroussin } 791a841e1ebSBaptiste Daroussin } 792a841e1ebSBaptiste Daroussin 793a841e1ebSBaptiste Daroussin /* 794a841e1ebSBaptiste Daroussin * dom4wrap - expand text at EOF 795a841e1ebSBaptiste Daroussin */ 796a841e1ebSBaptiste Daroussin static void 797a841e1ebSBaptiste Daroussin dom4wrap(const char *text) 798a841e1ebSBaptiste Daroussin { 799a841e1ebSBaptiste Daroussin if (wrapindex >= maxwraps) { 800a841e1ebSBaptiste Daroussin if (maxwraps == 0) 801a841e1ebSBaptiste Daroussin maxwraps = 16; 8029b50d902SRodney W. Grimes else 803a841e1ebSBaptiste Daroussin maxwraps *= 2; 80488497f0cSBaptiste Daroussin m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps), 805a841e1ebSBaptiste Daroussin "too many m4wraps"); 8069b50d902SRodney W. Grimes } 807a841e1ebSBaptiste Daroussin m4wraps[wrapindex++] = xstrdup(text); 8089b50d902SRodney W. Grimes } 8099b50d902SRodney W. Grimes 8109b50d902SRodney W. Grimes /* 8119b50d902SRodney W. Grimes * dodivert - divert the output to a temporary file 8129b50d902SRodney W. Grimes */ 813acc9d408SJuli Mallett static void 814bd2bfb58SJuli Mallett dodiv(int n) 8159b50d902SRodney W. Grimes { 816acc9d408SJuli Mallett int fd; 817acc9d408SJuli Mallett 818ef2cea81SJonathan Lemon oindex = n; 819acc9d408SJuli Mallett if (n >= maxout) { 820acc9d408SJuli Mallett if (mimic_gnu) 821acc9d408SJuli Mallett resizedivs(n + 10); 822acc9d408SJuli Mallett else 823acc9d408SJuli Mallett n = 0; /* bitbucket */ 824acc9d408SJuli Mallett } 825acc9d408SJuli Mallett 826acc9d408SJuli Mallett if (n < 0) 8279b50d902SRodney W. Grimes n = 0; /* bitbucket */ 8289b50d902SRodney W. Grimes if (outfile[n] == NULL) { 829acc9d408SJuli Mallett char fname[] = _PATH_DIVNAME; 830acc9d408SJuli Mallett 831acc9d408SJuli Mallett if ((fd = mkstemp(fname)) < 0 || 83288497f0cSBaptiste Daroussin unlink(fname) == -1 || 833acc9d408SJuli Mallett (outfile[n] = fdopen(fd, "w+")) == NULL) 834acc9d408SJuli Mallett err(1, "%s: cannot divert", fname); 8359b50d902SRodney W. Grimes } 8369b50d902SRodney W. Grimes active = outfile[n]; 8379b50d902SRodney W. Grimes } 8389b50d902SRodney W. Grimes 8399b50d902SRodney W. Grimes /* 8409b50d902SRodney W. Grimes * doundivert - undivert a specified output, or all 8419b50d902SRodney W. Grimes * other outputs, in numerical order. 8429b50d902SRodney W. Grimes */ 843acc9d408SJuli Mallett static void 844bd2bfb58SJuli Mallett doundiv(const char *argv[], int argc) 8459b50d902SRodney W. Grimes { 846acc9d408SJuli Mallett int ind; 847acc9d408SJuli Mallett int n; 8489b50d902SRodney W. Grimes 8499b50d902SRodney W. Grimes if (argc > 2) { 8509b50d902SRodney W. Grimes for (ind = 2; ind < argc; ind++) { 851a841e1ebSBaptiste Daroussin const char *errstr; 852a841e1ebSBaptiste Daroussin n = strtonum(argv[ind], 1, INT_MAX, &errstr); 853a841e1ebSBaptiste Daroussin if (errstr) { 854a841e1ebSBaptiste Daroussin if (errno == EINVAL && mimic_gnu) 855a841e1ebSBaptiste Daroussin getdivfile(argv[ind]); 856a841e1ebSBaptiste Daroussin } else { 857a841e1ebSBaptiste Daroussin if (n < maxout && outfile[n] != NULL) 8589b50d902SRodney W. Grimes getdiv(n); 859a841e1ebSBaptiste Daroussin } 8609b50d902SRodney W. Grimes } 8619b50d902SRodney W. Grimes } 8629b50d902SRodney W. Grimes else 863acc9d408SJuli Mallett for (n = 1; n < maxout; n++) 8649b50d902SRodney W. Grimes if (outfile[n] != NULL) 8659b50d902SRodney W. Grimes getdiv(n); 8669b50d902SRodney W. Grimes } 8679b50d902SRodney W. Grimes 8689b50d902SRodney W. Grimes /* 8699b50d902SRodney W. Grimes * dosub - select substring 8709b50d902SRodney W. Grimes */ 871acc9d408SJuli Mallett static void 872bd2bfb58SJuli Mallett dosub(const char *argv[], int argc) 8739b50d902SRodney W. Grimes { 874acc9d408SJuli Mallett const char *ap, *fc, *k; 875acc9d408SJuli Mallett int nc; 8769b50d902SRodney W. Grimes 8779b50d902SRodney W. Grimes ap = argv[2]; /* target string */ 8789b50d902SRodney W. Grimes #ifdef EXPR 8799b50d902SRodney W. Grimes fc = ap + expr(argv[3]); /* first char */ 8809b50d902SRodney W. Grimes #else 8819b50d902SRodney W. Grimes fc = ap + atoi(argv[3]); /* first char */ 8829b50d902SRodney W. Grimes #endif 8834ba4d387SGregory Neil Shapiro nc = strlen(fc); 884acc9d408SJuli Mallett if (argc >= 5) 8854ba4d387SGregory Neil Shapiro #ifdef EXPR 886acc9d408SJuli Mallett nc = min(nc, expr(argv[4])); 8874ba4d387SGregory Neil Shapiro #else 888acc9d408SJuli Mallett nc = min(nc, atoi(argv[4])); 8894ba4d387SGregory Neil Shapiro #endif 8909b50d902SRodney W. Grimes if (fc >= ap && fc < ap + strlen(ap)) 8914ba4d387SGregory Neil Shapiro for (k = fc + nc - 1; k >= fc; k--) 892a841e1ebSBaptiste Daroussin pushback(*k); 8939b50d902SRodney W. Grimes } 8949b50d902SRodney W. Grimes 8959b50d902SRodney W. Grimes /* 8969b50d902SRodney W. Grimes * map: 8979b50d902SRodney W. Grimes * map every character of s1 that is specified in from 8989b50d902SRodney W. Grimes * into s3 and replace in s. (source s1 remains untouched) 8999b50d902SRodney W. Grimes * 900a841e1ebSBaptiste Daroussin * This is derived from the a standard implementation of map(s,from,to) 901a841e1ebSBaptiste Daroussin * function of ICON language. Within mapvec, we replace every character 902a841e1ebSBaptiste Daroussin * of "from" with the corresponding character in "to". 903a841e1ebSBaptiste Daroussin * If "to" is shorter than "from", than the corresponding entries are null, 904af7ca7c8SPedro F. Giffuni * which means that those characters disappear altogether. 9059b50d902SRodney W. Grimes */ 906acc9d408SJuli Mallett static void 907bd2bfb58SJuli Mallett map(char *dest, const char *src, const char *from, const char *to) 9089b50d902SRodney W. Grimes { 909acc9d408SJuli Mallett const char *tmp; 910acc9d408SJuli Mallett unsigned char sch, dch; 911acc9d408SJuli Mallett static char frombis[257]; 912acc9d408SJuli Mallett static char tobis[257]; 913a841e1ebSBaptiste Daroussin int i; 914a841e1ebSBaptiste Daroussin char seen[256]; 915acc9d408SJuli Mallett static unsigned char mapvec[256] = { 916acc9d408SJuli Mallett 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 917acc9d408SJuli Mallett 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 918acc9d408SJuli Mallett 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 919acc9d408SJuli Mallett 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 920acc9d408SJuli Mallett 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 921acc9d408SJuli Mallett 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 922acc9d408SJuli Mallett 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 923acc9d408SJuli Mallett 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 924acc9d408SJuli Mallett 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 925acc9d408SJuli Mallett 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 926acc9d408SJuli Mallett 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 927acc9d408SJuli Mallett 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 928acc9d408SJuli Mallett 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 929acc9d408SJuli Mallett 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 930acc9d408SJuli Mallett 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 931acc9d408SJuli Mallett 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 932acc9d408SJuli Mallett 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 933acc9d408SJuli Mallett 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 9349b50d902SRodney W. Grimes }; 9359b50d902SRodney W. Grimes 9369b50d902SRodney W. Grimes if (*src) { 937acc9d408SJuli Mallett if (mimic_gnu) { 938acc9d408SJuli Mallett /* 939acc9d408SJuli Mallett * expand character ranges on the fly 940acc9d408SJuli Mallett */ 941acc9d408SJuli Mallett from = handledash(frombis, frombis + 256, from); 942acc9d408SJuli Mallett to = handledash(tobis, tobis + 256, to); 943acc9d408SJuli Mallett } 9449b50d902SRodney W. Grimes tmp = from; 9459b50d902SRodney W. Grimes /* 9469b50d902SRodney W. Grimes * create a mapping between "from" and 9479b50d902SRodney W. Grimes * "to" 9489b50d902SRodney W. Grimes */ 949a841e1ebSBaptiste Daroussin for (i = 0; i < 256; i++) 950a841e1ebSBaptiste Daroussin seen[i] = 0; 951a841e1ebSBaptiste Daroussin while (*from) { 952a841e1ebSBaptiste Daroussin if (!seen[(unsigned char)(*from)]) { 953a841e1ebSBaptiste Daroussin mapvec[(unsigned char)(*from)] = (unsigned char)(*to); 954a841e1ebSBaptiste Daroussin seen[(unsigned char)(*from)] = 1; 955a841e1ebSBaptiste Daroussin } 956a841e1ebSBaptiste Daroussin from++; 957a841e1ebSBaptiste Daroussin if (*to) 958a841e1ebSBaptiste Daroussin to++; 959a841e1ebSBaptiste Daroussin } 9609b50d902SRodney W. Grimes 9619b50d902SRodney W. Grimes while (*src) { 962acc9d408SJuli Mallett sch = (unsigned char)(*src++); 9639b50d902SRodney W. Grimes dch = mapvec[sch]; 964acc9d408SJuli Mallett if ((*dest = (char)dch)) 9659b50d902SRodney W. Grimes dest++; 9669b50d902SRodney W. Grimes } 9679b50d902SRodney W. Grimes /* 9689b50d902SRodney W. Grimes * restore all the changed characters 9699b50d902SRodney W. Grimes */ 9709b50d902SRodney W. Grimes while (*tmp) { 971acc9d408SJuli Mallett mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp); 9729b50d902SRodney W. Grimes tmp++; 9739b50d902SRodney W. Grimes } 9749b50d902SRodney W. Grimes } 975acc9d408SJuli Mallett *dest = '\0'; 9769b50d902SRodney W. Grimes } 977acc9d408SJuli Mallett 978acc9d408SJuli Mallett 979acc9d408SJuli Mallett /* 980acc9d408SJuli Mallett * handledash: 981acc9d408SJuli Mallett * use buffer to copy the src string, expanding character ranges 982acc9d408SJuli Mallett * on the way. 983acc9d408SJuli Mallett */ 984acc9d408SJuli Mallett static const char * 985bd2bfb58SJuli Mallett handledash(char *buffer, char *end, const char *src) 986acc9d408SJuli Mallett { 987acc9d408SJuli Mallett char *p; 988acc9d408SJuli Mallett 989acc9d408SJuli Mallett p = buffer; 990acc9d408SJuli Mallett while(*src) { 991acc9d408SJuli Mallett if (src[1] == '-' && src[2]) { 992acc9d408SJuli Mallett unsigned char i; 993a841e1ebSBaptiste Daroussin if ((unsigned char)src[0] <= (unsigned char)src[2]) { 994acc9d408SJuli Mallett for (i = (unsigned char)src[0]; 995acc9d408SJuli Mallett i <= (unsigned char)src[2]; i++) { 996acc9d408SJuli Mallett *p++ = i; 997acc9d408SJuli Mallett if (p == end) { 998acc9d408SJuli Mallett *p = '\0'; 999acc9d408SJuli Mallett return buffer; 1000acc9d408SJuli Mallett } 1001acc9d408SJuli Mallett } 1002a841e1ebSBaptiste Daroussin } else { 1003a841e1ebSBaptiste Daroussin for (i = (unsigned char)src[0]; 1004a841e1ebSBaptiste Daroussin i >= (unsigned char)src[2]; i--) { 1005a841e1ebSBaptiste Daroussin *p++ = i; 1006a841e1ebSBaptiste Daroussin if (p == end) { 1007a841e1ebSBaptiste Daroussin *p = '\0'; 1008a841e1ebSBaptiste Daroussin return buffer; 1009a841e1ebSBaptiste Daroussin } 1010a841e1ebSBaptiste Daroussin } 1011a841e1ebSBaptiste Daroussin } 1012acc9d408SJuli Mallett src += 3; 1013acc9d408SJuli Mallett } else 1014acc9d408SJuli Mallett *p++ = *src++; 1015acc9d408SJuli Mallett if (p == end) 1016acc9d408SJuli Mallett break; 1017acc9d408SJuli Mallett } 1018acc9d408SJuli Mallett *p = '\0'; 1019acc9d408SJuli Mallett return buffer; 1020acc9d408SJuli Mallett } 1021