ncurses 6.2 - patch 20201024
[ncurses.git] / progs / dump_entry.c
index dad3135f4fceec9ccca61e11c2de045ac8aaa138..e084e0f0f541a507cba7aa71d75c36e059d18915 100644 (file)
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2016,2017 Free Software Foundation, Inc.              *
+ * Copyright 2018-2019,2020 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 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            *
@@ -39,7 +40,7 @@
 #include "termsort.c"          /* this C file is generated */
 #include <parametrized.h>      /* so is this */
 
-MODULE_ID("$Id: dump_entry.c,v 1.152 2017/05/06 18:56:15 tom Exp $")
+MODULE_ID("$Id: dump_entry.c,v 1.179 2020/07/08 21:21:11 tom Exp $")
 
 #define DISCARD(string) string = ABSENT_STRING
 #define PRINTF (void) printf
@@ -94,7 +95,7 @@ static int indent = 8;
 #define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T')
 #endif
 
-#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n))
+#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && (sortmode != S_VARIABLE) && OBSOLETE(n))
 
 #if NCURSES_XNAMES
 #define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j]))
@@ -499,8 +500,9 @@ find_split(const char *src, int step, int size)
                int ch = UChar(src[step + n]);
                if (ch == '%') {
                    int need = op_length(src, step + n);
-                   if ((n + need) > size)
+                   if ((n + need) > size) {
                        mark = n;
+                   }
                    break;
                }
            }
