ncurses 6.0 - patch 20161126
[ncurses.git] / ncurses / tinfo / captoinfo.c
index faedb58c8690a8b91920c0302bb2016e68b0d172..dd02d902dc5261a67c4849508d8c15c07ec22b68 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2011 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            *
@@ -93,7 +93,7 @@
 #include <ctype.h>
 #include <tic.h>
 
-MODULE_ID("$Id: captoinfo.c,v 1.64 2011/07/23 20:36:28 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 */
 
@@ -114,9 +114,7 @@ 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(MSG_NO_MEMORY);
+       TYPE_MALLOC(char, my_length = 256, my_string);
 
     *my_string = '\0';
     return my_string;
@@ -133,7 +131,7 @@ save_string(char *d, const char *const s)
            _nc_err_abort(MSG_NO_MEMORY);
        d = my_string + have;
     }
-    (void) strcpy(d, s);
+    _nc_STRCPY(d, s, my_length - have);
     return d + strlen(d);
 }
 
@@ -240,6 +238,12 @@ getparm(int parm, int n)
        else if (parm == 2)
            parm = 1;
     }
+
+    while (n--) {
+       dp = save_string(dp, "%p");
+       dp = save_char(dp, '0' + parm);
+    }
+
     if (onstack == parm) {
        if (n > 1) {
            _nc_warning("string may not be optimal");
@@ -255,11 +259,6 @@ getparm(int parm, int n)
 
     onstack = parm;
 
-    while (n--) {
-       dp = save_string(dp, "%p");
-       dp = save_char(dp, '0' + parm);
-    }
-
     if (seenn && parm < 3) {
        dp = save_string(dp, "%{96}%^");
     }
@@ -514,7 +513,7 @@ bcd_expression(const char *str)
        {
            char buffer[80];
            int tst;
-           sprintf(buffer, fmt, ch1, ch2);
+           _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) fmt, ch1, ch2);
            tst = strlen(buffer) - 1;
            assert(len == tst);
        }
@@ -526,17 +525,20 @@ bcd_expression(const char *str)
 static char *
 save_tc_char(char *bufptr, int c1)
 {
-    char temp[80];
-
     if (is7bits(c1) && isprint(c1)) {
        if (c1 == ':' || c1 == '\\')
            bufptr = save_char(bufptr, '\\');
        bufptr = save_char(bufptr, c1);
     } else {
-       if (c1 == (c1 & 0x1f))  /* iscntrl() returns T on 255 */
-           (void) strcpy(temp, unctrl((chtype) c1));
-       else
-           (void) sprintf(temp, "\\%03o", c1);
+       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;
@@ -576,7 +578,6 @@ save_tc_inequality(char *bufptr, int c1, int c2)
 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;
@@ -589,8 +590,9 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
 
     /* we may have to move some trailing mandatory padding up front */
     padding = str + strlen(str) - 1;
-    if (padding > str && *padding == '>' && *--padding == '/') {
-       --padding;
+    if (padding > str && *padding == '>') {
+       if (*--padding == '/')
+           --padding;
        while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
            padding--;
        if (padding > str && *padding == '<' && *--padding == '$')
@@ -601,7 +603,7 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
            bufptr = save_char(bufptr, *padding++);
     }
 
-    for (; *str && str != trimmed; str++) {
+    for (; *str && ((trimmed == 0) || (str < trimmed)); str++) {
        int c1, c2;
        char *cp = 0;
 
@@ -623,13 +625,15 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
            } else if (str[1] == ',') {
                bufptr = save_char(bufptr, *++str);
            } else {
-               int xx1, xx2;
+               int xx1;
 
                bufptr = save_char(bufptr, *str++);
                xx1 = *str;
-               if (strict_bsd) {
+               if (_nc_strict_bsd) {
+
                    if (isdigit(UChar(xx1))) {
                        int pad = 0;
+                       int xx2;
 
                        if (!isdigit(UChar(str[1])))
                            pad = 2;
@@ -652,13 +656,11 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
                            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.
-                        */
+                   } else if (strchr("E\\nrtbf", xx1) == 0) {
                        switch (xx1) {
+                       case 'e':
+                           xx1 = 'E';
+                           break;
                        case 'l':
                            xx1 = 'n';
                            break;
@@ -667,13 +669,26 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
                            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 */
-                           sprintf(octal, "%03o", UChar(xx1));
+                           _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];
-                           continue;
+                           break;
                        }
                    }
                }
@@ -694,7 +709,8 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
                   && ((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");
+           if ((str = strstr(str, ";m")) == 0)
+               break;          /* cannot happen */
            ++str;
            if (in2 == 48) {
                bufptr = save_string(bufptr, "[48;5;%dm");
@@ -711,13 +727,13 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
            bufptr = save_tc_inequality(bufptr, c1, c2);
        } else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) {
            str = strchr(str, ';');
-           bufptr = save_tc_inequality(bufptr, c1, c2);
+           bufptr = save_tc_inequality(bufptr, c1, ch2);
        } else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) {
            str = strchr(str, ';');
-           bufptr = save_tc_inequality(bufptr, c1, c2);
+           bufptr = save_tc_inequality(bufptr, ch1, c2);
        } else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) {
            str = strchr(str, ';');
-           bufptr = save_tc_inequality(bufptr, c1, c2);
+           bufptr = save_tc_inequality(bufptr, ch1, ch2);
        } else if ((len = bcd_expression(str)) != 0) {
            str += len;
            bufptr = save_string(bufptr, "%B");
@@ -732,15 +748,15 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
            bufptr = save_tc_char(bufptr, c1);
        }
        /* FIXME: this "works" for 'delta' */
-       else if (strncmp(str, "%{2}%*%-", 8) == 0) {
+       else if (strncmp(str, "%{2}%*%-", (size_t) 8) == 0) {
            str += 7;
            bufptr = save_string(bufptr, "%D");
-       } else if (strncmp(str, "%{96}%^", 7) == 0) {
+       } else if (strncmp(str, "%{96}%^", (size_t) 7) == 0) {
            str += 6;
            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) {
                bufptr = save_string(bufptr, "%m");
@@ -768,14 +784,14 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
                while (isdigit(UChar(*str))) {
                    ch2 = ch1;
                    ch1 = *str++;
-                   if (strict_bsd) {
+                   if (_nc_strict_bsd) {
                        if (ch1 > '3')
                            return 0;
                    } else {
                        bufptr = save_char(bufptr, ch1);
                    }
                }
-               if (strict_bsd) {
+               if (_nc_strict_bsd) {
                    if (ch2 != 0 && ch2 != '0')
                        return 0;
                    if (ch1 < '2')
@@ -802,7 +818,7 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
                 * termcap notation.
                 */
            case 's':
-               if (strict_bsd)
+               if (_nc_strict_bsd)
                    return 0;
                bufptr = save_string(bufptr, "%s");
                break;
@@ -836,7 +852,7 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
         * but that may not be the end of the string.
         */
        assert(str != 0);
-       if (*str == '\0')
+       if (str == 0 || *str == '\0')
            break;
 
     }                          /* endwhile (*str) */