diff options
-rw-r--r-- | src/command.c | 2 | ||||
-rw-r--r-- | src/tokenizer.c | 58 | ||||
-rw-r--r-- | src/tokenizer.h | 21 |
3 files changed, 75 insertions, 6 deletions
diff --git a/src/command.c b/src/command.c index 7c2743975..f69bdf632 100644 --- a/src/command.c +++ b/src/command.c @@ -1959,7 +1959,7 @@ command_process(struct client *client, unsigned num, char *line) while (argc < (int)G_N_ELEMENTS(argv) && (argv[argc] = - tokenizer_next_word_or_string(&line, &error)) != NULL) + tokenizer_next_param(&line, &error)) != NULL) ++argc; /* some error checks; we have to set current_command because diff --git a/src/tokenizer.c b/src/tokenizer.c index 635d507df..c1b64f959 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -90,6 +90,60 @@ tokenizer_next_word(char **input_p, GError **error_r) return word; } +static inline bool +valid_unquoted_char(char ch) +{ + return (unsigned char)ch > 0x20 && ch != '"' && ch != '\''; +} + +char * +tokenizer_next_unquoted(char **input_p, GError **error_r) +{ + char *word, *input; + + assert(input_p != NULL); + assert(*input_p != NULL); + + word = input = *input_p; + + if (*input == 0) + return NULL; + + /* check the first character */ + + if (!valid_unquoted_char(*input)) { + g_set_error(error_r, tokenizer_quark(), 0, + "Invalid unquoted character"); + return NULL; + } + + /* now iterate over the other characters until we find a + whitespace or end-of-string */ + + while (*++input != 0) { + if (g_ascii_isspace(*input)) { + /* a whitespace: the word ends here */ + *input = 0; + /* skip all following spaces, too */ + input = g_strchug(input + 1); + break; + } + + if (!valid_unquoted_char(*input)) { + *input_p = input; + g_set_error(error_r, tokenizer_quark(), 0, + "Invalid unquoted character"); + return NULL; + } + } + + /* end of string: the string is already null-terminated + here */ + + *input_p = input; + return word; +} + char * tokenizer_next_string(char **input_p, GError **error_r) { @@ -155,7 +209,7 @@ tokenizer_next_string(char **input_p, GError **error_r) } char * -tokenizer_next_word_or_string(char **input_p, GError **error_r) +tokenizer_next_param(char **input_p, GError **error_r) { assert(input_p != NULL); assert(*input_p != NULL); @@ -163,5 +217,5 @@ tokenizer_next_word_or_string(char **input_p, GError **error_r) if (**input_p == '"') return tokenizer_next_string(input_p, error_r); else - return tokenizer_next_word(input_p, error_r); + return tokenizer_next_unquoted(input_p, error_r); } diff --git a/src/tokenizer.h b/src/tokenizer.h index e0238f0af..ce4c37ccd 100644 --- a/src/tokenizer.h +++ b/src/tokenizer.h @@ -37,6 +37,20 @@ char * tokenizer_next_word(char **input_p, GError **error_r); /** + * Reads the next unquoted word from the input string. This function + * modifies the input string. + * + * @param input_p the input string; this function returns a pointer to + * the first non-whitespace character of the following token + * @param error_r if this function returns NULL and **input_p!=0, it + * optionally provides a GError object in this argument + * @return a pointer to the null-terminated word, or NULL on error or + * end of line + */ +char * +tokenizer_next_unquoted(char **input_p, GError **error_r); + +/** * Reads the next quoted string from the input string. A backslash * escapes the following character. This function modifies the input * string. @@ -52,8 +66,9 @@ char * tokenizer_next_string(char **input_p, GError **error_r); /** - * Reads the next word or quoted string from the input. This is a - * wrapper for tokenizer_next_word() and tokenizer_next_string(). + * Reads the next unquoted word or quoted string from the input. This + * is a wrapper for tokenizer_next_unquoted() and + * tokenizer_next_string(). * * @param input_p the input string; this function returns a pointer to * the first non-whitespace character of the following token @@ -63,6 +78,6 @@ tokenizer_next_string(char **input_p, GError **error_r); * or end of line */ char * -tokenizer_next_word_or_string(char **input_p, GError **error_r); +tokenizer_next_param(char **input_p, GError **error_r); #endif |