From ece7c452afa8fa75638407b8da22b173a286af9d Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Mon, 3 Feb 2020 18:27:31 +0000 Subject: [PATCH] Accept OSC ... ST without an intermediate semicolon after the command number --- src/parser.c | 16 ++++++++++------ src/vterm_internal.h | 2 +- t/02parser.test | 8 ++++++++ t/run-test.pl | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/parser.c b/src/parser.c index 76d4a017..1f5389e8 100644 --- a/src/parser.c +++ b/src/parser.c @@ -116,12 +116,14 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) #define ENTER_STATE(st) do { vt->parser.state = st; string_start = NULL; } while(0) #define ENTER_NORMAL_STATE() ENTER_STATE(NORMAL) +#define IS_STRING_STATE() (vt->parser.state >= OSC_COMMAND) + for( ; pos < len; pos++) { unsigned char c = bytes[pos]; bool c1_allowed = !vt->mode.utf8; if(c == 0x00 || c == 0x7f) { // NUL, DEL - if(vt->parser.state >= OSC) { + if(IS_STRING_STATE()) { string_fragment(vt, string_start, bytes + pos - string_start, false); string_start = bytes + pos + 1; } @@ -134,20 +136,20 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) } else if(c == 0x1b) { // ESC vt->parser.intermedlen = 0; - if(vt->parser.state < OSC) + if(!IS_STRING_STATE()) vt->parser.state = NORMAL; vt->parser.in_esc = true; continue; } else if(c == 0x07 && // BEL, can stand for ST in OSC or DCS state - vt->parser.state >= OSC) { + IS_STRING_STATE()) { // fallthrough } else if(c < 0x20) { // other C0 - if(vt->parser.state >= OSC) + if(IS_STRING_STATE()) string_fragment(vt, string_start, bytes + pos - string_start, false); do_control(vt, c); - if(vt->parser.state >= OSC) + if(IS_STRING_STATE()) string_start = bytes + pos + 1; continue; } @@ -160,7 +162,7 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) // Always accept ESC \ == ST even in string mode if(!vt->parser.intermedlen && c >= 0x40 && c < 0x60 && - ((vt->parser.state < OSC || c == 0x5c))) { + ((!IS_STRING_STATE() || c == 0x5c))) { c += 0x40; c1_allowed = true; string_len -= 1; @@ -248,6 +250,7 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) /* else fallthrough */ string_start = bytes + pos; + string_len = 0; vt->parser.state = OSC; goto string_state; @@ -300,6 +303,7 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len) case 0x9d: // OSC vt->parser.v.osc.command = -1; vt->parser.string_initial = true; + string_start = bytes + pos + 1; ENTER_STATE(OSC_COMMAND); break; default: diff --git a/src/vterm_internal.h b/src/vterm_internal.h index abb92b6a..764597e3 100644 --- a/src/vterm_internal.h +++ b/src/vterm_internal.h @@ -170,9 +170,9 @@ struct VTerm CSI_LEADER, CSI_ARGS, CSI_INTERMED, - OSC_COMMAND, DCS_COMMAND, /* below here are the "string states" */ + OSC_COMMAND, OSC, DCS, } state; diff --git a/t/02parser.test b/t/02parser.test index 4a4a65bc..0a21b927 100644 --- a/t/02parser.test +++ b/t/02parser.test @@ -150,6 +150,14 @@ PUSH "def" PUSH "ghi\e\\" osc "ghi"] +!OSC BEL without semicolon +PUSH "\e]1234\x07" + osc [1234 ] + +!OSC ST without semicolon +PUSH "\e]1234\e\\" + osc [1234 ] + !Escape cancels OSC, starts Escape PUSH "\e]Something\e9" escape "9" diff --git a/t/run-test.pl b/t/run-test.pl index 0aec8ee4..4fb3fa88 100755 --- a/t/run-test.pl +++ b/t/run-test.pl @@ -112,7 +112,7 @@ sub do_line $initial //= ""; $initial .= ";" if $initial =~ m/\d+/; - $line = "$cmd $initial" . join( "", map sprintf("%02x", $_), unpack "C*", eval($data) ) . "$final"; + $line = "$cmd $initial" . join( "", map sprintf("%02x", $_), unpack "C*", length $data ? eval($data) : "" ) . "$final"; } elsif( $line =~ m/^(escape|dcs) (\[?)(.*?)(\]?)$/ ) { $line = "$1 $2" . join( "", map sprintf("%02x", $_), unpack "C*", eval($3) ) . "$4";