xref: /minix3/lib/libterminfo/tparm.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /* $NetBSD: tparm.c,v 1.15 2013/06/07 13:16:18 roy Exp $ */
251e66a47SVivek Prakash 
351e66a47SVivek Prakash /*
4*84d9c625SLionel Sambuc  * Copyright (c) 2009, 2011, 2013 The NetBSD Foundation, Inc.
551e66a47SVivek Prakash  *
651e66a47SVivek Prakash  * This code is derived from software contributed to The NetBSD Foundation
751e66a47SVivek Prakash  * by Roy Marples.
851e66a47SVivek Prakash  *
951e66a47SVivek Prakash  * Redistribution and use in source and binary forms, with or without
1051e66a47SVivek Prakash  * modification, are permitted provided that the following conditions
1151e66a47SVivek Prakash  * are met:
1251e66a47SVivek Prakash  * 1. Redistributions of source code must retain the above copyright
1351e66a47SVivek Prakash  *    notice, this list of conditions and the following disclaimer.
1451e66a47SVivek Prakash  * 2. Redistributions in binary form must reproduce the above copyright
1551e66a47SVivek Prakash  *    notice, this list of conditions and the following disclaimer in the
1651e66a47SVivek Prakash  *    documentation and/or other materials provided with the distribution.
1751e66a47SVivek Prakash  *
1851e66a47SVivek Prakash  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1951e66a47SVivek Prakash  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2051e66a47SVivek Prakash  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2151e66a47SVivek Prakash  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2251e66a47SVivek Prakash  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2351e66a47SVivek Prakash  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2451e66a47SVivek Prakash  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2551e66a47SVivek Prakash  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2651e66a47SVivek Prakash  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2751e66a47SVivek Prakash  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2851e66a47SVivek Prakash  */
2951e66a47SVivek Prakash 
3051e66a47SVivek Prakash #include <sys/cdefs.h>
31*84d9c625SLionel Sambuc __RCSID("$NetBSD: tparm.c,v 1.15 2013/06/07 13:16:18 roy Exp $");
320c3ae37fSLionel Sambuc #include <sys/param.h>
3351e66a47SVivek Prakash 
3451e66a47SVivek Prakash #include <assert.h>
3551e66a47SVivek Prakash #include <ctype.h>
3651e66a47SVivek Prakash #include <errno.h>
3751e66a47SVivek Prakash #include <stdarg.h>
3851e66a47SVivek Prakash #include <stdio.h>
3951e66a47SVivek Prakash #include <stdlib.h>
4051e66a47SVivek Prakash #include <string.h>
4151e66a47SVivek Prakash #include <term_private.h>
4251e66a47SVivek Prakash #include <term.h>
4351e66a47SVivek Prakash 
44*84d9c625SLionel Sambuc #define LONG_STR_MAX ((CHAR_BIT * sizeof(long)) / 3)
45*84d9c625SLionel Sambuc #define BUFINC 128	/* Size to increament the terminal buffer by */
46*84d9c625SLionel Sambuc 
47*84d9c625SLionel Sambuc #define VA_LONG_LONG	1
48*84d9c625SLionel Sambuc #define VA_CHAR_INT	2
49*84d9c625SLionel Sambuc //#define VA_CHAR_LONG	3	/* No need for this yet */
50*84d9c625SLionel Sambuc 
5151e66a47SVivek Prakash static TERMINAL *dumbterm; /* For non thread safe functions */
5251e66a47SVivek Prakash 
5351e66a47SVivek Prakash typedef struct {
54*84d9c625SLionel Sambuc 	long nums[20];
5551e66a47SVivek Prakash 	char *strings[20];
5651e66a47SVivek Prakash 	size_t offset;
5751e66a47SVivek Prakash } TPSTACK;
5851e66a47SVivek Prakash 
5951e66a47SVivek Prakash typedef struct {
60*84d9c625SLionel Sambuc 	long num;
6151e66a47SVivek Prakash 	char *string;
6251e66a47SVivek Prakash } TPVAR;
6351e66a47SVivek Prakash 
6451e66a47SVivek Prakash static int
push(long num,char * string,TPSTACK * stack)65*84d9c625SLionel Sambuc push(long num, char *string, TPSTACK *stack)
6651e66a47SVivek Prakash {
67*84d9c625SLionel Sambuc 	if (stack->offset >= sizeof(stack->nums)) {
6851e66a47SVivek Prakash 		errno = E2BIG;
6951e66a47SVivek Prakash 		return -1;
7051e66a47SVivek Prakash 	}
7151e66a47SVivek Prakash 	stack->nums[stack->offset] = num;
7251e66a47SVivek Prakash 	stack->strings[stack->offset] = string;
7351e66a47SVivek Prakash 	stack->offset++;
7451e66a47SVivek Prakash 	return 0;
7551e66a47SVivek Prakash }
7651e66a47SVivek Prakash 
7751e66a47SVivek Prakash static int
pop(long * num,char ** string,TPSTACK * stack)78*84d9c625SLionel Sambuc pop(long *num, char **string, TPSTACK *stack)
7951e66a47SVivek Prakash {
8051e66a47SVivek Prakash 	if (stack->offset == 0) {
810c3ae37fSLionel Sambuc 		if (num)
820c3ae37fSLionel Sambuc 			*num = 0;
830c3ae37fSLionel Sambuc 		if (string)
840c3ae37fSLionel Sambuc 			*string = NULL;
8551e66a47SVivek Prakash 		errno = E2BIG;
8651e66a47SVivek Prakash 		return -1;
8751e66a47SVivek Prakash 	}
8851e66a47SVivek Prakash 	stack->offset--;
8951e66a47SVivek Prakash 	if (num)
9051e66a47SVivek Prakash 		*num = stack->nums[stack->offset];
9151e66a47SVivek Prakash 	if (string)
9251e66a47SVivek Prakash 		*string = stack->strings[stack->offset];
9351e66a47SVivek Prakash 	return 0;
9451e66a47SVivek Prakash }
9551e66a47SVivek Prakash 
9651e66a47SVivek Prakash static char *
checkbuf(TERMINAL * term,size_t len)9751e66a47SVivek Prakash checkbuf(TERMINAL *term, size_t len)
9851e66a47SVivek Prakash {
9951e66a47SVivek Prakash 	char *buf;
10051e66a47SVivek Prakash 
10151e66a47SVivek Prakash 	if (term->_bufpos + len >= term->_buflen) {
102*84d9c625SLionel Sambuc 		len = term->_buflen + MAX(len, BUFINC);
10351e66a47SVivek Prakash 		buf = realloc(term->_buf, len);
10451e66a47SVivek Prakash 		if (buf == NULL)
1050c3ae37fSLionel Sambuc 			return NULL;
10651e66a47SVivek Prakash 		term->_buf = buf;
10751e66a47SVivek Prakash 		term->_buflen = len;
10851e66a47SVivek Prakash 	}
10951e66a47SVivek Prakash 	return term->_buf;
11051e66a47SVivek Prakash }
11151e66a47SVivek Prakash 
11251e66a47SVivek Prakash static size_t
ochar(TERMINAL * term,int c)11351e66a47SVivek Prakash ochar(TERMINAL *term, int c)
11451e66a47SVivek Prakash {
11551e66a47SVivek Prakash 	if (c == 0)
11651e66a47SVivek Prakash 		c = 0200;
11751e66a47SVivek Prakash 	/* Check we have space and a terminator */
11851e66a47SVivek Prakash 	if (checkbuf(term, 2) == NULL)
11951e66a47SVivek Prakash 		return 0;
12051e66a47SVivek Prakash 	term->_buf[term->_bufpos++] = (char)c;
12151e66a47SVivek Prakash 	return 1;
12251e66a47SVivek Prakash }
12351e66a47SVivek Prakash 
12451e66a47SVivek Prakash static size_t
onum(TERMINAL * term,const char * fmt,int num,unsigned int len)125*84d9c625SLionel Sambuc onum(TERMINAL *term, const char *fmt, int num, unsigned int len)
12651e66a47SVivek Prakash {
12751e66a47SVivek Prakash 	size_t l;
12851e66a47SVivek Prakash 
129*84d9c625SLionel Sambuc 	if (len < LONG_STR_MAX)
130*84d9c625SLionel Sambuc 		len = LONG_STR_MAX;
131*84d9c625SLionel Sambuc 	if (checkbuf(term, len + 2) == NULL)
13251e66a47SVivek Prakash 		return 0;
13351e66a47SVivek Prakash 	l = sprintf(term->_buf + term->_bufpos, fmt, num);
13451e66a47SVivek Prakash 	term->_bufpos += l;
13551e66a47SVivek Prakash 	return l;
13651e66a47SVivek Prakash }
13751e66a47SVivek Prakash 
138*84d9c625SLionel Sambuc /*
139*84d9c625SLionel Sambuc   Make a pass through the string so we can work out
140*84d9c625SLionel Sambuc   which parameters are ints and which are char *.
141*84d9c625SLionel Sambuc   Basically we only use char * if %p[1-9] is followed by %l or %s.
142*84d9c625SLionel Sambuc */
143*84d9c625SLionel Sambuc int
_ti_parm_analyse(const char * str,int * piss,int piss_len)144*84d9c625SLionel Sambuc _ti_parm_analyse(const char *str, int *piss, int piss_len)
14551e66a47SVivek Prakash {
146*84d9c625SLionel Sambuc 	int nparm, lpop;
147*84d9c625SLionel Sambuc 	char c;
148*84d9c625SLionel Sambuc 
149*84d9c625SLionel Sambuc 	nparm = 0;
150*84d9c625SLionel Sambuc 	lpop = -1;
151*84d9c625SLionel Sambuc 	while ((c = *str++) != '\0') {
152*84d9c625SLionel Sambuc 		if (c != '%')
153*84d9c625SLionel Sambuc 			continue;
154*84d9c625SLionel Sambuc 		c = *str++;
155*84d9c625SLionel Sambuc 		switch (c) {
156*84d9c625SLionel Sambuc 			case 'l': /* FALLTHROUGH */
157*84d9c625SLionel Sambuc 			case 's':
158*84d9c625SLionel Sambuc 				if (lpop > 0) {
159*84d9c625SLionel Sambuc 					if (lpop <= piss_len)
160*84d9c625SLionel Sambuc 						piss[lpop - 1] = 1;
161*84d9c625SLionel Sambuc 					else if (piss)
162*84d9c625SLionel Sambuc 						errno = E2BIG;
163*84d9c625SLionel Sambuc 				}
164*84d9c625SLionel Sambuc 				break;
165*84d9c625SLionel Sambuc 			case 'p':
166*84d9c625SLionel Sambuc 				c = *str++;
167*84d9c625SLionel Sambuc 				if (c < '1' || c > '9') {
168*84d9c625SLionel Sambuc 					errno = EINVAL;
169*84d9c625SLionel Sambuc 					continue;
170*84d9c625SLionel Sambuc 				} else {
171*84d9c625SLionel Sambuc 					lpop = c - '0';
172*84d9c625SLionel Sambuc 					if (lpop > nparm)
173*84d9c625SLionel Sambuc 						nparm = lpop;
174*84d9c625SLionel Sambuc 				}
175*84d9c625SLionel Sambuc 				break;
176*84d9c625SLionel Sambuc 			default:
177*84d9c625SLionel Sambuc 				lpop = -1;
178*84d9c625SLionel Sambuc 		}
179*84d9c625SLionel Sambuc 	}
180*84d9c625SLionel Sambuc 
181*84d9c625SLionel Sambuc 	return nparm;
182*84d9c625SLionel Sambuc }
183*84d9c625SLionel Sambuc 
184*84d9c625SLionel Sambuc static char *
_ti_tiparm(TERMINAL * term,const char * str,int va_type,va_list parms)185*84d9c625SLionel Sambuc _ti_tiparm(TERMINAL *term, const char *str, int va_type, va_list parms)
186*84d9c625SLionel Sambuc {
18751e66a47SVivek Prakash 	char c, fmt[64], *fp, *ostr;
188*84d9c625SLionel Sambuc 	long val, val2;
189*84d9c625SLionel Sambuc 	long dnums[26]; /* dynamic variables a-z, not preserved */
19051e66a47SVivek Prakash 	size_t l, max;
19151e66a47SVivek Prakash 	TPSTACK stack;
192*84d9c625SLionel Sambuc 	TPVAR params[TPARM_MAX];
193*84d9c625SLionel Sambuc 	unsigned int done, dot, minus, width, precision, olen;
194*84d9c625SLionel Sambuc 	int piss[TPARM_MAX]; /* Parameter IS String - piss ;) */
19551e66a47SVivek Prakash 
19651e66a47SVivek Prakash 	if (str == NULL)
19751e66a47SVivek Prakash 		return NULL;
19851e66a47SVivek Prakash 
19951e66a47SVivek Prakash 	/*
20051e66a47SVivek Prakash 	  If not passed a terminal, malloc a dummy one.
20151e66a47SVivek Prakash 	  This means we can preserve buffers and variables per terminal and
20251e66a47SVivek Prakash 	  still work with non thread safe functions (which sadly are still the
20351e66a47SVivek Prakash 	  norm and standard).
20451e66a47SVivek Prakash 	*/
20551e66a47SVivek Prakash 	if (term == NULL) {
20651e66a47SVivek Prakash 		if (dumbterm == NULL) {
20751e66a47SVivek Prakash 			dumbterm = malloc(sizeof(*dumbterm));
20851e66a47SVivek Prakash 			if (dumbterm == NULL)
20951e66a47SVivek Prakash 				return NULL;
21051e66a47SVivek Prakash 			dumbterm->_buflen = 0;
21151e66a47SVivek Prakash 		}
21251e66a47SVivek Prakash 		term = dumbterm;
21351e66a47SVivek Prakash 	}
21451e66a47SVivek Prakash 
21551e66a47SVivek Prakash 	term->_bufpos = 0;
21651e66a47SVivek Prakash 	/* Ensure we have an initial buffer */
21751e66a47SVivek Prakash 	if (term->_buflen == 0) {
218*84d9c625SLionel Sambuc 		term->_buf = malloc(BUFINC);
21951e66a47SVivek Prakash 		if (term->_buf == NULL)
22051e66a47SVivek Prakash 			return NULL;
221*84d9c625SLionel Sambuc 		term->_buflen = BUFINC;
22251e66a47SVivek Prakash 	}
22351e66a47SVivek Prakash 
22451e66a47SVivek Prakash 	memset(&piss, 0, sizeof(piss));
225*84d9c625SLionel Sambuc 	max = _ti_parm_analyse(str, piss, TPARM_MAX);
22651e66a47SVivek Prakash 
22751e66a47SVivek Prakash 	/* Put our parameters into variables */
22851e66a47SVivek Prakash 	memset(&params, 0, sizeof(params));
22951e66a47SVivek Prakash 	for (l = 0; l < max; l++) {
230*84d9c625SLionel Sambuc 		if (piss[l]) {
231*84d9c625SLionel Sambuc 			if (va_type == VA_LONG_LONG) {
232*84d9c625SLionel Sambuc 				/* This only works if char * fits into a long
233*84d9c625SLionel Sambuc 				 * on this platform. */
234*84d9c625SLionel Sambuc 				if (sizeof(char *) <= sizeof(long)/*CONSTCOND*/)
235*84d9c625SLionel Sambuc 					params[l].string =
236*84d9c625SLionel Sambuc 					    (char *)va_arg(parms, long);
237*84d9c625SLionel Sambuc 				else {
238*84d9c625SLionel Sambuc 					errno = ENOTSUP;
239*84d9c625SLionel Sambuc 					return NULL;
240*84d9c625SLionel Sambuc 				}
241*84d9c625SLionel Sambuc 			} else
24251e66a47SVivek Prakash 				params[l].string = va_arg(parms, char *);
243*84d9c625SLionel Sambuc 		} else {
244*84d9c625SLionel Sambuc 			if (va_type == VA_CHAR_INT)
245*84d9c625SLionel Sambuc 				params[l].num = (long)va_arg(parms, int);
246*84d9c625SLionel Sambuc 			else
247*84d9c625SLionel Sambuc 				params[l].num = va_arg(parms, long);
248*84d9c625SLionel Sambuc 		}
24951e66a47SVivek Prakash 	}
25051e66a47SVivek Prakash 
25151e66a47SVivek Prakash 	memset(&stack, 0, sizeof(stack));
25251e66a47SVivek Prakash 	while ((c = *str++) != '\0') {
25351e66a47SVivek Prakash 		if (c != '%' || (c = *str++) == '%') {
25451e66a47SVivek Prakash 			if (c == '\0')
25551e66a47SVivek Prakash 				break;
25651e66a47SVivek Prakash 			if (ochar(term, c) == 0)
25751e66a47SVivek Prakash 				return NULL;
25851e66a47SVivek Prakash 			continue;
25951e66a47SVivek Prakash 		}
26051e66a47SVivek Prakash 
26151e66a47SVivek Prakash 		/* Handle formatting. */
26251e66a47SVivek Prakash 		fp = fmt;
26351e66a47SVivek Prakash 		*fp++ = '%';
26451e66a47SVivek Prakash 		done = dot = minus = width = precision = 0;
26551e66a47SVivek Prakash 		val = 0;
26651e66a47SVivek Prakash 		while (done == 0 && (size_t)(fp - fmt) < sizeof(fmt)) {
26751e66a47SVivek Prakash 			switch (c) {
26851e66a47SVivek Prakash 			case 'c': /* FALLTHROUGH */
269*84d9c625SLionel Sambuc 			case 's':
270*84d9c625SLionel Sambuc 				*fp++ = c;
271*84d9c625SLionel Sambuc 				done = 1;
272*84d9c625SLionel Sambuc 				break;
27351e66a47SVivek Prakash 			case 'd': /* FALLTHROUGH */
27451e66a47SVivek Prakash 			case 'o': /* FALLTHROUGH */
27551e66a47SVivek Prakash 			case 'x': /* FALLTHROUGH */
27651e66a47SVivek Prakash 			case 'X': /* FALLTHROUGH */
277*84d9c625SLionel Sambuc 				*fp++ = 'l';
27851e66a47SVivek Prakash 				*fp++ = c;
27951e66a47SVivek Prakash 				done = 1;
28051e66a47SVivek Prakash 				break;
28151e66a47SVivek Prakash 			case '#': /* FALLTHROUGH */
28251e66a47SVivek Prakash 			case ' ':
28351e66a47SVivek Prakash 				*fp++ = c;
28451e66a47SVivek Prakash 				break;
28551e66a47SVivek Prakash 			case '.':
28651e66a47SVivek Prakash 				*fp++ = c;
28751e66a47SVivek Prakash 				if (dot == 0) {
28851e66a47SVivek Prakash 					dot = 1;
28951e66a47SVivek Prakash 					width = val;
29051e66a47SVivek Prakash 				} else
29151e66a47SVivek Prakash 					done = 2;
29251e66a47SVivek Prakash 				val = 0;
29351e66a47SVivek Prakash 				break;
29451e66a47SVivek Prakash 			case ':':
29551e66a47SVivek Prakash 				minus = 1;
29651e66a47SVivek Prakash 				break;
29751e66a47SVivek Prakash 			case '-':
29851e66a47SVivek Prakash 				if (minus)
29951e66a47SVivek Prakash 					*fp++ = c;
30051e66a47SVivek Prakash 				else
30151e66a47SVivek Prakash 					done = 1;
30251e66a47SVivek Prakash 				break;
30351e66a47SVivek Prakash 			default:
30451e66a47SVivek Prakash 				if (isdigit((unsigned char)c)) {
30551e66a47SVivek Prakash 					val = (val * 10) + (c - '0');
30651e66a47SVivek Prakash 					if (val > 10000)
30751e66a47SVivek Prakash 						done = 2;
30851e66a47SVivek Prakash 					else
30951e66a47SVivek Prakash 						*fp++ = c;
31051e66a47SVivek Prakash 				} else
31151e66a47SVivek Prakash 					done = 1;
31251e66a47SVivek Prakash 			}
31351e66a47SVivek Prakash 			if (done == 0)
31451e66a47SVivek Prakash 				c = *str++;
31551e66a47SVivek Prakash 		}
31651e66a47SVivek Prakash 		if (done == 2) {
31751e66a47SVivek Prakash 			/* Found an error in the format */
31851e66a47SVivek Prakash 			fp = fmt + 1;
31951e66a47SVivek Prakash 			*fp = *str;
32051e66a47SVivek Prakash 			olen = 0;
32151e66a47SVivek Prakash 		} else {
32251e66a47SVivek Prakash 			if (dot == 0)
32351e66a47SVivek Prakash 				width = val;
32451e66a47SVivek Prakash 			else
32551e66a47SVivek Prakash 				precision = val;
326*84d9c625SLionel Sambuc 			olen = MAX(width, precision);
32751e66a47SVivek Prakash 		}
32851e66a47SVivek Prakash 		*fp++ = '\0';
32951e66a47SVivek Prakash 
33051e66a47SVivek Prakash 		/* Handle commands */
33151e66a47SVivek Prakash 		switch (c) {
33251e66a47SVivek Prakash 		case 'c':
3330c3ae37fSLionel Sambuc 			pop(&val, NULL, &stack);
33451e66a47SVivek Prakash 			if (ochar(term, (unsigned char)val) == 0)
33551e66a47SVivek Prakash 				return NULL;
33651e66a47SVivek Prakash 			break;
33751e66a47SVivek Prakash 		case 's':
3380c3ae37fSLionel Sambuc 			pop(NULL, &ostr, &stack);
33951e66a47SVivek Prakash 			if (ostr != NULL) {
34051e66a47SVivek Prakash 				l = strlen(ostr);
34151e66a47SVivek Prakash 				if (l < (size_t)olen)
34251e66a47SVivek Prakash 					l = olen;
34351e66a47SVivek Prakash 				if (checkbuf(term, (size_t)(l + 1)) == NULL)
34451e66a47SVivek Prakash 					return NULL;
34551e66a47SVivek Prakash 				l = sprintf(term->_buf + term->_bufpos,
34651e66a47SVivek Prakash 				    fmt, ostr);
34751e66a47SVivek Prakash 				term->_bufpos += l;
34851e66a47SVivek Prakash 			}
34951e66a47SVivek Prakash 			break;
35051e66a47SVivek Prakash 		case 'l':
3510c3ae37fSLionel Sambuc 			pop(NULL, &ostr, &stack);
35251e66a47SVivek Prakash 			if (ostr == NULL)
35351e66a47SVivek Prakash 				l = 0;
35451e66a47SVivek Prakash 			else
35551e66a47SVivek Prakash 				l = strlen(ostr);
356*84d9c625SLionel Sambuc #ifdef NCURSES_COMPAT_57
357*84d9c625SLionel Sambuc 			if (onum(term, "%ld", (long)l, 0) == 0)
35851e66a47SVivek Prakash 				return NULL;
359*84d9c625SLionel Sambuc #else
360*84d9c625SLionel Sambuc 			push((long)l, NULL, &stack);
361*84d9c625SLionel Sambuc #endif
36251e66a47SVivek Prakash 			break;
36351e66a47SVivek Prakash 		case 'd': /* FALLTHROUGH */
36451e66a47SVivek Prakash 		case 'o': /* FALLTHROUGH */
36551e66a47SVivek Prakash 		case 'x': /* FALLTHROUGH */
36651e66a47SVivek Prakash 		case 'X':
3670c3ae37fSLionel Sambuc 			pop(&val, NULL, &stack);
368*84d9c625SLionel Sambuc 			if (onum(term, fmt, (int)val, olen) == 0)
36951e66a47SVivek Prakash 				return NULL;
37051e66a47SVivek Prakash 			break;
37151e66a47SVivek Prakash 		case 'p':
3720c3ae37fSLionel Sambuc 			if (*str < '1' || *str > '9')
3730c3ae37fSLionel Sambuc 				break;
37451e66a47SVivek Prakash 			l = *str++ - '1';
37551e66a47SVivek Prakash 			if (push(params[l].num, params[l].string, &stack))
37651e66a47SVivek Prakash 				return NULL;
37751e66a47SVivek Prakash 			break;
37851e66a47SVivek Prakash 		case 'P':
3790c3ae37fSLionel Sambuc 			pop(&val, NULL, &stack);
38051e66a47SVivek Prakash 			if (*str >= 'a' && *str <= 'z')
38151e66a47SVivek Prakash 				dnums[*str - 'a'] = val;
38251e66a47SVivek Prakash 			else if (*str >= 'A' && *str <= 'Z')
38351e66a47SVivek Prakash 				term->_snums[*str - 'A'] = val;
38451e66a47SVivek Prakash 			break;
38551e66a47SVivek Prakash 		case 'g':
38651e66a47SVivek Prakash 			if (*str >= 'a' && *str <= 'z') {
38751e66a47SVivek Prakash 				if (push(dnums[*str - 'a'], NULL, &stack))
38851e66a47SVivek Prakash 					return NULL;
38951e66a47SVivek Prakash 			} else if (*str >= 'A' && *str <= 'Z') {
39051e66a47SVivek Prakash 				if (push(term->_snums[*str - 'A'],
39151e66a47SVivek Prakash 					NULL, &stack))
39251e66a47SVivek Prakash 					return NULL;
39351e66a47SVivek Prakash 			}
39451e66a47SVivek Prakash 			break;
39551e66a47SVivek Prakash 		case 'i':
39651e66a47SVivek Prakash 			if (piss[0] == 0)
39751e66a47SVivek Prakash 				params[0].num++;
39851e66a47SVivek Prakash 			if (piss[1] == 0)
39951e66a47SVivek Prakash 				params[1].num++;
40051e66a47SVivek Prakash 			break;
40151e66a47SVivek Prakash 		case '\'':
402*84d9c625SLionel Sambuc 			if (push((long)(unsigned char)*str++, NULL, &stack))
40351e66a47SVivek Prakash 				return NULL;
40451e66a47SVivek Prakash 			while (*str != '\0' && *str != '\'')
40551e66a47SVivek Prakash 				str++;
40651e66a47SVivek Prakash 			if (*str == '\'')
40751e66a47SVivek Prakash 				str++;
40851e66a47SVivek Prakash 			break;
40951e66a47SVivek Prakash 		case '{':
41051e66a47SVivek Prakash 			val = 0;
4110c3ae37fSLionel Sambuc 			for (; isdigit((unsigned char)*str);  str++)
41251e66a47SVivek Prakash 				val = (val * 10) + (*str - '0');
41351e66a47SVivek Prakash 			if (push(val, NULL, &stack))
41451e66a47SVivek Prakash 				return NULL;
41551e66a47SVivek Prakash 			while (*str != '\0' && *str != '}')
41651e66a47SVivek Prakash 				str++;
41751e66a47SVivek Prakash 			if (*str == '}')
41851e66a47SVivek Prakash 				str++;
41951e66a47SVivek Prakash 			break;
42051e66a47SVivek Prakash 		case '+': /* FALLTHROUGH */
42151e66a47SVivek Prakash 		case '-': /* FALLTHROUGH */
42251e66a47SVivek Prakash 		case '*': /* FALLTHROUGH */
42351e66a47SVivek Prakash 		case '/': /* FALLTHROUGH */
42451e66a47SVivek Prakash 		case 'm': /* FALLTHROUGH */
42551e66a47SVivek Prakash 		case 'A': /* FALLTHROUGH */
42651e66a47SVivek Prakash 		case 'O': /* FALLTHROUGH */
42751e66a47SVivek Prakash 		case '&': /* FALLTHROUGH */
42851e66a47SVivek Prakash 		case '|': /* FALLTHROUGH */
42951e66a47SVivek Prakash 		case '^': /* FALLTHROUGH */
43051e66a47SVivek Prakash 		case '=': /* FALLTHROUGH */
43151e66a47SVivek Prakash 		case '<': /* FALLTHROUGH */
43251e66a47SVivek Prakash 		case '>':
4330c3ae37fSLionel Sambuc 			pop(&val, NULL, &stack);
4340c3ae37fSLionel Sambuc 			pop(&val2, NULL, &stack);
43551e66a47SVivek Prakash 			switch (c) {
43651e66a47SVivek Prakash 			case '+':
43751e66a47SVivek Prakash 				val = val + val2;
43851e66a47SVivek Prakash 				break;
43951e66a47SVivek Prakash 			case '-':
44051e66a47SVivek Prakash 				val = val2 - val;
44151e66a47SVivek Prakash 				break;
44251e66a47SVivek Prakash 			case '*':
44351e66a47SVivek Prakash 				val = val * val2;
44451e66a47SVivek Prakash 				break;
44551e66a47SVivek Prakash 			case '/':
44651e66a47SVivek Prakash 				val = val ? val2 / val : 0;
44751e66a47SVivek Prakash 				break;
44851e66a47SVivek Prakash 			case 'm':
44951e66a47SVivek Prakash 				val = val ? val2 % val : 0;
45051e66a47SVivek Prakash 				break;
45151e66a47SVivek Prakash 			case 'A':
45251e66a47SVivek Prakash 				val = val && val2;
45351e66a47SVivek Prakash 				break;
45451e66a47SVivek Prakash 			case 'O':
45551e66a47SVivek Prakash 				val = val || val2;
45651e66a47SVivek Prakash 				break;
45751e66a47SVivek Prakash 			case '&':
45851e66a47SVivek Prakash 				val = val & val2;
45951e66a47SVivek Prakash 				break;
46051e66a47SVivek Prakash 			case '|':
46151e66a47SVivek Prakash 				val = val | val2;
46251e66a47SVivek Prakash 				break;
46351e66a47SVivek Prakash 			case '^':
46451e66a47SVivek Prakash 				val = val ^ val2;
46551e66a47SVivek Prakash 				break;
46651e66a47SVivek Prakash 			case '=':
46751e66a47SVivek Prakash 				val = val == val2;
46851e66a47SVivek Prakash 				break;
46951e66a47SVivek Prakash 			case '<':
47051e66a47SVivek Prakash 				val = val2 < val;
47151e66a47SVivek Prakash 				break;
47251e66a47SVivek Prakash 			case '>':
47351e66a47SVivek Prakash 				val = val2 > val;
47451e66a47SVivek Prakash 				break;
47551e66a47SVivek Prakash 			}
47651e66a47SVivek Prakash 			if (push(val, NULL, &stack))
47751e66a47SVivek Prakash 				return NULL;
47851e66a47SVivek Prakash 			break;
47951e66a47SVivek Prakash 		case '!':
48051e66a47SVivek Prakash 		case '~':
4810c3ae37fSLionel Sambuc 			pop(&val, NULL, &stack);
482*84d9c625SLionel Sambuc 			switch (c) {
48351e66a47SVivek Prakash 			case '!':
48451e66a47SVivek Prakash 				val = !val;
48551e66a47SVivek Prakash 				break;
48651e66a47SVivek Prakash 			case '~':
48751e66a47SVivek Prakash 				val = ~val;
48851e66a47SVivek Prakash 				break;
48951e66a47SVivek Prakash 			}
49051e66a47SVivek Prakash 			if (push(val, NULL, &stack))
49151e66a47SVivek Prakash 				return NULL;
49251e66a47SVivek Prakash 			break;
49351e66a47SVivek Prakash 		case '?': /* if */
49451e66a47SVivek Prakash 			break;
49551e66a47SVivek Prakash 		case 't': /* then */
4960c3ae37fSLionel Sambuc 			pop(&val, NULL, &stack);
497*84d9c625SLionel Sambuc 			if (val == 0) {
49851e66a47SVivek Prakash 				l = 0;
49951e66a47SVivek Prakash 				for (; *str != '\0'; str++) {
50051e66a47SVivek Prakash 					if (*str != '%')
50151e66a47SVivek Prakash 						continue;
50251e66a47SVivek Prakash 					str++;
50351e66a47SVivek Prakash 					if (*str == '?')
50451e66a47SVivek Prakash 						l++;
50551e66a47SVivek Prakash 					else if (*str == ';') {
50651e66a47SVivek Prakash 						if (l > 0)
50751e66a47SVivek Prakash 							l--;
508*84d9c625SLionel Sambuc 						else {
509*84d9c625SLionel Sambuc 							str++;
51051e66a47SVivek Prakash 							break;
511*84d9c625SLionel Sambuc 						}
512*84d9c625SLionel Sambuc 					} else if (*str == 'e' && l == 0) {
513*84d9c625SLionel Sambuc 						str++;
51451e66a47SVivek Prakash 						break;
51551e66a47SVivek Prakash 					}
51651e66a47SVivek Prakash 				}
517*84d9c625SLionel Sambuc 			}
51851e66a47SVivek Prakash 			break;
51951e66a47SVivek Prakash 		case 'e': /* else */
52051e66a47SVivek Prakash 			l = 0;
52151e66a47SVivek Prakash 			for (; *str != '\0'; str++) {
52251e66a47SVivek Prakash 				if (*str != '%')
52351e66a47SVivek Prakash 					continue;
52451e66a47SVivek Prakash 				str++;
52551e66a47SVivek Prakash 				if (*str == '?')
52651e66a47SVivek Prakash 					l++;
52751e66a47SVivek Prakash 				else if (*str == ';') {
52851e66a47SVivek Prakash 					if (l > 0)
52951e66a47SVivek Prakash 						l--;
530*84d9c625SLionel Sambuc 					else {
531*84d9c625SLionel Sambuc 						str++;
53251e66a47SVivek Prakash 						break;
53351e66a47SVivek Prakash 					}
53451e66a47SVivek Prakash 				}
535*84d9c625SLionel Sambuc 			}
53651e66a47SVivek Prakash 			break;
53751e66a47SVivek Prakash 		case ';': /* fi */
53851e66a47SVivek Prakash 			break;
53951e66a47SVivek Prakash 		}
54051e66a47SVivek Prakash 	}
54151e66a47SVivek Prakash 	term->_buf[term->_bufpos] = '\0';
54251e66a47SVivek Prakash 	return term->_buf;
54351e66a47SVivek Prakash }
54451e66a47SVivek Prakash 
54551e66a47SVivek Prakash char *
ti_tiparm(TERMINAL * term,const char * str,...)5460c3ae37fSLionel Sambuc ti_tiparm(TERMINAL *term, const char *str, ...)
54751e66a47SVivek Prakash {
54851e66a47SVivek Prakash 	va_list va;
54951e66a47SVivek Prakash 	char *ret;
55051e66a47SVivek Prakash 
55151e66a47SVivek Prakash 	_DIAGASSERT(term != NULL);
55251e66a47SVivek Prakash 	_DIAGASSERT(str != NULL);
55351e66a47SVivek Prakash 
55451e66a47SVivek Prakash 	va_start(va, str);
555*84d9c625SLionel Sambuc 	ret = _ti_tiparm(term, str, VA_CHAR_INT, va);
55651e66a47SVivek Prakash 	va_end(va);
55751e66a47SVivek Prakash 	return ret;
55851e66a47SVivek Prakash }
55951e66a47SVivek Prakash 
56051e66a47SVivek Prakash char *
tiparm(const char * str,...)5610c3ae37fSLionel Sambuc tiparm(const char *str, ...)
56251e66a47SVivek Prakash {
56351e66a47SVivek Prakash 	va_list va;
56451e66a47SVivek Prakash 	char *ret;
56551e66a47SVivek Prakash 
56651e66a47SVivek Prakash 	_DIAGASSERT(str != NULL);
56751e66a47SVivek Prakash 
56851e66a47SVivek Prakash 	va_start(va, str);
569*84d9c625SLionel Sambuc 	ret = _ti_tiparm(NULL, str, VA_CHAR_INT, va);
570*84d9c625SLionel Sambuc 	va_end(va);
571*84d9c625SLionel Sambuc 	return ret;
572*84d9c625SLionel Sambuc }
573*84d9c625SLionel Sambuc 
574*84d9c625SLionel Sambuc #ifdef VA_CHAR_LONG
575*84d9c625SLionel Sambuc char *
ti_tlparm(TERMINAL * term,const char * str,...)576*84d9c625SLionel Sambuc ti_tlparm(TERMINAL *term, const char *str, ...)
577*84d9c625SLionel Sambuc {
578*84d9c625SLionel Sambuc 	va_list va;
579*84d9c625SLionel Sambuc 	char *ret;
580*84d9c625SLionel Sambuc 
581*84d9c625SLionel Sambuc 	_DIAGASSERT(term != NULL);
582*84d9c625SLionel Sambuc 	_DIAGASSERT(str != NULL);
583*84d9c625SLionel Sambuc 
584*84d9c625SLionel Sambuc 	va_start(va, str);
585*84d9c625SLionel Sambuc 	ret = _ti_tiparm(term, str, VA_CHAR_LONG, va);
586*84d9c625SLionel Sambuc 	va_end(va);
587*84d9c625SLionel Sambuc 	return ret;
588*84d9c625SLionel Sambuc }
589*84d9c625SLionel Sambuc 
590*84d9c625SLionel Sambuc char *
tlparm(const char * str,...)591*84d9c625SLionel Sambuc tlparm(const char *str, ...)
592*84d9c625SLionel Sambuc {
593*84d9c625SLionel Sambuc 	va_list va;
594*84d9c625SLionel Sambuc 	char *ret;
595*84d9c625SLionel Sambuc 
596*84d9c625SLionel Sambuc 	_DIAGASSERT(str != NULL);
597*84d9c625SLionel Sambuc 
598*84d9c625SLionel Sambuc 	va_start(va, str);
599*84d9c625SLionel Sambuc 	ret = _ti_tiparm(NULL, str, VA_CHAR_LONG, va);
600*84d9c625SLionel Sambuc 	va_end(va);
601*84d9c625SLionel Sambuc 	return ret;
602*84d9c625SLionel Sambuc }
603*84d9c625SLionel Sambuc #endif
604*84d9c625SLionel Sambuc 
605*84d9c625SLionel Sambuc static char *
_tparm(const char * str,...)606*84d9c625SLionel Sambuc _tparm(const char *str, ...)
607*84d9c625SLionel Sambuc {
608*84d9c625SLionel Sambuc 	va_list va;
609*84d9c625SLionel Sambuc 	char *ret;
610*84d9c625SLionel Sambuc 
611*84d9c625SLionel Sambuc 	_DIAGASSERT(str != NULL);
612*84d9c625SLionel Sambuc 
613*84d9c625SLionel Sambuc 	va_start(va, str);
614*84d9c625SLionel Sambuc 	ret = _ti_tiparm(NULL, str, VA_LONG_LONG, va);
61551e66a47SVivek Prakash 	va_end(va);
61651e66a47SVivek Prakash 	return ret;
61751e66a47SVivek Prakash }
61851e66a47SVivek Prakash 
61951e66a47SVivek Prakash char *
tparm(const char * str,long p1,long p2,long p3,long p4,long p5,long p6,long p7,long p8,long p9)62051e66a47SVivek Prakash tparm(const char *str,
621*84d9c625SLionel Sambuc     long p1, long p2, long p3, long p4, long p5,
622*84d9c625SLionel Sambuc     long p6, long p7, long p8, long p9)
62351e66a47SVivek Prakash {
62451e66a47SVivek Prakash 
625*84d9c625SLionel Sambuc 	return _tparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9);
62651e66a47SVivek Prakash }
627