mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-10 08:20:59 -04:00
vt: split up action_param() to three separate functions
We’re already switching on the next VT input byte in the state machine; no need to if...else if in action_param() too. That is, split up action_param() into three: * action_param_new() * action_param_new_subparam() * action_param() This makes the code cleaner, and hopefully slightly faster. Next, to improve performance further, only check for (sub)parameter overflow in action_param_new() and action_param_subparam(). Add pointers to the VT struct that points to the currently active parameter and sub-parameter. When the number of parameters (or sub-parameters) overflow, warn, and then point the parameter pointer to a "dummy" value in the VT struct. This way, we don’t have to check anything in action_param().
This commit is contained in:
parent
690d78edfa
commit
d88bea5e22
2 changed files with 75 additions and 68 deletions
|
|
@ -180,8 +180,10 @@ struct grid {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vt_subparams {
|
struct vt_subparams {
|
||||||
unsigned value[16];
|
|
||||||
uint8_t idx;
|
uint8_t idx;
|
||||||
|
unsigned *cur;
|
||||||
|
unsigned value[16];
|
||||||
|
unsigned dummy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vt_param {
|
struct vt_param {
|
||||||
|
|
@ -197,8 +199,10 @@ struct vt {
|
||||||
#endif
|
#endif
|
||||||
char32_t utf8;
|
char32_t utf8;
|
||||||
struct {
|
struct {
|
||||||
struct vt_param v[16];
|
|
||||||
uint8_t idx;
|
uint8_t idx;
|
||||||
|
struct vt_param *cur;
|
||||||
|
struct vt_param v[16];
|
||||||
|
struct vt_param dummy;
|
||||||
} params;
|
} params;
|
||||||
|
|
||||||
uint32_t private; /* LSB=priv0, MSB=priv3 */
|
uint32_t private; /* LSB=priv0, MSB=priv3 */
|
||||||
|
|
|
||||||
135
vt.c
135
vt.c
|
|
@ -294,74 +294,31 @@ action_print(struct terminal *term, uint8_t c)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
action_param(struct terminal *term, uint8_t c)
|
action_param_lazy_init(struct terminal *term)
|
||||||
{
|
{
|
||||||
if (term->vt.params.idx == 0) {
|
if (term->vt.params.idx == 0) {
|
||||||
struct vt_param *param = &term->vt.params.v[0];
|
struct vt_param *param = &term->vt.params.v[0];
|
||||||
|
|
||||||
|
term->vt.params.cur = param;
|
||||||
param->value = 0;
|
param->value = 0;
|
||||||
param->sub.idx = 0;
|
param->sub.idx = 0;
|
||||||
|
param->sub.cur = NULL;
|
||||||
term->vt.params.idx = 1;
|
term->vt.params.idx = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xassert(term->vt.params.idx > 0);
|
static void
|
||||||
|
action_param_new(struct terminal *term, uint8_t c)
|
||||||
|
{
|
||||||
|
xassert(c == ';');
|
||||||
|
action_param_lazy_init(term);
|
||||||
|
|
||||||
const size_t max_params
|
const size_t max_params
|
||||||
= sizeof(term->vt.params.v) / sizeof(term->vt.params.v[0]);
|
= sizeof(term->vt.params.v) / sizeof(term->vt.params.v[0]);
|
||||||
const size_t max_sub_params
|
|
||||||
= sizeof(term->vt.params.v[0].sub.value) / sizeof(term->vt.params.v[0].sub.value[0]);
|
|
||||||
|
|
||||||
/* New parameter */
|
struct vt_param *param;
|
||||||
if (c == ';') {
|
|
||||||
if (unlikely(term->vt.params.idx >= max_params))
|
|
||||||
goto excess_params;
|
|
||||||
|
|
||||||
struct vt_param *param = &term->vt.params.v[term->vt.params.idx++];
|
if (unlikely(term->vt.params.idx >= max_params)) {
|
||||||
param->value = 0;
|
|
||||||
param->sub.idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* New sub-parameter */
|
|
||||||
else if (c == ':') {
|
|
||||||
if (unlikely(term->vt.params.idx - 1 >= max_params))
|
|
||||||
goto excess_params;
|
|
||||||
|
|
||||||
struct vt_param *param = &term->vt.params.v[term->vt.params.idx - 1];
|
|
||||||
if (unlikely(param->sub.idx >= max_sub_params))
|
|
||||||
goto excess_sub_params;
|
|
||||||
|
|
||||||
param->sub.value[param->sub.idx++] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* New digit for current parameter/sub-parameter */
|
|
||||||
else {
|
|
||||||
if (unlikely(term->vt.params.idx - 1 >= max_params))
|
|
||||||
goto excess_params;
|
|
||||||
|
|
||||||
struct vt_param *param = &term->vt.params.v[term->vt.params.idx - 1];
|
|
||||||
unsigned *value;
|
|
||||||
|
|
||||||
if (param->sub.idx > 0) {
|
|
||||||
if (unlikely(param->sub.idx - 1 >= max_sub_params))
|
|
||||||
goto excess_sub_params;
|
|
||||||
value = ¶m->sub.value[param->sub.idx - 1];
|
|
||||||
} else
|
|
||||||
value = ¶m->value;
|
|
||||||
|
|
||||||
*value *= 10;
|
|
||||||
*value += c - '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_DEBUG)
|
|
||||||
/* The rest of the code assumes 'idx' *never* points outside the array */
|
|
||||||
xassert(term->vt.params.idx <= max_params);
|
|
||||||
for (size_t i = 0; i < term->vt.params.idx; i++)
|
|
||||||
xassert(term->vt.params.v[i].sub.idx <= max_sub_params);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
excess_params:
|
|
||||||
{
|
|
||||||
static bool have_warned = false;
|
static bool have_warned = false;
|
||||||
if (!have_warned) {
|
if (!have_warned) {
|
||||||
have_warned = true;
|
have_warned = true;
|
||||||
|
|
@ -370,11 +327,29 @@ excess_params:
|
||||||
"(will not warn again)",
|
"(will not warn again)",
|
||||||
sizeof(term->vt.params.v) / sizeof(term->vt.params.v[0]));
|
sizeof(term->vt.params.v) / sizeof(term->vt.params.v[0]));
|
||||||
}
|
}
|
||||||
}
|
param = &term->vt.params.dummy;
|
||||||
return;
|
} else
|
||||||
|
param = &term->vt.params.v[term->vt.params.idx++];
|
||||||
|
|
||||||
excess_sub_params:
|
term->vt.params.cur = param;
|
||||||
{
|
param->value = 0;
|
||||||
|
param->sub.idx = 0;
|
||||||
|
param->sub.cur = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
action_param_new_subparam(struct terminal *term, uint8_t c)
|
||||||
|
{
|
||||||
|
xassert(c == ':');
|
||||||
|
action_param_lazy_init(term);
|
||||||
|
|
||||||
|
const size_t max_sub_params
|
||||||
|
= sizeof(term->vt.params.v[0].sub.value) / sizeof(term->vt.params.v[0].sub.value[0]);
|
||||||
|
|
||||||
|
struct vt_param *param = term->vt.params.cur;
|
||||||
|
unsigned *sub_param_value;
|
||||||
|
|
||||||
|
if (unlikely(param->sub.idx >= max_sub_params)) {
|
||||||
static bool have_warned = false;
|
static bool have_warned = false;
|
||||||
if (!have_warned) {
|
if (!have_warned) {
|
||||||
have_warned = true;
|
have_warned = true;
|
||||||
|
|
@ -383,8 +358,33 @@ excess_sub_params:
|
||||||
"(will not warn again)",
|
"(will not warn again)",
|
||||||
sizeof(term->vt.params.v[0].sub.value) / sizeof(term->vt.params.v[0].sub.value[0]));
|
sizeof(term->vt.params.v[0].sub.value) / sizeof(term->vt.params.v[0].sub.value[0]));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return;
|
sub_param_value = ¶m->sub.dummy;
|
||||||
|
} else
|
||||||
|
sub_param_value = ¶m->sub.value[param->sub.idx++];
|
||||||
|
|
||||||
|
param->sub.cur = sub_param_value;
|
||||||
|
*sub_param_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
action_param(struct terminal *term, uint8_t c)
|
||||||
|
{
|
||||||
|
action_param_lazy_init(term);
|
||||||
|
xassert(term->vt.params.cur != NULL);
|
||||||
|
|
||||||
|
struct vt_param *param = term->vt.params.cur;
|
||||||
|
unsigned *value;
|
||||||
|
|
||||||
|
if (unlikely(param->sub.cur != NULL))
|
||||||
|
value = param->sub.cur;
|
||||||
|
else
|
||||||
|
value = ¶m->value;
|
||||||
|
|
||||||
|
unsigned v = *value;
|
||||||
|
v *= 10;
|
||||||
|
v += c - '0';
|
||||||
|
*value = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1024,7 +1024,9 @@ state_csi_entry_switch(struct terminal *term, uint8_t data)
|
||||||
|
|
||||||
case 0x20 ... 0x2f: action_collect(term, data); return STATE_CSI_INTERMEDIATE;
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_CSI_INTERMEDIATE;
|
||||||
case 0x30 ... 0x39: action_param(term, data); return STATE_CSI_PARAM;
|
case 0x30 ... 0x39: action_param(term, data); return STATE_CSI_PARAM;
|
||||||
case 0x3a ... 0x3b: action_param(term, data); return STATE_CSI_PARAM;
|
case 0x3a: action_param_new_subparam(term, data); return STATE_CSI_PARAM;
|
||||||
|
case 0x3b: action_param_new(term, data); return STATE_CSI_PARAM;
|
||||||
|
|
||||||
case 0x3c ... 0x3f: action_collect(term, data); return STATE_CSI_PARAM;
|
case 0x3c ... 0x3f: action_collect(term, data); return STATE_CSI_PARAM;
|
||||||
case 0x40 ... 0x7e: action_csi_dispatch(term, data); return STATE_GROUND;
|
case 0x40 ... 0x7e: action_csi_dispatch(term, data); return STATE_GROUND;
|
||||||
case 0x7f: action_ignore(term); return STATE_CSI_ENTRY;
|
case 0x7f: action_ignore(term); return STATE_CSI_ENTRY;
|
||||||
|
|
@ -1044,8 +1046,9 @@ state_csi_param_switch(struct terminal *term, uint8_t data)
|
||||||
|
|
||||||
case 0x20 ... 0x2f: action_collect(term, data); return STATE_CSI_INTERMEDIATE;
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_CSI_INTERMEDIATE;
|
||||||
|
|
||||||
case 0x30 ... 0x39:
|
case 0x30 ... 0x39: action_param(term, data); return STATE_CSI_PARAM;
|
||||||
case 0x3a ... 0x3b: action_param(term, data); return STATE_CSI_PARAM;
|
case 0x3a: action_param_new_subparam(term, data); return STATE_CSI_PARAM;
|
||||||
|
case 0x3b: action_param_new(term, data); return STATE_CSI_PARAM;
|
||||||
|
|
||||||
case 0x3c ... 0x3f: return STATE_CSI_IGNORE;
|
case 0x3c ... 0x3f: return STATE_CSI_IGNORE;
|
||||||
case 0x40 ... 0x7e: action_csi_dispatch(term, data); return STATE_GROUND;
|
case 0x40 ... 0x7e: action_csi_dispatch(term, data); return STATE_GROUND;
|
||||||
|
|
@ -1126,7 +1129,7 @@ state_dcs_entry_switch(struct terminal *term, uint8_t data)
|
||||||
case 0x20 ... 0x2f: action_collect(term, data); return STATE_DCS_INTERMEDIATE;
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_DCS_INTERMEDIATE;
|
||||||
case 0x30 ... 0x39: action_param(term, data); return STATE_DCS_PARAM;
|
case 0x30 ... 0x39: action_param(term, data); return STATE_DCS_PARAM;
|
||||||
case 0x3a: return STATE_DCS_IGNORE;
|
case 0x3a: return STATE_DCS_IGNORE;
|
||||||
case 0x3b: action_param(term, data); return STATE_DCS_PARAM;
|
case 0x3b: action_param_new(term, data); return STATE_DCS_PARAM;
|
||||||
case 0x3c ... 0x3f: action_collect(term, data); return STATE_DCS_PARAM;
|
case 0x3c ... 0x3f: action_collect(term, data); return STATE_DCS_PARAM;
|
||||||
case 0x40 ... 0x7e: action_hook(term, data); return STATE_DCS_PASSTHROUGH;
|
case 0x40 ... 0x7e: action_hook(term, data); return STATE_DCS_PASSTHROUGH;
|
||||||
case 0x7f: action_ignore(term); return STATE_DCS_ENTRY;
|
case 0x7f: action_ignore(term); return STATE_DCS_ENTRY;
|
||||||
|
|
@ -1147,7 +1150,7 @@ state_dcs_param_switch(struct terminal *term, uint8_t data)
|
||||||
case 0x20 ... 0x2f: action_collect(term, data); return STATE_DCS_INTERMEDIATE;
|
case 0x20 ... 0x2f: action_collect(term, data); return STATE_DCS_INTERMEDIATE;
|
||||||
case 0x30 ... 0x39: action_param(term, data); return STATE_DCS_PARAM;
|
case 0x30 ... 0x39: action_param(term, data); return STATE_DCS_PARAM;
|
||||||
case 0x3a: return STATE_DCS_IGNORE;
|
case 0x3a: return STATE_DCS_IGNORE;
|
||||||
case 0x3b: action_param(term, data); return STATE_DCS_PARAM;
|
case 0x3b: action_param_new(term, data); return STATE_DCS_PARAM;
|
||||||
case 0x3c ... 0x3f: return STATE_DCS_IGNORE;
|
case 0x3c ... 0x3f: return STATE_DCS_IGNORE;
|
||||||
case 0x40 ... 0x7e: action_hook(term, data); return STATE_DCS_PASSTHROUGH;
|
case 0x40 ... 0x7e: action_hook(term, data); return STATE_DCS_PASSTHROUGH;
|
||||||
case 0x7f: action_ignore(term); return STATE_DCS_PARAM;
|
case 0x7f: action_ignore(term); return STATE_DCS_PARAM;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue