[vte] parser: Define a type for CSI parameters



commit bec2fff7f9431f9765f165c3a54b7d2fc19542a9
Author: Christian Persch <chpe src gnome org>
Date:   Tue Mar 27 19:40:12 2018 +0200

    parser: Define a type for CSI parameters
    
    This is in preparation to parse subparameters delimited by ':'.

 src/Makefile.am    |    2 +
 src/interpret.cc   |    2 +-
 src/parser-arg.hh  |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/parser-glue.hh |    4 +-
 src/parser-test.cc |   62 +++++++++++++++++++++++++++++++++++++++------
 src/parser.cc      |   33 +++++++++---------------
 src/parser.hh      |    4 ++-
 7 files changed, 145 insertions(+), 33 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index ef8e44b..64ff262 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,6 +57,7 @@ libvte_@VTE_API_MAJOR_VERSION@_@VTE_API_MINOR_VERSION@_la_SOURCES = \
        keymap.h \
        parser.cc \
        parser.hh \
+       parser-arg.hh \
        parser-cmd.hh \
        parser-glue.hh \
        pty.cc \
@@ -306,6 +307,7 @@ test_parser_SOURCES = \
        parser-test.cc \
        parser.cc \
        parser.hh \
+       parser-arg.hh \
        parser-cmd.hh \
        parser-glue.hh \
        $(NULL)
diff --git a/src/interpret.cc b/src/interpret.cc
index 3c4fd64..e2d6f86 100644
--- a/src/interpret.cc
+++ b/src/interpret.cc
@@ -114,7 +114,7 @@ static  void print_seq(const struct vte_seq *seq)
                         for (unsigned int i = 0; i < seq->n_args; i++) {
                                 if (i > 0)
                                         g_print(";");
-                        g_print("%d", seq->args[i]);
+                                g_print("%d", vte_seq_arg_value(seq->args[i]));
                         }
                 }
                 g_print("\n");
diff --git a/src/parser-arg.hh b/src/parser-arg.hh
new file mode 100644
index 0000000..5c5d011
--- /dev/null
+++ b/src/parser-arg.hh
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2015 David Herrmann <dh herrmann gmail com>
+ * Copyright © 2018 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <assert.h>
+
+typedef int vte_seq_arg_t;
+
+#define VTE_SEQ_ARG_INIT_DEFAULT (-1)
+#define VTE_SEQ_ARG_INIT(value) (value)
+
+static inline void vte_seq_arg_push(vte_seq_arg_t* arg,
+                                    uint32_t c)
+{
+        auto value = *arg;
+
+        if (value < 0)
+                value = 0;
+        value = value * 10 + (c - '0');
+
+        /*
+         * VT510 tells us to clamp all values to [0, 9999], however, it
+         * also allows commands with values up to 2^15-1. We simply use
+         * 2^16 as maximum here to be compatible to all commands, but
+         * avoid overflows in any calculations.
+         */
+        if (value > 0xffff)
+                value = 0xffff;
+
+        *arg = value;
+}
+
+static inline void vte_seq_arg_finish(vte_seq_arg_t* arg)
+{
+}
+
+static inline bool vte_seq_arg_started(vte_seq_arg_t arg)
+{
+        return arg >= 0;
+}
+
+static inline bool vte_seq_arg_finished(vte_seq_arg_t arg)
+{
+        return arg >= 0;
+}
+
+static inline bool vte_seq_arg_default(vte_seq_arg_t arg)
+{
+        return arg == -1;
+}
+
+static inline int vte_seq_arg_value(vte_seq_arg_t arg)
+{
+        return arg;
+}
diff --git a/src/parser-glue.hh b/src/parser-glue.hh
index 7614d46..e730a23 100644
--- a/src/parser-glue.hh
+++ b/src/parser-glue.hh
@@ -46,7 +46,7 @@ public:
 
         inline int operator[](int position) const
         {
-                return G_LIKELY(position < (int)size()) ? m_seq->args[position] : -1;
+                return G_LIKELY(position < (int)size()) ? vte_seq_arg_value(m_seq->args[position]) : -1;
         }
 
         inline bool has_number_at_unchecked(unsigned int position) const
