File: | src/lib/libcurses/tinfo/lib_tparm.c |
Warning: | line 685, column 7 The expression is an uninitialized value. The computed value will also be garbage |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
48 | MODULE_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 | ||||
110 | NCURSES_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 | |||
115 | NCURSES_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 | ||||
128 | static NCURSES_INLINEinline void | |||
129 | get_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 | ||||
140 | static NCURSES_INLINEinline void | |||
141 | save_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 | ||||
153 | static NCURSES_INLINEinline void | |||
154 | save_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 | ||||
165 | static NCURSES_INLINEinline void | |||
166 | save_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 | ||||
174 | static NCURSES_INLINEinline void | |||
175 | npush(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 | ||||
187 | static NCURSES_INLINEinline int | |||
188 | npop(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 | ||||
202 | static NCURSES_INLINEinline void | |||
203 | spush(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 | ||||
215 | static NCURSES_INLINEinline char * | |||
216 | spop(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 | ||||
232 | static NCURSES_INLINEinline const char * | |||
233 | parse_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 | */ | |||
338 | NCURSES_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 | ||||
455 | static NCURSES_INLINEinline char * | |||
456 | tparam_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)) | |||
| ||||
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) | |||
482 | return NULL((void*)0); | |||
483 | ||||
484 | for (i = 0; i < max(popcount, number)((popcount) < (number) ? (number) : (popcount)); i++) { | |||
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) { | |||
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
| |||
508 | popcount = number; | |||
509 | for (i = number - 1; i >= 0; i--) { | |||
510 | if (p_is_s[i]) | |||
511 | spush(p_is_s[i]); | |||
512 | else | |||
513 | npush(param[i]); | |||
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 | ||||
766 | NCURSES_EXPORT(char *)char * | |||
767 | tparm_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 | |||
783 | NCURSES_EXPORT(char *)char * | |||
784 | tparm_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 */ |