Skip to content

Commit

Permalink
Accept OSC ... ST without an intermediate semicolon after the command…
Browse files Browse the repository at this point in the history
… number
  • Loading branch information
leonerd committed Feb 3, 2020
1 parent de5a2cb commit ece7c45
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 8 deletions.
16 changes: 10 additions & 6 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion src/vterm_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions t/02parser.test
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion t/run-test.pl
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down

0 comments on commit ece7c45

Please sign in to comment.