@@ -56,7 +56,7 @@ public:
 
         inline bool number_at_unchecked(unsigned int position, number& v) const
         {
-                v = m_seq->args[position];
+                v = vte_seq_arg_value(m_seq->args[position]);
                 return true;
         }
 
diff --git a/src/parser-test.cc b/src/parser-test.cc
index 6cd2e65..d8da13b 100644
--- a/src/parser-test.cc
+++ b/src/parser-test.cc
@@ -115,7 +115,7 @@ print_seq(const struct vte_seq *seq)
                         for (unsigned int i = 0; i < seq->n_args; i++) {
                                 if (i > 0)
                                         g_print(";");
-                        g_print("%d", seq->args[i]);
+                                g_print("%d", vte_seq_arg_value(seq->args[i]));
                         }
                 }
                 g_print("\n");
@@ -147,7 +147,7 @@ public:
                 m_seq.intermediates = flags;
         }
 
-        void set_params(int params[16])
+        void set_params(vte_seq_arg_t params[16])
         {
                 memcpy(&m_seq.args, params, 16*sizeof(params[0]));
         }
@@ -248,7 +248,7 @@ vte_seq_builder::assert_equal_full(struct vte_seq* seq)
                 g_assert_cmpuint(m_seq.args[m_seq.n_args - 1], ==, -1);
         }
         for (unsigned int n = 0; n < seq->n_args; n++)
-                g_assert_cmpint(std::min(m_seq.args[n], 0xffff), ==, seq->args[n]);
+                g_assert_cmpint(std::min(m_seq.args[n], 0xffff), ==, vte_seq_arg_value(seq->args[n]));
 }
 
 static int
@@ -271,6 +271,37 @@ feed_parser(vte_seq_builder& b,
 }
 
 static void
