diff options
Diffstat (limited to 'contrib/ncurses/ncurses/tinfo/lib_tparm.c')
-rw-r--r-- | contrib/ncurses/ncurses/tinfo/lib_tparm.c | 477 |
1 files changed, 267 insertions, 210 deletions
diff --git a/contrib/ncurses/ncurses/tinfo/lib_tparm.c b/contrib/ncurses/ncurses/tinfo/lib_tparm.c index 931669e..cba31d9 100644 --- a/contrib/ncurses/ncurses/tinfo/lib_tparm.c +++ b/contrib/ncurses/ncurses/tinfo/lib_tparm.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998,2000,2001 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2006 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,6 +29,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey, 1996 on * ****************************************************************************/ /* @@ -42,7 +43,7 @@ #include <term.h> #include <tic.h> -MODULE_ID("$Id: lib_tparm.c,v 1.53 2001/06/02 22:53:59 tom Exp $") +MODULE_ID("$Id: lib_tparm.c,v 1.71 2006/11/26 01:12:56 tom Exp $") /* * char * @@ -108,7 +109,7 @@ MODULE_ID("$Id: lib_tparm.c,v 1.53 2001/06/02 22:53:59 tom Exp $") typedef struct { union { - unsigned int num; + int num; char *str; } data; bool num_type; @@ -128,6 +129,9 @@ static char *out_buff; static size_t out_size; static size_t out_used; +static char *fmt_buff; +static size_t fmt_size; + #if NO_LEAKS NCURSES_EXPORT(void) _nc_free_tparm(void) @@ -136,28 +140,25 @@ _nc_free_tparm(void) FreeAndNull(out_buff); out_size = 0; out_used = 0; + FreeAndNull(fmt_buff); + fmt_size = 0; } } #endif -static void -really_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"); -} - -static inline void +static NCURSES_INLINE void get_space(size_t need) { need += out_used; - if (need > out_size) - really_get_space(need); + 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); + } } -static inline void +static NCURSES_INLINE void save_text(const char *fmt, const char *s, int len) { size_t s_len = strlen(s); @@ -170,19 +171,19 @@ save_text(const char *fmt, const char *s, int len) out_used += strlen(out_buff + 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(len + 1); + get_space((unsigned) len + 1); (void) sprintf(out_buff + out_used, fmt, number); out_used += strlen(out_buff + out_used); } -static inline void +static NCURSES_INLINE void save_char(int c) { if (c == 0) @@ -191,7 +192,7 @@ save_char(int c) out_buff[out_used++] = c; } -static inline void +static NCURSES_INLINE void npush(int x) { if (stack_ptr < STACKSIZE) { @@ -204,7 +205,7 @@ npush(int x) } } -static inline int +static NCURSES_INLINE int npop(void) { int result = 0; @@ -219,7 +220,7 @@ npop(void) return result; } -static inline void +static NCURSES_INLINE void spush(char *x) { if (stack_ptr < STACKSIZE) { @@ -232,7 +233,7 @@ spush(char *x) } } -static inline char * +static NCURSES_INLINE char * spop(void) { static char dummy[] = ""; /* avoid const-cast */ @@ -248,152 +249,139 @@ spop(void) 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 prec = 0; - int width = 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 { - dot = TRUE; - prec = 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) { - prec = width = value = 0; - format = fmt; - *format++ = '%'; - *format++ = *s; - } - if (dot) - width = value; - else - prec = value; + /* + * If we found an error, ignore (and remove) the flags. + */ + if (err) { + my_width = my_prec = value = 0; + format = fmt; + *format++ = '%'; + *format++ = *s; + } - *format = '\0'; - /* return maximum string length in print */ - *len = (prec > width) ? prec : width; + /* + * 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]; - int 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) + if ((len2 = strlen(cp)) > fmt_size) { + fmt_size = len2 + fmt_size + 2; + if ((fmt_buff = typeRealloc(char, fmt_size, 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, fmt_buff, &len); switch (*cp) { default: break; @@ -403,7 +391,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,15 +405,19 @@ 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; case 'P': + ++number; + ++cp; + break; + case 'g': cp++; break; @@ -436,7 +429,7 @@ tparam_internal(const char *string, va_list ap) case L_BRACE: cp++; - while (*cp >= '0' && *cp <= '9') { + while (isdigit(UChar(*cp))) { cp++; } break; @@ -454,16 +447,18 @@ tparam_internal(const char *string, va_list ap) case '=': case '<': case '>': + lastpop = -1; + number += 2; + break; + case '!': case '~': lastpop = -1; - number += 2; + ++number; break; case 'i': - lastpop = -1; - if (popcount < 2) - popcount = 2; + /* will add 1 to first (usually two) parameters */ break; } } @@ -471,18 +466,55 @@ 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) +{ +#define NUM_VARS 26 + 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; + static int dynamic_var[NUM_VARS]; + static int static_vars[NUM_VARS]; + + if (cp == NULL) + return NULL; + + 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 (fmt_buff == 0) + return NULL; + for (i = 0; i < max(popcount, number); i++) { /* * 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. + * 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. */ if (p_is_s[i] != 0) { p_is_s[i] = va_arg(ap, char *); } else { - param[i] = va_arg(ap, int); + param[i] = va_arg(ap, TPARM_ARG); } } @@ -507,18 +539,18 @@ tparam_internal(const char *string, va_list ap) else save_number(", %d", param[i], 0); } - _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(string), out_buff); + _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(cp), out_buff); out_used = 0; } #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) { + tparam_base = cp++; + cp = parse_format(cp, fmt_buff, &len); + switch (*cp) { default: break; case '%': @@ -529,22 +561,25 @@ tparam_internal(const char *string, va_list ap) case 'o': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ + save_number(fmt_buff, npop(), len); + break; + case 'c': /* FALLTHRU */ - save_number(format, npop(), len); + save_char(npop()); break; case 'l': - save_number("%d", strlen(spop()), 0); + save_number("%d", (int) strlen(spop()), 0); break; case 's': - save_text(format, spop(), len); + save_text(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 @@ -553,39 +588,39 @@ tparam_internal(const char *string, va_list ap) break; case 'P': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); + cp++; + if (isUPPER(*cp)) { + i = (UChar(*cp) - 'A'); static_vars[i] = npop(); - } else if (isLOWER(*string)) { - i = (*string - 'a'); + } else if (isLOWER(*cp)) { + i = (UChar(*cp) - 'a'); dynamic_var[i] = npop(); } break; case 'g': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); + cp++; + if (isUPPER(*cp)) { + i = (UChar(*cp) - 'A'); npush(static_vars[i]); - } else if (isLOWER(*string)) { - i = (*string - 'a'); + } else if (isLOWER(*cp)) { + i = (UChar(*cp) - 'a'); npush(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; @@ -676,38 +711,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 @@ -715,22 +750,22 @@ 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'; @@ -739,9 +774,14 @@ tparam_internal(const char *string, va_list ap) return (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; @@ -755,3 +795,20 @@ tparm 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 */ |