Allow string arguments to be quote within "".
[bertos.git] / bertos / mware / parser.c
index e63e55e870e158d74169451ac5bc024ee8fe0d02..2197d8482391b8616ab23fcb755078440ece50c0 100644 (file)
@@ -55,6 +55,8 @@
 
 #include "parser.h"
 
+#include "cfg/cfg_parser.h"
+
 #include <io/kfile.h>
 #include <struct/hashtable.h>
 
@@ -65,7 +67,7 @@
 static const void* get_key_from_command(const void* cmd, uint8_t* length);
 
 /// Hashtable that handles the commands that can be executed
-DECLARE_HASHTABLE_STATIC(commands, MAX_COMMANDS_NUMBER, get_key_from_command);
+DECLARE_HASHTABLE_STATIC(commands, CONFIG_MAX_COMMANDS_NUMBER, get_key_from_command);
 
 
 /**
@@ -87,17 +89,31 @@ DECLARE_HASHTABLE_STATIC(commands, MAX_COMMANDS_NUMBER, get_key_from_command);
  * \return True if a word was extracted, false if we got to the end
  * of the string without extracting any word.
  */
-static bool get_word(const char **begin, const char **end)
+bool get_word(const char **begin, const char **end)
 {
        const char *cur = *end;
+       bool open_quote = false;
 
        while ((*cur == ' ' || *cur == '\t') && *cur)
                ++cur;
 
+       if (*cur == '"')
+               open_quote = true;
+
        *begin = cur;
 
-       while ((*cur != ' ' && *cur != '\t') && *cur)
+       if (open_quote)
+       {
                ++cur;
+               while (*cur != '"' && *cur)
+                       ++cur;
+               if (*cur != '"')
+                       return false;
+               ++cur;
+       }
+       else
+               while ((*cur != ' ' && *cur != '\t') && *cur)
+                       ++cur;
 
        *end = cur;
 
@@ -135,7 +151,15 @@ static bool parseArgs(const char *fmt, const char *input, parms argv[])
                                break;
 
                        case 's':
-                               (*argv++).s = begin;
+                               (*argv).str.p = begin;
+                               (*argv).str.sz = end - begin;
+                               /* Remove the quotes from argument */
+                               if (*begin == '"' && *(end - 1) == '"')
+                               {
+                                       (*argv).str.p += 1;
+                                       (*argv).str.sz -= 2;
+                               }
+                               argv++;
                                break;
 
                        default:
@@ -197,6 +221,20 @@ bool parser_get_cmd_id(const char* line, unsigned long* ID)
 }
 #endif
 
+/**
+ * Find the template for the command contained in the text line.
+ * The template can be used to tokenize the command and interpret
+ * it.
+ *
+ * This function can be used to find out which command is contained
+ * in a given text line without parsing all the parameters and
+ * executing it.
+ *
+ * \param input Text line to be processed (ASCIIZ)
+ *
+ * \return The command template associated with the command contained
+ * in the line, or NULL if the command is invalid.
+ */
 const struct CmdTemplate* parser_get_cmd_template(const char *input)
 {
        const char *begin = input, *end = input;
@@ -230,13 +268,25 @@ static const char *skip_to_params(const char *input, const struct CmdTemplate *c
        return end;
 }
 
-bool parser_get_cmd_arguments(const char* input, const struct CmdTemplate* cmdp, parms args[PARSER_MAX_ARGS])
+/**
+ * Extract the arguments for the command contained in the text line.
+ *
+ * The first argument will always be the command name, so the actual arguments
+ * will start at index 1.
+ *
+ * \param input Text line to be processed (ASCIIZ)
+ * \param cmdp Command template for this line
+ * \param args Will contain the extracted parameters
+ *
+ * \return True if everything OK, false in case of parsing error.
+ */
+bool parser_get_cmd_arguments(const char* input, const struct CmdTemplate* cmdp, parms args[CONFIG_PARSER_MAX_ARGS])
 {
        input = skip_to_params(input, cmdp);
        if (!input)
                return false;
 
-       args[0].s = cmdp->name;
+       args[0].str.p = cmdp->name;
        if (!parseArgs(cmdp->arg_fmt, input, args + 1))
                return false;
 
@@ -250,10 +300,19 @@ static const void* get_key_from_command(const void* cmd, uint8_t* length)
        return c->name;
 }
 
+/**
+ * \brief Command input handler.
+ *
+ * Process the input, calling the requested command (if found).
+ *
+ * \param input Text line to be processed (ASCIIZ)
+ *
+ * \return true if everything is OK, false in case of errors
+ */
 bool parser_process_line(const char* input)
 {
        const struct CmdTemplate *cmdp;
-       parms args[PARSER_MAX_ARGS];
+       parms args[CONFIG_PARSER_MAX_ARGS];
 
        cmdp = parser_get_cmd_template(input);
        if (!cmdp)
@@ -268,9 +327,15 @@ bool parser_process_line(const char* input)
        return true;
 }
 
-void parser_register_cmd(const struct CmdTemplate* cmd)
+/**
+ * Register a new command into the parser
+ *
+ * \param cmd Command template describing the command
+ * \return true if registration was successful, false otherwise
+ */
+bool parser_register_cmd(const struct CmdTemplate* cmd)
 {
-       ht_insert(&commands, cmd);
+       return ht_insert(&commands, cmd);
 }
 
 void parser_init(void)