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