new parser: correctly handle leading/trailing newlines (+test) (Thanks helgikrs)

This commit is contained in:
Michael Stapelberg 2012-01-25 22:00:32 +00:00
parent 57a96bb61f
commit 19dc92a9a5
2 changed files with 26 additions and 9 deletions

View File

@ -214,8 +214,9 @@ char *parse_command(const char *input) {
/* The "<=" operator is intentional: We also handle the terminating 0-byte /* The "<=" operator is intentional: We also handle the terminating 0-byte
* explicitly by looking for an 'end' token. */ * explicitly by looking for an 'end' token. */
while ((walk - input) <= len) { while ((walk - input) <= len) {
/* skip whitespace before every token */ /* skip whitespace and newlines before every token */
while ((*walk == ' ' || *walk == '\t') && *walk != '\0') while ((*walk == ' ' || *walk == '\t' ||
*walk == '\r' || *walk == '\n') && *walk != '\0')
walk++; walk++;
DLOG("remaining input = %s\n", walk); DLOG("remaining input = %s\n", walk);
@ -255,15 +256,20 @@ char *parse_command(const char *input) {
if (token->name[0] == 's') { if (token->name[0] == 's') {
/* For a string (starting with 's'), the delimiters are /* For a string (starting with 's'), the delimiters are
* comma (,) and semicolon (;) which introduce a new * comma (,) and semicolon (;) which introduce a new
* operation or command, respectively. */ * operation or command, respectively. Also, newlines
while (*walk != ';' && *walk != ',' && *walk != '\0') * end a command. */
while (*walk != ';' && *walk != ',' &&
*walk != '\0' && *walk != '\r' &&
*walk != '\n')
walk++; walk++;
} else { } else {
/* For a word, the delimiters are white space (' ' or /* For a word, the delimiters are white space (' ' or
* '\t'), closing square bracket (]), comma (,) and * '\t'), closing square bracket (]), comma (,) and
* semicolon (;). */ * semicolon (;). */
while (*walk != ' ' && *walk != '\t' && *walk != ']' && while (*walk != ' ' && *walk != '\t' &&
*walk != ',' && *walk != ';' && *walk != '\0') *walk != ']' && *walk != ',' &&
*walk != ';' && *walk != '\r' &&
*walk != '\n' && *walk != '\0')
walk++; walk++;
} }
} }
@ -382,8 +388,8 @@ void debuglog(uint64_t lev, char *fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
fprintf(stdout, "# "); fprintf(stderr, "# ");
vfprintf(stdout, fmt, args); vfprintf(stderr, fmt, args);
va_end(args); va_end(args);
} }

View File

@ -12,7 +12,7 @@ sub parser_calls {
# TODO: use a timeout, so that we can error out if it doesnt terminate # TODO: use a timeout, so that we can error out if it doesnt terminate
# TODO: better way of passing arguments # TODO: better way of passing arguments
my $stdout = qx(../test.commands_parser '$command'); my $stdout = qx(../test.commands_parser '$command' 2>&-);
# Filter out all debugging output. # Filter out all debugging output.
my @lines = split("\n", $stdout); my @lines = split("\n", $stdout);
@ -129,6 +129,17 @@ is(parser_calls('[con_mark="yay"] focus'),
"cmd_focus()", "cmd_focus()",
'quoted criteria focus ok'); 'quoted criteria focus ok');
# Make sure trailing whitespace is stripped off: While this is not an issue for
# commands being parsed due to the configuration, people might send IPC
# commands with leading or trailing newlines.
is(parser_calls("workspace test\n"),
'cmd_workspace_name(test)',
'trailing whitespace stripped off ok');
is(parser_calls("\nworkspace test"),
'cmd_workspace_name(test)',
'trailing whitespace stripped off ok');
################################################################################ ################################################################################
# 2: Verify that the parser spits out the right error message on commands which # 2: Verify that the parser spits out the right error message on commands which
# are not ok. # are not ok.