home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume36 / options / patch01 next >
Encoding:
Text File  |  1993-04-04  |  20.3 KB  |  691 lines

  1. Newsgroups: comp.sources.misc
  2. From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  3. Subject: v36i092:  options - C++ library for parsing Unix-style command-lines, Patch01
  4. Message-ID: <1993Apr4.172850.29092@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4a13499239e54d0506cea4c47d1004b0
  6. Date: Sun, 4 Apr 1993 17:28:50 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  10. Posting-number: Volume 36, Issue 92
  11. Archive-name: options/patch01
  12. Environment: C++
  13. Patch-To: options: Volume 31, Issue 45-46
  14.  
  15. This is patch01 for the Options C++ class library.
  16.  
  17. To apply this patch:
  18.  
  19. 1) cd to your "Options" source directory
  20. 2) Unshar this file by typing "sh name-of-this-file"
  21.       (this will create the files MANIFEST and PATCH01)
  22. 3) type "patch -p0 <PATCH01"
  23.  
  24. Changes made in this patch are as follows:
  25. - made changes to compile with g++
  26. - added an OptIstreamIter class to iterate over options from an input stream
  27.  
  28. For those of you that are unfamiliar with the Options C++ class library,
  29. an excerpt from the README file follows:
  30.  
  31.  
  32.  WHAT IS THIS?
  33.  =============
  34.  This is "Options", a C++ library for parsing Unix-style command-line options.
  35.  Options understands options and gnu-long-options and the parsing behavior is
  36.  somewhat configurable. See the documentation (or the file <options.h>) for a
  37.  complete description.
  38.  
  39.  You "declare" your options by declaring an array of strings like so:
  40.  
  41.         const char * optv[] = {
  42.             "c:count <number>",
  43.             "s?str   <string>",
  44.             "x|xmode",
  45.             NULL
  46.         } ;
  47.   
  48.  Note the character (one of ':', '?', '|', '*', or '+') between the short
  49.  and long name of the option. It specifies the option type:
  50.  
  51.         '|' -- indicates that the option takes NO argument;
  52.         '?' -- indicates that the option takes an OPTIONAL argument;
  53.         ':' -- indicates that the option takes a REQUIRED argument;
  54.         '*' -- indicates that the option takes 0 or more arguments;
  55.         '+' -- indicates that the option takes 1 or more arguments;
  56.  
  57.  Using the above example, optv[] now corresponds to the following:
  58.  
  59.         progname [-c <number>] [-s [<string>]] [-x]
  60.  
  61.  Using long-options, optv corresponds to the following ("-" or "+" may
  62.  be used instead of "--" as the prefix):
  63.   
  64.         progname [--count <number>] [--str [<string>]] [--xmode]
  65.  
  66.  Now you can iterate over your options like so:
  67.  
  68.       #include <stdlib.h>
  69.       #include <options.h>
  70.  
  71.       main(int argc, char *argv[]) {
  72.          Options  opts(*argv, optv);
  73.          OptArgvIter  iter(--argc, ++argv);
  74.          const char *optarg, *str = NULL;
  75.          int  errors = 0, xflag = 0, count = 1;
  76.       
  77.          while( char optchar = opts(iter, optarg) ) {
  78.             switch (optchar) {
  79.             case 's' :
  80.                str = optarg; break;
  81.             case 'x' :
  82.                ++xflag; break;
  83.             case 'c' :
  84.                if (optarg == NULL)  ++errors;
  85.                else  count = (int) atol(optarg);
  86.                break;
  87.             default :  ++errors; break;
  88.             } //switch
  89.          }
  90.          ...  // process the rest of the arguments in "iter"
  91.       }
  92.  
  93.  
  94. ______________________ "And miles to go before I sleep." ______________________
  95.  Brad Appleton                         Harris Corp., Computer Systems Division
  96.    Senior Software Engineer            2101 West Cypress Creek Road,  M/S 161 
  97.      brad@ssd.csd.harris.com           Fort Lauderdale, FL  33309-1892  USA
  98.        ...!uunet!travis!brad                 Phone: (305) 973-5190
  99. ~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my employer! ~~~~~~~~~~~~~~~~~~~
  100.  
  101. #! /bin/sh
  102. # This is a shell archive.  Remove anything before this line, then unpack
  103. # it by saving it into a file and typing "sh file".  To overwrite existing
  104. # files, type "sh file -c".  You can also feed this as standard input via
  105. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  106. # will see the following message at the end:
  107. #        "End of shell archive."
  108. # Contents:  PATCH01 MANIFEST
  109. # Wrapped by brad@amber on Fri Mar 26 11:06:37 1993
  110. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  111. if test -f 'PATCH01' -a "${1}" != "-c" ; then 
  112.   echo shar: Will not clobber existing file \"'PATCH01'\"
  113. else
  114. echo shar: Extracting \"'PATCH01'\" \(14884 characters\)
  115. sed "s/^X//" >'PATCH01' <<'END_OF_FILE'
  116. X*** Makefile.OLD    Fri Mar 26 11:01:52 1993
  117. X--- Makefile    Thu Mar 25 17:20:22 1993
  118. X***************
  119. X*** 66,72 ****
  120. X  library: ${LIBRARY}
  121. X  
  122. X  ${LIBRARY}: ${OBJS}
  123. X!     ar -r $@ ${OBJS}
  124. X      ranlib $@
  125. X  
  126. X  test: testopts
  127. X--- 66,72 ----
  128. X  library: ${LIBRARY}
  129. X  
  130. X  ${LIBRARY}: ${OBJS}
  131. X!     ar r $@ ${OBJS}
  132. X      ranlib $@
  133. X  
  134. X  test: testopts
  135. X***************
  136. X*** 84,90 ****
  137. X      rm -f tags testopts ${LIBRARY}
  138. X      
  139. X  shar:
  140. X!     shar README ${SRCS} ${DOCS} Makefile >SHAR
  141. X  
  142. X  ###
  143. X  # object dependencies
  144. X--- 84,90 ----
  145. X      rm -f tags testopts ${LIBRARY}
  146. X      
  147. X  shar:
  148. X!     shar README MANIFEST ${SRCS} ${DOCS} Makefile >SHAR
  149. X  
  150. X  ###
  151. X  # object dependencies
  152. X*** README.OLD    Fri Mar 26 11:01:57 1993
  153. X--- README    Thu Mar 25 17:31:12 1993
  154. X***************
  155. X*** 90,102 ****
  156. X  
  157. X   CONTENTS
  158. X   ========
  159. X!  This release should contain the following files:
  160. X!      Makefile -- the makefile
  161. X!      README -- this file
  162. X!      options.3 -- Unix manual page(s) for the Options class
  163. X!      options.h -- include file and documentation for the Options class
  164. X!      options.C -- the C++ source for the Options class
  165. X!      testopts.C -- a test program for the Options class
  166. X  
  167. X  
  168. X   REQUIREMENTS
  169. X--- 90,97 ----
  170. X  
  171. X   CONTENTS
  172. X   ========
  173. X!  See the file "MANIFEST" in the distribution for a complete list and
  174. X!  description of all the files included in this release.
  175. X  
  176. X  
  177. X   REQUIREMENTS
  178. X***************
  179. X*** 140,151 ****
  180. X   that I wrote for the FSF that was posted on one of the "gnu" newsgroups
  181. X   (I think it was the group gnu.utils.bug) in February of 1992.  Many thanks
  182. X   to David J. MacKenzie for his input.  Options provides may more features
  183. X!  than "getopts" did.
  184. X  
  185. X  
  186. X   PATCHLEVEL
  187. X   ==========
  188. X!  The is release 1 of Options at patchlevel 0.
  189. X  
  190. X  
  191. X   HISTORY
  192. X--- 135,147 ----
  193. X   that I wrote for the FSF that was posted on one of the "gnu" newsgroups
  194. X   (I think it was the group gnu.utils.bug) in February of 1992.  Many thanks
  195. X   to David J. MacKenzie for his input.  Options provides may more features
  196. X!  than "getopts" did.  If you want the original "getopts" package (which
  197. X!  has since been vastly enhanced) then send me e-mail.
  198. X  
  199. X  
  200. X   PATCHLEVEL
  201. X   ==========
  202. X!  The is release 1 of Options at patchlevel 1.
  203. X  
  204. X  
  205. X   HISTORY
  206. X***************
  207. X*** 155,157 ****
  208. X--- 151,157 ----
  209. X   -----------------------------------------------------------------------------
  210. X   First release.
  211. X  
  212. X+  03/23/93        Brad Appleton        <brad@ssd.csd.harris.com>
  213. X+  -----------------------------------------------------------------------------
  214. X+  - Made some changes for compiling with g++
  215. X+  - Added OptIstreamIter class
  216. X*** options.3.OLD    Fri Mar 26 11:02:02 1993
  217. X--- options.3    Fri Mar 26 10:39:14 1993
  218. X***************
  219. X*** 118,123 ****
  220. X--- 118,173 ----
  221. X  
  222. X  
  223. X  .vs -2
  224. X+    // OptIstreamIter is a class for iterating over arguments that come
  225. X+    // from an input stream. Each line of the input stream is considered
  226. X+    // to be a set of white-space separated tokens. If the the first
  227. X+    // non-white character on a line is '#' ('!' for VMS systems) then
  228. X+    // the line is considered a comment and is ignored.
  229. X+    //
  230. X+    // *Note:: If a line is more than 1022 characters in length then we
  231. X+    // treat it as if it were several lines of length 1022 or less.
  232. X+    //
  233. X+    // *Note:: The string tokens returned by this iterator are pointers
  234. X+    //         to temporary buffers which may not necessarily stick around
  235. X+    //         for too long after the call to curr() or operator(), hence
  236. X+    //         if you need the string value to persist - you will need to
  237. X+    //         make a copy.
  238. X+    //
  239. X+ .vs +2
  240. X+ class OptIstreamIter : public OptIter {
  241. X+ private:
  242. X+    istream & is ;
  243. X+    OptStrTokIter * tok_iter ;
  244. X+ 
  245. X+    void
  246. X+    fill(void);
  247. X+ 
  248. X+ public:
  249. X+    static const unsigned  MAX_LINE_LEN ;
  250. X+ 
  251. X+ #ifdef vms
  252. X+    enum { c_COMMENT = '!' } ;
  253. X+ #else
  254. X+    enum { c_COMMENT = '#' } ;
  255. X+ #endif
  256. X+ 
  257. X+    OptIstreamIter(istream & input);
  258. X+ 
  259. X+    virtual
  260. X+    ~OptIstreamIter(void);
  261. X+ 
  262. X+    virtual const char *
  263. X+    curr(void);
  264. X+ 
  265. X+    virtual void
  266. X+    next(void);
  267. X+ 
  268. X+    virtual const char *
  269. X+    operator()(void);
  270. X+ } ;
  271. X+ 
  272. X+ 
  273. X+ .vs -2
  274. X  // Class to hold option-specifications and parsing-specifications
  275. X  //
  276. X  .vs +2
  277. X*** options.C.OLD    Fri Mar 26 11:02:07 1993
  278. X--- options.C    Tue Mar 23 16:55:12 1993
  279. X***************
  280. X*** 3,8 ****
  281. X--- 3,11 ----
  282. X  //
  283. X  // ^HISTORY:
  284. X  //    01/16/92    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  285. X+ //
  286. X+ //    03/23/93    Brad Appleton    <brad@ssd.csd.harris.com>
  287. X+ //    - Added OptIstreamIter class
  288. X  // ^^**************************************************************************
  289. X  
  290. X  #include <stdlib.h>
  291. X***************
  292. X*** 99,106 ****
  293. X--- 102,228 ----
  294. X     cur = ::strtok(tokstr, seps);
  295. X  }
  296. X  
  297. X+ // ************************************************************* OptIstreamIter
  298. X+ 
  299. X+ const unsigned  OptIstreamIter::MAX_LINE_LEN = 1024 ;
  300. X+ 
  301. X+    // Constructor
  302. X+ OptIstreamIter::OptIstreamIter(istream & input) : is(input), tok_iter(NULL)
  303. X+ {
  304. X+ }
  305. X+ 
  306. X+    // Destructor
  307. X+ OptIstreamIter::~OptIstreamIter(void)
  308. X+ {
  309. X+    delete  tok_iter;
  310. X+ }
  311. X+ 
  312. X+ const char *
  313. X+ OptIstreamIter::curr(void) {
  314. X+    const char * result = NULL;
  315. X+    if (tok_iter)  result = tok_iter->curr();
  316. X+    if (result)  return  result;
  317. X+    fill();
  318. X+    return (! is) ? NULL : tok_iter->curr();
  319. X+ }
  320. X+ 
  321. X+ void
  322. X+ OptIstreamIter::next(void) {
  323. X+    const char * result = NULL;
  324. X+    if (tok_iter)  result = tok_iter->operator()();
  325. X+    if (result)  return;
  326. X+    fill();
  327. X+    if (! is) tok_iter->next();
  328. X+ }
  329. X+ 
  330. X+ const char *
  331. X+ OptIstreamIter::operator()(void)
  332. X+ {
  333. X+    const char * result = NULL;
  334. X+    if (tok_iter)  result = tok_iter->operator()();
  335. X+    if (result)  return  result;
  336. X+    fill();
  337. X+    return (! is) ? NULL : tok_iter->operator()();
  338. X+ }
  339. X+ 
  340. X+    // What we do is this: for each line of text in the istream, we use
  341. X+    // a OptStrTokIter to iterate over each token on the line.
  342. X+    //
  343. X+    // If the first non-white character on a line is c_COMMENT, then we
  344. X+    // consider the line to be a comment and we ignore it.
  345. X+    //
  346. X+ void
  347. X+ OptIstreamIter::fill(void) {
  348. X+    char buf[OptIstreamIter::MAX_LINE_LEN];
  349. X+    do {
  350. X+       *buf = '\0';
  351. X+       is.getline(buf, sizeof(buf));
  352. X+       char * ptr = buf;
  353. X+       while (isspace(*ptr)) ++ptr;
  354. X+       if (*ptr && (*ptr != OptIstreamIter::c_COMMENT)) {
  355. X+          delete  tok_iter;
  356. X+          tok_iter = new OptStrTokIter(ptr);
  357. X+          return;
  358. X+       }
  359. X+    } while (is);
  360. X+ }
  361. X+ 
  362. X  // ******************************************************************* Options
  363. X  
  364. X+ // ---------------------------------------------------------------------------
  365. X+ // ^FUNCTION: verify - verify the syntax of each option-spec
  366. X+ //
  367. X+ // ^SYNOPSIS:
  368. X+ //    static void verify(name, optv[])
  369. X+ //
  370. X+ // ^PARAMETERS:
  371. X+ //    const char * name - name of this command
  372. X+ //    const char * const optv[] - the vector of option-specs to inspect.
  373. X+ //
  374. X+ // ^DESCRIPTION:
  375. X+ //    All we have to do is iterate through the option vector and make sure
  376. X+ //    That each option-spec is of the proper format.
  377. X+ //
  378. X+ // ^REQUIREMENTS:
  379. X+ //    - optv[] should be non-NULL and terminated by a NULL pointer.
  380. X+ //
  381. X+ // ^SIDE-EFFECTS:
  382. X+ //    If an invalid option-spec is found, prints a message on cerr and
  383. X+ //    exits with a status of 127.
  384. X+ //
  385. X+ // ^RETURN-VALUE:
  386. X+ //    None.
  387. X+ //
  388. X+ // ^ALGORITHM:
  389. X+ //    For each option-spec
  390. X+ //       - ensure (length > 0)
  391. X+ //       - verify the the second character is one of "|?:*+"
  392. X+ //    end-for
  393. X+ // ^^-------------------------------------------------------------------------
  394. X+ static void
  395. X+ verify(const char * name, const char * const optv[])
  396. X+ {
  397. X+    int errors = 0;
  398. X+    if ((optv == NULL) || (! *optv))  return;
  399. X+ 
  400. X+    for (; *optv ; optv++) {
  401. X+       char *p;
  402. X+       if (! **optv) {
  403. X+          cerr << name << ": invalid option spec \"" << *optv << "\"." << endl ;
  404. X+           cerr << "\tmust be at least 1 character long." << endl ;
  405. X+          ++errors;
  406. X+       }
  407. X+       if ((**optv) && ((*optv)[1]) &&
  408. X+           ((p = strchr("|?:*+", (*optv)[1])) == NULL)) {
  409. X+          cerr << name << ": invalid option spec \"" << *optv << "\"." << endl ;
  410. X+          cerr << "\t2nd character must be in the set \"|?:*+\"." << endl ;
  411. X+          ++errors;
  412. X+       }
  413. X+    }/*for*/
  414. X+ 
  415. X+    if (errors)  exit(127);
  416. X+ }
  417. X+ 
  418. X  Options::Options(const char * name, const char * const optv[])
  419. X     : cmdname(name), optvec(optv), explicit_end(0), optctrls(DEFAULT),
  420. X       nextchar(NULL), listopt(NULL)
  421. X***************
  422. X*** 107,112 ****
  423. X--- 229,235 ----
  424. X  {
  425. X     const char * basename = ::strrchr(cmdname, '/');
  426. X     if (basename)  cmdname = basename + 1;
  427. X+    verify(name, optv);
  428. X  }
  429. X  
  430. X  Options::~Options(void) {}
  431. X***************
  432. X*** 177,235 ****
  433. X  }
  434. X  
  435. X  // ---------------------------------------------------------------------------
  436. X- // ^FUNCTION: verify - verify the syntax of each option-spec
  437. X- //
  438. X- // ^SYNOPSIS:
  439. X- //    static void verify(optv[])
  440. X- //
  441. X- // ^PARAMETERS:
  442. X- //    const char * const optv[] - the vector of option-specs to inspect.
  443. X- //
  444. X- // ^DESCRIPTION:
  445. X- //    All we have to do is iterate through the option vector and make sure
  446. X- //    That each option-spec is of the proper format.
  447. X- //
  448. X- // ^REQUIREMENTS:
  449. X- //    - optv[] should be non-NULL and terminated by a NULL pointer.
  450. X- //
  451. X- // ^SIDE-EFFECTS:
  452. X- //    If an invalid option-spec is found, prints a message on cerr and
  453. X- //    exits with a status of 127.
  454. X- //
  455. X- // ^RETURN-VALUE:
  456. X- //    None.
  457. X- //
  458. X- // ^ALGORITHM:
  459. X- //    For each option-spec
  460. X- //       - ensure (length > 0)
  461. X- //       - verify the the second character is one of "|?:*+"
  462. X- //    end-for
  463. X- // ^^-------------------------------------------------------------------------
  464. X- static void
  465. X- verify(const char * const optv[])
  466. X- {
  467. X-    int errors = 0;
  468. X-    if ((optv == NULL) || (! *optv))  return;
  469. X- 
  470. X-    for (; *optv ; optv++) {
  471. X-       char *p;
  472. X-       if (! **optv) {
  473. X-          cerr << "invalid option spec \"" << *optv << "\"." << endl ;
  474. X-           cerr << "\tmust be at least 1 character long." << endl ;
  475. X-          ++errors;
  476. X-       }
  477. X-       if ((**optv) && ((*optv)[1]) &&
  478. X-           ((p = strchr("|?:*+", (*optv)[1])) == NULL)) {
  479. X-          cerr << "invalid option spec \"" << *optv << "\"." << endl ;
  480. X-          cerr << "\t2nd character must be in the set \"|?:*+\"." << endl ;
  481. X-          ++errors;
  482. X-       }
  483. X-    }/*for*/
  484. X- 
  485. X-    if (errors)  exit(127);
  486. X- }
  487. X- 
  488. X- // ---------------------------------------------------------------------------
  489. X  // ^FUNCTION: kwdmatch - match a keyword
  490. X  //
  491. X  // ^SYNOPSIS:
  492. X--- 300,305 ----
  493. X***************
  494. X*** 260,266 ****
  495. X  static kwdmatch_t
  496. X  kwdmatch(const char * src, const char * attempt, int len =0)
  497. X  {
  498. X!    unsigned  i;
  499. X  
  500. X     if (src == attempt)  return  EXACT_MATCH ;
  501. X     if ((src == NULL) || (attempt == NULL))  return  NO_MATCH ;
  502. X--- 330,336 ----
  503. X  static kwdmatch_t
  504. X  kwdmatch(const char * src, const char * attempt, int len =0)
  505. X  {
  506. X!    int  i;
  507. X  
  508. X     if (src == attempt)  return  EXACT_MATCH ;
  509. X     if ((src == NULL) || (attempt == NULL))  return  NO_MATCH ;
  510. X***************
  511. X*** 429,435 ****
  512. X  {
  513. X     listopt = NULL;  // reset the list pointer
  514. X  
  515. X!    if ((optvec == NULL) || (! *optvec))  return  NULL;
  516. X  
  517. X        // Try to match a known option
  518. X     const char * optspec = match_opt(optvec, *(nextchar++));
  519. X--- 499,505 ----
  520. X  {
  521. X     listopt = NULL;  // reset the list pointer
  522. X  
  523. X!    if ((optvec == NULL) || (! *optvec))  return  Options::ENDOPTS;
  524. X  
  525. X        // Try to match a known option
  526. X     const char * optspec = match_opt(optvec, *(nextchar++));
  527. X***************
  528. X*** 529,535 ****
  529. X  
  530. X     listopt = NULL ;  // reset the list-spec
  531. X  
  532. X!    if ((optvec == NULL) || (! *optvec))  return  NULL;
  533. X  
  534. X        // if a value is supplied in this argv element, get it now
  535. X     const char * val = strpbrk(nextchar, ":=") ;
  536. X--- 599,605 ----
  537. X  
  538. X     listopt = NULL ;  // reset the list-spec
  539. X  
  540. X!    if ((optvec == NULL) || (! *optvec))  return  Options::ENDOPTS;
  541. X  
  542. X        // if a value is supplied in this argv element, get it now
  543. X     const char * val = strpbrk(nextchar, ":=") ;
  544. X***************
  545. X*** 748,754 ****
  546. X  void
  547. X  Options::usage(ostream & os, const char * positionals) const
  548. X  {
  549. X!    const char ** optv = optvec;
  550. X     unsigned  cols = 79;
  551. X     int  first, nloop;
  552. X     char  buf[256] ;
  553. X--- 818,824 ----
  554. X  void
  555. X  Options::usage(ostream & os, const char * positionals) const
  556. X  {
  557. X!    const char * const * optv = optvec;
  558. X     unsigned  cols = 79;
  559. X     int  first, nloop;
  560. X     char  buf[256] ;
  561. X*** options.h.OLD    Fri Mar 26 11:02:13 1993
  562. X--- options.h    Tue Mar 23 16:58:19 1993
  563. X***************
  564. X*** 8,13 ****
  565. X--- 8,16 ----
  566. X  //
  567. X  // ^HISTORY:
  568. X  //    03/06/92  Brad Appleton   <brad@ssd.csd.harris.com>   Created
  569. X+ //
  570. X+ //    03/23/93    Brad Appleton    <brad@ssd.csd.harris.com>
  571. X+ //    - Added OptIstreamIter class
  572. X  // ^^**************************************************************************
  573. X  
  574. X  #ifndef _options_h
  575. X***************
  576. X*** 14,19 ****
  577. X--- 17,23 ----
  578. X  #define _options_h
  579. X  
  580. X  class  ostream;
  581. X+ class  istream;
  582. X  
  583. X  // Abstract class to iterate through options/arguments
  584. X  //
  585. X***************
  586. X*** 136,141 ****
  587. X--- 140,193 ----
  588. X     delimiters(const char * delims) {
  589. X        seps = (delims) ? delims : default_delims ;
  590. X     }
  591. X+ } ;
  592. X+ 
  593. X+ 
  594. X+    // OptIstreamIter is a class for iterating over arguments that come
  595. X+    // from an input stream. Each line of the input stream is considered
  596. X+    // to be a set of white-space separated tokens. If the the first
  597. X+    // non-white character on a line is '#' ('!' for VMS systems) then
  598. X+    // the line is considered a comment and is ignored.
  599. X+    //
  600. X+    // *Note:: If a line is more than 1022 characters in length then we
  601. X+    // treat it as if it were several lines of length 1022 or less.
  602. X+    //
  603. X+    // *Note:: The string tokens returned by this iterator are pointers
  604. X+    //         to temporary buffers which may not necessarily stick around
  605. X+    //         for too long after the call to curr() or operator(), hence
  606. X+    //         if you need the string value to persist - you will need to
  607. X+    //         make a copy.
  608. X+    //
  609. X+ class OptIstreamIter : public OptIter {
  610. X+ private:
  611. X+    istream & is ;
  612. X+    OptStrTokIter * tok_iter ;
  613. X+ 
  614. X+    void
  615. X+    fill(void);
  616. X+ 
  617. X+ public:
  618. X+    static const unsigned  MAX_LINE_LEN ;
  619. X+ 
  620. X+ #ifdef vms
  621. X+    enum { c_COMMENT = '!' } ;
  622. X+ #else
  623. X+    enum { c_COMMENT = '#' } ;
  624. X+ #endif
  625. X+ 
  626. X+    OptIstreamIter(istream & input);
  627. X+ 
  628. X+    virtual
  629. X+    ~OptIstreamIter(void);
  630. X+ 
  631. X+    virtual const char *
  632. X+    curr(void);
  633. X+ 
  634. X+    virtual void
  635. X+    next(void);
  636. X+ 
  637. X+    virtual const char *
  638. X+    operator()(void);
  639. X  } ;
  640. X  
  641. X  
  642. X*** testopts.C.OLD    Fri Mar 26 11:02:17 1993
  643. X--- testopts.C    Fri Nov 13 07:27:28 1992
  644. X***************
  645. X*** 10,16 ****
  646. X     long  atol(const char *);
  647. X  }
  648. X  
  649. X! static const char *optv[] = {
  650. X     "?|?",
  651. X     "H|help",
  652. X     "f?flags",
  653. X--- 10,16 ----
  654. X     long  atol(const char *);
  655. X  }
  656. X  
  657. X! static const char * const optv[] = {
  658. X     "?|?",
  659. X     "H|help",
  660. X     "f?flags",
  661. END_OF_FILE
  662. if test 14884 -ne `wc -c <'PATCH01'`; then
  663.     echo shar: \"'PATCH01'\" unpacked with wrong size!
  664. fi
  665. # end of 'PATCH01'
  666. fi
  667. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  668.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  669. else
  670. echo shar: Extracting \"'MANIFEST'\" \(524 characters\)
  671. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  672. X   File Name        Archive #    Description
  673. X-----------------------------------------------------------
  674. X MANIFEST                   1    this shipping list
  675. X Makefile                   1    make file for the product
  676. X README                     1    read this file first
  677. X options.3                  1    man page for the Options(3C++) library
  678. X options.C                  2    implementation of the Options(3C++) library
  679. X options.h                  1    definition of the Options(3C++) library
  680. X testopts.C                 1    test program for the library
  681. END_OF_FILE
  682. if test 524 -ne `wc -c <'MANIFEST'`; then
  683.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  684. fi
  685. # end of 'MANIFEST'
  686. fi
  687. echo shar: End of shell archive.
  688. exit 0
  689.  
  690. exit 0 # Just in case...
  691.