home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / copt / cset.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-07  |  7.0 KB  |  247 lines

  1. static char rcsid[] = "$Header: cset.c,v 1.1 89/03/03 12:53:22 np Exp $";
  2. /* $Log:    cset.c,v $
  3.  * Revision 1.1  89/03/03  12:53:22  np
  4.  * Initial revision
  5.  * 
  6.  */
  7.  
  8. /*
  9.  * Copyright (C) 1985-1989 Nigel Perry
  10.  *
  11.  * This program is distributed without any warranty.
  12.  * The author and and distributors accept no resposibility
  13.  * to anyone for the consequence of using this program or
  14.  * whether it serves any particular purpose or works at all,
  15.  * unless they say so in writing.
  16.  *
  17.  * Everyone is granted permission to copy, modify and
  18.  * redistribute this program, but only provided that:
  19.  *
  20.  * 1) They do so without financial or material gain.
  21.  *
  22.  * 2) The copyright notice and this notice are preserved on
  23.  *    all copies.
  24.  *
  25.  * 3) The original source is preserved in any redistribution.
  26.  *
  27.  * I hope you find this program useful!
  28.  *
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include "cset.h"
  33. #include "cset.d"
  34.  
  35. #define strequ(a, b) (!strcmp(a,b))
  36.  
  37. extern char *malloc(), *realloc();
  38.  
  39. /* args:
  40.  *    args     - array of char *'s to args (i.e. argv from main())
  41.  *    helpexit - exit program iff help given
  42.  * return:
  43.  *    array of _opt_desc describing options
  44.  */
  45.  
  46. _opt_desc *_cset(args, helpexit) char **args;
  47. {  char *name, *value, *info, *offset, *left, *right;
  48.    int i, type, maxopt, max, score, helpgiven, len;
  49.    _opt_entry *help_entry, *cp, *p;
  50.    int do_help_entry;
  51.    int super;
  52.    _opt_desc *result, *resvec;
  53.    extern _opt_entry _optable[];
  54.    extern char *index();
  55.  
  56.    helpgiven = do_help_entry = 0;
  57.    super = getuid() == 0; /* we be a super user */
  58.  
  59.    /* find largest option number, last entry in _optable is help_entry */
  60.    help_entry = _optable;
  61.    maxopt = 1;
  62.    while( help_entry->_opt_pat ) { help_entry++; maxopt++; }
  63.  
  64.    /* get a vector for the result */
  65.    for(i = 0; args[i]; i++); /* required length */
  66.    resvec = result = (_opt_desc *) malloc( sizeof(_opt_desc) * (i + 1) );
  67.    result[i]._opt_num = -1; /* flag end */
  68.  
  69.    for(i = 0; info = args[i]; i++)
  70.    {  if(*info == '+') /* +option */
  71.       {  name = info + 1;
  72.      type = PLUS_KWD;
  73.      result->_opt_type = '+';
  74.       }
  75.       else if(*info == '-') /* -option */
  76.       {  name = info + 1;
  77.      type = DASH_KWD;
  78.      result->_opt_type = '-';
  79.       }
  80.       else if(value = index(info, '='))
  81.       {  if(value != info) /* option=value */
  82.      {  name = info;
  83.         *value++ = '\0'; /* add eos over =, bump ptr to value */
  84.         if( *value == '\0' && args[i+1] != 0 ) /* option= value */
  85.            value = args[++i];
  86.         type = (SVAL_KWD | NVAL_KWD);
  87.         result->_opt_type = '=';
  88.      }
  89.      else /* =<something> */
  90.      {  value++; /* ptr to <something> */
  91.         if( strequ(value, "=") ) /* display complete option table */
  92.         {  d_optable(0, (_opt_entry *)0, super);
  93.            helpgiven = 1;
  94.            continue; /* don't wan't to scan optable, go direct to next */
  95.         }
  96.         else if( strequ(value, "+") ) /* display long optable */
  97.         {  d_optable(1, (_opt_entry *)0, super);
  98.            helpgiven = 1;
  99.            continue; /* don't wan't to scan optable, go direct to next */
  100.         }
  101.         else if( strequ(value, "#") ) /* display help info */
  102.         {  if(help_entry->_opt_types == 0)
  103.           fprintf(stderr, "Sorry, no help available, see manual\n");
  104.            else
  105.           do_help_entry  = 1;
  106.            helpgiven = 1;
  107.            continue; /* don't wan't to scan optable, go direct to next */
  108.         }
  109.         else /* see if <something> is an option */
  110.         {  /* scan optable for match */
  111.            max = 0; /* best match so far */
  112.            cp = (_opt_entry *)0;
  113.            p = _optable;
  114.            while( p->_opt_pat )
  115.            {  if( super || !(p->_opt_types & PRIV_BIT) )
  116.           {  if( (score = abbrev(p->_opt_pat, value)) > max )
  117.              {  max = score;
  118.             cp = p;
  119.              }
  120.           }
  121.           p++;
  122.            }
  123.            if(cp) /* got a match - print help message */
  124.            {  _opt_adorn(cp->_opt_types, &left, &right);
  125.           len = strlen(left) + strlen(cp->_opt_pat) + strlen(right);
  126.           fprintf(stderr, "%*s%s%s%s%*s%s\n", TAB1, "",
  127.                left, cp->_opt_pat, right,
  128.                TAB3 - (len + TAB1), "",
  129.                cp->_opt_help == (char *)0 ? "(see manual)" : cp->_opt_help);
  130.           helpgiven = 1;
  131.           continue; /* don't wan't to scan optable */
  132.            }
  133.            else /* treat as possible BLNK_KWD */
  134.            {  name = info;
  135.           type = BLNK_KWD | (i == 0 ? COMM_KWD : 0);
  136.           result->_opt_type = ' ';
  137.            }
  138.         }
  139.      }
  140.       }
  141.       else
  142.       {  name = info;
  143.      type = BLNK_KWD | (i == 0 ? COMM_KWD : 0 );
  144.      result->_opt_type = ' ';
  145.       }
  146.  
  147.       /* scan optable for match */
  148.       max = 0; /* best match so far */
  149.       cp = (_opt_entry *)0;
  150.       p = _optable;
  151.       while( p->_opt_pat )
  152.       {  if( super || !(p->_opt_types & PRIV_BIT) ) /* check for PRIV_KWD */
  153.      {  if( p->_opt_types & type ) /* compatible type? */
  154.         {  if( (score = abbrev(p->_opt_pat, name)) > max )
  155.            {  /* better match */
  156.           max = score;
  157.           cp = p;
  158.            }
  159.         }
  160.      }
  161.      p++;
  162.       }
  163.       if(cp)
  164.       {  result->_opt_num = (int)(cp - _optable) + 1;
  165.      switch( cp->_opt_types & type )
  166.      {  case SVAL_KWD:
  167.            result->_opt.sval = value;
  168.            break;
  169.         case NVAL_KWD:
  170.            if( read_num(value, cp->_opt_types, result) == 0 )
  171.            {  result->_opt_num = maxopt + 1; /* read_num failed */
  172.           result->_opt.sval = info; /* return 'looks like' */
  173.            }
  174.            break;
  175.      }
  176.       }
  177.       else if( type == BLNK_KWD )
  178.       {  result->_opt_num = 0; /* flag as a simple string */
  179.      result->_opt.sval = info;
  180.       }
  181.       else
  182.       {  result->_opt_num = maxopt + 1; /* flag as looks like an option */
  183.      result->_opt.sval = info;
  184.       }
  185.       result++; /* bump ptr */
  186.    }
  187.    result->_opt_num = -1; /* flag end */
  188.  
  189.    /* should we do help_entry */
  190.    if( do_help_entry ) switch( help_entry->_opt_types )
  191.    {  case OPT_LIST:
  192.      list_file(help_entry->_opt_help);
  193.      break;
  194.       case OPT_EXEC:
  195.      system(help_entry->_opt_help);
  196.      break;
  197.    }
  198.  
  199.    /* see if we should exit... */
  200.    if( helpexit && helpgiven ) exit(0);
  201.    return(resvec);
  202. }
  203.  
  204. #define CHUNK (sizeof(int) * 10)
  205.  
  206. static read_num(str, type, result) char *str; _opt_desc *result;
  207. {  int base, flag, offset, *mvals, maxnums, i;
  208.  
  209.    flag = 0; /* dont skip leading junk */
  210.    offset = 0;
  211.    base = type & BASE_MASK;
  212.    if( !(type & MVAL_BIT) ) /* single number */
  213.    {  result->_opt.nval = numarg(str, &offset, base, &flag);
  214.       if( flag == 0 || str[offset] != '\0' ) /* bad num or terminator */
  215.      return(0); /* fail */
  216.    }
  217.    else /* multivalued */
  218.    {  maxnums = CHUNK;
  219.       mvals = (int *)malloc(CHUNK);
  220.       i = 1; /* mvals[0] will be number of numbers */
  221.       do
  222.       {  if(i == maxnums) /* run out of space */
  223.      {  maxnums += CHUNK;
  224.         mvals = (int *)realloc(mvals, CHUNK); /* grow it */
  225.      }
  226.      flag = 0;
  227.      mvals[i++] = numarg(str, &offset, base, &flag);
  228.      if(flag == 0) /* bad input */
  229.      {  free(mvals); /* give back vector */
  230.         return(0);
  231.      }
  232.       }  while( str[offset++] != '\0' );
  233.       mvals[0] = i - 1; /* number of numbers found */
  234.       result->_opt.mval = mvals;
  235.    }
  236.    return(1); /* ok */
  237. }
  238.  
  239. static list_file(f) char *f;
  240. {  FILE *in;
  241.    char c;
  242.  
  243.    if( (in = fopen(f, "r")) == NULL ) return;
  244.    while( (c = getc(in)) != EOF ) putc(c, stderr);
  245.    fclose(in);
  246. }
  247.