/****************************************************************************
- * Copyright (c) 1998-2005,2006 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 *
#include <ctype.h>
#include <tic.h>
-MODULE_ID("$Id: captoinfo.c,v 1.49 2006/12/16 19:16:53 tom Exp $")
+MODULE_ID("$Id: captoinfo.c,v 1.64 2011/07/23 20:36:28 tom Exp $")
#define MAX_PUSHED 16 /* max # args we can push onto the stack */
static char *
save_string(char *d, const char *const s)
{
- size_t have = (d - my_string);
+ size_t have = (size_t) (d - my_string);
size_t need = have + strlen(s) + 2;
if (need > my_length) {
- my_string = (char *) realloc(my_string, my_length = (need + need));
+ 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;
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;
case '$':
case '\\':
case '%':
- c = *sp;
+ c = (unsigned char) (*sp);
len = 2;
break;
case '\0':
case '3':
len = 1;
while (isdigit(UChar(*sp))) {
- c = 8 * c + (*sp++ - '0');
+ 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 != ':') {
break;
}
break;
-#ifdef REVISIBILIZE
- case '\\':
- dp = save_char(dp, *s++);
- dp = save_char(dp, *s++);
- break;
- case '\n':
- dp = save_string(dp, "\\n");
- s++;
- break;
- case '\t':
- dp = save_string(dp, "\\t");
- s++;
- break;
- case '\r':
- dp = save_string(dp, "\\r");
- s++;
- break;
- case '\200':
- dp = save_string(dp, "\\0");
- s++;
- break;
- case '\f':
- dp = save_string(dp, "\\f");
- s++;
- break;
- case '\b':
- dp = save_string(dp, "\\b");
- s++;
- break;
- case ' ':
- dp = save_string(dp, "\\s");
- s++;
- break;
- case '^':
- dp = save_string(dp, "\\^");
- s++;
- break;
- case ':':
- dp = save_string(dp, "\\:");
- s++;
- break;
- case ',':
- dp = save_string(dp, "\\,");
- s++;
- break;
- default:
- if (*s == '\033') {
- dp = save_string(dp, "\\E");
- s++;
- } else if (*s > 0 && *s < 32) {
- dp = save_char(dp, '^');
- dp = save_char(dp, *s + '@');
- s++;
- } else if (*s <= 0 || *s >= 127) {
- dp = save_char(dp, '\\');
- dp = save_char(dp, ((*s & 0300) >> 6) + '0');
- dp = save_char(dp, ((*s & 0070) >> 3) + '0');
- dp = save_char(dp, (*s & 0007) + '0');
- s++;
- } else
- dp = save_char(dp, *s++);
- break;
-#else
default:
dp = save_char(dp, *s++);
break;
-#endif
}
}
NCURSES_EXPORT(char *)
_nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameterized)
{
+ int strict_bsd = 1; /* FIXME - consider making this an option */
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 octal[4];
int len;
bool syntax_error = FALSE;
int c1, c2;
char *cp = 0;
- if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) {
- bufptr = save_char(bufptr, *++str);
+ 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, xx2;
+
+ bufptr = save_char(bufptr, *str++);
+ xx1 = *str;
+ if (strict_bsd) {
+ if (isdigit(UChar(xx1))) {
+ int pad = 0;
+
+ 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) {
+ /*
+ * Note: termcap documentation claims that ":" must be
+ * escaped as "\072", however the documentation is
+ * incorrect - read the code.
+ */
+ switch (xx1) {
+ case 'l':
+ xx1 = 'n';
+ break;
+ case 's':
+ bufptr = save_char(bufptr, '0');
+ bufptr = save_char(bufptr, '4');
+ xx1 = '0';
+ break;
+ default:
+ /* should not happen, but handle this anyway */
+ sprintf(octal, "%03o", UChar(xx1));
+ bufptr = save_char(bufptr, octal[0]);
+ bufptr = save_char(bufptr, octal[1]);
+ xx1 = octal[2];
+ continue;
+ }
+ }
+ }
+ bufptr = save_char(bufptr, xx1);
+ }
} else if (str[0] == '$' && str[1] == '<') { /* discard padding */
str += 2;
while (isdigit(UChar(*str))
|| *str == '>')
str++;
--str;
+ } 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 */
+ str = strstr(str, ";m");
+ ++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;
case '8':
case '9':
bufptr = save_char(bufptr, '%');
- while (isdigit(UChar(*str)))
- bufptr = save_char(bufptr, *str++);
+ ch1 = 0;
+ ch2 = 0;
+ while (isdigit(UChar(*str))) {
+ ch2 = ch1;
+ ch1 = *str++;
+ if (strict_bsd) {
+ if (ch1 > '3')
+ return 0;
+ } else {
+ bufptr = save_char(bufptr, ch1);
+ }
+ }
+ if (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;
* termcap notation.
*/
case 's':
+ if (strict_bsd)
+ return 0;
bufptr = save_string(bufptr, "%s");
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')
break;