X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Flib_tparm.c;h=53a36092723aec2dc1b6ef48197946cfc1c6c427;hp=041667b4f7c3c5814b9934a62f75dfcbe4b9e56d;hb=f344f8539c1543f8cd65a5bb142dbaf23b9421d2;hpb=a8987e73ec254703634802b4f7ee30d3a485524d diff --git a/ncurses/tinfo/lib_tparm.c b/ncurses/tinfo/lib_tparm.c index 041667b4..53a36092 100644 --- a/ncurses/tinfo/lib_tparm.c +++ b/ncurses/tinfo/lib_tparm.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright (c) 1998-2015,2016 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 * @@ -40,10 +40,9 @@ #include #include -#include #include -MODULE_ID("$Id: lib_tparm.c,v 1.68 2004/02/07 20:52:51 tom Exp $") +MODULE_ID("$Id: lib_tparm.c,v 1.95 2016/05/28 23:22:52 tom Exp $") /* * char * @@ -54,7 +53,7 @@ MODULE_ID("$Id: lib_tparm.c,v 1.68 2004/02/07 20:52:51 tom Exp $") * * Cursor addressing and other strings requiring parame- * ters in the terminal are described by a parameterized string - * capability, with like escapes %x in it. For example, to + * capability, with escapes like %x in it. For example, to * address the cursor, the cup capability is given, using two * parameters: the row and column to address to. (Rows and * columns are numbered from zero and refer to the physical @@ -105,151 +104,132 @@ MODULE_ID("$Id: lib_tparm.c,v 1.68 2004/02/07 20:52:51 tom Exp $") * resulting in x mod y, not the reverse. */ -#define STACKSIZE 20 - -typedef struct { - union { - int num; - char *str; - } data; - bool num_type; -} stack_frame; - NCURSES_EXPORT_VAR(int) _nc_tparm_err = 0; -static stack_frame stack[STACKSIZE]; -static int stack_ptr; -static const char *tparam_base = ""; - -#ifdef TRACE -static const char *tname; -#endif /* TRACE */ - -static char *out_buff; -static size_t out_size; -static size_t out_used; - -static char *fmt_buff; -static size_t fmt_size; +#define TPS(var) _nc_prescreen.tparm_state.var +#define popcount _nc_popcount /* workaround for NetBSD 6.0 defect */ #if NO_LEAKS NCURSES_EXPORT(void) _nc_free_tparm(void) { - if (out_buff != 0) { - FreeAndNull(out_buff); - out_size = 0; - out_used = 0; - FreeAndNull(fmt_buff); - fmt_size = 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 inline void +static NCURSES_INLINE void get_space(size_t need) { - need += out_used; - if (need > out_size) { - out_size = need * 2; - out_buff = typeRealloc(char, out_size, out_buff); - if (out_buff == 0) - _nc_err_abort(MSG_NO_MEMORY); + need += TPS(out_used); + if (need > TPS(out_size)) { + TPS(out_size) = need * 2; + TYPE_REALLOC(char, TPS(out_size), TPS(out_buff)); } } -static inline void +static NCURSES_INLINE void save_text(const char *fmt, const char *s, int len) { size_t s_len = strlen(s); if (len > (int) s_len) - s_len = len; + s_len = (size_t) len; get_space(s_len + 1); - (void) sprintf(out_buff + out_used, fmt, s); - out_used += strlen(out_buff + out_used); + _nc_SPRINTF(TPS(out_buff) + TPS(out_used), + _nc_SLIMIT(TPS(out_size) - TPS(out_used)) + fmt, s); + TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); } -static inline void +static NCURSES_INLINE void save_number(const char *fmt, int number, int len) { if (len < 30) len = 30; /* actually log10(MAX_INT)+1 */ - get_space((unsigned) len + 1); + get_space((size_t) len + 1); - (void) sprintf(out_buff + out_used, fmt, number); - out_used += strlen(out_buff + out_used); + _nc_SPRINTF(TPS(out_buff) + TPS(out_used), + _nc_SLIMIT(TPS(out_size) - TPS(out_used)) + fmt, number); + TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); } -static inline void +static NCURSES_INLINE void save_char(int c) { if (c == 0) c = 0200; - get_space(1); - out_buff[out_used++] = c; + get_space((size_t) 1); + TPS(out_buff)[TPS(out_used)++] = (char) c; } -static inline void +static NCURSES_INLINE void npush(int x) { - if (stack_ptr < STACKSIZE) { - stack[stack_ptr].num_type = TRUE; - stack[stack_ptr].data.num = x; - stack_ptr++; + 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(tparam_base))); + DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); _nc_tparm_err++; } } -static inline int +static NCURSES_INLINE int npop(void) { int result = 0; - if (stack_ptr > 0) { - stack_ptr--; - if (stack[stack_ptr].num_type) - result = stack[stack_ptr].data.num; + 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(tparam_base))); + DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); _nc_tparm_err++; } return result; } -static inline void +static NCURSES_INLINE void spush(char *x) { - if (stack_ptr < STACKSIZE) { - stack[stack_ptr].num_type = FALSE; - stack[stack_ptr].data.str = x; - stack_ptr++; + 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(tparam_base))); + DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); _nc_tparm_err++; } } -static inline char * +static NCURSES_INLINE char * spop(void) { static char dummy[] = ""; /* avoid const-cast */ char *result = dummy; - if (stack_ptr > 0) { - stack_ptr--; - if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0) - result = stack[stack_ptr].data.str; + 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(tparam_base))); + DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); _nc_tparm_err++; } return result; } -static inline const char * +static NCURSES_INLINE const char * parse_format(const char *s, char *format, int *len) { *len = 0; @@ -273,6 +253,9 @@ parse_format(const char *s, char *format, int *len) case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 's': +#ifdef EXP_XTERM_1005 + case 'u': +#endif *format++ = *s; done = TRUE; break; @@ -369,10 +352,11 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) if (cp == 0) return 0; - if ((len2 = strlen(cp)) > fmt_size) { - fmt_size = len2 + fmt_size + 2; - if ((fmt_buff = typeRealloc(char, fmt_size, fmt_buff)) == 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); @@ -381,7 +365,7 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) while ((cp - string) < (int) len2) { if (*cp == '%') { cp++; - cp = parse_format(cp, fmt_buff, &len); + cp = parse_format(cp, TPS(fmt_buff), &len); switch (*cp) { default: break; @@ -391,6 +375,9 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 'c': /* FALLTHRU */ +#ifdef EXP_XTERM_1005 + case 'u': +#endif if (lastpop <= 0) number++; lastpop = -1; @@ -471,27 +458,27 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) return number; } -static inline char * -tparam_internal(const char *string, va_list ap) +static NCURSES_INLINE char * +tparam_internal(int use_TPARM_ARG, const char *string, va_list ap) { -#define NUM_VARS 26 char *p_is_s[NUM_PARM]; - long param[NUM_PARM]; - int popcount; + 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; - static int dynamic_var[NUM_VARS]; - static int static_vars[NUM_VARS]; + bool termcap_hack; + bool incremented_two; if (cp == NULL) return NULL; - out_used = 0; + TPS(out_used) = 0; len2 = strlen(cp); /* @@ -500,10 +487,18 @@ tparam_internal(const char *string, va_list ap) * variable-length argument list. */ number = _nc_tparm_analyze(cp, p_is_s, &popcount); - if (fmt_buff == 0) + if (TPS(fmt_buff) == 0) return NULL; - for (i = 0; i < max(popcount, number); i++) { + incremented_two = FALSE; + + 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++) { /* * A few caps (such as plab_norm) have string-valued parms. * We'll have to assume that the caller knows the difference, since @@ -513,8 +508,11 @@ tparam_internal(const char *string, va_list ap) */ 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] = va_arg(ap, long int); + param[i] = (TPARM_ARG) va_arg(ap, int); } } @@ -525,22 +523,28 @@ tparam_internal(const char *string, va_list ap) * the expansion of (for example) \E[%d;%dH work correctly in termcap * style, which means tparam() will expand termcap strings OK. */ - stack_ptr = 0; + TPS(stack_ptr) = 0; + termcap_hack = FALSE; if (popcount == 0) { - popcount = number; - for (i = number - 1; i >= 0; i--) - npush(param[i]); + termcap_hack = TRUE; + 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++) { + 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", param[i], 0); + save_number(", %d", (int) param[i], 0); } - _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(cp), out_buff); - out_used = 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 */ @@ -548,8 +552,8 @@ tparam_internal(const char *string, va_list ap) if (*cp != '%') { save_char(UChar(*cp)); } else { - tparam_base = cp++; - cp = parse_format(cp, fmt_buff, &len); + TPS(tparam_base) = cp++; + cp = parse_format(cp, TPS(fmt_buff), &len); switch (*cp) { default: break; @@ -561,29 +565,44 @@ tparam_internal(const char *string, va_list ap) case 'o': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ - save_number(fmt_buff, npop(), len); + save_number(TPS(fmt_buff), npop(), len); break; case 'c': /* FALLTHRU */ save_char(npop()); break; +#ifdef EXP_XTERM_1005 + case 'u': + { + unsigned char target[10]; + unsigned source = (unsigned) npop(); + int rc = _nc_conv_to_utf8(target, source, (unsigned) + sizeof(target)); + int n; + for (n = 0; n < rc; ++n) { + save_char(target[n]); + } + } + break; +#endif case 'l': - save_number("%d", (int) strlen(spop()), 0); + npush((int) strlen(spop())); break; case 's': - save_text(fmt_buff, spop(), len); + 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]) + if (p_is_s[i]) { spush(p_is_s[i]); - else - npush(param[i]); + } else { + npush((int) param[i]); + } } break; @@ -591,10 +610,10 @@ tparam_internal(const char *string, va_list ap) cp++; if (isUPPER(*cp)) { i = (UChar(*cp) - 'A'); - static_vars[i] = npop(); + TPS(static_vars)[i] = npop(); } else if (isLOWER(*cp)) { i = (UChar(*cp) - 'a'); - dynamic_var[i] = npop(); + TPS(dynamic_var)[i] = npop(); } break; @@ -602,10 +621,10 @@ tparam_internal(const char *string, va_list ap) cp++; if (isUPPER(*cp)) { i = (UChar(*cp) - 'A'); - npush(static_vars[i]); + npush(TPS(static_vars)[i]); } else if (isLOWER(*cp)) { i = (UChar(*cp) - 'a'); - npush(dynamic_var[i]); + npush(TPS(dynamic_var)[i]); } break; @@ -652,11 +671,15 @@ tparam_internal(const char *string, va_list ap) break; case 'A': - npush(npop() && npop()); + y = npop(); + x = npop(); + npush(y && x); break; case 'O': - npush(npop() || npop()); + y = npop(); + x = npop(); + npush(y || x); break; case '&': @@ -698,10 +721,26 @@ tparam_internal(const char *string, va_list ap) break; case 'i': - if (p_is_s[0] == 0) - param[0]++; - if (p_is_s[1] == 0) - param[1]++; + /* + * Increment the first two parameters -- if they are numbers + * rather than strings. As a side effect, assign into the + * stack; if this is termcap, then the stack was populated + * using the termcap hack above rather than via the terminfo + * 'p' case. + */ + if (!incremented_two) { + incremented_two = TRUE; + if (p_is_s[0] == 0) { + param[0]++; + if (termcap_hack) + TPS(stack)[0].data.num = (int) param[0]; + } + if (p_is_s[1] == 0) { + param[1]++; + if (termcap_hack) + TPS(stack)[1].data.num = (int) param[1]; + } + } break; case '?': @@ -767,15 +806,54 @@ tparam_internal(const char *string, va_list ap) cp++; } /* endwhile (*cp) */ - get_space(1); - out_buff[out_used] = '\0'; + get_space((size_t) 1); + TPS(out_buff)[TPS(out_used)] = '\0'; + + T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff)))); + return (TPS(out_buff)); +} + +#if NCURSES_TPARM_VARARGS +#define tparm_varargs tparm +#else +#define tparm_proto tparm +#endif - T((T_RETURN("%s"), _nc_visbuf(out_buff))); - return (out_buff); +NCURSES_EXPORT(char *) +tparm_varargs(NCURSES_CONST char *string,...) +{ + va_list ap; + char *result; + + _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; +} + +#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 */ NCURSES_EXPORT(char *) -tparm(NCURSES_CONST char *string,...) +tiparm(const char *string,...) { va_list ap; char *result; @@ -783,9 +861,9 @@ tparm(NCURSES_CONST char *string,...) _nc_tparm_err = 0; va_start(ap, string); #ifdef TRACE - tname = "tparm"; + TPS(tname) = "tiparm"; #endif /* TRACE */ - result = tparam_internal(string, ap); + result = tparam_internal(FALSE, string, ap); va_end(ap); return result; }