home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume35 / getlongopt / part01 / GetLongOpt.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-21  |  6.4 KB  |  275 lines

  1. /* $Id: GetLongOpt.cc,v 1.1 1993/01/23 14:35:44 mano Exp mano $ */
  2. /* S Manoharan. Advanced Computer Research Institute. Lyon. France */
  3.  
  4. #include "GetLongOpt.h"
  5.  
  6. GetLongOpt::GetLongOpt(const char optmark)
  7. {
  8.    table = last = 0;
  9.    ustring = "[valid options and arguments]";
  10.    enroll_done = 0;
  11.    optmarker = optmark;
  12. }
  13.  
  14. GetLongOpt::~GetLongOpt()
  15. {
  16.    Cell *t = table;
  17.  
  18.    while ( t ) {
  19.       Cell *tmp = t;
  20.       t = t->next;
  21.       delete tmp;
  22.    }
  23. }
  24.  
  25. char *
  26. GetLongOpt::basename(char * const pname) const
  27. {
  28.    char *s;
  29.  
  30.    s = strrchr(pname, '/');
  31.    if ( s == 0 ) s = pname;
  32.    else ++s;
  33.  
  34.    return s;
  35. }
  36.  
  37. int
  38. GetLongOpt::enroll(const char * const opt, const OptType t,
  39. const char * const desc, const char * const val)
  40. {
  41.    if ( enroll_done ) return 0;
  42.  
  43.    Cell *c = new Cell;
  44.    c->option = opt;
  45.    c->type = t;
  46.    c->description = desc ? desc : "no description available";
  47.    c->value = val;
  48.    c->next = 0;
  49.  
  50.    if ( last == 0 ) {
  51.       table = last = c;
  52.    }
  53.    else {
  54.       last->next = c;
  55.       last = c;
  56.    }
  57.  
  58.    return 1;
  59. }
  60.  
  61. const char *
  62. GetLongOpt::retrieve(const char * const opt) const
  63. {
  64.    Cell *t;
  65.    for ( t = table; t != 0; t = t->next ) {
  66.       if ( strcmp(opt, t->option) == 0 )
  67.      return t->value;
  68.    }
  69.    cerr << "GetLongOpt::retrieve - unenrolled option ";
  70.    cerr << optmarker << opt << "\n";
  71.    return 0;
  72. }
  73.  
  74. int
  75. GetLongOpt::parse(int argc, char * const *argv)
  76. {
  77.    int optind = 1;
  78.  
  79.    pname = basename(*argv);
  80.    enroll_done = 1;
  81.    if ( argc-- <= 1 ) return optind;
  82.  
  83.    while ( argc >= 1 ) {
  84.       char *token = *++argv; --argc;
  85.  
  86.       if ( token[0] != optmarker || token[1] == optmarker )
  87.      break;    /* end of options */
  88.  
  89.       ++optind;
  90.       char *tmptoken = ++token;
  91.       while ( *tmptoken && *tmptoken != '=' )
  92.      ++tmptoken;
  93.       /* (tmptoken - token) is now equal to the command line option
  94.      length. */
  95.  
  96.       Cell *t;
  97.       enum { NoMatch, ExactMatch, PartialMatch } matchStatus = NoMatch;
  98.       Cell *pc = 0;    // pointer to the partially-matched cell
  99.       for ( t = table; t != 0; t = t->next ) {
  100.      if ( strncmp(t->option, token, (tmptoken - token)) == 0 ) {
  101.         if ( strlen(t->option) == (tmptoken - token) ) {
  102.            /* an exact match found */
  103.            int stat = setcell(t, tmptoken, *(argv+1), pname);
  104.            if ( stat == -1 ) return -1;
  105.            else if ( stat == 1 ) {
  106.           ++argv; --argc; ++optind;
  107.            }
  108.            matchStatus = ExactMatch;
  109.            break;
  110.         }
  111.         else {
  112.            /* partial match found */
  113.            matchStatus = PartialMatch;
  114.            pc = t;
  115.         }
  116.      } /* end if */
  117.       } /* end for */
  118.  
  119.       if ( matchStatus == PartialMatch ) {
  120.      int stat = setcell(pc, tmptoken, *(argv+1), pname);
  121.      if ( stat == -1 ) return -1;
  122.      else if ( stat == 1 ) {
  123.         ++argv; --argc; ++optind;
  124.      }
  125.       }
  126.       else if ( matchStatus == NoMatch ) {
  127.      cerr << pname << ": unrecognized option ";
  128.      cerr << optmarker << strtok(token,"= ") << "\n";
  129.      return -1;        /* no match */
  130.       }
  131.  
  132.    } /* end while */
  133.  
  134.    return optind;
  135. }
  136.  
  137. int
  138. GetLongOpt::parse(char * const str, char * const p)
  139. {
  140.    enroll_done = 1;
  141.    char *token = strtok(str, " \t");
  142.    char *name = p ? p : "GetLongOpt";
  143.  
  144.    while ( token ) {
  145.       if ( token[0] != optmarker || token[1] == optmarker ) {
  146.      cerr << name << ": nonoptions not allowed\n";
  147.      return -1;    /* end of options */
  148.       }
  149.  
  150.       char *ladtoken = 0;    /* lookahead token */
  151.       char *tmptoken = ++token;
  152.       while ( *tmptoken && *tmptoken != '=' )
  153.      ++tmptoken;
  154.       /* (tmptoken - token) is now equal to the command line option
  155.      length. */
  156.  
  157.       Cell *t;
  158.       enum { NoMatch, ExactMatch, PartialMatch } matchStatus = NoMatch;
  159.       Cell *pc =0;    // pointer to the partially-matched cell
  160.       for ( t = table; t != 0; t = t->next ) {
  161.      if ( strncmp(t->option, token, (tmptoken - token)) == 0 ) {
  162.         if ( strlen(t->option) == (tmptoken - token) ) {
  163.            /* an exact match found */
  164.            ladtoken = strtok(0, " \t");
  165.            int stat = setcell(t, tmptoken, ladtoken, name);
  166.            if ( stat == -1 ) return -1;
  167.            else if ( stat == 1 ) {
  168.           ladtoken = 0;
  169.            }
  170.            matchStatus = ExactMatch;
  171.            break;
  172.         }
  173.         else {
  174.            /* partial match found */
  175.            matchStatus = PartialMatch;
  176.            pc = t;
  177.         }
  178.      } /* end if */
  179.       } /* end for */
  180.  
  181.       if ( matchStatus == PartialMatch ) {
  182.      ladtoken = strtok(0, " \t");
  183.      int stat = setcell(pc, tmptoken, ladtoken, name);
  184.      if ( stat == -1 ) return -1;
  185.      else if ( stat == 1 ) {
  186.         ladtoken = 0;
  187.      }
  188.       }
  189.       else if ( matchStatus == NoMatch ) {
  190.      cerr << name << ": unrecognized option ";
  191.      cerr << optmarker << strtok(token,"= ") << "\n";
  192.      return -1;        /* no match */
  193.       }
  194.  
  195.       token = ladtoken ? ladtoken : strtok(0, " \t");
  196.    } /* end while */
  197.  
  198.    return 1;
  199. }
  200.  
  201. /* ----------------------------------------------------------------
  202. GetLongOpt::setcell returns
  203.    -1    if there was an error
  204.     0    if the nexttoken was not consumed
  205.     1    if the nexttoken was consumed
  206. ------------------------------------------------------------------- */
  207.  
  208. int
  209. GetLongOpt::setcell(Cell *c, char *valtoken, char *nexttoken, char *name)
  210. {
  211.    if ( c == 0 ) return -1;
  212.  
  213.    switch ( c->type ) {
  214.    case GetLongOpt::NoValue :
  215.       if ( *valtoken == '=' ) {
  216.      cerr << name << ": unsolicited value for flag ";
  217.      cerr << optmarker << c->option << "\n";
  218.      return -1;    /* unsolicited value specification */
  219.       }
  220.       c->value = (c->value) ? 0 : (char *) ~0;
  221.       return 0;
  222.    case GetLongOpt::OptionalValue :
  223.       if ( *valtoken == '=' ) {
  224.      c->value = ++valtoken;
  225.      return 0;
  226.       }
  227.       else {
  228.      if ( nexttoken != 0 && nexttoken[0] != optmarker ) {
  229.         c->value = nexttoken;
  230.         return 1;
  231.      }
  232.      else return 0;
  233.       }
  234.       break;
  235.    case GetLongOpt::MandatoryValue :
  236.       if ( *valtoken == '=' ) {
  237.      c->value = ++valtoken;
  238.      return 0;
  239.       }
  240.       else {
  241.      if ( nexttoken != 0 && nexttoken[0] != optmarker ) {
  242.         c->value = nexttoken;
  243.         return 1;
  244.      }
  245.      else {
  246.         cerr << name << ": mandatory value for ";
  247.         cerr << optmarker << c->option << " not specified\n";
  248.         return -1;    /* mandatory value not specified */
  249.      }
  250.       }
  251.       break;
  252.    default :
  253.       break;
  254.    }
  255.    return -1;
  256. }
  257.  
  258. void
  259. GetLongOpt::usage(ostream &outfile) const
  260. {
  261.    Cell *t;
  262.  
  263.    outfile << "usage: " << pname << " " << ustring << "\n";
  264.    for ( t = table; t != 0; t = t->next ) {
  265.       outfile << "\t" << optmarker << t->option;
  266.       if ( t->type == GetLongOpt::MandatoryValue )
  267.      outfile << " <$val>";
  268.       else if ( t->type == GetLongOpt::OptionalValue )
  269.      outfile << " [$val]";
  270.       outfile << " (" << t->description << ")\n";
  271.    }
  272.    outfile.flush();
  273. }
  274.  
  275.