home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume22 / nn6.4 / part19 / options.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-07  |  3.7 KB  |  205 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Generic option parsing
  5.  */
  6.  
  7. #include "config.h"
  8. #include "options.h"
  9.  
  10. static char **save_argv, *usage_mesg;
  11. static struct option_descr *save_optd;
  12.  
  13.  
  14. char *program_name(av)
  15. char **av;
  16. {
  17.     char *cp;
  18.  
  19.     /* skip "/path/" part of program name */
  20.     if (cp = strrchr(*av, '/'))
  21.     return cp + 1;
  22.     else
  23.     return *av;
  24. }
  25.  
  26. static dump_options(type, tail)
  27. int type;
  28. char *tail;
  29. {
  30.     register struct option_descr *od;
  31.     int any = 0;
  32.  
  33.     for (od = save_optd; od->option_letter; od++) {
  34.     if (od->option_type != type) continue;
  35.     fprintf(stderr, any ? "%c" : " -%c", od->option_letter );
  36.     any++;
  37.     }
  38.  
  39.     if (any && tail && tail[0]) {
  40.     fprintf(stderr, "%s", tail);
  41.     }
  42. }
  43.  
  44. static error(message, option_letter)
  45. char *message, option_letter;
  46. {
  47.     char *prog_name = program_name(save_argv);
  48.  
  49.     fprintf(stderr, "%s: ", prog_name);
  50.     fprintf(stderr, message, option_letter);
  51.     fputc('\n', stderr);
  52.  
  53.     fprintf(stderr, "usage: %s", prog_name);
  54.  
  55.     dump_options(1, "");
  56.     dump_options(2, " STR");
  57.     dump_options(3, " [STR]");
  58.     dump_options(4, " NUM");
  59.     dump_options(5, " [NUM]");
  60.  
  61.     if (usage_mesg) fprintf(stderr, usage_mesg);
  62.     fputc(NL, stderr);
  63.  
  64.     nn_exit(9);
  65. }
  66.  
  67. parse_options(ac, av, envname, options, usage)
  68. int ac;
  69. char **av, *envname;
  70. struct option_descr options[];
  71. char *usage;
  72. {
  73.     register char *cp, opt;
  74.     register struct option_descr *od;
  75.     extern int atoi();
  76.     int files;
  77.     char **names;
  78.     char *envinit;
  79.  
  80.     save_argv = av;
  81.     save_optd = options;
  82.  
  83.     if (options == NULL) return 0;
  84.  
  85.     usage_mesg = usage;
  86.  
  87.     --ac;
  88.     names = ++av;
  89.     files = 0;
  90.  
  91.     envinit = envname ? getenv(envname) : NULL;
  92.     cp = envinit;
  93.  
  94.  next_option:
  95.  
  96.     if (envinit) {
  97.     while (*cp && isspace(*cp)) cp++;
  98.     if (*cp == '-') {
  99.         cp++;
  100.         goto next_option;
  101.     }
  102.     if (*cp == NUL) {
  103.         envinit = NULL;
  104.         goto next_option;
  105.     }
  106.     } else
  107.     if (cp == NULL || *cp == NUL) {
  108.         if ((cp = *av++) == NULL) {
  109.         *names = NULL;
  110.         return files;
  111.         }
  112.         ac--;
  113.  
  114.         if (*cp != '-') {
  115.         *names++ = cp;
  116.         cp = NULL;
  117.         files++;
  118.         goto next_option;
  119.         }
  120.  
  121.         cp++; /* skip - */
  122.     }
  123.  
  124.     opt = *cp++;
  125.  
  126.     for (od = options; od->option_letter; od++) {
  127.     if (od->option_letter != opt) continue;
  128.  
  129.     switch (od->option_type) {
  130.  
  131.      case 1:    /* BOOL_OPTION */
  132.  
  133.         *((int *)(od->option_address)) = !*((int *)(od->option_address));
  134.         goto next_option;
  135.  
  136.      case 2:    /* STRING_OPTION */
  137.      case 3:    /* OPTIONAL_STRING */
  138.  
  139.         /* -oSTR or -o STR */
  140.  
  141.         while (*cp && isspace(*cp)) cp++;
  142.  
  143.         if (*cp == NUL) {
  144.         if (envinit || ac == 0) {
  145.             if (od->option_type == 3) goto opt_str;
  146.             error("missing string argumet to -%c", opt);
  147.         }
  148.         cp = *av++;
  149.         ac--;
  150.         }
  151.  
  152.         if (od->option_type == 3 && *cp == '-') {
  153.         cp++;
  154.         goto opt_str;
  155.         }
  156.  
  157.         *(od->option_address) = cp;
  158.  
  159.         if (envinit) {
  160.         while (*cp && !isspace(*cp)) cp++;
  161.         if (*cp) *cp++ = NUL;
  162.         } else
  163.         cp = NULL;
  164.  
  165.         goto next_option;
  166.  
  167.      opt_str:
  168.         *(od->option_address) = od->option_default;
  169.         goto next_option;
  170.  
  171.      case 4:
  172.      case 5:
  173.  
  174.         /* -oN or -o N */
  175.  
  176.         while (*cp && isspace(*cp)) cp++;
  177.  
  178.         if (*cp) {
  179.         if (!isdigit(*cp)) {
  180.             if (od->option_type == 5) goto opt_int;
  181.             error("non-numeric argument to -%c", opt);
  182.         }
  183.         } else {
  184.         if (envinit || ac == 0 || !isdigit(**av)) {
  185.             if (od->option_type == 5) goto opt_int;
  186.             error("missing argument to -%c", opt);
  187.         }
  188.  
  189.         cp = *av++;
  190.         ac--;
  191.         }
  192.         *((int *)(od->option_address)) = atoi(cp);
  193.         while (isdigit(*cp)) cp++;
  194.         goto next_option;
  195.  
  196.      opt_int:
  197.         *((int *)(od->option_address)) = (int)(od->option_default);
  198.         goto next_option;
  199.     }
  200.     }
  201.  
  202.     error("unknown option '-%c'", opt);
  203.     /*NOTREACHED*/
  204. }
  205.