parser.c
Go to the documentation of this file.00001
00056 #include "parser.h"
00057
00058 #include "cfg/cfg_parser.h"
00059
00060 #include <io/kfile.h>
00061 #include <struct/hashtable.h>
00062
00063 #include <stdlib.h>
00064 #include <string.h>
00065
00067 static const void* get_key_from_command(const void* cmd, uint8_t* length);
00068
00070 DECLARE_HASHTABLE_STATIC(commands, CONFIG_MAX_COMMANDS_NUMBER, get_key_from_command);
00071
00072
00092 static bool get_word(const char **begin, const char **end)
00093 {
00094 const char *cur = *end;
00095
00096 while ((*cur == ' ' || *cur == '\t') && *cur)
00097 ++cur;
00098
00099 *begin = cur;
00100
00101 while ((*cur != ' ' && *cur != '\t') && *cur)
00102 ++cur;
00103
00104 *end = cur;
00105
00106 return (*end != *begin);
00107 }
00108
00109
00123 static bool parseArgs(const char *fmt, const char *input, parms argv[])
00124 {
00125 const char *begin = input, *end = input;
00126
00127 while (*fmt)
00128 {
00129
00130 if (!get_word(&begin, &end))
00131 return false;
00132
00133 switch (*fmt)
00134 {
00135 case 'd':
00136 (*argv++).l = atol(begin);
00137 break;
00138
00139 case 's':
00140 (*argv++).s = begin;
00141 break;
00142
00143 default:
00144 ASSERT2(0, "Unknown format for argument");
00145 return false;
00146 }
00147
00148 ++fmt;
00149 }
00150
00151
00152 if (get_word(&begin, &end))
00153 return false;
00154
00155 return true;
00156 }
00157
00159 const char* parser_rl_match(UNUSED_ARG(void *,dummy), const char *word, int word_len)
00160 {
00161 HashIterator cur;
00162 HashIterator end = ht_iter_end(&commands);
00163 const char *found = NULL;
00164
00165 for (cur = ht_iter_begin(&commands);
00166 !ht_iter_cmp(cur, end);
00167 cur = ht_iter_next(cur))
00168 {
00169 const struct CmdTemplate* cmdp = (const struct CmdTemplate*)ht_iter_get(cur);
00170 if (strncmp(cmdp->name, word, word_len) == 0)
00171 {
00172
00173
00174 if (found)
00175 return NULL;
00176
00177 found = cmdp->name;
00178 }
00179 }
00180
00181 return found;
00182 }
00183
00184 #if CONFIG_ENABLE_COMPAT_BEHAVIOUR
00185 bool parser_get_cmd_id(const char* line, unsigned long* ID)
00186 {
00187 const char *begin = line, *end = line;
00188 char *end2;
00189
00190
00191 if (!get_word(&begin, &end))
00192 return false;
00193
00194 *ID = strtoul(begin, &end2, 10);
00195 if (end2 != end)
00196 return false;
00197
00198 return true;
00199 }
00200 #endif
00201
00216 const struct CmdTemplate* parser_get_cmd_template(const char *input)
00217 {
00218 const char *begin = input, *end = input;
00219
00220 #if CONFIG_ENABLE_COMPAT_BEHAVIOUR
00221
00222 if (!get_word(&begin, &end))
00223 return NULL;
00224 #endif
00225 if (!get_word(&begin, &end))
00226 return NULL;
00227
00228 return (const struct CmdTemplate*)ht_find(&commands, begin, end-begin);
00229 }
00230
00231 static const char *skip_to_params(const char *input, const struct CmdTemplate *cmdp)
00232 {
00233 const char *begin = input, *end = input;
00234
00235 #if CONFIG_ENABLE_COMPAT_BEHAVIOUR
00236
00237 if (!get_word(&begin, &end))
00238 return NULL;
00239 #endif
00240 if (!get_word(&begin, &end))
00241 return NULL;
00242
00243 ASSERT2(strlen(cmdp->name) == (size_t)(end-begin), "Invalid command template specified");
00244 ASSERT2(!strncmp(begin, cmdp->name, end-begin), "Invalid command template specified");
00245
00246 return end;
00247 }
00248
00261 bool parser_get_cmd_arguments(const char* input, const struct CmdTemplate* cmdp, parms args[CONFIG_PARSER_MAX_ARGS])
00262 {
00263 input = skip_to_params(input, cmdp);
00264 if (!input)
00265 return false;
00266
00267 args[0].s = cmdp->name;
00268 if (!parseArgs(cmdp->arg_fmt, input, args + 1))
00269 return false;
00270
00271 return true;
00272 }
00273
00274 static const void* get_key_from_command(const void* cmd, uint8_t* length)
00275 {
00276 const struct CmdTemplate* c = cmd;
00277 *length = strlen(c->name);
00278 return c->name;
00279 }
00280
00290 bool parser_process_line(const char* input)
00291 {
00292 const struct CmdTemplate *cmdp;
00293 parms args[CONFIG_PARSER_MAX_ARGS];
00294
00295 cmdp = parser_get_cmd_template(input);
00296 if (!cmdp)
00297 return false;
00298
00299 if (!parser_get_cmd_arguments(input, cmdp, args))
00300 return false;
00301
00302 if (!parser_execute_cmd(cmdp, args))
00303 return false;
00304
00305 return true;
00306 }
00307
00314 bool parser_register_cmd(const struct CmdTemplate* cmd)
00315 {
00316 return ht_insert(&commands, cmd);
00317 }
00318
00319 void parser_init(void)
00320 {
00321
00322 ht_init(&commands);
00323 }