Commit bec2fff7 authored by Christian Persch's avatar Christian Persch

parser: Define a type for CSI parameters

This is in preparation to parse subparameters delimited by ':'.
parent e215bc51
......@@ -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)
......
......@@ -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");
......
/*
* 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;
}
......@@ -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;
}
......
......@@ -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
......@@ -270,6 +270,37 @@ feed_parser(vte_seq_builder& b,
return rv;
}
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)
{
......@@ -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);
......
/*
* 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;
......
......@@ -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;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment