home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / parsearg / part08 < prev    next >
Encoding:
Text File  |  1992-05-18  |  46.1 KB  |  1,091 lines

  1. Newsgroups: comp.sources.misc
  2. From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  3. Subject:  v29i123:  parseargs - functions to parse command line arguments, Part08/10
  4. Message-ID: <1992May17.182514.29013@sparky.imd.sterling.com>
  5. X-Md4-Signature: ef206485408e214e0bfce5f13ef252c6
  6. Date: Sun, 17 May 1992 18:25:14 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  10. Posting-number: Volume 29, Issue 123
  11. Archive-name: parseargs/part08
  12. Environment: UNIX, VMS, MS-DOS, OS/2, Amiga
  13. Supersedes: parseargs: Volume 17, Issue 46-57
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 8 (of 10)."
  22. # Contents:  parseargs.h
  23. # Wrapped by brad@hcx1 on Thu May  7 12:12:27 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'parseargs.h' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'parseargs.h'\"
  27. else
  28. echo shar: Extracting \"'parseargs.h'\" \(44214 characters\)
  29. sed "s/^X//" >'parseargs.h' <<'END_OF_FILE'
  30. X/*************************************************************************
  31. X** ^FILE: parseargs.h -- definitions for argument parsing library
  32. X**
  33. X** ^DESCRIPTION:
  34. X**    This file contains all the necessary macros, type, and function
  35. X**    declarations necessary to use the parseargs library. For most purposes,
  36. X**    no special symbols need be #defined before including this file; however,
  37. X**    for implementors (and more sophisticated uses), the following symbols
  38. X**    may be #defined before including this file in order to include/exclude
  39. X**    various portions of the file:
  40. X**
  41. X**    PARSEARGS_PRIVATE
  42. X**       Include private definitions that are needed to implement/enhance
  43. X**       various functions in the parseargs library.
  44. X**
  45. X**    PARSEARGS_NEXTERNS
  46. X**       Do NOT include the external function declarations for the members
  47. X**       of the parseargs library.
  48. X**
  49. X**    PARSEARGS_NARGTYPES
  50. X**       Do NOT include the external function declarations any of the
  51. X**       pre-defined argument-type (argXxxx) functions.
  52. X**
  53. X** ^HISTORY:
  54. X**    12/03/90    Brad Appleton    <brad@ssd.csd.harris.com>
  55. X**    - added ps_NOTCMDLINE state-flag for vms_style
  56. X**
  57. X**    08/27/91     Earl Chew     <cechew@bruce.cs.monash.edu.au>
  58. X**    - Add ProgNameLen
  59. X**    - Promote ps_flags_t to unsigned short
  60. X**    - Add new states ps_USERNAME, ps_USERPURPOSE, ps_FREENAME,
  61. X**      ps_FREEPURPOSE
  62. X**    - arg_sdesc() now only returns a raw string --- use get_argdesc()
  63. X**      to extract the description from it
  64. X**
  65. X**    12/03/90    Brad Appleton    <brad@ssd.csd.harris.com>
  66. X**    - Added all the #ifdef stuff
  67. X**    - Added public and private macros for getting and setting
  68. X**      the attributes of an argdesc-array and an argdesc
  69. X**
  70. X**    --/--/--    Peter da Silva    <peter@ferranti.com>
  71. X**
  72. X**    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  73. X***^^**********************************************************************/
  74. X
  75. X/* $Header: parseargs.h,v 2.0 89/12/24 00:56:29 eric Exp $ */
  76. X
  77. X#ifndef PARSEARGS_H
  78. X#define  PARSEARGS_H
  79. X
  80. X#include <useful.h>
  81. X
  82. X   /* type definition for argument prompt strings */
  83. X#define  MAX_ARGNAME  80
  84. Xtypedef char argName_t[ MAX_ARGNAME ];
  85. X
  86. X   /* type definition for bitmasks */
  87. Xtypedef unsigned short  argMask_t;
  88. X
  89. X/**********************************************************************
  90. X** ^STRUCT: ARGDESC - argument-descriptor
  91. X**
  92. X** ^DESCRIPTION:
  93. X**    The basic type used by the parseargs library is the argument descriptor
  94. X**    (or "argdesc" for short). An ARGDESC structure is used to describe a
  95. X**    command-line argument. Each command line argument contains various
  96. X**    fields which need to be set and/or queried by the programmer. Each
  97. X**    field is described in further detail below:
  98. X*/ 
  99. Xtypedef struct _argdesc {
  100. X   char ad_name;
  101. X/*    -- This is a single character which corresponds to the option-letter
  102. X**       (case-sensitive) from the command-line that matches the argument
  103. X**       described by this structure. Positional-arguments are denoted by
  104. X**       putting a a space character in this field.
  105. X*/ 
  106. X   argMask_t  ad_flags;
  107. X/*    -- This field contains the various bitflags that describe the semantics
  108. X**       of this argument. See the ARGFLAGS section for more information on
  109. X**       the possible combinations of bitmasks for this field.
  110. X*/ 
  111. X   BOOL (*ad_type) ARGS((struct _argdesc *, char *, BOOL));
  112. X/*    -- This field is a pointer to a type conversion function (such as the
  113. X**       ones provided in argtype(3)). The type conversion function is respon-
  114. X**       sible for verifying the validity of the argument, allocating any
  115. X**       necessary storage for its internal representation, and converting
  116. X**       the command-line argument into its required internal form. The type
  117. X**       conversion function used may be one of the pre-defined argtype(3)
  118. X**       functions. The function is given three parameters: The first is
  119. X**       a pointer to the ARGDESC struct in question, the second is the
  120. X**       string-value (if any) supplied on the command-line, and the third
  121. X**       is a boolean value that is TRUE only if the second parameter points
  122. X**       to temporary storage (and hence may need to be copied).
  123. X**       In the case of parseargs(1) this field must correspond to the name
  124. X**       of one of the argument type functions described in argtype(3).
  125. X*/ 
  126. X   ARBPTR ad_valp;
  127. X/*    -- This field is a generic pointer to the storage used to represent
  128. X**       the internal value of the command-line argument. It may be a
  129. X**       pointer to a number, a boolean value, a string, a list, or anything
  130. X**       else for which there exists a corresponding arg-type function to
  131. X**       use in the ad_type field. In the case of of parseargs(1) this field
  132. X**       must be the name of the corresponding shell variable which will
  133. X**       eventually hold the value of the argument given on the command-line.
  134. X*/ 
  135. X   CONST char *ad_prompt;
  136. X/*    -- This field contains the long-name of the argument and an optional
  137. X**       description (the description must be separated from the long-name by
  138. X**       at least one whitespace character and may optionally be enclosed in
  139. X**       a set of balanced delimiters (such as parentheses, curly-braces,
  140. X**       square-brackets, or angle-brackets). The longname may be specifed
  141. X**       in two parts: a keyword name and an argument name. The argument
  142. X**       name may be separated from the keyword name by a single equal sign
  143. X**       ('='). No whitespace is allowed before or after the equal sign.
  144. X**       Alternatatively, the keyword name may be distinguished from the
  145. X**       argument name by character case: if the long-name contains any
  146. X**       uppercase characters, then the substring of long-name consisting of
  147. X**       all uppercase characters is used as the argument keyword and the
  148. X**       entire long-name is used as the name of the argument (if a value may
  149. X**       be supplied). The long-name may be matched by supplying a unique
  150. X**       prefix of either the argument keyword or the argument name.
  151. X*/ 
  152. X} ARGDESC;
  153. X/**^^**********************************************************************/
  154. X
  155. X
  156. X   /* define a NULL pointer to an arg-descriptor */
  157. X#define ARGDESCNULL   (ARGDESC *)NULL
  158. X
  159. X   /* define a pointer to an argtype function */
  160. Xtypedef BOOL (*argTypePtr_t) ARGS((ARGDESC *, char *, BOOL));
  161. X
  162. X
  163. X/**********************************************************************
  164. X** ^SECTION: RETURN-CODES
  165. X**    The XparseXXXX functions in the parseargs library may return any of
  166. X**    the following return codes (which are #define'd below):
  167. X*/
  168. X#define  pe_SYSTEM   -1
  169. X/*    -- a system error occurred. The global variable errno may indicate
  170. X**       the problem (then again, it may not).
  171. X*/
  172. X#define  pe_SUCCESS   0
  173. X/*    -- success, no errors encountered.
  174. X*/
  175. X#define  pe_SYNTAX    1
  176. X/*    -- a command-line syntax error was encountered
  177. X*/
  178. X#define  pe_DEFARGS   2
  179. X/*    -- an attempt (using parsecntl()) was made to change the
  180. X**       default arg-search list of a command to point to an argdesc-array
  181. X**       which already has the given command on its default arg-search list
  182. X**       (which would cause an infinite loop when attempting to match an
  183. X**       unknown command-line argument).
  184. X*/
  185. X#define  pe_NOMATCH   3
  186. X/*    -- unable to match the named argument. This occurs
  187. X**       when the argument keyword name passed to parsecntl() (using the 
  188. X**       pc_ARGFLAGS function code) was NOT found in the given argdesc-array
  189. X**       or in its default-list.
  190. X*/
  191. X#define  pe_BADMODE   4
  192. X/*    -- bad mode for given command in parsecntl(). This occurs when 
  193. X**       pc_WRITE or pc_RDWR mode is passed to parsecntl() in conjunction
  194. X**       with the pc_ARGFLAGS functions code. Parsecntl will not modify
  195. X**       existing arguments.
  196. X*/
  197. X#define  pe_BADCNTL   5
  198. X/*    -- bad command for parsecntl. This occurs if an unknown function-code
  199. X**       was passed to parsecntl().
  200. X*/
  201. X#define  pe_BADOPEN   6
  202. X/*    -- error opening file
  203. X*/
  204. X#define  pe_BADREAD   7
  205. X/*    -- error reading file
  206. X*/
  207. X/**^^**********************************************************************/
  208. X
  209. X
  210. X/**********************************************************************
  211. X** ^SECTION: ARGUMENT-FLAGS
  212. X**    These are the possible bitmasks that may be turned ON or OFF in
  213. X**    the ad_flags field of an ARGDESC structure.
  214. X*/
  215. X#define ARGOPT       0x0000
  216. X/*    -- This flag is actually a dummy flag (i.e. it is the default). This flag
  217. X**       specifies that the command-line argument is optional (need not appear
  218. X**       on the command-line). It is only needed if no other flags are used to
  219. X**       define the given argument.  If other flags are given and ARGREQ is NOT
  220. X**       one of them, then ARGOPT is always assumed.
  221. X*/
  222. X#define ARGREQ       0x0001
  223. X/*    -- The associated command argument is required on the command-line.
  224. X*/
  225. X#define ARGPOS       0x0002
  226. X/*    -- The associated command argument is positonal. The difference between
  227. X**       using this flag to indicate a positional argument and between using
  228. X**       a blank in the ad_name field to indicate a positional arguments is
  229. X**       the following: If this flag is set but the ad_name of the argument
  230. X**       is non-blank, then this argument may be matched either positionally
  231. X**       or by keyword. If the ad_name field is blank, then this argument may
  232. X**       only be matched positionally.
  233. X*/
  234. X#define ARGNOVAL     0x0004
  235. X/*    -- The associated command argument takes no value (as in "-x value");
  236. X**       Its mere presence (or lack thereof) on the command-line is sufficient
  237. X**       to determine the necessary action(s) to take (as in "-x").
  238. X**
  239. X**       NOTE: all argBool, and arg[STU]Bool arguments are always forced to be
  240. X**       ARGNOVAL (as are argUsage arguments).
  241. X*/
  242. X#define ARGVALOPT    0x0008
  243. X/*    -- This flag is used to indicate that the command-line argument takes a
  244. X**       value (as in "-s string" or "/str=string") but that the value to this
  245. X**       command-line argument is NOT required (hence simply "-s" or "/str" is
  246. X**       also permissable).
  247. X*/
  248. X#define ARGVALREQ    0x0000
  249. X/*    -- Another "dummy" flag. Unless ARGNOVAL or ARGVALOPT is specified,
  250. X**       ARGVALREQ is always assumed. This flag indicates that the value to a
  251. X**       command-line argument is required (hence "-s string" is okay but just
  252. X**       "-s" is not).
  253. X*/
  254. X#define ARGHIDDEN    0x0010
  255. X/*    -- Don't display this argument in usage messages but still attempt to
  256. X**       match it against strings given on the command-line.
  257. X*/
  258. X#define ARGLIST      0x0020
  259. X/*    -- A variable number of values are used for this argument (and hence may
  260. X**       use more than one or two argv elements from the command-line as in
  261. X**       "-l val1 val2 ..."). The list of values must be stored in an arglist
  262. X**       structure (NOT a vector structure), an the corresponding argument-type
  263. X**       function should be one of the listXxxx functions.
  264. X*/
  265. X#define ARGVEC       0x0040
  266. X/*    -- A variable number of values are used for this argument (and hence may
  267. X**       use more than one or two argv elements from the command-line as in
  268. X**       in "-v val1 val2 ..."). The list of values must be stored in a vector
  269. X**       structure (NOT an arglist structure).
  270. X*/
  271. X
  272. X/*   The following bitmasks may also be present, but, unlike the above masks
  273. X**   which must be specified by the programmer at initialization time, the
  274. X**   following masks must only be read (never set) by the programmer:
  275. X*/
  276. X#define ARGGIVEN     0x0080
  277. X/*    -- The argument WAS given on the command-line.
  278. X*/
  279. X#define ARGVALGIVEN  0x0100
  280. X/*    -- The value for this argument was given on the command-line.
  281. X*/
  282. X#define ARGVALSEP    0x0200
  283. X/*    -- The value to this argument was supplied in a separate argv element
  284. X**       from the argument itself (as in "-x value" as opposed to "-xvalue").
  285. X*/
  286. X#define ARGKEYWORD   0x0400
  287. X/*    -- This argument was matched as a keyword (long-form) on the command-line
  288. X**       and not as a single character.
  289. X*/
  290. X#define ARGDESCRIBED 0x0800
  291. X/*    -- This argument was given a description by the programmer at
  292. X**       initialization.
  293. X*/
  294. X#define ARGCOPYF     0x1000
  295. X/*    -- This flag is only used for lists and vectors (multivalued arguments)
  296. X**       and is used on a per-item basis. If it is set, it means that the
  297. X**       corresponding value in the vector/list required space to be allocated
  298. X**       (such as the duplication of a temporary string).
  299. X*/
  300. X/**^^**********************************************************************/
  301. X
  302. X
  303. X/**********************************************************************
  304. X** ^SECTION: ARGDESC-MACROS
  305. X**    The following macros are used to extract and query the attributes
  306. X**    of a pointer to a preprocessed arg-descriptor:
  307. X*/
  308. X#define  arg_cname(ad)        ((ad) -> ad_name)
  309. X/*    -- return the single-character name of an argument.
  310. X*/
  311. X#define  arg_flags(ad)        ((ad) -> ad_flags)
  312. X/*    -- return the argument flags of an argument.  The flags themselves
  313. X**       may be manipulated using the BTEST, BSET, and BCLEAR macros
  314. X**       #defined in <useful.h>.
  315. X*/
  316. X#define  arg_type(ad)         ((ad) -> ad_type)
  317. X/*    -- return the pointer to the value-translation-routine of an argument.
  318. X*/
  319. X#define  arg_valp(ad)         ((ad) -> ad_valp)
  320. X/*    -- return the pointer to the value of this argument.
  321. X*/
  322. X#define  arg_sname(ad)        ((ad) -> ad_prompt)
  323. X/*    -- return the string name of an argument.
  324. X*/
  325. X#define  arg_sdesc(ad)        ( arg_sname(ad) )
  326. X/*    -- return the description of an argument. If a description was supplied,
  327. X**       the ARGDESCRIBED flag will be set and the description is available
  328. X**       by calling get_argdesc().
  329. X*/
  330. X#define  ARG_isDESCRIBED(ad)  BTEST( arg_flags(ad), ARGDESCRIBED )
  331. X/*    -- Evaluates to TRUE only if an argument description was provided.
  332. X*/
  333. X#define  arg_description(ad)  ( ARG_isDESCRIBED(ad) ? arg_sdesc(ad) : "" )
  334. X/*    -- Return the description string (or an empty string if no description
  335. X**       was given) for this argument.
  336. X*/
  337. X#define  ARG_isPOSITIONAL(ad) BTEST( arg_flags(ad), ARGPOS )
  338. X/*    -- Evaluates to TRUE if this argument may be positionally matched.
  339. X*/
  340. X#define  ARG_isPOSONLY(ad) ( arg_cname(ad) == ' ' )
  341. X/*    -- Evaluates to TRUE if this argument may only be positionally matched.
  342. X*/
  343. X#define  ARG_isLIST(ad)       ( BTEST(arg_flags(ad), ARGLIST) )
  344. X/*    -- Evaluates to TRUE if this argument is an arglist.
  345. X*/
  346. X#define  ARG_isVEC(ad)        ( BTEST(arg_flags(ad), ARGVEC) )
  347. X/*    -- Evaluates to TRUE if this argument is a vector.
  348. X*/
  349. X#define  ARG_isMULTIVAL(ad)   ( BTEST(arg_flags(ad), ARGVEC | ARGLIST) )
  350. X/*    -- Evaluates to TRUE if this argument is an arglist or a vector.
  351. X*/
  352. X#define  ARG_isVALTAKEN(ad)      ( ! BTEST(arg_flags(ad), ARGNOVAL) )
  353. X/*    -- Evaluates to TRUE if this argument does NOT take a value.
  354. X*/
  355. X#define  ARG_isGIVEN(ad)      ( BTEST(arg_flags(ad), ARGGIVEN) )
  356. X/*    -- Evaluates to TRUE if this argument was given on the command-line.
  357. X*/
  358. X#define  ARG_isVALGIVEN(ad)      ( BTEST(arg_flags(ad), ARGVALGIVEN) )
  359. X/*    -- Evaluates to TRUE if the argument value was given on the command-line.
  360. X*/
  361. X#define  ARG_isREQUIRED(ad)   ( BTEST(arg_flags(ad), ARGREQ) )
  362. X/*    -- Evaluates to TRUE if this argument is required.
  363. X*/
  364. X#define  ARG_isVALOPTIONAL(ad)   ( BTEST(arg_flags(ad), ARGVALOPT) )
  365. X/*    -- Evaluates to TRUE if the argument value is optional.
  366. X*/
  367. X#define  ARG_isVALSEPARATE(ad)   ( BTEST(arg_flags(ad), ARGVALSEP) )
  368. X/*    -- Evaluates to TRUE if the argument value is optional.
  369. X*/
  370. X#define  ARG_isHIDDEN(ad)     ( BTEST(arg_flags(ad), ARGHIDDEN) )
  371. X/*    -- Evaluates to TRUE if this argument is omitted from usage messages.
  372. X*/
  373. X/**^^**********************************************************************/
  374. X
  375. X
  376. X   /* macro to define a NULL argument-type function */
  377. X#define argNULL    (argTypePtr_t)NULL
  378. X
  379. X   /* macro for an empty argument descriptor */
  380. X#define ARG_EMPTY   { '\0', 0x0000, argNULL, ARBNULL, CHARNULL }
  381. X
  382. X   /*
  383. X   ** macro to denote start & end of an ARGDESC array declared without
  384. X   ** the CMD_XXXXXXX macros which follow.
  385. X   */
  386. X#define STARTOFARGS  ARG_EMPTY
  387. X#define ENDOFARGS    ARG_EMPTY, ARG_EMPTY
  388. X
  389. X/***************************************************************************
  390. X** ^SECTION: CMD-MACROS
  391. X**    Parseargs.h defines a set of macros to allow a more "self documenting"
  392. X**    approach to declaring argument-descriptor arrays. The "old-style" is
  393. X**    still accepted (but if used it is recommended that the STARTOFARGS
  394. X**    macro is used in conjunction with ENDOFARGS).  An example use of these
  395. X**    macros (which, with one exception, all begin with "CMD") follows:
  396. X**
  397. X**         #include <parseargs.h>
  398. X**    
  399. X**         static BOOL bflag = FALSE;
  400. X**         static char *arg1 = CHARNULL;
  401. X**         static char *arg2 = CHARNULL;
  402. X**    
  403. X**         static
  404. X**         CMD_OBJECT
  405. X**            MyCmd
  406. X**
  407. X**         CMD_NAME
  408. X**            "mycmd -- one line statement of purpose"
  409. X**    
  410. X**         CMD_DESCRIPTION
  411. X**            "Mycmd will try really really hard to run without errors \
  412. X**         and do whatever the heck it is supposed to do. If (God forbid) \
  413. X**         something should actually go wrong it will say so."
  414. X**    
  415. X**         CMD_ARGUMENTS
  416. X**            'b', ARGOPT, argSBool, __ &bflag,
  417. X**            "bflag -- turn on `b'-mode (whatever that is)",
  418. X**    
  419. X**            ' ', ARGREQ, argStr, __ &arg1,
  420. X**            "arg1 -- first argument to this spiffy program",
  421. X**    
  422. X**            ' ', ARGOPT, argStr, __ &arg2,
  423. X**            "arg2 -- optional second argument to this spiffy program",
  424. X**    
  425. X**            END_ARGUMENTS
  426. X**         CMD_END
  427. X**    
  428. X**         main( argc, argv )
  429. X**            int argc;
  430. X**            char *argv[];
  431. X**         {
  432. X**            (void) parseargs( argv, MyCmd );
  433. X**            (void) dostuff();
  434. X**            exit( 0 );
  435. X**         }
  436. X***^^**********************************************************************/
  437. X#define CMD_OBJECT       ARGDESC
  438. X#define CMD_NAME         [] = { { '\0', (argMask_t)0x0000, (argTypePtr_t)
  439. X#define CMD_DESCRIPTION  , ARBNULL,
  440. X#define CMD_ARGUMENTS    },
  441. X#define START_ARGUMENTS  ARG_EMPTY
  442. X#define END_ARGUMENTS    ARG_EMPTY
  443. X#define CMD_END          };
  444. X
  445. X   /*
  446. X   ** shorthand for declaring main program
  447. X   */
  448. X#ifdef __ANSI_C__
  449. X# define MAIN(argc,argv)  int main( int argc, char *argv[] )
  450. X#else
  451. X# define MAIN(argc,argv)  int main( argc, argv ) int argc; char *argv[];
  452. X#endif
  453. X
  454. X/***************************************************************************
  455. X** ^SECTION: MULTI-VALUED_ARGUMENTS
  456. X**    Parseargs supports two different types of multi-valued arguments:
  457. X**    linked-lists and vectors. The linked-lists are called argument lists
  458. X**    (or arg-lists) and are specified by supplying the ARGLIST flag along
  459. X**    with an associated listXxxx argument-translation routine. The value
  460. X**    associated with an arg-list should be a list structure of type ArgList.
  461. X**    The include file <parseargs.h> defines four macros for manipulating
  462. X**    ArgList structures:  ARGLISTNULL, L_NEXT, L_STRING, and L_FLAGS.
  463. X**
  464. X**    ARGLISTNULL is simply the NULL argument-list pointer.  L_NEXT and
  465. X**    L_STRING each take a pointer to a non-NULL ArgList structure. L_NEXT
  466. X**    returns the address of the next item in the list and L_STRING returns
  467. X**    the string-value of the current list-item.  L_FLAGS return the argflags
  468. X**    for a given item in the list. With non-multivalued arguments, only the
  469. X**    flags in the argument descriptor are needed; lists and vectors however
  470. X**    need a set of flags for each item they contain. Once an arg-list has
  471. X**    been created, it may be deallocated using the function listFree. List-
  472. X**    Free takes one parameter: the address of the first item in the arg-list.
  473. X**
  474. X**    An alternative to argument-lists is argument vectors (or arg-vectors).
  475. X**    Arg-vectors use the ARGVEC flag instead of the ARGLIST flag and do not
  476. X**    require a special listXxxx function for each vector-type.  Each of the
  477. X**    argXxxx functions is responsible for handling vectors of its type
  478. X**    (although some argXxx functions such as the boolean types do not sup-
  479. X**    port vectors). An arg-vector is a structure which contains a count, an
  480. X**    array of elements (i.e. an argc/argv pair), and an array of flags, one
  481. X**    for each element of argv. There are two macros in defined in
  482. X**    <parseargs.h> which are used for arg-vectors. ARGVEC_T may be used to
  483. X**    declare a vector structure or a vector type; ARGVEC_EMPTY may be used
  484. X**    to initialize the structure.  It is strongly recommended that ARGVEC_T
  485. X**    be used to declare vector types in a typedef statement (particularly
  486. X**    if one is using function prototypes) but for those who insist, it may
  487. X**    be used to directly declare a  structure.  String-vectors will always
  488. X**    have an extra NULL-pointer at the end such that:
  489. X**
  490. X**         ( StrVec.array[ StrVec.count ] == (char *)NULL )
  491. X**
  492. X**    is always true, and character-vectors will always have an extra NUL-
  493. X**    character at the end such that:
  494. X**
  495. X**         ( CharVec.array[ CharVec.count ] == '\0' )
  496. X**
  497. X**    is always true. Integer and floating point vectors contain no extra
  498. X**    "null" elements.
  499. X**
  500. X**    Once created, arg-vectors may be deallocated by calling the macro vec-
  501. X**    Free or the macro vecDeepFree and passing it the arg-vector structure.
  502. X**    The differemce between these two macros is that the latter will also
  503. X**    free each item in the vector that required space to be allocated (at
  504. X**    the expense of traversing the vector).  At this writing, the only
  505. X**    predefined argument-type(s) that would benefit from vecDeepFree is
  506. X**    argStr vectors.
  507. X**
  508. X**    An example use of arg-lists, and of arg-vectors follows:
  509. X**
  510. X**         #include <parseargs.h>
  511. X**
  512. X**         typedef ARGVEC_T(char *) strvec_t;
  513. X**
  514. X**         static ArgList  *StringList = ARGLISTNULL;
  515. X**         static strvec_t  StringVec = ARGVEC_EMPTY(char *);
  516. X**         static ARGVEC_T(int)  NumberVec = ARGVEC_EMPTY(int);
  517. X**
  518. X**         static
  519. X**          CMD_OBJECT  Args
  520. X**          CMD_NAME    "foo -- do whatever foo does"
  521. X**          CMD_DESCRIPTION  "put a brief paragraph here"
  522. X**          CMD_ARGUMENTS
  523. X**            'l', ARGLIST, listStr, __ &StrList, "LiSt {list of strings}",
  524. X**            's', ARGVEC,  argStr,  __ &StrVec,  "STRing {vector of strings}",
  525. X**            'i', ARGVEC,  argInt,  __ &NumVec,  "NUMber {vector of numbers}",
  526. X**            END_ARGUMENTS
  527. X**          CMD_END
  528. X**
  529. X**         main( int argc, char *argv[] )
  530. X**         {
  531. X**            int i, *ls;
  532. X**
  533. X**            if ( parseargs(argv, Args) )  syserr( "parseargs failed" );
  534. X**
  535. X**            for ( ls = StrList, i=1 ; ls ; ls = L_NEXT(ls), i++ )
  536. X**               printf( "List item %d=%s, flags=%x0\n",
  537. X**                       i, L_STRING(ls), L_FLAGS(ls) );
  538. X**
  539. X**            for ( i = 0 ; i < StrVec.count ; i++ )
  540. X**               printf( "String[%d]=%s, flags=%x0\n",
  541. X**                       i, StrVec.array[i], StrVec.flags[i] );
  542. X**
  543. X**            for ( i = 0 ; i < NumVec.count ; i++ )
  544. X**               printf( "Number[%d]=%s, flags=%x0\n",
  545. X**                       i, NumVec.array[i], NumVec.flags[i] );
  546. X**
  547. X**            listFree( StrList );
  548. X**            StrList = ARGLISTNULL;
  549. X**
  550. X**            vecDeepFree( StrVec, char * );
  551. X**            vecFree( NumVec, int );
  552. X**
  553. X**            exit( 0 );
  554. X**         }
  555. X**
  556. X**^^***********************************************************************/
  557. X
  558. X   /* definition of an arg-list */
  559. Xtypedef struct arglist {
  560. X   struct arglist  *nl_next;  /* pointer to next item */
  561. X   ARBPTR           nl_val;   /* value of current item */
  562. X   argMask_t        nl_flags; /* flags for current item */
  563. X} ArgList;
  564. X#define ARGLISTNULL  (ArgList *)NULL
  565. X
  566. X   /* definition of an arg-list-head (the first two fields MUST exactly
  567. X   ** overlay with their corresponding elements in an ArgList struct)
  568. X   */
  569. Xtypedef struct arglisthead {
  570. X   ArgList  *nl_next;  /* pointer to next item */
  571. X   ARBPTR    nl_val;   /* value of current item */
  572. X   argMask_t nl_flags; /* flags for current item */
  573. X   ArgList  *nl_tail;  /* pointer to last item */
  574. X} ArgListHead;
  575. X#define ARGLISTHEADNULL  (ArgListHead *)NULL
  576. X
  577. X   /*
  578. X   ** macros to manipulate arg-lists
  579. X   */
  580. X#define L_STRING(ls)   ((char *)((ls)->nl_val))  /* Item as a string */
  581. X#define L_NEXT(ls)     ((ls)->nl_next)           /* Next item of list */
  582. X#define L_ADVANCE(ls)  (ls) = (ArgList *)L_NEXT(ls) /* Advance list ptr */
  583. X#define L_FLAGS(ls)    ((ls)->nl_flags)          /* flags of current item */
  584. X
  585. X   /*
  586. X   ** macros to declare and initialize arg-vectors
  587. X   **   (NOTE: this wont work for vectors of function pointers)
  588. X   */
  589. X#define ARGVEC_T(type) \
  590. X    struct { type  *array; unsigned short  count; argMask_t *flags; }
  591. X#define ARGVEC_EMPTY(type) \
  592. X    { (type *) NULL, (unsigned short) 0, (argMask_t *) NULL }
  593. X
  594. X
  595. X/**********************************************************************
  596. X** ^SECTION: PARSE-FLAGS
  597. X**    The following bitmasks may be combined in order to modify the
  598. X**    behavior of the parseargs library. The parse flags for a given
  599. X**    may be set through the use of the parsecntl() function.
  600. X*/
  601. X#define pa_PROMPT    0x0001
  602. X/*    -- Prompt the user for any missing arguments that are required on the
  603. X**       command-line. No special escaping or quoting is performed on the
  604. X**       user input. Required arguments that expect a list of values will
  605. X**       be repeatedly prompted for (one item per line) until a blank line
  606. X**       (followed by a carriage return) is entered.
  607. X*/
  608. X#define pa_IGNORE    0x0002
  609. X/*    -- Ignore any unrecognized or improperly specified command-line arguments
  610. X**       and continue execution of the program. Normally, if a required
  611. X**       argument is unmatched (or an argument is improperly specified),
  612. X**       a usage message is printed program execution is terminated.
  613. X*/
  614. X#define pa_OPTSONLY  0x0004
  615. X/*    -- Under UNIX, setting this flag will disable the parsing of long-option
  616. X**       syntax. This will cause all arguments starting with '+' to always be
  617. X**       treated as a positional parameter (instead of a long-option).
  618. X*/
  619. X#define pa_KWDSONLY  0x0008
  620. X/*    -- Under UNIX, setting this flag disables the parsing of single-character
  621. X**       options.  This will cause all arguments starting with '-' to always
  622. X**       be treated as a positional parameter (instead of an option).
  623. X*/
  624. X#define pa_FLAGS1ST  0x0010
  625. X/*    -- Setting this flag causes the parseargs library to force any and all
  626. X**       non-positional arguments to be specified before any positional ones.
  627. X**       As an example, under UNIX, if this flag is SET then parseargs will
  628. X**       consider the command line "cmd -x arg" to consist of one option and
  629. X**       one positional argument; however the command line "cmd arg -x" would
  630. X**       be considered to consist of two positional arguments (the -x option
  631. X**       will be unmatched).
  632. X**
  633. X**       If this flag is UNSET, then both of the previous examples are
  634. X**       considered to consist of one option and one positional argument.
  635. X*/
  636. X#define pa_ANYCASE   0x0020
  637. X/*    -- Setting this flag cause character-case to be ignored when attempting
  638. X**       to match single-character argument names (i.e. causes "-i" and "-I"
  639. X**       to be considered equivalent).
  640. X*/
  641. X#define pa_ARGV0     0x0040
  642. X/*    -- Normally, the parseargs library will assume that the first argument
  643. X**       on the command-line is the name of the command. Setting this flag
  644. X**       tells parseargs that this is NOT the case and that the very first
  645. X**       argument on the command-line is a bona-fide argument to the command.
  646. X*/
  647. X#define pa_NOCHECK   0x0080
  648. X/*    -- Setting this flag will prevent parseargs from checking for any 
  649. X**       required arguments that were not given on the command-line. This
  650. X**       is useful when more than one call to the parseargs library is needed
  651. X**       to parse all the command-line arguments (which could occur if the
  652. X**       command-line argument came from a file or from two argv-vectors).
  653. X**       When this flag is set, then each call to parseargs will check for
  654. X**       missing required arguments (and will prompt the user for them if
  655. X**       desired).
  656. X**
  657. X**       Keeping this flag on until the final set of arguments is parsed will
  658. X**       cause parseargs to not check for missing arguments until the last set
  659. X**       of arguments has been parsed (by the final call to one of the
  660. X**       functions in the parseargs library).
  661. X*/
  662. X#define pa_CONTINUE  0x0100
  663. X/*    -- Setting this flag will cause subsequent calls to the parseargs library
  664. X**       to NOT reset the current command-state. Hence, all arguments will not
  665. X**       be initially set to "NOT GIVEN" and other (normal) initializations are
  666. X**       not be performed.  This is useful in conjunction with the pa_NOCHECK
  667. X**       when more than one call to parseargs is required to parse all the
  668. X**       command arguments. In this scenario, pa_CONTINUE should be unset (the
  669. X**       default setting) for the very first call to parseargs, but should then
  670. X**       be set before any subsequent calls to parseargs are made.
  671. X*/
  672. X#define pa_NOCMDENV  0x0200
  673. X/*    -- Setting this flag prevents parseargs from checking the <CMD-NAME>_ARGS
  674. X**       environment variable for any user-defined default command arguments.
  675. X*/
  676. X#define pa_COPYF     0x0400
  677. X/*    -- When this flag is OFF (the default), a value of FALSE is provided as
  678. X**       the <copyf> argument to all the arg-type (argXxxxx) functions when an
  679. X**       argument is matched. Setting this flag will cause a value of TRUE to
  680. X**       be provided as the <copyf> argument to all the arg-type (argXxxxx)
  681. X**       functions when an argument is matched.
  682. X*/
  683. X/**^^**********************************************************************/
  684. X
  685. X
  686. X/**********************************************************************
  687. X** ^SECTION: PARSE-CNTLS - specify which attributes to get/set
  688. X**    Each of the following function codes specifies an attribute that
  689. X**    is to be manipulated by parsecntl(3).  The function code is the
  690. X**    second parameter to parsecntl(3). With the exception of pc_ARGFLAGS,
  691. X**    each of the function codes corresponds to a call to parsecntl(3) 
  692. X**    using four parameters (pc_ARGFLAGS uses 5 parameters). In each case,
  693. X**    the last parameter is either the address of a buffer to write the
  694. X**    attribute to, or the actual buffer to read the attribute from 
  695. X**    (depending upon the mode -- the third parameter to parsecntl).
  696. X*/
  697. Xtypedef enum  {
  698. X   pc_PARSEFLAGS,
  699. X/*    -- get/set parse flags
  700. X**
  701. X**    This function code is used to read and/or modify the existing parsing 
  702. X**    parsing behavior. The fourth parameter to parsecntl should be a 
  703. X**    combination of pc_XXXX bitmasks if the parse-flags are only being
  704. X**    written, otherwise it should be a pointer to an argMask_t variable.
  705. X*/
  706. X   pc_ARGFLAGS,
  707. X/*    -- get/set argument flags
  708. X**
  709. X**    This function code may only be used to read the argument-flags of
  710. X**    a named argument. It is an error to specify a mode that attempts
  711. X**    to write the argument-flags with this function code. The fourth
  712. X**    parameter to parsecntl should be the keyword name of the argument
  713. X**    whose flags are to be read. The fifth (and final) argument should
  714. X**    be a pointer to the argMask_t variable which will receive the resulting
  715. X**    argument-flags.
  716. X*/
  717. X   pc_DEFARGS,
  718. X/*    -- get/set the default arguments
  719. X**
  720. X**    This function code is used to query or modify the current default
  721. X**    argument-descriptor list for the given command. The fourth parameter
  722. X**    to parsecntl should be the argument-descriptor array to assign as the
  723. X**    new default-list (or the address of an argdesc-array if the default
  724. X**    list is being retrieved).
  725. X**
  726. X**    If a given option/qualifier does not appear to match any items in the
  727. X**    argdesc-array, a  default argdesc-array is then searched to match the
  728. X**    option. If it is STILL unmatched then it is flagged as such. The
  729. X**    default-argdesc array is automatically used by all programmer-defined
  730. X**    argdesc-array but may be unset or reset using the pc_DEFARGS function
  731. X**    of parsecntl(3). In such a  manner, a  programmer could specify a dif-
  732. X**    ferent set of default-arguments to search for. Furthermore, default
  733. X**    argdesc-arrays may also be assigned default argdesc-arrays, thus
  734. X**    allowing the programmer to define a whole search-list of default
  735. X**    argdesc-arrays for a given command.
  736. X**
  737. X**    This could prove useful in a situation where a set of commands have a
  738. X**    few common-options and differ in their remaining ones. If the same
  739. X**    main() were used for each command, then main could define one common
  740. X**    argdesc-array and then a set of argdesc-arrays for each command. Main
  741. X**    could then figure out which argdesc-array to used based on the name in
  742. X**    argv[0], and set its default argdesc-array to be the common argdesc-
  743. X**    array, as in the following:
  744. X**
  745. X**         #include <parseargs.h>
  746. X**             .
  747. X**             . variable declarations
  748. X**             .
  749. X**
  750. X**         static ARGDESC common_args[] = {
  751. X**            STARTOFARGS,
  752. X**            'L', ARGOPT, argBool, __ &lflag, "list (list available items)"
  753. X**            'I', ARGOPT, argStr, __ &item, "item (specify item to use)",
  754. X**            ENDOFARGS
  755. X**         };
  756. X**
  757. X**         static ARGDESC cmd1_args[] = {
  758. X**            STARTOFARGS,
  759. X**            's', ARGOPT, argBool, __ &sflag, "S (set S)",
  760. X**            't', ARGOPT, argBool, __ &tflag, "T (set T)",
  761. X**            ENDOFARGS
  762. X**         };
  763. X**
  764. X**         static ARGDESC cmd2_args[] = {
  765. X**            STARTOFARGS,
  766. X**            'x', ARGOPT, argBool, __ &xflag, "X (set X)",
  767. X**            'y', ARGOPT, argBool, __ &yflag, "Y (set Y)",
  768. X**            ENDOFARGS
  769. X**         };
  770. X**
  771. X**         main( argc, argv ) int argc; char *argv[];
  772. X**         {
  773. X**            ARGDESC *cmd = cmd1_args;
  774. X**            int status;
  775. X**
  776. X**            if ( strcmp(*argv, "cmd2") == 0 ) cmd = cmd2_args;
  777. X**
  778. X**            if ( parsecntl( cmd, pc_DEFARGS, pc_WRITE, common_args ) != 0 )
  779. X**               syserr( "unable to set default args" );
  780. X**
  781. X**            status = parseargs( argv, cmd );
  782. X**                   .
  783. X**                   .
  784. X**                   .
  785. X**         }
  786. X**
  787. X**    Note that in the above call to parsecntl(3), that zero will be
  788. X**    returned upon success and non-zero upon failure. If pe_DEFARGS is
  789. X**    returned, then cmd is already on common_args's list of defaults (and
  790. X**    would result in an infinite loop while parsing).
  791. X*/
  792. X   pc_NAME,
  793. X/*    -- get/set the command-name
  794. X*/
  795. X   pc_PURPOSE,
  796. X/*    -- get/set the command-purpose
  797. X*/
  798. X   pc_DESCRIPTION
  799. X/*    -- get/set the command-description
  800. X*/
  801. X/*    Each of these last three function codes are used to modify or query the
  802. X**    name, purpose, or description associated with a command. The fourth
  803. X**    parameter to parsecntl should be the new string to use (or the address
  804. X**    of the string, a char** variable, to recieve the current value).
  805. X*/
  806. X} parsecntl_t;
  807. X
  808. X/**^^**********************************************************************/
  809. X
  810. X
  811. X/**********************************************************************
  812. X** ^SECTION: PARSE-MODES - modes to get/set command attributes.
  813. X**    Parsecntl may be used to read current command attributes, write/assign
  814. X**    new command attributes, or both. The mode argument to parsecntl
  815. X**    determines which of these three alternatives are desired. If the
  816. X**    programmer merely wishes to assign new attributes, then invoking
  817. X**    parsecntl in pc_WRITE mode and passing the new attributes will do the
  818. X**    job. If the programmer wishes simply to query attributes, then
  819. X**    invoking parsecntl in pc_READ mode and passing a pointer to the
  820. X**    desired object in which to write the attribute settings will suffice.
  821. X**
  822. X**    If the programmer wishes to assign new attributes and at the same time
  823. X**    find out what the attributes were before making the assignment, then
  824. X**    programmer must invoke parsecntl for pc_RDWR mode and pass a pointer
  825. X**    to the object containing the new attribute settings; When parsecntl
  826. X**    returns, then (assuming it returns 0) the desired attributes will have
  827. X**    been assigned and the object that contained the new attribute settings
  828. X**    will now contain the attribute settings that were in effect immediately
  829. X**    before parsecntl was invoked.
  830. X*/
  831. Xtypedef enum  {
  832. X   pc_READ,
  833. X/*    -- read-mode: attributes are retrieved
  834. X*/
  835. X   pc_WRITE,
  836. X/*    -- write-mode: attributes are assigned new values
  837. X*/
  838. X   pc_RDWR
  839. X/*    -- read/write-mode: attributes are retrieved and then assigned
  840. X*/
  841. X
  842. X} parsemode_t;
  843. X/**^^**********************************************************************/
  844. X
  845. X
  846. X   /*
  847. X   ** private (implementation specific) definitions
  848. X   */
  849. X#ifdef PARSEARGS_PRIVATE
  850. X
  851. X   /* macros to define command-line style specific character sequences */
  852. X# ifdef amiga_style
  853. X#   define  s_ARG_SEP  "=:"  /* AmigaDOS argument separator characters */
  854. X# endif
  855. X# ifdef ibm_style
  856. X#   define  s_ARG_SEP  "="  /* MS-DOS and OS/2 argument separator characters */
  857. X# endif
  858. X# ifdef unix_style
  859. X#   define  c_OPT_PFX  '-'   /* Unix option prefix character */
  860. X#   define  c_KWD_PFX  '+'   /* Unix keyword prefix character */
  861. X#   define  s_ARG_SEP  "=:"  /* Unix keyword-value separator characters */
  862. X# endif
  863. X# ifdef vms_style
  864. X#   define  s_KWD_PFX  "/"   /* VMS qualifier prefix character */
  865. X#   define  s_LSI_SEP  ",+"  /* VMS LiSt Item separator characters */
  866. X#   define  s_ARG_SEP  "=:"  /* VMS qualifier-value separator characters */
  867. X# endif
  868. X
  869. X
  870. X   /* call the function to parse the given argument-value string */
  871. X# define HANDLE(ad,vp,pflags) ((*arg_type(ad))(ad, vp, BTEST(pflags, pa_COPYF)))
  872. X
  873. X
  874. X   /* parse-state flags */
  875. X# define  ps_OLDSTYLE     0x01  /* force backward compatibility? */
  876. X# define  ps_NOFLAGS      0x02  /* opt/kwd parsing in effect? */
  877. X# define  ps_NOCMDENV     0x04  /* <CMD>_ARGS environment-variable parsed? */
  878. X# define  ps_NOPARSECNTL  0x08  /* PARSECNTL environment-variable parsed? */
  879. X# define  ps_USERNAME     0x10    /* user supplied name string */
  880. X# define  ps_FREENAME     0x10    /* free name string space */
  881. X# define  ps_USERPURPOSE  0x20    /* user supplied purpose string */
  882. X# define  ps_FREEPURPOSE  0x20    /* free purpose string space */
  883. X# ifdef vms_style
  884. X#  define  ps_NOTCMDLINE  0x40  /* argv-array is NOT from the command-line */
  885. X# endif
  886. X
  887. Xtypedef unsigned short   ps_flags_t;
  888. X
  889. X
  890. X   /*
  891. X   ** structure to hold arg-desc pointers maintained in the command-context
  892. X   */
  893. Xtypedef struct {
  894. X   ARGDESC  *default_argd;   /* pointer to default args */
  895. X   ARGDESC  *current_list;   /* pointer to ad with arglist (or argvector)
  896. X                             ** that is currently being appended.
  897. X                             */
  898. X# ifdef amiga_style
  899. X     ARGDESC  *previous_ad;  /* pointer to previously matched ad */
  900. X# endif
  901. X} ARGDPTRS;
  902. X
  903. X   /*
  904. X   ** structures to replace the first and last argument descriptor
  905. X   ** in a command (each field must exactly overlay its counterpart
  906. X   ** in an ARGDESC struct).
  907. X   */
  908. Xtypedef struct  {
  909. X   char        id;      /* id is ALWAYS '\0' for first and last ad */
  910. X   ps_flags_t  state_flags;  /* current parse-state */
  911. X   CONST char *argv0;   /* argv[0] from the command-line */
  912. X   ARGDPTRS   *argdp;   /* structure with ARGDESC pointers */
  913. X   CONST char *purpose; /* one-line purpose provided with CMD_NAME */
  914. X} CTXDESC;  /* the command-context */
  915. X
  916. Xtypedef struct  {
  917. X   char        id;      /* id is ALWAYS '\0' for first and last ad */
  918. X   argMask_t   parse_flags;  /* current parse-flag bitmasks */
  919. X   CONST char *name;    /* command-name provided with CMD_NAME */
  920. X   CTXDESC    *context; /* pointer to command-context */
  921. X   CONST char *description;  /* description provided with CMD_DESCRIPTION */
  922. X} CMDDESC; /* the command-descriptor */
  923. X
  924. X   /*
  925. X   ** macros to extract command-line attributes in the command-object
  926. X   */
  927. X# define  cmd_desc(cmd)         (CMDDESC *)cmd
  928. X# define  cmd_id(cmd)           (cmd_desc(cmd)) -> id
  929. X# define  cmd_flags(cmd)        (cmd_desc(cmd)) -> parse_flags
  930. X# define  cmd_name(cmd)         (cmd_desc(cmd)) -> name
  931. X# define  cmd_description(cmd)  (cmd_desc(cmd)) -> description
  932. X# define  cmd_context(cmd)      (cmd_desc(cmd)) -> context
  933. X# define  cmd_ctxid(cmd)        (cmd_context(cmd)) -> id
  934. X# define  cmd_state(cmd)        (cmd_context(cmd)) -> state_flags
  935. X# define  cmd_argv0(cmd)        (cmd_context(cmd)) -> argv0
  936. X# define  cmd_purpose(cmd)      (cmd_context(cmd)) -> purpose
  937. X# define  cmd_ptrs(cmd)         (cmd_context(cmd)) -> argdp
  938. X# define  cmd_defargs(cmd)      (cmd_ptrs(cmd)) -> default_argd
  939. X# define  cmd_list(cmd)         (cmd_ptrs(cmd)) -> current_list
  940. X# ifdef amiga_style
  941. X#   define  cmd_prev(cmd)  (cmd_ptrs(cmd)) -> previous_ad
  942. X# endif
  943. X
  944. X   /* macro to determine if a command-object has been initialized */
  945. X# define  CMD_isINIT(cmd)  \
  946. X   ( !cmd_id(cmd)  &&  cmd_context(cmd) )
  947. X
  948. X   /*
  949. X   ** macros to help ascertain argument type
  950. X   */
  951. X# define ARG_isBOOLEAN(ad)   \
  952. X   ( arg_type(ad) == argBool  || arg_type(ad) == argSBool || \
  953. X     arg_type(ad) == argUBool || arg_type(ad) == argTBool    \
  954. X   )
  955. X# define ARG_isPSEUDOARG(ad) \
  956. X   ( arg_type(ad) == argEnd   || \
  957. X     arg_type(ad) == argUsage || \
  958. X     arg_type(ad) == argDummy    \
  959. X   )
  960. X
  961. X   /*
  962. X   ** macros to assist in traversing a command-object
  963. X   */
  964. X# define  ARG_FIRST(cmd)   ((cmd) + 1)
  965. X# define  ARG_LAST(cmd)    ( ((ARGDESC *)cmd_context(cmd)) - 1 )
  966. X# define  ARG_isEND(ad)    ( arg_cname(ad)  ==  '\0' )
  967. X# define  ARG_ADVANCE(ad)  (ad)++
  968. X# define  ARG_RETREAT(ad)  (ad)--
  969. X
  970. X
  971. X/**********************************************************************
  972. X** ^SECTION: USAGECNTL
  973. X**    Each of the different values in $USAGECNTL corresponds to a
  974. X**    bitmask as follows:
  975. X*/
  976. X# define  usg_NONE         0x0001
  977. X/*    -- "Quiet", "Silent", and "None" : dont print usage
  978. X*/
  979. X# define  usg_VERBOSE      0x0002
  980. X/*    -- "Verbose", "!Terse" : print argument descriptions
  981. X*/
  982. X# define  usg_OPTS         0x0004
  983. X/*    -- "Options" -- print option syntax
  984. X*/
  985. X# define usg_LONGOPTS     0x0008
  986. X/*    -- "LongOpts", "KeyWords" : print long-option/keyword syntax
  987. X*/
  988. X# define  usg_DESCRIPTION  0x0010
  989. X/*    -- "Description" : print the command description
  990. X*/
  991. X# define  usg_PAGED        0x0020
  992. X/*    -- "Paged" : pipe the usage message through a paging program
  993. X*/
  994. X/**^^**********************************************************************/
  995. X
  996. X#endif /* PARSEARGS_PRIVATE */
  997. X
  998. X   /*
  999. X   ** pre-defined types available for ad_type
  1000. X   */
  1001. X#ifndef PARSEARGS_NARGTYPES
  1002. X# define  ARGTYPE(name)  EXTERN  BOOL  name ARGS(( ARGDESC *, char *, BOOL ))
  1003. X   ARGTYPE( argUsage );
  1004. X   ARGTYPE( argEnd );
  1005. X   ARGTYPE( argDummy );
  1006. X   ARGTYPE( argBool );
  1007. X   ARGTYPE( argSBool );
  1008. X   ARGTYPE( argUBool );
  1009. X   ARGTYPE( argTBool );
  1010. X   ARGTYPE( argChar );
  1011. X   ARGTYPE( argStr );
  1012. X   ARGTYPE( argInt );
  1013. X   ARGTYPE( argShort );
  1014. X   ARGTYPE( argLong );
  1015. X   ARGTYPE( argFloat );
  1016. X   ARGTYPE( argDouble );
  1017. X   ARGTYPE( listStr );
  1018. X   EXTERN  VOID  listFree ARGS((ArgList *argls));
  1019. X# define vecFree(vec,type)  \
  1020. X    do { \
  1021. X        if ( vec.count > 0 ) { \
  1022. X            if ( vec.array )  free( vec.array ); \
  1023. X            if ( vec.flags )  free( vec.flags ); \
  1024. X        } \
  1025. X        vec.array = (type *)NULL; \
  1026. X        vec.flags = (argMask_t *)NULL; \
  1027. X        vec.count = 0; \
  1028. X    } while ( 0 )
  1029. X# define vecDeepFree(vec,type)  \
  1030. X    do { \
  1031. X        register int i; \
  1032. X \
  1033. X        for ( i = 0 ; i < vec.count ; i++ ) \
  1034. X            if ( BTEST(vec.flags[i], ARGCOPYF) ) \
  1035. X                free( (ARBPTR) vec.array[i] ); \
  1036. X \
  1037. X        if ( vec.count > 0 ) { \
  1038. X            if ( vec.array )  free( vec.array ); \
  1039. X            if ( vec.flags )  free( vec.flags ); \
  1040. X        } \
  1041. X        vec.array = (type *)NULL; \
  1042. X        vec.flags = (argMask_t *)NULL; \
  1043. X        vec.count = 0; \
  1044. X    } while ( 0 )
  1045. X
  1046. X# undef ARGTYPE
  1047. X#endif  /* PARSEARGS_NARGTYPES */
  1048. X
  1049. X   /*
  1050. X   ** parseargs library function-prototypes
  1051. X   */
  1052. X#ifndef  PARSEARGS_NEXTERNS
  1053. X   EXTERN int   fparseargs  ARGS(( FILE *, ARGDESC * ));
  1054. X   EXTERN int   lparseargs  ARGS(( ArgList *, ARGDESC * ));
  1055. X   EXTERN int   sparseargs  ARGS(( char *, ARGDESC * ));
  1056. X   EXTERN int   vparseargs  ARGS(( ARGDESC *, int, ...));
  1057. X   EXTERN int   parseargs   ARGS(( char **, ARGDESC * ));
  1058. X   EXTERN int   parsecntl   ARGS(( ARGDESC *, parsecntl_t, parsemode_t, ...));
  1059. X   EXTERN VOID  usage       ARGS(( const ARGDESC * ));
  1060. X   EXTERN VOID  init_args   ARGS(( ARGDESC * ));
  1061. X   EXTERN CONST char *ProgName;
  1062. X   EXTERN int   ProgNameLen;
  1063. X#endif  /* PARSEARGS_NEXTERNS */
  1064. X
  1065. X#endif  /* PARSEARGS_H */
  1066. END_OF_FILE
  1067. if test 44214 -ne `wc -c <'parseargs.h'`; then
  1068.     echo shar: \"'parseargs.h'\" unpacked with wrong size!
  1069. fi
  1070. # end of 'parseargs.h'
  1071. fi
  1072. echo shar: End of archive 8 \(of 10\).
  1073. cp /dev/null ark8isdone
  1074. MISSING=""
  1075. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1076.     if test ! -f ark${I}isdone ; then
  1077.     MISSING="${MISSING} ${I}"
  1078.     fi
  1079. done
  1080. if test "${MISSING}" = "" ; then
  1081.     echo You have unpacked all 10 archives.
  1082.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1083. else
  1084.     echo You still need to unpack the following archives:
  1085.     echo "        " ${MISSING}
  1086. fi
  1087. ##  End of shell archive.
  1088. exit 0
  1089.  
  1090. exit 0 # Just in case...
  1091.