@@ -529,7 +531,7 @@ fill_spaces(const char *src)
        for (s = d = 0; src[s] != '\0'; ++s) {
            if (src[s] == ' ') {
                if (pass) {
-                   strcpy(&result[d], fill);
+                   _nc_STRCPY(&result[d], fill, need + 1 - d);
                    d += (int) size;
                } else {
                    need += size;
@@ -553,22 +555,34 @@ fill_spaces(const char *src)
     return result;
 }
 
+typedef enum {
+    wOFF = 0
+    ,w1ST = 1
+    ,w2ND = 2
+    ,wEND = 4
+    ,wERR = 8
+} WRAPMODE;
+
+#define wrap_1ST(mode) ((mode)&w1ST)
+#define wrap_END(mode) ((mode)&wEND)
+#define wrap_ERR(mode) ((mode)&wERR)
+
 static void
-wrap_concat(const char *src)
+wrap_concat(const char *src, int need, unsigned mode)
 {
-    int need = (int) strlen(src);
     int gaps = (int) strlen(separator);
     int want = gaps + need;
 
     did_wrap = (width <= 0);
-    if (column > indent
+    if (wrap_1ST(mode)
+       && column > indent
        && column + want > width) {
        force_wrap();
     }
-    if (wrapped &&
+    if ((wrap_END(mode) && !wrap_ERR(mode)) &&
+       wrapped &&
        (width >= 0) &&
-       (column + want) > width &&
-       (!TcOutput() || strncmp(src, "..", 2))) {
+       (column + want) > width) {
        int step = 0;
        int used = width > WRAPPED ? width : WRAPPED;
        int size;
@@ -583,18 +597,29 @@ wrap_concat(const char *src)
        if (TcOutput())
            trailer = "\\\n\t ";
 
-       if ((p = strchr(fill, '=')) != 0) {
+       if (!TcOutput() && (p = strchr(fill, '=')) != 0) {
            base = (int) (p + 1 - fill);
            if (base > 8)
                base = 8;
            _nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " ");
+       } else if (column > 8) {
+           base = column - 8;
+           if (base > 8)
+               base = 8;
+           _nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " ");
        } else {
            align[base] = '\0';
        }
        /* "pretty" overrides wrapping if it already split the line */
        if (!pretty || strchr(fill, '\n') == 0) {
+           int tag = 0;
+
+           if (TcOutput() && outbuf.used && !wrap_1ST(mode)) {
+               tag = 3;
+           }
+
            while ((column + (need + gaps)) > used) {
-               size = used;
+               size = used - tag;
                if (step) {
                    strcpy_DYN(&outbuf, align);
                    size -= base;
@@ -609,6 +634,7 @@ wrap_concat(const char *src)
                if (need > 0) {
                    force_wrap();
                    did_wrap = TRUE;
+                   tag = 0;
                }
            }
        }
@@ -617,18 +643,39 @@ wrap_concat(const char *src)
                strcpy_DYN(&outbuf, align);
            strcpy_DYN(&outbuf, fill + step);
        }
-       strcpy_DYN(&outbuf, separator);
+       if (wrap_END(mode))
+           strcpy_DYN(&outbuf, separator);
        trailer = my_t;
        force_wrap();
 
        free(fill);
     } else {
        strcpy_DYN(&outbuf, src);
-       strcpy_DYN(&outbuf, separator);
-       column += need;
+       if (wrap_END(mode))
+           strcpy_DYN(&outbuf, separator);
+       column += (int) strlen(src);
     }
 }
 
+static void
+wrap_concat1(const char *src)
+{
+    int need = (int) strlen(src);
+    wrap_concat(src, need, w1ST | wEND);
+}
+
+static void
+wrap_concat3(const char *name, const char *eqls, const char *value)
+{
+    int nlen = (int) strlen(name);
+    int elen = (int) strlen(eqls);
+    int vlen = (int) strlen(value);
+
+    wrap_concat(name, nlen + elen + vlen, w1ST);
+    wrap_concat(eqls, elen + vlen, w2ND);
+    wrap_concat(value, vlen, wEND);
+}
+
 #define IGNORE_SEP_TRAIL(first,last,sep_trail) \
        if ((size_t)(last - first) > sizeof(sep_trail)-1 \
         && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \
@@ -672,6 +719,33 @@ indent_DYN(DYNBUF * buffer, int level)
        strncpy_DYN(buffer, "\t", (size_t) 1);
 }
 
+/*
+ * Check if the current line which was begun consists only of a tab and the
+ * given leading text.
+ */
+static bool
+leading_DYN(DYNBUF * buffer, const char *leading)
+{
+    bool result = FALSE;
+    size_t need = strlen(leading);
+    if (buffer->used > need) {
+       need = buffer->used - need;
+       if (!strcmp(buffer->text + need, leading)) {
+           result = TRUE;
+           while (--need != 0) {
+               if (buffer->text[need] == '\n') {
+                   break;
+               }
+               if (buffer->text[need] != '\t') {
+                   result = FALSE;
+                   break;
+               }
+           }
+       }
+    }
+    return result;
+}
+
 bool
 has_params(const char *src)
 {
@@ -775,7 +849,7 @@ fmt_complex(TERMTYPE2 *tterm, const char *capability, char *src, int level)
            }
            break;
        case 'p':
-           if (percent && params) {
+           if (percent && params && !leading_DYN(&tmpbuf, "%")) {
                tmpbuf.text[tmpbuf.used - 1] = '\n';
                indent_DYN(&tmpbuf, level + 1);
                strncpy_DYN(&tmpbuf, "%", (size_t) 1);
@@ -807,8 +881,10 @@ number_format(int value)
     if ((outform != F_TERMCAP) && (value > 255)) {
        unsigned long lv = (unsigned long) value;
        unsigned long mm;
+       int bits = sizeof(unsigned long) * 8;
        int nn;
-       for (nn = 8; (mm = (1UL << nn)) != 0; ++nn) {
+       for (nn = 8; nn < bits; ++nn) {
+           mm = 1UL << nn;
            if ((mm - 16) <= lv && (mm + 16) > lv) {
                result = "%#x";
                break;
@@ -839,9 +915,8 @@ fmt_entry(TERMTYPE2 *tterm,
     PredIdx num_strings = 0;
     bool outcount = 0;
 
-#define WRAP_CONCAT    \
-       wrap_concat(buffer); \
-       outcount = TRUE
+#define WRAP_CONCAT1(s)                wrap_concat1(s); outcount = TRUE
+#define WRAP_CONCAT            WRAP_CONCAT1(buffer)
 
     len = 12;                  /* terminfo file-header */
 
@@ -940,12 +1015,12 @@ fmt_entry(TERMTYPE2 *tterm,
 #undef CUR
 #define CUR tterm->
     if (outform == F_TERMCAP) {
-       if (termcap_reset != ABSENT_STRING) {
-           if (init_3string != ABSENT_STRING
+       if (VALID_STRING(termcap_reset)) {
+           if (VALID_STRING(init_3string)
                && !strcmp(init_3string, termcap_reset))
                DISCARD(init_3string);
 
-           if (reset_2string != ABSENT_STRING
+           if (VALID_STRING(reset_2string)
                && !strcmp(reset_2string, termcap_reset))
                DISCARD(reset_2string);
        }
@@ -1005,9 +1080,9 @@ fmt_entry(TERMTYPE2 *tterm,
                    set_attributes = save_sgr;
 
                    trimmed_sgr0 = _nc_trim_sgr0(tterm);
-                   if (strcmp(capability, trimmed_sgr0))
+                   if (strcmp(capability, trimmed_sgr0)) {
                        capability = trimmed_sgr0;
-                   else {
+                   else {
                        if (trimmed_sgr0 != exit_attribute_mode)
                            free(trimmed_sgr0);
                    }
@@ -1021,7 +1096,7 @@ fmt_entry(TERMTYPE2 *tterm,
        buffer[0] = '\0';
 
        if (predval != FAIL) {
-           if (capability != ABSENT_STRING
+           if (VALID_STRING(capability)
                && i + 1 > num_strings)
                num_strings = i + 1;
 
@@ -1031,8 +1106,7 @@ fmt_entry(TERMTYPE2 *tterm,
                WRAP_CONCAT;
            } else if (TcOutput()) {
                char *srccap = _nc_tic_expand(capability, TRUE, numbers);
-               int params = (((i < (int) SIZEOF(parametrized)) &&
-                              (i < STRCOUNT))
+               int params = ((i < (int) SIZEOF(parametrized))
                              ? parametrized[i]
                              : ((*srccap == 'k')
                                 ? 0
@@ -1044,28 +1118,45 @@ fmt_entry(TERMTYPE2 *tterm,
                        _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
                                    "%s=!!! %s WILL NOT CONVERT !!!",
                                    name, srccap);
+                       WRAP_CONCAT;
                    } else if (suppress_untranslatable) {
                        continue;
                    } else {
                        char *s = srccap, *d = buffer;
-                       _nc_SPRINTF(d, _nc_SLIMIT(sizeof(buffer)) "..%s=", name);
-                       d += strlen(d);
+                       int need = 3 + (int) strlen(name);
                        while ((*d = *s++) != 0) {
+                           if ((d - buffer + 2) >= (int) sizeof(buffer)) {
+                               fprintf(stderr,
+                                       "%s: value for %s is too long\n",
+                                       _nc_progname,
+                                       name);
+                               *d = '\0';
+                               break;
+                           }
                            if (*d == ':') {
                                *d++ = '\\';
                                *d = ':';
                            } else if (*d == '\\') {
-                               *++d = *s++;
+                               if ((*++d = *s++) == '\0')
+                                   break;
                            }
                            d++;
+                           *d = '\0';
                        }
+                       need += (int) (d - buffer);
+                       wrap_concat("..", need, w1ST | wERR);
+                       need -= 2;
+                       wrap_concat(name, need, wOFF | wERR);
+                       need -= (int) strlen(name);
+                       wrap_concat("=", need, w2ND | wERR);
+                       need -= 1;
+                       wrap_concat(buffer, need, wEND | wERR);
+                       outcount = TRUE;
                    }
                } else {
-                   _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
-                               "%s=%s", name, cv);
+                   wrap_concat3(name, "=", cv);
                }
                len += (int) strlen(capability) + 1;
-               WRAP_CONCAT;
            } else {
                char *src = _nc_tic_expand(capability,
                                           outform == F_TERMINFO, numbers);
@@ -1081,13 +1172,11 @@ fmt_entry(TERMTYPE2 *tterm,
                    strcpy_DYN(&tmpbuf, src);
                }
                len += (int) strlen(capability) + 1;
-               wrap_concat(tmpbuf.text);
-               outcount = TRUE;
+               WRAP_CONCAT1(tmpbuf.text);
            }
        }
        /* e.g., trimmed_sgr0 */
-       if (capability != ABSENT_STRING &&
-           capability != CANCELLED_STRING &&
+       if (VALID_STRING(capability) &&
            capability != tterm->Strings[i])
            free(capability);
     }
@@ -1258,7 +1347,8 @@ kill_labels(TERMTYPE2 *tterm, int target)
 
     for (n = 0; n <= 10; ++n) {
        _nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "lf%d", n);
-       if ((cap = find_string(tterm, name)) != ABSENT_STRING
+       cap = find_string(tterm, name);
+       if (VALID_STRING(cap)
            && kill_string(tterm, cap)) {
            target -= (int) (strlen(cap) + 5);
            ++result;
@@ -1283,7 +1373,8 @@ kill_fkeys(TERMTYPE2 *tterm, int target)
 
     for (n = 60; n >= 0; --n) {
        _nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "kf%d", n);
-       if ((cap = find_string(tterm, name)) != ABSENT_STRING
+       cap = find_string(tterm, name);
+       if (VALID_STRING(cap)
            && kill_string(tterm, cap)) {
            target -= (int) (strlen(cap) + 5);
            ++result;
@@ -1305,9 +1396,9 @@ one_one_mapping(const char *mapping)
 {
     bool result = TRUE;
 
-    if (mapping != ABSENT_STRING) {
+    if (VALID_STRING(mapping)) {
        int n = 0;
-       while (mapping[n] != '\0') {
+       while (mapping[n] != '\0' && mapping[n + 1] != '\0') {
            if (isLine(mapping[n]) &&
                mapping[n] != mapping[n + 1]) {
                result = FALSE;
@@ -1397,12 +1488,12 @@ dump_entry(TERMTYPE2 *tterm,
            char numbuf[80];
            if (quickdump & 1) {
                if (outbuf.used)
-                   wrap_concat("\n");
-               wrap_concat("hex:");
+                   wrap_concat1("\n");
+               wrap_concat1("hex:");
                for (n = 0; n < offset; ++n) {
                    _nc_SPRINTF(numbuf, _nc_SLIMIT(sizeof(numbuf))
                                "%02X", UChar(bigbuf[n]));
-                   wrap_concat(numbuf);
+                   wrap_concat1(numbuf);
                }
            }
            if (quickdump & 2) {
@@ -1410,24 +1501,24 @@ dump_entry(TERMTYPE2 *tterm,
                {0, 0};
                int value = 0;
                if (outbuf.used)
-                   wrap_concat("\n");
-               wrap_concat("b64:");
+                   wrap_concat1("\n");
+               wrap_concat1("b64:");
                for (n = 0; n < offset; ++n) {
                    encode_b64(numbuf, bigbuf, n, &value);
-                   wrap_concat(numbuf);
+                   wrap_concat1(numbuf);
                }
                switch (n % 3) {
                case 0:
                    break;
                case 1:
                    encode_b64(numbuf, padding, 1, &value);
-                   wrap_concat(numbuf);
-                   wrap_concat("==");
+                   wrap_concat1(numbuf);
+                   wrap_concat1("==");
                    break;
                case 2:
                    encode_b64(numbuf, padding, 1, &value);
-                   wrap_concat(numbuf);
-                   wrap_concat("=");
+                   wrap_concat1(numbuf);
+                   wrap_concat1("=");
                    break;
                }
            }
@@ -1524,7 +1615,8 @@ dump_entry(TERMTYPE2 *tterm,
                }
                if (len > critlen) {
                    (void) fprintf(stderr,
-                                  "warning: %s entry is %d bytes long\n",
+                                  "%s: %s entry is %d bytes long\n",
+                                  _nc_progname,
                                   _nc_first_name(tterm->term_names),
                                   len);
                    SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
@@ -1554,7 +1646,7 @@ dump_uses(const char *name, bool infodump)
        trim_trailing();
     _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
                "%s%s", infodump ? "use=" : "tc=", name);
-    wrap_concat(buffer);
+    wrap_concat1(buffer);
 }
 
 int