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(¶ms, 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