Bug Summary

File:src/lib/libcurses/tinfo/lib_tparm.c
Warning:line 513, column 3
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name lib_tparm.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libcurses/obj -resource-dir /usr/local/lib/clang/13.0.0 -I . -I /usr/src/lib/libcurses -D PIC -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcurses/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libcurses/tinfo/lib_tparm.c
1/* $OpenBSD: lib_tparm.c,v 1.9 2010/01/12 23:22:06 nicm Exp $ */
2
3/****************************************************************************
4 * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. *
5 * *
6 * Permission is hereby granted, free of charge, to any person obtaining a *
7 * copy of this software and associated documentation files (the *
8 * "Software"), to deal in the Software without restriction, including *
9 * without limitation the rights to use, copy, modify, merge, publish, *
10 * distribute, distribute with modifications, sublicense, and/or sell *
11 * copies of the Software, and to permit persons to whom the Software is *
12 * furnished to do so, subject to the following conditions: *
13 * *
14 * The above copyright notice and this permission notice shall be included *
15 * in all copies or substantial portions of the Software. *
16 * *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
20 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
23 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
24 * *
25 * Except as contained in this notice, the name(s) of the above copyright *
26 * holders shall not be used in advertising or otherwise to promote the *
27 * sale, use or other dealings in this Software without prior written *
28 * authorization. *
29 ****************************************************************************/
30
31/****************************************************************************
32 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
33 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
34 * and: Thomas E. Dickey, 1996 on *
35 ****************************************************************************/
36
37/*
38 * tparm.c
39 *
40 */
41
42#include <curses.priv.h>
43
44#include <ctype.h>
45#include <term.h>
46#include <tic.h>
47
48MODULE_ID("$Id: lib_tparm.c,v 1.9 2010/01/12 23:22:06 nicm Exp $")
49
50/*
51 * char *
52 * tparm(string, ...)
53 *
54 * Substitute the given parameters into the given string by the following
55 * rules (taken from terminfo(5)):
56 *
57 * Cursor addressing and other strings requiring parame-
58 * ters in the terminal are described by a parameterized string
59 * capability, with like escapes %x in it. For example, to
60 * address the cursor, the cup capability is given, using two
61 * parameters: the row and column to address to. (Rows and
62 * columns are numbered from zero and refer to the physical
63 * screen visible to the user, not to any unseen memory.) If
64 * the terminal has memory relative cursor addressing, that can
65 * be indicated by
66 *
67 * The parameter mechanism uses a stack and special %
68 * codes to manipulate it. Typically a sequence will push one
69 * of the parameters onto the stack and then print it in some
70 * format. Often more complex operations are necessary.
71 *
72 * The % encodings have the following meanings:
73 *
74 * %% outputs `%'
75 * %c print pop() like %c in printf()
76 * %s print pop() like %s in printf()
77 * %[[:]flags][width[.precision]][doxXs]
78 * as in printf, flags are [-+#] and space
79 * The ':' is used to avoid making %+ or %-
80 * patterns (see below).
81 *
82 * %p[1-9] push ith parm
83 * %P[a-z] set dynamic variable [a-z] to pop()
84 * %g[a-z] get dynamic variable [a-z] and push it
85 * %P[A-Z] set static variable [A-Z] to pop()
86 * %g[A-Z] get static variable [A-Z] and push it
87 * %l push strlen(pop)
88 * %'c' push char constant c
89 * %{nn} push integer constant nn
90 *
91 * %+ %- %* %/ %m
92 * arithmetic (%m is mod): push(pop() op pop())
93 * %& %| %^ bit operations: push(pop() op pop())
94 * %= %> %< logical operations: push(pop() op pop())
95 * %A %O logical and & or operations for conditionals
96 * %! %~ unary operations push(op pop())
97 * %i add 1 to first two parms (for ANSI terminals)
98 *
99 * %? expr %t thenpart %e elsepart %;
100 * if-then-else, %e elsepart is optional.
101 * else-if's are possible ala Algol 68:
102 * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
103 *
104 * For those of the above operators which are binary and not commutative,
105 * the stack works in the usual way, with
106 * %gx %gy %m
107 * resulting in x mod y, not the reverse.
108 */
109
110NCURSES_EXPORT_VAR(int)int _nc_tparm_err = 0;
111
112#define TPS(var)_nc_prescreen.tparm_state.var _nc_prescreen.tparm_state.var
113
114#if NO_LEAKS0
115NCURSES_EXPORT(void)void
116_nc_free_tparm(void)
117{
118 if (TPS(out_buff)_nc_prescreen.tparm_state.out_buff != 0) {
119 FreeAndNull(TPS(out_buff))free(_nc_prescreen.tparm_state.out_buff); _nc_prescreen.tparm_state
.out_buff = 0
;
120 TPS(out_size)_nc_prescreen.tparm_state.out_size = 0;
121 TPS(out_used)_nc_prescreen.tparm_state.out_used = 0;
122 FreeAndNull(TPS(fmt_buff))free(_nc_prescreen.tparm_state.fmt_buff); _nc_prescreen.tparm_state
.fmt_buff = 0
;
123 TPS(fmt_size)_nc_prescreen.tparm_state.fmt_size = 0;
124 }
125}
126#endif
127
128static NCURSES_INLINEinline void
129get_space(size_t need)
130{
131 need += TPS(out_used)_nc_prescreen.tparm_state.out_used;
132 if (need > TPS(out_size)_nc_prescreen.tparm_state.out_size) {
133 TPS(out_size)_nc_prescreen.tparm_state.out_size = need * 2;
134 TPS(out_buff)_nc_prescreen.tparm_state.out_buff = typeRealloc(char, TPS(out_size), TPS(out_buff))(char *)_nc_doalloc(_nc_prescreen.tparm_state.out_buff, (_nc_prescreen
.tparm_state.out_size)*sizeof(char))
;
135 if (TPS(out_buff)_nc_prescreen.tparm_state.out_buff == 0)
136 _nc_err_abort(MSG_NO_MEMORY"Out of memory");
137 }
138}
139
140static NCURSES_INLINEinline void
141save_text(const char *fmt, const char *s, int len)
142{
143 size_t s_len = strlen(s);
144 if (len > (int) s_len)
145 s_len = len;
146
147 get_space(s_len + 1);
148
149 (void) snprintf(TPS(out_buff)_nc_prescreen.tparm_state.out_buff + TPS(out_used)_nc_prescreen.tparm_state.out_used, TPS(out_size)_nc_prescreen.tparm_state.out_size - TPS(out_used)_nc_prescreen.tparm_state.out_used, fmt, s);
150 TPS(out_used)_nc_prescreen.tparm_state.out_used += strlen(TPS(out_buff)_nc_prescreen.tparm_state.out_buff + TPS(out_used)_nc_prescreen.tparm_state.out_used);
151}
152
153static NCURSES_INLINEinline void
154save_number(const char *fmt, int number, int len)
155{
156 if (len < 30)
157 len = 30; /* actually log10(MAX_INT)+1 */
158
159 get_space((unsigned) len + 1);
160
161 (void) snprintf(TPS(out_buff)_nc_prescreen.tparm_state.out_buff + TPS(out_used)_nc_prescreen.tparm_state.out_used, TPS(out_size)_nc_prescreen.tparm_state.out_size - TPS(out_used)_nc_prescreen.tparm_state.out_used, fmt, number);
162 TPS(out_used)_nc_prescreen.tparm_state.out_used += strlen(TPS(out_buff)_nc_prescreen.tparm_state.out_buff + TPS(out_used)_nc_prescreen.tparm_state.out_used);
163}
164
165static NCURSES_INLINEinline void
166save_char(int c)
167{
168 if (c == 0)
169 c = 0200;
170 get_space(1);
171 TPS(out_buff)_nc_prescreen.tparm_state.out_buff[TPS(out_used)_nc_prescreen.tparm_state.out_used++] = (char) c;
172}
173
174static NCURSES_INLINEinline void
175npush(int x)
176{
177 if (TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr < STACKSIZE20) {
178 TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].num_type = TRUE1;
179 TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].data.num = x;
180 TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr++;
181 } else {
182 DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(TPS(tparam_base))));
183 _nc_tparm_err++;
184 }
185}
186
187static NCURSES_INLINEinline int
188npop(void)
189{
190 int result = 0;
191 if (TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr > 0) {
192 TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr--;
193 if (TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].num_type)
194 result = TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].data.num;
195 } else {
196 DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(TPS(tparam_base))));
197 _nc_tparm_err++;
198 }
199 return result;
200}
201
202static NCURSES_INLINEinline void
203spush(char *x)
204{
205 if (TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr < STACKSIZE20) {
206 TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].num_type = FALSE0;
207 TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].data.str = x;
208 TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr++;
209 } else {
210 DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(TPS(tparam_base))));
211 _nc_tparm_err++;
212 }
213}
214
215static NCURSES_INLINEinline char *
216spop(void)
217{
218 static char dummy[] = ""; /* avoid const-cast */
219 char *result = dummy;
220 if (TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr > 0) {
221 TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr--;
222 if (!TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].num_type
223 && TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].data.str != 0)
224 result = TPS(stack)_nc_prescreen.tparm_state.stack[TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr].data.str;
225 } else {
226 DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(TPS(tparam_base))));
227 _nc_tparm_err++;
228 }
229 return result;
230}
231
232static NCURSES_INLINEinline const char *
233parse_format(const char *s, char *format, int *len)
234{
235 *len = 0;
236 if (format != 0) {
237 bool_Bool done = FALSE0;
238 bool_Bool allowminus = FALSE0;
239 bool_Bool dot = FALSE0;
240 bool_Bool err = FALSE0;
241 char *fmt = format;
242 int my_width = 0;
243 int my_prec = 0;
244 int value = 0;
245
246 *len = 0;
247 *format++ = '%';
248 while (*s != '\0' && !done) {
249 switch (*s) {
250 case 'c': /* FALLTHRU */
251 case 'd': /* FALLTHRU */
252 case 'o': /* FALLTHRU */
253 case 'x': /* FALLTHRU */
254 case 'X': /* FALLTHRU */
255 case 's':
256 *format++ = *s;
257 done = TRUE1;
258 break;
259 case '.':
260 *format++ = *s++;
261 if (dot) {
262 err = TRUE1;
263 } else { /* value before '.' is the width */
264 dot = TRUE1;
265 my_width = value;
266 }
267 value = 0;
268 break;
269 case '#':
270 *format++ = *s++;
271 break;
272 case ' ':
273 *format++ = *s++;
274 break;
275 case ':':
276 s++;
277 allowminus = TRUE1;
278 break;
279 case '-':
280 if (allowminus) {
281 *format++ = *s++;
282 } else {
283 done = TRUE1;
284 }
285 break;
286 default:
287 if (isdigit(UChar(*s)((unsigned char)(*s)))) {
288 value = (value * 10) + (*s - '0');
289 if (value > 10000)
290 err = TRUE1;
291 *format++ = *s++;
292 } else {
293 done = TRUE1;
294 }
295 }
296 }
297
298 /*
299 * If we found an error, ignore (and remove) the flags.
300 */
301 if (err) {
302 my_width = my_prec = value = 0;
303 format = fmt;
304 *format++ = '%';
305 *format++ = *s;
306 }
307
308 /*
309 * Any value after '.' is the precision. If we did not see '.', then
310 * the value is the width.
311 */
312 if (dot)
313 my_prec = value;
314 else
315 my_width = value;
316
317 *format = '\0';
318 /* return maximum string length in print */
319 *len = (my_width > my_prec) ? my_width : my_prec;
320 }
321 return s;
322}
323
324#define isUPPER(c)((c) >= 'A' && (c) <= 'Z') ((c) >= 'A' && (c) <= 'Z')
325#define isLOWER(c)((c) >= 'a' && (c) <= 'z') ((c) >= 'a' && (c) <= 'z')
326
327/*
328 * Analyze the string to see how many parameters we need from the varargs list,
329 * and what their types are. We will only accept string parameters if they
330 * appear as a %l or %s format following an explicit parameter reference (e.g.,
331 * %p2%s). All other parameters are numbers.
332 *
333 * 'number' counts coarsely the number of pop's we see in the string, and
334 * 'popcount' shows the highest parameter number in the string. We would like
335 * to simply use the latter count, but if we are reading termcap strings, there
336 * may be cases that we cannot see the explicit parameter numbers.
337 */
338NCURSES_EXPORT(int)int
339_nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM9], int *popcount)
340{
341 size_t len2;
342 int i;
343 int lastpop = -1;
344 int len;
345 int number = 0;
346 const char *cp = string;
347 static char dummy[] = "";
348
349 if (cp == 0)
350 return 0;
351
352 if ((len2 = strlen(cp)) > TPS(fmt_size)_nc_prescreen.tparm_state.fmt_size) {
353 TPS(fmt_size)_nc_prescreen.tparm_state.fmt_size = len2 + TPS(fmt_size)_nc_prescreen.tparm_state.fmt_size + 2;
354 TPS(fmt_buff)_nc_prescreen.tparm_state.fmt_buff = typeRealloc(char, TPS(fmt_size), TPS(fmt_buff))(char *)_nc_doalloc(_nc_prescreen.tparm_state.fmt_buff, (_nc_prescreen
.tparm_state.fmt_size)*sizeof(char))
;
355 if (TPS(fmt_buff)_nc_prescreen.tparm_state.fmt_buff == 0)
356 return 0;
357 }
358
359 memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM9);
360 *popcount = 0;
361
362 while ((cp - string) < (int) len2) {
363 if (*cp == '%') {
364 cp++;
365 cp = parse_format(cp, TPS(fmt_buff)_nc_prescreen.tparm_state.fmt_buff, &len);
366 switch (*cp) {
367 default:
368 break;
369
370 case 'd': /* FALLTHRU */
371 case 'o': /* FALLTHRU */
372 case 'x': /* FALLTHRU */
373 case 'X': /* FALLTHRU */
374 case 'c': /* FALLTHRU */
375 if (lastpop <= 0)
376 number++;
377 lastpop = -1;
378 break;
379
380 case 'l':
381 case 's':
382 if (lastpop > 0)
383 p_is_s[lastpop - 1] = dummy;
384 ++number;
385 break;
386
387 case 'p':
388 cp++;
389 i = (UChar(*cp)((unsigned char)(*cp)) - '0');
390 if (i >= 0 && i <= NUM_PARM9) {
391 lastpop = i;
392 if (lastpop > *popcount)
393 *popcount = lastpop;
394 }
395 break;
396
397 case 'P':
398 ++number;
399 ++cp;
400 break;
401
402 case 'g':
403 cp++;
404 break;
405
406 case S_QUOTE'\'':
407 cp += 2;
408 lastpop = -1;
409 break;
410
411 case L_BRACE'{':
412 cp++;
413 while (isdigit(UChar(*cp)((unsigned char)(*cp)))) {
414 cp++;
415 }
416 break;
417
418 case '+':
419 case '-':
420 case '*':
421 case '/':
422 case 'm':
423 case 'A':
424 case 'O':
425 case '&':
426 case '|':
427 case '^':
428 case '=':
429 case '<':
430 case '>':
431 lastpop = -1;
432 number += 2;
433 break;
434
435 case '!':
436 case '~':
437 lastpop = -1;
438 ++number;
439 break;
440
441 case 'i':
442 /* will add 1 to first (usually two) parameters */
443 break;
444 }
445 }
446 if (*cp != '\0')
447 cp++;
448 }
449
450 if (number > NUM_PARM9)
451 number = NUM_PARM9;
452 return number;
453}
454
455static NCURSES_INLINEinline char *
456tparam_internal(const char *string, va_list ap)
457{
458 char *p_is_s[NUM_PARM9];
459 TPARM_ARGlong param[NUM_PARM9];
460 int popcount;
461 int number;
462 int len;
463 int level;
464 int x, y;
465 int i;
466 const char *cp = string;
467 size_t len2;
468
469 if (cp == NULL((void*)0))
1
Assuming 'cp' is not equal to NULL
2
Taking false branch
470 return NULL((void*)0);
471
472 TPS(out_used)_nc_prescreen.tparm_state.out_used = 0;
473 len2 = strlen(cp);
474
475 /*
476 * Find the highest parameter-number referred to in the format string.
477 * Use this value to limit the number of arguments copied from the
478 * variable-length argument list.
479 */
480 number = _nc_tparm_analyze(cp, p_is_s, &popcount);
481 if (TPS(fmt_buff)_nc_prescreen.tparm_state.fmt_buff == 0)
3
Assuming field 'fmt_buff' is not equal to null
4
Taking false branch
482 return NULL((void*)0);
483
484 for (i = 0; i < max(popcount, number)((popcount) < (number) ? (number) : (popcount)); i++) {
5
Assuming 'popcount' is < 'number'
6
'?' condition is true
7
Assuming the condition is true
8
Loop condition is true. Entering loop body
11
'?' condition is true
12
Assuming the condition is false
13
Loop condition is false. Execution continues on line 506
485 /*
486 * A few caps (such as plab_norm) have string-valued parms.
487 * We'll have to assume that the caller knows the difference, since
488 * a char* and an int may not be the same size on the stack. The
489 * normal prototype for this uses 9 long's, which is consistent with
490 * our va_arg() usage.
491 */
492 if (p_is_s[i] != 0) {
9
Assuming the condition is true
10
Taking true branch
493 p_is_s[i] = va_arg(ap, char *)__builtin_va_arg(ap, char *);
494 } else {
495 param[i] = va_arg(ap, TPARM_ARG)__builtin_va_arg(ap, long);
496 }
497 }
498
499 /*
500 * This is a termcap compatibility hack. If there are no explicit pop
501 * operations in the string, load the stack in such a way that
502 * successive pops will grab successive parameters. That will make
503 * the expansion of (for example) \E[%d;%dH work correctly in termcap
504 * style, which means tparam() will expand termcap strings OK.
505 */
506 TPS(stack_ptr)_nc_prescreen.tparm_state.stack_ptr = 0;
507 if (popcount == 0) {
14
Assuming 'popcount' is equal to 0
15
Taking true branch
508 popcount = number;
509 for (i = number - 1; i >= 0; i--) {
16
The value 0 is assigned to 'i'
17
Loop condition is true. Entering loop body
510 if (p_is_s[i])
18
Assuming the condition is false
19
Taking false branch
511 spush(p_is_s[i]);
512 else
513 npush(param[i]);
20
1st function call argument is an uninitialized value
514 }
515 }
516#ifdef TRACE
517 if (USE_TRACEF(TRACE_CALLS0x0020)) {
518 for (i = 0; i < popcount; i++) {
519 if (p_is_s[i] != 0)
520 save_text(", %s", _nc_visbuf(p_is_s[i]), 0);
521 else
522 save_number(", %d", param[i], 0);
523 }
524 _tracef(T_CALLED("%s(%s%s)")"called {" "%s(%s%s)", TPS(tname)_nc_prescreen.tparm_state.tname, _nc_visbuf(cp), TPS(out_buff)_nc_prescreen.tparm_state.out_buff);
525 TPS(out_used)_nc_prescreen.tparm_state.out_used = 0;
526 _nc_unlock_global(tracef);
527 }
528#endif /* TRACE */
529
530 while ((cp - string) < (int) len2) {
531 if (*cp != '%') {
532 save_char(UChar(*cp)((unsigned char)(*cp)));
533 } else {
534 TPS(tparam_base)_nc_prescreen.tparm_state.tparam_base = cp++;
535 cp = parse_format(cp, TPS(fmt_buff)_nc_prescreen.tparm_state.fmt_buff, &len);
536 switch (*cp) {
537 default:
538 break;
539 case '%':
540 save_char('%');
541 break;
542
543 case 'd': /* FALLTHRU */
544 case 'o': /* FALLTHRU */
545 case 'x': /* FALLTHRU */
546 case 'X': /* FALLTHRU */
547 save_number(TPS(fmt_buff)_nc_prescreen.tparm_state.fmt_buff, npop(), len);
548 break;
549
550 case 'c': /* FALLTHRU */
551 save_char(npop());
552 break;
553
554 case 'l':
555 save_number("%d", (int) strlen(spop()), 0);
556 break;
557
558 case 's':
559 save_text(TPS(fmt_buff)_nc_prescreen.tparm_state.fmt_buff, spop(), len);
560 break;
561
562 case 'p':
563 cp++;
564 i = (UChar(*cp)((unsigned char)(*cp)) - '1');
565 if (i >= 0 && i < NUM_PARM9) {
566 if (p_is_s[i])
567 spush(p_is_s[i]);
568 else
569 npush(param[i]);
570 }
571 break;
572
573 case 'P':
574 cp++;
575 if (isUPPER(*cp)((*cp) >= 'A' && (*cp) <= 'Z')) {
576 i = (UChar(*cp)((unsigned char)(*cp)) - 'A');
577 TPS(static_vars)_nc_prescreen.tparm_state.static_vars[i] = npop();
578 } else if (isLOWER(*cp)((*cp) >= 'a' && (*cp) <= 'z')) {
579 i = (UChar(*cp)((unsigned char)(*cp)) - 'a');
580 TPS(dynamic_var)_nc_prescreen.tparm_state.dynamic_var[i] = npop();
581 }
582 break;
583
584 case 'g':
585 cp++;
586 if (isUPPER(*cp)((*cp) >= 'A' && (*cp) <= 'Z')) {
587 i = (UChar(*cp)((unsigned char)(*cp)) - 'A');
588 npush(TPS(static_vars)_nc_prescreen.tparm_state.static_vars[i]);
589 } else if (isLOWER(*cp)((*cp) >= 'a' && (*cp) <= 'z')) {
590 i = (UChar(*cp)((unsigned char)(*cp)) - 'a');
591 npush(TPS(dynamic_var)_nc_prescreen.tparm_state.dynamic_var[i]);
592 }
593 break;
594
595 case S_QUOTE'\'':
596 cp++;
597 npush(UChar(*cp)((unsigned char)(*cp)));
598 cp++;
599 break;
600
601 case L_BRACE'{':
602 number = 0;
603 cp++;
604 while (isdigit(UChar(*cp)((unsigned char)(*cp)))) {
605 number = (number * 10) + (UChar(*cp)((unsigned char)(*cp)) - '0');
606 cp++;
607 }
608 npush(number);
609 break;
610
611 case '+':
612 npush(npop() + npop());
613 break;
614
615 case '-':
616 y = npop();
617 x = npop();
618 npush(x - y);
619 break;
620
621 case '*':
622 npush(npop() * npop());
623 break;
624
625 case '/':
626 y = npop();
627 x = npop();
628 npush(y ? (x / y) : 0);
629 break;
630
631 case 'm':
632 y = npop();
633 x = npop();
634 npush(y ? (x % y) : 0);
635 break;
636
637 case 'A':
638 npush(npop() && npop());
639 break;
640
641 case 'O':
642 npush(npop() || npop());
643 break;
644
645 case '&':
646 npush(npop() & npop());
647 break;
648
649 case '|':
650 npush(npop() | npop());
651 break;
652
653 case '^':
654 npush(npop() ^ npop());
655 break;
656
657 case '=':
658 y = npop();
659 x = npop();
660 npush(x == y);
661 break;
662
663 case '<':
664 y = npop();
665 x = npop();
666 npush(x < y);
667 break;
668
669 case '>':
670 y = npop();
671 x = npop();
672 npush(x > y);
673 break;
674
675 case '!':
676 npush(!npop());
677 break;
678
679 case '~':
680 npush(~npop());
681 break;
682
683 case 'i':
684 if (p_is_s[0] == 0)
685 param[0]++;
686 if (p_is_s[1] == 0)
687 param[1]++;
688 break;
689
690 case '?':
691 break;
692
693 case 't':
694 x = npop();
695 if (!x) {
696 /* scan forward for %e or %; at level zero */
697 cp++;
698 level = 0;
699 while (*cp) {
700 if (*cp == '%') {
701 cp++;
702 if (*cp == '?')
703 level++;
704 else if (*cp == ';') {
705 if (level > 0)
706 level--;
707 else
708 break;
709 } else if (*cp == 'e' && level == 0)
710 break;
711 }
712
713 if (*cp)
714 cp++;
715 }
716 }
717 break;
718
719 case 'e':
720 /* scan forward for a %; at level zero */
721 cp++;
722 level = 0;
723 while (*cp) {
724 if (*cp == '%') {
725 cp++;
726 if (*cp == '?')
727 level++;
728 else if (*cp == ';') {
729 if (level > 0)
730 level--;
731 else
732 break;
733 }
734 }
735
736 if (*cp)
737 cp++;
738 }
739 break;
740
741 case ';':
742 break;
743
744 } /* endswitch (*cp) */
745 } /* endelse (*cp == '%') */
746
747 if (*cp == '\0')
748 break;
749
750 cp++;
751 } /* endwhile (*cp) */
752
753 get_space(1);
754 TPS(out_buff)_nc_prescreen.tparm_state.out_buff[TPS(out_used)_nc_prescreen.tparm_state.out_used] = '\0';
755
756 T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff))));
757 return (TPS(out_buff)_nc_prescreen.tparm_state.out_buff);
758}
759
760#if NCURSES_TPARM_VARARGS1
761#define tparm_varargstparm tparm
762#else
763#define tparm_proto tparm
764#endif
765
766NCURSES_EXPORT(char *)char *
767tparm_varargstparm(NCURSES_CONSTconst char *string,...)
768{
769 va_list ap;
770 char *result;
771
772 _nc_tparm_err = 0;
773 va_start(ap, string)__builtin_va_start(ap, string);
774#ifdef TRACE
775 TPS(tname)_nc_prescreen.tparm_state.tname = "tparm";
776#endif /* TRACE */
777 result = tparam_internal(string, ap);
778 va_end(ap)__builtin_va_end(ap);
779 return result;
780}
781
782#if !NCURSES_TPARM_VARARGS1
783NCURSES_EXPORT(char *)char *
784tparm_proto(NCURSES_CONSTconst char *string,
785 TPARM_ARGlong a1,
786 TPARM_ARGlong a2,
787 TPARM_ARGlong a3,
788 TPARM_ARGlong a4,
789 TPARM_ARGlong a5,
790 TPARM_ARGlong a6,
791 TPARM_ARGlong a7,
792 TPARM_ARGlong a8,
793 TPARM_ARGlong a9)
794{
795 return tparm_varargstparm(string, a1, a2, a3, a4, a5, a6, a7, a8, a9);
796}
797#endif /* NCURSES_TPARM_VARARGS */