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> // 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 bool get_word(const char **begin, const char **end) 00093 { 00094 const char *cur = *end; 00095 bool open_quote = false; 00096 00097 while ((*cur == ' ' || *cur == '\t') && *cur) 00098 ++cur; 00099 00100 if (*cur == '"') 00101 open_quote = true; 00102 00103 *begin = cur; 00104 00105 if (open_quote) 00106 { 00107 ++cur; 00108 while (*cur != '"' && *cur) 00109 ++cur; 00110 if (*cur != '"') 00111 return false; 00112 ++cur; 00113 } 00114 else 00115 while ((*cur != ' ' && *cur != '\t') && *cur) 00116 ++cur; 00117 00118 *end = cur; 00119 00120 return (*end != *begin); 00121 } 00122 00123 00137 static bool parseArgs(const char *fmt, const char *input, parms argv[]) 00138 { 00139 const char *begin = input, *end = input; 00140 00141 while (*fmt) 00142 { 00143 // Extract the argument 00144 if (!get_word(&begin, &end)) 00145 return false; 00146 00147 switch (*fmt) 00148 { 00149 case 'd': 00150 (*argv++).l = atol(begin); 00151 break; 00152 00153 case 's': 00154 (*argv).s.p = begin; 00155 (*argv).s.sz = end - begin; 00156 /* Remove the quotes from argument */ 00157 if (*begin == '"' && *(end - 1) == '"') 00158 { 00159 (*argv).s.p += 1; 00160 (*argv).s.sz -= 2; 00161 } 00162 argv++; 00163 break; 00164 00165 default: 00166 ASSERT2(0, "Unknown format for argument"); 00167 return false; 00168 } 00169 00170 ++fmt; 00171 } 00172 00173 /* check if there are remaining args */ 00174 if (get_word(&begin, &end)) 00175 return false; 00176 00177 return true; 00178 } 00179 00181 const char* parser_rl_match(UNUSED_ARG(void *,dummy), const char *word, int word_len) 00182 { 00183 HashIterator cur; 00184 HashIterator end = ht_iter_end(&commands); 00185 const char *found = NULL; 00186 00187 for (cur = ht_iter_begin(&commands); 00188 !ht_iter_cmp(cur, end); 00189 cur = ht_iter_next(cur)) 00190 { 00191 const struct CmdTemplate* cmdp = (const struct CmdTemplate*)ht_iter_get(cur); 00192 if (strncmp(cmdp->name, word, word_len) == 0) 00193 { 00194 // If there was another matching word, it means that we have a multiple 00195 // match: then return NULL. 00196 if (found) 00197 return NULL; 00198 00199 found = cmdp->name; 00200 } 00201 } 00202 00203 return found; 00204 } 00205 00206 #if CONFIG_ENABLE_COMPAT_BEHAVIOUR 00207 bool parser_get_cmd_id(const char* line, unsigned long* ID) 00208 { 00209 const char *begin = line, *end = line; 00210 char *end2; 00211 00212 // The first word is the ID 00213 if (!get_word(&begin, &end)) 00214 return false; 00215 00216 *ID = strtoul(begin, &end2, 10); 00217 if (end2 != end) 00218 return false; 00219 00220 return true; 00221 } 00222 #endif 00223 00238 const struct CmdTemplate* parser_get_cmd_template(const char *input) 00239 { 00240 const char *begin = input, *end = input; 00241 00242 #if CONFIG_ENABLE_COMPAT_BEHAVIOUR 00243 // Skip the ID, and get the command 00244 if (!get_word(&begin, &end)) 00245 return NULL; 00246 #endif 00247 00248 if (!get_word(&begin, &end)) 00249 return NULL; 00250 00251 return (const struct CmdTemplate*)ht_find(&commands, begin, end-begin); 00252 } 00253 00254 static const char *skip_to_params(const char *input, const struct CmdTemplate *cmdp) 00255 { 00256 const char *begin = input, *end = input; 00257 00258 #if CONFIG_ENABLE_COMPAT_BEHAVIOUR 00259 // Skip the ID, and get the command 00260 if (!get_word(&begin, &end)) 00261 return NULL; 00262 #endif 00263 00264 if (!get_word(&begin, &end)) 00265 return NULL; 00266 00267 ASSERT2(strlen(cmdp->name) == (size_t)(end-begin), "Invalid command template specified"); 00268 ASSERT2(!strncmp(begin, cmdp->name, end-begin), "Invalid command template specified"); 00269 00270 return end; 00271 } 00272 00285 bool parser_get_cmd_arguments(const char* input, const struct CmdTemplate* cmdp, parms args[CONFIG_PARSER_MAX_ARGS]) 00286 { 00287 input = skip_to_params(input, cmdp); 00288 if (!input) 00289 return false; 00290 00291 args[0].s.p = cmdp->name; 00292 if (!parseArgs(cmdp->arg_fmt, input, args + 1)) 00293 return false; 00294 00295 return true; 00296 } 00297 00298 static const void* get_key_from_command(const void* cmd, uint8_t* length) 00299 { 00300 const struct CmdTemplate* c = cmd; 00301 *length = strlen(c->name); 00302 return c->name; 00303 } 00304 00314 bool parser_process_line(const char* input) 00315 { 00316 const struct CmdTemplate *cmdp; 00317 parms args[CONFIG_PARSER_MAX_ARGS]; 00318 00319 cmdp = parser_get_cmd_template(input); 00320 if (!cmdp) 00321 return false; 00322 00323 if (!parser_get_cmd_arguments(input, cmdp, args)) 00324 return false; 00325 00326 if (!parser_execute_cmd(cmdp, args)) 00327 return false; 00328 00329 return true; 00330 } 00331 00338 bool parser_register_cmd(const struct CmdTemplate* cmd) 00339 { 00340 return ht_insert(&commands, cmd); 00341 } 00342 00343 void parser_init(void) 00344 { 00345 // Initialize the hashtable used to store the command description 00346 ht_init(&commands); 00347 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)