150276Speter/**************************************************************************** 2184989Srafan * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32166124Srafan * and: Thomas E. Dickey, 1996 on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter/* 3650276Speter * tparm.c 3750276Speter * 3850276Speter */ 3950276Speter 4050276Speter#include <curses.priv.h> 4150276Speter 4250276Speter#include <ctype.h> 4350276Speter#include <term.h> 4450276Speter#include <tic.h> 4550276Speter 46184989SrafanMODULE_ID("$Id: lib_tparm.c,v 1.76 2008/08/16 19:22:55 tom Exp $") 4750276Speter 4850276Speter/* 4950276Speter * char * 5050276Speter * tparm(string, ...) 5150276Speter * 5250276Speter * Substitute the given parameters into the given string by the following 5350276Speter * rules (taken from terminfo(5)): 5450276Speter * 5550276Speter * Cursor addressing and other strings requiring parame- 5650276Speter * ters in the terminal are described by a parameterized string 5750276Speter * capability, with like escapes %x in it. For example, to 5850276Speter * address the cursor, the cup capability is given, using two 5950276Speter * parameters: the row and column to address to. (Rows and 6050276Speter * columns are numbered from zero and refer to the physical 6150276Speter * screen visible to the user, not to any unseen memory.) If 6250276Speter * the terminal has memory relative cursor addressing, that can 6350276Speter * be indicated by 6450276Speter * 6550276Speter * The parameter mechanism uses a stack and special % 6650276Speter * codes to manipulate it. Typically a sequence will push one 6750276Speter * of the parameters onto the stack and then print it in some 6850276Speter * format. Often more complex operations are necessary. 6950276Speter * 7050276Speter * The % encodings have the following meanings: 7150276Speter * 7250276Speter * %% outputs `%' 7350276Speter * %c print pop() like %c in printf() 7450276Speter * %s print pop() like %s in printf() 7550276Speter * %[[:]flags][width[.precision]][doxXs] 7650276Speter * as in printf, flags are [-+#] and space 7766963Speter * The ':' is used to avoid making %+ or %- 7866963Speter * patterns (see below). 7950276Speter * 8050276Speter * %p[1-9] push ith parm 8150276Speter * %P[a-z] set dynamic variable [a-z] to pop() 8250276Speter * %g[a-z] get dynamic variable [a-z] and push it 8350276Speter * %P[A-Z] set static variable [A-Z] to pop() 8450276Speter * %g[A-Z] get static variable [A-Z] and push it 8550276Speter * %l push strlen(pop) 8650276Speter * %'c' push char constant c 8750276Speter * %{nn} push integer constant nn 8850276Speter * 8950276Speter * %+ %- %* %/ %m 9050276Speter * arithmetic (%m is mod): push(pop() op pop()) 9150276Speter * %& %| %^ bit operations: push(pop() op pop()) 9250276Speter * %= %> %< logical operations: push(pop() op pop()) 9350276Speter * %A %O logical and & or operations for conditionals 9450276Speter * %! %~ unary operations push(op pop()) 9550276Speter * %i add 1 to first two parms (for ANSI terminals) 9650276Speter * 9750276Speter * %? expr %t thenpart %e elsepart %; 9850276Speter * if-then-else, %e elsepart is optional. 9950276Speter * else-if's are possible ala Algol 68: 10050276Speter * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %; 10150276Speter * 10250276Speter * For those of the above operators which are binary and not commutative, 10350276Speter * the stack works in the usual way, with 10450276Speter * %gx %gy %m 10550276Speter * resulting in x mod y, not the reverse. 10650276Speter */ 10750276Speter 10876726SpeterNCURSES_EXPORT_VAR(int) _nc_tparm_err = 0; 10976726Speter 110174993Srafan#define TPS(var) _nc_prescreen.tparm_state.var 11166963Speter 11250276Speter#if NO_LEAKS 11376726SpeterNCURSES_EXPORT(void) 11466963Speter_nc_free_tparm(void) 11550276Speter{ 116174993Srafan if (TPS(out_buff) != 0) { 117174993Srafan FreeAndNull(TPS(out_buff)); 118174993Srafan TPS(out_size) = 0; 119174993Srafan TPS(out_used) = 0; 120174993Srafan FreeAndNull(TPS(fmt_buff)); 121174993Srafan TPS(fmt_size) = 0; 12266963Speter } 12350276Speter} 12450276Speter#endif 12550276Speter 126166124Srafanstatic NCURSES_INLINE void 12766963Speterget_space(size_t need) 12850276Speter{ 129174993Srafan need += TPS(out_used); 130174993Srafan if (need > TPS(out_size)) { 131174993Srafan TPS(out_size) = need * 2; 132174993Srafan TPS(out_buff) = typeRealloc(char, TPS(out_size), TPS(out_buff)); 133174993Srafan if (TPS(out_buff) == 0) 134166124Srafan _nc_err_abort(MSG_NO_MEMORY); 135166124Srafan } 13650276Speter} 13750276Speter 138166124Srafanstatic NCURSES_INLINE void 13966963Spetersave_text(const char *fmt, const char *s, int len) 14050276Speter{ 14166963Speter size_t s_len = strlen(s); 14266963Speter if (len > (int) s_len) 14366963Speter s_len = len; 14450276Speter 14566963Speter get_space(s_len + 1); 14650276Speter 147174993Srafan (void) sprintf(TPS(out_buff) + TPS(out_used), fmt, s); 148174993Srafan TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); 14950276Speter} 15050276Speter 151166124Srafanstatic NCURSES_INLINE void 15266963Spetersave_number(const char *fmt, int number, int len) 15350276Speter{ 15466963Speter if (len < 30) 15566963Speter len = 30; /* actually log10(MAX_INT)+1 */ 15650276Speter 157166124Srafan get_space((unsigned) len + 1); 15850276Speter 159174993Srafan (void) sprintf(TPS(out_buff) + TPS(out_used), fmt, number); 160174993Srafan TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); 16150276Speter} 16250276Speter 163166124Srafanstatic NCURSES_INLINE void 16466963Spetersave_char(int c) 16550276Speter{ 16666963Speter if (c == 0) 16766963Speter c = 0200; 16866963Speter get_space(1); 169184989Srafan TPS(out_buff)[TPS(out_used)++] = (char) c; 17050276Speter} 17150276Speter 172166124Srafanstatic NCURSES_INLINE void 17366963Speternpush(int x) 17450276Speter{ 175174993Srafan if (TPS(stack_ptr) < STACKSIZE) { 176174993Srafan TPS(stack)[TPS(stack_ptr)].num_type = TRUE; 177174993Srafan TPS(stack)[TPS(stack_ptr)].data.num = x; 178174993Srafan TPS(stack_ptr)++; 17976726Speter } else { 180174993Srafan DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); 18176726Speter _nc_tparm_err++; 18266963Speter } 18350276Speter} 18450276Speter 185166124Srafanstatic NCURSES_INLINE int 18666963Speternpop(void) 18750276Speter{ 18866963Speter int result = 0; 189174993Srafan if (TPS(stack_ptr) > 0) { 190174993Srafan TPS(stack_ptr)--; 191174993Srafan if (TPS(stack)[TPS(stack_ptr)].num_type) 192174993Srafan result = TPS(stack)[TPS(stack_ptr)].data.num; 19376726Speter } else { 194174993Srafan DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); 19576726Speter _nc_tparm_err++; 19666963Speter } 19766963Speter return result; 19850276Speter} 19950276Speter 200166124Srafanstatic NCURSES_INLINE void 20166963Speterspush(char *x) 20250276Speter{ 203174993Srafan if (TPS(stack_ptr) < STACKSIZE) { 204174993Srafan TPS(stack)[TPS(stack_ptr)].num_type = FALSE; 205174993Srafan TPS(stack)[TPS(stack_ptr)].data.str = x; 206174993Srafan TPS(stack_ptr)++; 20776726Speter } else { 208174993Srafan DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); 20976726Speter _nc_tparm_err++; 21066963Speter } 21150276Speter} 21250276Speter 213166124Srafanstatic NCURSES_INLINE char * 21466963Speterspop(void) 21550276Speter{ 21666963Speter static char dummy[] = ""; /* avoid const-cast */ 21766963Speter char *result = dummy; 218174993Srafan if (TPS(stack_ptr) > 0) { 219174993Srafan TPS(stack_ptr)--; 220174993Srafan if (!TPS(stack)[TPS(stack_ptr)].num_type 221174993Srafan && TPS(stack)[TPS(stack_ptr)].data.str != 0) 222174993Srafan result = TPS(stack)[TPS(stack_ptr)].data.str; 22376726Speter } else { 224174993Srafan DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); 22576726Speter _nc_tparm_err++; 22666963Speter } 22766963Speter return result; 22866963Speter} 22950276Speter 230166124Srafanstatic NCURSES_INLINE const char * 23166963Speterparse_format(const char *s, char *format, int *len) 23266963Speter{ 233166124Srafan *len = 0; 234166124Srafan if (format != 0) { 235166124Srafan bool done = FALSE; 236166124Srafan bool allowminus = FALSE; 237166124Srafan bool dot = FALSE; 238166124Srafan bool err = FALSE; 239166124Srafan char *fmt = format; 240166124Srafan int my_width = 0; 241166124Srafan int my_prec = 0; 242166124Srafan int value = 0; 24366963Speter 244166124Srafan *len = 0; 245166124Srafan *format++ = '%'; 246166124Srafan while (*s != '\0' && !done) { 247166124Srafan switch (*s) { 248166124Srafan case 'c': /* FALLTHRU */ 249166124Srafan case 'd': /* FALLTHRU */ 250166124Srafan case 'o': /* FALLTHRU */ 251166124Srafan case 'x': /* FALLTHRU */ 252166124Srafan case 'X': /* FALLTHRU */ 253166124Srafan case 's': 254166124Srafan *format++ = *s; 255166124Srafan done = TRUE; 256166124Srafan break; 257166124Srafan case '.': 25866963Speter *format++ = *s++; 259166124Srafan if (dot) { 26066963Speter err = TRUE; 261166124Srafan } else { /* value before '.' is the width */ 262166124Srafan dot = TRUE; 263166124Srafan my_width = value; 264166124Srafan } 265166124Srafan value = 0; 266166124Srafan break; 267166124Srafan case '#': 26866963Speter *format++ = *s++; 269166124Srafan break; 270166124Srafan case ' ': 271166124Srafan *format++ = *s++; 272166124Srafan break; 273166124Srafan case ':': 274166124Srafan s++; 275166124Srafan allowminus = TRUE; 276166124Srafan break; 277166124Srafan case '-': 278166124Srafan if (allowminus) { 279166124Srafan *format++ = *s++; 280166124Srafan } else { 281166124Srafan done = TRUE; 282166124Srafan } 283166124Srafan break; 284166124Srafan default: 285166124Srafan if (isdigit(UChar(*s))) { 286166124Srafan value = (value * 10) + (*s - '0'); 287166124Srafan if (value > 10000) 288166124Srafan err = TRUE; 289166124Srafan *format++ = *s++; 290166124Srafan } else { 291166124Srafan done = TRUE; 292166124Srafan } 29366963Speter } 29466963Speter } 29566963Speter 296166124Srafan /* 297166124Srafan * If we found an error, ignore (and remove) the flags. 298166124Srafan */ 299166124Srafan if (err) { 300166124Srafan my_width = my_prec = value = 0; 301166124Srafan format = fmt; 302166124Srafan *format++ = '%'; 303166124Srafan *format++ = *s; 304166124Srafan } 30566963Speter 306166124Srafan /* 307166124Srafan * Any value after '.' is the precision. If we did not see '.', then 308166124Srafan * the value is the width. 309166124Srafan */ 310166124Srafan if (dot) 311166124Srafan my_prec = value; 312166124Srafan else 313166124Srafan my_width = value; 31466963Speter 315166124Srafan *format = '\0'; 316166124Srafan /* return maximum string length in print */ 317166124Srafan *len = (my_width > my_prec) ? my_width : my_prec; 318166124Srafan } 31966963Speter return s; 32050276Speter} 32150276Speter 32250276Speter#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z') 32350276Speter#define isLOWER(c) ((c) >= 'a' && (c) <= 'z') 32450276Speter 325166124Srafan/* 326166124Srafan * Analyze the string to see how many parameters we need from the varargs list, 327166124Srafan * and what their types are. We will only accept string parameters if they 328166124Srafan * appear as a %l or %s format following an explicit parameter reference (e.g., 329166124Srafan * %p2%s). All other parameters are numbers. 330166124Srafan * 331166124Srafan * 'number' counts coarsely the number of pop's we see in the string, and 332166124Srafan * 'popcount' shows the highest parameter number in the string. We would like 333166124Srafan * to simply use the latter count, but if we are reading termcap strings, there 334166124Srafan * may be cases that we cannot see the explicit parameter numbers. 335166124Srafan */ 336166124SrafanNCURSES_EXPORT(int) 337166124Srafan_nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) 33850276Speter{ 339166124Srafan size_t len2; 340166124Srafan int i; 341166124Srafan int lastpop = -1; 34266963Speter int len; 343166124Srafan int number = 0; 344166124Srafan const char *cp = string; 34566963Speter static char dummy[] = ""; 34650276Speter 347166124Srafan if (cp == 0) 348166124Srafan return 0; 34950276Speter 350174993Srafan if ((len2 = strlen(cp)) > TPS(fmt_size)) { 351174993Srafan TPS(fmt_size) = len2 + TPS(fmt_size) + 2; 352174993Srafan TPS(fmt_buff) = typeRealloc(char, TPS(fmt_size), TPS(fmt_buff)); 353174993Srafan if (TPS(fmt_buff) == 0) 354174993Srafan return 0; 35566963Speter } 35666963Speter 357166124Srafan memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM); 358166124Srafan *popcount = 0; 35966963Speter 360166124Srafan while ((cp - string) < (int) len2) { 36166963Speter if (*cp == '%') { 36266963Speter cp++; 363174993Srafan cp = parse_format(cp, TPS(fmt_buff), &len); 36466963Speter switch (*cp) { 36566963Speter default: 36666963Speter break; 36766963Speter 36866963Speter case 'd': /* FALLTHRU */ 36966963Speter case 'o': /* FALLTHRU */ 37066963Speter case 'x': /* FALLTHRU */ 37166963Speter case 'X': /* FALLTHRU */ 37266963Speter case 'c': /* FALLTHRU */ 373166124Srafan if (lastpop <= 0) 374166124Srafan number++; 37566963Speter lastpop = -1; 37666963Speter break; 37766963Speter 37866963Speter case 'l': 37966963Speter case 's': 38066963Speter if (lastpop > 0) 38166963Speter p_is_s[lastpop - 1] = dummy; 38266963Speter ++number; 38366963Speter break; 38466963Speter 38566963Speter case 'p': 38666963Speter cp++; 387166124Srafan i = (UChar(*cp) - '0'); 388166124Srafan if (i >= 0 && i <= NUM_PARM) { 38966963Speter lastpop = i; 390166124Srafan if (lastpop > *popcount) 391166124Srafan *popcount = lastpop; 39250276Speter } 39366963Speter break; 39450276Speter 39566963Speter case 'P': 396166124Srafan ++number; 397166124Srafan ++cp; 398166124Srafan break; 399166124Srafan 40066963Speter case 'g': 40166963Speter cp++; 40266963Speter break; 40366963Speter 40466963Speter case S_QUOTE: 40566963Speter cp += 2; 40666963Speter lastpop = -1; 40766963Speter break; 40866963Speter 40966963Speter case L_BRACE: 41066963Speter cp++; 411166124Srafan while (isdigit(UChar(*cp))) { 41266963Speter cp++; 41366963Speter } 41466963Speter break; 41566963Speter 41666963Speter case '+': 41766963Speter case '-': 41866963Speter case '*': 41966963Speter case '/': 42066963Speter case 'm': 42166963Speter case 'A': 42266963Speter case 'O': 42366963Speter case '&': 42466963Speter case '|': 42566963Speter case '^': 42666963Speter case '=': 42766963Speter case '<': 42866963Speter case '>': 429166124Srafan lastpop = -1; 430166124Srafan number += 2; 431166124Srafan break; 432166124Srafan 43366963Speter case '!': 43466963Speter case '~': 43566963Speter lastpop = -1; 436166124Srafan ++number; 43766963Speter break; 43866963Speter 43966963Speter case 'i': 440166124Srafan /* will add 1 to first (usually two) parameters */ 44166963Speter break; 44266963Speter } 44350276Speter } 44466963Speter if (*cp != '\0') 44566963Speter cp++; 44666963Speter } 44750276Speter 448166124Srafan if (number > NUM_PARM) 449166124Srafan number = NUM_PARM; 450166124Srafan return number; 451166124Srafan} 452166124Srafan 453166124Srafanstatic NCURSES_INLINE char * 454166124Srafantparam_internal(const char *string, va_list ap) 455166124Srafan{ 456166124Srafan char *p_is_s[NUM_PARM]; 457166124Srafan TPARM_ARG param[NUM_PARM]; 458166124Srafan int popcount; 459166124Srafan int number; 460166124Srafan int len; 461166124Srafan int level; 462166124Srafan int x, y; 463166124Srafan int i; 464166124Srafan const char *cp = string; 465166124Srafan size_t len2; 466166124Srafan 467166124Srafan if (cp == NULL) 468166124Srafan return NULL; 469166124Srafan 470174993Srafan TPS(out_used) = 0; 471166124Srafan len2 = strlen(cp); 472166124Srafan 473166124Srafan /* 474166124Srafan * Find the highest parameter-number referred to in the format string. 475166124Srafan * Use this value to limit the number of arguments copied from the 476166124Srafan * variable-length argument list. 477166124Srafan */ 478166124Srafan number = _nc_tparm_analyze(cp, p_is_s, &popcount); 479174993Srafan if (TPS(fmt_buff) == 0) 480166124Srafan return NULL; 481166124Srafan 48266963Speter for (i = 0; i < max(popcount, number); i++) { 48350276Speter /* 48466963Speter * A few caps (such as plab_norm) have string-valued parms. 48566963Speter * We'll have to assume that the caller knows the difference, since 486166124Srafan * a char* and an int may not be the same size on the stack. The 487166124Srafan * normal prototype for this uses 9 long's, which is consistent with 488166124Srafan * our va_arg() usage. 48950276Speter */ 49066963Speter if (p_is_s[i] != 0) { 49166963Speter p_is_s[i] = va_arg(ap, char *); 49266963Speter } else { 493166124Srafan param[i] = va_arg(ap, TPARM_ARG); 49450276Speter } 49566963Speter } 49650276Speter 49766963Speter /* 49866963Speter * This is a termcap compatibility hack. If there are no explicit pop 49966963Speter * operations in the string, load the stack in such a way that 50066963Speter * successive pops will grab successive parameters. That will make 50166963Speter * the expansion of (for example) \E[%d;%dH work correctly in termcap 50266963Speter * style, which means tparam() will expand termcap strings OK. 50366963Speter */ 504174993Srafan TPS(stack_ptr) = 0; 50566963Speter if (popcount == 0) { 50666963Speter popcount = number; 507184989Srafan for (i = number - 1; i >= 0; i--) { 508184989Srafan if (p_is_s[i]) 509184989Srafan spush(p_is_s[i]); 510184989Srafan else 511184989Srafan npush(param[i]); 512184989Srafan } 51366963Speter } 51450276Speter#ifdef TRACE 515174993Srafan if (USE_TRACEF(TRACE_CALLS)) { 51666963Speter for (i = 0; i < popcount; i++) { 51766963Speter if (p_is_s[i] != 0) 51866963Speter save_text(", %s", _nc_visbuf(p_is_s[i]), 0); 51966963Speter else 52066963Speter save_number(", %d", param[i], 0); 52150276Speter } 522174993Srafan _tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(cp), TPS(out_buff)); 523174993Srafan TPS(out_used) = 0; 524174993Srafan _nc_unlock_global(tracef); 52566963Speter } 52650276Speter#endif /* TRACE */ 52750276Speter 528166124Srafan while ((cp - string) < (int) len2) { 529166124Srafan if (*cp != '%') { 530166124Srafan save_char(UChar(*cp)); 53166963Speter } else { 532174993Srafan TPS(tparam_base) = cp++; 533174993Srafan cp = parse_format(cp, TPS(fmt_buff), &len); 534166124Srafan switch (*cp) { 53566963Speter default: 53666963Speter break; 53766963Speter case '%': 53866963Speter save_char('%'); 53966963Speter break; 54050276Speter 54166963Speter case 'd': /* FALLTHRU */ 54266963Speter case 'o': /* FALLTHRU */ 54366963Speter case 'x': /* FALLTHRU */ 54466963Speter case 'X': /* FALLTHRU */ 545174993Srafan save_number(TPS(fmt_buff), npop(), len); 546166124Srafan break; 547166124Srafan 54866963Speter case 'c': /* FALLTHRU */ 549166124Srafan save_char(npop()); 55066963Speter break; 55150276Speter 55266963Speter case 'l': 553166124Srafan save_number("%d", (int) strlen(spop()), 0); 55466963Speter break; 55550276Speter 55666963Speter case 's': 557174993Srafan save_text(TPS(fmt_buff), spop(), len); 55866963Speter break; 55950276Speter 56066963Speter case 'p': 561166124Srafan cp++; 562166124Srafan i = (UChar(*cp) - '1'); 563166124Srafan if (i >= 0 && i < NUM_PARM) { 56466963Speter if (p_is_s[i]) 56566963Speter spush(p_is_s[i]); 56666963Speter else 56766963Speter npush(param[i]); 56866963Speter } 56966963Speter break; 57050276Speter 57166963Speter case 'P': 572166124Srafan cp++; 573166124Srafan if (isUPPER(*cp)) { 574166124Srafan i = (UChar(*cp) - 'A'); 575174993Srafan TPS(static_vars)[i] = npop(); 576166124Srafan } else if (isLOWER(*cp)) { 577166124Srafan i = (UChar(*cp) - 'a'); 578174993Srafan TPS(dynamic_var)[i] = npop(); 57966963Speter } 58066963Speter break; 58150276Speter 58266963Speter case 'g': 583166124Srafan cp++; 584166124Srafan if (isUPPER(*cp)) { 585166124Srafan i = (UChar(*cp) - 'A'); 586174993Srafan npush(TPS(static_vars)[i]); 587166124Srafan } else if (isLOWER(*cp)) { 588166124Srafan i = (UChar(*cp) - 'a'); 589174993Srafan npush(TPS(dynamic_var)[i]); 59066963Speter } 59166963Speter break; 59250276Speter 59366963Speter case S_QUOTE: 594166124Srafan cp++; 595166124Srafan npush(UChar(*cp)); 596166124Srafan cp++; 59766963Speter break; 59850276Speter 59966963Speter case L_BRACE: 60066963Speter number = 0; 601166124Srafan cp++; 602166124Srafan while (isdigit(UChar(*cp))) { 603166124Srafan number = (number * 10) + (UChar(*cp) - '0'); 604166124Srafan cp++; 60566963Speter } 60666963Speter npush(number); 60766963Speter break; 60850276Speter 60966963Speter case '+': 61066963Speter npush(npop() + npop()); 61166963Speter break; 61250276Speter 61366963Speter case '-': 61466963Speter y = npop(); 61566963Speter x = npop(); 61666963Speter npush(x - y); 61766963Speter break; 61850276Speter 61966963Speter case '*': 62066963Speter npush(npop() * npop()); 62166963Speter break; 62250276Speter 62366963Speter case '/': 62466963Speter y = npop(); 62566963Speter x = npop(); 62666963Speter npush(y ? (x / y) : 0); 62766963Speter break; 62850276Speter 62966963Speter case 'm': 63066963Speter y = npop(); 63166963Speter x = npop(); 63266963Speter npush(y ? (x % y) : 0); 63366963Speter break; 63450276Speter 63566963Speter case 'A': 63666963Speter npush(npop() && npop()); 63766963Speter break; 63850276Speter 63966963Speter case 'O': 64066963Speter npush(npop() || npop()); 64166963Speter break; 64250276Speter 64366963Speter case '&': 64466963Speter npush(npop() & npop()); 64566963Speter break; 64650276Speter 64766963Speter case '|': 64866963Speter npush(npop() | npop()); 64966963Speter break; 65050276Speter 65166963Speter case '^': 65266963Speter npush(npop() ^ npop()); 65366963Speter break; 65450276Speter 65566963Speter case '=': 65666963Speter y = npop(); 65766963Speter x = npop(); 65866963Speter npush(x == y); 65966963Speter break; 66050276Speter 66166963Speter case '<': 66266963Speter y = npop(); 66366963Speter x = npop(); 66466963Speter npush(x < y); 66566963Speter break; 66650276Speter 66766963Speter case '>': 66866963Speter y = npop(); 66966963Speter x = npop(); 67066963Speter npush(x > y); 67166963Speter break; 67250276Speter 67366963Speter case '!': 67466963Speter npush(!npop()); 67566963Speter break; 67650276Speter 67766963Speter case '~': 67866963Speter npush(~npop()); 67966963Speter break; 68050276Speter 68166963Speter case 'i': 68266963Speter if (p_is_s[0] == 0) 68366963Speter param[0]++; 68466963Speter if (p_is_s[1] == 0) 68566963Speter param[1]++; 68666963Speter break; 68750276Speter 68866963Speter case '?': 68966963Speter break; 69066963Speter 69166963Speter case 't': 69266963Speter x = npop(); 69366963Speter if (!x) { 69466963Speter /* scan forward for %e or %; at level zero */ 695166124Srafan cp++; 69666963Speter level = 0; 697166124Srafan while (*cp) { 698166124Srafan if (*cp == '%') { 699166124Srafan cp++; 700166124Srafan if (*cp == '?') 70166963Speter level++; 702166124Srafan else if (*cp == ';') { 70366963Speter if (level > 0) 70466963Speter level--; 70566963Speter else 70666963Speter break; 707166124Srafan } else if (*cp == 'e' && level == 0) 70850276Speter break; 70966963Speter } 71050276Speter 711166124Srafan if (*cp) 712166124Srafan cp++; 71366963Speter } 71466963Speter } 71566963Speter break; 71650276Speter 71766963Speter case 'e': 71866963Speter /* scan forward for a %; at level zero */ 719166124Srafan cp++; 72066963Speter level = 0; 721166124Srafan while (*cp) { 722166124Srafan if (*cp == '%') { 723166124Srafan cp++; 724166124Srafan if (*cp == '?') 72566963Speter level++; 726166124Srafan else if (*cp == ';') { 72766963Speter if (level > 0) 72866963Speter level--; 72966963Speter else 73050276Speter break; 73166963Speter } 73266963Speter } 73350276Speter 734166124Srafan if (*cp) 735166124Srafan cp++; 73666963Speter } 73766963Speter break; 73850276Speter 73966963Speter case ';': 74066963Speter break; 74150276Speter 742166124Srafan } /* endswitch (*cp) */ 743166124Srafan } /* endelse (*cp == '%') */ 74450276Speter 745166124Srafan if (*cp == '\0') 74666963Speter break; 74750276Speter 748166124Srafan cp++; 749166124Srafan } /* endwhile (*cp) */ 75050276Speter 75176726Speter get_space(1); 752174993Srafan TPS(out_buff)[TPS(out_used)] = '\0'; 75350276Speter 754174993Srafan T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff)))); 755174993Srafan return (TPS(out_buff)); 75650276Speter} 75750276Speter 758166124Srafan#if NCURSES_TPARM_VARARGS 759166124Srafan#define tparm_varargs tparm 760166124Srafan#else 761166124Srafan#define tparm_proto tparm 762166124Srafan#endif 763166124Srafan 76476726SpeterNCURSES_EXPORT(char *) 765166124Srafantparm_varargs(NCURSES_CONST char *string,...) 76650276Speter{ 76766963Speter va_list ap; 76866963Speter char *result; 76950276Speter 77076726Speter _nc_tparm_err = 0; 77166963Speter va_start(ap, string); 77250276Speter#ifdef TRACE 773174993Srafan TPS(tname) = "tparm"; 77450276Speter#endif /* TRACE */ 77566963Speter result = tparam_internal(string, ap); 77666963Speter va_end(ap); 77766963Speter return result; 77850276Speter} 779166124Srafan 780166124Srafan#if !NCURSES_TPARM_VARARGS 781166124SrafanNCURSES_EXPORT(char *) 782166124Srafantparm_proto(NCURSES_CONST char *string, 783166124Srafan TPARM_ARG a1, 784166124Srafan TPARM_ARG a2, 785166124Srafan TPARM_ARG a3, 786166124Srafan TPARM_ARG a4, 787166124Srafan TPARM_ARG a5, 788166124Srafan TPARM_ARG a6, 789166124Srafan TPARM_ARG a7, 790166124Srafan TPARM_ARG a8, 791166124Srafan TPARM_ARG a9) 792166124Srafan{ 793166124Srafan return tparm_varargs(string, a1, a2, a3, a4, a5, a6, a7, a8, a9); 794166124Srafan} 795166124Srafan#endif /* NCURSES_TPARM_VARARGS */ 796