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