static enum wav2prg_bool find_single_character_match(const struct option_names *names, const char option, uint32_t *option_index, char **last_matched_option){ free(*last_matched_option); *last_matched_option = malloc(2); (*last_matched_option)[0] = option; (*last_matched_option)[1] = 0; return search_option(names, *last_matched_option, option_index); }
static struct xemutools_config_st *search_option_query ( const char *name, enum xemutools_option_type type ) { struct xemutools_config_st *p = search_option(name); if (!p) FATAL("Internal ConfigDB error: not defined option '%s' is queried inside Xemu!", name); if (p->type == type || (p->type == OPT_NO && type == OPT_BOOL)) return p; FATAL("Internal ConfigDB error: queried option '%s' with different type as defined inside Xemu!", name); }
static enum wav2prg_bool find_multiple_character_match(const struct option_names *names, const char *option, uint32_t *option_index, char **last_matched_option, uint32_t *consumed_chars){ char *equal_pos; free(*last_matched_option); *last_matched_option = strdup(option); equal_pos = strchr(*last_matched_option, '='); if (equal_pos) *equal_pos = 0; *consumed_chars = strlen(*last_matched_option) - 1; return search_option(names, *last_matched_option, option_index); }
bool DHCPv6::has_reconfigure_accept() const { return search_option(RECONF_ACCEPT); }
bool DHCPv6::has_rapid_commit() const { return search_option(RAPID_COMMIT); }
static int xemucfg_parse_commandline ( int argc, char **argv, const char *only_this ) { argc--; argv++; while (argc) { struct xemutools_config_st *o; if (*argv[0] != '/' && *argv[0] != '-') OPT_ERROR_CMDLINE("Invalid option '%s', must start with '-'", *argv); if (!strcasecmp(*argv + 1, "h") || !strcasecmp(*argv + 1, "help") || !strcasecmp(*argv + 1, "-help") || !strcasecmp(*argv + 1, "?")) { if (!only_this || (only_this && !strcasecmp(only_this, "help"))) { dump_help(); return 1; } argc--; argv++; continue; } o = search_option(*argv + 1); if (!o) OPT_ERROR_CMDLINE("Unknown option '%s'", *argv); argc--; argv++; if (o->type == OPT_NO) { if (only_this && strcasecmp(only_this, o->name)) continue; o->value = (void*)1; } else { const char *s; if (!argc) OPT_ERROR_CMDLINE("Option '%s' requires a parameter, but end of command line detected.", argv[-1]); if (only_this && strcasecmp(only_this, o->name)) goto do_not; switch (o->type) { case OPT_STR: if (o->value) free(o->value); if (check_string_size(*argv)) OPT_ERROR_CMDLINE("Option '%s' has too long value.", argv[1]); o->value = xemu_strdup(*argv); break; case OPT_BOOL: s = set_boolean_value(*argv, &o->value); if (s) OPT_ERROR_CMDLINE("Option '%s' %s, but '%s' is detected.", argv[-1], s, *argv); break; case OPT_NUM: o->value = (void*)(intptr_t)atoi(*argv); break; case OPT_PROC: s = (*(xemucfg_parser_callback_func_t)(o->value))(o, argv[-1] + 1, *argv); if (s) OPT_ERROR_CMDLINE("Option's '%s' parameter '%s' is invalid: %s", argv[-1], *argv, s); break; case OPT_NO: break; // make GCC happy to handle all cases ... } do_not: argc--; argv++; } } return 0; }
int xemucfg_parse_config_file ( const char *filename_in, int open_can_fail ) { char *p, cfgmem[CONFIG_FILE_MAX_SIZE + 1]; int lineno = xemu_load_file(filename_in, cfgmem, 0, CONFIG_FILE_MAX_SIZE, open_can_fail ? NULL : "Cannot load specified configuration file."); if (lineno < 0) { if (open_can_fail) return 1; XEMUEXIT(1); } cfgmem[lineno] = 0; // terminate string if (strlen(cfgmem) != lineno) FATAL("Config: bad config file (%s), contains NULL character (not a text file)", xemu_load_filepath); p = cfgmem; lineno = 1; // line number counter in read config file from now do { char *p1, *pn; // Skip white-spaces at the beginning of the line while (*p == ' ' || *p == '\t') p++; // Search for end of line (relaxed check, too much mixed line-endings I've seen already within ONE config file failed with simple fgets() etc method ...) p1 = strstr(p, "\r\n"); if (p1) pn = p1 + 2; else { p1 = strstr(p, "\n\r"); if (p1) pn = p1 + 2; else { p1 = strchr(p, '\n'); if (p1) pn = p1 + 1; else { p1 = strchr(p, '\r'); pn = p1 ? p1 + 1 : NULL; } } } if (p1) *p1 = 0; // terminate line string at EOL marker p1 = strchr(p, '#'); if (p1) *p1 = 0; // comment - if any - is also excluded // Chop white-spaces off from the end of the line p1 = p + strlen(p); while (p1 > p && (p1[-1] == '\t' || p1[-1] == ' ')) *(--p1) = 0; // If line is not empty, separate key/val (if there is) and see what it means if (*p) { struct xemutools_config_st *o; const char *s; p1 = p; while (*p1 && *p1 != '\t' && *p1 != ' ' && *p1 != '=') p1++; if (*p1) { *(p1++) = 0; while (*p1 == '\t' || *p1 == ' ' || *p1 == '=') p1++; if (!*p1) p1 = NULL; } else p1 = NULL; printf("Line#%d = \"%s\",\"%s\"" NL, lineno, p, p1 ? p1 : "<no-specified>"); o = search_option(p); if (!o) FATAL("Config file (%s) error at line %d: keyword '%s' is unknown.", xemu_load_filepath, lineno, p); if (o->type != OPT_NO && !p1) FATAL("Config file (%s) error at line %d: keyword '%s' requires a value.", xemu_load_filepath, lineno, p); switch (o->type) { case OPT_STR: if (o->value) free(o->value); if (check_string_size(p1)) FATAL("Config file (%s) error at line %d: keyword '%s' has too long value", xemu_load_filepath, lineno, p); o->value = xemu_strdup(p1); break; case OPT_BOOL: s = set_boolean_value(p1, &o->value); if (s) FATAL("Config file (%s) error at line %d: keyword '%s' %s, but '%s' is detected.", xemu_load_filepath, lineno, p, s, p1); break; case OPT_NUM: o->value = (void*)(intptr_t)atoi(p1); break; case OPT_NO: if (p1) FATAL("Config file (%s) error at line %d: keyword '%s' DOES NOT require any value, but '%s' is detected.", xemu_load_filepath, lineno, p, p1); o->value = (void*)1; break; case OPT_PROC: s = (*(xemucfg_parser_callback_func_t)(o->value))(o, p, p1); if (s) FATAL("Config file (%s) error at line %d: keyword's '%s' parameter '%s' is invalid: %s", xemu_load_filepath, lineno, p, p1, s); break; } } // Prepare for next line p = pn; // start of next line (or EOF if NULL) lineno++; } while (p); return 0; }
enum wav2prg_bool yet_another_getopt(const struct get_option *options, uint32_t *argc, char **argv){ uint32_t total_options = 0, total_names = 0, i; struct option_names* names = calloc(1, sizeof(struct option_names)); uint32_t current_arg_num = 0, current_arg_pos = 0, num_arg_non_options = 0; uint32_t *arg_non_options = malloc(*argc * sizeof(uint32_t)); enum { beginning_of_one_arg, single_dash_at_beginning, double_dash_at_beginning, one_letter_arg, multi_letter_arg, may_be_argument_option, must_be_argument_option, next_is_argument_option, after_multi_letter_no_argument } state = beginning_of_one_arg; uint32_t found_option; enum wav2prg_bool ok_so_far = wav2prg_true; const struct get_option *options_to_get_names_from; char *last_matched_option = NULL; for(options_to_get_names_from = options; options_to_get_names_from->names; options_to_get_names_from++){ const char **name; for (name = options_to_get_names_from->names; *name != NULL; name++){ if(!search_option(names, *name, NULL)){ names = realloc(names, sizeof(struct option_names) * (total_names + 2)); names[total_names ].option_name = strdup(*name) ; names[total_names++].option_index = total_options; names[total_names ].option_name = NULL; } } total_options++; } while(current_arg_num < *argc && ok_so_far){ enum { keep_going, argument_consumed, argument_is_not_option } state_of_current_arg = keep_going; const char* current_arg = argv[current_arg_num] + current_arg_pos; switch(state){ case beginning_of_one_arg: switch(current_arg[0]){ case '-': state = single_dash_at_beginning; break; default: state_of_current_arg = argument_is_not_option; break; } break; case single_dash_at_beginning: switch(current_arg[0]){ case '-': state = double_dash_at_beginning; break; case 0: state_of_current_arg = argument_is_not_option; default: ok_so_far = find_single_character_match(names, current_arg[0], &found_option, &last_matched_option); if (ok_so_far){ switch(options[found_option].arguments){ case option_no_argument: ok_so_far = options[found_option].callback(NULL, options[found_option].callback_parameter); state = one_letter_arg; break; case option_may_have_argument: state = may_be_argument_option; break; case option_must_have_argument: state = must_be_argument_option; break; } } else printf("Option %c unknown\n", current_arg[0]); break; } break; case one_letter_arg: switch(current_arg[0]){ case 0: state = beginning_of_one_arg; break; default: ok_so_far = find_single_character_match(names, current_arg[0], &found_option, &last_matched_option); if (ok_so_far){ switch(options[found_option].arguments){ case option_no_argument: ok_so_far = options[found_option].callback(NULL, options[found_option].callback_parameter); state = one_letter_arg; break; case option_may_have_argument: state = may_be_argument_option; break; case option_must_have_argument: state = must_be_argument_option; break; } } else printf("Option %c unknown\n", current_arg[0]); break; } break; case may_be_argument_option: switch(current_arg[0]){ case 0: ok_so_far = options[found_option].callback(NULL, options[found_option].callback_parameter); state = beginning_of_one_arg; break; case '=': current_arg_pos++; current_arg ++; /* fallback */ default: ok_so_far = options[found_option].callback(current_arg, options[found_option].callback_parameter); state_of_current_arg = argument_consumed; state = beginning_of_one_arg; break; } break; case must_be_argument_option: switch(current_arg[0]){ case 0: state = next_is_argument_option; break; case '=': current_arg_pos++; current_arg ++; /* fallback */ default: ok_so_far = options[found_option].callback(current_arg, options[found_option].callback_parameter); state_of_current_arg = argument_consumed; state = beginning_of_one_arg; break; } break; case next_is_argument_option: ok_so_far = options[found_option].callback(current_arg, options[found_option].callback_parameter); state_of_current_arg = argument_consumed; state = beginning_of_one_arg; break; case double_dash_at_beginning: switch(current_arg[0]){ case '-': state_of_current_arg = argument_is_not_option; state = beginning_of_one_arg; argv[current_arg_num] += 2; break; default: { uint32_t matched; ok_so_far = find_multiple_character_match(names, current_arg, &found_option, &last_matched_option, &matched); if(ok_so_far){ current_arg_pos += matched; current_arg += matched; switch(options[found_option].arguments){ case option_no_argument: ok_so_far = options[found_option].callback(NULL, options[found_option].callback_parameter); state = after_multi_letter_no_argument; break; case option_may_have_argument: state = may_be_argument_option; break; case option_must_have_argument: state = must_be_argument_option; break; } } else printf("Option %s unknown\n", current_arg); } break; } break; case after_multi_letter_no_argument: switch(current_arg[0]){ case 0: state = beginning_of_one_arg; break; default: printf("Argument given to option %s\n", last_matched_option); ok_so_far = wav2prg_false; break; } break; } if (state_of_current_arg != keep_going){ if(state_of_current_arg == argument_is_not_option) arg_non_options[num_arg_non_options++] = current_arg_num; current_arg_pos += strlen(current_arg); current_arg += strlen(current_arg); } if (current_arg[0] == 0){ current_arg_num++; current_arg_pos = 0; } else current_arg_pos++; } if (state == next_is_argument_option){ printf("No argument given to option %s\n", last_matched_option); ok_so_far = wav2prg_false; } for(i = 0; names[i].option_name; i++) free(names[i].option_name); free(names); for (i = 0; i < num_arg_non_options; i++) argv[i] = argv[arg_non_options[i]]; *argc = num_arg_non_options; free(arg_non_options); free(last_matched_option); return ok_so_far; }