X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=mware%2Fparser.c;h=142feba68c8a895b4c8932ccbc1c109707ac5c26;hb=HEAD;hp=d486ad4673ee2b9f2973010b3d6b248489123466;hpb=77c1d6ba65a199f60faa0e0a68e63ef0eb87677c;p=bertos.git diff --git a/mware/parser.c b/mware/parser.c deleted file mode 100644 index d486ad46..00000000 --- a/mware/parser.c +++ /dev/null @@ -1,399 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * \author Giovanni Bajo - * - * \brief Serial protocol parser and commands. - * - * This file contains the serial protocol parser and - * the definition of the protocol commands. Commands are defined - * in a "CmdTemplate" type array, containing: - * - the name of the command, - * - the arguments it expects to receive, - * - the output values, - * - the name of the function implementing the command. - * - * The arguments and results are passed to command function - * using an union: the element of the union to use for each - * argument is determined by format strings present in the - * CmdTemplate table. - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:28 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2006/06/01 12:27:39 marco - *#* Added utilities for protocols - *#* - *#*/ - -#include "parser.h" -#include - -#include // atol(), NULL -#include // strchr(), strcmp() - -#include - -#define ARG_SEP_S " " -#define ARG_SEP_C ' ' - -#define MAX_COMMANDS_NUMBER 128 // 64 - -/// Hashtable hook to extract the key from a command -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); - - -/** - * \brief Tokenize one word at a time from a text. - * - * This function is similar to strtok, but does not use any implicit - * context, nor it does modify the input buffer in any form. - * The word is returned as a STL-like [begin,end) range. - * - * To extract the first word, make both begin and end point at the - * start of the text, and call the function. Then, subsequent - * calls will return the following words (assuming the begin/end - * variable are not modified between calls). - * - * \param begin Will contain the index of the first character of the word - * \param end Will contain the index of the character after the last - * character of the word - * - * \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) -{ - const char *cur = *end; - - while ((*cur == ' ' || *cur == '\t') && *cur) - ++cur; - - *begin = cur; - - while ((*cur != ' ' && *cur != '\t') && *cur) - ++cur; - - *end = cur; - - return (*end != *begin); -} - - -/** - * \brief Command arguments parser. - * - * Using the format pointed by the argument fmt - * parses the input string filling the array argv - * with input parameters of the correct type. - * - * \param fmt Parameters format string. - * \param input Input string. - * \param argv Array filled with parameters. - * - * \return False in case of errors, otherwise true. - */ -static bool parseArgs(const char *fmt, const char *input, parms argv[]) -{ - const char *begin = input, *end = input; - - while (*fmt) - { - // Extract the argument - if (!get_word(&begin, &end)) - return false; - - switch (*fmt) - { - case 'd': - (*argv++).l = atol(begin); - break; - - case 's': - (*argv++).s = begin; - break; - - default: - ASSERT2(0, "Unknown format for argument"); - return false; - } - - ++fmt; - } - - /* check if there are remaining args */ - if (get_word(&begin, &end)) - return false; - - return true; -} - - -#ifdef UNUSED_CODE -/** - * \brief Command result formatting and printing. - * - * Prints out on device fd the values contained - * in the array result, using the format specified - * in fmt. - * - * \param ser Serial handle. - * \param fmt Values format string. - * \param result Array containing result to be printed. - * - * \return -1 in case of errors, otherwise 0. - */ -static int printResult(struct Serial *ser, const char *fmt, parms result[]) -{ - long n; - char repeat_cnt = 0; - - while (*fmt) - { - if (*fmt >= '0' && *fmt <= '9') - { - /* Collect repeat count digit (left to right order) */ - repeat_cnt = (repeat_cnt * 10) + (*fmt - '0'); - } - else - { - /* Set default repeat cnt of 1 when not specified */ - if (repeat_cnt == 0) - repeat_cnt = 1; - - /* Loop repeat_cnt times */ - do - { - switch (*fmt) - { - case 'd': - ser_printf(ser, ARG_SEP_S "%ld", (*result).l); - result++; - break; - case 'c': - ser_print(ser, ARG_SEP_S); - ser_print(ser, (*result).s); - result++; - break; - case 's': - ser_printf(ser, ARG_SEP_S "%s", (*result).s); - result++; - break; - case 'n': - n = (*result++).l; - ser_printf(ser, ARG_SEP_S "%ld", n); - while (n--) { - ser_printf(ser, ARG_SEP_S "%ld", (*result).l); - result++; - } - break; - default: - break; - } - } - while (--repeat_cnt); - } - - /* Skip to next format char */ - ++fmt; - - } /* while (*fmt) */ - - - ser_print(ser, "\r\n"); - return 0; -} -#endif /* UNUSED_CODE */ - -/// Hook provided by the parser for matching of command names (TAB completion) for readline -const char* parser_rl_match(UNUSED_ARG(void *,dummy), const char *word, int word_len) -{ - HashIterator cur; - HashIterator end = ht_iter_end(&commands); - const char *found = NULL; - - for (cur = ht_iter_begin(&commands); - !ht_iter_cmp(cur, end); - cur = ht_iter_next(cur)) - { - const struct CmdTemplate* cmdp = (const struct CmdTemplate*)ht_iter_get(cur); - if (strncmp(cmdp->name, word, word_len) == 0) - { - // If there was another matching word, it means that we have a multiple - // match: then return NULL. - if (found) - return NULL; - - found = cmdp->name; - } - } - - return found; -} - -bool parser_get_cmd_id(const char* line, unsigned long* ID) -{ - const char *begin = line, *end = line; - char *end2; - - // The first word is the ID - if (!get_word(&begin, &end)) - return false; - - *ID = strtoul(begin, &end2, 10); - if (end2 != end) - return false; - - return true; -} - -const struct CmdTemplate* parser_get_cmd_template(const char *input) -{ -// const struct CmdTemplate *cmdp; -// int cmdlen; - const char *begin = input, *end = input; - - // Skip the ID, and get the command - if (!get_word(&begin, &end)) - return NULL; - if (!get_word(&begin, &end)) - return NULL; - - return (const struct CmdTemplate*)ht_find(&commands, begin, end-begin); -} - -static const char *skip_to_params(const char *input, const struct CmdTemplate *cmdp) -{ - const char *begin = input, *end = input; - - // Skip the ID, and get the command - if (!get_word(&begin, &end)) - return NULL; - if (!get_word(&begin, &end)) - return NULL; - - ASSERT2(strlen(cmdp->name) == (size_t)(end-begin), "Invalid command template specified"); - ASSERT2(!strncmp(begin, cmdp->name, end-begin), "Invalid command template specified"); - - return end; -} - -bool parser_get_cmd_arguments(const char* input, const struct CmdTemplate* cmdp, parms args[PARSER_MAX_ARGS]) -{ - input = skip_to_params(input, cmdp); - if (!input) - return false; - - args[0].s = cmdp->name; - if (!parseArgs(cmdp->arg_fmt, input, args + 1)) - return false; - - return true; -} - -static const void* get_key_from_command(const void* cmd, uint8_t* length) -{ - const struct CmdTemplate* c = cmd; - *length = strlen(c->name); - return c->name; -} - -bool parser_process_line(const char* input) -{ - const struct CmdTemplate *cmdp; - parms args[PARSER_MAX_ARGS]; - - cmdp = parser_get_cmd_template(input); - if (!cmdp) - return false; - - if (!parser_get_cmd_arguments(input, cmdp, args)) - return false; - - if (!parser_execute_cmd(cmdp, args)) - return false; - - return true; -} - -void parser_register_cmd(const struct CmdTemplate* cmd) -{ - ht_insert(&commands, cmd); -} - -#if CONFIG_INTERNAL_COMMANDS -static ResultCode cmd_help(void) -{ -#ifdef _DEBUG - - // FIXME: There is no way at the moment to access the serial port. Dump - // this through JTAG for now - for (HashIterator iter = ht_iter_begin(&commands); - !ht_iter_cmp(iter, ht_iter_end(&commands)); - iter = ht_iter_next(iter)) - { - struct CmdTemplate* cmd = (struct CmdTemplate*)ht_iter_get(iter); - kprintf("%-20s", cmd->name); - for (unsigned j = 0; cmd->arg_fmt[j]; ++j) - kprintf("%c ", 'a' + j); - kprintf("\r\n"); - } -#endif - - return RC_OK; -} - -#include "cmd_hunk.h" -DECLARE_CMD_HUNK(help, (NIL), (NIL)); - -#endif // CONFIG_INTERNAL_COMMANDS - - -void parser_init(void) -{ - // Initialize the hashtable used to store the command description - ht_init(&commands); - -#if CONFIG_INTERNAL_COMMANDS - parser_register_cmd(&CMD_HUNK_TEMPLATE(help)); -#endif -}