Handle comments more correctly inside {}, from Avi Halachmi.

This commit is contained in:
nicm 2019-06-18 11:17:40 +00:00 committed by Nicholas Marriott
parent 748633c887
commit 797042584e

View File

@ -1281,8 +1281,8 @@ static int
yylex_token_brace(char **buf, size_t *len) yylex_token_brace(char **buf, size_t *len)
{ {
struct cmd_parse_state *ps = &parse_state; struct cmd_parse_state *ps = &parse_state;
int ch, nesting = 1, escape = 0, quote = '\0'; int ch, lines = 0, nesting = 1, escape = 0;
int lines = 0; int quote = '\0', token = 0;
/* /*
* Extract a string up to the matching unquoted '}', including newlines * Extract a string up to the matching unquoted '}', including newlines
@ -1292,6 +1292,10 @@ yylex_token_brace(char **buf, size_t *len)
* depth, we scan the input as if it was a tmux config file, and ignore * depth, we scan the input as if it was a tmux config file, and ignore
* braces which would be considered quoted, escaped, or in a comment. * braces which would be considered quoted, escaped, or in a comment.
* *
* We update the token state after every character because '#' begins a
* comment only when it begins a token. For simplicity, we treat an
* unquoted directive format as comment.
*
* The result is verbatim copy of the input excluding the final brace. * The result is verbatim copy of the input excluding the final brace.
*/ */
@ -1311,6 +1315,8 @@ yylex_token_brace(char **buf, size_t *len)
ch == '\n' || ch == '\n' ||
ch == '\\')) { ch == '\\')) {
escape = 0; escape = 0;
if (ch != '\n')
token = 1;
continue; continue;
} }
@ -1326,7 +1332,7 @@ yylex_token_brace(char **buf, size_t *len)
/* A newline always resets to unquoted. */ /* A newline always resets to unquoted. */
if (ch == '\n') { if (ch == '\n') {
quote = 0; quote = token = 0;
continue; continue;
} }
@ -1337,33 +1343,47 @@ yylex_token_brace(char **buf, size_t *len)
*/ */
if (ch == quote && quote != '#') if (ch == quote && quote != '#')
quote = 0; quote = 0;
token = 1; /* token continues regardless */
} else { } else {
/* Not inside quotes or comment. */ /* Not inside quotes or comment. */
switch (ch) { switch (ch) {
case '"': case '"':
case '\'': case '\'':
case '#': case '#':
/* Beginning of quote or comment. */ /* Beginning of quote or maybe comment. */
if (ch != '#' || !token)
quote = ch; quote = ch;
token = 1;
break;
case ' ':
case '\t':
case ';':
/* Delimiter - token resets. */
token = 0;
break; break;
case '{': case '{':
nesting++; nesting++;
token = 0; /* new commands set - token resets */
break; break;
case '}': case '}':
nesting--; nesting--;
token = 1; /* same as after quotes */
if (nesting == 0) { if (nesting == 0) {
(*len)--; /* remove closing } */ (*len)--; /* remove closing } */
ps->input->line += lines; ps->input->line += lines;
return (1); return (1);
} }
break; break;
default:
token = 1;
break;
} }
} }
} }
/* /*
* Update line count after error as reporting the opening line * Update line count after error as reporting the opening line is more
* is more useful than EOF. * useful than EOF.
*/ */
yyerror("unterminated brace string"); yyerror("unterminated brace string");
ps->input->line += lines; ps->input->line += lines;