xref: /dflybsd-src/contrib/ncurses/ncurses/tinfo/lib_tparm.c (revision 0cadad7e49c6219b0de0675ef6a6f44683d177d4)
1fdd4e1e0SJan Lentfer /****************************************************************************
2*32bb5217SDaniel Fojt  * Copyright 2018-2019,2020 Thomas E. Dickey                                *
3*32bb5217SDaniel Fojt  * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
4fdd4e1e0SJan Lentfer  *                                                                          *
5fdd4e1e0SJan Lentfer  * Permission is hereby granted, free of charge, to any person obtaining a  *
6fdd4e1e0SJan Lentfer  * copy of this software and associated documentation files (the            *
7fdd4e1e0SJan Lentfer  * "Software"), to deal in the Software without restriction, including      *
8fdd4e1e0SJan Lentfer  * without limitation the rights to use, copy, modify, merge, publish,      *
9fdd4e1e0SJan Lentfer  * distribute, distribute with modifications, sublicense, and/or sell       *
10fdd4e1e0SJan Lentfer  * copies of the Software, and to permit persons to whom the Software is    *
11fdd4e1e0SJan Lentfer  * furnished to do so, subject to the following conditions:                 *
12fdd4e1e0SJan Lentfer  *                                                                          *
13fdd4e1e0SJan Lentfer  * The above copyright notice and this permission notice shall be included  *
14fdd4e1e0SJan Lentfer  * in all copies or substantial portions of the Software.                   *
15fdd4e1e0SJan Lentfer  *                                                                          *
16fdd4e1e0SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17fdd4e1e0SJan Lentfer  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18fdd4e1e0SJan Lentfer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19fdd4e1e0SJan Lentfer  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20fdd4e1e0SJan Lentfer  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21fdd4e1e0SJan Lentfer  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22fdd4e1e0SJan Lentfer  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23fdd4e1e0SJan Lentfer  *                                                                          *
24fdd4e1e0SJan Lentfer  * Except as contained in this notice, the name(s) of the above copyright   *
25fdd4e1e0SJan Lentfer  * holders shall not be used in advertising or otherwise to promote the     *
26fdd4e1e0SJan Lentfer  * sale, use or other dealings in this Software without prior written       *
27fdd4e1e0SJan Lentfer  * authorization.                                                           *
28fdd4e1e0SJan Lentfer  ****************************************************************************/
29fdd4e1e0SJan Lentfer 
30fdd4e1e0SJan Lentfer /****************************************************************************
31fdd4e1e0SJan Lentfer  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
32fdd4e1e0SJan Lentfer  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
33fdd4e1e0SJan Lentfer  *     and: Thomas E. Dickey, 1996 on                                       *
34fdd4e1e0SJan Lentfer  ****************************************************************************/
35fdd4e1e0SJan Lentfer 
36fdd4e1e0SJan Lentfer /*
37fdd4e1e0SJan Lentfer  *	tparm.c
38fdd4e1e0SJan Lentfer  *
39fdd4e1e0SJan Lentfer  */
40fdd4e1e0SJan Lentfer 
41fdd4e1e0SJan Lentfer #include <curses.priv.h>
42fdd4e1e0SJan Lentfer 
43fdd4e1e0SJan Lentfer #include <ctype.h>
44fdd4e1e0SJan Lentfer #include <tic.h>
45fdd4e1e0SJan Lentfer 
46*32bb5217SDaniel Fojt MODULE_ID("$Id: lib_tparm.c,v 1.108 2020/02/02 23:34:34 tom Exp $")
47fdd4e1e0SJan Lentfer 
48fdd4e1e0SJan Lentfer /*
49fdd4e1e0SJan Lentfer  *	char *
50fdd4e1e0SJan Lentfer  *	tparm(string, ...)
51fdd4e1e0SJan Lentfer  *
52fdd4e1e0SJan Lentfer  *	Substitute the given parameters into the given string by the following
53fdd4e1e0SJan Lentfer  *	rules (taken from terminfo(5)):
54fdd4e1e0SJan Lentfer  *
55fdd4e1e0SJan Lentfer  *	     Cursor addressing and other strings  requiring  parame-
56fdd4e1e0SJan Lentfer  *	ters in the terminal are described by a parameterized string
573468e90cSJohn Marino  *	capability, with escapes like %x in  it.   For  example,  to
58fdd4e1e0SJan Lentfer  *	address  the  cursor, the cup capability is given, using two
59fdd4e1e0SJan Lentfer  *	parameters: the row and column to  address  to.   (Rows  and
60fdd4e1e0SJan Lentfer  *	columns  are  numbered  from  zero and refer to the physical
61fdd4e1e0SJan Lentfer  *	screen visible to the user, not to any  unseen  memory.)  If
62fdd4e1e0SJan Lentfer  *	the terminal has memory relative cursor addressing, that can
63fdd4e1e0SJan Lentfer  *	be indicated by
64fdd4e1e0SJan Lentfer  *
65fdd4e1e0SJan Lentfer  *	     The parameter mechanism uses  a  stack  and  special  %
66fdd4e1e0SJan Lentfer  *	codes  to manipulate it.  Typically a sequence will push one
67fdd4e1e0SJan Lentfer  *	of the parameters onto the stack and then print it  in  some
68fdd4e1e0SJan Lentfer  *	format.  Often more complex operations are necessary.
69fdd4e1e0SJan Lentfer  *
70fdd4e1e0SJan Lentfer  *	     The % encodings have the following meanings:
71fdd4e1e0SJan Lentfer  *
72fdd4e1e0SJan Lentfer  *	     %%        outputs `%'
73fdd4e1e0SJan Lentfer  *	     %c        print pop() like %c in printf()
74fdd4e1e0SJan Lentfer  *	     %s        print pop() like %s in printf()
75fdd4e1e0SJan Lentfer  *           %[[:]flags][width[.precision]][doxXs]
76fdd4e1e0SJan Lentfer  *                     as in printf, flags are [-+#] and space
77fdd4e1e0SJan Lentfer  *                     The ':' is used to avoid making %+ or %-
78fdd4e1e0SJan Lentfer  *                     patterns (see below).
79fdd4e1e0SJan Lentfer  *
80fdd4e1e0SJan Lentfer  *	     %p[1-9]   push ith parm
81fdd4e1e0SJan Lentfer  *	     %P[a-z]   set dynamic variable [a-z] to pop()
82fdd4e1e0SJan Lentfer  *	     %g[a-z]   get dynamic variable [a-z] and push it
83fdd4e1e0SJan Lentfer  *	     %P[A-Z]   set static variable [A-Z] to pop()
84fdd4e1e0SJan Lentfer  *	     %g[A-Z]   get static variable [A-Z] and push it
85fdd4e1e0SJan Lentfer  *	     %l        push strlen(pop)
86fdd4e1e0SJan Lentfer  *	     %'c'      push char constant c
87fdd4e1e0SJan Lentfer  *	     %{nn}     push integer constant nn
88fdd4e1e0SJan Lentfer  *
89fdd4e1e0SJan Lentfer  *	     %+ %- %* %/ %m
90fdd4e1e0SJan Lentfer  *	               arithmetic (%m is mod): push(pop() op pop())
91fdd4e1e0SJan Lentfer  *	     %& %| %^  bit operations: push(pop() op pop())
92fdd4e1e0SJan Lentfer  *	     %= %> %<  logical operations: push(pop() op pop())
93fdd4e1e0SJan Lentfer  *	     %A %O     logical and & or operations for conditionals
94fdd4e1e0SJan Lentfer  *	     %! %~     unary operations push(op pop())
95fdd4e1e0SJan Lentfer  *	     %i        add 1 to first two parms (for ANSI terminals)
96fdd4e1e0SJan Lentfer  *
97fdd4e1e0SJan Lentfer  *	     %? expr %t thenpart %e elsepart %;
98fdd4e1e0SJan Lentfer  *	               if-then-else, %e elsepart is optional.
99fdd4e1e0SJan Lentfer  *	               else-if's are possible ala Algol 68:
100fdd4e1e0SJan Lentfer  *	               %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
101fdd4e1e0SJan Lentfer  *
102fdd4e1e0SJan Lentfer  *	For those of the above operators which are binary and not commutative,
103fdd4e1e0SJan Lentfer  *	the stack works in the usual way, with
104fdd4e1e0SJan Lentfer  *			%gx %gy %m
105fdd4e1e0SJan Lentfer  *	resulting in x mod y, not the reverse.
106fdd4e1e0SJan Lentfer  */
107fdd4e1e0SJan Lentfer 
108fdd4e1e0SJan Lentfer NCURSES_EXPORT_VAR(int) _nc_tparm_err = 0;
109fdd4e1e0SJan Lentfer 
1101d102085SJan Lentfer #define TPS(var) _nc_prescreen.tparm_state.var
1113468e90cSJohn Marino #define popcount _nc_popcount	/* workaround for NetBSD 6.0 defect */
112fdd4e1e0SJan Lentfer 
113fdd4e1e0SJan Lentfer #if NO_LEAKS
114fdd4e1e0SJan Lentfer NCURSES_EXPORT(void)
_nc_free_tparm(void)115fdd4e1e0SJan Lentfer _nc_free_tparm(void)
116fdd4e1e0SJan Lentfer {
1171d102085SJan Lentfer     if (TPS(out_buff) != 0) {
1181d102085SJan Lentfer 	FreeAndNull(TPS(out_buff));
1191d102085SJan Lentfer 	TPS(out_size) = 0;
1201d102085SJan Lentfer 	TPS(out_used) = 0;
1211d102085SJan Lentfer 	FreeAndNull(TPS(fmt_buff));
1221d102085SJan Lentfer 	TPS(fmt_size) = 0;
123fdd4e1e0SJan Lentfer     }
124fdd4e1e0SJan Lentfer }
125fdd4e1e0SJan Lentfer #endif
126fdd4e1e0SJan Lentfer 
1271d102085SJan Lentfer static NCURSES_INLINE void
get_space(size_t need)128fdd4e1e0SJan Lentfer get_space(size_t need)
129fdd4e1e0SJan Lentfer {
1301d102085SJan Lentfer     need += TPS(out_used);
1311d102085SJan Lentfer     if (need > TPS(out_size)) {
1321d102085SJan Lentfer 	TPS(out_size) = need * 2;
1333468e90cSJohn Marino 	TYPE_REALLOC(char, TPS(out_size), TPS(out_buff));
134fdd4e1e0SJan Lentfer     }
135fdd4e1e0SJan Lentfer }
136fdd4e1e0SJan Lentfer 
1371d102085SJan Lentfer static NCURSES_INLINE void
save_text(const char * fmt,const char * s,int len)138fdd4e1e0SJan Lentfer save_text(const char *fmt, const char *s, int len)
139fdd4e1e0SJan Lentfer {
140fdd4e1e0SJan Lentfer     size_t s_len = strlen(s);
141fdd4e1e0SJan Lentfer     if (len > (int) s_len)
14200d8f3c4SJohn Marino 	s_len = (size_t) len;
143fdd4e1e0SJan Lentfer 
144fdd4e1e0SJan Lentfer     get_space(s_len + 1);
145fdd4e1e0SJan Lentfer 
1463468e90cSJohn Marino     _nc_SPRINTF(TPS(out_buff) + TPS(out_used),
1473468e90cSJohn Marino 		_nc_SLIMIT(TPS(out_size) - TPS(out_used))
1483468e90cSJohn Marino 		fmt, s);
1491d102085SJan Lentfer     TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used));
150fdd4e1e0SJan Lentfer }
151fdd4e1e0SJan Lentfer 
1521d102085SJan Lentfer static NCURSES_INLINE void
save_number(const char * fmt,int number,int len)153fdd4e1e0SJan Lentfer save_number(const char *fmt, int number, int len)
154fdd4e1e0SJan Lentfer {
155fdd4e1e0SJan Lentfer     if (len < 30)
156fdd4e1e0SJan Lentfer 	len = 30;		/* actually log10(MAX_INT)+1 */
157fdd4e1e0SJan Lentfer 
1583468e90cSJohn Marino     get_space((size_t) len + 1);
159fdd4e1e0SJan Lentfer 
1603468e90cSJohn Marino     _nc_SPRINTF(TPS(out_buff) + TPS(out_used),
1613468e90cSJohn Marino 		_nc_SLIMIT(TPS(out_size) - TPS(out_used))
1623468e90cSJohn Marino 		fmt, number);
1631d102085SJan Lentfer     TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used));
164fdd4e1e0SJan Lentfer }
165fdd4e1e0SJan Lentfer 
1661d102085SJan Lentfer static NCURSES_INLINE void
save_char(int c)167fdd4e1e0SJan Lentfer save_char(int c)
168fdd4e1e0SJan Lentfer {
169fdd4e1e0SJan Lentfer     if (c == 0)
170fdd4e1e0SJan Lentfer 	c = 0200;
1713468e90cSJohn Marino     get_space((size_t) 1);
1721d102085SJan Lentfer     TPS(out_buff)[TPS(out_used)++] = (char) c;
173fdd4e1e0SJan Lentfer }
174fdd4e1e0SJan Lentfer 
1751d102085SJan Lentfer static NCURSES_INLINE void
npush(int x)176fdd4e1e0SJan Lentfer npush(int x)
177fdd4e1e0SJan Lentfer {
1781d102085SJan Lentfer     if (TPS(stack_ptr) < STACKSIZE) {
1791d102085SJan Lentfer 	TPS(stack)[TPS(stack_ptr)].num_type = TRUE;
1801d102085SJan Lentfer 	TPS(stack)[TPS(stack_ptr)].data.num = x;
1811d102085SJan Lentfer 	TPS(stack_ptr)++;
182fdd4e1e0SJan Lentfer     } else {
1831d102085SJan Lentfer 	DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(TPS(tparam_base))));
184fdd4e1e0SJan Lentfer 	_nc_tparm_err++;
185fdd4e1e0SJan Lentfer     }
186fdd4e1e0SJan Lentfer }
187fdd4e1e0SJan Lentfer 
1881d102085SJan Lentfer static NCURSES_INLINE int
npop(void)189fdd4e1e0SJan Lentfer npop(void)
190fdd4e1e0SJan Lentfer {
191fdd4e1e0SJan Lentfer     int result = 0;
1921d102085SJan Lentfer     if (TPS(stack_ptr) > 0) {
1931d102085SJan Lentfer 	TPS(stack_ptr)--;
1941d102085SJan Lentfer 	if (TPS(stack)[TPS(stack_ptr)].num_type)
1951d102085SJan Lentfer 	    result = TPS(stack)[TPS(stack_ptr)].data.num;
196fdd4e1e0SJan Lentfer     } else {
1971d102085SJan Lentfer 	DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(TPS(tparam_base))));
198fdd4e1e0SJan Lentfer 	_nc_tparm_err++;
199fdd4e1e0SJan Lentfer     }
200fdd4e1e0SJan Lentfer     return result;
201fdd4e1e0SJan Lentfer }
202fdd4e1e0SJan Lentfer 
2031d102085SJan Lentfer static NCURSES_INLINE void
spush(char * x)204fdd4e1e0SJan Lentfer spush(char *x)
205fdd4e1e0SJan Lentfer {
2061d102085SJan Lentfer     if (TPS(stack_ptr) < STACKSIZE) {
2071d102085SJan Lentfer 	TPS(stack)[TPS(stack_ptr)].num_type = FALSE;
2081d102085SJan Lentfer 	TPS(stack)[TPS(stack_ptr)].data.str = x;
2091d102085SJan Lentfer 	TPS(stack_ptr)++;
210fdd4e1e0SJan Lentfer     } else {
2111d102085SJan Lentfer 	DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(TPS(tparam_base))));
212fdd4e1e0SJan Lentfer 	_nc_tparm_err++;
213fdd4e1e0SJan Lentfer     }
214fdd4e1e0SJan Lentfer }
215fdd4e1e0SJan Lentfer 
2161d102085SJan Lentfer static NCURSES_INLINE char *
spop(void)217fdd4e1e0SJan Lentfer spop(void)
218fdd4e1e0SJan Lentfer {
219fdd4e1e0SJan Lentfer     static char dummy[] = "";	/* avoid const-cast */
220fdd4e1e0SJan Lentfer     char *result = dummy;
2211d102085SJan Lentfer     if (TPS(stack_ptr) > 0) {
2221d102085SJan Lentfer 	TPS(stack_ptr)--;
2231d102085SJan Lentfer 	if (!TPS(stack)[TPS(stack_ptr)].num_type
2241d102085SJan Lentfer 	    && TPS(stack)[TPS(stack_ptr)].data.str != 0)
2251d102085SJan Lentfer 	    result = TPS(stack)[TPS(stack_ptr)].data.str;
226fdd4e1e0SJan Lentfer     } else {
2271d102085SJan Lentfer 	DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(TPS(tparam_base))));
228fdd4e1e0SJan Lentfer 	_nc_tparm_err++;
229fdd4e1e0SJan Lentfer     }
230fdd4e1e0SJan Lentfer     return result;
231fdd4e1e0SJan Lentfer }
232fdd4e1e0SJan Lentfer 
2331d102085SJan Lentfer static NCURSES_INLINE const char *
parse_format(const char * s,char * format,int * len)234fdd4e1e0SJan Lentfer parse_format(const char *s, char *format, int *len)
235fdd4e1e0SJan Lentfer {
236fdd4e1e0SJan Lentfer     *len = 0;
237fdd4e1e0SJan Lentfer     if (format != 0) {
238fdd4e1e0SJan Lentfer 	bool done = FALSE;
239fdd4e1e0SJan Lentfer 	bool allowminus = FALSE;
240fdd4e1e0SJan Lentfer 	bool dot = FALSE;
241fdd4e1e0SJan Lentfer 	bool err = FALSE;
242fdd4e1e0SJan Lentfer 	char *fmt = format;
243fdd4e1e0SJan Lentfer 	int my_width = 0;
244fdd4e1e0SJan Lentfer 	int my_prec = 0;
245fdd4e1e0SJan Lentfer 	int value = 0;
246fdd4e1e0SJan Lentfer 
247fdd4e1e0SJan Lentfer 	*len = 0;
248fdd4e1e0SJan Lentfer 	*format++ = '%';
249fdd4e1e0SJan Lentfer 	while (*s != '\0' && !done) {
250fdd4e1e0SJan Lentfer 	    switch (*s) {
251fdd4e1e0SJan Lentfer 	    case 'c':		/* FALLTHRU */
252fdd4e1e0SJan Lentfer 	    case 'd':		/* FALLTHRU */
253fdd4e1e0SJan Lentfer 	    case 'o':		/* FALLTHRU */
254fdd4e1e0SJan Lentfer 	    case 'x':		/* FALLTHRU */
255fdd4e1e0SJan Lentfer 	    case 'X':		/* FALLTHRU */
256fdd4e1e0SJan Lentfer 	    case 's':
2573468e90cSJohn Marino #ifdef EXP_XTERM_1005
2583468e90cSJohn Marino 	    case 'u':
2593468e90cSJohn Marino #endif
260fdd4e1e0SJan Lentfer 		*format++ = *s;
261fdd4e1e0SJan Lentfer 		done = TRUE;
262fdd4e1e0SJan Lentfer 		break;
263fdd4e1e0SJan Lentfer 	    case '.':
264fdd4e1e0SJan Lentfer 		*format++ = *s++;
265fdd4e1e0SJan Lentfer 		if (dot) {
266fdd4e1e0SJan Lentfer 		    err = TRUE;
267fdd4e1e0SJan Lentfer 		} else {	/* value before '.' is the width */
268fdd4e1e0SJan Lentfer 		    dot = TRUE;
269fdd4e1e0SJan Lentfer 		    my_width = value;
270fdd4e1e0SJan Lentfer 		}
271fdd4e1e0SJan Lentfer 		value = 0;
272fdd4e1e0SJan Lentfer 		break;
273fdd4e1e0SJan Lentfer 	    case '#':
274fdd4e1e0SJan Lentfer 		*format++ = *s++;
275fdd4e1e0SJan Lentfer 		break;
276fdd4e1e0SJan Lentfer 	    case ' ':
277fdd4e1e0SJan Lentfer 		*format++ = *s++;
278fdd4e1e0SJan Lentfer 		break;
279fdd4e1e0SJan Lentfer 	    case ':':
280fdd4e1e0SJan Lentfer 		s++;
281fdd4e1e0SJan Lentfer 		allowminus = TRUE;
282fdd4e1e0SJan Lentfer 		break;
283fdd4e1e0SJan Lentfer 	    case '-':
284fdd4e1e0SJan Lentfer 		if (allowminus) {
285fdd4e1e0SJan Lentfer 		    *format++ = *s++;
286fdd4e1e0SJan Lentfer 		} else {
287fdd4e1e0SJan Lentfer 		    done = TRUE;
288fdd4e1e0SJan Lentfer 		}
289fdd4e1e0SJan Lentfer 		break;
290fdd4e1e0SJan Lentfer 	    default:
291fdd4e1e0SJan Lentfer 		if (isdigit(UChar(*s))) {
292fdd4e1e0SJan Lentfer 		    value = (value * 10) + (*s - '0');
293fdd4e1e0SJan Lentfer 		    if (value > 10000)
294fdd4e1e0SJan Lentfer 			err = TRUE;
295fdd4e1e0SJan Lentfer 		    *format++ = *s++;
296fdd4e1e0SJan Lentfer 		} else {
297fdd4e1e0SJan Lentfer 		    done = TRUE;
298fdd4e1e0SJan Lentfer 		}
299fdd4e1e0SJan Lentfer 	    }
300fdd4e1e0SJan Lentfer 	}
301fdd4e1e0SJan Lentfer 
302fdd4e1e0SJan Lentfer 	/*
303fdd4e1e0SJan Lentfer 	 * If we found an error, ignore (and remove) the flags.
304fdd4e1e0SJan Lentfer 	 */
305fdd4e1e0SJan Lentfer 	if (err) {
306fdd4e1e0SJan Lentfer 	    my_width = my_prec = value = 0;
307fdd4e1e0SJan Lentfer 	    format = fmt;
308fdd4e1e0SJan Lentfer 	    *format++ = '%';
309fdd4e1e0SJan Lentfer 	    *format++ = *s;
310fdd4e1e0SJan Lentfer 	}
311fdd4e1e0SJan Lentfer 
312fdd4e1e0SJan Lentfer 	/*
313fdd4e1e0SJan Lentfer 	 * Any value after '.' is the precision.  If we did not see '.', then
314fdd4e1e0SJan Lentfer 	 * the value is the width.
315fdd4e1e0SJan Lentfer 	 */
316fdd4e1e0SJan Lentfer 	if (dot)
317fdd4e1e0SJan Lentfer 	    my_prec = value;
318fdd4e1e0SJan Lentfer 	else
319fdd4e1e0SJan Lentfer 	    my_width = value;
320fdd4e1e0SJan Lentfer 
321fdd4e1e0SJan Lentfer 	*format = '\0';
322fdd4e1e0SJan Lentfer 	/* return maximum string length in print */
323fdd4e1e0SJan Lentfer 	*len = (my_width > my_prec) ? my_width : my_prec;
324fdd4e1e0SJan Lentfer     }
325fdd4e1e0SJan Lentfer     return s;
326fdd4e1e0SJan Lentfer }
327fdd4e1e0SJan Lentfer 
328fdd4e1e0SJan Lentfer #define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')
329fdd4e1e0SJan Lentfer #define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
330*32bb5217SDaniel Fojt #define tc_BUMP()  if (level < 0 && number < 2) number++
331fdd4e1e0SJan Lentfer 
332fdd4e1e0SJan Lentfer /*
333fdd4e1e0SJan Lentfer  * Analyze the string to see how many parameters we need from the varargs list,
334fdd4e1e0SJan Lentfer  * and what their types are.  We will only accept string parameters if they
335fdd4e1e0SJan Lentfer  * appear as a %l or %s format following an explicit parameter reference (e.g.,
336fdd4e1e0SJan Lentfer  * %p2%s).  All other parameters are numbers.
337fdd4e1e0SJan Lentfer  *
338fdd4e1e0SJan Lentfer  * 'number' counts coarsely the number of pop's we see in the string, and
339fdd4e1e0SJan Lentfer  * 'popcount' shows the highest parameter number in the string.  We would like
340fdd4e1e0SJan Lentfer  * to simply use the latter count, but if we are reading termcap strings, there
341fdd4e1e0SJan Lentfer  * may be cases that we cannot see the explicit parameter numbers.
342fdd4e1e0SJan Lentfer  */
343fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
_nc_tparm_analyze(const char * string,char * p_is_s[NUM_PARM],int * popcount)344fdd4e1e0SJan Lentfer _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
345fdd4e1e0SJan Lentfer {
346fdd4e1e0SJan Lentfer     size_t len2;
347fdd4e1e0SJan Lentfer     int i;
348fdd4e1e0SJan Lentfer     int lastpop = -1;
349fdd4e1e0SJan Lentfer     int len;
350fdd4e1e0SJan Lentfer     int number = 0;
351*32bb5217SDaniel Fojt     int level = -1;
352fdd4e1e0SJan Lentfer     const char *cp = string;
353fdd4e1e0SJan Lentfer     static char dummy[] = "";
354fdd4e1e0SJan Lentfer 
355fdd4e1e0SJan Lentfer     if (cp == 0)
356fdd4e1e0SJan Lentfer 	return 0;
357fdd4e1e0SJan Lentfer 
358*32bb5217SDaniel Fojt     if ((len2 = strlen(cp)) + 2 > TPS(fmt_size)) {
359*32bb5217SDaniel Fojt 	TPS(fmt_size) += len2 + 2;
3601d102085SJan Lentfer 	TPS(fmt_buff) = typeRealloc(char, TPS(fmt_size), TPS(fmt_buff));
3611d102085SJan Lentfer 	if (TPS(fmt_buff) == 0)
362fdd4e1e0SJan Lentfer 	    return 0;
363fdd4e1e0SJan Lentfer     }
364fdd4e1e0SJan Lentfer 
365fdd4e1e0SJan Lentfer     memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM);
366fdd4e1e0SJan Lentfer     *popcount = 0;
367fdd4e1e0SJan Lentfer 
368fdd4e1e0SJan Lentfer     while ((cp - string) < (int) len2) {
369fdd4e1e0SJan Lentfer 	if (*cp == '%') {
370fdd4e1e0SJan Lentfer 	    cp++;
3711d102085SJan Lentfer 	    cp = parse_format(cp, TPS(fmt_buff), &len);
372fdd4e1e0SJan Lentfer 	    switch (*cp) {
373fdd4e1e0SJan Lentfer 	    default:
374fdd4e1e0SJan Lentfer 		break;
375fdd4e1e0SJan Lentfer 
376fdd4e1e0SJan Lentfer 	    case 'd':		/* FALLTHRU */
377fdd4e1e0SJan Lentfer 	    case 'o':		/* FALLTHRU */
378fdd4e1e0SJan Lentfer 	    case 'x':		/* FALLTHRU */
379fdd4e1e0SJan Lentfer 	    case 'X':		/* FALLTHRU */
380fdd4e1e0SJan Lentfer 	    case 'c':		/* FALLTHRU */
3813468e90cSJohn Marino #ifdef EXP_XTERM_1005
3823468e90cSJohn Marino 	    case 'u':
3833468e90cSJohn Marino #endif
384*32bb5217SDaniel Fojt 		if (lastpop <= 0) {
385*32bb5217SDaniel Fojt 		    tc_BUMP();
386*32bb5217SDaniel Fojt 		}
387*32bb5217SDaniel Fojt 		level -= 1;
388fdd4e1e0SJan Lentfer 		lastpop = -1;
389fdd4e1e0SJan Lentfer 		break;
390fdd4e1e0SJan Lentfer 
391fdd4e1e0SJan Lentfer 	    case 'l':
392fdd4e1e0SJan Lentfer 	    case 's':
393*32bb5217SDaniel Fojt 		if (lastpop > 0) {
394*32bb5217SDaniel Fojt 		    level -= 1;
395fdd4e1e0SJan Lentfer 		    p_is_s[lastpop - 1] = dummy;
396*32bb5217SDaniel Fojt 		}
397*32bb5217SDaniel Fojt 		tc_BUMP();
398fdd4e1e0SJan Lentfer 		break;
399fdd4e1e0SJan Lentfer 
400fdd4e1e0SJan Lentfer 	    case 'p':
401fdd4e1e0SJan Lentfer 		cp++;
402fdd4e1e0SJan Lentfer 		i = (UChar(*cp) - '0');
403fdd4e1e0SJan Lentfer 		if (i >= 0 && i <= NUM_PARM) {
404*32bb5217SDaniel Fojt 		    ++level;
405fdd4e1e0SJan Lentfer 		    lastpop = i;
406fdd4e1e0SJan Lentfer 		    if (lastpop > *popcount)
407fdd4e1e0SJan Lentfer 			*popcount = lastpop;
408fdd4e1e0SJan Lentfer 		}
409fdd4e1e0SJan Lentfer 		break;
410fdd4e1e0SJan Lentfer 
411fdd4e1e0SJan Lentfer 	    case 'P':
412fdd4e1e0SJan Lentfer 		++cp;
413fdd4e1e0SJan Lentfer 		break;
414fdd4e1e0SJan Lentfer 
415fdd4e1e0SJan Lentfer 	    case 'g':
416*32bb5217SDaniel Fojt 		++level;
417fdd4e1e0SJan Lentfer 		cp++;
418fdd4e1e0SJan Lentfer 		break;
419fdd4e1e0SJan Lentfer 
420fdd4e1e0SJan Lentfer 	    case S_QUOTE:
421*32bb5217SDaniel Fojt 		++level;
422fdd4e1e0SJan Lentfer 		cp += 2;
423fdd4e1e0SJan Lentfer 		lastpop = -1;
424fdd4e1e0SJan Lentfer 		break;
425fdd4e1e0SJan Lentfer 
426fdd4e1e0SJan Lentfer 	    case L_BRACE:
427*32bb5217SDaniel Fojt 		++level;
428fdd4e1e0SJan Lentfer 		cp++;
429fdd4e1e0SJan Lentfer 		while (isdigit(UChar(*cp))) {
430fdd4e1e0SJan Lentfer 		    cp++;
431fdd4e1e0SJan Lentfer 		}
432fdd4e1e0SJan Lentfer 		break;
433fdd4e1e0SJan Lentfer 
434fdd4e1e0SJan Lentfer 	    case '+':
435fdd4e1e0SJan Lentfer 	    case '-':
436fdd4e1e0SJan Lentfer 	    case '*':
437fdd4e1e0SJan Lentfer 	    case '/':
438fdd4e1e0SJan Lentfer 	    case 'm':
439fdd4e1e0SJan Lentfer 	    case 'A':
440fdd4e1e0SJan Lentfer 	    case 'O':
441fdd4e1e0SJan Lentfer 	    case '&':
442fdd4e1e0SJan Lentfer 	    case '|':
443fdd4e1e0SJan Lentfer 	    case '^':
444fdd4e1e0SJan Lentfer 	    case '=':
445fdd4e1e0SJan Lentfer 	    case '<':
446fdd4e1e0SJan Lentfer 	    case '>':
447*32bb5217SDaniel Fojt 		tc_BUMP();
448*32bb5217SDaniel Fojt 		level -= 1;	/* pop 2, operate, push 1 */
449fdd4e1e0SJan Lentfer 		lastpop = -1;
450fdd4e1e0SJan Lentfer 		break;
451fdd4e1e0SJan Lentfer 
452fdd4e1e0SJan Lentfer 	    case '!':
453fdd4e1e0SJan Lentfer 	    case '~':
454*32bb5217SDaniel Fojt 		tc_BUMP();
455fdd4e1e0SJan Lentfer 		lastpop = -1;
456fdd4e1e0SJan Lentfer 		break;
457fdd4e1e0SJan Lentfer 
458fdd4e1e0SJan Lentfer 	    case 'i':
459fdd4e1e0SJan Lentfer 		/* will add 1 to first (usually two) parameters */
460fdd4e1e0SJan Lentfer 		break;
461fdd4e1e0SJan Lentfer 	    }
462fdd4e1e0SJan Lentfer 	}
463fdd4e1e0SJan Lentfer 	if (*cp != '\0')
464fdd4e1e0SJan Lentfer 	    cp++;
465fdd4e1e0SJan Lentfer     }
466fdd4e1e0SJan Lentfer 
467fdd4e1e0SJan Lentfer     if (number > NUM_PARM)
468fdd4e1e0SJan Lentfer 	number = NUM_PARM;
469fdd4e1e0SJan Lentfer     return number;
470fdd4e1e0SJan Lentfer }
471fdd4e1e0SJan Lentfer 
4721d102085SJan Lentfer static NCURSES_INLINE char *
tparam_internal(int use_TPARM_ARG,const char * string,va_list ap)4733468e90cSJohn Marino tparam_internal(int use_TPARM_ARG, const char *string, va_list ap)
474fdd4e1e0SJan Lentfer {
475fdd4e1e0SJan Lentfer     char *p_is_s[NUM_PARM];
4761d102085SJan Lentfer     TPARM_ARG param[NUM_PARM];
47700d8f3c4SJohn Marino     int popcount = 0;
478fdd4e1e0SJan Lentfer     int number;
47900d8f3c4SJohn Marino     int num_args;
480fdd4e1e0SJan Lentfer     int len;
481fdd4e1e0SJan Lentfer     int level;
482fdd4e1e0SJan Lentfer     int x, y;
483fdd4e1e0SJan Lentfer     int i;
484fdd4e1e0SJan Lentfer     const char *cp = string;
485fdd4e1e0SJan Lentfer     size_t len2;
4863468e90cSJohn Marino     bool termcap_hack;
4873468e90cSJohn Marino     bool incremented_two;
488fdd4e1e0SJan Lentfer 
489*32bb5217SDaniel Fojt     if (cp == NULL) {
490*32bb5217SDaniel Fojt 	TR(TRACE_CALLS, ("%s: format is null", TPS(tname)));
491fdd4e1e0SJan Lentfer 	return NULL;
492*32bb5217SDaniel Fojt     }
493fdd4e1e0SJan Lentfer 
4941d102085SJan Lentfer     TPS(out_used) = 0;
495fdd4e1e0SJan Lentfer     len2 = strlen(cp);
496fdd4e1e0SJan Lentfer 
497fdd4e1e0SJan Lentfer     /*
498fdd4e1e0SJan Lentfer      * Find the highest parameter-number referred to in the format string.
499fdd4e1e0SJan Lentfer      * Use this value to limit the number of arguments copied from the
500fdd4e1e0SJan Lentfer      * variable-length argument list.
501fdd4e1e0SJan Lentfer      */
502fdd4e1e0SJan Lentfer     number = _nc_tparm_analyze(cp, p_is_s, &popcount);
503*32bb5217SDaniel Fojt     if (TPS(fmt_buff) == 0) {
504*32bb5217SDaniel Fojt 	TR(TRACE_CALLS, ("%s: error in analysis", TPS(tname)));
505fdd4e1e0SJan Lentfer 	return NULL;
506*32bb5217SDaniel Fojt     }
507fdd4e1e0SJan Lentfer 
5083468e90cSJohn Marino     incremented_two = FALSE;
5093468e90cSJohn Marino 
51000d8f3c4SJohn Marino     if (number > NUM_PARM)
51100d8f3c4SJohn Marino 	number = NUM_PARM;
51200d8f3c4SJohn Marino     if (popcount > NUM_PARM)
51300d8f3c4SJohn Marino 	popcount = NUM_PARM;
51400d8f3c4SJohn Marino     num_args = max(popcount, number);
51500d8f3c4SJohn Marino 
51600d8f3c4SJohn Marino     for (i = 0; i < num_args; i++) {
517fdd4e1e0SJan Lentfer 	/*
518fdd4e1e0SJan Lentfer 	 * A few caps (such as plab_norm) have string-valued parms.
519fdd4e1e0SJan Lentfer 	 * We'll have to assume that the caller knows the difference, since
520fdd4e1e0SJan Lentfer 	 * a char* and an int may not be the same size on the stack.  The
521fdd4e1e0SJan Lentfer 	 * normal prototype for this uses 9 long's, which is consistent with
522fdd4e1e0SJan Lentfer 	 * our va_arg() usage.
523fdd4e1e0SJan Lentfer 	 */
524fdd4e1e0SJan Lentfer 	if (p_is_s[i] != 0) {
525fdd4e1e0SJan Lentfer 	    p_is_s[i] = va_arg(ap, char *);
52600d8f3c4SJohn Marino 	    param[i] = 0;
52700d8f3c4SJohn Marino 	} else if (use_TPARM_ARG) {
5281d102085SJan Lentfer 	    param[i] = va_arg(ap, TPARM_ARG);
52900d8f3c4SJohn Marino 	} else {
53000d8f3c4SJohn Marino 	    param[i] = (TPARM_ARG) va_arg(ap, int);
531fdd4e1e0SJan Lentfer 	}
532fdd4e1e0SJan Lentfer     }
533fdd4e1e0SJan Lentfer 
534fdd4e1e0SJan Lentfer     /*
535fdd4e1e0SJan Lentfer      * This is a termcap compatibility hack.  If there are no explicit pop
536fdd4e1e0SJan Lentfer      * operations in the string, load the stack in such a way that
537fdd4e1e0SJan Lentfer      * successive pops will grab successive parameters.  That will make
538fdd4e1e0SJan Lentfer      * the expansion of (for example) \E[%d;%dH work correctly in termcap
539fdd4e1e0SJan Lentfer      * style, which means tparam() will expand termcap strings OK.
540fdd4e1e0SJan Lentfer      */
5411d102085SJan Lentfer     TPS(stack_ptr) = 0;
5423468e90cSJohn Marino     termcap_hack = FALSE;
543fdd4e1e0SJan Lentfer     if (popcount == 0) {
5443468e90cSJohn Marino 	termcap_hack = TRUE;
5451d102085SJan Lentfer 	for (i = number - 1; i >= 0; i--) {
5461d102085SJan Lentfer 	    if (p_is_s[i])
5471d102085SJan Lentfer 		spush(p_is_s[i]);
5481d102085SJan Lentfer 	    else
54900d8f3c4SJohn Marino 		npush((int) param[i]);
550fdd4e1e0SJan Lentfer 	}
5511d102085SJan Lentfer     }
552fdd4e1e0SJan Lentfer #ifdef TRACE
5531d102085SJan Lentfer     if (USE_TRACEF(TRACE_CALLS)) {
5543468e90cSJohn Marino 	for (i = 0; i < num_args; i++) {
555*32bb5217SDaniel Fojt 	    if (p_is_s[i] != 0) {
556fdd4e1e0SJan Lentfer 		save_text(", %s", _nc_visbuf(p_is_s[i]), 0);
557*32bb5217SDaniel Fojt 	    } else if ((long) param[i] > MAX_OF_TYPE(NCURSES_INT2) ||
558*32bb5217SDaniel Fojt 		       (long) param[i] < 0) {
559*32bb5217SDaniel Fojt 		_tracef("BUG: problem with tparm parameter #%d of %d",
560*32bb5217SDaniel Fojt 			i + 1, num_args);
561*32bb5217SDaniel Fojt 		break;
562*32bb5217SDaniel Fojt 	    } else {
56300d8f3c4SJohn Marino 		save_number(", %d", (int) param[i], 0);
564fdd4e1e0SJan Lentfer 	    }
565*32bb5217SDaniel Fojt 	}
5661d102085SJan Lentfer 	_tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(cp), TPS(out_buff));
5671d102085SJan Lentfer 	TPS(out_used) = 0;
5681d102085SJan Lentfer 	_nc_unlock_global(tracef);
569fdd4e1e0SJan Lentfer     }
570fdd4e1e0SJan Lentfer #endif /* TRACE */
571fdd4e1e0SJan Lentfer 
572fdd4e1e0SJan Lentfer     while ((cp - string) < (int) len2) {
573fdd4e1e0SJan Lentfer 	if (*cp != '%') {
574fdd4e1e0SJan Lentfer 	    save_char(UChar(*cp));
575fdd4e1e0SJan Lentfer 	} else {
5761d102085SJan Lentfer 	    TPS(tparam_base) = cp++;
5771d102085SJan Lentfer 	    cp = parse_format(cp, TPS(fmt_buff), &len);
578fdd4e1e0SJan Lentfer 	    switch (*cp) {
579fdd4e1e0SJan Lentfer 	    default:
580fdd4e1e0SJan Lentfer 		break;
581fdd4e1e0SJan Lentfer 	    case '%':
582fdd4e1e0SJan Lentfer 		save_char('%');
583fdd4e1e0SJan Lentfer 		break;
584fdd4e1e0SJan Lentfer 
585fdd4e1e0SJan Lentfer 	    case 'd':		/* FALLTHRU */
586fdd4e1e0SJan Lentfer 	    case 'o':		/* FALLTHRU */
587fdd4e1e0SJan Lentfer 	    case 'x':		/* FALLTHRU */
588fdd4e1e0SJan Lentfer 	    case 'X':		/* FALLTHRU */
5891d102085SJan Lentfer 		save_number(TPS(fmt_buff), npop(), len);
590fdd4e1e0SJan Lentfer 		break;
591fdd4e1e0SJan Lentfer 
592fdd4e1e0SJan Lentfer 	    case 'c':		/* FALLTHRU */
593fdd4e1e0SJan Lentfer 		save_char(npop());
594fdd4e1e0SJan Lentfer 		break;
595fdd4e1e0SJan Lentfer 
5963468e90cSJohn Marino #ifdef EXP_XTERM_1005
5973468e90cSJohn Marino 	    case 'u':
5983468e90cSJohn Marino 		{
5993468e90cSJohn Marino 		    unsigned char target[10];
6003468e90cSJohn Marino 		    unsigned source = (unsigned) npop();
6013468e90cSJohn Marino 		    int rc = _nc_conv_to_utf8(target, source, (unsigned)
6023468e90cSJohn Marino 					      sizeof(target));
6033468e90cSJohn Marino 		    int n;
6043468e90cSJohn Marino 		    for (n = 0; n < rc; ++n) {
6053468e90cSJohn Marino 			save_char(target[n]);
6063468e90cSJohn Marino 		    }
6073468e90cSJohn Marino 		}
6083468e90cSJohn Marino 		break;
6093468e90cSJohn Marino #endif
610fdd4e1e0SJan Lentfer 	    case 'l':
6113468e90cSJohn Marino 		npush((int) strlen(spop()));
612fdd4e1e0SJan Lentfer 		break;
613fdd4e1e0SJan Lentfer 
614fdd4e1e0SJan Lentfer 	    case 's':
6151d102085SJan Lentfer 		save_text(TPS(fmt_buff), spop(), len);
616fdd4e1e0SJan Lentfer 		break;
617fdd4e1e0SJan Lentfer 
618fdd4e1e0SJan Lentfer 	    case 'p':
619fdd4e1e0SJan Lentfer 		cp++;
620fdd4e1e0SJan Lentfer 		i = (UChar(*cp) - '1');
621fdd4e1e0SJan Lentfer 		if (i >= 0 && i < NUM_PARM) {
6223468e90cSJohn Marino 		    if (p_is_s[i]) {
623fdd4e1e0SJan Lentfer 			spush(p_is_s[i]);
6243468e90cSJohn Marino 		    } else {
62500d8f3c4SJohn Marino 			npush((int) param[i]);
626fdd4e1e0SJan Lentfer 		    }
6273468e90cSJohn Marino 		}
628fdd4e1e0SJan Lentfer 		break;
629fdd4e1e0SJan Lentfer 
630fdd4e1e0SJan Lentfer 	    case 'P':
631fdd4e1e0SJan Lentfer 		cp++;
632fdd4e1e0SJan Lentfer 		if (isUPPER(*cp)) {
633fdd4e1e0SJan Lentfer 		    i = (UChar(*cp) - 'A');
6341d102085SJan Lentfer 		    TPS(static_vars)[i] = npop();
635fdd4e1e0SJan Lentfer 		} else if (isLOWER(*cp)) {
636fdd4e1e0SJan Lentfer 		    i = (UChar(*cp) - 'a');
6371d102085SJan Lentfer 		    TPS(dynamic_var)[i] = npop();
638fdd4e1e0SJan Lentfer 		}
639fdd4e1e0SJan Lentfer 		break;
640fdd4e1e0SJan Lentfer 
641fdd4e1e0SJan Lentfer 	    case 'g':
642fdd4e1e0SJan Lentfer 		cp++;
643fdd4e1e0SJan Lentfer 		if (isUPPER(*cp)) {
644fdd4e1e0SJan Lentfer 		    i = (UChar(*cp) - 'A');
6451d102085SJan Lentfer 		    npush(TPS(static_vars)[i]);
646fdd4e1e0SJan Lentfer 		} else if (isLOWER(*cp)) {
647fdd4e1e0SJan Lentfer 		    i = (UChar(*cp) - 'a');
6481d102085SJan Lentfer 		    npush(TPS(dynamic_var)[i]);
649fdd4e1e0SJan Lentfer 		}
650fdd4e1e0SJan Lentfer 		break;
651fdd4e1e0SJan Lentfer 
652fdd4e1e0SJan Lentfer 	    case S_QUOTE:
653fdd4e1e0SJan Lentfer 		cp++;
654fdd4e1e0SJan Lentfer 		npush(UChar(*cp));
655fdd4e1e0SJan Lentfer 		cp++;
656fdd4e1e0SJan Lentfer 		break;
657fdd4e1e0SJan Lentfer 
658fdd4e1e0SJan Lentfer 	    case L_BRACE:
659fdd4e1e0SJan Lentfer 		number = 0;
660fdd4e1e0SJan Lentfer 		cp++;
661fdd4e1e0SJan Lentfer 		while (isdigit(UChar(*cp))) {
662fdd4e1e0SJan Lentfer 		    number = (number * 10) + (UChar(*cp) - '0');
663fdd4e1e0SJan Lentfer 		    cp++;
664fdd4e1e0SJan Lentfer 		}
665fdd4e1e0SJan Lentfer 		npush(number);
666fdd4e1e0SJan Lentfer 		break;
667fdd4e1e0SJan Lentfer 
668fdd4e1e0SJan Lentfer 	    case '+':
669fdd4e1e0SJan Lentfer 		npush(npop() + npop());
670fdd4e1e0SJan Lentfer 		break;
671fdd4e1e0SJan Lentfer 
672fdd4e1e0SJan Lentfer 	    case '-':
673fdd4e1e0SJan Lentfer 		y = npop();
674fdd4e1e0SJan Lentfer 		x = npop();
675fdd4e1e0SJan Lentfer 		npush(x - y);
676fdd4e1e0SJan Lentfer 		break;
677fdd4e1e0SJan Lentfer 
678fdd4e1e0SJan Lentfer 	    case '*':
679fdd4e1e0SJan Lentfer 		npush(npop() * npop());
680fdd4e1e0SJan Lentfer 		break;
681fdd4e1e0SJan Lentfer 
682fdd4e1e0SJan Lentfer 	    case '/':
683fdd4e1e0SJan Lentfer 		y = npop();
684fdd4e1e0SJan Lentfer 		x = npop();
685fdd4e1e0SJan Lentfer 		npush(y ? (x / y) : 0);
686fdd4e1e0SJan Lentfer 		break;
687fdd4e1e0SJan Lentfer 
688fdd4e1e0SJan Lentfer 	    case 'm':
689fdd4e1e0SJan Lentfer 		y = npop();
690fdd4e1e0SJan Lentfer 		x = npop();
691fdd4e1e0SJan Lentfer 		npush(y ? (x % y) : 0);
692fdd4e1e0SJan Lentfer 		break;
693fdd4e1e0SJan Lentfer 
694fdd4e1e0SJan Lentfer 	    case 'A':
6953468e90cSJohn Marino 		y = npop();
6963468e90cSJohn Marino 		x = npop();
6973468e90cSJohn Marino 		npush(y && x);
698fdd4e1e0SJan Lentfer 		break;
699fdd4e1e0SJan Lentfer 
700fdd4e1e0SJan Lentfer 	    case 'O':
7013468e90cSJohn Marino 		y = npop();
7023468e90cSJohn Marino 		x = npop();
7033468e90cSJohn Marino 		npush(y || x);
704fdd4e1e0SJan Lentfer 		break;
705fdd4e1e0SJan Lentfer 
706fdd4e1e0SJan Lentfer 	    case '&':
707fdd4e1e0SJan Lentfer 		npush(npop() & npop());
708fdd4e1e0SJan Lentfer 		break;
709fdd4e1e0SJan Lentfer 
710fdd4e1e0SJan Lentfer 	    case '|':
711fdd4e1e0SJan Lentfer 		npush(npop() | npop());
712fdd4e1e0SJan Lentfer 		break;
713fdd4e1e0SJan Lentfer 
714fdd4e1e0SJan Lentfer 	    case '^':
715fdd4e1e0SJan Lentfer 		npush(npop() ^ npop());
716fdd4e1e0SJan Lentfer 		break;
717fdd4e1e0SJan Lentfer 
718fdd4e1e0SJan Lentfer 	    case '=':
719fdd4e1e0SJan Lentfer 		y = npop();
720fdd4e1e0SJan Lentfer 		x = npop();
721fdd4e1e0SJan Lentfer 		npush(x == y);
722fdd4e1e0SJan Lentfer 		break;
723fdd4e1e0SJan Lentfer 
724fdd4e1e0SJan Lentfer 	    case '<':
725fdd4e1e0SJan Lentfer 		y = npop();
726fdd4e1e0SJan Lentfer 		x = npop();
727fdd4e1e0SJan Lentfer 		npush(x < y);
728fdd4e1e0SJan Lentfer 		break;
729fdd4e1e0SJan Lentfer 
730fdd4e1e0SJan Lentfer 	    case '>':
731fdd4e1e0SJan Lentfer 		y = npop();
732fdd4e1e0SJan Lentfer 		x = npop();
733fdd4e1e0SJan Lentfer 		npush(x > y);
734fdd4e1e0SJan Lentfer 		break;
735fdd4e1e0SJan Lentfer 
736fdd4e1e0SJan Lentfer 	    case '!':
737fdd4e1e0SJan Lentfer 		npush(!npop());
738fdd4e1e0SJan Lentfer 		break;
739fdd4e1e0SJan Lentfer 
740fdd4e1e0SJan Lentfer 	    case '~':
741fdd4e1e0SJan Lentfer 		npush(~npop());
742fdd4e1e0SJan Lentfer 		break;
743fdd4e1e0SJan Lentfer 
744fdd4e1e0SJan Lentfer 	    case 'i':
7453468e90cSJohn Marino 		/*
7463468e90cSJohn Marino 		 * Increment the first two parameters -- if they are numbers
7473468e90cSJohn Marino 		 * rather than strings.  As a side effect, assign into the
7483468e90cSJohn Marino 		 * stack; if this is termcap, then the stack was populated
7493468e90cSJohn Marino 		 * using the termcap hack above rather than via the terminfo
7503468e90cSJohn Marino 		 * 'p' case.
7513468e90cSJohn Marino 		 */
7523468e90cSJohn Marino 		if (!incremented_two) {
7533468e90cSJohn Marino 		    incremented_two = TRUE;
7543468e90cSJohn Marino 		    if (p_is_s[0] == 0) {
755fdd4e1e0SJan Lentfer 			param[0]++;
7563468e90cSJohn Marino 			if (termcap_hack)
7573468e90cSJohn Marino 			    TPS(stack)[0].data.num = (int) param[0];
7583468e90cSJohn Marino 		    }
7593468e90cSJohn Marino 		    if (p_is_s[1] == 0) {
760fdd4e1e0SJan Lentfer 			param[1]++;
7613468e90cSJohn Marino 			if (termcap_hack)
7623468e90cSJohn Marino 			    TPS(stack)[1].data.num = (int) param[1];
7633468e90cSJohn Marino 		    }
7643468e90cSJohn Marino 		}
765fdd4e1e0SJan Lentfer 		break;
766fdd4e1e0SJan Lentfer 
767fdd4e1e0SJan Lentfer 	    case '?':
768fdd4e1e0SJan Lentfer 		break;
769fdd4e1e0SJan Lentfer 
770fdd4e1e0SJan Lentfer 	    case 't':
771fdd4e1e0SJan Lentfer 		x = npop();
772fdd4e1e0SJan Lentfer 		if (!x) {
773fdd4e1e0SJan Lentfer 		    /* scan forward for %e or %; at level zero */
774fdd4e1e0SJan Lentfer 		    cp++;
775fdd4e1e0SJan Lentfer 		    level = 0;
776fdd4e1e0SJan Lentfer 		    while (*cp) {
777fdd4e1e0SJan Lentfer 			if (*cp == '%') {
778fdd4e1e0SJan Lentfer 			    cp++;
779fdd4e1e0SJan Lentfer 			    if (*cp == '?')
780fdd4e1e0SJan Lentfer 				level++;
781fdd4e1e0SJan Lentfer 			    else if (*cp == ';') {
782fdd4e1e0SJan Lentfer 				if (level > 0)
783fdd4e1e0SJan Lentfer 				    level--;
784fdd4e1e0SJan Lentfer 				else
785fdd4e1e0SJan Lentfer 				    break;
786fdd4e1e0SJan Lentfer 			    } else if (*cp == 'e' && level == 0)
787fdd4e1e0SJan Lentfer 				break;
788fdd4e1e0SJan Lentfer 			}
789fdd4e1e0SJan Lentfer 
790fdd4e1e0SJan Lentfer 			if (*cp)
791fdd4e1e0SJan Lentfer 			    cp++;
792fdd4e1e0SJan Lentfer 		    }
793fdd4e1e0SJan Lentfer 		}
794fdd4e1e0SJan Lentfer 		break;
795fdd4e1e0SJan Lentfer 
796fdd4e1e0SJan Lentfer 	    case 'e':
797fdd4e1e0SJan Lentfer 		/* scan forward for a %; at level zero */
798fdd4e1e0SJan Lentfer 		cp++;
799fdd4e1e0SJan Lentfer 		level = 0;
800fdd4e1e0SJan Lentfer 		while (*cp) {
801fdd4e1e0SJan Lentfer 		    if (*cp == '%') {
802fdd4e1e0SJan Lentfer 			cp++;
803fdd4e1e0SJan Lentfer 			if (*cp == '?')
804fdd4e1e0SJan Lentfer 			    level++;
805fdd4e1e0SJan Lentfer 			else if (*cp == ';') {
806fdd4e1e0SJan Lentfer 			    if (level > 0)
807fdd4e1e0SJan Lentfer 				level--;
808fdd4e1e0SJan Lentfer 			    else
809fdd4e1e0SJan Lentfer 				break;
810fdd4e1e0SJan Lentfer 			}
811fdd4e1e0SJan Lentfer 		    }
812fdd4e1e0SJan Lentfer 
813fdd4e1e0SJan Lentfer 		    if (*cp)
814fdd4e1e0SJan Lentfer 			cp++;
815fdd4e1e0SJan Lentfer 		}
816fdd4e1e0SJan Lentfer 		break;
817fdd4e1e0SJan Lentfer 
818fdd4e1e0SJan Lentfer 	    case ';':
819fdd4e1e0SJan Lentfer 		break;
820fdd4e1e0SJan Lentfer 
821fdd4e1e0SJan Lentfer 	    }			/* endswitch (*cp) */
822fdd4e1e0SJan Lentfer 	}			/* endelse (*cp == '%') */
823fdd4e1e0SJan Lentfer 
824fdd4e1e0SJan Lentfer 	if (*cp == '\0')
825fdd4e1e0SJan Lentfer 	    break;
826fdd4e1e0SJan Lentfer 
827fdd4e1e0SJan Lentfer 	cp++;
828fdd4e1e0SJan Lentfer     }				/* endwhile (*cp) */
829fdd4e1e0SJan Lentfer 
8303468e90cSJohn Marino     get_space((size_t) 1);
8311d102085SJan Lentfer     TPS(out_buff)[TPS(out_used)] = '\0';
832fdd4e1e0SJan Lentfer 
8331d102085SJan Lentfer     T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff))));
8341d102085SJan Lentfer     return (TPS(out_buff));
835fdd4e1e0SJan Lentfer }
836fdd4e1e0SJan Lentfer 
8371d102085SJan Lentfer #if NCURSES_TPARM_VARARGS
8381d102085SJan Lentfer #define tparm_varargs tparm
8391d102085SJan Lentfer #else
8401d102085SJan Lentfer #define tparm_proto tparm
8411d102085SJan Lentfer #endif
8421d102085SJan Lentfer 
843fdd4e1e0SJan Lentfer NCURSES_EXPORT(char *)
tparm_varargs(const char * string,...)844*32bb5217SDaniel Fojt tparm_varargs(const char *string, ...)
845fdd4e1e0SJan Lentfer {
846fdd4e1e0SJan Lentfer     va_list ap;
847fdd4e1e0SJan Lentfer     char *result;
848fdd4e1e0SJan Lentfer 
849fdd4e1e0SJan Lentfer     _nc_tparm_err = 0;
850fdd4e1e0SJan Lentfer     va_start(ap, string);
851fdd4e1e0SJan Lentfer #ifdef TRACE
8521d102085SJan Lentfer     TPS(tname) = "tparm";
853fdd4e1e0SJan Lentfer #endif /* TRACE */
85400d8f3c4SJohn Marino     result = tparam_internal(TRUE, string, ap);
855fdd4e1e0SJan Lentfer     va_end(ap);
856fdd4e1e0SJan Lentfer     return result;
857fdd4e1e0SJan Lentfer }
8581d102085SJan Lentfer 
8591d102085SJan Lentfer #if !NCURSES_TPARM_VARARGS
8601d102085SJan Lentfer NCURSES_EXPORT(char *)
tparm_proto(const char * string,TPARM_ARG a1,TPARM_ARG a2,TPARM_ARG a3,TPARM_ARG a4,TPARM_ARG a5,TPARM_ARG a6,TPARM_ARG a7,TPARM_ARG a8,TPARM_ARG a9)861*32bb5217SDaniel Fojt tparm_proto(const char *string,
8621d102085SJan Lentfer 	    TPARM_ARG a1,
8631d102085SJan Lentfer 	    TPARM_ARG a2,
8641d102085SJan Lentfer 	    TPARM_ARG a3,
8651d102085SJan Lentfer 	    TPARM_ARG a4,
8661d102085SJan Lentfer 	    TPARM_ARG a5,
8671d102085SJan Lentfer 	    TPARM_ARG a6,
8681d102085SJan Lentfer 	    TPARM_ARG a7,
8691d102085SJan Lentfer 	    TPARM_ARG a8,
8701d102085SJan Lentfer 	    TPARM_ARG a9)
8711d102085SJan Lentfer {
8721d102085SJan Lentfer     return tparm_varargs(string, a1, a2, a3, a4, a5, a6, a7, a8, a9);
8731d102085SJan Lentfer }
8741d102085SJan Lentfer #endif /* NCURSES_TPARM_VARARGS */
87500d8f3c4SJohn Marino 
87600d8f3c4SJohn Marino NCURSES_EXPORT(char *)
tiparm(const char * string,...)87700d8f3c4SJohn Marino tiparm(const char *string, ...)
87800d8f3c4SJohn Marino {
87900d8f3c4SJohn Marino     va_list ap;
88000d8f3c4SJohn Marino     char *result;
88100d8f3c4SJohn Marino 
88200d8f3c4SJohn Marino     _nc_tparm_err = 0;
88300d8f3c4SJohn Marino     va_start(ap, string);
88400d8f3c4SJohn Marino #ifdef TRACE
88500d8f3c4SJohn Marino     TPS(tname) = "tiparm";
88600d8f3c4SJohn Marino #endif /* TRACE */
88700d8f3c4SJohn Marino     result = tparam_internal(FALSE, string, ap);
88800d8f3c4SJohn Marino     va_end(ap);
88900d8f3c4SJohn Marino     return result;
89000d8f3c4SJohn Marino }
891