X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Flib_tparm.c;h=53205d1711bf06fb86c563edc4433e959ee9e995;hp=71b82916a356e405a4bab93694fc6de3e5824543;hb=29b24b6ba47681c8a26007492567c3daecb3defe;hpb=0eb88fc5281804773e2a0c7a488a4452463535ce diff --git a/ncurses/tinfo/lib_tparm.c b/ncurses/tinfo/lib_tparm.c index 71b82916..53205d17 100644 --- a/ncurses/tinfo/lib_tparm.c +++ b/ncurses/tinfo/lib_tparm.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,9 +29,9 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey, 1996 on * ****************************************************************************/ - /* * tparm.c * @@ -40,10 +40,9 @@ #include #include -#include #include -MODULE_ID("$Id: lib_tparm.c,v 1.39 1999/06/06 00:04:55 tom Exp $") +MODULE_ID("$Id: lib_tparm.c,v 1.84 2011/10/22 15:48:47 tom Exp $") /* * char * @@ -74,6 +73,8 @@ MODULE_ID("$Id: lib_tparm.c,v 1.39 1999/06/06 00:04:55 tom Exp $") * %s print pop() like %s in printf() * %[[:]flags][width[.precision]][doxXs] * as in printf, flags are [-+#] and space + * The ':' is used to avoid making %+ or %- + * patterns (see below). * * %p[1-9] push ith parm * %P[a-z] set dynamic variable [a-z] to pop() @@ -103,483 +104,717 @@ MODULE_ID("$Id: lib_tparm.c,v 1.39 1999/06/06 00:04:55 tom Exp $") * resulting in x mod y, not the reverse. */ -#define STACKSIZE 20 - -typedef union { - unsigned int num; - char *str; -} stack_frame; +NCURSES_EXPORT_VAR(int) _nc_tparm_err = 0; -static stack_frame stack[STACKSIZE]; -static int stack_ptr; -#ifdef TRACE -static const char *tname; -#endif /* TRACE */ - -static char *out_buff; -static size_t out_size; -static size_t out_used; +#define TPS(var) _nc_prescreen.tparm_state.var #if NO_LEAKS -void _nc_free_tparm(void) +NCURSES_EXPORT(void) +_nc_free_tparm(void) { - if (out_buff != 0) { - FreeAndNull(out_buff); - out_size = 0; - out_used = 0; - } + if (TPS(out_buff) != 0) { + FreeAndNull(TPS(out_buff)); + TPS(out_size) = 0; + TPS(out_used) = 0; + FreeAndNull(TPS(fmt_buff)); + TPS(fmt_size) = 0; + } } #endif -static void really_get_space(size_t need) +static NCURSES_INLINE void +get_space(size_t need) { - out_size = need * 2; - out_buff = typeRealloc(char, out_size, out_buff); - if (out_buff == 0) - _nc_err_abort("Out of memory"); + need += TPS(out_used); + if (need > TPS(out_size)) { + TPS(out_size) = need * 2; + TPS(out_buff) = typeRealloc(char, TPS(out_size), TPS(out_buff)); + if (TPS(out_buff) == 0) + _nc_err_abort(MSG_NO_MEMORY); + } } -static inline void get_space(size_t need) +static NCURSES_INLINE void +save_text(const char *fmt, const char *s, int len) { - need += out_used; - if (need > out_size) - really_get_space(need); + size_t s_len = strlen(s); + if (len > (int) s_len) + s_len = (size_t) len; + + get_space(s_len + 1); + + (void) sprintf(TPS(out_buff) + TPS(out_used), fmt, s); + TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); } -static inline void save_text(const char *fmt, char *s, int len) +static NCURSES_INLINE void +save_number(const char *fmt, int number, int len) { - size_t s_len = strlen(s); - if (len > (int)s_len) - s_len = len; + if (len < 30) + len = 30; /* actually log10(MAX_INT)+1 */ - get_space(s_len + 1); + get_space((size_t) len + 1); - (void)sprintf(out_buff+out_used, fmt, s); - out_used += strlen(out_buff+out_used); + (void) sprintf(TPS(out_buff) + TPS(out_used), fmt, number); + TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); } -static inline void save_number(const char *fmt, int number, int len) +static NCURSES_INLINE void +save_char(int c) { - if (len < 30) - len = 30; /* actually log10(MAX_INT)+1 */ - - get_space(len + 1); - - (void)sprintf(out_buff+out_used, fmt, number); - out_used += strlen(out_buff+out_used); + if (c == 0) + c = 0200; + get_space((size_t) 1); + TPS(out_buff)[TPS(out_used)++] = (char) c; } -static inline void save_char(int c) +static NCURSES_INLINE void +npush(int x) { - if (c == 0) - c = 0200; - get_space(1); - out_buff[out_used++] = c; + if (TPS(stack_ptr) < STACKSIZE) { + TPS(stack)[TPS(stack_ptr)].num_type = TRUE; + TPS(stack)[TPS(stack_ptr)].data.num = x; + TPS(stack_ptr)++; + } else { + DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); + _nc_tparm_err++; + } } -static inline void npush(int x) +static NCURSES_INLINE int +npop(void) { - if (stack_ptr < STACKSIZE) { - stack[stack_ptr].num = x; - stack_ptr++; - } + int result = 0; + if (TPS(stack_ptr) > 0) { + TPS(stack_ptr)--; + if (TPS(stack)[TPS(stack_ptr)].num_type) + result = TPS(stack)[TPS(stack_ptr)].data.num; + } else { + DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); + _nc_tparm_err++; + } + return result; } -static inline int npop(void) +static NCURSES_INLINE void +spush(char *x) { - return (stack_ptr > 0 ? stack[--stack_ptr].num : 0); + if (TPS(stack_ptr) < STACKSIZE) { + TPS(stack)[TPS(stack_ptr)].num_type = FALSE; + TPS(stack)[TPS(stack_ptr)].data.str = x; + TPS(stack_ptr)++; + } else { + DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); + _nc_tparm_err++; + } } -static inline char *spop(void) +static NCURSES_INLINE char * +spop(void) { - static char dummy[] = ""; /* avoid const-cast */ - return (stack_ptr > 0 ? stack[--stack_ptr].str : dummy); + static char dummy[] = ""; /* avoid const-cast */ + char *result = dummy; + if (TPS(stack_ptr) > 0) { + TPS(stack_ptr)--; + if (!TPS(stack)[TPS(stack_ptr)].num_type + && TPS(stack)[TPS(stack_ptr)].data.str != 0) + result = TPS(stack)[TPS(stack_ptr)].data.str; + } else { + DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); + _nc_tparm_err++; + } + return result; } -static inline const char *parse_format(const char *s, char *format, int *len) +static NCURSES_INLINE const char * +parse_format(const char *s, char *format, int *len) { + *len = 0; + if (format != 0) { bool done = FALSE; bool allowminus = FALSE; bool dot = FALSE; - int prec = 0; - int width = 0; + bool err = FALSE; + char *fmt = format; + int my_width = 0; + int my_prec = 0; + int value = 0; *len = 0; *format++ = '%'; while (*s != '\0' && !done) { - switch (*s) { - case 'c': /* FALLTHRU */ - case 'd': /* FALLTHRU */ - case 'o': /* FALLTHRU */ - case 'x': /* FALLTHRU */ - case 'X': /* FALLTHRU */ - case 's': - *format++ = *s; - done = TRUE; - break; - case '.': - *format++ = *s++; - dot = TRUE; - break; - case '#': - *format++ = *s++; - break; - case ' ': - *format++ = *s++; - break; - case ':': - s++; - allowminus = TRUE; - break; - case '-': - if (allowminus) { - *format++ = *s++; - } else { - done = TRUE; - } - break; - default: - if (isdigit(*s)) { - if (dot) - prec = (prec * 10) + (*s - '0'); - else - width = (width * 10) + (*s - '0'); - *format++ = *s++; - } else { - done = TRUE; - } + switch (*s) { + case 'c': /* FALLTHRU */ + case 'd': /* FALLTHRU */ + case 'o': /* FALLTHRU */ + case 'x': /* FALLTHRU */ + case 'X': /* FALLTHRU */ + case 's': + *format++ = *s; + done = TRUE; + break; + case '.': + *format++ = *s++; + if (dot) { + err = TRUE; + } else { /* value before '.' is the width */ + dot = TRUE; + my_width = value; } + value = 0; + break; + case '#': + *format++ = *s++; + break; + case ' ': + *format++ = *s++; + break; + case ':': + s++; + allowminus = TRUE; + break; + case '-': + if (allowminus) { + *format++ = *s++; + } else { + done = TRUE; + } + break; + default: + if (isdigit(UChar(*s))) { + value = (value * 10) + (*s - '0'); + if (value > 10000) + err = TRUE; + *format++ = *s++; + } else { + done = TRUE; + } + } + } + + /* + * If we found an error, ignore (and remove) the flags. + */ + if (err) { + my_width = my_prec = value = 0; + format = fmt; + *format++ = '%'; + *format++ = *s; } + + /* + * Any value after '.' is the precision. If we did not see '.', then + * the value is the width. + */ + if (dot) + my_prec = value; + else + my_width = value; + *format = '\0'; /* return maximum string length in print */ - *len = (prec > width) ? prec : width; - return s; + *len = (my_width > my_prec) ? my_width : my_prec; + } + return s; } #define isUPPER(c) ((c) >= 'A' && (c) <= 'Z') #define isLOWER(c) ((c) >= 'a' && (c) <= 'z') -static inline char *tparam_internal(const char *string, va_list ap) +/* + * Analyze the string to see how many parameters we need from the varargs list, + * and what their types are. We will only accept string parameters if they + * appear as a %l or %s format following an explicit parameter reference (e.g., + * %p2%s). All other parameters are numbers. + * + * 'number' counts coarsely the number of pop's we see in the string, and + * 'popcount' shows the highest parameter number in the string. We would like + * to simply use the latter count, but if we are reading termcap strings, there + * may be cases that we cannot see the explicit parameter numbers. + */ +NCURSES_EXPORT(int) +_nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) { -#define NUM_VARS 26 -int param[9]; -int popcount; -int number; -int len; -int level; -int x, y; -int i; -register const char *cp; -static size_t len_fmt; -static char *format; -static int dynamic_var[NUM_VARS]; -static int static_vars[NUM_VARS]; - - out_used = 0; - if (string == NULL) - return NULL; - - /* - * Find the highest parameter-number referred to in the format string. - * Use this value to limit the number of arguments copied from the - * variable-length argument list. - */ - for (cp = string, popcount = number = 0; *cp != '\0'; cp++) { - if (cp[0] == '%' && cp[1] != '\0') { - switch (cp[1]) { - case '%': - cp++; - break; - case 'i': - if (popcount < 2) - popcount = 2; - break; - case 'p': - cp++; - if (cp[1] >= '1' && cp[1] <= '9') { - int c = cp[1] - '0'; - if (c > popcount) - popcount = c; - } - break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case 'd': case 'c': case 's': - ++number; - break; - } + size_t len2; + int i; + int lastpop = -1; + int len; + int number = 0; + const char *cp = string; + static char dummy[] = ""; + + if (cp == 0) + return 0; + + if ((len2 = strlen(cp)) > TPS(fmt_size)) { + TPS(fmt_size) = len2 + TPS(fmt_size) + 2; + TPS(fmt_buff) = typeRealloc(char, TPS(fmt_size), TPS(fmt_buff)); + if (TPS(fmt_buff) == 0) + return 0; + } + + memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM); + *popcount = 0; + + while ((cp - string) < (int) len2) { + if (*cp == '%') { + cp++; + cp = parse_format(cp, TPS(fmt_buff), &len); + switch (*cp) { + default: + break; + + case 'd': /* FALLTHRU */ + case 'o': /* FALLTHRU */ + case 'x': /* FALLTHRU */ + case 'X': /* FALLTHRU */ + case 'c': /* FALLTHRU */ + if (lastpop <= 0) + number++; + lastpop = -1; + break; + + case 'l': + case 's': + if (lastpop > 0) + p_is_s[lastpop - 1] = dummy; + ++number; + break; + + case 'p': + cp++; + i = (UChar(*cp) - '0'); + if (i >= 0 && i <= NUM_PARM) { + lastpop = i; + if (lastpop > *popcount) + *popcount = lastpop; } + break; + + case 'P': + ++number; + ++cp; + break; + + case 'g': + cp++; + break; + + case S_QUOTE: + cp += 2; + lastpop = -1; + break; + + case L_BRACE: + cp++; + while (isdigit(UChar(*cp))) { + cp++; + } + break; + + case '+': + case '-': + case '*': + case '/': + case 'm': + case 'A': + case 'O': + case '&': + case '|': + case '^': + case '=': + case '<': + case '>': + lastpop = -1; + number += 2; + break; + + case '!': + case '~': + lastpop = -1; + ++number; + break; + + case 'i': + /* will add 1 to first (usually two) parameters */ + break; + } } - if ((size_t)(cp - string) > len_fmt) { - len_fmt = (cp - string) + len_fmt + 2; - if ((format = typeRealloc(char, len_fmt, format)) == 0) - return 0; - } + if (*cp != '\0') + cp++; + } - if (number > 9) number = 9; - for (i = 0; i < max(popcount, number); i++) { - /* - * FIXME: potential loss here if sizeof(int) != sizeof(char *). - * A few caps (such as plab_norm) have string-valued parms. - */ - param[i] = va_arg(ap, int); - } + if (number > NUM_PARM) + number = NUM_PARM; + return number; +} +static NCURSES_INLINE char * +tparam_internal(int use_TPARM_ARG, const char *string, va_list ap) +{ + char *p_is_s[NUM_PARM]; + TPARM_ARG param[NUM_PARM]; + int popcount = 0; + int number; + int num_args; + int len; + int level; + int x, y; + int i; + const char *cp = string; + size_t len2; + + if (cp == NULL) + return NULL; + + TPS(out_used) = 0; + len2 = strlen(cp); + + /* + * Find the highest parameter-number referred to in the format string. + * Use this value to limit the number of arguments copied from the + * variable-length argument list. + */ + number = _nc_tparm_analyze(cp, p_is_s, &popcount); + if (TPS(fmt_buff) == 0) + return NULL; + + if (number > NUM_PARM) + number = NUM_PARM; + if (popcount > NUM_PARM) + popcount = NUM_PARM; + num_args = max(popcount, number); + + for (i = 0; i < num_args; i++) { /* - * This is a termcap compatibility hack. If there are no explicit pop - * operations in the string, load the stack in such a way that - * successive pops will grab successive parameters. That will make - * the expansion of (for example) \E[%d;%dH work correctly in termcap - * style, which means tparam() will expand termcap strings OK. + * A few caps (such as plab_norm) have string-valued parms. + * We'll have to assume that the caller knows the difference, since + * a char* and an int may not be the same size on the stack. The + * normal prototype for this uses 9 long's, which is consistent with + * our va_arg() usage. */ - stack_ptr = 0; - if (popcount == 0) { - popcount = number; - for (i = number - 1; i >= 0; i--) - npush(param[i]); + if (p_is_s[i] != 0) { + p_is_s[i] = va_arg(ap, char *); + param[i] = 0; + } else if (use_TPARM_ARG) { + param[i] = va_arg(ap, TPARM_ARG); + } else { + param[i] = (TPARM_ARG) va_arg(ap, int); } - + } + + /* + * This is a termcap compatibility hack. If there are no explicit pop + * operations in the string, load the stack in such a way that + * successive pops will grab successive parameters. That will make + * the expansion of (for example) \E[%d;%dH work correctly in termcap + * style, which means tparam() will expand termcap strings OK. + */ + TPS(stack_ptr) = 0; + if (popcount == 0) { + popcount = number; + for (i = number - 1; i >= 0; i--) { + if (p_is_s[i]) + spush(p_is_s[i]); + else + npush((int) param[i]); + } + } #ifdef TRACE - if (_nc_tracing & TRACE_CALLS) { - for (i = 0; i < popcount; i++) - save_number(", %d", param[i], 0); - _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(string), out_buff); - out_used = 0; + if (USE_TRACEF(TRACE_CALLS)) { + for (i = 0; i < num_args; i++) { + if (p_is_s[i] != 0) + save_text(", %s", _nc_visbuf(p_is_s[i]), 0); + else + save_number(", %d", (int) param[i], 0); } + _tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(cp), TPS(out_buff)); + TPS(out_used) = 0; + _nc_unlock_global(tracef); + } #endif /* TRACE */ - while (*string) { - if (*string != '%') { - save_char(*string); - } else { - string++; - string = parse_format(string, format, &len); - switch (*string) { - default: - break; - case '%': - save_char('%'); - break; - - case 'd': /* FALLTHRU */ - case 'o': /* FALLTHRU */ - case 'x': /* FALLTHRU */ - case 'X': /* FALLTHRU */ - case 'c': - save_number(format, npop(), len); - break; - - case 'l': - save_number("%d", strlen(spop()), 0); - break; - - case 's': - save_text(format, spop(), len); - break; - - case 'p': - string++; - if (*string >= '1' && *string <= '9') - npush(param[*string - '1']); - break; - - case 'P': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); - static_vars[i] = npop(); - } else if (isLOWER(*string)) { - i = (*string - 'a'); - dynamic_var[i] = npop(); - } - break; - - case 'g': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); - npush(static_vars[i]); - } else if (isLOWER(*string)) { - i = (*string - 'a'); - npush(dynamic_var[i]); - } - break; - - case S_QUOTE: - string++; - npush(*string); - string++; - break; - - case L_BRACE: - number = 0; - string++; - while (*string >= '0' && *string <= '9') { - number = number * 10 + *string - '0'; - string++; - } - npush(number); - break; - - case '+': - npush(npop() + npop()); - break; - - case '-': - y = npop(); - x = npop(); - npush(x - y); - break; - - case '*': - npush(npop() * npop()); - break; - - case '/': - y = npop(); - x = npop(); - npush(y ? (x / y) : 0); - break; - - case 'm': - y = npop(); - x = npop(); - npush(y ? (x % y) : 0); - break; - - case 'A': - npush(npop() && npop()); - break; - - case 'O': - npush(npop() || npop()); - break; - - case '&': - npush(npop() & npop()); - break; - - case '|': - npush(npop() | npop()); - break; - - case '^': - npush(npop() ^ npop()); - break; - - case '=': - y = npop(); - x = npop(); - npush(x == y); - break; - - case '<': - y = npop(); - x = npop(); - npush(x < y); - break; - - case '>': - y = npop(); - x = npop(); - npush(x > y); + while ((cp - string) < (int) len2) { + if (*cp != '%') { + save_char(UChar(*cp)); + } else { + TPS(tparam_base) = cp++; + cp = parse_format(cp, TPS(fmt_buff), &len); + switch (*cp) { + default: + break; + case '%': + save_char('%'); + break; + + case 'd': /* FALLTHRU */ + case 'o': /* FALLTHRU */ + case 'x': /* FALLTHRU */ + case 'X': /* FALLTHRU */ + save_number(TPS(fmt_buff), npop(), len); + break; + + case 'c': /* FALLTHRU */ + save_char(npop()); + break; + + case 'l': + save_number("%d", (int) strlen(spop()), 0); + break; + + case 's': + save_text(TPS(fmt_buff), spop(), len); + break; + + case 'p': + cp++; + i = (UChar(*cp) - '1'); + if (i >= 0 && i < NUM_PARM) { + if (p_is_s[i]) + spush(p_is_s[i]); + else + npush((int) param[i]); + } + break; + + case 'P': + cp++; + if (isUPPER(*cp)) { + i = (UChar(*cp) - 'A'); + TPS(static_vars)[i] = npop(); + } else if (isLOWER(*cp)) { + i = (UChar(*cp) - 'a'); + TPS(dynamic_var)[i] = npop(); + } + break; + + case 'g': + cp++; + if (isUPPER(*cp)) { + i = (UChar(*cp) - 'A'); + npush(TPS(static_vars)[i]); + } else if (isLOWER(*cp)) { + i = (UChar(*cp) - 'a'); + npush(TPS(dynamic_var)[i]); + } + break; + + case S_QUOTE: + cp++; + npush(UChar(*cp)); + cp++; + break; + + case L_BRACE: + number = 0; + cp++; + while (isdigit(UChar(*cp))) { + number = (number * 10) + (UChar(*cp) - '0'); + cp++; + } + npush(number); + break; + + case '+': + npush(npop() + npop()); + break; + + case '-': + y = npop(); + x = npop(); + npush(x - y); + break; + + case '*': + npush(npop() * npop()); + break; + + case '/': + y = npop(); + x = npop(); + npush(y ? (x / y) : 0); + break; + + case 'm': + y = npop(); + x = npop(); + npush(y ? (x % y) : 0); + break; + + case 'A': + npush(npop() && npop()); + break; + + case 'O': + npush(npop() || npop()); + break; + + case '&': + npush(npop() & npop()); + break; + + case '|': + npush(npop() | npop()); + break; + + case '^': + npush(npop() ^ npop()); + break; + + case '=': + y = npop(); + x = npop(); + npush(x == y); + break; + + case '<': + y = npop(); + x = npop(); + npush(x < y); + break; + + case '>': + y = npop(); + x = npop(); + npush(x > y); + break; + + case '!': + npush(!npop()); + break; + + case '~': + npush(~npop()); + break; + + case 'i': + if (p_is_s[0] == 0) + param[0]++; + if (p_is_s[1] == 0) + param[1]++; + break; + + case '?': + break; + + case 't': + x = npop(); + if (!x) { + /* scan forward for %e or %; at level zero */ + cp++; + level = 0; + while (*cp) { + if (*cp == '%') { + cp++; + if (*cp == '?') + level++; + else if (*cp == ';') { + if (level > 0) + level--; + else + break; + } else if (*cp == 'e' && level == 0) break; + } - case '!': - npush(! npop()); + if (*cp) + cp++; + } + } + break; + + case 'e': + /* scan forward for a %; at level zero */ + cp++; + level = 0; + while (*cp) { + if (*cp == '%') { + cp++; + if (*cp == '?') + level++; + else if (*cp == ';') { + if (level > 0) + level--; + else break; + } + } - case '~': - npush(~ npop()); - break; + if (*cp) + cp++; + } + break; - case 'i': - param[0]++; - param[1]++; - break; + case ';': + break; - case '?': - break; + } /* endswitch (*cp) */ + } /* endelse (*cp == '%') */ - case 't': - x = npop(); - if (!x) { - /* scan forward for %e or %; at level zero */ - string++; - level = 0; - while (*string) { - if (*string == '%') { - string++; - if (*string == '?') - level++; - else if (*string == ';') { - if (level > 0) - level--; - else - break; - } - else if (*string == 'e' && level == 0) - break; - } - - if (*string) - string++; - } - } - break; + if (*cp == '\0') + break; - case 'e': - /* scan forward for a %; at level zero */ - string++; - level = 0; - while (*string) { - if (*string == '%') { - string++; - if (*string == '?') - level++; - else if (*string == ';') { - if (level > 0) - level--; - else - break; - } - } - - if (*string) - string++; - } - break; + cp++; + } /* endwhile (*cp) */ - case ';': - break; + get_space((size_t) 1); + TPS(out_buff)[TPS(out_used)] = '\0'; - } /* endswitch (*string) */ - } /* endelse (*string == '%') */ + T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff)))); + return (TPS(out_buff)); +} - if (*string == '\0') - break; +#if NCURSES_TPARM_VARARGS +#define tparm_varargs tparm +#else +#define tparm_proto tparm +#endif - string++; - } /* endwhile (*string) */ +NCURSES_EXPORT(char *) +tparm_varargs(NCURSES_CONST char *string,...) +{ + va_list ap; + char *result; - if (out_buff == 0 && (out_buff = typeCalloc(char,1)) == NULL) - return(NULL); - out_buff[out_used] = '\0'; + _nc_tparm_err = 0; + va_start(ap, string); +#ifdef TRACE + TPS(tname) = "tparm"; +#endif /* TRACE */ + result = tparam_internal(TRUE, string, ap); + va_end(ap); + return result; +} - T((T_RETURN("%s"), _nc_visbuf(out_buff))); - return(out_buff); +#if !NCURSES_TPARM_VARARGS +NCURSES_EXPORT(char *) +tparm_proto(NCURSES_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) +{ + return tparm_varargs(string, a1, a2, a3, a4, a5, a6, a7, a8, a9); } +#endif /* NCURSES_TPARM_VARARGS */ -char *tparm(NCURSES_CONST char *string, ...) +NCURSES_EXPORT(char *) +tiparm(const char *string,...) { -va_list ap; -char *result; + va_list ap; + char *result; - va_start(ap, string); + _nc_tparm_err = 0; + va_start(ap, string); #ifdef TRACE - tname = "tparm"; + TPS(tname) = "tiparm"; #endif /* TRACE */ - result = tparam_internal(string, ap); - va_end(ap); - return result; + result = tparam_internal(FALSE, string, ap); + va_end(ap); + return result; }