xref: /titanic_52/usr/src/cmd/sgs/m4/common/m4macs.c (revision 447603b54aaea470ed1dcdb5c52d0be1d7801f84)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51dd08564Sab196087  * Common Development and Distribution License (the "License").
61dd08564Sab196087  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate /*
231dd08564Sab196087  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*447603b5SGary Mills /*
28*447603b5SGary Mills  * Copyright (c) 2011 Gary Mills
29*447603b5SGary Mills  */
30*447603b5SGary Mills 
319fb11590Smike_s /*	Copyright (c) 1988 AT&T	*/
329fb11590Smike_s /*	  All Rights Reserved  	*/
339fb11590Smike_s 
347c478bd9Sstevel@tonic-gate #include	<limits.h>
357c478bd9Sstevel@tonic-gate #include	<unistd.h>
367c478bd9Sstevel@tonic-gate #include	<sys/types.h>
377c478bd9Sstevel@tonic-gate #include	"m4.h"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #define	arg(n)	(c < (n) ? nullstr: ap[n])
407c478bd9Sstevel@tonic-gate static void mkpid(char *);
417c478bd9Sstevel@tonic-gate static void def(wchar_t **, int, int);
427c478bd9Sstevel@tonic-gate static void dump(wchar_t *, wchar_t *);
437c478bd9Sstevel@tonic-gate static void incl(wchar_t **, int, int);
447c478bd9Sstevel@tonic-gate static int leftmatch(wchar_t *, wchar_t *);
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate static void
477c478bd9Sstevel@tonic-gate dochcom(wchar_t **ap, int c)
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate 	wchar_t	*l = arg(1);
507c478bd9Sstevel@tonic-gate 	wchar_t	*r = arg(2);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate 	if (wcslen(l) > MAXSYM || wcslen(r) > MAXSYM)
537c478bd9Sstevel@tonic-gate 		error2(gettext(
547c478bd9Sstevel@tonic-gate 		"comment marker longer than %d chars"), MAXSYM);
557c478bd9Sstevel@tonic-gate 	(void) wcscpy(lcom, l);
567c478bd9Sstevel@tonic-gate 	(void) wcscpy(rcom, *r ? r : L"\n");
577c478bd9Sstevel@tonic-gate }
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate static void
607c478bd9Sstevel@tonic-gate docq(wchar_t **ap, int c)
617c478bd9Sstevel@tonic-gate {
627c478bd9Sstevel@tonic-gate 	wchar_t	*l = arg(1);
637c478bd9Sstevel@tonic-gate 	wchar_t	*r = arg(2);
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	if (wcslen(l) > MAXSYM || wcslen(r) > MAXSYM)
667c478bd9Sstevel@tonic-gate 		error2(gettext(
677c478bd9Sstevel@tonic-gate 		"quote marker longer than %d chars"), MAXSYM);
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	if (c <= 1 && !*l) {
707c478bd9Sstevel@tonic-gate 		l = L"`";
717c478bd9Sstevel@tonic-gate 		r = L"'";
727c478bd9Sstevel@tonic-gate 	} else if (c == 1) {
737c478bd9Sstevel@tonic-gate 		r = l;
747c478bd9Sstevel@tonic-gate 	}
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	(void) wcscpy(lquote, l);
777c478bd9Sstevel@tonic-gate 	(void) wcscpy(rquote, r);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate static void
817c478bd9Sstevel@tonic-gate dodecr(wchar_t **ap, int c)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	pbnum(ctol(arg(1))-1);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate void
877c478bd9Sstevel@tonic-gate dodef(wchar_t **ap, int c)
887c478bd9Sstevel@tonic-gate {
897c478bd9Sstevel@tonic-gate 	def(ap, c, NOPUSH);
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate static void
937c478bd9Sstevel@tonic-gate def(wchar_t **ap, int c, int mode)
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	wchar_t	*s;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	if (c < 1)
987c478bd9Sstevel@tonic-gate 		return;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	s = ap[1];
1017c478bd9Sstevel@tonic-gate 	if (is_alpha(*s) || *s == '_') {
1027c478bd9Sstevel@tonic-gate 		s++;
1037c478bd9Sstevel@tonic-gate 		while (is_alnum(*s) || *s == '_')
1047c478bd9Sstevel@tonic-gate 			s++;
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 	if (*s || s == ap[1])
1077c478bd9Sstevel@tonic-gate 		error(gettext("bad macro name"));
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	if ((ap[2] != NULL) && (wcscmp(ap[1], ap[2]) == 0))
1107c478bd9Sstevel@tonic-gate 		error(gettext("macro defined as itself"));
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	install(ap[1], arg(2), mode);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate static void
1167c478bd9Sstevel@tonic-gate dodefn(wchar_t **ap, int c)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate 	wchar_t *d;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	while (c > 0)
1217c478bd9Sstevel@tonic-gate 		if ((d = lookup(ap[c--])->def) != NULL) {
1227c478bd9Sstevel@tonic-gate 			putbak(*rquote);
1237c478bd9Sstevel@tonic-gate 			while (*d)
1247c478bd9Sstevel@tonic-gate 				putbak(*d++);
1257c478bd9Sstevel@tonic-gate 			putbak(*lquote);
1267c478bd9Sstevel@tonic-gate 		}
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate static void
1307c478bd9Sstevel@tonic-gate dodiv(wchar_t **ap, int c)
1317c478bd9Sstevel@tonic-gate {
1329fb11590Smike_s 	int f;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	f = wstoi(arg(1));
1357c478bd9Sstevel@tonic-gate 	if (f >= 10 || f < 0) {
1367c478bd9Sstevel@tonic-gate 		cf = NULL;
1377c478bd9Sstevel@tonic-gate 		ofx = f;
1387c478bd9Sstevel@tonic-gate 		return;
1397c478bd9Sstevel@tonic-gate 	}
1407c478bd9Sstevel@tonic-gate 	tempfile[7] = 'a'+f;
1417c478bd9Sstevel@tonic-gate 	if (ofile[f] || (ofile[f] = xfopen(tempfile, "w"))) {
1427c478bd9Sstevel@tonic-gate 		ofx = f;
1437c478bd9Sstevel@tonic-gate 		cf = ofile[f];
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate /* ARGSUSED */
1487c478bd9Sstevel@tonic-gate static void
1497c478bd9Sstevel@tonic-gate dodivnum(wchar_t **ap, int c)
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate 	pbnum((long)ofx);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate /* ARGSUSED */
1557c478bd9Sstevel@tonic-gate static void
1567c478bd9Sstevel@tonic-gate dodnl(wchar_t **ap, int c)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate 	wchar_t t;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	while ((t = getchr()) != '\n' && t != WEOF)
1617c478bd9Sstevel@tonic-gate 		;
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate static void
1657c478bd9Sstevel@tonic-gate dodump(wchar_t **ap, int c)
1667c478bd9Sstevel@tonic-gate {
1679fb11590Smike_s 	struct nlist *np;
1689fb11590Smike_s 	int	i;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	if (c > 0)
1717c478bd9Sstevel@tonic-gate 		while (c--) {
1727c478bd9Sstevel@tonic-gate 			if ((np = lookup(*++ap))->name != NULL)
1737c478bd9Sstevel@tonic-gate 				dump(np->name, np->def);
1747c478bd9Sstevel@tonic-gate 		}
1757c478bd9Sstevel@tonic-gate 	else
1767c478bd9Sstevel@tonic-gate 		for (i = 0; i < hshsize; i++)
1777c478bd9Sstevel@tonic-gate 			for (np = hshtab[i]; np != NULL; np = np->next)
1787c478bd9Sstevel@tonic-gate 				dump(np->name, np->def);
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate 
1811dd08564Sab196087 /*ARGSUSED*/
1827c478bd9Sstevel@tonic-gate static void
1837c478bd9Sstevel@tonic-gate dump(wchar_t *name, wchar_t *defnn)
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate 	wchar_t	*s = defnn;
1867c478bd9Sstevel@tonic-gate 
1871dd08564Sab196087 #if !defined(__lint)	/* lint doesn't grok "%ws" */
1887c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%ws:\t", name);
1891dd08564Sab196087 #endif
1907c478bd9Sstevel@tonic-gate 
1911dd08564Sab196087 	while (*s++)
1921dd08564Sab196087 		;
1937c478bd9Sstevel@tonic-gate 	--s;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	while (s > defnn) {
1967c478bd9Sstevel@tonic-gate 		--s;
1971dd08564Sab196087 		if (is_builtin(*s)) {
1981dd08564Sab196087 #if !defined(__lint)	/* lint doesn't grok "%ws" */
1997c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "<%ws>",
2007c478bd9Sstevel@tonic-gate 			    barray[builtin_idx(*s)].bname);
2011dd08564Sab196087 		} else {
2021dd08564Sab196087 #endif
2037c478bd9Sstevel@tonic-gate 			(void) fputwc(*s, stderr);
2047c478bd9Sstevel@tonic-gate 		}
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 	(void) fputc('\n', stderr);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2091dd08564Sab196087 /*ARGSUSED*/
2107c478bd9Sstevel@tonic-gate static void
2117c478bd9Sstevel@tonic-gate doerrp(wchar_t **ap, int c)
2127c478bd9Sstevel@tonic-gate {
2131dd08564Sab196087 #if !defined(__lint)	/* lint doesn't grok "%ws" */
2147c478bd9Sstevel@tonic-gate 	if (c > 0)
2157c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%ws", ap[1]);
2161dd08564Sab196087 #endif
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate long	evalval;	/* return value from yacc stuff */
2207c478bd9Sstevel@tonic-gate wchar_t	*pe;	/* used by grammar */
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate static void
2237c478bd9Sstevel@tonic-gate doeval(wchar_t **ap, int c)
2247c478bd9Sstevel@tonic-gate {
2257c478bd9Sstevel@tonic-gate 	int base = wstoi(arg(2));
2267c478bd9Sstevel@tonic-gate 	int pad = wstoi(arg(3));
2277c478bd9Sstevel@tonic-gate 	extern	int yyparse(void);
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	evalval = 0;
2307c478bd9Sstevel@tonic-gate 	if (c > 0) {
2317c478bd9Sstevel@tonic-gate 		pe = ap[1];
2327c478bd9Sstevel@tonic-gate 		if (yyparse() != 0)
2337c478bd9Sstevel@tonic-gate 			error(gettext(
2347c478bd9Sstevel@tonic-gate 			"invalid expression"));
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 	pbnbr(evalval, base > 0 ? base:10, pad > 0 ? pad : 1);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate /*
2407c478bd9Sstevel@tonic-gate  * doexit
2417c478bd9Sstevel@tonic-gate  *
2427c478bd9Sstevel@tonic-gate  * Process m4exit macro.
2437c478bd9Sstevel@tonic-gate  */
2447c478bd9Sstevel@tonic-gate static void
2457c478bd9Sstevel@tonic-gate doexit(wchar_t **ap, int c)
2467c478bd9Sstevel@tonic-gate {
2477c478bd9Sstevel@tonic-gate 	delexit(wstoi(arg(1)), 1);
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate static void
2517c478bd9Sstevel@tonic-gate doif(wchar_t **ap, int c)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate 	if (c < 3)
2547c478bd9Sstevel@tonic-gate 		return;
2557c478bd9Sstevel@tonic-gate 	while (c >= 3) {
2567c478bd9Sstevel@tonic-gate 		if (wcscmp(ap[1], ap[2]) == 0) {
2577c478bd9Sstevel@tonic-gate 			pbstr(ap[3]);
2587c478bd9Sstevel@tonic-gate 			return;
2597c478bd9Sstevel@tonic-gate 		}
2607c478bd9Sstevel@tonic-gate 		c -= 3;
2617c478bd9Sstevel@tonic-gate 		ap += 3;
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 	if (c > 0)
2647c478bd9Sstevel@tonic-gate 		pbstr(ap[1]);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate static void
2687c478bd9Sstevel@tonic-gate doifdef(wchar_t **ap, int c)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 	if (c < 2)
2717c478bd9Sstevel@tonic-gate 		return;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	while (c >= 2) {
2747c478bd9Sstevel@tonic-gate 		if (lookup(ap[1])->name != NULL) {
2757c478bd9Sstevel@tonic-gate 			pbstr(ap[2]);
2767c478bd9Sstevel@tonic-gate 			return;
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 		c -= 2;
2797c478bd9Sstevel@tonic-gate 		ap += 2;
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if (c > 0)
2837c478bd9Sstevel@tonic-gate 		pbstr(ap[1]);
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate static void
2877c478bd9Sstevel@tonic-gate doincl(wchar_t **ap, int c)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate 	incl(ap, c, 1);
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate static void
2937c478bd9Sstevel@tonic-gate incl(wchar_t **ap, int c, int noisy)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate 	if (c > 0 && wcslen(ap[1]) > 0) {
2967c478bd9Sstevel@tonic-gate 		if (ifx >= 9)
2977c478bd9Sstevel@tonic-gate 			error(gettext(
2987c478bd9Sstevel@tonic-gate 			"input file nesting too deep (9)"));
2997c478bd9Sstevel@tonic-gate 		if ((ifile[++ifx] = fopen(wstr2str(ap[1], 0), "r")) == NULL) {
3007c478bd9Sstevel@tonic-gate 			--ifx;
3017c478bd9Sstevel@tonic-gate 			if (noisy)
302*447603b5SGary Mills 				errorf(gettext("cannot open file: %s"),
303*447603b5SGary Mills 				    strerror(errno));
3047c478bd9Sstevel@tonic-gate 		} else {
3057c478bd9Sstevel@tonic-gate 			ipstk[ifx] = ipflr = ip;
3067c478bd9Sstevel@tonic-gate 			setfname(wstr2str(ap[1], 0));
3077c478bd9Sstevel@tonic-gate 		}
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate static void
3127c478bd9Sstevel@tonic-gate doincr(wchar_t **ap, int c)
3137c478bd9Sstevel@tonic-gate {
3147c478bd9Sstevel@tonic-gate 	pbnum(ctol(arg(1))+1);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate static void
3187c478bd9Sstevel@tonic-gate doindex(wchar_t **ap, int c)
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate 	wchar_t	*subj = arg(1);
3217c478bd9Sstevel@tonic-gate 	wchar_t	*obj  = arg(2);
3229fb11590Smike_s 	int	i;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	for (i = 0; *subj; ++i)
3257c478bd9Sstevel@tonic-gate 		if (leftmatch(subj++, obj)) {
3267c478bd9Sstevel@tonic-gate 			pbnum((long)i);
3277c478bd9Sstevel@tonic-gate 			return;
3287c478bd9Sstevel@tonic-gate 		}
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	pbnum((long)-1);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate static int
3347c478bd9Sstevel@tonic-gate leftmatch(wchar_t *str, wchar_t *substr)
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate 	while (*substr)
3377c478bd9Sstevel@tonic-gate 		if (*str++ != *substr++)
3387c478bd9Sstevel@tonic-gate 			return (0);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	return (1);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate static void
3447c478bd9Sstevel@tonic-gate dolen(wchar_t **ap, int c)
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate 	pbnum((long)wcslen(arg(1)));
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate static void
3507c478bd9Sstevel@tonic-gate domake(wchar_t **ap, int c)
3517c478bd9Sstevel@tonic-gate {
3527c478bd9Sstevel@tonic-gate 	char *path;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	if (c > 0) {
3557c478bd9Sstevel@tonic-gate 		path = wstr2str(ap[1], 1);
3567c478bd9Sstevel@tonic-gate 		mkpid(path);
3577c478bd9Sstevel@tonic-gate 		pbstr(str2wstr(path, 0));
3587c478bd9Sstevel@tonic-gate 		free(path);
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate static void
3637c478bd9Sstevel@tonic-gate dopopdef(wchar_t **ap, int c)
3647c478bd9Sstevel@tonic-gate {
3659fb11590Smike_s 	int	i;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	for (i = 1; i <= c; ++i)
3687c478bd9Sstevel@tonic-gate 		(void) undef(ap[i]);
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate static void
3727c478bd9Sstevel@tonic-gate dopushdef(wchar_t **ap, int c)
3737c478bd9Sstevel@tonic-gate {
3747c478bd9Sstevel@tonic-gate 	def(ap, c, PUSH);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate static void
3787c478bd9Sstevel@tonic-gate doshift(wchar_t **ap, int c)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate 	if (c <= 1)
3817c478bd9Sstevel@tonic-gate 		return;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	for (;;) {
3847c478bd9Sstevel@tonic-gate 		pbstr(rquote);
3857c478bd9Sstevel@tonic-gate 		pbstr(ap[c--]);
3867c478bd9Sstevel@tonic-gate 		pbstr(lquote);
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 		if (c <= 1)
3897c478bd9Sstevel@tonic-gate 			break;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 		pbstr(L",");
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate static void
3967c478bd9Sstevel@tonic-gate dosincl(wchar_t **ap, int c)
3977c478bd9Sstevel@tonic-gate {
3987c478bd9Sstevel@tonic-gate 	incl(ap, c, 0);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate static void
4027c478bd9Sstevel@tonic-gate dosubstr(wchar_t **ap, int c)
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate 	wchar_t	*str;
4057c478bd9Sstevel@tonic-gate 	int	inlen, outlen;
4067c478bd9Sstevel@tonic-gate 	int	offset, ix;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	inlen = wcslen(str = arg(1));
4097c478bd9Sstevel@tonic-gate 	offset = wstoi(arg(2));
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	if (offset < 0 || offset >= inlen)
4127c478bd9Sstevel@tonic-gate 		return;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	outlen = c >= 3 ? wstoi(ap[3]) : inlen;
4157c478bd9Sstevel@tonic-gate 	ix = min(offset+outlen, inlen);
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	while (ix > offset)
4187c478bd9Sstevel@tonic-gate 		putbak(str[--ix]);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate static void
4227c478bd9Sstevel@tonic-gate dosyscmd(wchar_t **ap, int c)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	sysrval = 0;
4257c478bd9Sstevel@tonic-gate 	if (c > 0) {
4267c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
4277c478bd9Sstevel@tonic-gate 		sysrval = system(wstr2str(ap[1], 0));
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate /* ARGSUSED */
4327c478bd9Sstevel@tonic-gate static void
4337c478bd9Sstevel@tonic-gate dosysval(wchar_t **ap, int c)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	pbnum((long)(sysrval < 0 ? sysrval :
4367c478bd9Sstevel@tonic-gate 	    (sysrval >> 8) & ((1 << 8) - 1)) |
4377c478bd9Sstevel@tonic-gate 	    ((sysrval & ((1 << 8) - 1)) << 8));
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate static void
4417c478bd9Sstevel@tonic-gate dotransl(wchar_t **ap, int c)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	wchar_t	*sink, *fr, *sto;
4447c478bd9Sstevel@tonic-gate 	wchar_t	*source, *to;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if (c < 1)
4477c478bd9Sstevel@tonic-gate 		return;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	sink = ap[1];
4507c478bd9Sstevel@tonic-gate 	fr = arg(2);
4517c478bd9Sstevel@tonic-gate 	sto = arg(3);
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	for (source = ap[1]; *source; source++) {
4547c478bd9Sstevel@tonic-gate 		wchar_t	*i;
4557c478bd9Sstevel@tonic-gate 		to = sto;
4567c478bd9Sstevel@tonic-gate 		for (i = fr; *i; ++i) {
4577c478bd9Sstevel@tonic-gate 			if (*source == *i)
4587c478bd9Sstevel@tonic-gate 				break;
4597c478bd9Sstevel@tonic-gate 			if (*to)
4607c478bd9Sstevel@tonic-gate 				++to;
4617c478bd9Sstevel@tonic-gate 		}
4627c478bd9Sstevel@tonic-gate 		if (*i) {
4637c478bd9Sstevel@tonic-gate 			if (*to)
4647c478bd9Sstevel@tonic-gate 				*sink++ = *to;
4657c478bd9Sstevel@tonic-gate 		} else
4667c478bd9Sstevel@tonic-gate 			*sink++ = *source;
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate 	*sink = EOS;
4697c478bd9Sstevel@tonic-gate 	pbstr(ap[1]);
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate static void
4737c478bd9Sstevel@tonic-gate dotroff(wchar_t **ap, int c)
4747c478bd9Sstevel@tonic-gate {
4759fb11590Smike_s 	struct nlist	*np;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	trace = 0;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	while (c > 0)
4807c478bd9Sstevel@tonic-gate 		if ((np = lookup(ap[c--]))->name)
4817c478bd9Sstevel@tonic-gate 			np->tflag = 0;
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate static void
4857c478bd9Sstevel@tonic-gate dotron(wchar_t **ap, int c)
4867c478bd9Sstevel@tonic-gate {
4879fb11590Smike_s 	struct nlist	*np;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	trace = !*arg(1);
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 	while (c > 0)
4927c478bd9Sstevel@tonic-gate 		if ((np = lookup(ap[c--]))->name)
4937c478bd9Sstevel@tonic-gate 			np->tflag = 1;
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate void
4977c478bd9Sstevel@tonic-gate doundef(wchar_t **ap, int c)
4987c478bd9Sstevel@tonic-gate {
4999fb11590Smike_s 	int	i;
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	for (i = 1; i <= c; ++i)
5027c478bd9Sstevel@tonic-gate 		while (undef(ap[i]))
5037c478bd9Sstevel@tonic-gate 			;
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate int
5077c478bd9Sstevel@tonic-gate undef(wchar_t *nam)
5087c478bd9Sstevel@tonic-gate {
5099fb11590Smike_s 	struct	nlist *np, *tnp;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	if ((np = lookup(nam))->name == NULL)
5127c478bd9Sstevel@tonic-gate 		return (0);
5137c478bd9Sstevel@tonic-gate 	tnp = hshtab[hshval];	/* lookup sets hshval */
5147c478bd9Sstevel@tonic-gate 	if (tnp == np)	/* it's in first place */
5157c478bd9Sstevel@tonic-gate 		hshtab[hshval] = tnp->next;
5167c478bd9Sstevel@tonic-gate 	else {
5177c478bd9Sstevel@tonic-gate 		while (tnp->next != np)
5187c478bd9Sstevel@tonic-gate 			tnp = tnp->next;
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 		tnp->next = np->next;
5217c478bd9Sstevel@tonic-gate 	}
5227c478bd9Sstevel@tonic-gate 	free(np->name);
5237c478bd9Sstevel@tonic-gate 	free(np->def);
5247c478bd9Sstevel@tonic-gate 	free(np);
5257c478bd9Sstevel@tonic-gate 	return (1);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate static void
5297c478bd9Sstevel@tonic-gate doundiv(wchar_t **ap, int c)
5307c478bd9Sstevel@tonic-gate {
5319fb11590Smike_s 	int i;
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	if (c <= 0)
5347c478bd9Sstevel@tonic-gate 		for (i = 1; i < 10; i++)
5357c478bd9Sstevel@tonic-gate 			undiv(i, OK);
5367c478bd9Sstevel@tonic-gate 	else
5377c478bd9Sstevel@tonic-gate 		while (--c >= 0)
5387c478bd9Sstevel@tonic-gate 			undiv(wstoi(*++ap), OK);
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate /*
5427c478bd9Sstevel@tonic-gate  * dowrap
5437c478bd9Sstevel@tonic-gate  *
5447c478bd9Sstevel@tonic-gate  * Process m4wrap macro.
5457c478bd9Sstevel@tonic-gate  */
5467c478bd9Sstevel@tonic-gate static void
5477c478bd9Sstevel@tonic-gate dowrap(wchar_t **ap, int c)
5487c478bd9Sstevel@tonic-gate {
5497c478bd9Sstevel@tonic-gate 	wchar_t	*a = arg(1);
5507c478bd9Sstevel@tonic-gate 	struct Wrap *wrapentry;		/* entry for list of "m4wrap" strings */
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	wrapentry = xmalloc(sizeof (struct Wrap));
5537c478bd9Sstevel@tonic-gate 	/* store m4wrap string */
5547c478bd9Sstevel@tonic-gate 	wrapentry->wrapstr = wstrdup(a);
5557c478bd9Sstevel@tonic-gate 	/* add this entry to the front of the list of Wrap entries */
5567c478bd9Sstevel@tonic-gate 	wrapentry->nxt = wrapstart;
5577c478bd9Sstevel@tonic-gate 	wrapstart = wrapentry;
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate static void
5617c478bd9Sstevel@tonic-gate mkpid(char *as)
5627c478bd9Sstevel@tonic-gate {
5637c478bd9Sstevel@tonic-gate 	char *s = as;
5647c478bd9Sstevel@tonic-gate 	char *l;
5657c478bd9Sstevel@tonic-gate 	char *first_X;
5667c478bd9Sstevel@tonic-gate 	unsigned xcnt = 0;
5677c478bd9Sstevel@tonic-gate 	char my_pid[32];
5687c478bd9Sstevel@tonic-gate 	int pid_len;
5697c478bd9Sstevel@tonic-gate 	int i = 0;
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	/*
5727c478bd9Sstevel@tonic-gate 	 * Count number of X.
5737c478bd9Sstevel@tonic-gate 	 */
5747c478bd9Sstevel@tonic-gate 	l = &s[strlen(s)-1];
5757c478bd9Sstevel@tonic-gate 	while (l != as) {
5767c478bd9Sstevel@tonic-gate 		if (*l == 'X') {
5777c478bd9Sstevel@tonic-gate 			first_X = l;
5787c478bd9Sstevel@tonic-gate 			l--;
5797c478bd9Sstevel@tonic-gate 			xcnt++;
5807c478bd9Sstevel@tonic-gate 		} else if (xcnt == 0)
5817c478bd9Sstevel@tonic-gate 			l--;
5827c478bd9Sstevel@tonic-gate 		else {
5837c478bd9Sstevel@tonic-gate 			break;
5847c478bd9Sstevel@tonic-gate 		}
5857c478bd9Sstevel@tonic-gate 	}
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	/*
5887c478bd9Sstevel@tonic-gate 	 *	1) If there is no X in the passed string,
5897c478bd9Sstevel@tonic-gate 	 *		then it just return the passed string.
5907c478bd9Sstevel@tonic-gate 	 *	2) If the length of the continuous right most X's of
5917c478bd9Sstevel@tonic-gate 	 *	   the string is shorter than the length of pid,
5927c478bd9Sstevel@tonic-gate 	 *		then right most X's will be substitued with
5937c478bd9Sstevel@tonic-gate 	 *		upper digits of pid.
5947c478bd9Sstevel@tonic-gate 	 *	3) If the length of the continuous right most X's of
5957c478bd9Sstevel@tonic-gate 	 *	   the string is equat to the length of pid,
5967c478bd9Sstevel@tonic-gate 	 *		then X's will be replaced with pid.
5977c478bd9Sstevel@tonic-gate 	 *	4) If the lenght of the continuous right most X's of
5987c478bd9Sstevel@tonic-gate 	 *	   the string is longer than the length of pid,
5997c478bd9Sstevel@tonic-gate 	 *		then X's will have leading 0 followed by
6007c478bd9Sstevel@tonic-gate 	 *		pid.
6017c478bd9Sstevel@tonic-gate 	 */
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	/*
6047c478bd9Sstevel@tonic-gate 	 * If there were no X, don't do anything.
6057c478bd9Sstevel@tonic-gate 	 */
6067c478bd9Sstevel@tonic-gate 	if (xcnt == 0)
6077c478bd9Sstevel@tonic-gate 		return;
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	/*
6107c478bd9Sstevel@tonic-gate 	 * Get pid
6117c478bd9Sstevel@tonic-gate 	 */
6127c478bd9Sstevel@tonic-gate 	(void) snprintf(my_pid, sizeof (my_pid), "%d", (int)getpid());
6137c478bd9Sstevel@tonic-gate 	pid_len = strlen(my_pid);
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	if (pid_len > xcnt)
6167c478bd9Sstevel@tonic-gate 		my_pid[xcnt] = 0;
6177c478bd9Sstevel@tonic-gate 	else if (pid_len < xcnt) {
6187c478bd9Sstevel@tonic-gate 		while (xcnt != pid_len) {
6197c478bd9Sstevel@tonic-gate 			*first_X++ = '0';
6207c478bd9Sstevel@tonic-gate 			xcnt--;
6217c478bd9Sstevel@tonic-gate 		}
6227c478bd9Sstevel@tonic-gate 	}
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	/*
6257c478bd9Sstevel@tonic-gate 	 * Copy pid
6267c478bd9Sstevel@tonic-gate 	 */
6277c478bd9Sstevel@tonic-gate 	while (i != xcnt)
6287c478bd9Sstevel@tonic-gate 		*first_X++ = my_pid[i++];
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate struct bs	barray[] = {
6327c478bd9Sstevel@tonic-gate 	dochcom,	L"changecom",
6337c478bd9Sstevel@tonic-gate 	docq,		L"changequote",
6347c478bd9Sstevel@tonic-gate 	dodecr,		L"decr",
6357c478bd9Sstevel@tonic-gate 	dodef,		L"define",
6367c478bd9Sstevel@tonic-gate 	dodefn,		L"defn",
6377c478bd9Sstevel@tonic-gate 	dodiv,		L"divert",
6387c478bd9Sstevel@tonic-gate 	dodivnum,	L"divnum",
6397c478bd9Sstevel@tonic-gate 	dodnl,		L"dnl",
6407c478bd9Sstevel@tonic-gate 	dodump,		L"dumpdef",
6417c478bd9Sstevel@tonic-gate 	doerrp,		L"errprint",
6427c478bd9Sstevel@tonic-gate 	doeval,		L"eval",
6437c478bd9Sstevel@tonic-gate 	doexit,		L"m4exit",
6447c478bd9Sstevel@tonic-gate 	doif,		L"ifelse",
6457c478bd9Sstevel@tonic-gate 	doifdef,	L"ifdef",
6467c478bd9Sstevel@tonic-gate 	doincl,		L"include",
6477c478bd9Sstevel@tonic-gate 	doincr,		L"incr",
6487c478bd9Sstevel@tonic-gate 	doindex,	L"index",
6497c478bd9Sstevel@tonic-gate 	dolen,		L"len",
6507c478bd9Sstevel@tonic-gate 	domake,		L"maketemp",
6517c478bd9Sstevel@tonic-gate 	dopopdef,	L"popdef",
6527c478bd9Sstevel@tonic-gate 	dopushdef,	L"pushdef",
6537c478bd9Sstevel@tonic-gate 	doshift,	L"shift",
6547c478bd9Sstevel@tonic-gate 	dosincl,	L"sinclude",
6557c478bd9Sstevel@tonic-gate 	dosubstr,	L"substr",
6567c478bd9Sstevel@tonic-gate 	dosyscmd,	L"syscmd",
6577c478bd9Sstevel@tonic-gate 	dosysval,	L"sysval",
6587c478bd9Sstevel@tonic-gate 	dotransl,	L"translit",
6597c478bd9Sstevel@tonic-gate 	dotroff,	L"traceoff",
6607c478bd9Sstevel@tonic-gate 	dotron,		L"traceon",
6617c478bd9Sstevel@tonic-gate 	doundef,	L"undefine",
6627c478bd9Sstevel@tonic-gate 	doundiv,	L"undivert",
6637c478bd9Sstevel@tonic-gate 	dowrap,		L"m4wrap",
6647c478bd9Sstevel@tonic-gate 	0,		0
6657c478bd9Sstevel@tonic-gate };
666