home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / k / ksh48.zip / sh / getopts.c < prev    next >
C/C++ Source or Header  |  1992-08-25  |  4KB  |  180 lines

  1. /*
  2.  * Reimplementation of SysVr3 sh builtin command "getopts" for S5R2 shell.
  3.  *
  4.  * created by Arnold Robbins
  5.  * modified by Doug Gwyn
  6.  * modified for PD ksh by Eric Gisin
  7.  */
  8.  
  9. #ifndef lint
  10. static char *RCSid = "$Id: getopts.c,v 1.3 1992/08/10 12:02:41 sjg Exp $";
  11. #endif
  12.  
  13. #include "stdh.h"
  14. #include <errno.h>
  15. #include <setjmp.h>
  16. #include "sh.h"
  17.  
  18. #ifdef _BSDI
  19. /* internal getopt conflicts with system getopt prototype */
  20. # define getopt    local_getopt
  21. #endif
  22.  
  23. /*
  24.  * The following is derived from getopt() source placed into the public
  25.  * domain by AT&T (the only time they're known to have done that).
  26.  *
  27.  * It has been modified somewhat to fit into the context of the shell.
  28.  *
  29.  * -D"FASCIST" if you really want to strictly enforce ALL the
  30.  * Command Syntax Standard rules (not recommended).
  31.  */
  32.  
  33. #define GETOPTEOF    (-1)
  34. #define ERR(S, C)    shellf("%s%c\n", (S), (C))
  35.  
  36. static    int    optind;
  37. static char    *optarg;
  38. static int    sp;
  39.  
  40. static int
  41. getopt(argc, argv, opts)
  42.     int argc;
  43.     register char **argv, *opts;
  44. {
  45.     register int c;
  46.     register char *cp;
  47.  
  48.     if (sp == 1)
  49.         if (optind >= argc ||
  50.            argv[optind][0] != '-' || argv[optind][1] == '\0')
  51.             return(GETOPTEOF);
  52.         else if (strcmp(argv[optind], "--") == 0) {
  53.             optind++;
  54.             return(GETOPTEOF);
  55.         }
  56.     c = argv[optind][sp];
  57.     if (c == ':' || (cp=strchr(opts, c)) == NULL) {
  58.         ERR("illegal option -- ", c);
  59.         if (argv[optind][++sp] == '\0') {
  60.             optind++;
  61.             sp = 1;
  62.         }
  63.         optarg = NULL;
  64.         return('?');
  65.     }
  66.     if (*++cp == ':') {
  67. #ifdef FASCIST
  68.         if (sp != 1) {
  69.             ERR("option must not be grouped -- ", c );
  70.             optind++;
  71.             sp = 1;
  72.             optarg = NULL;
  73.             return('?');
  74.         } else
  75. #endif
  76.         if (argv[optind][sp+1] != '\0') {
  77. #ifdef FASCIST
  78.             ERR("option must be followed by whitespace -- ", c );
  79.             optind++;
  80.             sp = 1;
  81.             optarg = NULL;
  82.             return('?');
  83. #else
  84.             optarg = &argv[optind++][sp+1];
  85. #endif
  86.         } else if (++optind >= argc) {
  87.             ERR("option requires an argument -- ", c);
  88.             sp = 1;
  89.             optarg = NULL;
  90.             return('?');
  91.         } else
  92.             optarg = argv[optind++];
  93.         sp = 1;
  94.     } else {
  95.         if (argv[optind][++sp] == '\0') {
  96.             sp = 1;
  97.             optind++;
  98.         }
  99.         optarg = NULL;
  100.     }
  101.     return(c);
  102. }
  103.  
  104. /*
  105.  * The following were created by Arnold Robbins.
  106.  */
  107.  
  108. /* resetopts --- magic code for when OPTIND is reset to 1 */
  109.  
  110. void
  111. resetopts ()
  112. {
  113.     optind = 1;
  114.     sp = 1;
  115. }
  116.  
  117. int
  118. c_getopts(wp)
  119.     char **wp;
  120. {
  121.     int ret;
  122.     register int argc;
  123.     char temp[2];
  124.     char *optstr;            /* list of options */
  125.     char *name;            /* variable to get flag val */
  126.     char **argv;
  127.  
  128.     if ((optstr = *++wp) == NULL || (name = *++wp) == NULL)
  129.         errorf("missing arguments\n");
  130.  
  131.     for (argc = 1; wp[argc] != NULL; argc++)
  132.         ;
  133.  
  134.     if (argc > 1)
  135.         ret = getopt(argc, wp, optstr);
  136.     else {
  137.         if (**(e.loc->argv) == '\0') {
  138.             /*
  139.              * When c_getopts gets called from comexec() it
  140.              * doesn't set up argc/argv in the local block.
  141.              * Maybe this should be done in newblock() but
  142.              * I'm not sure about the implications, and this
  143.              * is the only place I've been bitten so far...
  144.              * JRM
  145.              */
  146.             argc = e.loc->next->argc;
  147.             argv = e.loc->next->argv;
  148.         } else {
  149.             argc = e.loc->argc;
  150.             argv = e.loc->argv;
  151.         }
  152.         ret = getopt(argc+1, argv, optstr);
  153.  
  154.     }
  155.  
  156.     /*
  157.      * set the OPTIND variable in any case, to handle "--" skipping
  158.      * unless it's 1, which would trigger a reset
  159.      */
  160.  
  161.     if (optind != 1)
  162.         setint(global("OPTIND"), (long)optind);
  163.  
  164.     if (ret == GETOPTEOF)        /* end of args */
  165.         return (1);
  166.  
  167.     /*
  168.      * else, got an arg, set the various shell variables
  169.      */
  170.  
  171.     if (optarg != NULL)
  172.         setstr(global("OPTARG"), optarg);
  173.  
  174.     temp[0] = (char) ret;
  175.     temp[1] = '\0';
  176.     setstr(global(name), temp);
  177.  
  178.     return (0);
  179. }
  180.