+test_seq_arg(void)
+{
+        /* Basic test */
+        vte_seq_arg_t arg = VTE_SEQ_ARG_INIT_DEFAULT;
+        g_assert_false(vte_seq_arg_started(arg));
+        g_assert_false(vte_seq_arg_finished(arg));
+        g_assert_true(vte_seq_arg_default(arg));
+
+        vte_seq_arg_push(&arg, '1');
+        vte_seq_arg_push(&arg, '2');
+        vte_seq_arg_push(&arg, '3');
+        vte_seq_arg_finish(&arg);
+
+        g_assert_true(vte_seq_arg_finished(arg));
+        g_assert_cmpint(vte_seq_arg_value(arg), ==, 123);
+        g_assert_false(vte_seq_arg_default(arg));
+
+        /* Test max value */
+        arg = VTE_SEQ_ARG_INIT_DEFAULT;
+        vte_seq_arg_push(&arg, '6');
+        vte_seq_arg_push(&arg, '5');
+        vte_seq_arg_push(&arg, '5');
+        vte_seq_arg_push(&arg, '3');
+        vte_seq_arg_push(&arg, '6');
+        vte_seq_arg_finish(&arg);
+
+        g_assert_true(vte_seq_arg_finished(arg));
+        g_assert_cmpint(vte_seq_arg_value(arg), ==, 65535);
+}
+
+static void
 test_seq_control(void)
 {
         static struct {
@@ -446,7 +477,7 @@ test_seq_esc_Fpes(void)
 static void
 test_seq_csi(uint32_t f,
              uint32_t p,
-             int params[16],
+             vte_seq_arg_t params[16],
              uint32_t i[4],
              unsigned int ni)
 {
@@ -477,7 +508,7 @@ test_seq_csi(uint32_t f,
 
 static void
 test_seq_csi(uint32_t p,
-             int params[16])
+             vte_seq_arg_t params[16])
 {
         uint32_t i[4];
         for (uint32_t f = 0x30; f < 0x7f; f++) {
@@ -492,7 +523,7 @@ test_seq_csi(uint32_t p,
 }
 
 static void
-test_seq_csi(int params[16])
+test_seq_csi(vte_seq_arg_t params[16])
 {
         test_seq_csi(0, params);
         for (uint32_t p = 0x3c; p <= 0x3f; p++)
@@ -510,10 +541,24 @@ test_seq_csi(void)
          * There could be any number of extra params bytes, but we only test up to 1.
          * CSI can be either the C1 control itself, or ESC [
          */
-        int params1[16]{ -1, 0, 1, 9, 10, 99, 100, 999, 1000, 9999, 10000, 65534, 65535, 65536, -1, -1 };
+        vte_seq_arg_t params1[16]{ VTE_SEQ_ARG_INIT(-1), VTE_SEQ_ARG_INIT(0),
+                        VTE_SEQ_ARG_INIT(1), VTE_SEQ_ARG_INIT(9),
+                        VTE_SEQ_ARG_INIT(10), VTE_SEQ_ARG_INIT(99),
+                        VTE_SEQ_ARG_INIT(100), VTE_SEQ_ARG_INIT(999),
+                        VTE_SEQ_ARG_INIT(1000), VTE_SEQ_ARG_INIT(9999),
+                        VTE_SEQ_ARG_INIT(10000), VTE_SEQ_ARG_INIT(65534),
+                        VTE_SEQ_ARG_INIT(65535), VTE_SEQ_ARG_INIT(65536),
+                        VTE_SEQ_ARG_INIT(-1), VTE_SEQ_ARG_INIT(-1) };
         test_seq_csi(params1);
 
-        int params2[16]{ 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1 };
+        vte_seq_arg_t params2[16]{ VTE_SEQ_ARG_INIT(1), VTE_SEQ_ARG_INIT(-1),
+                        VTE_SEQ_ARG_INIT(-1), VTE_SEQ_ARG_INIT(-1),
+                        VTE_SEQ_ARG_INIT(1), VTE_SEQ_ARG_INIT(-1),
+                        VTE_SEQ_ARG_INIT(1), VTE_SEQ_ARG_INIT(1),
+                        VTE_SEQ_ARG_INIT(1), VTE_SEQ_ARG_INIT(-1),
+                        VTE_SEQ_ARG_INIT(-1), VTE_SEQ_ARG_INIT(-1),
+                        VTE_SEQ_ARG_INIT(-1), VTE_SEQ_ARG_INIT(1),
+                        VTE_SEQ_ARG_INIT(1), VTE_SEQ_ARG_INIT(1) };
         test_seq_csi(params2);
 }
 
@@ -526,6 +571,7 @@ main(int argc,
         if (vte_parser_new(&parser) < 0)
                 return 1;
 
+        g_test_add_func("/vte/parser/sequences/arg", test_seq_arg);
         g_test_add_func("/vte/parser/sequences/control", test_seq_control);
         g_test_add_func("/vte/parser/sequences/escape/invalid", test_seq_esc_invalid);
         g_test_add_func("/vte/parser/sequences/escape/nF", test_seq_esc_nF);
diff --git a/src/parser.cc b/src/parser.cc
index b727219..9dd9b23 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2015 David Herrmann <dh herrmann gmail com>
+ * Copyright © 2017, 2018 Christian Persch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -788,7 +789,7 @@ static unsigned int vte_parse_host_csi(const struct vte_seq *seq)
                 } else if (flags == VTE_SEQ_FLAG_WHAT) {
                         /* DECRQUPSS */
                         return VTE_CMD_DECRQUPSS;
-                } else if (seq->args[0] == 1 && flags == VTE_SEQ_FLAG_CASH) {
+                } else if (vte_seq_arg_value(seq->args[0]) == 1 && flags == VTE_SEQ_FLAG_CASH) {
                         /* DECRQTSR */
                         return VTE_CMD_DECRQTSR;
                 } else if (flags == VTE_SEQ_FLAG_MULT) {
@@ -814,7 +815,7 @@ static unsigned int vte_parse_host_csi(const struct vte_seq *seq)
                         return VTE_CMD_DECRPKT;
                 break;
         case 'W':
-                if (seq->args[0] == 5 && flags == VTE_SEQ_FLAG_WHAT) {
+                if (vte_seq_arg_value(seq->args[0]) == 5 && flags == VTE_SEQ_FLAG_WHAT) {
                         /* DECST8C */
                         return VTE_CMD_DECST8C;
                 }
@@ -1007,7 +1008,7 @@ static inline void parser_clear(struct vte_parser *parser)
         parser->seq.charset = VTE_CHARSET_NONE;
         parser->seq.n_args = 0;
         for (i = 0; i < VTE_PARSER_ARG_MAX; ++i)
-                parser->seq.args[i] = -1;
+                parser->seq.args[i] = VTE_SEQ_ARG_INIT_DEFAULT;
 
         parser->seq.n_st = 0;
         parser->seq.st[0] = 0;
@@ -1064,8 +1065,10 @@ static void parser_collect(struct vte_parser *parser, uint32_t raw)
 static void parser_param(struct vte_parser *parser, uint32_t raw)
 {
         if (raw == ';') {
-                if (parser->seq.n_args < VTE_PARSER_ARG_MAX)
+                if (parser->seq.n_args < VTE_PARSER_ARG_MAX) {
+                        vte_seq_arg_finish(&parser->seq.args[parser->seq.n_args]);
                         ++parser->seq.n_args;
+                }
 
                 return;
         }
@@ -1074,21 +1077,7 @@ static void parser_param(struct vte_parser *parser, uint32_t raw)
                 return;
 
         if (raw >= '0' && raw <= '9') {
-                auto value = parser->seq.args[parser->seq.n_args];
-                if (value < 0)
-                        value = 0;
-                value = value * 10 + raw - '0';
-
-                /*
-                 * VT510 tells us to clamp all values to [0, 9999], however, it
-                 * also allows commands with values up to 2^15-1. We simply use
-                 * 2^16 as maximum here to be compatible to all commands, but
-                 * avoid overflows in any calculations.
-                 */
-                if (value > 0xffff)
-                        value = 0xffff;
-
-                parser->seq.args[parser->seq.n_args] = value;
+                vte_seq_arg_push(&parser->seq.args[parser->seq.n_args], raw);
         }
 }
 
@@ -1099,7 +1088,7 @@ static int parser_esc(struct vte_parser *parser, uint32_t raw)
         parser->seq.terminator = raw;
         parser->seq.charset = VTE_CHARSET_NONE;
         parser->seq.command = vte_parse_host_escape(&parser->seq,
-                                                       &parser->seq.charset);
+                                                    &parser->seq.charset);
 
         return parser->seq.type;
 }
@@ -1111,8 +1100,10 @@ static int parser_csi(struct vte_parser *parser, uint32_t raw)
 
         if (parser->seq.n_args < VTE_PARSER_ARG_MAX) {
                 if (parser->seq.n_args > 0 ||
-                    parser->seq.args[parser->seq.n_args] >= 0)
+                    vte_seq_arg_started(parser->seq.args[parser->seq.n_args])) {
+                        vte_seq_arg_finish(&parser->seq.args[parser->seq.n_args]);
                         ++parser->seq.n_args;
+                }
         }
 
         parser->seq.type = VTE_SEQ_CSI;
diff --git a/src/parser.hh b/src/parser.hh
index ed357ba..8718a18 100644
--- a/src/parser.hh
+++ b/src/parser.hh
@@ -20,6 +20,8 @@
 #include <cstdint>
 #include <cstdio>
 
+#include "parser-arg.hh"
+
 struct vte_parser;
 struct vte_seq;
 struct vte_utf8;
@@ -181,7 +183,7 @@ struct vte_seq {
         unsigned int intermediates;
         unsigned int charset;
         unsigned int n_args;
-        int args[VTE_PARSER_ARG_MAX];
+        vte_seq_arg_t args[VTE_PARSER_ARG_MAX];
         unsigned int n_st;
         char *st;
 };


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]