home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- *
- * Generic option parsing
- */
-
- #include "config.h"
- #include "options.h"
-
- static char **save_argv, *usage_mesg;
- static struct option_descr *save_optd;
-
-
- char *program_name(av)
- char **av;
- {
- char *cp;
-
- /* skip "/path/" part of program name */
- if (cp = strrchr(*av, '/'))
- return cp + 1;
- else
- return *av;
- }
-
- static dump_options(type, tail)
- int type;
- char *tail;
- {
- register struct option_descr *od;
- int any = 0;
-
- for (od = save_optd; od->option_letter; od++) {
- if (od->option_type != type) continue;
- fprintf(stderr, any ? "%c" : " -%c", od->option_letter );
- any++;
- }
-
- if (any && tail && tail[0]) {
- fprintf(stderr, "%s", tail);
- }
- }
-
- static error(message, option_letter)
- char *message, option_letter;
- {
- char *prog_name = program_name(save_argv);
-
- fprintf(stderr, "%s: ", prog_name);
- fprintf(stderr, message, option_letter);
- fputc('\n', stderr);
-
- fprintf(stderr, "usage: %s", prog_name);
-
- dump_options(1, "");
- dump_options(2, " STR");
- dump_options(3, " [STR]");
- dump_options(4, " NUM");
- dump_options(5, " [NUM]");
-
- if (usage_mesg) fprintf(stderr, usage_mesg);
- fputc(NL, stderr);
-
- nn_exit(9);
- }
-
- parse_options(ac, av, envname, options, usage)
- int ac;
- char **av, *envname;
- struct option_descr options[];
- char *usage;
- {
- register char *cp, opt;
- register struct option_descr *od;
- extern int atoi();
- int files;
- char **names;
- char *envinit;
-
- save_argv = av;
- save_optd = options;
-
- if (options == NULL) return 0;
-
- usage_mesg = usage;
-
- --ac;
- names = ++av;
- files = 0;
-
- envinit = envname ? getenv(envname) : NULL;
- cp = envinit;
-
- next_option:
-
- if (envinit) {
- while (*cp && isspace(*cp)) cp++;
- if (*cp == '-') {
- cp++;
- goto next_option;
- }
- if (*cp == NUL) {
- envinit = NULL;
- goto next_option;
- }
- } else
- if (cp == NULL || *cp == NUL) {
- if ((cp = *av++) == NULL) {
- *names = NULL;
- return files;
- }
- ac--;
-
- if (*cp != '-') {
- *names++ = cp;
- cp = NULL;
- files++;
- goto next_option;
- }
-
- cp++; /* skip - */
- }
-
- opt = *cp++;
-
- for (od = options; od->option_letter; od++) {
- if (od->option_letter != opt) continue;
-
- switch (od->option_type) {
-
- case 1: /* BOOL_OPTION */
-
- *((int *)(od->option_address)) = !*((int *)(od->option_address));
- goto next_option;
-
- case 2: /* STRING_OPTION */
- case 3: /* OPTIONAL_STRING */
-
- /* -oSTR or -o STR */
-
- while (*cp && isspace(*cp)) cp++;
-
- if (*cp == NUL) {
- if (envinit || ac == 0) {
- if (od->option_type == 3) goto opt_str;
- error("missing string argumet to -%c", opt);
- }
- cp = *av++;
- ac--;
- }
-
- if (od->option_type == 3 && *cp == '-') {
- cp++;
- goto opt_str;
- }
-
- *(od->option_address) = cp;
-
- if (envinit) {
- while (*cp && !isspace(*cp)) cp++;
- if (*cp) *cp++ = NUL;
- } else
- cp = NULL;
-
- goto next_option;
-
- opt_str:
- *(od->option_address) = od->option_default;
- goto next_option;
-
- case 4:
- case 5:
-
- /* -oN or -o N */
-
- while (*cp && isspace(*cp)) cp++;
-
- if (*cp) {
- if (!isdigit(*cp)) {
- if (od->option_type == 5) goto opt_int;
- error("non-numeric argument to -%c", opt);
- }
- } else {
- if (envinit || ac == 0 || !isdigit(**av)) {
- if (od->option_type == 5) goto opt_int;
- error("missing argument to -%c", opt);
- }
-
- cp = *av++;
- ac--;
- }
- *((int *)(od->option_address)) = atoi(cp);
- while (isdigit(*cp)) cp++;
- goto next_option;
-
- opt_int:
- *((int *)(od->option_address)) = (int)(od->option_default);
- goto next_option;
- }
- }
-
- error("unknown option '-%c'", opt);
- /*NOTREACHED*/
- }
-