static const char* vfs_vdir_iter(VFSNode *vdir, void **opaque) { ht_str2ptr_iter_t *iter = *opaque; if(!iter) { iter = *opaque = calloc(1, sizeof(*iter)); ht_iter_begin(VDIR_TABLE(vdir), iter); } else { ht_iter_next(iter); } return iter->has_data ? iter->key : NULL; }
static ResultCode cmd_help(void) { #ifdef _DEBUG // FIXME: There is no way at the moment to access the serial port. Dump // this through JTAG for now for (HashIterator iter = ht_iter_begin(&commands); !ht_iter_cmp(iter, ht_iter_end(&commands)); iter = ht_iter_next(iter)) { struct CmdTemplate* cmd = (struct CmdTemplate*)ht_iter_get(iter); kprintf("%-20s", cmd->name); for (unsigned j = 0; cmd->arg_fmt[j]; ++j) kprintf("%c ", 'a' + j); kprintf("\r\n"); } #endif return RC_OK; }
static VFSInfo vfs_vdir_query(VFSNode *vdir) { return (VFSInfo) { .exists = true, .is_dir = true, }; } static void vfs_vdir_free(VFSNode *vdir) { ht_str2ptr_t *ht = VDIR_TABLE(vdir); ht_str2ptr_iter_t iter; ht_iter_begin(ht, &iter); for(; iter.has_data; ht_iter_next(&iter)) { vfs_decref(iter.value); } ht_iter_end(&iter); ht_destroy(ht); free(ht); }
/// Hook provided by the parser for matching of command names (TAB completion) for readline const char* parser_rl_match(UNUSED_ARG(void *,dummy), const char *word, int word_len) { HashIterator cur; HashIterator end = ht_iter_end(&commands); const char *found = NULL; for (cur = ht_iter_begin(&commands); !ht_iter_cmp(cur, end); cur = ht_iter_next(cur)) { const struct CmdTemplate* cmdp = (const struct CmdTemplate*)ht_iter_get(cur); if (strncmp(cmdp->name, word, word_len) == 0) { // If there was another matching word, it means that we have a multiple // match: then return NULL. if (found) return NULL; found = cmdp->name; } } return found; }
/** * Processes the given command line according to the configuration of the optin object * * o - The optin object * argc - Pointer to the argument count, should include the program name * argv - Pointer to the arguments, *argv[0] should be the program name * * On exit, argc and argv will be modified to be the arguments left over after option processing * RETURNS: zero if options were parsed successfully, nonzero if there was an error */ int optin_process(optin* o, int* argc, char** argv) { int i, ret; int is_long_option; int next_argv; /* Used to keep track of the next valid argv slot for shuffling non-option args */ char* arg, *opt, *value; _option* option; _option_wrapper* wrapper; hashtable_iter* opt_iter; enum { STATE_NORMAL, STATE_IN_OPTION} state; is_long_option = 0; state = STATE_NORMAL; o->argc = *argc; o->argv = argv; next_argv = 1; ret = 0; i = 1; /* Skip over the program name */ while (i < o->argc) { arg = o->argv[i]; switch(state) { case STATE_NORMAL: if (*arg == '-') { state = STATE_IN_OPTION; opt = arg+1; continue; } argv[next_argv++] = o->argv[i]; break; case STATE_IN_OPTION: (*argc)--; is_long_option = (*opt == '-'); value = 0; if (is_long_option) { opt++; if (*opt == '\0') { /* We have a lone --, that means to stop arg processing NOW */ i++; goto done; } /* We need to check if there's an equal sign in the longopt somewhere */ value = opt; while (*value) { if (*value == '=' && is_long_option) { *value++ = '\0'; /* Modify string so opt ends at where equals sign was */ break; } else if (*value == '=') { fprintf(stderr, "Equals sign not allowed in short option\n"); ret = OPTIN_ERR_INVALID_OPTION; goto done; } value++; } if (!*value) { value = 0; } } if (*opt != '\0') { /* TODO: What do we do if it does? */ option = _query(o->options, opt); if (!option) { fprintf(stderr, "Unrecognized option: '%s'\n", opt); ret = OPTIN_ERR_INVALID_OPTION; goto done; } else if (value && !option->accepts_value) { fprintf(stderr, "Option '%s' does not take a value\n", opt); ret = OPTIN_ERR_INVALID_VALUE; goto done; } if (option->accepts_value && !value) { /* Let's see if our next arg can function as a value */ if ((i + 1) == o->argc || *(o->argv[i+1]) == '-') { fprintf(stderr, "Option '%s' requires a value\n", opt); ret = OPTIN_ERR_VALUE_MISSING; goto done; } else { (*argc)--; } value = o->argv[i+1]; } ret = optin_process_option(o, opt, value); if (ret != 0) { goto done; } } state = STATE_NORMAL; break; } if (value && value == o->argv[i+1]) { /* Need to skip over the value we used */ i += 2; } else { i++; } } done: /* Analyze required options */ opt_iter = ht_iter_begin(o->options); while (opt_iter) { wrapper = ht_value(opt_iter); /* Only consider the real options, ignore aliases so we don't check the same option twice */ if (wrapper && !wrapper->alias) { option = wrapper->o; if (option && option->has_default == OPTIN_REQUIRED && !option->set) { fprintf(stderr, "Missing required option '%s'\n", option->name); ret = OPTIN_ERR_OPTION_MISSING; break; } } opt_iter = ht_iter_next(opt_iter); } /* Reorder any args after the options in the caller's argv array */ for (; i < o->argc; i++) { argv[next_argv++] = o->argv[i]; } return ret; }