home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / options / patch02 < prev    next >
Encoding:
Text File  |  1993-11-24  |  14.4 KB  |  442 lines

  1. Newsgroups: comp.sources.misc
  2. From: brad@amber.ssd.csd.harris.com (Brad Appleton)
  3. Subject: v40i157:  options - C++ library for parsing Unix-style command-lines, Patch02
  4. Message-ID: <1993Nov24.165117.3187@sparky.sterling.com>
  5. X-Md4-Signature: aa8e249ab66b16e302a0f8bc92dce3ce
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Reply-To: brad@travis.csd.harris.com
  8. Organization: Harris Computer Systems
  9. Date: Wed, 24 Nov 1993 16:51:17 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: brad@amber.ssd.csd.harris.com (Brad Appleton)
  13. Posting-number: Volume 40, Issue 157
  14. Archive-name: options/patch02
  15. Environment: C++
  16. Patch-To: options: Volume 31, Issue 45-46
  17.  
  18. This is patch-level 2 of "Options", a C++ library for parsing
  19. Unix-style command-line options. Options understands options and
  20. gnu-long-options and the parsing behavior is somewhat configurable.
  21.  
  22.  To apply this patch:
  23.  --------------------
  24.    0) save this article to a file in your "Options" source directory
  25.  
  26.    1) "cd" to your Options source directory
  27.  
  28.    2) Remove all lines in the sharfile (the file you saved in #0)
  29.       that precede the line that starts with "#! /bin/sh".
  30.  
  31.    3) Run the command "sh sharfile" (or whatever you named your sharfile).
  32.       This will create a file named "PATCH02" in your current directory
  33.  
  34.    4) Run "patch -p0 < PATCH02"
  35.  
  36.  
  37.  Changes in this release:
  38.  ------------------------
  39.  - Added "hidden" options
  40.  - Fixed a few portability problems
  41.  
  42. For those of you who are unfamiliar with "Options", the following
  43. is an excerpt from the README file. You can send e-mail to me at
  44. brad@ssd.csd.harris.com if you want the complete C++ source.
  45.  
  46.  ------------------------------------------------------------------------------
  47.  
  48.  You "declare" your options by declaring an array of strings like so:
  49.  
  50.         const char * optv[] = {
  51.             "c:count <number>",
  52.             "s?str   <string>",
  53.             "x|xmode",
  54.             NULL
  55.         } ;
  56.   
  57.  Note the character (one of ':', '?', '|', '*', or '+') between the short
  58.  and long name of the option. It specifies the option type:
  59.  
  60.         '|' -- indicates that the option takes NO argument;
  61.         '?' -- indicates that the option takes an OPTIONAL argument;
  62.         ':' -- indicates that the option takes a REQUIRED argument;
  63.         '*' -- indicates that the option takes 0 or more arguments;
  64.         '+' -- indicates that the option takes 1 or more arguments;
  65.  
  66.  Using the above example, optv[] now corresponds to the following:
  67.  
  68.         progname [-c <number>] [-s [<string>]] [-x]
  69.  
  70.  Using long-options, optv corresponds to the following ("-" or "+" may
  71.  be used instead of "--" as the prefix):
  72.   
  73.         progname [--count <number>] [--str [<string>]] [--xmode]
  74.  
  75.  Now you can iterate over your options like so:
  76.  
  77.       #include <stdlib.h>
  78.       #include <options.h>
  79.  
  80.       main(int argc, char *argv[]) {
  81.          Options  opts(*argv, optv);
  82.          OptArgvIter  iter(--argc, ++argv);
  83.          const char *optarg, *str = NULL;
  84.          int  errors = 0, xflag = 0, count = 1;
  85.       
  86.          while( char optchar = opts(iter, optarg) ) {
  87.             switch (optchar) {
  88.             case 's' :
  89.                str = optarg; break;
  90.             case 'x' :
  91.                ++xflag; break;
  92.             case 'c' :
  93.                if (optarg == NULL)  ++errors;
  94.                else  count = (int) atol(optarg);
  95.                break;
  96.             default :  ++errors; break;
  97.             } //switch
  98.          }
  99.          ...  // process the rest of the arguments in "iter"
  100.       }
  101.  
  102.  ______________________ "And miles to go before I sleep." ______________________
  103.   Brad Appleton, Senior Software Engineer    Harris Computer Systems Division
  104.     E-mail: brad@ssd.csd.harris.com          2101 W. Cypress Creek Rd., M/S 161 
  105.     Phone : (305) 973-5190                   Fort Lauderdale, FL  USA  33309
  106.  ~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my employer! ~~~~~~~~~~~~~~~~~~~
  107. ----------
  108. #! /bin/sh
  109. # This is a shell archive.  Remove anything before this line, then unpack
  110. # it by saving it into a file and typing "sh file".  To overwrite existing
  111. # files, type "sh file -c".  You can also feed this as standard input via
  112. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  113. # will see the following message at the end:
  114. #        "End of shell archive."
  115. # Contents:  PATCH02
  116. # Wrapped by brad@amber on Fri Nov  5 15:22:33 1993
  117. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  118. if test -f 'PATCH02' -a "${1}" != "-c" ; then 
  119.   echo shar: Will not clobber existing file \"'PATCH02'\"
  120. else
  121. echo shar: Extracting \"'PATCH02'\" \(9589 characters\)
  122. sed "s/^X//" >'PATCH02' <<'END_OF_FILE'
  123. X*** README.OLD    Fri Nov 05 15:22:02 1993
  124. X--- README    Sat Oct 30 17:11:07 1993
  125. X***************
  126. X*** 141,152 ****
  127. X  
  128. X   PATCHLEVEL
  129. X   ==========
  130. X!  The is release 1 of Options at patchlevel 1.
  131. X  
  132. X  
  133. X   HISTORY
  134. X   =======
  135. X- 
  136. X   07/21/92        Brad Appleton        <brad@ssd.csd.harris.com>
  137. X   -----------------------------------------------------------------------------
  138. X   First release.
  139. X--- 141,151 ----
  140. X  
  141. X   PATCHLEVEL
  142. X   ==========
  143. X!  The is release 1 of Options at patchlevel 2.
  144. X  
  145. X  
  146. X   HISTORY
  147. X   =======
  148. X   07/21/92        Brad Appleton        <brad@ssd.csd.harris.com>
  149. X   -----------------------------------------------------------------------------
  150. X   First release.
  151. X***************
  152. X*** 155,157 ****
  153. X--- 154,160 ----
  154. X   -----------------------------------------------------------------------------
  155. X   - Made some changes for compiling with g++
  156. X   - Added OptIstreamIter class
  157. X+ 
  158. X+  10/08/93        Brad Appleton        <brad@ssd.csd.harris.com>
  159. X+  -----------------------------------------------------------------------------
  160. X+  - Added "hidden" options
  161. X*** options.3.OLD    Fri Nov 05 15:22:04 1993
  162. X--- options.3    Sat Oct 30 16:52:10 1993
  163. X***************
  164. X*** 305,310 ****
  165. X--- 305,321 ----
  166. X  
  167. X  .SS Exceptions to the Above:
  168. X  .PP
  169. X+ If the first character of the string is `\-', then the rest of the
  170. X+ string must correspond to the above format, and the option is
  171. X+ considered to be a "hidden" option. This means it will be parsed
  172. X+ when actually matching options from the command line, but it will
  173. X+ \fInot\fP show-up if a usage message is printed using the \f4usage()\fP
  174. X+ member function. Such an example might be \f4"-h|hidden"\fP. If
  175. X+ you want to use an "dummy" options (options that are not parsed,
  176. X+ but that to show up in the usage message), you can specify them
  177. X+ along with any positional parameters to the \f4usage()\fP member
  178. X+ function.
  179. X+ 
  180. X  If the second character of the string is \f4'\\0'\fP then it is assumed
  181. X  that there is no corresponding long-option and that the option
  182. X  takes no argument (hence \f4"f"\fP, and \f4"f| "\fP are equivalent).
  183. X*** options.C.OLD    Fri Nov 05 15:22:07 1993
  184. X--- options.C    Thu Nov 04 11:52:37 1993
  185. X***************
  186. X*** 6,11 ****
  187. X--- 6,14 ----
  188. X  //
  189. X  //    03/23/93    Brad Appleton    <brad@ssd.csd.harris.com>
  190. X  //    - Added OptIstreamIter class
  191. X+ //
  192. X+ //    10/08/93    Brad Appleton    <brad@ssd.csd.harris.com>
  193. X+ //    - Added "hidden" options
  194. X  // ^^**************************************************************************
  195. X  
  196. X  #include <stdlib.h>
  197. X***************
  198. X*** 19,25 ****
  199. X     void  exit(int);
  200. X  }
  201. X  
  202. X! static const char ident[] = "@(#)Options  1.00" ;
  203. X  
  204. X     // I need a portable version of "tolower" that does NOT modify
  205. X     // non-uppercase characters.
  206. X--- 22,28 ----
  207. X     void  exit(int);
  208. X  }
  209. X  
  210. X! static const char ident[] = "@(#)Options  1.02" ;
  211. X  
  212. X     // I need a portable version of "tolower" that does NOT modify
  213. X     // non-uppercase characters.
  214. X***************
  215. X*** 169,174 ****
  216. X--- 172,181 ----
  217. X  
  218. X  // ******************************************************************* Options
  219. X  
  220. X+    // See if an opt-spec is a Hidden option
  221. X+ inline static int
  222. X+ isHiddenOpt(const char * optspec) { return  (*optspec == '-'); }
  223. X+ 
  224. X  // ---------------------------------------------------------------------------
  225. X  // ^FUNCTION: verify - verify the syntax of each option-spec
  226. X  //
  227. X***************
  228. X*** 205,224 ****
  229. X     int errors = 0;
  230. X     if ((optv == NULL) || (! *optv))  return;
  231. X  
  232. X!    for (; *optv ; optv++) {
  233. X!       char *p;
  234. X!       if (! **optv) {
  235. X!          cerr << name << ": invalid option spec \"" << *optv << "\"." << endl ;
  236. X!           cerr << "\tmust be at least 1 character long." << endl ;
  237. X           ++errors;
  238. X!       }
  239. X!       if ((**optv) && ((*optv)[1]) &&
  240. X!           ((p = strchr("|?:*+", (*optv)[1])) == NULL)) {
  241. X!          cerr << name << ": invalid option spec \"" << *optv << "\"." << endl ;
  242. X           cerr << "\t2nd character must be in the set \"|?:*+\"." << endl ;
  243. X           ++errors;
  244. X        }
  245. X!    }/*for*/
  246. X  
  247. X     if (errors)  exit(127);
  248. X  }
  249. X--- 212,230 ----
  250. X     int errors = 0;
  251. X     if ((optv == NULL) || (! *optv))  return;
  252. X  
  253. X!    const char * cp = *optv;
  254. X!    while (cp = *(optv++)) {
  255. X!       if (isHiddenOpt(cp))  ++cp;
  256. X!       if (! *cp) {
  257. X!          cerr << name << ": invalid option spec \"" << cp << "\"." << endl ;
  258. X!          cerr << "\tmust be at least 1 character long." << endl ;
  259. X           ++errors;
  260. X!       } else if (cp[1] && (strchr("|?:*+", cp[1]) == NULL)) {
  261. X!          cerr << name << ": invalid option spec \"" << cp << "\"." << endl ;
  262. X           cerr << "\t2nd character must be in the set \"|?:*+\"." << endl ;
  263. X           ++errors;
  264. X        }
  265. X!    }/*while*/
  266. X  
  267. X     if (errors)  exit(127);
  268. X  }
  269. X***************
  270. X*** 379,392 ****
  271. X  {
  272. X     if ((optv == NULL) || (! *optv))  return  NULL;
  273. X  
  274. X!    for (; *optv ; ++optv) {
  275. X!      char optchar = OptChar(*optv);
  276. X!      if (isNullOpt(optchar))  continue;
  277. X!      if (opt == optchar) {
  278. X!         return *optv;
  279. X!      } else if (ignore_case && (TOLOWER(opt) == TOLOWER(optchar))) {
  280. X!         return *optv;
  281. X!      }
  282. X     }
  283. X  
  284. X     return  NULL;  // not found
  285. X--- 385,399 ----
  286. X  {
  287. X     if ((optv == NULL) || (! *optv))  return  NULL;
  288. X  
  289. X!    for (const char * optspec = *optv; optspec ; optspec =  *(++optv)) {
  290. X!       if (isHiddenOpt(optspec))  ++optspec;
  291. X!       char optchar = OptChar(optspec);
  292. X!       if (isNullOpt(optchar))  continue;
  293. X!       if (opt == optchar) {
  294. X!          return optspec;
  295. X!       } else if (ignore_case && (TOLOWER(opt) == TOLOWER(optchar))) {
  296. X!          return optspec;
  297. X!       }
  298. X     }
  299. X  
  300. X     return  NULL;  // not found
  301. X***************
  302. X*** 445,462 ****
  303. X     ambiguous = 0;
  304. X     if ((optv == NULL) || (! *optv))  return  NULL;
  305. X  
  306. X!    for (; *optv ; ++optv) {
  307. X!       const char * longopt = LongOpt(*optv) ;
  308. X        if (longopt == NULL)  continue;
  309. X        result = kwdmatch(longopt, opt, len);
  310. X        if (result == EXACT_MATCH) {
  311. X!          return  *optv;
  312. X        } else if (result == PARTIAL_MATCH) {
  313. X           if (matched) {
  314. X              ++ambiguous;
  315. X              return  NULL;
  316. X           } else {
  317. X!             matched = *optv;
  318. X           }
  319. X        }
  320. X     }/*for*/
  321. X--- 452,470 ----
  322. X     ambiguous = 0;
  323. X     if ((optv == NULL) || (! *optv))  return  NULL;
  324. X  
  325. X!    for (const char * optspec = *optv; optspec ; optspec =  *(++optv)) {
  326. X!       if (isHiddenOpt(optspec))  ++optspec;
  327. X!       const char * longopt = LongOpt(optspec);
  328. X        if (longopt == NULL)  continue;
  329. X        result = kwdmatch(longopt, opt, len);
  330. X        if (result == EXACT_MATCH) {
  331. X!          return  optspec;
  332. X        } else if (result == PARTIAL_MATCH) {
  333. X           if (matched) {
  334. X              ++ambiguous;
  335. X              return  NULL;
  336. X           } else {
  337. X!             matched = optspec;
  338. X           }
  339. X        }
  340. X     }/*for*/
  341. X***************
  342. X*** 717,722 ****
  343. X--- 725,731 ----
  344. X  Options::fmt_opt(const char * optspec, char * buf) const
  345. X  {
  346. X     static  char default_value[] = "<value>";
  347. X+    if (isHiddenOpt(optspec))  return (unsigned)(*buf = '\0');
  348. X     char optchar = OptChar(optspec);
  349. X     const char * longopt = LongOpt(optspec);
  350. X     char * p = buf ;
  351. X***************
  352. X*** 843,848 ****
  353. X--- 852,858 ----
  354. X           len = strlen(positionals);
  355. X           ++nloop;  // terminate this loop
  356. X        } else {
  357. X+          if (isHiddenOpt(*optv))  continue;
  358. X           len = fmt_opt(*optv, buf);
  359. X        }
  360. X  
  361. X*** options.h.OLD    Fri Nov 05 15:22:10 1993
  362. X--- options.h    Sat Oct 30 16:57:09 1993
  363. X***************
  364. X*** 240,245 ****
  365. X--- 240,255 ----
  366. X  //
  367. X  //   EXCEPTIONS TO THE ABOVE:
  368. X  //   ------------------------ 
  369. X+ //   If the 1st character of the string is '-', then the rest of the
  370. X+ //   string must correspond to the above format, and the option is
  371. X+ //   considered to be a hidden-option. This means it will be parsed
  372. X+ //   when actually matching options from the command-line, but will
  373. X+ //   NOT show-up if a usage message is printed using the usage() member
  374. X+ //   function. Such an example might be "-h|hidden". If you want to
  375. X+ //   use any "dummy" options (options that are not parsed, but that
  376. X+ //   to show up in the usage message), you can specify them along with
  377. X+ //   any positional parameters to the usage() member function.
  378. X+ //
  379. X  //   If the 2nd character of the string is '\0' then it is assumed
  380. X  //   that there is no corresponding long-option and that the option
  381. X  //   takes no argument (hence "f", and "f| " are equivalent).
  382. X*** testopts.C.OLD    Fri Nov 05 15:22:13 1993
  383. X--- testopts.C    Sat Oct 30 16:47:40 1993
  384. X***************
  385. X*** 19,24 ****
  386. X--- 19,25 ----
  387. X     "s?str <string>",
  388. X     "x",
  389. X     " |hello",
  390. X+    "-h|hidden",
  391. X     NULL
  392. X  } ;
  393. X  
  394. X***************
  395. X*** 51,57 ****
  396. X     int  optchar;
  397. X     const char * optarg;
  398. X     const char * str = "default_string";
  399. X!    int  count = 0, xflag = 0, hello = 0;
  400. X     int  errors = 0;
  401. X     int  ngroups = 0;
  402. X  
  403. X--- 52,58 ----
  404. X     int  optchar;
  405. X     const char * optarg;
  406. X     const char * str = "default_string";
  407. X!    int  count = 0, xflag = 0, hello = 0, hidden = 0;
  408. X     int  errors = 0;
  409. X     int  ngroups = 0;
  410. X  
  411. X***************
  412. X*** 70,75 ****
  413. X--- 71,78 ----
  414. X  
  415. X        case 'g' : ++ngroups; break;
  416. X  
  417. X+       case 'h' : ++hidden; break;
  418. X+ 
  419. X        case 's' : str = optarg; break;
  420. X  
  421. X        case 'x' : ++xflag; break;
  422. X***************
  423. X*** 105,110 ****
  424. X--- 108,114 ----
  425. X     cout << "xflag=" << ((xflag) ? "ON"  : "OFF") << '\n'
  426. X          << "hello=" << ((hello) ? "YES" : "NO") << '\n'
  427. X          << "count=" << count << '\n'
  428. X+         << "hidden=" << ((hidden) ? "ON"  : "OFF") << '\n'
  429. X          << "string=\"" << ((str) ? str : "No value given!") << "\"" << '\n'
  430. X          << "ngroups=" << ngroups << endl ;
  431. X  
  432. END_OF_FILE
  433. if test 9589 -ne `wc -c <'PATCH02'`; then
  434.     echo shar: \"'PATCH02'\" unpacked with wrong size!
  435. fi
  436. # end of 'PATCH02'
  437. fi
  438. echo shar: End of shell archive.
  439. exit 0
  440.  
  441. exit 0 # Just in case...
  442.