📄 options.c
字号:
else { ent = 0; if (opt->nelt) *opt->nelt = 0; nvars = opt->nvars; } /* parse all arguments */ while (index < argc && cnt < nvars && argv[index][0] != '-') { tmp = strtod(argv[index], &endp); if (*endp) { /* could not parse entire argument */ fatal("could not parse argument `%s' of option `%s'", argv[index], opt->name); } if (tmp < FLT_MIN || tmp > FLT_MAX) { /* over/underflow */ fatal("FP over/underflow for argument `%s' of option `%s'", argv[index], opt->name); } /* else, argument converted correctly */ opt->variant.for_float.var[ent] = (float)tmp; if (opt->nelt) (*opt->nelt)++; cnt++; index++; ent++; } break; case oc_double: /* this option needs at least one argument */ if (index >= argc || argv[index][0] == '-') { /* no arguments available */ fatal("option `%s' requires an argument", opt->name); } cnt = 0; if (opt->accrue) { ent = opt->nelt ? *opt->nelt : 0; nvars = 1; if (ent >= opt->nvars) fatal("too many invocations of option `%s'", opt->name); } else { ent = 0; if (opt->nelt) *opt->nelt = 0; nvars = opt->nvars; } /* parse all arguments */ while (index < argc && cnt < nvars && argv[index][0] != '-') { opt->variant.for_double.var[ent] = strtod(argv[index], &endp); if (*endp) { /* could not parse entire argument */ fatal("could not parse argument `%s' of option `%s'", argv[index], opt->name); } /* else, argument converted correctly */ if (opt->nelt) (*opt->nelt)++; cnt++; index++; ent++; } break; case oc_enum: /* this option needs at least one argument */ if (index >= argc || argv[index][0] == '-') { /* no arguments available */ fatal("option `%s' requires an argument", opt->name); } cnt = 0; if (opt->accrue) { ent = opt->nelt ? *opt->nelt : 0; nvars = 1; if (ent >= opt->nvars) fatal("too many invocations of option `%s'", opt->name); } else { ent = 0; if (opt->nelt) *opt->nelt = 0; nvars = opt->nvars; } /* parse all arguments */ while (index < argc && cnt < nvars && argv[index][0] != '-') { if (!bind_to_enum(argv[index], opt->variant.for_enum.emap, opt->variant.for_enum.eval, opt->variant.for_enum.emap_sz, &opt->variant.for_enum.var[ent])) { /* could not parse entire argument */ fatal("could not parse argument `%s' of option `%s'", argv[index], opt->name); } /* else, argument converted correctly */ if (opt->nelt) (*opt->nelt)++; cnt++; index++; ent++; } break; case oc_flag: /* check if this option has at least one argument */ if (index >= argc || argv[index][0] == '-') { /* no arguments available, default value for flag is true */ opt->variant.for_enum.var[0] = TRUE; break; } /* else, parse boolean argument(s) */ cnt = 0; if (opt->accrue) { ent = opt->nelt ? *opt->nelt : 0; nvars = 1; if (ent >= opt->nvars) fatal("too many invocations of option `%s'", opt->name); } else { ent = 0; if (opt->nelt) *opt->nelt = 0; nvars = opt->nvars; } while (index < argc && cnt < nvars && argv[index][0] != '-') { if (!bind_to_enum(argv[index], opt->variant.for_enum.emap, opt->variant.for_enum.eval, opt->variant.for_enum.emap_sz, &opt->variant.for_enum.var[ent])) { /* could not parse entire argument, default to true */ opt->variant.for_enum.var[ent] = TRUE; break; } else { /* else, argument converted correctly */ if (opt->nelt) (*opt->nelt)++; cnt++; index++; ent++; } } break; case oc_string: /* this option needs at least one argument */ if (index >= argc || argv[index][0] == '-') { /* no arguments available */ fatal("option `%s' requires an argument", opt->name); } cnt = 0; if (opt->accrue) { ent = opt->nelt ? *opt->nelt : 0; nvars = 1; if (ent >= opt->nvars) fatal("too many invocations of option `%s'", opt->name); } else { ent = 0; if (opt->nelt) *opt->nelt = 0; nvars = opt->nvars; } /* parse all arguments */ while (index < argc && cnt < nvars && argv[index][0] != '-') { opt->variant.for_string.var[ent] = argv[index]; if (opt->nelt) (*opt->nelt)++; cnt++; index++; ent++; } break; default: panic("bogus option class"); } return index;}/* forward declarations */static void process_file(struct opt_odb_t *odb, char *fname, int depth);static void dump_config(struct opt_odb_t *odb, char *fname);/* process a command line, internal version that tracks `-config' depth */static void__opt_process_options(struct opt_odb_t *odb, /* option data base */ int argc, /* number of arguments */ char **argv, /* argument array */ int depth) /* `-config' option depth */{ int index, do_dumpconfig; char *dumpconfig_name; index = 0; do_dumpconfig = FALSE; dumpconfig_name = NULL; /* visit all command line arguments */ while (index < argc) { /* process any encountered orphans */ while (index < argc && argv[index][0] != '-') { if (depth > 0) { /* orphans are not allowed during config file processing */ fatal("orphan `%s' encountered during config file processing", argv[index]); } /* else, call the user-stalled orphan handler */ if (odb->orphan_fn) { if (!odb->orphan_fn(index+1, argc, argv)) { /* done processing command line */ goto done_processing; } } else { /* no one claimed this option */ fatal("orphan argument `%s' was unclaimed", argv[index]); } /* go to next option */ } /* done with command line? */ if (index == argc) { /* done processing command line */ goto done_processing; } /* when finished, argv[index] is an option to parse */ /* process builtin options */ if (!strcmp(argv[index], "-config")) { /* handle `-config' builtin option */ index++; if (index >= argc || argv[index][0] == '-') { /* no arguments available */ fatal("option `-config' requires an argument"); } process_file(odb, argv[index], depth); index++; } else if (!strcmp(argv[index], "-dumpconfig")) { /* this is performed *last* */ do_dumpconfig = TRUE; /* handle `-dumpconfig' builtin option */ index++; if (index >= argc || (argv[index][0] == '-' && argv[index][1] != '\0')) { /* no arguments available */ fatal("option `-dumpconfig' requires an argument"); } dumpconfig_name = argv[index]; index++; } else { /* process user-installed option */ index = process_option(odb, index, argc, argv); } } done_processing: if (do_dumpconfig) dump_config(odb, dumpconfig_name);}/* process command line arguments */voidopt_process_options(struct opt_odb_t *odb, /* option data base */ int argc, /* number of arguments */ char **argv) /* argument array */{ /* need at least two entries to have an option */ if (argc < 2) return; /* process the command, starting at `-config' depth zero */ __opt_process_options(odb, argc-1, argv+1, /* top level */0);}/* handle `-config' builtin option */#define MAX_LINE_ARGS 256static voidprocess_file(struct opt_odb_t *odb, char *fname, int depth){ int largc; char *largv[MAX_LINE_ARGS]; char line[1024], *p, *q; FILE *fd; fd = fopen(fname, "r"); if (!fd) fatal("could not open configuration file `%s'", fname); while (!feof(fd)) {#if 0 fprintf(stderr, "!feof(fd): %d, strlen(line): %d, line: %s\n", !feof(fd), strlen(line), line);#endif line[0] = '\n'; /* read a line from the file and chop */ fgets(line, 1024, fd); if (line[0] == '\0' || line[0] == '\n') continue; if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; /* process one line from the file */ largc = 0; p = line; while (*p) { /* skip whitespace */ while (*p != '\0' && (*p == ' ' || *p == '\t')) p++; /* ignore empty lines and comments */ if (*p == '\0' || *p == '#') break; /* skip to the end of the argument */ q = p; while (*q != '\0' && *q != ' ' && *q != '\t') q++; if (*q) { *q = '\0'; q++; } /* marshall an option array */ largv[largc++] = mystrdup(p); if (largc == MAX_LINE_ARGS) fatal("option line too complex in file `%s'", fname); /* go to next argument */ p = q; } /* process the line */ if (largc > 0) __opt_process_options(odb, largc, largv, depth+1); /* else, empty line */ } fclose(fd);}/* print the value of an option */voidopt_print_option(struct opt_opt_t *opt,/* option variable */ FILE *fd) /* output stream */{ int i, nelt; switch (opt->oc) { case oc_int: if (opt->nelt) nelt = *(opt->nelt); else nelt = 1; for (i=0; i<nelt; i++) { fprintf(fd, opt->format, opt->variant.for_int.var[i]); fprintf(fd, " "); } break; case oc_uint: if (opt->nelt) nelt = *(opt->nelt); else nelt = 1; for (i=0; i<nelt; i++) { fprintf(fd, opt->format, opt->variant.for_uint.var[i]); fprintf(fd, " "); } break; case oc_float: if (opt->nelt) nelt = *(opt->nelt); else nelt = 1; for (i=0; i<nelt; i++) { fprintf(fd, opt->format, (double)opt->variant.for_float.var[i]); fprintf(fd, " "); } break; case oc_double: if (opt->nelt) nelt = *(opt->nelt); else nelt = 1; for (i=0; i<nelt; i++) { fprintf(fd, opt->format, opt->variant.for_double.var[i]); fprintf(fd, " "); } break; case oc_enum: if (opt->nelt) nelt = *(opt->nelt); else nelt = 1; for (i=0; i<nelt; i++) { char *estr = bind_to_str(opt->variant.for_enum.var[i], opt->variant.for_enum.emap, opt->variant.for_enum.eval, opt->variant.for_enum.emap_sz); if (!estr) panic("could not bind enum `%d' for option `%s'", opt->variant.for_enum.var[i], opt->name); fprintf(fd, opt->format, estr); fprintf(fd, " "); } break; case oc_flag:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -