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; 899b50d902SRodney W. Grimes 909b50d902SRodney W. Grimes #ifdef DEBUG 919b50d902SRodney W. Grimes printf("argc = %d\n", argc); 929b50d902SRodney W. Grimes for (n = 0; n < argc; n++) 939b50d902SRodney W. Grimes printf("argv[%d] = %s\n", n, argv[n]); 949b50d902SRodney W. Grimes #endif 959b50d902SRodney W. Grimes /* 969b50d902SRodney W. Grimes * if argc == 3 and argv[2] is null, then we 979b50d902SRodney W. Grimes * have macro-or-builtin() type call. We adjust 989b50d902SRodney W. Grimes * argc to avoid further checking.. 999b50d902SRodney W. Grimes */ 1009b50d902SRodney W. Grimes if (argc == 3 && !*(argv[2])) 1019b50d902SRodney W. Grimes argc--; 1029b50d902SRodney W. Grimes 1039b50d902SRodney W. Grimes switch (td & ~STATIC) { 1049b50d902SRodney W. Grimes 1059b50d902SRodney W. Grimes case DEFITYPE: 1069b50d902SRodney W. Grimes if (argc > 2) 1079b50d902SRodney W. Grimes dodefine(argv[2], (argc > 3) ? argv[3] : null); 1089b50d902SRodney W. Grimes break; 1099b50d902SRodney W. Grimes 1109b50d902SRodney W. Grimes case PUSDTYPE: 1119b50d902SRodney W. Grimes if (argc > 2) 1129b50d902SRodney W. Grimes dopushdef(argv[2], (argc > 3) ? argv[3] : null); 1139b50d902SRodney W. Grimes break; 1149b50d902SRodney W. Grimes 1159b50d902SRodney W. Grimes case DUMPTYPE: 1169b50d902SRodney W. Grimes dodump(argv, argc); 1179b50d902SRodney W. Grimes break; 1189b50d902SRodney W. Grimes 1199b50d902SRodney W. Grimes case EXPRTYPE: 1209b50d902SRodney W. Grimes /* 1219b50d902SRodney W. Grimes * doexpr - evaluate arithmetic 1229b50d902SRodney W. Grimes * expression 1239b50d902SRodney W. Grimes */ 1249b50d902SRodney W. Grimes if (argc > 2) 1259b50d902SRodney W. Grimes pbnum(expr(argv[2])); 1269b50d902SRodney W. Grimes break; 1279b50d902SRodney W. Grimes 1289b50d902SRodney W. Grimes case IFELTYPE: 1299b50d902SRodney W. Grimes if (argc > 4) 1309b50d902SRodney W. Grimes doifelse(argv, argc); 1319b50d902SRodney W. Grimes break; 1329b50d902SRodney W. Grimes 1339b50d902SRodney W. Grimes case IFDFTYPE: 1349b50d902SRodney W. Grimes /* 1359b50d902SRodney W. Grimes * doifdef - select one of two 1369b50d902SRodney W. Grimes * alternatives based on the existence of 1379b50d902SRodney W. Grimes * another definition 1389b50d902SRodney W. Grimes */ 1399b50d902SRodney W. Grimes if (argc > 3) { 1409b50d902SRodney W. Grimes if (lookup(argv[2]) != nil) 1419b50d902SRodney W. Grimes pbstr(argv[3]); 1429b50d902SRodney W. Grimes else if (argc > 4) 1439b50d902SRodney W. Grimes pbstr(argv[4]); 1449b50d902SRodney W. Grimes } 1459b50d902SRodney W. Grimes break; 1469b50d902SRodney W. Grimes 1479b50d902SRodney W. Grimes case LENGTYPE: 1489b50d902SRodney W. Grimes /* 1499b50d902SRodney W. Grimes * dolen - find the length of the 1509b50d902SRodney W. Grimes * argument 1519b50d902SRodney W. Grimes */ 1529b50d902SRodney W. Grimes if (argc > 2) 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 */ 3569b50d902SRodney W. Grimes m4wraps = (argc > 2) ? xstrdup(argv[2]) : null; 3579b50d902SRodney W. Grimes break; 3589b50d902SRodney W. Grimes 3599b50d902SRodney W. Grimes case EXITTYPE: 3609b50d902SRodney W. Grimes /* 3619b50d902SRodney W. Grimes * doexit - immediate exit from m4. 3629b50d902SRodney W. Grimes */ 363cac6992aSAndrey A. Chernov killdiv(); 3649b50d902SRodney W. Grimes exit((argc > 2) ? atoi(argv[2]) : 0); 3659b50d902SRodney W. Grimes break; 3669b50d902SRodney W. Grimes 3679b50d902SRodney W. Grimes case DEFNTYPE: 3689b50d902SRodney W. Grimes if (argc > 2) 3699b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 3709b50d902SRodney W. Grimes dodefn(argv[n]); 3719b50d902SRodney W. Grimes break; 3729b50d902SRodney W. Grimes 373bbfd1447SSteve Price case MACRTYPE: 374bbfd1447SSteve Price pbstr(""); 375bbfd1447SSteve Price break; 376bbfd1447SSteve Price 3779b50d902SRodney W. Grimes default: 37895105358SPhilippe Charnier errx(1, "eval: major botch"); 3799b50d902SRodney W. Grimes break; 3809b50d902SRodney W. Grimes } 3819b50d902SRodney W. Grimes } 3829b50d902SRodney W. Grimes 38350d793ebSKris Kennaway const char dumpfmt[] = "`%s'\t`%s'\n"; /* format string for dumpdef */ 3849b50d902SRodney W. Grimes 3859b50d902SRodney W. Grimes /* 3869b50d902SRodney W. Grimes * expand - user-defined macro expansion 3879b50d902SRodney W. Grimes */ 3889b50d902SRodney W. Grimes void 3899b50d902SRodney W. Grimes expand(argv, argc) 3909b50d902SRodney W. Grimes register char *argv[]; 3919b50d902SRodney W. Grimes register int argc; 3929b50d902SRodney W. Grimes { 3937c5eeb39SAndrey A. Chernov register unsigned char *t; 3947c5eeb39SAndrey A. Chernov register unsigned char *p; 3959b50d902SRodney W. Grimes register int n; 3969b50d902SRodney W. Grimes register int argno; 3979b50d902SRodney W. Grimes 3989b50d902SRodney W. Grimes t = argv[0]; /* defn string as a whole */ 3999b50d902SRodney W. Grimes p = t; 4009b50d902SRodney W. Grimes while (*p) 4019b50d902SRodney W. Grimes p++; 4029b50d902SRodney W. Grimes p--; /* last character of defn */ 4039b50d902SRodney W. Grimes while (p > t) { 4049b50d902SRodney W. Grimes if (*(p - 1) != ARGFLAG) 4059b50d902SRodney W. Grimes putback(*p); 4069b50d902SRodney W. Grimes else { 4079b50d902SRodney W. Grimes switch (*p) { 4089b50d902SRodney W. Grimes 4099b50d902SRodney W. Grimes case '#': 4109b50d902SRodney W. Grimes pbnum(argc - 2); 4119b50d902SRodney W. Grimes break; 4129b50d902SRodney W. Grimes case '0': 4139b50d902SRodney W. Grimes case '1': 4149b50d902SRodney W. Grimes case '2': 4159b50d902SRodney W. Grimes case '3': 4169b50d902SRodney W. Grimes case '4': 4179b50d902SRodney W. Grimes case '5': 4189b50d902SRodney W. Grimes case '6': 4199b50d902SRodney W. Grimes case '7': 4209b50d902SRodney W. Grimes case '8': 4219b50d902SRodney W. Grimes case '9': 4229b50d902SRodney W. Grimes if ((argno = *p - '0') < argc - 1) 4239b50d902SRodney W. Grimes pbstr(argv[argno + 1]); 4249b50d902SRodney W. Grimes break; 4259b50d902SRodney W. Grimes case '*': 4269b50d902SRodney W. Grimes for (n = argc - 1; n > 2; n--) { 4279b50d902SRodney W. Grimes pbstr(argv[n]); 4289b50d902SRodney W. Grimes putback(','); 4299b50d902SRodney W. Grimes } 4309b50d902SRodney W. Grimes pbstr(argv[2]); 4319b50d902SRodney W. Grimes break; 432232eaee6SJoerg Wunsch case '@': 433232eaee6SJoerg Wunsch for( n = argc - 1; n >= 2; n-- ) 434232eaee6SJoerg Wunsch { 435232eaee6SJoerg Wunsch putback(rquote); 436232eaee6SJoerg Wunsch pbstr(argv[n]); 437232eaee6SJoerg Wunsch putback(lquote); 438232eaee6SJoerg Wunsch if( n > 2 ) 439232eaee6SJoerg Wunsch putback(','); 440232eaee6SJoerg Wunsch } 441232eaee6SJoerg Wunsch break; 4429b50d902SRodney W. Grimes default: 4439b50d902SRodney W. Grimes putback(*p); 4449b50d902SRodney W. Grimes putback('$'); 4459b50d902SRodney W. Grimes break; 4469b50d902SRodney W. Grimes } 4479b50d902SRodney W. Grimes p--; 4489b50d902SRodney W. Grimes } 4499b50d902SRodney W. Grimes p--; 4509b50d902SRodney W. Grimes } 4519b50d902SRodney W. Grimes if (p == t) /* do last character */ 4529b50d902SRodney W. Grimes putback(*p); 4539b50d902SRodney W. Grimes } 4549b50d902SRodney W. Grimes 4559b50d902SRodney W. Grimes /* 4569b50d902SRodney W. Grimes * dodefine - install definition in the table 4579b50d902SRodney W. Grimes */ 4589b50d902SRodney W. Grimes void 4599b50d902SRodney W. Grimes dodefine(name, defn) 4609b50d902SRodney W. Grimes register char *name; 4619b50d902SRodney W. Grimes register char *defn; 4629b50d902SRodney W. Grimes { 4639b50d902SRodney W. Grimes register ndptr p; 4649b50d902SRodney W. Grimes 4659b50d902SRodney W. Grimes if (!*name) 46695105358SPhilippe Charnier errx(1, "null definition"); 4679b50d902SRodney W. Grimes if (STREQ(name, defn)) 46895105358SPhilippe Charnier errx(1, "%s: recursive definition", name); 4699b50d902SRodney W. Grimes if ((p = lookup(name)) == nil) 4709b50d902SRodney W. Grimes p = addent(name); 4719b50d902SRodney W. Grimes else if (p->defn != null) 4729b50d902SRodney W. Grimes free((char *) p->defn); 4739b50d902SRodney W. Grimes if (!*defn) 4749b50d902SRodney W. Grimes p->defn = null; 4759b50d902SRodney W. Grimes else 4769b50d902SRodney W. Grimes p->defn = xstrdup(defn); 4779b50d902SRodney W. Grimes p->type = MACRTYPE; 4789b50d902SRodney W. Grimes } 4799b50d902SRodney W. Grimes 4809b50d902SRodney W. Grimes /* 4819b50d902SRodney W. Grimes * dodefn - push back a quoted definition of 4829b50d902SRodney W. Grimes * the given name. 4839b50d902SRodney W. Grimes */ 4849b50d902SRodney W. Grimes void 4859b50d902SRodney W. Grimes dodefn(name) 4869b50d902SRodney W. Grimes char *name; 4879b50d902SRodney W. Grimes { 4889b50d902SRodney W. Grimes register ndptr p; 4899b50d902SRodney W. Grimes 4909b50d902SRodney W. Grimes if ((p = lookup(name)) != nil && p->defn != null) { 4919b50d902SRodney W. Grimes putback(rquote); 4929b50d902SRodney W. Grimes pbstr(p->defn); 4939b50d902SRodney W. Grimes putback(lquote); 4949b50d902SRodney W. Grimes } 4959b50d902SRodney W. Grimes } 4969b50d902SRodney W. Grimes 4979b50d902SRodney W. Grimes /* 4989b50d902SRodney W. Grimes * dopushdef - install a definition in the hash table 4999b50d902SRodney W. Grimes * without removing a previous definition. Since 5009b50d902SRodney W. Grimes * each new entry is entered in *front* of the 5019b50d902SRodney W. Grimes * hash bucket, it hides a previous definition from 5029b50d902SRodney W. Grimes * lookup. 5039b50d902SRodney W. Grimes */ 5049b50d902SRodney W. Grimes void 5059b50d902SRodney W. Grimes dopushdef(name, defn) 5069b50d902SRodney W. Grimes register char *name; 5079b50d902SRodney W. Grimes register char *defn; 5089b50d902SRodney W. Grimes { 5099b50d902SRodney W. Grimes register ndptr p; 5109b50d902SRodney W. Grimes 5119b50d902SRodney W. Grimes if (!*name) 51295105358SPhilippe Charnier errx(1, "null definition"); 5139b50d902SRodney W. Grimes if (STREQ(name, defn)) 51495105358SPhilippe Charnier errx(1, "%s: recursive definition", name); 5159b50d902SRodney W. Grimes p = addent(name); 5169b50d902SRodney W. Grimes if (!*defn) 5179b50d902SRodney W. Grimes p->defn = null; 5189b50d902SRodney W. Grimes else 5199b50d902SRodney W. Grimes p->defn = xstrdup(defn); 5209b50d902SRodney W. Grimes p->type = MACRTYPE; 5219b50d902SRodney W. Grimes } 5229b50d902SRodney W. Grimes 5239b50d902SRodney W. Grimes /* 5249b50d902SRodney W. Grimes * dodumpdef - dump the specified definitions in the hash 5259b50d902SRodney W. Grimes * table to stderr. If nothing is specified, the entire 5269b50d902SRodney W. Grimes * hash table is dumped. 5279b50d902SRodney W. Grimes */ 5289b50d902SRodney W. Grimes void 5299b50d902SRodney W. Grimes dodump(argv, argc) 5309b50d902SRodney W. Grimes register char *argv[]; 5319b50d902SRodney W. Grimes register int argc; 5329b50d902SRodney W. Grimes { 5339b50d902SRodney W. Grimes register int n; 5349b50d902SRodney W. Grimes ndptr p; 5359b50d902SRodney W. Grimes 5369b50d902SRodney W. Grimes if (argc > 2) { 5379b50d902SRodney W. Grimes for (n = 2; n < argc; n++) 5389b50d902SRodney W. Grimes if ((p = lookup(argv[n])) != nil) 5399b50d902SRodney W. Grimes fprintf(stderr, dumpfmt, p->name, 5409b50d902SRodney W. Grimes p->defn); 5419b50d902SRodney W. Grimes } 5429b50d902SRodney W. Grimes else { 5439b50d902SRodney W. Grimes for (n = 0; n < HASHSIZE; n++) 5449b50d902SRodney W. Grimes for (p = hashtab[n]; p != nil; p = p->nxtptr) 5459b50d902SRodney W. Grimes fprintf(stderr, dumpfmt, p->name, 5469b50d902SRodney W. Grimes p->defn); 5479b50d902SRodney W. Grimes } 5489b50d902SRodney W. Grimes } 5499b50d902SRodney W. Grimes 5509b50d902SRodney W. Grimes /* 5519b50d902SRodney W. Grimes * doifelse - select one of two alternatives - loop. 5529b50d902SRodney W. Grimes */ 5539b50d902SRodney W. Grimes void 5549b50d902SRodney W. Grimes doifelse(argv, argc) 5559b50d902SRodney W. Grimes register char *argv[]; 5569b50d902SRodney W. Grimes register int argc; 5579b50d902SRodney W. Grimes { 5589b50d902SRodney W. Grimes cycle { 5599b50d902SRodney W. Grimes if (STREQ(argv[2], argv[3])) 5609b50d902SRodney W. Grimes pbstr(argv[4]); 5619b50d902SRodney W. Grimes else if (argc == 6) 5629b50d902SRodney W. Grimes pbstr(argv[5]); 5639b50d902SRodney W. Grimes else if (argc > 6) { 5649b50d902SRodney W. Grimes argv += 3; 5659b50d902SRodney W. Grimes argc -= 3; 5669b50d902SRodney W. Grimes continue; 5679b50d902SRodney W. Grimes } 5689b50d902SRodney W. Grimes break; 5699b50d902SRodney W. Grimes } 5709b50d902SRodney W. Grimes } 5719b50d902SRodney W. Grimes 5729b50d902SRodney W. Grimes /* 5739b50d902SRodney W. Grimes * doinclude - include a given file. 5749b50d902SRodney W. Grimes */ 5759b50d902SRodney W. Grimes int 5769b50d902SRodney W. Grimes doincl(ifile) 5779b50d902SRodney W. Grimes char *ifile; 5789b50d902SRodney W. Grimes { 5799b50d902SRodney W. Grimes if (ilevel + 1 == MAXINP) 58095105358SPhilippe Charnier errx(1, "too many include files"); 5819b50d902SRodney W. Grimes if ((infile[ilevel + 1] = fopen(ifile, "r")) != NULL) { 5829b50d902SRodney W. Grimes ilevel++; 5839b50d902SRodney W. Grimes bbase[ilevel] = bufbase = bp; 5849b50d902SRodney W. Grimes return (1); 5859b50d902SRodney W. Grimes } 5869b50d902SRodney W. Grimes else 5879b50d902SRodney W. Grimes return (0); 5889b50d902SRodney W. Grimes } 5899b50d902SRodney W. Grimes 5909b50d902SRodney W. Grimes #ifdef EXTENDED 5919b50d902SRodney W. Grimes /* 5929b50d902SRodney W. Grimes * dopaste - include a given file without any 5939b50d902SRodney W. Grimes * macro processing. 5949b50d902SRodney W. Grimes */ 5959b50d902SRodney W. Grimes int 5969b50d902SRodney W. Grimes dopaste(pfile) 5979b50d902SRodney W. Grimes char *pfile; 5989b50d902SRodney W. Grimes { 5999b50d902SRodney W. Grimes FILE *pf; 6009b50d902SRodney W. Grimes register int c; 6019b50d902SRodney W. Grimes 6029b50d902SRodney W. Grimes if ((pf = fopen(pfile, "r")) != NULL) { 6039b50d902SRodney W. Grimes while ((c = getc(pf)) != EOF) 6049b50d902SRodney W. Grimes putc(c, active); 6059b50d902SRodney W. Grimes (void) fclose(pf); 6069b50d902SRodney W. Grimes return (1); 6079b50d902SRodney W. Grimes } 6089b50d902SRodney W. Grimes else 6099b50d902SRodney W. Grimes return (0); 6109b50d902SRodney W. Grimes } 6119b50d902SRodney W. Grimes #endif 6129b50d902SRodney W. Grimes 6139b50d902SRodney W. Grimes /* 6149b50d902SRodney W. Grimes * dochq - change quote characters 6159b50d902SRodney W. Grimes */ 6169b50d902SRodney W. Grimes void 6179b50d902SRodney W. Grimes dochq(argv, argc) 6189b50d902SRodney W. Grimes register char *argv[]; 6199b50d902SRodney W. Grimes register int argc; 6209b50d902SRodney W. Grimes { 6219b50d902SRodney W. Grimes if (argc > 2) { 6229b50d902SRodney W. Grimes if (*argv[2]) 6239b50d902SRodney W. Grimes lquote = *argv[2]; 624ef2cea81SJonathan Lemon else 625ef2cea81SJonathan Lemon lquote = LQUOTE; 6269b50d902SRodney W. Grimes if (argc > 3) { 6279b50d902SRodney W. Grimes if (*argv[3]) 6289b50d902SRodney W. Grimes rquote = *argv[3]; 629ef2cea81SJonathan Lemon else 630ef2cea81SJonathan Lemon rquote = RQUOTE; 6319b50d902SRodney W. Grimes } 6329b50d902SRodney W. Grimes else 6339b50d902SRodney W. Grimes rquote = lquote; 6349b50d902SRodney W. Grimes } 6359b50d902SRodney W. Grimes else { 6369b50d902SRodney W. Grimes lquote = LQUOTE; 6379b50d902SRodney W. Grimes rquote = RQUOTE; 6389b50d902SRodney W. Grimes } 6399b50d902SRodney W. Grimes } 6409b50d902SRodney W. Grimes 6419b50d902SRodney W. Grimes /* 6429b50d902SRodney W. Grimes * dochc - change comment characters 6439b50d902SRodney W. Grimes */ 6449b50d902SRodney W. Grimes void 6459b50d902SRodney W. Grimes dochc(argv, argc) 6469b50d902SRodney W. Grimes register char *argv[]; 6479b50d902SRodney W. Grimes register int argc; 6489b50d902SRodney W. Grimes { 6499b50d902SRodney W. Grimes if (argc > 2) { 6509b50d902SRodney W. Grimes if (*argv[2]) 6519b50d902SRodney W. Grimes scommt = *argv[2]; 6529b50d902SRodney W. Grimes if (argc > 3) { 6539b50d902SRodney W. Grimes if (*argv[3]) 6549b50d902SRodney W. Grimes ecommt = *argv[3]; 6559b50d902SRodney W. Grimes } 6569b50d902SRodney W. Grimes else 6579b50d902SRodney W. Grimes ecommt = ECOMMT; 6589b50d902SRodney W. Grimes } 6599b50d902SRodney W. Grimes else { 6609b50d902SRodney W. Grimes scommt = SCOMMT; 6619b50d902SRodney W. Grimes ecommt = ECOMMT; 6629b50d902SRodney W. Grimes } 6639b50d902SRodney W. Grimes } 6649b50d902SRodney W. Grimes 6659b50d902SRodney W. Grimes /* 6669b50d902SRodney W. Grimes * dodivert - divert the output to a temporary file 6679b50d902SRodney W. Grimes */ 6689b50d902SRodney W. Grimes void 6699b50d902SRodney W. Grimes dodiv(n) 6709b50d902SRodney W. Grimes register int n; 6719b50d902SRodney W. Grimes { 672ef2cea81SJonathan Lemon oindex = n; 6739b50d902SRodney W. Grimes if (n < 0 || n >= MAXOUT) 6749b50d902SRodney W. Grimes n = 0; /* bitbucket */ 6759b50d902SRodney W. Grimes if (outfile[n] == NULL) { 6769b50d902SRodney W. Grimes m4temp[UNIQUE] = n + '0'; 6779b50d902SRodney W. Grimes if ((outfile[n] = fopen(m4temp, "w")) == NULL) 67895105358SPhilippe Charnier errx(1, "%s: cannot divert", m4temp); 6799b50d902SRodney W. Grimes } 6809b50d902SRodney W. Grimes active = outfile[n]; 6819b50d902SRodney W. Grimes } 6829b50d902SRodney W. Grimes 6839b50d902SRodney W. Grimes /* 6849b50d902SRodney W. Grimes * doundivert - undivert a specified output, or all 6859b50d902SRodney W. Grimes * other outputs, in numerical order. 6869b50d902SRodney W. Grimes */ 6879b50d902SRodney W. Grimes void 6889b50d902SRodney W. Grimes doundiv(argv, argc) 6899b50d902SRodney W. Grimes register char *argv[]; 6909b50d902SRodney W. Grimes register int argc; 6919b50d902SRodney W. Grimes { 6929b50d902SRodney W. Grimes register int ind; 6939b50d902SRodney W. Grimes register int n; 6949b50d902SRodney W. Grimes 6959b50d902SRodney W. Grimes if (argc > 2) { 6969b50d902SRodney W. Grimes for (ind = 2; ind < argc; ind++) { 6979b50d902SRodney W. Grimes n = atoi(argv[ind]); 6989b50d902SRodney W. Grimes if (n > 0 && n < MAXOUT && outfile[n] != NULL) 6999b50d902SRodney W. Grimes getdiv(n); 7009b50d902SRodney W. Grimes 7019b50d902SRodney W. Grimes } 7029b50d902SRodney W. Grimes } 7039b50d902SRodney W. Grimes else 7049b50d902SRodney W. Grimes for (n = 1; n < MAXOUT; n++) 7059b50d902SRodney W. Grimes if (outfile[n] != NULL) 7069b50d902SRodney W. Grimes getdiv(n); 7079b50d902SRodney W. Grimes } 7089b50d902SRodney W. Grimes 7099b50d902SRodney W. Grimes /* 7109b50d902SRodney W. Grimes * dosub - select substring 7119b50d902SRodney W. Grimes */ 7129b50d902SRodney W. Grimes void 7139b50d902SRodney W. Grimes dosub(argv, argc) 7149b50d902SRodney W. Grimes register char *argv[]; 7159b50d902SRodney W. Grimes register int argc; 7169b50d902SRodney W. Grimes { 7177c5eeb39SAndrey A. Chernov register unsigned char *ap, *fc, *k; 7189b50d902SRodney W. Grimes register int nc; 7199b50d902SRodney W. Grimes 7209b50d902SRodney W. Grimes ap = argv[2]; /* target string */ 7219b50d902SRodney W. Grimes #ifdef EXPR 7229b50d902SRodney W. Grimes fc = ap + expr(argv[3]); /* first char */ 7239b50d902SRodney W. Grimes #else 7249b50d902SRodney W. Grimes fc = ap + atoi(argv[3]); /* first char */ 7259b50d902SRodney W. Grimes #endif 7264ba4d387SGregory Neil Shapiro if (argc < 5) 7274ba4d387SGregory Neil Shapiro nc = strlen(fc); 7284ba4d387SGregory Neil Shapiro else 7294ba4d387SGregory Neil Shapiro #ifdef EXPR 7304ba4d387SGregory Neil Shapiro nc = expr(argv[4]); 7314ba4d387SGregory Neil Shapiro #else 7324ba4d387SGregory Neil Shapiro nc = atoi(argv[4]); 7334ba4d387SGregory Neil Shapiro #endif 7349b50d902SRodney W. Grimes if (fc >= ap && fc < ap + strlen(ap)) 7354ba4d387SGregory Neil Shapiro for (k = fc + nc - 1; k >= fc; k--) 7369b50d902SRodney W. Grimes putback(*k); 7379b50d902SRodney W. Grimes } 7389b50d902SRodney W. Grimes 7399b50d902SRodney W. Grimes /* 7409b50d902SRodney W. Grimes * map: 7419b50d902SRodney W. Grimes * map every character of s1 that is specified in from 7429b50d902SRodney W. Grimes * into s3 and replace in s. (source s1 remains untouched) 7439b50d902SRodney W. Grimes * 7449b50d902SRodney W. Grimes * This is a standard implementation of map(s,from,to) function of ICON 7459b50d902SRodney W. Grimes * language. Within mapvec, we replace every character of "from" with 7469b50d902SRodney W. Grimes * the corresponding character in "to". If "to" is shorter than "from", 7479b50d902SRodney W. Grimes * than the corresponding entries are null, which means that those 7489b50d902SRodney W. Grimes * characters dissapear altogether. Furthermore, imagine 7499b50d902SRodney W. Grimes * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case, 7509b50d902SRodney W. Grimes * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s' 7519b50d902SRodney W. Grimes * ultimately maps to `*'. In order to achieve this effect in an efficient 7529b50d902SRodney W. Grimes * manner (i.e. without multiple passes over the destination string), we 7539b50d902SRodney W. Grimes * loop over mapvec, starting with the initial source character. if the 7549b50d902SRodney W. Grimes * character value (dch) in this location is different than the source 7559b50d902SRodney W. Grimes * character (sch), sch becomes dch, once again to index into mapvec, until 7569b50d902SRodney W. Grimes * the character value stabilizes (i.e. sch = dch, in other words 7579b50d902SRodney W. Grimes * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary 7589b50d902SRodney W. Grimes * character, it will stabilize, since mapvec[0] == 0 at all times. At the 7599b50d902SRodney W. Grimes * end, we restore mapvec* back to normal where mapvec[n] == n for 7609b50d902SRodney W. Grimes * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is 7619b50d902SRodney W. Grimes * about 5 times faster than any algorithm that makes multiple passes over 7629b50d902SRodney W. Grimes * destination string. 7639b50d902SRodney W. Grimes */ 7649b50d902SRodney W. Grimes void 7659b50d902SRodney W. Grimes map(dest, src, from, to) 7669b50d902SRodney W. Grimes register char *dest; 7679b50d902SRodney W. Grimes register char *src; 7689b50d902SRodney W. Grimes register char *from; 7699b50d902SRodney W. Grimes register char *to; 7709b50d902SRodney W. Grimes { 7719b50d902SRodney W. Grimes register char *tmp; 7729b50d902SRodney W. Grimes register char sch, dch; 7739b50d902SRodney W. Grimes static char mapvec[128] = { 7749b50d902SRodney W. Grimes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 7759b50d902SRodney W. Grimes 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 7769b50d902SRodney W. Grimes 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 7779b50d902SRodney W. Grimes 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 7789b50d902SRodney W. Grimes 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 7799b50d902SRodney W. Grimes 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 7809b50d902SRodney W. Grimes 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 7819b50d902SRodney W. Grimes 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 7829b50d902SRodney W. Grimes 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 7839b50d902SRodney W. Grimes 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 7849b50d902SRodney W. Grimes 120, 121, 122, 123, 124, 125, 126, 127 7859b50d902SRodney W. Grimes }; 7869b50d902SRodney W. Grimes 7879b50d902SRodney W. Grimes if (*src) { 7889b50d902SRodney W. Grimes tmp = from; 7899b50d902SRodney W. Grimes /* 7909b50d902SRodney W. Grimes * create a mapping between "from" and 7919b50d902SRodney W. Grimes * "to" 7929b50d902SRodney W. Grimes */ 7939b50d902SRodney W. Grimes while (*from) 7949b50d902SRodney W. Grimes mapvec[*from++] = (*to) ? *to++ : (char) 0; 7959b50d902SRodney W. Grimes 7969b50d902SRodney W. Grimes while (*src) { 7979b50d902SRodney W. Grimes sch = *src++; 7989b50d902SRodney W. Grimes dch = mapvec[sch]; 7999b50d902SRodney W. Grimes while (dch != sch) { 8009b50d902SRodney W. Grimes sch = dch; 8019b50d902SRodney W. Grimes dch = mapvec[sch]; 8029b50d902SRodney W. Grimes } 8039b50d902SRodney W. Grimes if (*dest = dch) 8049b50d902SRodney W. Grimes dest++; 8059b50d902SRodney W. Grimes } 8069b50d902SRodney W. Grimes /* 8079b50d902SRodney W. Grimes * restore all the changed characters 8089b50d902SRodney W. Grimes */ 8099b50d902SRodney W. Grimes while (*tmp) { 8109b50d902SRodney W. Grimes mapvec[*tmp] = *tmp; 8119b50d902SRodney W. Grimes tmp++; 8129b50d902SRodney W. Grimes } 8139b50d902SRodney W. Grimes } 8149b50d902SRodney W. Grimes *dest = (char) 0; 8159b50d902SRodney W. Grimes } 816