xref: /onnv-gate/usr/src/cmd/sgs/m4/common/m4macs.c (revision 6951:59445bec7ef4)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*6951Sab196087  * Common Development and Distribution License (the "License").
6*6951Sab196087  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21291Smike_s 
22291Smike_s /*
23*6951Sab196087  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24291Smike_s  * Use is subject to license terms.
25291Smike_s  */
26291Smike_s 
270Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include	<limits.h>
330Sstevel@tonic-gate #include	<unistd.h>
340Sstevel@tonic-gate #include	<sys/types.h>
350Sstevel@tonic-gate #include	"m4.h"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #define	arg(n)	(c < (n) ? nullstr: ap[n])
380Sstevel@tonic-gate static void mkpid(char *);
390Sstevel@tonic-gate static void def(wchar_t **, int, int);
400Sstevel@tonic-gate static void dump(wchar_t *, wchar_t *);
410Sstevel@tonic-gate static void incl(wchar_t **, int, int);
420Sstevel@tonic-gate static int leftmatch(wchar_t *, wchar_t *);
430Sstevel@tonic-gate 
440Sstevel@tonic-gate static void
dochcom(wchar_t ** ap,int c)450Sstevel@tonic-gate dochcom(wchar_t **ap, int c)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate 	wchar_t	*l = arg(1);
480Sstevel@tonic-gate 	wchar_t	*r = arg(2);
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 	if (wcslen(l) > MAXSYM || wcslen(r) > MAXSYM)
510Sstevel@tonic-gate 		error2(gettext(
520Sstevel@tonic-gate 		"comment marker longer than %d chars"), MAXSYM);
530Sstevel@tonic-gate 	(void) wcscpy(lcom, l);
540Sstevel@tonic-gate 	(void) wcscpy(rcom, *r ? r : L"\n");
550Sstevel@tonic-gate }
560Sstevel@tonic-gate 
570Sstevel@tonic-gate static void
docq(wchar_t ** ap,int c)580Sstevel@tonic-gate docq(wchar_t **ap, int c)
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 	wchar_t	*l = arg(1);
610Sstevel@tonic-gate 	wchar_t	*r = arg(2);
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	if (wcslen(l) > MAXSYM || wcslen(r) > MAXSYM)
640Sstevel@tonic-gate 		error2(gettext(
650Sstevel@tonic-gate 		"quote marker longer than %d chars"), MAXSYM);
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	if (c <= 1 && !*l) {
680Sstevel@tonic-gate 		l = L"`";
690Sstevel@tonic-gate 		r = L"'";
700Sstevel@tonic-gate 	} else if (c == 1) {
710Sstevel@tonic-gate 		r = l;
720Sstevel@tonic-gate 	}
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	(void) wcscpy(lquote, l);
750Sstevel@tonic-gate 	(void) wcscpy(rquote, r);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate 
780Sstevel@tonic-gate static void
dodecr(wchar_t ** ap,int c)790Sstevel@tonic-gate dodecr(wchar_t **ap, int c)
800Sstevel@tonic-gate {
810Sstevel@tonic-gate 	pbnum(ctol(arg(1))-1);
820Sstevel@tonic-gate }
830Sstevel@tonic-gate 
840Sstevel@tonic-gate void
dodef(wchar_t ** ap,int c)850Sstevel@tonic-gate dodef(wchar_t **ap, int c)
860Sstevel@tonic-gate {
870Sstevel@tonic-gate 	def(ap, c, NOPUSH);
880Sstevel@tonic-gate }
890Sstevel@tonic-gate 
900Sstevel@tonic-gate static void
def(wchar_t ** ap,int c,int mode)910Sstevel@tonic-gate def(wchar_t **ap, int c, int mode)
920Sstevel@tonic-gate {
930Sstevel@tonic-gate 	wchar_t	*s;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	if (c < 1)
960Sstevel@tonic-gate 		return;
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	s = ap[1];
990Sstevel@tonic-gate 	if (is_alpha(*s) || *s == '_') {
1000Sstevel@tonic-gate 		s++;
1010Sstevel@tonic-gate 		while (is_alnum(*s) || *s == '_')
1020Sstevel@tonic-gate 			s++;
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 	if (*s || s == ap[1])
1050Sstevel@tonic-gate 		error(gettext("bad macro name"));
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	if ((ap[2] != NULL) && (wcscmp(ap[1], ap[2]) == 0))
1080Sstevel@tonic-gate 		error(gettext("macro defined as itself"));
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	install(ap[1], arg(2), mode);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate static void
dodefn(wchar_t ** ap,int c)1140Sstevel@tonic-gate dodefn(wchar_t **ap, int c)
1150Sstevel@tonic-gate {
1160Sstevel@tonic-gate 	wchar_t *d;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	while (c > 0)
1190Sstevel@tonic-gate 		if ((d = lookup(ap[c--])->def) != NULL) {
1200Sstevel@tonic-gate 			putbak(*rquote);
1210Sstevel@tonic-gate 			while (*d)
1220Sstevel@tonic-gate 				putbak(*d++);
1230Sstevel@tonic-gate 			putbak(*lquote);
1240Sstevel@tonic-gate 		}
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate static void
dodiv(wchar_t ** ap,int c)1280Sstevel@tonic-gate dodiv(wchar_t **ap, int c)
1290Sstevel@tonic-gate {
130291Smike_s 	int f;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	f = wstoi(arg(1));
1330Sstevel@tonic-gate 	if (f >= 10 || f < 0) {
1340Sstevel@tonic-gate 		cf = NULL;
1350Sstevel@tonic-gate 		ofx = f;
1360Sstevel@tonic-gate 		return;
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 	tempfile[7] = 'a'+f;
1390Sstevel@tonic-gate 	if (ofile[f] || (ofile[f] = xfopen(tempfile, "w"))) {
1400Sstevel@tonic-gate 		ofx = f;
1410Sstevel@tonic-gate 		cf = ofile[f];
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate /* ARGSUSED */
1460Sstevel@tonic-gate static void
dodivnum(wchar_t ** ap,int c)1470Sstevel@tonic-gate dodivnum(wchar_t **ap, int c)
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate 	pbnum((long)ofx);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate /* ARGSUSED */
1530Sstevel@tonic-gate static void
dodnl(wchar_t ** ap,int c)1540Sstevel@tonic-gate dodnl(wchar_t **ap, int c)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate 	wchar_t t;
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	while ((t = getchr()) != '\n' && t != WEOF)
1590Sstevel@tonic-gate 		;
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate static void
dodump(wchar_t ** ap,int c)1630Sstevel@tonic-gate dodump(wchar_t **ap, int c)
1640Sstevel@tonic-gate {
165291Smike_s 	struct nlist *np;
166291Smike_s 	int	i;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	if (c > 0)
1690Sstevel@tonic-gate 		while (c--) {
1700Sstevel@tonic-gate 			if ((np = lookup(*++ap))->name != NULL)
1710Sstevel@tonic-gate 				dump(np->name, np->def);
1720Sstevel@tonic-gate 		}
1730Sstevel@tonic-gate 	else
1740Sstevel@tonic-gate 		for (i = 0; i < hshsize; i++)
1750Sstevel@tonic-gate 			for (np = hshtab[i]; np != NULL; np = np->next)
1760Sstevel@tonic-gate 				dump(np->name, np->def);
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate 
179*6951Sab196087 /*ARGSUSED*/
1800Sstevel@tonic-gate static void
dump(wchar_t * name,wchar_t * defnn)1810Sstevel@tonic-gate dump(wchar_t *name, wchar_t *defnn)
1820Sstevel@tonic-gate {
1830Sstevel@tonic-gate 	wchar_t	*s = defnn;
1840Sstevel@tonic-gate 
185*6951Sab196087 #if !defined(__lint)	/* lint doesn't grok "%ws" */
1860Sstevel@tonic-gate 	(void) fprintf(stderr, "%ws:\t", name);
187*6951Sab196087 #endif
1880Sstevel@tonic-gate 
189*6951Sab196087 	while (*s++)
190*6951Sab196087 		;
1910Sstevel@tonic-gate 	--s;
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	while (s > defnn) {
1940Sstevel@tonic-gate 		--s;
195*6951Sab196087 		if (is_builtin(*s)) {
196*6951Sab196087 #if !defined(__lint)	/* lint doesn't grok "%ws" */
1970Sstevel@tonic-gate 			(void) fprintf(stderr, "<%ws>",
198*6951Sab196087 			    barray[builtin_idx(*s)].bname);
199*6951Sab196087 		} else {
200*6951Sab196087 #endif
2010Sstevel@tonic-gate 			(void) fputwc(*s, stderr);
2020Sstevel@tonic-gate 		}
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 	(void) fputc('\n', stderr);
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
207*6951Sab196087 /*ARGSUSED*/
2080Sstevel@tonic-gate static void
doerrp(wchar_t ** ap,int c)2090Sstevel@tonic-gate doerrp(wchar_t **ap, int c)
2100Sstevel@tonic-gate {
211*6951Sab196087 #if !defined(__lint)	/* lint doesn't grok "%ws" */
2120Sstevel@tonic-gate 	if (c > 0)
2130Sstevel@tonic-gate 		(void) fprintf(stderr, "%ws", ap[1]);
214*6951Sab196087 #endif
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate long	evalval;	/* return value from yacc stuff */
2180Sstevel@tonic-gate wchar_t	*pe;	/* used by grammar */
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate static void
doeval(wchar_t ** ap,int c)2210Sstevel@tonic-gate doeval(wchar_t **ap, int c)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate 	int base = wstoi(arg(2));
2240Sstevel@tonic-gate 	int pad = wstoi(arg(3));
2250Sstevel@tonic-gate 	extern	int yyparse(void);
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	evalval = 0;
2280Sstevel@tonic-gate 	if (c > 0) {
2290Sstevel@tonic-gate 		pe = ap[1];
2300Sstevel@tonic-gate 		if (yyparse() != 0)
2310Sstevel@tonic-gate 			error(gettext(
2320Sstevel@tonic-gate 			"invalid expression"));
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 	pbnbr(evalval, base > 0 ? base:10, pad > 0 ? pad : 1);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate  * doexit
2390Sstevel@tonic-gate  *
2400Sstevel@tonic-gate  * Process m4exit macro.
2410Sstevel@tonic-gate  */
2420Sstevel@tonic-gate static void
doexit(wchar_t ** ap,int c)2430Sstevel@tonic-gate doexit(wchar_t **ap, int c)
2440Sstevel@tonic-gate {
2450Sstevel@tonic-gate 	delexit(wstoi(arg(1)), 1);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate static void
doif(wchar_t ** ap,int c)2490Sstevel@tonic-gate doif(wchar_t **ap, int c)
2500Sstevel@tonic-gate {
2510Sstevel@tonic-gate 	if (c < 3)
2520Sstevel@tonic-gate 		return;
2530Sstevel@tonic-gate 	while (c >= 3) {
2540Sstevel@tonic-gate 		if (wcscmp(ap[1], ap[2]) == 0) {
2550Sstevel@tonic-gate 			pbstr(ap[3]);
2560Sstevel@tonic-gate 			return;
2570Sstevel@tonic-gate 		}
2580Sstevel@tonic-gate 		c -= 3;
2590Sstevel@tonic-gate 		ap += 3;
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 	if (c > 0)
2620Sstevel@tonic-gate 		pbstr(ap[1]);
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate static void
doifdef(wchar_t ** ap,int c)2660Sstevel@tonic-gate doifdef(wchar_t **ap, int c)
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate 	if (c < 2)
2690Sstevel@tonic-gate 		return;
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	while (c >= 2) {
2720Sstevel@tonic-gate 		if (lookup(ap[1])->name != NULL) {
2730Sstevel@tonic-gate 			pbstr(ap[2]);
2740Sstevel@tonic-gate 			return;
2750Sstevel@tonic-gate 		}
2760Sstevel@tonic-gate 		c -= 2;
2770Sstevel@tonic-gate 		ap += 2;
2780Sstevel@tonic-gate 	}
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	if (c > 0)
2810Sstevel@tonic-gate 		pbstr(ap[1]);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate static void
doincl(wchar_t ** ap,int c)2850Sstevel@tonic-gate doincl(wchar_t **ap, int c)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate 	incl(ap, c, 1);
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate static void
incl(wchar_t ** ap,int c,int noisy)2910Sstevel@tonic-gate incl(wchar_t **ap, int c, int noisy)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate 	if (c > 0 && wcslen(ap[1]) > 0) {
2940Sstevel@tonic-gate 		if (ifx >= 9)
2950Sstevel@tonic-gate 			error(gettext(
2960Sstevel@tonic-gate 			"input file nesting too deep (9)"));
2970Sstevel@tonic-gate 		if ((ifile[++ifx] = fopen(wstr2str(ap[1], 0), "r")) == NULL) {
2980Sstevel@tonic-gate 			--ifx;
2990Sstevel@tonic-gate 			if (noisy)
3000Sstevel@tonic-gate 				error(gettext(
3010Sstevel@tonic-gate 				"can't open file"));
3020Sstevel@tonic-gate 		} else {
3030Sstevel@tonic-gate 			ipstk[ifx] = ipflr = ip;
3040Sstevel@tonic-gate 			setfname(wstr2str(ap[1], 0));
3050Sstevel@tonic-gate 		}
3060Sstevel@tonic-gate 	}
3070Sstevel@tonic-gate }
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate static void
doincr(wchar_t ** ap,int c)3100Sstevel@tonic-gate doincr(wchar_t **ap, int c)
3110Sstevel@tonic-gate {
3120Sstevel@tonic-gate 	pbnum(ctol(arg(1))+1);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate static void
doindex(wchar_t ** ap,int c)3160Sstevel@tonic-gate doindex(wchar_t **ap, int c)
3170Sstevel@tonic-gate {
3180Sstevel@tonic-gate 	wchar_t	*subj = arg(1);
3190Sstevel@tonic-gate 	wchar_t	*obj  = arg(2);
320291Smike_s 	int	i;
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	for (i = 0; *subj; ++i)
3230Sstevel@tonic-gate 		if (leftmatch(subj++, obj)) {
3240Sstevel@tonic-gate 			pbnum((long)i);
3250Sstevel@tonic-gate 			return;
3260Sstevel@tonic-gate 		}
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	pbnum((long)-1);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate static int
leftmatch(wchar_t * str,wchar_t * substr)3320Sstevel@tonic-gate leftmatch(wchar_t *str, wchar_t *substr)
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate 	while (*substr)
3350Sstevel@tonic-gate 		if (*str++ != *substr++)
3360Sstevel@tonic-gate 			return (0);
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	return (1);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate static void
dolen(wchar_t ** ap,int c)3420Sstevel@tonic-gate dolen(wchar_t **ap, int c)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate 	pbnum((long)wcslen(arg(1)));
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate static void
domake(wchar_t ** ap,int c)3480Sstevel@tonic-gate domake(wchar_t **ap, int c)
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate 	char *path;
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	if (c > 0) {
3530Sstevel@tonic-gate 		path = wstr2str(ap[1], 1);
3540Sstevel@tonic-gate 		mkpid(path);
3550Sstevel@tonic-gate 		pbstr(str2wstr(path, 0));
3560Sstevel@tonic-gate 		free(path);
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate static void
dopopdef(wchar_t ** ap,int c)3610Sstevel@tonic-gate dopopdef(wchar_t **ap, int c)
3620Sstevel@tonic-gate {
363291Smike_s 	int	i;
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	for (i = 1; i <= c; ++i)
3660Sstevel@tonic-gate 		(void) undef(ap[i]);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate static void
dopushdef(wchar_t ** ap,int c)3700Sstevel@tonic-gate dopushdef(wchar_t **ap, int c)
3710Sstevel@tonic-gate {
3720Sstevel@tonic-gate 	def(ap, c, PUSH);
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate static void
doshift(wchar_t ** ap,int c)3760Sstevel@tonic-gate doshift(wchar_t **ap, int c)
3770Sstevel@tonic-gate {
3780Sstevel@tonic-gate 	if (c <= 1)
3790Sstevel@tonic-gate 		return;
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	for (;;) {
3820Sstevel@tonic-gate 		pbstr(rquote);
3830Sstevel@tonic-gate 		pbstr(ap[c--]);
3840Sstevel@tonic-gate 		pbstr(lquote);
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 		if (c <= 1)
3870Sstevel@tonic-gate 			break;
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 		pbstr(L",");
3900Sstevel@tonic-gate 	}
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate static void
dosincl(wchar_t ** ap,int c)3940Sstevel@tonic-gate dosincl(wchar_t **ap, int c)
3950Sstevel@tonic-gate {
3960Sstevel@tonic-gate 	incl(ap, c, 0);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate static void
dosubstr(wchar_t ** ap,int c)4000Sstevel@tonic-gate dosubstr(wchar_t **ap, int c)
4010Sstevel@tonic-gate {
4020Sstevel@tonic-gate 	wchar_t	*str;
4030Sstevel@tonic-gate 	int	inlen, outlen;
4040Sstevel@tonic-gate 	int	offset, ix;
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	inlen = wcslen(str = arg(1));
4070Sstevel@tonic-gate 	offset = wstoi(arg(2));
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	if (offset < 0 || offset >= inlen)
4100Sstevel@tonic-gate 		return;
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	outlen = c >= 3 ? wstoi(ap[3]) : inlen;
4130Sstevel@tonic-gate 	ix = min(offset+outlen, inlen);
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	while (ix > offset)
4160Sstevel@tonic-gate 		putbak(str[--ix]);
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate static void
dosyscmd(wchar_t ** ap,int c)4200Sstevel@tonic-gate dosyscmd(wchar_t **ap, int c)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 	sysrval = 0;
4230Sstevel@tonic-gate 	if (c > 0) {
4240Sstevel@tonic-gate 		(void) fflush(stdout);
4250Sstevel@tonic-gate 		sysrval = system(wstr2str(ap[1], 0));
4260Sstevel@tonic-gate 	}
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate /* ARGSUSED */
4300Sstevel@tonic-gate static void
dosysval(wchar_t ** ap,int c)4310Sstevel@tonic-gate dosysval(wchar_t **ap, int c)
4320Sstevel@tonic-gate {
4330Sstevel@tonic-gate 	pbnum((long)(sysrval < 0 ? sysrval :
434*6951Sab196087 	    (sysrval >> 8) & ((1 << 8) - 1)) |
435*6951Sab196087 	    ((sysrval & ((1 << 8) - 1)) << 8));
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate static void
dotransl(wchar_t ** ap,int c)4390Sstevel@tonic-gate dotransl(wchar_t **ap, int c)
4400Sstevel@tonic-gate {
4410Sstevel@tonic-gate 	wchar_t	*sink, *fr, *sto;
4420Sstevel@tonic-gate 	wchar_t	*source, *to;
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	if (c < 1)
4450Sstevel@tonic-gate 		return;
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 	sink = ap[1];
4480Sstevel@tonic-gate 	fr = arg(2);
4490Sstevel@tonic-gate 	sto = arg(3);
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	for (source = ap[1]; *source; source++) {
4520Sstevel@tonic-gate 		wchar_t	*i;
4530Sstevel@tonic-gate 		to = sto;
4540Sstevel@tonic-gate 		for (i = fr; *i; ++i) {
4550Sstevel@tonic-gate 			if (*source == *i)
4560Sstevel@tonic-gate 				break;
4570Sstevel@tonic-gate 			if (*to)
4580Sstevel@tonic-gate 				++to;
4590Sstevel@tonic-gate 		}
4600Sstevel@tonic-gate 		if (*i) {
4610Sstevel@tonic-gate 			if (*to)
4620Sstevel@tonic-gate 				*sink++ = *to;
4630Sstevel@tonic-gate 		} else
4640Sstevel@tonic-gate 			*sink++ = *source;
4650Sstevel@tonic-gate 	}
4660Sstevel@tonic-gate 	*sink = EOS;
4670Sstevel@tonic-gate 	pbstr(ap[1]);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate static void
dotroff(wchar_t ** ap,int c)4710Sstevel@tonic-gate dotroff(wchar_t **ap, int c)
4720Sstevel@tonic-gate {
473291Smike_s 	struct nlist	*np;
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	trace = 0;
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 	while (c > 0)
4780Sstevel@tonic-gate 		if ((np = lookup(ap[c--]))->name)
4790Sstevel@tonic-gate 			np->tflag = 0;
4800Sstevel@tonic-gate }
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate static void
dotron(wchar_t ** ap,int c)4830Sstevel@tonic-gate dotron(wchar_t **ap, int c)
4840Sstevel@tonic-gate {
485291Smike_s 	struct nlist	*np;
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	trace = !*arg(1);
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	while (c > 0)
4900Sstevel@tonic-gate 		if ((np = lookup(ap[c--]))->name)
4910Sstevel@tonic-gate 			np->tflag = 1;
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate void
doundef(wchar_t ** ap,int c)4950Sstevel@tonic-gate doundef(wchar_t **ap, int c)
4960Sstevel@tonic-gate {
497291Smike_s 	int	i;
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	for (i = 1; i <= c; ++i)
5000Sstevel@tonic-gate 		while (undef(ap[i]))
5010Sstevel@tonic-gate 			;
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate int
undef(wchar_t * nam)5050Sstevel@tonic-gate undef(wchar_t *nam)
5060Sstevel@tonic-gate {
507291Smike_s 	struct	nlist *np, *tnp;
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	if ((np = lookup(nam))->name == NULL)
5100Sstevel@tonic-gate 		return (0);
5110Sstevel@tonic-gate 	tnp = hshtab[hshval];	/* lookup sets hshval */
5120Sstevel@tonic-gate 	if (tnp == np)	/* it's in first place */
5130Sstevel@tonic-gate 		hshtab[hshval] = tnp->next;
5140Sstevel@tonic-gate 	else {
5150Sstevel@tonic-gate 		while (tnp->next != np)
5160Sstevel@tonic-gate 			tnp = tnp->next;
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 		tnp->next = np->next;
5190Sstevel@tonic-gate 	}
5200Sstevel@tonic-gate 	free(np->name);
5210Sstevel@tonic-gate 	free(np->def);
5220Sstevel@tonic-gate 	free(np);
5230Sstevel@tonic-gate 	return (1);
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate static void
doundiv(wchar_t ** ap,int c)5270Sstevel@tonic-gate doundiv(wchar_t **ap, int c)
5280Sstevel@tonic-gate {
529291Smike_s 	int i;
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	if (c <= 0)
5320Sstevel@tonic-gate 		for (i = 1; i < 10; i++)
5330Sstevel@tonic-gate 			undiv(i, OK);
5340Sstevel@tonic-gate 	else
5350Sstevel@tonic-gate 		while (--c >= 0)
5360Sstevel@tonic-gate 			undiv(wstoi(*++ap), OK);
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate /*
5400Sstevel@tonic-gate  * dowrap
5410Sstevel@tonic-gate  *
5420Sstevel@tonic-gate  * Process m4wrap macro.
5430Sstevel@tonic-gate  */
5440Sstevel@tonic-gate static void
dowrap(wchar_t ** ap,int c)5450Sstevel@tonic-gate dowrap(wchar_t **ap, int c)
5460Sstevel@tonic-gate {
5470Sstevel@tonic-gate 	wchar_t	*a = arg(1);
5480Sstevel@tonic-gate 	struct Wrap *wrapentry;		/* entry for list of "m4wrap" strings */
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	wrapentry = xmalloc(sizeof (struct Wrap));
5510Sstevel@tonic-gate 	/* store m4wrap string */
5520Sstevel@tonic-gate 	wrapentry->wrapstr = wstrdup(a);
5530Sstevel@tonic-gate 	/* add this entry to the front of the list of Wrap entries */
5540Sstevel@tonic-gate 	wrapentry->nxt = wrapstart;
5550Sstevel@tonic-gate 	wrapstart = wrapentry;
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate static void
mkpid(char * as)5590Sstevel@tonic-gate mkpid(char *as)
5600Sstevel@tonic-gate {
5610Sstevel@tonic-gate 	char *s = as;
5620Sstevel@tonic-gate 	char *l;
5630Sstevel@tonic-gate 	char *first_X;
5640Sstevel@tonic-gate 	unsigned xcnt = 0;
5650Sstevel@tonic-gate 	char my_pid[32];
5660Sstevel@tonic-gate 	int pid_len;
5670Sstevel@tonic-gate 	int i = 0;
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 	/*
5700Sstevel@tonic-gate 	 * Count number of X.
5710Sstevel@tonic-gate 	 */
5720Sstevel@tonic-gate 	l = &s[strlen(s)-1];
5730Sstevel@tonic-gate 	while (l != as) {
5740Sstevel@tonic-gate 		if (*l == 'X') {
5750Sstevel@tonic-gate 			first_X = l;
5760Sstevel@tonic-gate 			l--;
5770Sstevel@tonic-gate 			xcnt++;
5780Sstevel@tonic-gate 		} else if (xcnt == 0)
5790Sstevel@tonic-gate 			l--;
5800Sstevel@tonic-gate 		else {
5810Sstevel@tonic-gate 			break;
5820Sstevel@tonic-gate 		}
5830Sstevel@tonic-gate 	}
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	/*
5860Sstevel@tonic-gate 	 *	1) If there is no X in the passed string,
5870Sstevel@tonic-gate 	 *		then it just return the passed string.
5880Sstevel@tonic-gate 	 *	2) If the length of the continuous right most X's of
5890Sstevel@tonic-gate 	 *	   the string is shorter than the length of pid,
5900Sstevel@tonic-gate 	 *		then right most X's will be substitued with
5910Sstevel@tonic-gate 	 *		upper digits of pid.
5920Sstevel@tonic-gate 	 *	3) If the length of the continuous right most X's of
5930Sstevel@tonic-gate 	 *	   the string is equat to the length of pid,
5940Sstevel@tonic-gate 	 *		then X's will be replaced with pid.
5950Sstevel@tonic-gate 	 *	4) If the lenght of the continuous right most X's of
5960Sstevel@tonic-gate 	 *	   the string is longer than the length of pid,
5970Sstevel@tonic-gate 	 *		then X's will have leading 0 followed by
5980Sstevel@tonic-gate 	 *		pid.
5990Sstevel@tonic-gate 	 */
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	/*
6020Sstevel@tonic-gate 	 * If there were no X, don't do anything.
6030Sstevel@tonic-gate 	 */
6040Sstevel@tonic-gate 	if (xcnt == 0)
6050Sstevel@tonic-gate 		return;
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 	/*
6080Sstevel@tonic-gate 	 * Get pid
6090Sstevel@tonic-gate 	 */
6100Sstevel@tonic-gate 	(void) snprintf(my_pid, sizeof (my_pid), "%d", (int)getpid());
6110Sstevel@tonic-gate 	pid_len = strlen(my_pid);
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	if (pid_len > xcnt)
6140Sstevel@tonic-gate 		my_pid[xcnt] = 0;
6150Sstevel@tonic-gate 	else if (pid_len < xcnt) {
6160Sstevel@tonic-gate 		while (xcnt != pid_len) {
6170Sstevel@tonic-gate 			*first_X++ = '0';
6180Sstevel@tonic-gate 			xcnt--;
6190Sstevel@tonic-gate 		}
6200Sstevel@tonic-gate 	}
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	/*
6230Sstevel@tonic-gate 	 * Copy pid
6240Sstevel@tonic-gate 	 */
6250Sstevel@tonic-gate 	while (i != xcnt)
6260Sstevel@tonic-gate 		*first_X++ = my_pid[i++];
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate struct bs	barray[] = {
6300Sstevel@tonic-gate 	dochcom,	L"changecom",
6310Sstevel@tonic-gate 	docq,		L"changequote",
6320Sstevel@tonic-gate 	dodecr,		L"decr",
6330Sstevel@tonic-gate 	dodef,		L"define",
6340Sstevel@tonic-gate 	dodefn,		L"defn",
6350Sstevel@tonic-gate 	dodiv,		L"divert",
6360Sstevel@tonic-gate 	dodivnum,	L"divnum",
6370Sstevel@tonic-gate 	dodnl,		L"dnl",
6380Sstevel@tonic-gate 	dodump,		L"dumpdef",
6390Sstevel@tonic-gate 	doerrp,		L"errprint",
6400Sstevel@tonic-gate 	doeval,		L"eval",
6410Sstevel@tonic-gate 	doexit,		L"m4exit",
6420Sstevel@tonic-gate 	doif,		L"ifelse",
6430Sstevel@tonic-gate 	doifdef,	L"ifdef",
6440Sstevel@tonic-gate 	doincl,		L"include",
6450Sstevel@tonic-gate 	doincr,		L"incr",
6460Sstevel@tonic-gate 	doindex,	L"index",
6470Sstevel@tonic-gate 	dolen,		L"len",
6480Sstevel@tonic-gate 	domake,		L"maketemp",
6490Sstevel@tonic-gate 	dopopdef,	L"popdef",
6500Sstevel@tonic-gate 	dopushdef,	L"pushdef",
6510Sstevel@tonic-gate 	doshift,	L"shift",
6520Sstevel@tonic-gate 	dosincl,	L"sinclude",
6530Sstevel@tonic-gate 	dosubstr,	L"substr",
6540Sstevel@tonic-gate 	dosyscmd,	L"syscmd",
6550Sstevel@tonic-gate 	dosysval,	L"sysval",
6560Sstevel@tonic-gate 	dotransl,	L"translit",
6570Sstevel@tonic-gate 	dotroff,	L"traceoff",
6580Sstevel@tonic-gate 	dotron,		L"traceon",
6590Sstevel@tonic-gate 	doundef,	L"undefine",
6600Sstevel@tonic-gate 	doundiv,	L"undivert",
6610Sstevel@tonic-gate 	dowrap,		L"m4wrap",
6620Sstevel@tonic-gate 	0,		0
6630Sstevel@tonic-gate };
664