BeRTOS
|
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> // atol(), NULL 00064 #include <string.h> // strchr(), strcmp() 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 // Extract the argument 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 /* check if there are remaining args */ 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 // If there was another matching word, it means that we have a multiple 00173 // match: then return NULL. 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 // The first word is the ID 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 // Skip the ID, and get the command 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 // Skip the ID, and get the command 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 00313 void parser_register_cmd(const struct CmdTemplate* cmd) 00314 { 00315 ht_insert(&commands, cmd); 00316 } 00317 00318 void parser_init(void) 00319 { 00320 // Initialize the hashtable used to store the command description 00321 ht_init(&commands); 00322 }