home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / pdksh-4.9-src.tgz / tar.out / contrib / pdksh / sh / getopts.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  4KB  |  186 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.5 93/05/08 16:00:00 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. #ifdef amigaos
  24. /* redefine it, or it collides with stdlib.h, it's static anyway */
  25. #define getopt(argc,argv,opts) static_getopt(argc,argv,opts)
  26. #endif
  27.  
  28. /*
  29.  * The following is derived from getopt() source placed into the public
  30.  * domain by AT&T (the only time they're known to have done that).
  31.  *
  32.  * It has been modified somewhat to fit into the context of the shell.
  33.  *
  34.  * -D"FASCIST" if you really want to strictly enforce ALL the
  35.  * Command Syntax Standard rules (not recommended).
  36.  */
  37.  
  38. #define GETOPTEOF    (-1)
  39. #define ERR(S, C)    shellf("%s%c\n", (S), (C))
  40.  
  41. static    int    optind;
  42. static char    *optarg;
  43. static int    sp;
  44.  
  45. static int
  46. getopt(argc, argv, opts)
  47.     int argc;
  48.     char * const *argv;
  49.     const char *opts;
  50. {
  51.     register int c;
  52.     register char *cp;
  53.  
  54.     if (sp == 1)
  55.         if (optind >= argc ||
  56.            argv[optind][0] != '-' || argv[optind][1] == '\0')
  57.             return(GETOPTEOF);
  58.         else if (strcmp(argv[optind], "--") == 0) {
  59.             optind++;
  60.             return(GETOPTEOF);
  61.         }
  62.     c = argv[optind][sp];
  63.     if (c == ':' || (cp=strchr(opts, c)) == NULL) {
  64.         ERR("illegal option -- ", c);
  65.         if (argv[optind][++sp] == '\0') {
  66.             optind++;
  67.             sp = 1;
  68.         }
  69.         optarg = NULL;
  70.         return('?');
  71.     }
  72.     if (*++cp == ':') {
  73. #ifdef FASCIST
  74.         if (sp != 1) {
  75.             ERR("option must not be grouped -- ", c );
  76.             optind++;
  77.             sp = 1;
  78.             optarg = NULL;
  79.             return('?');
  80.         } else
  81. #endif
  82.         if (argv[optind][sp+1] != '\0') {
  83. #ifdef FASCIST
  84.             ERR("option must be followed by whitespace -- ", c );
  85.             optind++;
  86.             sp = 1;
  87.             optarg = NULL;
  88.             return('?');
  89. #else
  90.             optarg = &argv[optind++][sp+1];
  91. #endif
  92.         } else if (++optind >= argc) {
  93.             ERR("option requires an argument -- ", c);
  94.             sp = 1;
  95.             optarg = NULL;
  96.             return('?');
  97.         } else
  98.             optarg = argv[optind++];
  99.         sp = 1;
  100.     } else {
  101.         if (argv[optind][++sp] == '\0') {
  102.             sp = 1;
  103.             optind++;
  104.         }
  105.         optarg = NULL;
  106.     }
  107.     return(c);
  108. }
  109.  
  110. /*
  111.  * The following were created by Arnold Robbins.
  112.  */
  113.  
  114. /* resetopts --- magic code for when OPTIND is reset to 1 */
  115.  
  116. void
  117. resetopts ()
  118. {
  119.     optind = 1;
  120.     sp = 1;
  121. }
  122.  
  123. int
  124. c_getopts(wp)
  125.     char **wp;
  126. {
  127.     int ret;
  128.     register int argc;
  129.     char temp[2];
  130.     char *optstr;            /* list of options */
  131.     char *name;            /* variable to get flag val */
  132.     char **argv;
  133.  
  134.     if ((optstr = *++wp) == NULL || (name = *++wp) == NULL)
  135.         errorf("missing arguments\n");
  136.  
  137.     for (argc = 1; wp[argc] != NULL; argc++)
  138.         ;
  139.  
  140.     if (argc > 1)
  141.         ret = getopt(argc, wp, optstr);
  142.     else {
  143.         if (**(e.loc->argv) == '\0') {
  144.             /*
  145.              * When c_getopts gets called from comexec() it
  146.              * doesn't set up argc/argv in the local block.
  147.              * Maybe this should be done in newblock() but
  148.              * I'm not sure about the implications, and this
  149.              * is the only place I've been bitten so far...
  150.              * JRM
  151.              */
  152.             argc = e.loc->next->argc;
  153.             argv = e.loc->next->argv;
  154.         } else {
  155.             argc = e.loc->argc;
  156.             argv = e.loc->argv;
  157.         }
  158.         ret = getopt(argc+1, argv, optstr);
  159.  
  160.     }
  161.  
  162.     /*
  163.      * set the OPTIND variable in any case, to handle "--" skipping
  164.      * unless it's 1, which would trigger a reset
  165.      */
  166.  
  167.     if (optind != 1)
  168.         setint(global("OPTIND"), (long)optind);
  169.  
  170.     if (ret == GETOPTEOF)        /* end of args */
  171.         return (1);
  172.  
  173.     /*
  174.      * else, got an arg, set the various shell variables
  175.      */
  176.  
  177.     if (optarg != NULL)
  178.         setstr(global("OPTARG"), optarg);
  179.  
  180.     temp[0] = (char) ret;
  181.     temp[1] = '\0';
  182.     setstr(global(name), temp);
  183.  
  184.     return (0);
  185. }
  186.