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