aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command.c2
-rw-r--r--src/tokenizer.c58
-rw-r--r--src/tokenizer.h21
3 files changed, 75 insertions, 6 deletions
diff --git a/src/command.c b/src/command.c
index 7c274397..f69bdf63 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 635d507d..c1b64f95 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 e0238f0a..ce4c37cc 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