X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Flib_tparm.c;h=dce6973af02dc365510473243fbb064ca02934dc;hp=6df1e2d085722d3a1bc7222aab7fffb89011d3e0;hb=8f527f87c0b979d9c2598ef5c3394463af288468;hpb=46722468f47c2b77b3987729b4bcf2321cccfd01 diff --git a/ncurses/tinfo/lib_tparm.c b/ncurses/tinfo/lib_tparm.c index 6df1e2d0..dce6973a 100644 --- a/ncurses/tinfo/lib_tparm.c +++ b/ncurses/tinfo/lib_tparm.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2001,2002 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 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 * @@ -43,7 +43,7 @@ #include #include -MODULE_ID("$Id: lib_tparm.c,v 1.62 2002/10/05 19:33:24 Frank.Henigman Exp $") +MODULE_ID("$Id: lib_tparm.c,v 1.75 2008/08/03 22:37:22 tom Exp $") /* * char * @@ -105,55 +105,37 @@ MODULE_ID("$Id: lib_tparm.c,v 1.62 2002/10/05 19:33:24 Frank.Henigman 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; +#define TPS(var) _nc_prescreen.tparm_state.var #if NO_LEAKS 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 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) + 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 +static NCURSES_INLINE void save_text(const char *fmt, const char *s, int len) { size_t s_len = strlen(s); @@ -162,11 +144,11 @@ save_text(const char *fmt, const char *s, int len) get_space(s_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, 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) @@ -174,226 +156,211 @@ save_number(const char *fmt, int number, int len) get_space((unsigned) len + 1); - (void) sprintf(out_buff + out_used, fmt, number); - 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 +static NCURSES_INLINE void save_char(int c) { if (c == 0) c = 0200; get_space(1); - out_buff[out_used++] = c; + TPS(out_buff)[TPS(out_used)++] = 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) { - bool done = FALSE; - bool allowminus = FALSE; - bool dot = FALSE; - 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++; - 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 { + if (format != 0) { + bool done = FALSE; + bool allowminus = FALSE; + bool dot = FALSE; + 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; - default: - if (isdigit(UChar(*s))) { - value = (value * 10) + (*s - '0'); - if (value > 10000) + 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++; - } else { - done = TRUE; + 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; - } + /* + * 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 = (my_width > my_prec) ? my_width : my_prec; + /* + * 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 = (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 - char *p_is_s[9]; - long param[9]; - int lastpop; - int popcount; - int number; - int len; - int level; - int x, y; - int i; size_t len2; - register const char *cp; - static size_t len_fmt; + int i; + int lastpop = -1; + int len; + int number = 0; + const char *cp = string; static char dummy[] = ""; - static char *format; - static int dynamic_var[NUM_VARS]; - static int static_vars[NUM_VARS]; - out_used = 0; - if (string == NULL) - return NULL; + if (cp == 0) + return 0; - if ((len2 = strlen(string)) > len_fmt) { - len_fmt = len2 + len_fmt + 2; - if ((format = typeRealloc(char, len_fmt, format)) == 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; } - /* - * 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 = 0; - lastpop = -1; - popcount = 0; - memset(p_is_s, 0, sizeof(p_is_s)); + memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM); + *popcount = 0; - /* - * 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. - */ - for (cp = string; (cp - string) < (int) len2;) { + while ((cp - string) < (int) len2) { if (*cp == '%') { cp++; - cp = parse_format(cp, format, &len); + cp = parse_format(cp, TPS(fmt_buff), &len); switch (*cp) { default: break; @@ -403,7 +370,8 @@ tparam_internal(const char *string, va_list ap) case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 'c': /* FALLTHRU */ - number++; + if (lastpop <= 0) + number++; lastpop = -1; break; @@ -416,11 +384,11 @@ tparam_internal(const char *string, va_list ap) case 'p': cp++; - i = (*cp - '0'); - if (i >= 0 && i <= 9) { + i = (UChar(*cp) - '0'); + if (i >= 0 && i <= NUM_PARM) { lastpop = i; - if (lastpop > popcount) - popcount = lastpop; + if (lastpop > *popcount) + *popcount = lastpop; } break; @@ -440,7 +408,7 @@ tparam_internal(const char *string, va_list ap) case L_BRACE: cp++; - while (*cp >= '0' && *cp <= '9') { + while (isdigit(UChar(*cp))) { cp++; } break; @@ -469,9 +437,7 @@ tparam_internal(const char *string, va_list ap) break; case 'i': - lastpop = -1; - if (popcount < 2) - popcount = 2; + /* will add 1 to first (usually two) parameters */ break; } } @@ -479,8 +445,40 @@ tparam_internal(const char *string, va_list ap) cp++; } - if (number > 9) - number = 9; + if (number > NUM_PARM) + number = NUM_PARM; + return number; +} + +static NCURSES_INLINE char * +tparam_internal(const char *string, va_list ap) +{ + char *p_is_s[NUM_PARM]; + TPARM_ARG param[NUM_PARM]; + int popcount; + int number; + 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; + for (i = 0; i < max(popcount, number); i++) { /* * A few caps (such as plab_norm) have string-valued parms. @@ -492,7 +490,7 @@ tparam_internal(const char *string, va_list ap) if (p_is_s[i] != 0) { p_is_s[i] = va_arg(ap, char *); } else { - param[i] = va_arg(ap, long int); + param[i] = va_arg(ap, TPARM_ARG); } } @@ -503,32 +501,37 @@ 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; if (popcount == 0) { popcount = number; - for (i = number - 1; i >= 0; i--) - npush(param[i]); + for (i = number - 1; i >= 0; i--) { + if (p_is_s[i]) + spush(p_is_s[i]); + else + npush(param[i]); + } } #ifdef TRACE - if (_nc_tracing & TRACE_CALLS) { + if (USE_TRACEF(TRACE_CALLS)) { for (i = 0; i < popcount; i++) { if (p_is_s[i] != 0) save_text(", %s", _nc_visbuf(p_is_s[i]), 0); else save_number(", %d", param[i], 0); } - _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(string), 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 */ - while (*string) { - if (*string != '%') { - save_char(*string); + while ((cp - string) < (int) len2) { + if (*cp != '%') { + save_char(UChar(*cp)); } else { - tparam_base = string++; - string = parse_format(string, format, &len); - switch (*string) { + TPS(tparam_base) = cp++; + cp = parse_format(cp, TPS(fmt_buff), &len); + switch (*cp) { default: break; case '%': @@ -539,7 +542,7 @@ tparam_internal(const char *string, va_list ap) case 'o': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ - save_number(format, npop(), len); + save_number(TPS(fmt_buff), npop(), len); break; case 'c': /* FALLTHRU */ @@ -551,13 +554,13 @@ tparam_internal(const char *string, va_list ap) break; case 's': - save_text(format, spop(), len); + save_text(TPS(fmt_buff), spop(), len); break; case 'p': - string++; - i = (*string - '1'); - if (i >= 0 && i < 9) { + cp++; + i = (UChar(*cp) - '1'); + if (i >= 0 && i < NUM_PARM) { if (p_is_s[i]) spush(p_is_s[i]); else @@ -566,39 +569,39 @@ tparam_internal(const char *string, va_list ap) 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(); + 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': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); - npush(static_vars[i]); - } else if (isLOWER(*string)) { - i = (*string - 'a'); - npush(dynamic_var[i]); + 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: - string++; - npush(*string); - string++; + cp++; + npush(UChar(*cp)); + cp++; break; case L_BRACE: number = 0; - string++; - while (*string >= '0' && *string <= '9') { - number = number * 10 + *string - '0'; - string++; + cp++; + while (isdigit(UChar(*cp))) { + number = (number * 10) + (UChar(*cp) - '0'); + cp++; } npush(number); break; @@ -689,38 +692,38 @@ tparam_internal(const char *string, va_list ap) x = npop(); if (!x) { /* scan forward for %e or %; at level zero */ - string++; + cp++; level = 0; - while (*string) { - if (*string == '%') { - string++; - if (*string == '?') + while (*cp) { + if (*cp == '%') { + cp++; + if (*cp == '?') level++; - else if (*string == ';') { + else if (*cp == ';') { if (level > 0) level--; else break; - } else if (*string == 'e' && level == 0) + } else if (*cp == 'e' && level == 0) break; } - if (*string) - string++; + if (*cp) + cp++; } } break; case 'e': /* scan forward for a %; at level zero */ - string++; + cp++; level = 0; - while (*string) { - if (*string == '%') { - string++; - if (*string == '?') + while (*cp) { + if (*cp == '%') { + cp++; + if (*cp == '?') level++; - else if (*string == ';') { + else if (*cp == ';') { if (level > 0) level--; else @@ -728,32 +731,38 @@ tparam_internal(const char *string, va_list ap) } } - if (*string) - string++; + if (*cp) + cp++; } break; case ';': break; - } /* endswitch (*string) */ - } /* endelse (*string == '%') */ + } /* endswitch (*cp) */ + } /* endelse (*cp == '%') */ - if (*string == '\0') + if (*cp == '\0') break; - string++; - } /* endwhile (*string) */ + cp++; + } /* endwhile (*cp) */ get_space(1); - out_buff[out_used] = '\0'; + TPS(out_buff)[TPS(out_used)] = '\0'; - T((T_RETURN("%s"), _nc_visbuf(out_buff))); - return (out_buff); + 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 + NCURSES_EXPORT(char *) -tparm(NCURSES_CONST char *string,...) +tparm_varargs(NCURSES_CONST char *string,...) { va_list ap; char *result; @@ -761,9 +770,26 @@ tparm(NCURSES_CONST char *string,...) _nc_tparm_err = 0; va_start(ap, string); #ifdef TRACE - tname = "tparm"; + TPS(tname) = "tparm"; #endif /* TRACE */ result = tparam_internal(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 */