X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fcaptoinfo.c;h=dd02d902dc5261a67c4849508d8c15c07ec22b68;hp=d0881ecd47921728fa1aaf8435a4fd80212c7af5;hb=ee27d238caeccd1ed781a92957afbdb890e1e88f;hpb=0eb88fc5281804773e2a0c7a488a4452463535ce diff --git a/ncurses/tinfo/captoinfo.c b/ncurses/tinfo/captoinfo.c index d0881ecd..dd02d902 100644 --- a/ncurses/tinfo/captoinfo.c +++ b/ncurses/tinfo/captoinfo.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998 Free Software Foundation, Inc. * + * Copyright (c) 1998-2012,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 * @@ -29,10 +29,9 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ - - /* * captoinfo.c --- conversion between termcap and terminfo formats * @@ -41,7 +40,7 @@ * * There is just one entry point: * - * char *captoinfo(n, s, parametrized) + * char *_nc_captoinfo(n, s, parameterized) * * Convert value s for termcap string capability named n into terminfo * format. @@ -94,10 +93,9 @@ #include #include -MODULE_ID("$Id: captoinfo.c,v 1.24 1999/07/24 20:06:13 tom Exp $") +MODULE_ID("$Id: captoinfo.c,v 1.78 2016/05/28 23:22:52 tom Exp $") #define MAX_PUSHED 16 /* max # args we can push onto the stack */ -#define MAX_ENTRY 2048 /* maximum chars in a translated capability */ static int stack[MAX_PUSHED]; /* the stack */ static int stackptr; /* the next empty place on the stack */ @@ -108,52 +106,55 @@ static int seenr; /* seen a %r */ static int param; /* current parameter */ static char *dp; /* pointer to end of the converted string */ -static char *my_string; +static char *my_string; static size_t my_length; -static char *init_string(void) +static char * +init_string(void) /* initialize 'my_string', 'my_length' */ { - if (my_string == 0) - my_string = typeMalloc(char, my_length = 256); - if (my_string == 0) - _nc_err_abort("Out of memory"); + if (my_string == 0) + TYPE_MALLOC(char, my_length = 256, my_string); - *my_string = '\0'; - return my_string; + *my_string = '\0'; + return my_string; } -static char *save_string(char *d, const char *const s) +static char * +save_string(char *d, const char *const s) { - size_t have = (d - my_string); - size_t need = have + strlen(s) + 2; - if (need > my_length) { - my_string = (char *)realloc(my_string, my_length = (need + need)); - if (my_string == 0) - _nc_err_abort("Out of memory"); - d = my_string + have; - } - (void) strcpy(d, s); - return d + strlen(d); + size_t have = (size_t) (d - my_string); + size_t need = have + strlen(s) + 2; + if (need > my_length) { + my_string = (char *) _nc_doalloc(my_string, my_length = (need + need)); + if (my_string == 0) + _nc_err_abort(MSG_NO_MEMORY); + d = my_string + have; + } + _nc_STRCPY(d, s, my_length - have); + return d + strlen(d); } -static inline char *save_char(char *s, char c) +static NCURSES_INLINE char * +save_char(char *s, int c) { - static char temp[2]; - temp[0] = c; - return save_string(s, temp); + static char temp[2]; + temp[0] = (char) c; + return save_string(s, temp); } -static void push(void) +static void +push(void) /* push onstack on to the stack */ { - if (stackptr > MAX_PUSHED) + if (stackptr >= MAX_PUSHED) _nc_warning("string too complex to convert"); else stack[stackptr++] = onstack; } -static void pop(void) +static void +pop(void) /* pop the top of the stack into onstack */ { if (stackptr == 0) { @@ -161,26 +162,26 @@ static void pop(void) _nc_warning("I'm confused"); else onstack = 0; - } - else + } else onstack = stack[--stackptr]; param++; } -static int cvtchar(register const char *sp) +static int +cvtchar(register const char *sp) /* convert a character to a terminfo push */ { unsigned char c = 0; int len; - switch(*sp) { + switch (*sp) { case '\\': - switch(*++sp) { + switch (*++sp) { case '\'': case '$': case '\\': case '%': - c = *sp; + c = (unsigned char) (*sp); len = 2; break; case '\0': @@ -192,86 +193,92 @@ static int cvtchar(register const char *sp) case '2': case '3': len = 1; - while (isdigit(*sp)) - { - c = 8 * c + (*sp++ - '0'); + while (isdigit(UChar(*sp))) { + c = (unsigned char) (8 * c + (*sp++ - '0')); len++; } break; default: - c = *sp; + c = (unsigned char) (*sp); len = 2; break; } break; case '^': - c = (*++sp & 0x1f); + c = (unsigned char) (*++sp & 0x1f); len = 2; break; default: - c = *sp; + c = (unsigned char) (*sp); len = 1; } if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') { - *dp++ = '%'; *dp++ = '\''; *dp++ = c; *dp++ = '\''; + dp = save_string(dp, "%\'"); + dp = save_char(dp, c); + dp = save_char(dp, '\''); } else { - *dp++ = '%'; *dp++ = '{'; + dp = save_string(dp, "%{"); if (c > 99) - *dp++ = c / 100 + '0'; + dp = save_char(dp, c / 100 + '0'); if (c > 9) - *dp++ = ((int)(c / 10)) % 10 + '0'; - *dp++ = c % 10 + '0'; - *dp++ = '}'; + dp = save_char(dp, ((int) (c / 10)) % 10 + '0'); + dp = save_char(dp, c % 10 + '0'); + dp = save_char(dp, '}'); } return len; } -static void getparm(int parm, int n) +static void +getparm(int parm, int n) /* push n copies of param on the terminfo stack if not already there */ { - if (seenr) { - if (parm == 1) - parm = 2; - else if (parm == 2) - parm = 1; - } - if (onstack == parm) { - if (n > 1) { - _nc_warning("string may not be optimal"); - *dp++ = '%'; *dp++ = 'P'; *dp++ = 'a'; - while(n--) { - *dp++ = '%'; *dp++ = 'g'; *dp++ = 'a'; - } - } - return; - } - if (onstack != 0) - push(); + if (seenr) { + if (parm == 1) + parm = 2; + else if (parm == 2) + parm = 1; + } - onstack = parm; + while (n--) { + dp = save_string(dp, "%p"); + dp = save_char(dp, '0' + parm); + } - while(n--) { /* %p0 */ - *dp++ = '%'; *dp++ = 'p'; *dp++ = '0' + parm; + if (onstack == parm) { + if (n > 1) { + _nc_warning("string may not be optimal"); + dp = save_string(dp, "%Pa"); + while (n--) { + dp = save_string(dp, "%ga"); + } } + return; + } + if (onstack != 0) + push(); - if (seenn && parm < 3) { /* %{96}%^ */ - *dp++ = '%'; *dp++ = '{'; *dp++ = '9'; *dp++ = '6'; *dp++ = '}'; - *dp++ = '%'; *dp++ = '^'; - } + onstack = parm; - if (seenm && parm < 3) { /* %{127}%^ */ - *dp++ = '%'; *dp++ = '{'; *dp++ = '1'; *dp++ = '2'; *dp++ = '7'; - *dp++ = '}'; *dp++ = '%'; *dp++ = '^'; - } + if (seenn && parm < 3) { + dp = save_string(dp, "%{96}%^"); + } + + if (seenm && parm < 3) { + dp = save_string(dp, "%{127}%^"); + } } -char *_nc_captoinfo( -/* convert a termcap string to terminfo format */ -register const char *cap, /* relevant terminfo capability index */ -register const char *s, /* string value of the capability */ -int const parametrized) /* do % translations if 1, pad translations if >=0 */ +/* + * Convert a termcap string to terminfo format. + * 'cap' is the relevant terminfo capability index. + * 's' is the string value of the capability. + * 'parameterized' tells what type of translations to do: + * % translations if 1 + * pad translations if >=0 + */ +NCURSES_EXPORT(char *) +_nc_captoinfo(const char *cap, const char *s, int const parameterized) { - static char line[MAX_ENTRY]; const char *capstart; stackptr = 0; @@ -281,27 +288,29 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ seenr = 0; param = 1; - dp = line; + dp = init_string(); /* skip the initial padding (if we haven't been told not to) */ capstart = 0; if (s == 0) s = ""; - if (parametrized >= 0 && isdigit(*s)) - for (capstart = s; ; s++) - if (!(isdigit(*s) || *s == '*' || *s == '.')) + if (parameterized >= 0 && isdigit(UChar(*s))) + for (capstart = s;; s++) + if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.')) break; - while(*s != '\0') { - switch(*s) { + while (*s != '\0') { + switch (*s) { case '%': s++; - if (parametrized < 1) { - *dp++ = '%'; + if (parameterized < 1) { + dp = save_char(dp, '%'); break; } - switch(*s++) { - case '%': *dp++ = '%'; break; + switch (*s++) { + case '%': + dp = save_char(dp, '%'); + break; case 'r': if (seenr++ == 1) { _nc_warning("saw %%r twice in %s", cap); @@ -317,33 +326,29 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ _nc_warning("saw %%n twice in %s", cap); } break; - case 'i': *dp++ = '%'; *dp++ = 'i'; break; + case 'i': + dp = save_string(dp, "%i"); + break; case '6': case 'B': - getparm(param, 2); - /* %{6}%*%+ */ - *dp++ = '%'; *dp++ = '{'; *dp++ = '6'; - *dp++ = '}'; *dp++ = '%'; *dp++ = '*'; - *dp++ = '%'; *dp++ = '+'; + getparm(param, 1); + dp = save_string(dp, "%{10}%/%{16}%*"); + getparm(param, 1); + dp = save_string(dp, "%{10}%m%+"); break; case '8': case 'D': getparm(param, 2); - /* %{2}%*%- */ - *dp++ = '%'; *dp++ = '{'; *dp++ = '2'; - *dp++ = '}'; *dp++ = '%'; *dp++ = '*'; - *dp++ = '%'; *dp++ = '-'; + dp = save_string(dp, "%{2}%*%-"); break; case '>': getparm(param, 2); /* %?%{x}%>%t%{y}%+%; */ - *dp++ = '%'; *dp++ = '?'; + dp = save_string(dp, "%?"); s += cvtchar(s); - *dp++ = '%'; *dp++ = '>'; - *dp++ = '%'; *dp++ = 't'; + dp = save_string(dp, "%>%t"); s += cvtchar(s); - *dp++ = '%'; *dp++ = '+'; - *dp++ = '%'; *dp++ = ';'; + dp = save_string(dp, "%+%;"); break; case 'a': if ((*s == '=' || *s == '+' || *s == '-' @@ -363,18 +368,18 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ l++; } else l += cvtchar(s + 2); - switch(*s) { + switch (*s) { case '+': - *dp++ = '%'; *dp++ = '+'; + dp = save_string(dp, "%+"); break; case '-': - *dp++ = '%'; *dp++ = '-'; + dp = save_string(dp, "%-"); break; case '*': - *dp++ = '%'; *dp++ = '*'; + dp = save_string(dp, "%*"); break; case '/': - *dp++ = '%'; *dp++ = '/'; + dp = save_string(dp, "%/"); break; case '=': if (seenr) { @@ -384,8 +389,7 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ onstack = 1; else onstack = param; - } - else + } else onstack = param; break; } @@ -394,39 +398,37 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ } getparm(param, 1); s += cvtchar(s); - *dp++ = '%'; *dp++ = '+'; + dp = save_string(dp, "%+"); break; case '+': getparm(param, 1); s += cvtchar(s); - *dp++ = '%'; *dp++ = '+'; - *dp++ = '%'; *dp++ = 'c'; + dp = save_string(dp, "%+%c"); pop(); break; case 's': #ifdef WATERLOO s += cvtchar(s); getparm(param, 1); - *dp++ = '%'; *dp++ = '-'; + dp = save_string(dp, "%-"); #else getparm(param, 1); - *dp++ = '%'; *dp++ = 's'; + dp = save_string(dp, "%s"); pop(); #endif /* WATERLOO */ break; case '-': s += cvtchar(s); getparm(param, 1); - *dp++ = '%'; *dp++ = '-'; - *dp++ = '%'; *dp++ = 'c'; + dp = save_string(dp, "%-%c"); pop(); break; case '.': getparm(param, 1); - *dp++ = '%'; *dp++ = 'c'; + dp = save_string(dp, "%c"); pop(); break; - case '0': /* not clear any of the historical termcaps did this */ + case '0': /* not clear any of the historical termcaps did this */ if (*s == '3') goto see03; else if (*s != '2') @@ -434,19 +436,18 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ /* FALLTHRU */ case '2': getparm(param, 1); - *dp++ = '%'; /* *dp++ = '0'; */ - *dp++ = '2'; *dp++ = 'd'; + dp = save_string(dp, "%2d"); pop(); break; - case '3': see03: + case '3': + see03: getparm(param, 1); - *dp++ = '%'; /* *dp++ = '0'; */ - *dp++ = '3'; *dp++ = 'd'; + dp = save_string(dp, "%3d"); pop(); break; case 'd': getparm(param, 1); - *dp++ = '%'; *dp++ = 'd'; + dp = save_string(dp, "%d"); pop(); break; case 'f': @@ -456,63 +457,20 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ param--; break; case '\\': - *dp++ = '%'; - *dp++ = '\\'; + dp = save_string(dp, "%\\"); break; - default: invalid: - *dp++ = '%'; + default: + invalid: + dp = save_char(dp, '%'); s--; - _nc_warning("unknown %% code %s in %s", - _tracechar(*s), cap); + _nc_warning("unknown %% code %s (%#x) in %s", + unctrl((chtype) *s), UChar(*s), cap); break; } break; -#ifdef REVISIBILIZE - case '\\': - *dp++ = *s++; *dp++ = *s++; break; - case '\n': - *dp++ = '\\'; *dp++ = 'n'; s++; break; - case '\t': - *dp++ = '\\'; *dp++ = 't'; s++; break; - case '\r': - *dp++ = '\\'; *dp++ = 'r'; s++; break; - case '\200': - *dp++ = '\\'; *dp++ = '0'; s++; break; - case '\f': - *dp++ = '\\'; *dp++ = 'f'; s++; break; - case '\b': - *dp++ = '\\'; *dp++ = 'b'; s++; break; - case ' ': - *dp++ = '\\'; *dp++ = 's'; s++; break; - case '^': - *dp++ = '\\'; *dp++ = '^'; s++; break; - case ':': - *dp++ = '\\'; *dp++ = ':'; s++; break; - case ',': - *dp++ = '\\'; *dp++ = ','; s++; break; - default: - if (*s == '\033') { - *dp++ = '\\'; - *dp++ = 'E'; - s++; - } else if (*s > 0 && *s < 32) { - *dp++ = '^'; - *dp++ = *s + '@'; - s++; - } else if (*s <= 0 || *s >= 127) { - *dp++ = '\\'; - *dp++ = ((*s & 0300) >> 6) + '0'; - *dp++ = ((*s & 0070) >> 3) + '0'; - *dp++ = (*s & 0007) + '0'; - s++; - } else - *dp++ = *s++; - break; -#else default: - *dp++ = *s++; + dp = save_char(dp, *s++); break; -#endif } } @@ -520,21 +478,79 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ * Now, if we stripped off some leading padding, add it at the end * of the string as mandatory padding. */ - if (capstart) - { - *dp++ = '$'; - *dp++ = '<'; - for (s = capstart; ; s++) - if (isdigit(*s) || *s == '*' || *s == '.') - *dp++ = *s; + if (capstart) { + dp = save_string(dp, "$<"); + for (s = capstart;; s++) + if (isdigit(UChar(*s)) || *s == '*' || *s == '.') + dp = save_char(dp, *s); else break; - *dp++ = '/'; - *dp++ = '>'; + dp = save_string(dp, "/>"); } - *dp = '\0'; - return(line); + (void) save_char(dp, '\0'); + return (my_string); +} + +/* + * Check for an expression that corresponds to "%B" (BCD): + * (parameter / 10) * 16 + (parameter % 10) + */ +static int +bcd_expression(const char *str) +{ + /* leave this non-const for HPUX */ + static char fmt[] = "%%p%c%%{10}%%/%%{16}%%*%%p%c%%{10}%%m%%+"; + int len = 0; + char ch1, ch2; + + if (sscanf(str, fmt, &ch1, &ch2) == 2 + && isdigit(UChar(ch1)) + && isdigit(UChar(ch2)) + && (ch1 == ch2)) { + len = 28; +#ifndef NDEBUG + { + char buffer[80]; + int tst; + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) fmt, ch1, ch2); + tst = strlen(buffer) - 1; + assert(len == tst); + } +#endif + } + return len; +} + +static char * +save_tc_char(char *bufptr, int c1) +{ + if (is7bits(c1) && isprint(c1)) { + if (c1 == ':' || c1 == '\\') + bufptr = save_char(bufptr, '\\'); + bufptr = save_char(bufptr, c1); + } else { + char temp[80]; + + if (c1 == (c1 & 0x1f)) { /* iscntrl() returns T on 255 */ + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) + "%.20s", unctrl((chtype) c1)); + } else { + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) + "\\%03o", c1); + } + bufptr = save_string(bufptr, temp); + } + return bufptr; +} + +static char * +save_tc_inequality(char *bufptr, int c1, int c2) +{ + bufptr = save_string(bufptr, "%>"); + bufptr = save_tc_char(bufptr, c1); + bufptr = save_tc_char(bufptr, c2); + return bufptr; } /* @@ -555,129 +571,197 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ * %m exclusive-or all parameters with 0177 (not in 4.4BSD) */ -char *_nc_infotocap( -/* convert a terminfo string to termcap format */ -register const char *cap GCC_UNUSED, /* relevant termcap capability index */ -register const char *str, /* string value of the capability */ -int const parametrized) /* do % translations if 1, pad translations if >=0 */ +/* + * Convert a terminfo string to termcap format. Parameters are as in + * _nc_captoinfo(). + */ +NCURSES_EXPORT(char *) +_nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameterized) { - int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0; + int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0; const char *padding; const char *trimmed = 0; + int in0, in1, in2; char ch1 = 0, ch2 = 0; char *bufptr = init_string(); - char temp[256]; + char octal[4]; + int len; + bool syntax_error = FALSE; /* we may have to move some trailing mandatory padding up front */ padding = str + strlen(str) - 1; - if (*padding == '>' && *--padding == '/') - { - --padding; - while (isdigit(*padding) || *padding == '.' || *padding == '*') + if (padding > str && *padding == '>') { + if (*--padding == '/') + --padding; + while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*') padding--; - if (*padding == '<' && *--padding == '$') + if (padding > str && *padding == '<' && *--padding == '$') trimmed = padding; padding += 2; - while (isdigit(*padding) || *padding == '.' || *padding == '*') + while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*') bufptr = save_char(bufptr, *padding++); } - for (; *str && str != trimmed; str++) - { - int c1, c2; - char *cp = 0; - - if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) - { - bufptr = save_char(bufptr, *++str); - } - else if (str[0] == '$' && str[1] == '<') /* discard padding */ - { + for (; *str && ((trimmed == 0) || (str < trimmed)); str++) { + int c1, c2; + char *cp = 0; + + if (str[0] == '^') { + if (str[1] == '\0' || (str + 1) == trimmed) { + bufptr = save_string(bufptr, "\\136"); + ++str; + } else { + bufptr = save_char(bufptr, *str++); + bufptr = save_char(bufptr, *str); + } + } else if (str[0] == '\\') { + if (str[1] == '\0' || (str + 1) == trimmed) { + bufptr = save_string(bufptr, "\\134"); + ++str; + } else if (str[1] == '^') { + bufptr = save_string(bufptr, "\\136"); + ++str; + } else if (str[1] == ',') { + bufptr = save_char(bufptr, *++str); + } else { + int xx1; + + bufptr = save_char(bufptr, *str++); + xx1 = *str; + if (_nc_strict_bsd) { + + if (isdigit(UChar(xx1))) { + int pad = 0; + int xx2; + + if (!isdigit(UChar(str[1]))) + pad = 2; + else if (str[1] && !isdigit(UChar(str[2]))) + pad = 1; + + /* + * Test for "\0", "\00" or "\000" and transform those + * into "\200". + */ + if (xx1 == '0' + && ((pad == 2) || (str[1] == '0')) + && ((pad >= 1) || (str[2] == '0'))) { + xx2 = '2'; + } else { + xx2 = '0'; + pad = 0; /* FIXME - optionally pad to 3 digits */ + } + while (pad-- > 0) { + bufptr = save_char(bufptr, xx2); + xx2 = '0'; + } + } else if (strchr("E\\nrtbf", xx1) == 0) { + switch (xx1) { + case 'e': + xx1 = 'E'; + break; + case 'l': + xx1 = 'n'; + break; + case 's': + bufptr = save_char(bufptr, '0'); + bufptr = save_char(bufptr, '4'); + xx1 = '0'; + break; + case ':': + /* + * Note: termcap documentation claims that ":" + * must be escaped as "\072", however the + * documentation is incorrect - read the code. + * The replacement does not work reliably, + * so the advice is not helpful. + */ + bufptr = save_char(bufptr, '0'); + bufptr = save_char(bufptr, '7'); + xx1 = '2'; + break; + default: + /* should not happen, but handle this anyway */ + _nc_SPRINTF(octal, _nc_SLIMIT(sizeof(octal)) + "%03o", UChar(xx1)); + bufptr = save_char(bufptr, octal[0]); + bufptr = save_char(bufptr, octal[1]); + xx1 = octal[2]; + break; + } + } + } + bufptr = save_char(bufptr, xx1); + } + } else if (str[0] == '$' && str[1] == '<') { /* discard padding */ str += 2; - while (isdigit(*str) || *str == '.' || *str == '*' || *str == '/' || *str == '>') + while (isdigit(UChar(*str)) + || *str == '.' + || *str == '*' + || *str == '/' + || *str == '>') str++; --str; - } - else if (*str != '%' || (parametrized < 1)) + } else if (sscanf(str, + "[%%?%%p1%%{8}%%<%%t%d%%p1%%d%%e%%p1%%{16}%%<%%t%d%%p1%%{8}%%-%%d%%e%d;5;%%p1%%d%%;m", + &in0, &in1, &in2) == 3 + && ((in0 == 4 && in1 == 10 && in2 == 48) + || (in0 == 3 && in1 == 9 && in2 == 38))) { + /* dumb-down an optimized case from xterm-256color for termcap */ + if ((str = strstr(str, ";m")) == 0) + break; /* cannot happen */ + ++str; + if (in2 == 48) { + bufptr = save_string(bufptr, "[48;5;%dm"); + } else { + bufptr = save_string(bufptr, "[38;5;%dm"); + } + } else if (str[0] == '%' && str[1] == '%') { /* escaped '%' */ + bufptr = save_string(bufptr, "%%"); + ++str; + } else if (*str != '%' || (parameterized < 1)) { bufptr = save_char(bufptr, *str); - else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1,&c2) == 2) - { + } else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1, &c2) == 2) { str = strchr(str, ';'); - (void) sprintf(temp, "%%>%s%s", unctrl(c1), unctrl(c2)); - bufptr = save_string(bufptr, temp); - } - else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1,&ch2) == 2) - { + bufptr = save_tc_inequality(bufptr, c1, c2); + } else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) { str = strchr(str, ';'); - (void) sprintf(temp, "%%>%s%c", unctrl(c1), ch2); - bufptr = save_string(bufptr, temp); - } - else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1,&c2) == 2) - { + bufptr = save_tc_inequality(bufptr, c1, ch2); + } else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) { str = strchr(str, ';'); - (void) sprintf(temp, "%%>%c%c", ch1, c2); - bufptr = save_string(bufptr, temp); - } - else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) - { + bufptr = save_tc_inequality(bufptr, ch1, c2); + } else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) { str = strchr(str, ';'); - (void) sprintf(temp, "%%>%c%c", ch1, ch2); - bufptr = save_string(bufptr, temp); - } - else if (strncmp(str, "%{6}%*%+", 8) == 0) - { - str += 7; - (void) sprintf(temp, "%%B"); - bufptr = save_string(bufptr, temp); - } - else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1 - || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1) - && (cp = strchr(str, '+'))) - { + bufptr = save_tc_inequality(bufptr, ch1, ch2); + } else if ((len = bcd_expression(str)) != 0) { + str += len; + bufptr = save_string(bufptr, "%B"); + } else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1 + || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1) + && (cp = strchr(str, '+'))) { str = cp + 2; - bufptr = save_char(bufptr, '%'); - bufptr = save_char(bufptr, '+'); + bufptr = save_string(bufptr, "%+"); if (ch1) c1 = ch1; - if (is7bits(c1) && isprint(c1)) - bufptr = save_char(bufptr, (char)c1); - else - { - if (c1 == (c1 & 0x1f)) /* iscntrl() returns T on 255 */ - (void) strcpy(temp, unctrl(c1)); - else - (void) sprintf(temp, "\\%03o", c1); - bufptr = save_string(bufptr, temp); - } + bufptr = save_tc_char(bufptr, c1); } - else if (strncmp(str, "%{2}%*%-", 8) == 0) - { + /* FIXME: this "works" for 'delta' */ + else if (strncmp(str, "%{2}%*%-", (size_t) 8) == 0) { str += 7; - (void) sprintf(temp, "%%D"); - bufptr = save_string(bufptr, temp); - } - else if (strncmp(str, "%{96}%^", 7) == 0) - { + bufptr = save_string(bufptr, "%D"); + } else if (strncmp(str, "%{96}%^", (size_t) 7) == 0) { str += 6; - if (saw_m++ == 0) - { - (void) sprintf(temp, "%%n"); - bufptr = save_string(bufptr, temp); + if (saw_m++ == 0) { + bufptr = save_string(bufptr, "%n"); } - } - else if (strncmp(str, "%{127}%^", 8) == 0) - { + } else if (strncmp(str, "%{127}%^", (size_t) 8) == 0) { str += 7; - if (saw_n++ == 0) - { - (void) sprintf(temp, "%%m"); - bufptr = save_string(bufptr, temp); + if (saw_n++ == 0) { + bufptr = save_string(bufptr, "%m"); } - } - else - { + } else { /* cm-style format element */ str++; switch (*str) { case '%': @@ -695,92 +779,106 @@ int const parametrized) /* do % translations if 1, pad translations if >=0 */ case '8': case '9': bufptr = save_char(bufptr, '%'); - while (isdigit(*str)) - bufptr = save_char(bufptr, *str++); - if (*str == 'd') - str++; - else - _nc_warning("numeric prefix is missing trailing d in %s", - cap); - --str; + ch1 = 0; + ch2 = 0; + while (isdigit(UChar(*str))) { + ch2 = ch1; + ch1 = *str++; + if (_nc_strict_bsd) { + if (ch1 > '3') + return 0; + } else { + bufptr = save_char(bufptr, ch1); + } + } + if (_nc_strict_bsd) { + if (ch2 != 0 && ch2 != '0') + return 0; + if (ch1 < '2') + ch1 = 'd'; + bufptr = save_char(bufptr, ch1); + } + if (strchr("doxX.", *str)) { + if (*str != 'd') /* termcap doesn't have octal, hex */ + return 0; + } break; case 'd': - bufptr = save_char(bufptr, '%'); - bufptr = save_char(bufptr, 'd'); + bufptr = save_string(bufptr, "%d"); break; case 'c': - bufptr = save_char(bufptr, '%'); - bufptr = save_char(bufptr, '.'); + bufptr = save_string(bufptr, "%."); break; - /* - * %s isn't in termcap, but it's convenient to pass it through - * so we can represent things like terminfo pfkey strings in - * termcap notation. - */ + /* + * %s isn't in termcap, but it's convenient to pass it through + * so we can represent things like terminfo pfkey strings in + * termcap notation. + */ case 's': - bufptr = save_char(bufptr, '%'); - bufptr = save_char(bufptr, 's'); + if (_nc_strict_bsd) + return 0; + bufptr = save_string(bufptr, "%s"); break; case 'p': str++; if (*str == '1') seenone = 1; - else if (*str == '2') - { - if (!seenone && !seentwo) - { - bufptr = save_char(bufptr, '%'); - bufptr = save_char(bufptr, 'r'); + else if (*str == '2') { + if (!seenone && !seentwo) { + bufptr = save_string(bufptr, "%r"); seentwo++; } - } - else if (*str >= '3') - return(0); + } else if (*str >= '3') + return (0); break; case 'i': - bufptr = save_char(bufptr, '%'); - bufptr = save_char(bufptr, 'i'); + bufptr = save_string(bufptr, "%i"); break; default: - return(0); - - } /* endswitch (*str) */ - } /* endelse (*str == '%') */ - - if (*str == '\0') + bufptr = save_char(bufptr, *str); + syntax_error = TRUE; + break; + } /* endswitch (*str) */ + } /* endelse (*str == '%') */ + + /* + * 'str' always points to the end of what was scanned in this step, + * but that may not be the end of the string. + */ + assert(str != 0); + if (str == 0 || *str == '\0') break; - } /* endwhile (*str) */ + } /* endwhile (*str) */ - return(my_string); + return (syntax_error ? NULL : my_string); } #ifdef MAIN int curr_line; -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { int c, tc = FALSE; while ((c = getopt(argc, argv, "c")) != EOF) - switch (c) - { + switch (c) { case 'c': tc = TRUE; break; } curr_line = 0; - for (;;) - { - char buf[BUFSIZ]; + for (;;) { + char buf[BUFSIZ]; ++curr_line; if (fgets(buf, sizeof(buf), stdin) == 0) @@ -788,20 +886,26 @@ int main(int argc, char *argv[]) buf[strlen(buf) - 1] = '\0'; _nc_set_source(buf); - if (tc) - { - char *cp = _nc_infotocap("to termcap", buf, 1); + if (tc) { + char *cp = _nc_infotocap("to termcap", buf, 1); if (cp) (void) fputs(cp, stdout); - } - else + } else (void) fputs(_nc_captoinfo("to terminfo", buf, 1), stdout); (void) putchar('\n'); } - return(0); + return (0); } #endif /* MAIN */ -/* captoinfo.c ends here */ - +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_captoinfo_leaks(void) +{ + if (my_string != 0) { + FreeAndNull(my_string); + } + my_length = 0; +} +#endif