xref: /freebsd/usr.bin/m4/eval.c (revision ef2cea8123fe4caef2e3f94c211d4e14f8c2e103)
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[] =
42ef2cea81SJonathan Lemon 	"$Id: eval.c,v 1.7 1997/07/23 06:50:04 charnier Exp $";
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 
3739b50d902SRodney W. Grimes 	default:
37495105358SPhilippe Charnier 		errx(1, "eval: major botch");
3759b50d902SRodney W. Grimes 		break;
3769b50d902SRodney W. Grimes 	}
3779b50d902SRodney W. Grimes }
3789b50d902SRodney W. Grimes 
3799b50d902SRodney W. Grimes char *dumpfmt = "`%s'\t`%s'\n";	       /* format string for dumpdef   */
3809b50d902SRodney W. Grimes 
3819b50d902SRodney W. Grimes /*
3829b50d902SRodney W. Grimes  * expand - user-defined macro expansion
3839b50d902SRodney W. Grimes  */
3849b50d902SRodney W. Grimes void
3859b50d902SRodney W. Grimes expand(argv, argc)
3869b50d902SRodney W. Grimes register char *argv[];
3879b50d902SRodney W. Grimes register int argc;
3889b50d902SRodney W. Grimes {
3897c5eeb39SAndrey A. Chernov 	register unsigned char *t;
3907c5eeb39SAndrey A. Chernov 	register unsigned char *p;
3919b50d902SRodney W. Grimes 	register int n;
3929b50d902SRodney W. Grimes 	register int argno;
3939b50d902SRodney W. Grimes 
3949b50d902SRodney W. Grimes 	t = argv[0];		       /* defn string as a whole */
3959b50d902SRodney W. Grimes 	p = t;
3969b50d902SRodney W. Grimes 	while (*p)
3979b50d902SRodney W. Grimes 		p++;
3989b50d902SRodney W. Grimes 	p--;			       /* last character of defn */
3999b50d902SRodney W. Grimes 	while (p > t) {
4009b50d902SRodney W. Grimes 		if (*(p - 1) != ARGFLAG)
4019b50d902SRodney W. Grimes 			putback(*p);
4029b50d902SRodney W. Grimes 		else {
4039b50d902SRodney W. Grimes 			switch (*p) {
4049b50d902SRodney W. Grimes 
4059b50d902SRodney W. Grimes 			case '#':
4069b50d902SRodney W. Grimes 				pbnum(argc - 2);
4079b50d902SRodney W. Grimes 				break;
4089b50d902SRodney W. Grimes 			case '0':
4099b50d902SRodney W. Grimes 			case '1':
4109b50d902SRodney W. Grimes 			case '2':
4119b50d902SRodney W. Grimes 			case '3':
4129b50d902SRodney W. Grimes 			case '4':
4139b50d902SRodney W. Grimes 			case '5':
4149b50d902SRodney W. Grimes 			case '6':
4159b50d902SRodney W. Grimes 			case '7':
4169b50d902SRodney W. Grimes 			case '8':
4179b50d902SRodney W. Grimes 			case '9':
4189b50d902SRodney W. Grimes 				if ((argno = *p - '0') < argc - 1)
4199b50d902SRodney W. Grimes 					pbstr(argv[argno + 1]);
4209b50d902SRodney W. Grimes 				break;
4219b50d902SRodney W. Grimes 			case '*':
4229b50d902SRodney W. Grimes 				for (n = argc - 1; n > 2; n--) {
4239b50d902SRodney W. Grimes 					pbstr(argv[n]);
4249b50d902SRodney W. Grimes 					putback(',');
4259b50d902SRodney W. Grimes 				}
4269b50d902SRodney W. Grimes 				pbstr(argv[2]);
4279b50d902SRodney W. Grimes 				break;
428232eaee6SJoerg Wunsch 			case '@':
429232eaee6SJoerg Wunsch 				for( n = argc - 1; n >= 2; n-- )
430232eaee6SJoerg Wunsch 				{
431232eaee6SJoerg Wunsch 					putback(rquote);
432232eaee6SJoerg Wunsch 					pbstr(argv[n]);
433232eaee6SJoerg Wunsch 					putback(lquote);
434232eaee6SJoerg Wunsch 					if( n > 2 )
435232eaee6SJoerg Wunsch 						putback(',');
436232eaee6SJoerg Wunsch 				}
437232eaee6SJoerg Wunsch 				break;
4389b50d902SRodney W. Grimes 			default:
4399b50d902SRodney W. Grimes 				putback(*p);
4409b50d902SRodney W. Grimes 				putback('$');
4419b50d902SRodney W. Grimes 				break;
4429b50d902SRodney W. Grimes 			}
4439b50d902SRodney W. Grimes 			p--;
4449b50d902SRodney W. Grimes 		}
4459b50d902SRodney W. Grimes 		p--;
4469b50d902SRodney W. Grimes 	}
4479b50d902SRodney W. Grimes 	if (p == t)		       /* do last character */
4489b50d902SRodney W. Grimes 		putback(*p);
4499b50d902SRodney W. Grimes }
4509b50d902SRodney W. Grimes 
4519b50d902SRodney W. Grimes /*
4529b50d902SRodney W. Grimes  * dodefine - install definition in the table
4539b50d902SRodney W. Grimes  */
4549b50d902SRodney W. Grimes void
4559b50d902SRodney W. Grimes dodefine(name, defn)
4569b50d902SRodney W. Grimes register char *name;
4579b50d902SRodney W. Grimes register char *defn;
4589b50d902SRodney W. Grimes {
4599b50d902SRodney W. Grimes 	register ndptr p;
4609b50d902SRodney W. Grimes 
4619b50d902SRodney W. Grimes 	if (!*name)
46295105358SPhilippe Charnier 		errx(1, "null definition");
4639b50d902SRodney W. Grimes 	if (STREQ(name, defn))
46495105358SPhilippe Charnier 		errx(1, "%s: recursive definition", name);
4659b50d902SRodney W. Grimes 	if ((p = lookup(name)) == nil)
4669b50d902SRodney W. Grimes 		p = addent(name);
4679b50d902SRodney W. Grimes 	else if (p->defn != null)
4689b50d902SRodney W. Grimes 		free((char *) p->defn);
4699b50d902SRodney W. Grimes 	if (!*defn)
4709b50d902SRodney W. Grimes 		p->defn = null;
4719b50d902SRodney W. Grimes 	else
4729b50d902SRodney W. Grimes 		p->defn = xstrdup(defn);
4739b50d902SRodney W. Grimes 	p->type = MACRTYPE;
4749b50d902SRodney W. Grimes }
4759b50d902SRodney W. Grimes 
4769b50d902SRodney W. Grimes /*
4779b50d902SRodney W. Grimes  * dodefn - push back a quoted definition of
4789b50d902SRodney W. Grimes  *      the given name.
4799b50d902SRodney W. Grimes  */
4809b50d902SRodney W. Grimes void
4819b50d902SRodney W. Grimes dodefn(name)
4829b50d902SRodney W. Grimes char *name;
4839b50d902SRodney W. Grimes {
4849b50d902SRodney W. Grimes 	register ndptr p;
4859b50d902SRodney W. Grimes 
4869b50d902SRodney W. Grimes 	if ((p = lookup(name)) != nil && p->defn != null) {
4879b50d902SRodney W. Grimes 		putback(rquote);
4889b50d902SRodney W. Grimes 		pbstr(p->defn);
4899b50d902SRodney W. Grimes 		putback(lquote);
4909b50d902SRodney W. Grimes 	}
4919b50d902SRodney W. Grimes }
4929b50d902SRodney W. Grimes 
4939b50d902SRodney W. Grimes /*
4949b50d902SRodney W. Grimes  * dopushdef - install a definition in the hash table
4959b50d902SRodney W. Grimes  *      without removing a previous definition. Since
4969b50d902SRodney W. Grimes  *      each new entry is entered in *front* of the
4979b50d902SRodney W. Grimes  *      hash bucket, it hides a previous definition from
4989b50d902SRodney W. Grimes  *      lookup.
4999b50d902SRodney W. Grimes  */
5009b50d902SRodney W. Grimes void
5019b50d902SRodney W. Grimes dopushdef(name, defn)
5029b50d902SRodney W. Grimes register char *name;
5039b50d902SRodney W. Grimes register char *defn;
5049b50d902SRodney W. Grimes {
5059b50d902SRodney W. Grimes 	register ndptr p;
5069b50d902SRodney W. Grimes 
5079b50d902SRodney W. Grimes 	if (!*name)
50895105358SPhilippe Charnier 		errx(1, "null definition");
5099b50d902SRodney W. Grimes 	if (STREQ(name, defn))
51095105358SPhilippe Charnier 		errx(1, "%s: recursive definition", name);
5119b50d902SRodney W. Grimes 	p = addent(name);
5129b50d902SRodney W. Grimes 	if (!*defn)
5139b50d902SRodney W. Grimes 		p->defn = null;
5149b50d902SRodney W. Grimes 	else
5159b50d902SRodney W. Grimes 		p->defn = xstrdup(defn);
5169b50d902SRodney W. Grimes 	p->type = MACRTYPE;
5179b50d902SRodney W. Grimes }
5189b50d902SRodney W. Grimes 
5199b50d902SRodney W. Grimes /*
5209b50d902SRodney W. Grimes  * dodumpdef - dump the specified definitions in the hash
5219b50d902SRodney W. Grimes  *      table to stderr. If nothing is specified, the entire
5229b50d902SRodney W. Grimes  *      hash table is dumped.
5239b50d902SRodney W. Grimes  */
5249b50d902SRodney W. Grimes void
5259b50d902SRodney W. Grimes dodump(argv, argc)
5269b50d902SRodney W. Grimes register char *argv[];
5279b50d902SRodney W. Grimes register int argc;
5289b50d902SRodney W. Grimes {
5299b50d902SRodney W. Grimes 	register int n;
5309b50d902SRodney W. Grimes 	ndptr p;
5319b50d902SRodney W. Grimes 
5329b50d902SRodney W. Grimes 	if (argc > 2) {
5339b50d902SRodney W. Grimes 		for (n = 2; n < argc; n++)
5349b50d902SRodney W. Grimes 			if ((p = lookup(argv[n])) != nil)
5359b50d902SRodney W. Grimes 				fprintf(stderr, dumpfmt, p->name,
5369b50d902SRodney W. Grimes 					p->defn);
5379b50d902SRodney W. Grimes 	}
5389b50d902SRodney W. Grimes 	else {
5399b50d902SRodney W. Grimes 		for (n = 0; n < HASHSIZE; n++)
5409b50d902SRodney W. Grimes 			for (p = hashtab[n]; p != nil; p = p->nxtptr)
5419b50d902SRodney W. Grimes 				fprintf(stderr, dumpfmt, p->name,
5429b50d902SRodney W. Grimes 					p->defn);
5439b50d902SRodney W. Grimes 	}
5449b50d902SRodney W. Grimes }
5459b50d902SRodney W. Grimes 
5469b50d902SRodney W. Grimes /*
5479b50d902SRodney W. Grimes  * doifelse - select one of two alternatives - loop.
5489b50d902SRodney W. Grimes  */
5499b50d902SRodney W. Grimes void
5509b50d902SRodney W. Grimes doifelse(argv, argc)
5519b50d902SRodney W. Grimes register char *argv[];
5529b50d902SRodney W. Grimes register int argc;
5539b50d902SRodney W. Grimes {
5549b50d902SRodney W. Grimes 	cycle {
5559b50d902SRodney W. Grimes 		if (STREQ(argv[2], argv[3]))
5569b50d902SRodney W. Grimes 			pbstr(argv[4]);
5579b50d902SRodney W. Grimes 		else if (argc == 6)
5589b50d902SRodney W. Grimes 			pbstr(argv[5]);
5599b50d902SRodney W. Grimes 		else if (argc > 6) {
5609b50d902SRodney W. Grimes 			argv += 3;
5619b50d902SRodney W. Grimes 			argc -= 3;
5629b50d902SRodney W. Grimes 			continue;
5639b50d902SRodney W. Grimes 		}
5649b50d902SRodney W. Grimes 		break;
5659b50d902SRodney W. Grimes 	}
5669b50d902SRodney W. Grimes }
5679b50d902SRodney W. Grimes 
5689b50d902SRodney W. Grimes /*
5699b50d902SRodney W. Grimes  * doinclude - include a given file.
5709b50d902SRodney W. Grimes  */
5719b50d902SRodney W. Grimes int
5729b50d902SRodney W. Grimes doincl(ifile)
5739b50d902SRodney W. Grimes char *ifile;
5749b50d902SRodney W. Grimes {
5759b50d902SRodney W. Grimes 	if (ilevel + 1 == MAXINP)
57695105358SPhilippe Charnier 		errx(1, "too many include files");
5779b50d902SRodney W. Grimes 	if ((infile[ilevel + 1] = fopen(ifile, "r")) != NULL) {
5789b50d902SRodney W. Grimes 		ilevel++;
5799b50d902SRodney W. Grimes 		bbase[ilevel] = bufbase = bp;
5809b50d902SRodney W. Grimes 		return (1);
5819b50d902SRodney W. Grimes 	}
5829b50d902SRodney W. Grimes 	else
5839b50d902SRodney W. Grimes 		return (0);
5849b50d902SRodney W. Grimes }
5859b50d902SRodney W. Grimes 
5869b50d902SRodney W. Grimes #ifdef EXTENDED
5879b50d902SRodney W. Grimes /*
5889b50d902SRodney W. Grimes  * dopaste - include a given file without any
5899b50d902SRodney W. Grimes  *           macro processing.
5909b50d902SRodney W. Grimes  */
5919b50d902SRodney W. Grimes int
5929b50d902SRodney W. Grimes dopaste(pfile)
5939b50d902SRodney W. Grimes char *pfile;
5949b50d902SRodney W. Grimes {
5959b50d902SRodney W. Grimes 	FILE *pf;
5969b50d902SRodney W. Grimes 	register int c;
5979b50d902SRodney W. Grimes 
5989b50d902SRodney W. Grimes 	if ((pf = fopen(pfile, "r")) != NULL) {
5999b50d902SRodney W. Grimes 		while ((c = getc(pf)) != EOF)
6009b50d902SRodney W. Grimes 			putc(c, active);
6019b50d902SRodney W. Grimes 		(void) fclose(pf);
6029b50d902SRodney W. Grimes 		return (1);
6039b50d902SRodney W. Grimes 	}
6049b50d902SRodney W. Grimes 	else
6059b50d902SRodney W. Grimes 		return (0);
6069b50d902SRodney W. Grimes }
6079b50d902SRodney W. Grimes #endif
6089b50d902SRodney W. Grimes 
6099b50d902SRodney W. Grimes /*
6109b50d902SRodney W. Grimes  * dochq - change quote characters
6119b50d902SRodney W. Grimes  */
6129b50d902SRodney W. Grimes void
6139b50d902SRodney W. Grimes dochq(argv, argc)
6149b50d902SRodney W. Grimes register char *argv[];
6159b50d902SRodney W. Grimes register int argc;
6169b50d902SRodney W. Grimes {
6179b50d902SRodney W. Grimes 	if (argc > 2) {
6189b50d902SRodney W. Grimes 		if (*argv[2])
6199b50d902SRodney W. Grimes 			lquote = *argv[2];
620ef2cea81SJonathan Lemon 		else
621ef2cea81SJonathan Lemon 			lquote = LQUOTE;
6229b50d902SRodney W. Grimes 		if (argc > 3) {
6239b50d902SRodney W. Grimes 			if (*argv[3])
6249b50d902SRodney W. Grimes 				rquote = *argv[3];
625ef2cea81SJonathan Lemon 			else
626ef2cea81SJonathan Lemon 				rquote = RQUOTE;
6279b50d902SRodney W. Grimes 		}
6289b50d902SRodney W. Grimes 		else
6299b50d902SRodney W. Grimes 			rquote = lquote;
6309b50d902SRodney W. Grimes 	}
6319b50d902SRodney W. Grimes 	else {
6329b50d902SRodney W. Grimes 		lquote = LQUOTE;
6339b50d902SRodney W. Grimes 		rquote = RQUOTE;
6349b50d902SRodney W. Grimes 	}
6359b50d902SRodney W. Grimes }
6369b50d902SRodney W. Grimes 
6379b50d902SRodney W. Grimes /*
6389b50d902SRodney W. Grimes  * dochc - change comment characters
6399b50d902SRodney W. Grimes  */
6409b50d902SRodney W. Grimes void
6419b50d902SRodney W. Grimes dochc(argv, argc)
6429b50d902SRodney W. Grimes register char *argv[];
6439b50d902SRodney W. Grimes register int argc;
6449b50d902SRodney W. Grimes {
6459b50d902SRodney W. Grimes 	if (argc > 2) {
6469b50d902SRodney W. Grimes 		if (*argv[2])
6479b50d902SRodney W. Grimes 			scommt = *argv[2];
6489b50d902SRodney W. Grimes 		if (argc > 3) {
6499b50d902SRodney W. Grimes 			if (*argv[3])
6509b50d902SRodney W. Grimes 				ecommt = *argv[3];
6519b50d902SRodney W. Grimes 		}
6529b50d902SRodney W. Grimes 		else
6539b50d902SRodney W. Grimes 			ecommt = ECOMMT;
6549b50d902SRodney W. Grimes 	}
6559b50d902SRodney W. Grimes 	else {
6569b50d902SRodney W. Grimes 		scommt = SCOMMT;
6579b50d902SRodney W. Grimes 		ecommt = ECOMMT;
6589b50d902SRodney W. Grimes 	}
6599b50d902SRodney W. Grimes }
6609b50d902SRodney W. Grimes 
6619b50d902SRodney W. Grimes /*
6629b50d902SRodney W. Grimes  * dodivert - divert the output to a temporary file
6639b50d902SRodney W. Grimes  */
6649b50d902SRodney W. Grimes void
6659b50d902SRodney W. Grimes dodiv(n)
6669b50d902SRodney W. Grimes register int n;
6679b50d902SRodney W. Grimes {
668ef2cea81SJonathan Lemon 	oindex = n;
6699b50d902SRodney W. Grimes 	if (n < 0 || n >= MAXOUT)
6709b50d902SRodney W. Grimes 		n = 0;		       /* bitbucket */
6719b50d902SRodney W. Grimes 	if (outfile[n] == NULL) {
6729b50d902SRodney W. Grimes 		m4temp[UNIQUE] = n + '0';
6739b50d902SRodney W. Grimes 		if ((outfile[n] = fopen(m4temp, "w")) == NULL)
67495105358SPhilippe Charnier 			errx(1, "%s: cannot divert", m4temp);
6759b50d902SRodney W. Grimes 	}
6769b50d902SRodney W. Grimes 	active = outfile[n];
6779b50d902SRodney W. Grimes }
6789b50d902SRodney W. Grimes 
6799b50d902SRodney W. Grimes /*
6809b50d902SRodney W. Grimes  * doundivert - undivert a specified output, or all
6819b50d902SRodney W. Grimes  *              other outputs, in numerical order.
6829b50d902SRodney W. Grimes  */
6839b50d902SRodney W. Grimes void
6849b50d902SRodney W. Grimes doundiv(argv, argc)
6859b50d902SRodney W. Grimes register char *argv[];
6869b50d902SRodney W. Grimes register int argc;
6879b50d902SRodney W. Grimes {
6889b50d902SRodney W. Grimes 	register int ind;
6899b50d902SRodney W. Grimes 	register int n;
6909b50d902SRodney W. Grimes 
6919b50d902SRodney W. Grimes 	if (argc > 2) {
6929b50d902SRodney W. Grimes 		for (ind = 2; ind < argc; ind++) {
6939b50d902SRodney W. Grimes 			n = atoi(argv[ind]);
6949b50d902SRodney W. Grimes 			if (n > 0 && n < MAXOUT && outfile[n] != NULL)
6959b50d902SRodney W. Grimes 				getdiv(n);
6969b50d902SRodney W. Grimes 
6979b50d902SRodney W. Grimes 		}
6989b50d902SRodney W. Grimes 	}
6999b50d902SRodney W. Grimes 	else
7009b50d902SRodney W. Grimes 		for (n = 1; n < MAXOUT; n++)
7019b50d902SRodney W. Grimes 			if (outfile[n] != NULL)
7029b50d902SRodney W. Grimes 				getdiv(n);
7039b50d902SRodney W. Grimes }
7049b50d902SRodney W. Grimes 
7059b50d902SRodney W. Grimes /*
7069b50d902SRodney W. Grimes  * dosub - select substring
7079b50d902SRodney W. Grimes  */
7089b50d902SRodney W. Grimes void
7099b50d902SRodney W. Grimes dosub(argv, argc)
7109b50d902SRodney W. Grimes register char *argv[];
7119b50d902SRodney W. Grimes register int argc;
7129b50d902SRodney W. Grimes {
7137c5eeb39SAndrey A. Chernov 	register unsigned char *ap, *fc, *k;
7149b50d902SRodney W. Grimes 	register int nc;
7159b50d902SRodney W. Grimes 
7169b50d902SRodney W. Grimes 	if (argc < 5)
7179b50d902SRodney W. Grimes 		nc = MAXTOK;
7189b50d902SRodney W. Grimes 	else
7199b50d902SRodney W. Grimes #ifdef EXPR
7209b50d902SRodney W. Grimes 		nc = expr(argv[4]);
7219b50d902SRodney W. Grimes #else
7229b50d902SRodney W. Grimes 		nc = atoi(argv[4]);
7239b50d902SRodney W. Grimes #endif
7249b50d902SRodney W. Grimes 	ap = argv[2];		       /* target string */
7259b50d902SRodney W. Grimes #ifdef EXPR
7269b50d902SRodney W. Grimes 	fc = ap + expr(argv[3]);       /* first char */
7279b50d902SRodney W. Grimes #else
7289b50d902SRodney W. Grimes 	fc = ap + atoi(argv[3]);       /* first char */
7299b50d902SRodney W. Grimes #endif
7309b50d902SRodney W. Grimes 	if (fc >= ap && fc < ap + strlen(ap))
7319b50d902SRodney W. Grimes 		for (k = fc + min(nc, strlen(fc)) - 1; k >= fc; k--)
7329b50d902SRodney W. Grimes 			putback(*k);
7339b50d902SRodney W. Grimes }
7349b50d902SRodney W. Grimes 
7359b50d902SRodney W. Grimes /*
7369b50d902SRodney W. Grimes  * map:
7379b50d902SRodney W. Grimes  * map every character of s1 that is specified in from
7389b50d902SRodney W. Grimes  * into s3 and replace in s. (source s1 remains untouched)
7399b50d902SRodney W. Grimes  *
7409b50d902SRodney W. Grimes  * This is a standard implementation of map(s,from,to) function of ICON
7419b50d902SRodney W. Grimes  * language. Within mapvec, we replace every character of "from" with
7429b50d902SRodney W. Grimes  * the corresponding character in "to". If "to" is shorter than "from",
7439b50d902SRodney W. Grimes  * than the corresponding entries are null, which means that those
7449b50d902SRodney W. Grimes  * characters dissapear altogether. Furthermore, imagine
7459b50d902SRodney W. Grimes  * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
7469b50d902SRodney W. Grimes  * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
7479b50d902SRodney W. Grimes  * ultimately maps to `*'. In order to achieve this effect in an efficient
7489b50d902SRodney W. Grimes  * manner (i.e. without multiple passes over the destination string), we
7499b50d902SRodney W. Grimes  * loop over mapvec, starting with the initial source character. if the
7509b50d902SRodney W. Grimes  * character value (dch) in this location is different than the source
7519b50d902SRodney W. Grimes  * character (sch), sch becomes dch, once again to index into mapvec, until
7529b50d902SRodney W. Grimes  * the character value stabilizes (i.e. sch = dch, in other words
7539b50d902SRodney W. Grimes  * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
7549b50d902SRodney W. Grimes  * character, it will stabilize, since mapvec[0] == 0 at all times. At the
7559b50d902SRodney W. Grimes  * end, we restore mapvec* back to normal where mapvec[n] == n for
7569b50d902SRodney W. Grimes  * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
7579b50d902SRodney W. Grimes  * about 5 times faster than any algorithm that makes multiple passes over
7589b50d902SRodney W. Grimes  * destination string.
7599b50d902SRodney W. Grimes  */
7609b50d902SRodney W. Grimes void
7619b50d902SRodney W. Grimes map(dest, src, from, to)
7629b50d902SRodney W. Grimes register char *dest;
7639b50d902SRodney W. Grimes register char *src;
7649b50d902SRodney W. Grimes register char *from;
7659b50d902SRodney W. Grimes register char *to;
7669b50d902SRodney W. Grimes {
7679b50d902SRodney W. Grimes 	register char *tmp;
7689b50d902SRodney W. Grimes 	register char sch, dch;
7699b50d902SRodney W. Grimes 	static char mapvec[128] = {
7709b50d902SRodney W. Grimes 		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
7719b50d902SRodney W. Grimes 		12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
7729b50d902SRodney W. Grimes 		24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
7739b50d902SRodney W. Grimes 		36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
7749b50d902SRodney W. Grimes 		48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
7759b50d902SRodney W. Grimes 		60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
7769b50d902SRodney W. Grimes 		72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
7779b50d902SRodney W. Grimes 		84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
7789b50d902SRodney W. Grimes 		96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
7799b50d902SRodney W. Grimes 		108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
7809b50d902SRodney W. Grimes 		120, 121, 122, 123, 124, 125, 126, 127
7819b50d902SRodney W. Grimes 	};
7829b50d902SRodney W. Grimes 
7839b50d902SRodney W. Grimes 	if (*src) {
7849b50d902SRodney W. Grimes 		tmp = from;
7859b50d902SRodney W. Grimes 	/*
7869b50d902SRodney W. Grimes 	 * create a mapping between "from" and
7879b50d902SRodney W. Grimes 	 * "to"
7889b50d902SRodney W. Grimes 	 */
7899b50d902SRodney W. Grimes 		while (*from)
7909b50d902SRodney W. Grimes 			mapvec[*from++] = (*to) ? *to++ : (char) 0;
7919b50d902SRodney W. Grimes 
7929b50d902SRodney W. Grimes 		while (*src) {
7939b50d902SRodney W. Grimes 			sch = *src++;
7949b50d902SRodney W. Grimes 			dch = mapvec[sch];
7959b50d902SRodney W. Grimes 			while (dch != sch) {
7969b50d902SRodney W. Grimes 				sch = dch;
7979b50d902SRodney W. Grimes 				dch = mapvec[sch];
7989b50d902SRodney W. Grimes 			}
7999b50d902SRodney W. Grimes 			if (*dest = dch)
8009b50d902SRodney W. Grimes 				dest++;
8019b50d902SRodney W. Grimes 		}
8029b50d902SRodney W. Grimes 	/*
8039b50d902SRodney W. Grimes 	 * restore all the changed characters
8049b50d902SRodney W. Grimes 	 */
8059b50d902SRodney W. Grimes 		while (*tmp) {
8069b50d902SRodney W. Grimes 			mapvec[*tmp] = *tmp;
8079b50d902SRodney W. Grimes 			tmp++;
8089b50d902SRodney W. Grimes 		}
8099b50d902SRodney W. Grimes 	}
8109b50d902SRodney W. Grimes 	*dest = (char) 0;
8119b50d902SRodney W. Grimes }
812