19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1989, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by 69b50d902SRodney W. Grimes * Ozan Yigit at York University. 79b50d902SRodney W. Grimes * 89b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 99b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 109b50d902SRodney W. Grimes * are met: 119b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 129b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 139b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 149b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 159b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 169b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 179b50d902SRodney W. Grimes * must display the following acknowledgement: 189b50d902SRodney W. Grimes * This product includes software developed by the University of 199b50d902SRodney W. Grimes * California, Berkeley and its contributors. 209b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 219b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 229b50d902SRodney W. Grimes * without specific prior written permission. 239b50d902SRodney W. Grimes * 249b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 259b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 269b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 279b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 289b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 299b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 309b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 319b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 329b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 339b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 349b50d902SRodney W. Grimes * SUCH DAMAGE. 359b50d902SRodney W. Grimes */ 369b50d902SRodney W. Grimes 379b50d902SRodney W. Grimes #ifndef lint 3895105358SPhilippe Charnier #if 0 399b50d902SRodney W. Grimes static char sccsid[] = "@(#)eval.c 8.1 (Berkeley) 6/6/93"; 4095105358SPhilippe Charnier #endif 4195105358SPhilippe Charnier static const char rcsid[] = 42c3aac50fSPeter Wemm "$FreeBSD$"; 439b50d902SRodney W. Grimes #endif /* not lint */ 449b50d902SRodney W. Grimes 459b50d902SRodney W. Grimes /* 469b50d902SRodney W. Grimes * eval.c 479b50d902SRodney W. Grimes * Facility: m4 macro processor 489b50d902SRodney W. Grimes * by: oz 499b50d902SRodney W. Grimes */ 509b50d902SRodney W. Grimes 519b50d902SRodney W. Grimes #include <sys/types.h> 5295105358SPhilippe Charnier #include <err.h> 539b50d902SRodney W. Grimes #include <stdio.h> 549b50d902SRodney W. Grimes #include <stdlib.h> 559b50d902SRodney W. Grimes #include <string.h> 5695105358SPhilippe Charnier #include <unistd.h> 579b50d902SRodney W. Grimes #include "mdef.h" 589b50d902SRodney W. Grimes #include "stdd.h" 599b50d902SRodney W. Grimes #include "extern.h" 609b50d902SRodney W. Grimes #include "pathnames.h" 619b50d902SRodney W. Grimes 629b50d902SRodney W. Grimes /* 639b50d902SRodney W. Grimes * eval - evaluate built-in macros. 649b50d902SRodney W. Grimes * argc - number of elements in argv. 659b50d902SRodney W. Grimes * argv - element vector : 669b50d902SRodney W. Grimes * argv[0] = definition of a user 679b50d902SRodney W. Grimes * macro or nil if built-in. 689b50d902SRodney W. Grimes * argv[1] = name of the macro or 699b50d902SRodney W. Grimes * built-in. 709b50d902SRodney W. Grimes * argv[2] = parameters to user-defined 719b50d902SRodney W. Grimes * . macro or built-in. 729b50d902SRodney W. Grimes * . 739b50d902SRodney W. Grimes * 749b50d902SRodney W. Grimes * Note that the minimum value for argc is 3. A call in the form 759b50d902SRodney W. Grimes * of macro-or-builtin() will result in: 769b50d902SRodney W. Grimes * argv[0] = nullstr 779b50d902SRodney W. Grimes * argv[1] = macro-or-builtin 789b50d902SRodney W. Grimes * argv[2] = nullstr 799b50d902SRodney W. Grimes */ 809b50d902SRodney W. Grimes 819b50d902SRodney W. Grimes void 829b50d902SRodney W. Grimes eval(argv, argc, td) 839b50d902SRodney W. Grimes register char *argv[]; 849b50d902SRodney W. Grimes register int argc; 859b50d902SRodney W. Grimes register int td; 869b50d902SRodney W. Grimes { 879b50d902SRodney W. Grimes register int c, n; 889b50d902SRodney W. Grimes static int sysval = 0; 89de9b3b90SDavid E. O'Brien char *p; 909b50d902SRodney W. Grimes 919b50d902SRodney W. Grimes #ifdef DEBUG 929b50d902SRodney W. Grimes printf("argc = %d\n", argc); 939b50d902SRodney W. Grimes for (n = 0; n < argc; n++) 949b50d902SRodney W. Grimes printf("argv[%d] = %s\n", n, argv[n]); 959b50d902SRodney W. Grimes #endif 969b50d902SRodney W. Grimes /* 979b50d902SRodney W. Grimes * if argc == 3 and argv[2] is null, then we 989b50d902SRodney W. Grimes * have macro-or-builtin() type call. We adjust 999b50d902SRodney W. Grimes * argc to avoid further checking.. 1009b50d902SRodney W. Grimes */ 1019b50d902SRodney W. Grimes if (argc == 3 && !*(argv[2])) 1029b50d902SRodney W. Grimes argc--; 1039b50d902SRodney W. Grimes 1049b50d902SRodney W. Grimes switch (td & ~STATIC) { 1059b50d902SRodney W. Grimes 1069b50d902SRodney W. Grimes case DEFITYPE: 1079b50d902SRodney W. Grimes if (argc > 2) 1089b50d902SRodney W. Grimes dodefine(argv[2], (argc > 3) ? argv[3] : null); 1099b50d902SRodney W. Grimes break; 1109b50d902SRodney W. Grimes 1119b50d902SRodney W. Grimes case PUSDTYPE: 1129b50d902SRodney W. Grimes if (argc > 2) 1139b50d902SRodney W. Grimes dopushdef(argv[2], (argc > 3) ? argv[3] : null); 1149b50d902SRodney W. Grimes break; 1159b50d902SRodney W. Grimes 1169b50d902SRodney W. Grimes case DUMPTYPE: 1179b50d902SRodney W. Grimes dodump(argv, argc); 1189b50d902SRodney W. Grimes break; 1199b50d902SRodney W. Grimes 1209b50d902SRodney W. Grimes case EXPRTYPE: 1219b50d902SRodney W. Grimes /* 1229b50d902SRodney W. Grimes * doexpr - evaluate arithmetic 1239b50d902SRodney W. Grimes * expression 1249b50d902SRodney W. Grimes */ 1259b50d902SRodney W. Grimes if (argc > 2) 1269b50d902SRodney W. Grimes pbnum(expr(argv[2])); 1279b50d902SRodney W. Grimes break; 1289b50d902SRodney W. Grimes 1299b50d902SRodney W. Grimes case IFELTYPE: 1309b50d902SRodney W. Grimes if (argc > 4) 1319b50d902SRodney W. Grimes doifelse(argv, argc); 1329b50d902SRodney W. Grimes break; 1339b50d902SRodney W. Grimes 1349b50d902SRodney W. Grimes case IFDFTYPE: 1359b50d902SRodney W. Grimes /* 1369b50d902SRodney W. Grimes * doifdef - select one of two 1379b50d902SRodney W. Grimes * alternatives based on the existence of 1389b50d902SRodney W. Grimes * another definition 1399b50d902SRodney W. Grimes */ 1409b50d902SRodney W. Grimes if (argc > 3) { 1419b50d902SRodney W. Grimes if (lookup(argv[2]) != nil) 1429b50d902SRodney W. Grimes pbstr(argv[3]); 1439b50d902SRodney W. Grimes else if (argc > 4) 1449b50d902SRodney W. Grimes pbstr(argv[4]); 1459b50d902SRodney W. Grimes } 1469b50d902SRodney W. Grimes break; 1479b50d902SRodney W. Grimes 1489b50d902SRodney W. Grimes case LENGTYPE: 1499b50d902SRodney W. Grimes /* 1509b50d902SRodney W. Grimes * dolen - find the length of the 1519b50d902SRodney W. Grimes * argument 1529b50d902SRodney W. Grimes */ 1539b50d902SRodney W. Grimes pbnum((argc > 2) ? strlen(argv[2]) : 0); 1549b50d902SRodney W. Grimes break; 1559b50d902SRodney W. Grimes 1569b50d902SRodney W. Grimes case INCRTYPE: 1579b50d902SRodney W. Grimes /* 1589b50d902SRodney W. Grimes * doincr - increment the value of the 1599b50d902SRodney W. Grimes * argument 1609b50d902SRodney W. Grimes */ 1619b50d902SRodney W. Grimes if (argc > 2) 1629b50d902SRodney W. Grimes pbnum(atoi(argv[2]) + 1); 1639b50d902SRodney W. Grimes break; 1649b50d902SRodney W. Grimes 1659b50d902SRodney W. Grimes case DECRTYPE: 1669b50d902SRodney W. Grimes /* 1679b50d902SRodney W. Grimes * dodecr - decrement the value of the 1689b50d902SRodney W. Grimes * argument 1699b50d902SRodney W. Grimes */ 1709b50d902SRodney W. Grimes if (argc > 2) 1719b50d902SRodney W. Grimes pbnum(atoi(argv[2]) - 1); 1729b50d902SRodney W. Grimes break; 1739b50d902SRodney W. Grimes 1749b50d902SRodney W. Grimes case SYSCTYPE: 1759b50d902SRodney W. Grimes /* 1769b50d902SRodney W. Grimes * dosys - execute system command 1779b50d902SRodney W. Grimes */ 1783ee80812SAndrey A. Chernov /* Make sure m4 output is NOT interrupted */ 1793ee80812SAndrey A. Chernov fflush(stdout); 1803ee80812SAndrey A. Chernov fflush(stderr); 1819b50d902SRodney W. Grimes if (argc > 2) 1829b50d902SRodney W. Grimes sysval = system(argv[2]); 1839b50d902SRodney W. Grimes break; 1849b50d902SRodney W. Grimes 1859b50d902SRodney W. Grimes case SYSVTYPE: 1869b50d902SRodney W. Grimes /* 1879b50d902SRodney W. Grimes * dosysval - return value of the last 1889b50d902SRodney W. Grimes * system call. 1899b50d902SRodney W. Grimes * 1909b50d902SRodney W. Grimes */ 1919b50d902SRodney W. Grimes pbnum(sysval); 1929b50d902SRodney W. Grimes break; 1939b50d902SRodney W. Grimes 1949b50d902SRodney W. Grimes case INCLTYPE: 1959b50d902SRodney W. Grimes if (argc > 2) 1969b50d902SRodney W. Grimes if (!doincl(argv[2])) 19795105358SPhilippe Charnier err(1, "%s", argv[2]); 1989b50d902SRodney W. Grimes break; 1999b50d902SRodney W. Grimes 2009b50d902SRodney W. Grimes case SINCTYPE: 2019b50d902SRodney W. Grimes if (argc > 2) 2029b50d902SRodney W. Grimes (void) doincl(argv[2]); 2039b50d902SRodney W. Grimes break; 2049b50d902SRodney W. Grimes #ifdef EXTENDED 2059b50d902SRodney W. Grimes case PASTTYPE: 2069b50d902SRodney W. Grimes if (argc > 2) 2079b50d902SRodney W. Grimes if (!dopaste(argv[2])) 20895105358SPhilippe Charnier err(1, "%s", argv[2]); 2099b50d902SRodney W. Grimes break; 2109b50d902SRodney W. Grimes 2119b50d902SRodney W. Grimes case SPASTYPE: 2129b50d902SRodney W. Grimes if (argc > 2) 2139b50d902SRodney W. Grimes (void) dopaste(argv[2]); 2149b50d902SRodney W. Grimes break; 2159b50d902SRodney W. Grimes #endif 2169b50d902SRodney W. Grimes case CHNQTYPE: 2179b50d902SRodney W. Grimes dochq(argv, argc); 2189b50d902SRodney W. Grimes break; 2199b50d902SRodney W. Grimes 2209b50d902SRodney W. Grimes case CHNCTYPE: 2219b50d902SRodney W. Grimes dochc(argv, argc); 2229b50d902SRodney W. Grimes break; 2239b50d902SRodney W. Grimes 2249b50d902SRodney W. Grimes case SUBSTYPE: 2259b50d902SRodney W. Grimes /* 2269b50d902SRodney W. Grimes * dosub - select substring 2279b50d902SRodney W. Grimes * 2289b50d902SRodney W. Grimes */ 2299b50d902SRodney W. Grimes if (argc > 3) 2309b50d902SRodney W. Grimes dosub(argv, argc); 2319b50d902SRodney W. Grimes break; 2329b50d902SRodney W. Grimes 2339b50d902SRodney W. Grimes case SHIFTYPE: 2349b50d902SRodney W. Grimes /* 2359b50d902SRodney W. Grimes * doshift - push back all arguments 2369b50d902SRodney W. Grimes * except the first one (i.e. skip 2379b50d902SRodney W. Grimes * argv[2]) 2389b50d902SRodney W. Grimes */ 2399b50d902SRodney W. Grimes if (argc > 3) { 2409b50d902SRodney W. Grimes for (n = argc - 1; n > 3; n--) { 2419b50d902SRodney W. Grimes putback(rquote); 2429b50d902SRodney W. Grimes pbstr(argv[n]); 2439b50d902SRodney W. Grimes putback(lquote); 2449b50d902SRodney W. Grimes putback(','); 2459b50d902SRodney W. Grimes } 2469b50d902SRodney W. Grimes putback(rquote); 2479b50d902SRodney W. Grimes pbstr(argv[3]); 2489b50d902SRodney W. Grimes putback(lquote); 2499b50d902SRodney W. Grimes } 2509b50d902SRodney W. Grimes break; 2519b50d902SRodney W. Grimes 2529b50d902SRodney W. Grimes case DIVRTYPE: 2539b50d902SRodney W. Grimes if (argc > 2 && (n = atoi(argv[2])) != 0) 2549b50d902SRodney W. Grimes dodiv(n); 2559b50d902SRodney W. Grimes else { 2569b50d902SRodney W. Grimes active = stdout; 2579b50d902SRodney W. Grimes oindex = 0; 2589b50d902SRodney W. Grimes } 2599b50d902SRodney W. Grimes break; 2609b50d902SRodney W. Grimes 2619b50d902SRodney W. Grimes case UNDVTYPE: 2629b50d902SRodney W. Grimes doundiv(argv, argc); 2639b50d902SRodney W. Grimes break; 2649b50d902SRodney W. Grimes 2659b50d902SRodney W. Grimes case DIVNTYPE: 2669b50d902SRodney W. Grimes /* 2679b50d902SRodney W. Grimes * dodivnum - return the number of 2689b50d902SRodney W. Grimes * current output diversion 2699b50d902SRodney W. Grimes */ 2709b50d902SRodney W. Grimes pbnum(oindex); 2719b50d902SRodney W. Grimes break; 2729b50d902SRodney W. Grimes 2739b50d902SRodney W. Grimes case UNDFTYPE: 2749b50d902SRodney W. Grimes /* 2759b50d902SRodney W. Grimes * doundefine - undefine a previously 2769b50d902SRodney W. Grimes * defined macro(s) or m4 keyword(s). 2779b50d902SRodney W. Grimes */ 2789b50d902SRodney W. Grimes if (argc > 2) 2799b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 2809b50d902SRodney W. Grimes remhash(argv[n], ALL); 2819b50d902SRodney W. Grimes break; 2829b50d902SRodney W. Grimes 2839b50d902SRodney W. Grimes case POPDTYPE: 2849b50d902SRodney W. Grimes /* 2859b50d902SRodney W. Grimes * dopopdef - remove the topmost 2869b50d902SRodney W. Grimes * definitions of macro(s) or m4 2879b50d902SRodney W. Grimes * keyword(s). 2889b50d902SRodney W. Grimes */ 2899b50d902SRodney W. Grimes if (argc > 2) 2909b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 2919b50d902SRodney W. Grimes remhash(argv[n], TOP); 2929b50d902SRodney W. Grimes break; 2939b50d902SRodney W. Grimes 2949b50d902SRodney W. Grimes case MKTMTYPE: 2959b50d902SRodney W. Grimes /* 2969b50d902SRodney W. Grimes * dotemp - create a temporary file 2979b50d902SRodney W. Grimes */ 2989b50d902SRodney W. Grimes if (argc > 2) 2999b50d902SRodney W. Grimes pbstr(mktemp(argv[2])); 3009b50d902SRodney W. Grimes break; 3019b50d902SRodney W. Grimes 3029b50d902SRodney W. Grimes case TRNLTYPE: 3039b50d902SRodney W. Grimes /* 3049b50d902SRodney W. Grimes * dotranslit - replace all characters in 3059b50d902SRodney W. Grimes * the source string that appears in the 3069b50d902SRodney W. Grimes * "from" string with the corresponding 3079b50d902SRodney W. Grimes * characters in the "to" string. 3089b50d902SRodney W. Grimes */ 3099b50d902SRodney W. Grimes if (argc > 3) { 310ef2cea81SJonathan Lemon char temp[STRSPMAX+1]; 3119b50d902SRodney W. Grimes if (argc > 4) 3129b50d902SRodney W. Grimes map(temp, argv[2], argv[3], argv[4]); 3139b50d902SRodney W. Grimes else 3149b50d902SRodney W. Grimes map(temp, argv[2], argv[3], null); 3159b50d902SRodney W. Grimes pbstr(temp); 3169b50d902SRodney W. Grimes } 3179b50d902SRodney W. Grimes else if (argc > 2) 3189b50d902SRodney W. Grimes pbstr(argv[2]); 3199b50d902SRodney W. Grimes break; 3209b50d902SRodney W. Grimes 3219b50d902SRodney W. Grimes case INDXTYPE: 3229b50d902SRodney W. Grimes /* 3239b50d902SRodney W. Grimes * doindex - find the index of the second 3249b50d902SRodney W. Grimes * argument string in the first argument 3259b50d902SRodney W. Grimes * string. -1 if not present. 3269b50d902SRodney W. Grimes */ 3279b50d902SRodney W. Grimes pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 3289b50d902SRodney W. Grimes break; 3299b50d902SRodney W. Grimes 3309b50d902SRodney W. Grimes case ERRPTYPE: 3319b50d902SRodney W. Grimes /* 3329b50d902SRodney W. Grimes * doerrp - print the arguments to stderr 3339b50d902SRodney W. Grimes * file 3349b50d902SRodney W. Grimes */ 3359b50d902SRodney W. Grimes if (argc > 2) { 3369b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 3379b50d902SRodney W. Grimes fprintf(stderr, "%s ", argv[n]); 3389b50d902SRodney W. Grimes fprintf(stderr, "\n"); 3399b50d902SRodney W. Grimes } 3409b50d902SRodney W. Grimes break; 3419b50d902SRodney W. Grimes 3429b50d902SRodney W. Grimes case DNLNTYPE: 3439b50d902SRodney W. Grimes /* 3449b50d902SRodney W. Grimes * dodnl - eat-up-to and including 3459b50d902SRodney W. Grimes * newline 3469b50d902SRodney W. Grimes */ 3479b50d902SRodney W. Grimes while ((c = gpbc()) != '\n' && c != EOF) 3489b50d902SRodney W. Grimes ; 3499b50d902SRodney W. Grimes break; 3509b50d902SRodney W. Grimes 3519b50d902SRodney W. Grimes case M4WRTYPE: 3529b50d902SRodney W. Grimes /* 3539b50d902SRodney W. Grimes * dom4wrap - set up for 3549b50d902SRodney W. Grimes * wrap-up/wind-down activity 3559b50d902SRodney W. Grimes */ 356de9b3b90SDavid E. O'Brien if ((p = strdup(argv[2])) == NULL) 357de9b3b90SDavid E. O'Brien err(1, "strdup"); 358de9b3b90SDavid E. O'Brien m4wraps = (argc > 2) ? p : null; 3599b50d902SRodney W. Grimes break; 3609b50d902SRodney W. Grimes 3619b50d902SRodney W. Grimes case EXITTYPE: 3629b50d902SRodney W. Grimes /* 3639b50d902SRodney W. Grimes * doexit - immediate exit from m4. 3649b50d902SRodney W. Grimes */ 365cac6992aSAndrey A. Chernov killdiv(); 3669b50d902SRodney W. Grimes exit((argc > 2) ? atoi(argv[2]) : 0); 3679b50d902SRodney W. Grimes break; 3689b50d902SRodney W. Grimes 3699b50d902SRodney W. Grimes case DEFNTYPE: 3709b50d902SRodney W. Grimes if (argc > 2) 3719b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 3729b50d902SRodney W. Grimes dodefn(argv[n]); 3739b50d902SRodney W. Grimes break; 3749b50d902SRodney W. Grimes 375bbfd1447SSteve Price case MACRTYPE: 376bbfd1447SSteve Price pbstr(""); 377bbfd1447SSteve Price break; 378bbfd1447SSteve Price 3799b50d902SRodney W. Grimes default: 38095105358SPhilippe Charnier errx(1, "eval: major botch"); 3819b50d902SRodney W. Grimes break; 3829b50d902SRodney W. Grimes } 3839b50d902SRodney W. Grimes } 3849b50d902SRodney W. Grimes 38550d793ebSKris Kennaway const char dumpfmt[] = "`%s'\t`%s'\n"; /* format string for dumpdef */ 3869b50d902SRodney W. Grimes 3879b50d902SRodney W. Grimes /* 3889b50d902SRodney W. Grimes * expand - user-defined macro expansion 3899b50d902SRodney W. Grimes */ 3909b50d902SRodney W. Grimes void 3919b50d902SRodney W. Grimes expand(argv, argc) 3929b50d902SRodney W. Grimes register char *argv[]; 3939b50d902SRodney W. Grimes register int argc; 3949b50d902SRodney W. Grimes { 3957c5eeb39SAndrey A. Chernov register unsigned char *t; 3967c5eeb39SAndrey A. Chernov register unsigned char *p; 3979b50d902SRodney W. Grimes register int n; 3989b50d902SRodney W. Grimes register int argno; 3999b50d902SRodney W. Grimes 4009b50d902SRodney W. Grimes t = argv[0]; /* defn string as a whole */ 4019b50d902SRodney W. Grimes p = t; 4029b50d902SRodney W. Grimes while (*p) 4039b50d902SRodney W. Grimes p++; 4049b50d902SRodney W. Grimes p--; /* last character of defn */ 4059b50d902SRodney W. Grimes while (p > t) { 4069b50d902SRodney W. Grimes if (*(p - 1) != ARGFLAG) 4079b50d902SRodney W. Grimes putback(*p); 4089b50d902SRodney W. Grimes else { 4099b50d902SRodney W. Grimes switch (*p) { 4109b50d902SRodney W. Grimes 4119b50d902SRodney W. Grimes case '#': 4129b50d902SRodney W. Grimes pbnum(argc - 2); 4139b50d902SRodney W. Grimes break; 4149b50d902SRodney W. Grimes case '0': 4159b50d902SRodney W. Grimes case '1': 4169b50d902SRodney W. Grimes case '2': 4179b50d902SRodney W. Grimes case '3': 4189b50d902SRodney W. Grimes case '4': 4199b50d902SRodney W. Grimes case '5': 4209b50d902SRodney W. Grimes case '6': 4219b50d902SRodney W. Grimes case '7': 4229b50d902SRodney W. Grimes case '8': 4239b50d902SRodney W. Grimes case '9': 4249b50d902SRodney W. Grimes if ((argno = *p - '0') < argc - 1) 4259b50d902SRodney W. Grimes pbstr(argv[argno + 1]); 4269b50d902SRodney W. Grimes break; 4279b50d902SRodney W. Grimes case '*': 4289b50d902SRodney W. Grimes for (n = argc - 1; n > 2; n--) { 4299b50d902SRodney W. Grimes pbstr(argv[n]); 4309b50d902SRodney W. Grimes putback(','); 4319b50d902SRodney W. Grimes } 4329b50d902SRodney W. Grimes pbstr(argv[2]); 4339b50d902SRodney W. Grimes break; 434232eaee6SJoerg Wunsch case '@': 435232eaee6SJoerg Wunsch for( n = argc - 1; n >= 2; n-- ) 436232eaee6SJoerg Wunsch { 437232eaee6SJoerg Wunsch putback(rquote); 438232eaee6SJoerg Wunsch pbstr(argv[n]); 439232eaee6SJoerg Wunsch putback(lquote); 440232eaee6SJoerg Wunsch if( n > 2 ) 441232eaee6SJoerg Wunsch putback(','); 442232eaee6SJoerg Wunsch } 443232eaee6SJoerg Wunsch break; 4449b50d902SRodney W. Grimes default: 4459b50d902SRodney W. Grimes putback(*p); 4469b50d902SRodney W. Grimes putback('$'); 4479b50d902SRodney W. Grimes break; 4489b50d902SRodney W. Grimes } 4499b50d902SRodney W. Grimes p--; 4509b50d902SRodney W. Grimes } 4519b50d902SRodney W. Grimes p--; 4529b50d902SRodney W. Grimes } 4539b50d902SRodney W. Grimes if (p == t) /* do last character */ 4549b50d902SRodney W. Grimes putback(*p); 4559b50d902SRodney W. Grimes } 4569b50d902SRodney W. Grimes 4579b50d902SRodney W. Grimes /* 4589b50d902SRodney W. Grimes * dodefine - install definition in the table 4599b50d902SRodney W. Grimes */ 4609b50d902SRodney W. Grimes void 4619b50d902SRodney W. Grimes dodefine(name, defn) 4629b50d902SRodney W. Grimes register char *name; 4639b50d902SRodney W. Grimes register char *defn; 4649b50d902SRodney W. Grimes { 4659b50d902SRodney W. Grimes register ndptr p; 4669b50d902SRodney W. Grimes 4679b50d902SRodney W. Grimes if (!*name) 46895105358SPhilippe Charnier errx(1, "null definition"); 4699b50d902SRodney W. Grimes if (STREQ(name, defn)) 47095105358SPhilippe Charnier errx(1, "%s: recursive definition", name); 4719b50d902SRodney W. Grimes if ((p = lookup(name)) == nil) 4729b50d902SRodney W. Grimes p = addent(name); 4739b50d902SRodney W. Grimes else if (p->defn != null) 4749b50d902SRodney W. Grimes free((char *) p->defn); 4759b50d902SRodney W. Grimes if (!*defn) 4769b50d902SRodney W. Grimes p->defn = null; 4779b50d902SRodney W. Grimes else 478de9b3b90SDavid E. O'Brien if ((p->defn = strdup(defn)) == NULL) 479de9b3b90SDavid E. O'Brien err(1, "strdup"); 4809b50d902SRodney W. Grimes p->type = MACRTYPE; 4819b50d902SRodney W. Grimes } 4829b50d902SRodney W. Grimes 4839b50d902SRodney W. Grimes /* 4849b50d902SRodney W. Grimes * dodefn - push back a quoted definition of 4859b50d902SRodney W. Grimes * the given name. 4869b50d902SRodney W. Grimes */ 4879b50d902SRodney W. Grimes void 4889b50d902SRodney W. Grimes dodefn(name) 4899b50d902SRodney W. Grimes char *name; 4909b50d902SRodney W. Grimes { 4919b50d902SRodney W. Grimes register ndptr p; 4929b50d902SRodney W. Grimes 4939b50d902SRodney W. Grimes if ((p = lookup(name)) != nil && p->defn != null) { 4949b50d902SRodney W. Grimes putback(rquote); 4959b50d902SRodney W. Grimes pbstr(p->defn); 4969b50d902SRodney W. Grimes putback(lquote); 4979b50d902SRodney W. Grimes } 4989b50d902SRodney W. Grimes } 4999b50d902SRodney W. Grimes 5009b50d902SRodney W. Grimes /* 5019b50d902SRodney W. Grimes * dopushdef - install a definition in the hash table 5029b50d902SRodney W. Grimes * without removing a previous definition. Since 5039b50d902SRodney W. Grimes * each new entry is entered in *front* of the 5049b50d902SRodney W. Grimes * hash bucket, it hides a previous definition from 5059b50d902SRodney W. Grimes * lookup. 5069b50d902SRodney W. Grimes */ 5079b50d902SRodney W. Grimes void 5089b50d902SRodney W. Grimes dopushdef(name, defn) 5099b50d902SRodney W. Grimes register char *name; 5109b50d902SRodney W. Grimes register char *defn; 5119b50d902SRodney W. Grimes { 5129b50d902SRodney W. Grimes register ndptr p; 5139b50d902SRodney W. Grimes 5149b50d902SRodney W. Grimes if (!*name) 51595105358SPhilippe Charnier errx(1, "null definition"); 5169b50d902SRodney W. Grimes if (STREQ(name, defn)) 51795105358SPhilippe Charnier errx(1, "%s: recursive definition", name); 5189b50d902SRodney W. Grimes p = addent(name); 5199b50d902SRodney W. Grimes if (!*defn) 5209b50d902SRodney W. Grimes p->defn = null; 5219b50d902SRodney W. Grimes else 522de9b3b90SDavid E. O'Brien if ((p->defn = strdup(defn)) == NULL) 523de9b3b90SDavid E. O'Brien err(1, "strdup"); 5249b50d902SRodney W. Grimes p->type = MACRTYPE; 5259b50d902SRodney W. Grimes } 5269b50d902SRodney W. Grimes 5279b50d902SRodney W. Grimes /* 5289b50d902SRodney W. Grimes * dodumpdef - dump the specified definitions in the hash 5299b50d902SRodney W. Grimes * table to stderr. If nothing is specified, the entire 5309b50d902SRodney W. Grimes * hash table is dumped. 5319b50d902SRodney W. Grimes */ 5329b50d902SRodney W. Grimes void 5339b50d902SRodney W. Grimes dodump(argv, argc) 5349b50d902SRodney W. Grimes register char *argv[]; 5359b50d902SRodney W. Grimes register int argc; 5369b50d902SRodney W. Grimes { 5379b50d902SRodney W. Grimes register int n; 5389b50d902SRodney W. Grimes ndptr p; 5399b50d902SRodney W. Grimes 5409b50d902SRodney W. Grimes if (argc > 2) { 5419b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 5429b50d902SRodney W. Grimes if ((p = lookup(argv[n])) != nil) 5439b50d902SRodney W. Grimes fprintf(stderr, dumpfmt, p->name, 5449b50d902SRodney W. Grimes p->defn); 5459b50d902SRodney W. Grimes } 5469b50d902SRodney W. Grimes else { 5479b50d902SRodney W. Grimes for (n = 0; n < HASHSIZE; n++) 5489b50d902SRodney W. Grimes for (p = hashtab[n]; p != nil; p = p->nxtptr) 5499b50d902SRodney W. Grimes fprintf(stderr, dumpfmt, p->name, 5509b50d902SRodney W. Grimes p->defn); 5519b50d902SRodney W. Grimes } 5529b50d902SRodney W. Grimes } 5539b50d902SRodney W. Grimes 5549b50d902SRodney W. Grimes /* 5559b50d902SRodney W. Grimes * doifelse - select one of two alternatives - loop. 5569b50d902SRodney W. Grimes */ 5579b50d902SRodney W. Grimes void 5589b50d902SRodney W. Grimes doifelse(argv, argc) 5599b50d902SRodney W. Grimes register char *argv[]; 5609b50d902SRodney W. Grimes register int argc; 5619b50d902SRodney W. Grimes { 5629b50d902SRodney W. Grimes cycle { 5639b50d902SRodney W. Grimes if (STREQ(argv[2], argv[3])) 5649b50d902SRodney W. Grimes pbstr(argv[4]); 5659b50d902SRodney W. Grimes else if (argc == 6) 5669b50d902SRodney W. Grimes pbstr(argv[5]); 5679b50d902SRodney W. Grimes else if (argc > 6) { 5689b50d902SRodney W. Grimes argv += 3; 5699b50d902SRodney W. Grimes argc -= 3; 5709b50d902SRodney W. Grimes continue; 5719b50d902SRodney W. Grimes } 5729b50d902SRodney W. Grimes break; 5739b50d902SRodney W. Grimes } 5749b50d902SRodney W. Grimes } 5759b50d902SRodney W. Grimes 5769b50d902SRodney W. Grimes /* 5779b50d902SRodney W. Grimes * doinclude - include a given file. 5789b50d902SRodney W. Grimes */ 5799b50d902SRodney W. Grimes int 5809b50d902SRodney W. Grimes doincl(ifile) 5819b50d902SRodney W. Grimes char *ifile; 5829b50d902SRodney W. Grimes { 5839b50d902SRodney W. Grimes if (ilevel + 1 == MAXINP) 58495105358SPhilippe Charnier errx(1, "too many include files"); 5859b50d902SRodney W. Grimes if ((infile[ilevel + 1] = fopen(ifile, "r")) != NULL) { 5869b50d902SRodney W. Grimes ilevel++; 587b1ea3d46SJuli Mallett if ((inname[ilevel] = strdup(ifile)) == NULL) 588b1ea3d46SJuli Mallett err(1, NULL); 589b1ea3d46SJuli Mallett inlineno[ilevel] = 1; 5909b50d902SRodney W. Grimes bbase[ilevel] = bufbase = bp; 591b1ea3d46SJuli Mallett emitline(); 5929b50d902SRodney W. Grimes return (1); 5939b50d902SRodney W. Grimes } 5949b50d902SRodney W. Grimes else 5959b50d902SRodney W. Grimes return (0); 5969b50d902SRodney W. Grimes } 5979b50d902SRodney W. Grimes 5989b50d902SRodney W. Grimes #ifdef EXTENDED 5999b50d902SRodney W. Grimes /* 6009b50d902SRodney W. Grimes * dopaste - include a given file without any 6019b50d902SRodney W. Grimes * macro processing. 6029b50d902SRodney W. Grimes */ 6039b50d902SRodney W. Grimes int 6049b50d902SRodney W. Grimes dopaste(pfile) 6059b50d902SRodney W. Grimes char *pfile; 6069b50d902SRodney W. Grimes { 6079b50d902SRodney W. Grimes FILE *pf; 6089b50d902SRodney W. Grimes register int c; 6099b50d902SRodney W. Grimes 6109b50d902SRodney W. Grimes if ((pf = fopen(pfile, "r")) != NULL) { 611b1ea3d46SJuli Mallett fprintf(active, "#line 1 \"%s\"\n", pfile); 6129b50d902SRodney W. Grimes while ((c = getc(pf)) != EOF) 6139b50d902SRodney W. Grimes putc(c, active); 6149b50d902SRodney W. Grimes (void) fclose(pf); 615b1ea3d46SJuli Mallett emitline(); 6169b50d902SRodney W. Grimes return (1); 6179b50d902SRodney W. Grimes } 6189b50d902SRodney W. Grimes else 6199b50d902SRodney W. Grimes return (0); 6209b50d902SRodney W. Grimes } 6219b50d902SRodney W. Grimes #endif 6229b50d902SRodney W. Grimes 6239b50d902SRodney W. Grimes /* 6249b50d902SRodney W. Grimes * dochq - change quote characters 6259b50d902SRodney W. Grimes */ 6269b50d902SRodney W. Grimes void 6279b50d902SRodney W. Grimes dochq(argv, argc) 6289b50d902SRodney W. Grimes register char *argv[]; 6299b50d902SRodney W. Grimes register int argc; 6309b50d902SRodney W. Grimes { 6319b50d902SRodney W. Grimes if (argc > 2) { 6329b50d902SRodney W. Grimes if (*argv[2]) 6339b50d902SRodney W. Grimes lquote = *argv[2]; 634ef2cea81SJonathan Lemon else 635ef2cea81SJonathan Lemon lquote = LQUOTE; 6369b50d902SRodney W. Grimes if (argc > 3) { 6379b50d902SRodney W. Grimes if (*argv[3]) 6389b50d902SRodney W. Grimes rquote = *argv[3]; 639ef2cea81SJonathan Lemon else 640ef2cea81SJonathan Lemon rquote = RQUOTE; 6419b50d902SRodney W. Grimes } 6429b50d902SRodney W. Grimes else 6439b50d902SRodney W. Grimes rquote = lquote; 6449b50d902SRodney W. Grimes } 6459b50d902SRodney W. Grimes else { 6469b50d902SRodney W. Grimes lquote = LQUOTE; 6479b50d902SRodney W. Grimes rquote = RQUOTE; 6489b50d902SRodney W. Grimes } 6499b50d902SRodney W. Grimes } 6509b50d902SRodney W. Grimes 6519b50d902SRodney W. Grimes /* 6529b50d902SRodney W. Grimes * dochc - change comment characters 6539b50d902SRodney W. Grimes */ 6549b50d902SRodney W. Grimes void 6559b50d902SRodney W. Grimes dochc(argv, argc) 6569b50d902SRodney W. Grimes register char *argv[]; 6579b50d902SRodney W. Grimes register int argc; 6589b50d902SRodney W. Grimes { 6599b50d902SRodney W. Grimes if (argc > 2) { 6609b50d902SRodney W. Grimes if (*argv[2]) 6619b50d902SRodney W. Grimes scommt = *argv[2]; 6629b50d902SRodney W. Grimes if (argc > 3) { 6639b50d902SRodney W. Grimes if (*argv[3]) 6649b50d902SRodney W. Grimes ecommt = *argv[3]; 6659b50d902SRodney W. Grimes } 6669b50d902SRodney W. Grimes else 6679b50d902SRodney W. Grimes ecommt = ECOMMT; 6689b50d902SRodney W. Grimes } 6699b50d902SRodney W. Grimes else { 6709b50d902SRodney W. Grimes scommt = SCOMMT; 6719b50d902SRodney W. Grimes ecommt = ECOMMT; 6729b50d902SRodney W. Grimes } 6739b50d902SRodney W. Grimes } 6749b50d902SRodney W. Grimes 6759b50d902SRodney W. Grimes /* 6769b50d902SRodney W. Grimes * dodivert - divert the output to a temporary file 6779b50d902SRodney W. Grimes */ 6789b50d902SRodney W. Grimes void 6799b50d902SRodney W. Grimes dodiv(n) 6809b50d902SRodney W. Grimes register int n; 6819b50d902SRodney W. Grimes { 682ef2cea81SJonathan Lemon oindex = n; 6839b50d902SRodney W. Grimes if (n < 0 || n >= MAXOUT) 6849b50d902SRodney W. Grimes n = 0; /* bitbucket */ 6859b50d902SRodney W. Grimes if (outfile[n] == NULL) { 6869b50d902SRodney W. Grimes m4temp[UNIQUE] = n + '0'; 6879b50d902SRodney W. Grimes if ((outfile[n] = fopen(m4temp, "w")) == NULL) 68895105358SPhilippe Charnier errx(1, "%s: cannot divert", m4temp); 6899b50d902SRodney W. Grimes } 6909b50d902SRodney W. Grimes active = outfile[n]; 6919b50d902SRodney W. Grimes } 6929b50d902SRodney W. Grimes 6939b50d902SRodney W. Grimes /* 6949b50d902SRodney W. Grimes * doundivert - undivert a specified output, or all 6959b50d902SRodney W. Grimes * other outputs, in numerical order. 6969b50d902SRodney W. Grimes */ 6979b50d902SRodney W. Grimes void 6989b50d902SRodney W. Grimes doundiv(argv, argc) 6999b50d902SRodney W. Grimes register char *argv[]; 7009b50d902SRodney W. Grimes register int argc; 7019b50d902SRodney W. Grimes { 7029b50d902SRodney W. Grimes register int ind; 7039b50d902SRodney W. Grimes register int n; 7049b50d902SRodney W. Grimes 7059b50d902SRodney W. Grimes if (argc > 2) { 7069b50d902SRodney W. Grimes for (ind = 2; ind < argc; ind++) { 7079b50d902SRodney W. Grimes n = atoi(argv[ind]); 7089b50d902SRodney W. Grimes if (n > 0 && n < MAXOUT && outfile[n] != NULL) 7099b50d902SRodney W. Grimes getdiv(n); 7109b50d902SRodney W. Grimes 7119b50d902SRodney W. Grimes } 7129b50d902SRodney W. Grimes } 7139b50d902SRodney W. Grimes else 7149b50d902SRodney W. Grimes for (n = 1; n < MAXOUT; n++) 7159b50d902SRodney W. Grimes if (outfile[n] != NULL) 7169b50d902SRodney W. Grimes getdiv(n); 7179b50d902SRodney W. Grimes } 7189b50d902SRodney W. Grimes 7199b50d902SRodney W. Grimes /* 7209b50d902SRodney W. Grimes * dosub - select substring 7219b50d902SRodney W. Grimes */ 7229b50d902SRodney W. Grimes void 7239b50d902SRodney W. Grimes dosub(argv, argc) 7249b50d902SRodney W. Grimes register char *argv[]; 7259b50d902SRodney W. Grimes register int argc; 7269b50d902SRodney W. Grimes { 7277c5eeb39SAndrey A. Chernov register unsigned char *ap, *fc, *k; 7289b50d902SRodney W. Grimes register int nc; 7299b50d902SRodney W. Grimes 7309b50d902SRodney W. Grimes ap = argv[2]; /* target string */ 7319b50d902SRodney W. Grimes #ifdef EXPR 7329b50d902SRodney W. Grimes fc = ap + expr(argv[3]); /* first char */ 7339b50d902SRodney W. Grimes #else 7349b50d902SRodney W. Grimes fc = ap + atoi(argv[3]); /* first char */ 7359b50d902SRodney W. Grimes #endif 7364ba4d387SGregory Neil Shapiro if (argc < 5) 7374ba4d387SGregory Neil Shapiro nc = strlen(fc); 7384ba4d387SGregory Neil Shapiro else 7394ba4d387SGregory Neil Shapiro #ifdef EXPR 7404ba4d387SGregory Neil Shapiro nc = expr(argv[4]); 7414ba4d387SGregory Neil Shapiro #else 7424ba4d387SGregory Neil Shapiro nc = atoi(argv[4]); 7434ba4d387SGregory Neil Shapiro #endif 7449b50d902SRodney W. Grimes if (fc >= ap && fc < ap + strlen(ap)) 7454ba4d387SGregory Neil Shapiro for (k = fc + nc - 1; k >= fc; k--) 7469b50d902SRodney W. Grimes putback(*k); 7479b50d902SRodney W. Grimes } 7489b50d902SRodney W. Grimes 7499b50d902SRodney W. Grimes /* 7509b50d902SRodney W. Grimes * map: 7519b50d902SRodney W. Grimes * map every character of s1 that is specified in from 7529b50d902SRodney W. Grimes * into s3 and replace in s. (source s1 remains untouched) 7539b50d902SRodney W. Grimes * 7549b50d902SRodney W. Grimes * This is a standard implementation of map(s,from,to) function of ICON 7559b50d902SRodney W. Grimes * language. Within mapvec, we replace every character of "from" with 7569b50d902SRodney W. Grimes * the corresponding character in "to". If "to" is shorter than "from", 7579b50d902SRodney W. Grimes * than the corresponding entries are null, which means that those 7589b50d902SRodney W. Grimes * characters dissapear altogether. Furthermore, imagine 7599b50d902SRodney W. Grimes * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case, 7609b50d902SRodney W. Grimes * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s' 7619b50d902SRodney W. Grimes * ultimately maps to `*'. In order to achieve this effect in an efficient 7629b50d902SRodney W. Grimes * manner (i.e. without multiple passes over the destination string), we 7639b50d902SRodney W. Grimes * loop over mapvec, starting with the initial source character. if the 7649b50d902SRodney W. Grimes * character value (dch) in this location is different than the source 7659b50d902SRodney W. Grimes * character (sch), sch becomes dch, once again to index into mapvec, until 7669b50d902SRodney W. Grimes * the character value stabilizes (i.e. sch = dch, in other words 7679b50d902SRodney W. Grimes * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary 7689b50d902SRodney W. Grimes * character, it will stabilize, since mapvec[0] == 0 at all times. At the 7699b50d902SRodney W. Grimes * end, we restore mapvec* back to normal where mapvec[n] == n for 7709b50d902SRodney W. Grimes * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is 7719b50d902SRodney W. Grimes * about 5 times faster than any algorithm that makes multiple passes over 7729b50d902SRodney W. Grimes * destination string. 7739b50d902SRodney W. Grimes */ 7749b50d902SRodney W. Grimes void 7759b50d902SRodney W. Grimes map(dest, src, from, to) 7769b50d902SRodney W. Grimes register char *dest; 7779b50d902SRodney W. Grimes register char *src; 7789b50d902SRodney W. Grimes register char *from; 7799b50d902SRodney W. Grimes register char *to; 7809b50d902SRodney W. Grimes { 7819b50d902SRodney W. Grimes register char *tmp; 7829b50d902SRodney W. Grimes register char sch, dch; 7839b50d902SRodney W. Grimes static char mapvec[128] = { 7849b50d902SRodney W. Grimes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 7859b50d902SRodney W. Grimes 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 7869b50d902SRodney W. Grimes 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 7879b50d902SRodney W. Grimes 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 7889b50d902SRodney W. Grimes 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 7899b50d902SRodney W. Grimes 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 7909b50d902SRodney W. Grimes 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 7919b50d902SRodney W. Grimes 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 7929b50d902SRodney W. Grimes 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 7939b50d902SRodney W. Grimes 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 7949b50d902SRodney W. Grimes 120, 121, 122, 123, 124, 125, 126, 127 7959b50d902SRodney W. Grimes }; 7969b50d902SRodney W. Grimes 7979b50d902SRodney W. Grimes if (*src) { 7989b50d902SRodney W. Grimes tmp = from; 7999b50d902SRodney W. Grimes /* 8009b50d902SRodney W. Grimes * create a mapping between "from" and 8019b50d902SRodney W. Grimes * "to" 8029b50d902SRodney W. Grimes */ 8039b50d902SRodney W. Grimes while (*from) 8049b50d902SRodney W. Grimes mapvec[*from++] = (*to) ? *to++ : (char) 0; 8059b50d902SRodney W. Grimes 8069b50d902SRodney W. Grimes while (*src) { 8079b50d902SRodney W. Grimes sch = *src++; 8089b50d902SRodney W. Grimes dch = mapvec[sch]; 8099b50d902SRodney W. Grimes while (dch != sch) { 8109b50d902SRodney W. Grimes sch = dch; 8119b50d902SRodney W. Grimes dch = mapvec[sch]; 8129b50d902SRodney W. Grimes } 8139b50d902SRodney W. Grimes if (*dest = dch) 8149b50d902SRodney W. Grimes dest++; 8159b50d902SRodney W. Grimes } 8169b50d902SRodney W. Grimes /* 8179b50d902SRodney W. Grimes * restore all the changed characters 8189b50d902SRodney W. Grimes */ 8199b50d902SRodney W. Grimes while (*tmp) { 8209b50d902SRodney W. Grimes mapvec[*tmp] = *tmp; 8219b50d902SRodney W. Grimes tmp++; 8229b50d902SRodney W. Grimes } 8239b50d902SRodney W. Grimes } 8249b50d902SRodney W. Grimes *dest = (char) 0; 8259b50d902SRodney W. Grimes } 826