home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume29 / parseargs / part08 / parseargs.h
Encoding:
C/C++ Source or Header  |  1992-05-19  |  43.2 KB  |  1,037 lines

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