]> git.neil.brown.name Git - edlib.git/commitdiff
display-ncurses: Improve attr parsing
authorNeilBrown <neil@brown.name>
Sat, 19 Aug 2023 22:32:30 +0000 (08:32 +1000)
committerNeilBrown <neil@brown.name>
Sun, 20 Aug 2023 22:46:11 +0000 (08:46 +1000)
Move the attr parsing code from lib-renderline into core-misc.c and
use it in display-ncurses to avoid using a fixed-size char array that we
never test for overflow.

Signed-off-by: NeilBrown <neil@brown.name>
core-misc.c
display-ncurses.c
lib-renderline.c
misc.h

index 28a2ebe5e9435b3126166c92f1be80dd0a58b6c6..6475aadf67666526f0dfb8b980b9b0bb41ee084a 100644 (file)
@@ -549,3 +549,97 @@ bool debugger_is_present(void)
        }
        return _debugger_present;
 }
+
+/* attr parsing */
+const char *afind_val(const char **cp safe, const char *end)
+{
+       const char *c = *cp;
+       const char *ret;
+
+       if (!c)
+               return NULL;
+       if (!end)
+               end = c + strlen(c);
+       while (c < end && *c != ':' && *c != ',')
+               c++;
+       if (c == end) {
+               *cp = NULL;
+               return NULL;
+       }
+       if (*c == ',') {
+               while (*c == ',' && c < end)
+                       c++;
+               if (c == end) {
+                       *cp = NULL;
+                       return NULL;
+               }
+               *cp = c;
+               return NULL;
+       }
+       c += 1;
+       ret = c;
+       while (c < end && *c != ',')
+               c++;
+       while (c < end && *c == ',')
+               c++;
+       if (c == end)
+               c = NULL;
+       *cp = c;
+       return ret;
+}
+
+char *aupdate(char **cp safe, const char *v)
+{
+       /* duplicate value at v and store in *cp, freeing what is there
+        * first
+        */
+       const char *end = v;
+
+       while (end && *end != ',' && *end >= ' ')
+               end += 1;
+
+       free(*cp);
+       if (v)
+               *cp = strndup(v, end-v);
+       else
+               *cp = NULL;
+       return *cp;
+}
+
+bool amatch(const char *a safe, const char *m safe)
+{
+       while (*a && *a == *m) {
+               a += 1;
+               m += 1;
+       }
+       if (*m)
+               /* Didn't match all of m */
+               return False;
+       if (*a != ':' && *a != ',' && *a >= ' ')
+               /* Didn't match all of a */
+               return False;
+       return True;
+}
+
+bool aprefix(const char *a safe, const char *m safe)
+{
+       while (*a && *a == *m) {
+               a += 1;
+               m += 1;
+       }
+       if (*m)
+               /* Didn't match all of m */
+               return False;
+       return True;
+}
+
+long anum(const char *v safe)
+{
+       char *end = NULL;
+       long ret = strtol(v, &end, 10);
+       if (end == v || !end ||
+           (*end != ',' && *end >= ' '))
+               /* Not a valid number - use zero */
+               return 0;
+       return ret;
+}
index 8e7436f415ce12ace8bda234b238fd74b63a4cc4..0b1eda0784b1d5f785aa346d0592ef44586d6d2c 100644 (file)
@@ -804,8 +804,8 @@ static int cvt_attrs(struct pane *p safe, struct pane *home safe,
 {
        struct display_data *dd = &home->data;
        int attr = 0;
-       char tmp[40];
-       const char *a;
+       const char *a, *v;
+       char *col = NULL;
        PANEL *pan = NULL;
        int fg = COLOR_BLACK;
        int bg = COLOR_WHITE+8;
@@ -825,39 +825,35 @@ static int cvt_attrs(struct pane *p safe, struct pane *home safe,
                if (dbg >= 0)
                        bg = dbg;
        }
-       a = attrs;
-       while (a && *a) {
-               const char *c;
-               if (*a == ',') {
-                       a++;
-                       continue;
-               }
-               c = strchr(a, ',');
-               if (!c)
-                       c = a+strlen(a);
-               strncpy(tmp, a, c-a);
-               tmp[c-a] = 0;
-               if (strcmp(tmp, "inverse")==0) attr |= A_STANDOUT;
-               else if (strcmp(tmp, "noinverse")==0) attr &= ~A_STANDOUT;
-               else if (strcmp(tmp, "bold")==0) attr |= A_BOLD;
-               else if (strcmp(tmp, "nobold")==0) attr &= ~A_BOLD;
-               else if (strcmp(tmp, "underline")==0) attr |= A_UNDERLINE;
-               else if (strcmp(tmp, "nounderline")==0) attr &= ~A_UNDERLINE;
-               else if (strstarts(tmp, "fg:")) {
+
+       foreach_attr(a, v, attrs, NULL) {
+               if (amatch(a, "inverse"))
+                       attr |= A_STANDOUT;
+               else if (amatch(a, "noinverse"))
+                       attr &= ~A_STANDOUT;
+               else if (amatch(a, "bold"))
+                       attr |= A_BOLD;
+               else if (amatch(a, "nobold"))
+                       attr &= ~A_BOLD;
+               else if (amatch(a, "underline"))
+                       attr |= A_UNDERLINE;
+               else if (amatch(a, "nounderline"))
+                       attr &= ~A_UNDERLINE;
+               else if (amatch(a, "fg") && v) {
                        struct call_return cr =
                                call_ret(all, "colour:map", home,
-                                        0, NULL, tmp+3);
+                                        0, NULL, aupdate(&col, v));
                        int rgb[3] = {cr.i, cr.i2, cr.x};
                        fg = find_col(dd, rgb);
-               } else if (strstarts(tmp, "bg:")) {
+               } else if (amatch(a, "bg") && v) {
                        struct call_return cr =
                                call_ret(all, "colour:map", home,
-                                        0, NULL, tmp+3);
+                                        0, NULL, aupdate(&col, v));
                        int rgb[3] = {cr.i, cr.i2, cr.x};
                        bg = find_col(dd, rgb);
                }
-               a = c;
        }
+       free(col);
        if (fg != COLOR_BLACK || bg != COLOR_WHITE+8)
                *pairp = to_pair(dd, fg, bg);
        return attr;
index 436f7491ca41b4ef9d1f5d8f04cc22a3f90d81a6..1708c1b08129a03274f618b17ca3747df694d3f2 100644 (file)
@@ -141,106 +141,6 @@ struct rline_data {
 };
 #include "core-pane.h"
 
-/* Sequentially set _attr to the an attr name, and _val to
- * either the val (following ":") or NULL.
- * _attr is valid up to : or , or < space and _val is valid up to , or <space
- * _c is the start which will be updates, and _end is the end which
- * must point to , or nul or a control char
- */
-#define foreach_attr(_attr, _val, _c, _end)                    \
-       for (_attr = _c, _val = find_val(&_c, _end);            \
-            _attr;                                             \
-            _attr = _c, _val = find_val(&_c, _end))
-static const char *find_val(const char **cp safe, const char *end safe)
-{
-       const char *c = *cp;
-       const char *ret;
-
-       if (!c)
-               return NULL;
-       while (c < end && *c != ':' && *c != ',')
-               c++;
-       if (c == end) {
-               *cp = NULL;
-               return NULL;
-       }
-       if (*c == ',') {
-               while (*c == ',' && c < end)
-                       c++;
-               if (c == end) {
-                       *cp = NULL;
-                       return NULL;
-               }
-               *cp = c;
-               return NULL;
-       }
-       c += 1;
-       ret = c;
-       while (c < end && *c != ',')
-               c++;
-       while (c < end && *c == ',')
-               c++;
-       if (c == end)
-               c = NULL;
-       *cp = c;
-       return ret;
-}
-
-static bool amatch(const char *a safe, const char *m safe)
-{
-       while (*a && *a == *m) {
-               a += 1;
-               m += 1;
-       }
-       if (*m)
-               /* Didn't match all of m */
-               return False;
-       if (*a != ':' && *a != ',' && *a >= ' ')
-               /* Didn't match all of a */
-               return False;
-       return True;
-}
-
-static bool aprefix(const char *a safe, const char *m safe)
-{
-       while (*a && *a == *m) {
-               a += 1;
-               m += 1;
-       }
-       if (*m)
-               /* Didn't match all of m */
-               return False;
-       return True;
-}
-
-static long anum(const char *v safe)
-{
-       char *end = NULL;
-       long ret = strtol(v, &end, 10);
-       if (end == v || !end ||
-           (*end != ',' && *end >= ' '))
-               /* Not a valid number - use zero */
-               return 0;
-       return ret;
-}
-
-static void aupdate(char **cp safe, const char *v)
-{
-       /* duplicate value at v and store in *cp, freeing what is there
-        * first
-        */
-       const char *end = v;
-
-       while (end && *end != ',' && *end >= ' ')
-               end += 1;
-
-       free(*cp);
-       if (v)
-               *cp = strndup(v, end-v);
-       else
-               *cp = NULL;
-}
-
 static void aappend(struct buf *b safe, char const *a safe)
 {
        const char *end = a;
diff --git a/misc.h b/misc.h
index 848f30d54566b73261e8ec9ed8b74fbb1460d0cd..83bf6550756741615a43933ef3e742e34d416f11 100644 (file)
--- a/misc.h
+++ b/misc.h
@@ -150,4 +150,22 @@ void do_unalloc(struct mempool *pool safe, const void *obj, int size);
 #define unalloc_str_safe(var, pool)                                            \
        unalloc_buf_safe(var, strlen(var)+1, pool)
 
+/* attrs parsing */
+
+/* Sequentially set _attr to the an attr name, and _val to
+ * either the val (following ":") or NULL.
+ * _attr is valid up to : or , or < space and _val is valid up to , or <space
+ * _c is the start which will be updates, and _end is the end which
+ * must point to , or nul or a control char
+ */
+#define foreach_attr(_attr, _val, _c, _end)                    \
+       for (_attr = _c, _val = afind_val(&_c, _end);           \
+            _attr;                                             \
+            _attr = _c, _val = afind_val(&_c, _end))
+const char *afind_val(const char **cp safe, const char *end);
+char *aupdate(char **cp safe, const char *v);
+bool amatch(const char *a safe, const char *m safe);
+bool aprefix(const char *a safe, const char *m safe);
+long anum(const char *v safe);
+
 #endif /* EDLIB_MISC */