00001
00058 #include "parser.h"
00059
00060 #include "cfg/cfg_parser.h"
00061
00062 #include <drv/ser.h>
00063 #include <struct/hashtable.h>
00064
00065 #include <stdlib.h>
00066 #include <string.h>
00067
00068
00069
00070 #define ARG_SEP_S " "
00071 #define ARG_SEP_C ' '
00072
00073 #define MAX_COMMANDS_NUMBER 128 // 64
00074
00076 static const void* get_key_from_command(const void* cmd, uint8_t* length);
00077
00079 DECLARE_HASHTABLE_STATIC(commands, MAX_COMMANDS_NUMBER, get_key_from_command);
00080
00081
00101 static bool get_word(const char **begin, const char **end)
00102 {
00103 const char *cur = *end;
00104
00105 while ((*cur == ' ' || *cur == '\t') && *cur)
00106 ++cur;
00107
00108 *begin = cur;
00109
00110 while ((*cur != ' ' && *cur != '\t') && *cur)
00111 ++cur;
00112
00113 *end = cur;
00114
00115 return (*end != *begin);
00116 }
00117
00118
00132 static bool parseArgs(const char *fmt, const char *input, parms argv[])
00133 {
00134 const char *begin = input, *end = input;
00135
00136 while (*fmt)
00137 {
00138
00139 if (!get_word(&begin, &end))
00140 return false;
00141
00142 switch (*fmt)
00143 {
00144 case 'd':
00145 (*argv++).l = atol(begin);
00146 break;
00147
00148 case 's':
00149 (*argv++).s = begin;
00150 break;
00151
00152 default:
00153 ASSERT2(0, "Unknown format for argument");
00154 return false;
00155 }
00156
00157 ++fmt;
00158 }
00159
00160
00161 if (get_word(&begin, &end))
00162 return false;
00163
00164 return true;
00165 }
00166
00167
00168 #ifdef UNUSED_CODE
00169
00182 static int printResult(struct Serial *ser, const char *fmt, parms result[])
00183 {
00184 long n;
00185 char repeat_cnt = 0;
00186
00187 while (*fmt)
00188 {
00189 if (*fmt >= '0' && *fmt <= '9')
00190 {
00191
00192 repeat_cnt = (repeat_cnt * 10) + (*fmt - '0');
00193 }
00194 else
00195 {
00196
00197 if (repeat_cnt == 0)
00198 repeat_cnt = 1;
00199
00200
00201 do
00202 {
00203 switch (*fmt)
00204 {
00205 case 'd':
00206 ser_printf(ser, ARG_SEP_S "%ld", (*result).l);
00207 result++;
00208 break;
00209 case 'c':
00210 ser_print(ser, ARG_SEP_S);
00211 ser_print(ser, (*result).s);
00212 result++;
00213 break;
00214 case 's':
00215 ser_printf(ser, ARG_SEP_S "%s", (*result).s);
00216 result++;
00217 break;
00218 case 'n':
00219 n = (*result++).l;
00220 ser_printf(ser, ARG_SEP_S "%ld", n);
00221 while (n--) {
00222 ser_printf(ser, ARG_SEP_S "%ld", (*result).l);
00223 result++;
00224 }
00225 break;
00226 default:
00227 break;
00228 }
00229 }
00230 while (--repeat_cnt);
00231 }
00232
00233
00234 ++fmt;
00235
00236 }
00237
00238
00239 ser_print(ser, "\r\n");
00240 return 0;
00241 }
00242 #endif
00243
00245 const char* parser_rl_match(UNUSED_ARG(void *,dummy), const char *word, int word_len)
00246 {
00247 HashIterator cur;
00248 HashIterator end = ht_iter_end(&commands);
00249 const char *found = NULL;
00250
00251 for (cur = ht_iter_begin(&commands);
00252 !ht_iter_cmp(cur, end);
00253 cur = ht_iter_next(cur))
00254 {
00255 const struct CmdTemplate* cmdp = (const struct CmdTemplate*)ht_iter_get(cur);
00256 if (strncmp(cmdp->name, word, word_len) == 0)
00257 {
00258
00259
00260 if (found)
00261 return NULL;
00262
00263 found = cmdp->name;
00264 }
00265 }
00266
00267 return found;
00268 }
00269
00270 bool parser_get_cmd_id(const char* line, unsigned long* ID)
00271 {
00272 const char *begin = line, *end = line;
00273 char *end2;
00274
00275
00276 if (!get_word(&begin, &end))
00277 return false;
00278
00279 *ID = strtoul(begin, &end2, 10);
00280 if (end2 != end)
00281 return false;
00282
00283 return true;
00284 }
00285
00286 const struct CmdTemplate* parser_get_cmd_template(const char *input)
00287 {
00288
00289
00290 const char *begin = input, *end = input;
00291
00292
00293 if (!get_word(&begin, &end))
00294 return NULL;
00295 if (!get_word(&begin, &end))
00296 return NULL;
00297
00298 return (const struct CmdTemplate*)ht_find(&commands, begin, end-begin);
00299 }
00300
00301 static const char *skip_to_params(const char *input, const struct CmdTemplate *cmdp)
00302 {
00303 const char *begin = input, *end = input;
00304
00305
00306 if (!get_word(&begin, &end))
00307 return NULL;
00308 if (!get_word(&begin, &end))
00309 return NULL;
00310
00311 ASSERT2(strlen(cmdp->name) == (size_t)(end-begin), "Invalid command template specified");
00312 ASSERT2(!strncmp(begin, cmdp->name, end-begin), "Invalid command template specified");
00313
00314 return end;
00315 }
00316
00317 bool parser_get_cmd_arguments(const char* input, const struct CmdTemplate* cmdp, parms args[PARSER_MAX_ARGS])
00318 {
00319 input = skip_to_params(input, cmdp);
00320 if (!input)
00321 return false;
00322
00323 args[0].s = cmdp->name;
00324 if (!parseArgs(cmdp->arg_fmt, input, args + 1))
00325 return false;
00326
00327 return true;
00328 }
00329
00330 static const void* get_key_from_command(const void* cmd, uint8_t* length)
00331 {
00332 const struct CmdTemplate* c = cmd;
00333 *length = strlen(c->name);
00334 return c->name;
00335 }
00336
00337 bool parser_process_line(const char* input)
00338 {
00339 const struct CmdTemplate *cmdp;
00340 parms args[PARSER_MAX_ARGS];
00341
00342 cmdp = parser_get_cmd_template(input);
00343 if (!cmdp)
00344 return false;
00345
00346 if (!parser_get_cmd_arguments(input, cmdp, args))
00347 return false;
00348
00349 if (!parser_execute_cmd(cmdp, args))
00350 return false;
00351
00352 return true;
00353 }
00354
00355 void parser_register_cmd(const struct CmdTemplate* cmd)
00356 {
00357 ht_insert(&commands, cmd);
00358 }
00359
00360 #if CONFIG_INTERNAL_COMMANDS
00361 #warning FIXME:This code use boost lib, if you compile with internal command you must fix it.
00362 static ResultCode cmd_help(void)
00363 {
00364 #ifdef _DEBUG
00365
00366
00367
00368 for (HashIterator iter = ht_iter_begin(&commands);
00369 !ht_iter_cmp(iter, ht_iter_end(&commands));
00370 iter = ht_iter_next(iter))
00371 {
00372 struct CmdTemplate* cmd = (struct CmdTemplate*)ht_iter_get(iter);
00373 kprintf("%-20s", cmd->name);
00374 for (unsigned j = 0; cmd->arg_fmt[j]; ++j)
00375 kprintf("%c ", 'a' + j);
00376 kprintf("\r\n");
00377 }
00378 #endif
00379
00380 return RC_OK;
00381 }
00382
00383 #include "cmd_hunk.h"
00384 DECLARE_CMD_HUNK(help, (NIL), (NIL));
00385
00386 #endif // CONFIG_INTERNAL_COMMANDS
00387
00388
00389 void parser_init(void)
00390 {
00391
00392 ht_init(&commands);
00393
00394 #if CONFIG_INTERNAL_COMMANDS
00395 parser_register_cmd(&CMD_HUNK_TEMPLATE(help));
00396 #endif
00397 }