home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume17 / parseargs / part02 < prev    next >
Encoding:
Internet Message Format  |  1991-03-18  |  61.3 KB

  1. From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i047:  parseargs - functions to parse command line arguments, Part02/12
  4. Message-ID: <1991Mar17.200602.17757@sparky.IMD.Sterling.COM>
  5. Date: 17 Mar 91 20:06:02 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 2bd96682 5a86dd46 98f7903c bf35aa67
  8.  
  9. Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com>
  10. Posting-number: Volume 17, Issue 47
  11. Archive-name: parseargs/part02
  12.  
  13. This is part 2 of parseargs
  14.  
  15. #!/bin/sh
  16. # this is Part.02 (part 2 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file parseargs/README continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 2; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping parseargs/README'
  34. else
  35. echo 'x - continuing file parseargs/README'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'parseargs/README' &&
  37. X
  38. X The cmd_xxx macros are included only if PARSEARGS_PRIVATE is #defined.
  39. X
  40. X Similarly, there are also some macros (some public, some private) to
  41. X query certain attributes of an argument descriptor (or assist in its
  42. X manipulation). The public macros are documented in the manual pages,
  43. X private ones are listed here:
  44. X
  45. X     ARG_isBOOLEAN(ad) -- is this arg an argBool, or an arg[STU]Bool type?
  46. X     ARG_isPSEUDOARG(ad) -- is this arg an argDummy or an argUsage type?
  47. X     ARG_FIRST(argd) -- return the first argument-entry
  48. X     ARG_LAST(argd) -- return the first last-entry
  49. X     ARG_isEND(ad) -- are we at the end of the argument list?
  50. X     ARG_ADVANCE(ad) -- return the next argument entry.
  51. X     ARG_RETREAT(ad) -- return the previous argument entry.
  52. X
  53. X
  54. X These last five macros are for traversing all the entries in the
  55. X argument descriptor array that correspond to actual command-line
  56. X arguments (i.e. the 2nd thru 2nd-to-last entries in the array):
  57. X
  58. X     for ( ad = ARG_FIRST(argd) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) )  ...
  59. X or
  60. X     for ( ad = ARG_LAST(argd) ; !ARG_isEND(ad) ; ARG_RETREAT(ad) )  ...
  61. X
  62. X
  63. X OPERATING SYSTEM DEPENDENCIES
  64. X =============================
  65. X I also added "-D${os}_style" to the CFLAGS macro used in the Makefile.
  66. X It is used to conditionally include OS dependent code in the parseargs
  67. X files. I tried to keep "#ifdef <os>_style" sections of code to a
  68. X minimum.
  69. X
  70. X I tried to make a distinction between portions of the code that depend
  71. X upon the underlying OS and portions of the code that depend on the
  72. X desired argument parsing style so that - in theory - one could compile
  73. X for any of the existing styles on any of the supported systems. Thus,
  74. X just because "unix_style" is #defined does not necessarily imply that
  75. X the underlying OS is unix. This would only be implied if "unix" was
  76. X #defined.
  77. X
  78. X It is assumed that the following constants are #defined for the
  79. X following operating systems:
  80. X
  81. X        NAME                        OS
  82. X    ------------------   ------------------------
  83. X     unix                Unix (BSD or AT&T)
  84. X     BSD, ucb_universe   BSD Unix (only one need be present)
  85. X     MANX, AZTEC         AmigaDOS
  86. X     MSDOS               MS-DOS for IBM PCs
  87. X     OS2                 OS/2 for IBM PCs
  88. X     vms                 VAX/VMS
  89. X
  90. X As of this writing, as long as the above constants are defined for the
  91. X corresponding OS, parseargs compiles without errors on both BSD and
  92. X AT&T Unix Systems using both ANSI and non-ANSI C Compilers.
  93. X
  94. X
  95. X IBM-PC VERSION OF parseargs(3)
  96. X ==============================
  97. X I also added ibm_args.c for MS-DOS and OS/2.
  98. X
  99. X IBM_ARGS.C HAS NOT BEEN TESTED ON AN IBM-PC! I did not have one to
  100. X test it on.
  101. X
  102. X The ibm-pc version is VERY similar to the unix version. The difference
  103. X is that ibm_args.c will look in $SWITCHAR for the option character(s)
  104. X to use. If the option character is '-', it behaves just like
  105. X unix_args.c, if the option character is something else or $SWITCHAR is
  106. X undefined then it behaves more like normal MS-DOS stuff. The main
  107. X difference is that if the ibm-pc version is NOT emulating unix, than
  108. X all option arguments MUST be in the same argument as the option itself
  109. X and they must be separated by an '=' character (so "/S=str" is fine
  110. X but "/Sstr" and "/S str" are not).
  111. X
  112. X By default, if SWITCHAR is undefined then both the long and short
  113. X option prefix character are '/'. One is able to distinguish an option
  114. X from a long-option in this case because the third character of an
  115. X option-arg will always be '=' or ' '. Hence, using the test program
  116. X with the defaults, both "ibm_test foo /D=directory" and "ibm_test
  117. X /DIR=directory" are equivalent.
  118. X
  119. X
  120. X VAX/VMS VERSION OF parseargs(3)
  121. X ===============================
  122. X I also added vms_args.c for VAX/VMS.
  123. X
  124. X VMS_ARGS.C HAS NOT BEEN TESTED ON A VMS SYSTEM!!! I did not have one
  125. X to test it on. It should accept command-line arguments as described in
  126. X the "Grammar Rules" section of the VAX manual but I  cant guarantee
  127. X anything so you'll have to test it out for yourself.
  128. X
  129. X ARGLIST and ARGVEC are comma-separated lists in the VMS version of
  130. X parseargs (not whitespace separated lists). In order to preserve a
  131. X one-to-one mapping between UNIX & AmigaDOS whitespace separated lists
  132. X with VMS comma-separated lists, a  VMS ARGLIST or ARGVEC that
  133. X corresponds to a positional parameter may use both commas and white-
  134. X space to separate its arguments. This avoids having VMS command lines
  135. X like the following:
  136. X
  137. X     cmdname file1,file2,file3 directory1,directory2
  138. X
  139. X for which there exists no corresponding command-line for UNIX or or
  140. X AmigaDOS programs without changing the standard command-line syntax
  141. X for these systems.
  142. X
  143. X In addition to a help option in the default argument descriptor, The
  144. X VMS version of parseargs(3) also has /OUTPUT, /INPUT, and /ERROR
  145. X qualifiers in the standard default argument-descriptor array. These
  146. X all serve to redirect stdin, stdout, or stderr to or from a file (many
  147. X thanks to posters from comp.os.vms for giving me a clue on how to do
  148. X this). As a result of this, under VAX/VMS, there are two new argtype
  149. X functions "argInput" and "argOutput": each requires that ad->ad_valp
  150. X be a  file pointer (not a pointer to a file pointer as in "__ &stdin"
  151. X but an actual file pointer as in "__ stdin"). ArgInput and argOutput
  152. X close the stream associated with the given file-pointer and reconnect
  153. X the stream to the named file for input or output (so the effect is to
  154. X redirect input (output) from (to) the stream to the named file. If
  155. X redirection fails, the original stream remains closed (sorry -- its a
  156. X side-effect of freopen()).
  157. X
  158. X One can implement a "negatable" vms qualifier by using two entries in
  159. X the argument descriptor table as follows:
  160. X
  161. X     'F', ARGOPT, argSBool, __ &myflag, "FLAG {set flag}",
  162. X     'f', ARGOPT, argUBool, __ &myflag, "NOFLAG {unset flag}",
  163. X
  164. X so that /FLAG will turn the flag on (via argBool or argSBool) and
  165. X /NOFLAG will turn it off (via argUBool).
  166. X
  167. X I did not know what to do (if anything) to add the VAX/VMS shell (DCL)
  168. X into the parseargs command-line interface (parseargs(1)) so it is not
  169. X currently implemented. I  will leave the task of configuring
  170. X parseargs(1) for DCL programmers to some other brave soul who knows
  171. X more than I about DCL! I was thinking that for DCL, the parseargs
  172. X command could directly set the value of a symbol (with the proper
  173. X scope of course) at execution time instead of printing something on
  174. X stdout that would be evaluated later (as the UNIX version does).
  175. X
  176. X Anyone who uses VAX/VMS is strongly encouraged to test vms_args.c on
  177. X their system (and make changes if need be) and to modify the usage and
  178. X parsing functions accordingly!!! It would probably be a good idea to
  179. X use some builtin VMS system call to replace the method used for
  180. X finding the basename of a file (basename() in strfuncs.c) when "#ifdef
  181. X vms" is true. There are also some command-line parsing routines
  182. X available through DCL that could replace a  lot of the guts of
  183. X vms_args.c as well.
  184. X
  185. X
  186. X LITERATE PROGRAMMING
  187. X ====================
  188. X If you look at the source code you will notice that it contains lots
  189. X of funny looking comments with sections that have titles enclosed
  190. X between '^' and ':' characters. This is my own feeble attempt at
  191. X literate programming. I  have a Unix-shell script which will extract
  192. X certain portions of these "structured" comments so that I  may dump
  193. X them directly into the documentation (and thus attempt to keep the
  194. X documentation up-to-date at the same rate as the source). If anyone
  195. X is interested in my script(s) please let me know and I will gladly e-
  196. X mail them to the interested parties.
  197. X
  198. X
  199. X ACKNOWLEDGEMENTS
  200. X ================
  201. X I was in constant contact with Peter Da Silva during the entire period
  202. X that I  implemented all of the above modifications and would like to
  203. X thank him for his time and his sage advice.
  204. X
  205. X Thanx also to Jim Barbour for helping me with some VMS specific things
  206. X (like getting the original, unparsed command-line from DCL and
  207. X retreiving the value of a symbol), and to Tom Christiansen and Raymond
  208. X Chen for their help in getting parseargs(1) to work for perl scripts.
  209. X
  210. X Lastly, thanks to all those who use and will continue to improve
  211. X parseargs, all I ask is that you keep me updated of your efforts (so I
  212. X can keep my own version of parseargs up-to-date). I am always eager
  213. X to discuss possible changes or enhancements with any interested
  214. X parties.
  215. X
  216. SHAR_EOF
  217. echo 'File parseargs/README is complete' &&
  218. chmod 0664 parseargs/README ||
  219. echo 'restore of parseargs/README failed'
  220. Wc_c="`wc -c < 'parseargs/README'`"
  221. test 41278 -eq "$Wc_c" ||
  222.     echo 'parseargs/README: original size 41278, current size' "$Wc_c"
  223. rm -f _shar_wnt_.tmp
  224. fi
  225. # ============= parseargs/amiga_args.c ==============
  226. if test -f 'parseargs/amiga_args.c' -a X"$1" != X"-c"; then
  227.     echo 'x - skipping parseargs/amiga_args.c (File already exists)'
  228.     rm -f _shar_wnt_.tmp
  229. else
  230. > _shar_wnt_.tmp
  231. echo 'x - extracting parseargs/amiga_args.c (Text)'
  232. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/amiga_args.c' &&
  233. /*************************************************************************
  234. ** ^FILE: amiga_args.c - parse AmigaDOS argument vectors
  235. **
  236. ** ^DESCRIPTION:
  237. **    This file contains the routines used to parse AmigaDOS argument
  238. **    vectors and to print AmigaDOS usage messages.
  239. **
  240. ** ^HISTORY:
  241. **    01/02/91     Brad Appleton     <brad@ssd.csd.harris.com>
  242. **    - Added structured block comments
  243. **    - Added optional arguments to keywords
  244. **
  245. **    --/--/--  Peter da Silva  <peter@ferranti.com>    Created
  246. ***^^**********************************************************************/
  247. X
  248. #include <ctype.h>
  249. #include <useful.h>
  250. #include "strfuncs.h"
  251. #include "pgopen.h"
  252. X
  253. #define PARSEARGS_PRIVATE   /* include private definitions */
  254. #include "parseargs.h"
  255. X
  256. EXTERN  VOID  syserr       ARGS((const char *, ...));
  257. EXTERN  VOID  usrerr       ARGS((const char *, ...));
  258. EXTERN  char *getenv       ARGS((const char *));
  259. EXTERN  VOID  get_winsize  ARGS((int, int *, int *));
  260. X
  261. VERSIONID("$Header: parseargs.c,v 2.1 89/12/30 20:59:48 eric Exp $");
  262. X
  263. /***************************************************************************
  264. ** ^GLOBAL-VARIABLE: Usage_Requested
  265. **
  266. ** ^VISIBILITY:
  267. **    static-global (visible to all functions in this file).
  268. **
  269. ** ^DESCRIPTION:
  270. **    Indicates whether a usage message was requested by the user
  271. **    (as opposed to triggerred by a syntax error).  If the message
  272. **    is requested by the user then it is always printed in verbose
  273. **    mode and does not return an error-status-code.
  274. ***^^**********************************************************************/
  275. static  BOOL  Usage_Requested = FALSE;
  276. X
  277. X
  278. /***************************************************************************
  279. ** ^FUNCTION: amiga_parse - parse Amiga_DOS arg-vectors
  280. **
  281. ** ^SYNOPSIS:
  282. */
  283. #ifndef __ANSI_C__
  284. X   int amiga_parse( argv, argd )
  285. /*
  286. ** ^PARAMETERS:
  287. */
  288. X   char *argv[];
  289. /*    -- the vector of string arguments from the command-line
  290. */
  291. X   ARGDESC argd[];
  292. /*    -- the programmer description of the command and its args
  293. */
  294. #endif  /* !__ANSI_C__ */
  295. X
  296. /* ^DESCRIPTION:
  297. **    Amiga_parse will parse the arguments in the given vector of strings,
  298. **    assign the corresponding values to the command-line arguments specified
  299. **    in argd, and check the syntax of the command-line.
  300. **
  301. ** ^REQUIREMENTS:
  302. **    The final element in argv must be a NULL pointer.
  303. **
  304. ** ^SIDE-EFECTS:
  305. **    argd is modified according to the command-line description and parameters
  306. **
  307. ** ^RETURN-VALUE:
  308. **    pe_SUCCESS (0) if no errors are encountered
  309. **    pe_SYSTEM (-1) if a system error is encountered
  310. **    pe_SYNTAX if a syntax error is encountered
  311. **
  312. ** ^ALGORITHM:
  313. **    - for each command-line argument
  314. **       - attempt to match the argument as a keyword
  315. **       - if it is a keyword argument
  316. **          - record and convert its value (if any)
  317. **         else it is a positional parameter
  318. **          - record and convert its value (if any)
  319. **         else there are too many arguments
  320. **          - return pe_SYNTAX
  321. **         end-if
  322. **       end-for
  323. ***^^**********************************************************************/
  324. #ifdef __ANSI_C__
  325. X   int amiga_parse( char **argv, ARGDESC argd[] )
  326. #endif
  327. {
  328. X   register ARGDESC *cmd, *args, *ad = ARGDESCNULL;
  329. X   register char **av;
  330. X   register char *p = CHARNULL;
  331. X   argName_t   keyword;
  332. X   argMask_t   flags;
  333. X   int  parse_error = pe_SUCCESS;
  334. X   BOOL is_match = FALSE;
  335. X
  336. X   if ( !argd )  return  parse_error;
  337. X
  338. X      /* initialize command-structure */
  339. X   if ( !CMD_isINIT(argd) )  init_args( argd );
  340. X   cmd = argd;
  341. X   cmd_prev(cmd) = ARGDESCNULL;
  342. X
  343. X      /* run through the argument vector */
  344. X   for ( av = argv ; *av ; av++ ) {
  345. X      char c = '\0';
  346. X
  347. X         /* If looking for keywords, see if this is one */
  348. X      if( !BTEST(cmd_state(cmd), ps_NOFLAGS) ) {
  349. X         p = strpbrk(*av, s_ARG_SEP);
  350. X         if ( p ) {
  351. X            c = *p;
  352. X            *p++ = '\0';  /* skip past arg-separator character */
  353. X         }
  354. X
  355. X         is_match = FALSE;
  356. X         for ( args = argd ; args  &&  !is_match ; args = cmd_defargs(args) ) {
  357. X            for (ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad)) {
  358. X               if (arg_type(ad) == argDummy)  continue;
  359. X
  360. X               if (!ARG_isPOSONLY(ad)  &&  match(*av, arg_sname(ad)) == 0) {
  361. X                  is_match = TRUE;
  362. X                  break;
  363. X               }/*if*/
  364. X            }
  365. X         }
  366. X
  367. X         if ( !is_match )  ad = ARGDESCNULL;
  368. X      }/*if !NOFLAGS*/
  369. X
  370. X      if (c)  *(p-1) = c;  /* restore the equal sign */
  371. X
  372. X         /* If we have a keyword here */
  373. X      if( !BTEST(cmd_state(cmd), ps_NOFLAGS)  &&  ad) {
  374. X         if ( cmd_prev(cmd) ) { /* a value may have been given but wasnt */
  375. X            if ( ARG_isVALOPTIONAL(cmd_prev(cmd)) ) {
  376. X               BSET( arg_flags(cmd_prev(cmd)), ARGGIVEN );
  377. X            }
  378. X            else {  /* value was required */
  379. X               (VOID)get_keyword( arg_sname(cmd_prev(cmd)), keyword );
  380. X               usrerr( "value required for %s keyword", keyword );
  381. X               parse_error = pe_SYNTAX;
  382. X            }
  383. X            cmd_prev(cmd) = ARGDESCNULL;
  384. X         }
  385. X
  386. X         if ( cmd_list(cmd) ) { /* end of list */
  387. X            cmd_list(cmd) = ARGDESCNULL;
  388. X         }
  389. X
  390. X         flags = arg_flags(ad);    /* save flags */
  391. X         if ( ARG_isGIVEN(ad) )    /* reset flags for this appearance */
  392. X            BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP );
  393. X
  394. X         if ( p ) { /* matched NAME=VALUE */
  395. X            if ( ARG_isMULTIVAL(ad) )
  396. X               cmd_list(cmd) = ad;
  397. X            else
  398. X               cmd_list(cmd) = ARGDESCNULL;
  399. X
  400. X               /* try to convert the type */
  401. X            if ( !HANDLE(ad, p, cmd_flags(cmd)) ) {
  402. X               arg_flags(ad) = flags;  /* restore flags */
  403. X               parse_error = pe_SYNTAX;
  404. X            }
  405. X            else
  406. X               BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  407. X            ad = ARGDESCNULL;
  408. X         }
  409. X         else {
  410. X            if (arg_type(ad) == argUsage) {
  411. X               Usage_Requested = TRUE;
  412. X               usage(argd);
  413. X               exit(1);
  414. X            }
  415. X            else if (arg_type(ad) == argEnd) {
  416. X               BSET( cmd_state(cmd), ps_NOFLAGS );
  417. X               BSET( arg_flags(ad), ARGGIVEN );
  418. X            }
  419. X            else if ( ARG_isVALTAKEN(ad) ) {
  420. X               cmd_prev(cmd) = ad;
  421. X            }
  422. X            else if ( !HANDLE(ad, CHARNULL, cmd_flags(cmd)) ) {
  423. X               arg_flags(ad) = flags;  /* restore flags */
  424. X               parse_error = pe_SYNTAX;
  425. X            }
  426. X            else {
  427. X               BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  428. X            }
  429. X            ad = ARGDESCNULL;
  430. X         }/*else*/
  431. X      }
  432. X      else if (cmd_prev(cmd)) {
  433. X         flags = arg_flags(cmd_prev(cmd));    /* save flags */
  434. X         if ( ARG_isGIVEN(cmd_prev(cmd)) )    /* reset flags */
  435. X            BCLEAR( arg_flags(cmd_prev(cmd)), ARGVALGIVEN | ARGVALSEP );
  436. X
  437. X            /* previous value may have required a keyword */
  438. X         BSET( arg_flags(cmd_prev(cmd)), ARGVALSEP );
  439. X
  440. X         if ( ARG_isMULTIVAL(cmd_prev(cmd)) )
  441. X            cmd_list(cmd) = cmd_prev(cmd);
  442. X         else
  443. X            cmd_list(cmd) = ARGDESCNULL;
  444. X
  445. X            /* try to convert the type */
  446. X         if ( !HANDLE(cmd_prev(cmd), *av, cmd_flags(cmd)) ) {
  447. X            arg_flags(cmd_prev(cmd)) = flags;  /* restore flags */
  448. X            parse_error = pe_SYNTAX;
  449. X         }
  450. X         else
  451. X            BSET( arg_flags(cmd_prev(cmd)), ARGGIVEN | ARGVALGIVEN );
  452. X
  453. X         ad = ARGDESCNULL;
  454. X         cmd_prev(cmd) = ARGDESCNULL;
  455. X         continue;
  456. X      }
  457. X      else {  /* it's a positional argument or a list item */
  458. X         if (cmd_list(cmd)) { /* its a list item */
  459. X            flags = arg_flags(cmd_list(cmd));    /* save flags */
  460. X            if ( ARG_isGIVEN(cmd_list(cmd)) )    /* reset flags */
  461. X               BCLEAR( arg_flags(cmd_list(cmd)), ARGVALGIVEN | ARGVALSEP );
  462. X
  463. X            BSET( arg_flags(cmd_list(cmd)), ARGVALSEP );
  464. X
  465. X            if ( !HANDLE(cmd_list(cmd), *av, cmd_flags(cmd)) ) {
  466. X               arg_flags(cmd_list(cmd)) = flags;  /* restore flags */
  467. X               parse_error = pe_SYNTAX;
  468. X            }
  469. X
  470. X            BSET( arg_flags(cmd_list(cmd)), ARGGIVEN | ARGVALGIVEN );
  471. X            continue;
  472. X         }
  473. X         else {  /* its a positional argument */
  474. X            if ( BTEST(cmd_flags(cmd), pa_FLAGS1ST) )
  475. X               BSET( cmd_state(cmd), ps_NOFLAGS );
  476. X
  477. X            is_match = FALSE;
  478. X            for ( args = argd; args && !is_match; args = cmd_defargs(args) ) {
  479. X               for (ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad)) {
  480. X                  if (arg_type(ad) == argDummy)  continue;
  481. X
  482. X                  if ( ARG_isPOSITIONAL(ad)  &&
  483. X                       (!ARG_isGIVEN(ad) || ARG_isMULTIVAL(ad)) ) {
  484. X                     is_match = TRUE;
  485. X                     break;
  486. X                  }/*if*/
  487. X               }
  488. X            }
  489. X
  490. X            if ( !is_match ) {
  491. X               usrerr("too any arguments");
  492. X               parse_error = pe_SYNTAX;
  493. X               ad = ARGDESCNULL;
  494. X            }
  495. X            else {
  496. X               flags = arg_flags(ad);    /* save flags */
  497. X               if ( ARG_isGIVEN(ad) )    /* reset flags for this appearance */
  498. X                  BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP );
  499. X
  500. X               BSET( arg_flags(ad), ARGVALSEP );
  501. X
  502. X                  /* try to convert */
  503. X               if ( !HANDLE(ad, *av, cmd_flags(cmd)) ) {
  504. X                  arg_flags(ad) = flags;  /* restore flags */
  505. X                  parse_error = pe_SYNTAX;
  506. X               }
  507. X               else
  508. X                  BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  509. X               ad = ARGDESCNULL;
  510. X            }
  511. X         }/*else positional*/
  512. X      }/*else not keyword*/
  513. X   }/*while*/
  514. X
  515. X   /* If last argument was a keyword and required an option
  516. X   ** then complain about it
  517. X   */
  518. X   if ( cmd_prev(cmd) ) { /* a value may have been given but wasnt */
  519. X      if ( ARG_isVALOPTIONAL(cmd_prev(cmd)) ) {
  520. X         BSET( arg_flags(cmd_prev(cmd)), ARGGIVEN );
  521. X      }
  522. X      else {  /* value was required */
  523. X         (VOID)get_keyword( arg_sname(cmd_prev(cmd)), keyword );
  524. X         usrerr( "value required for %s keyword", keyword );
  525. X         parse_error = pe_SYNTAX;
  526. X      }
  527. X      cmd_prev(cmd) = ARGDESCNULL;
  528. X   }
  529. X
  530. X   return  parse_error;
  531. }
  532. X
  533. X
  534. /***************************************************************************
  535. ** ^FUNCTION: fmtarg - format command-argument syntax
  536. **
  537. ** ^SYNOPSIS:
  538. */
  539. #ifndef __ANSI_C__
  540. X   static int fmtarg(ad, buf)
  541. /*  
  542. ** ^PARAMETERS:
  543. */
  544. X   ARGDESC *ad;
  545. /*    -- pointer to the argument to format
  546. */
  547. X   char *buf;
  548. /*    -- character buffer to hold the formatted result
  549. */
  550. #endif  /* !__ANSI_C__ */
  551. X
  552. /* ^DESCRIPTION:
  553. **    Fmtarg will determine the proper command-line syntax for the
  554. **    given argument and write the result to the given buffer.
  555. **
  556. ** ^REQUIREMENTS:
  557. **    buf must be large enough to hold the formatted result (100 characters
  558. **    should do the trick).
  559. **
  560. ** ^SIDE-EFECTS:
  561. **    buf is overwritten.
  562. **
  563. ** ^RETURN-VALUE:
  564. **    The number of printable characters in the argument-syntax-string
  565. **
  566. ** ^ALGORITHM:
  567. **    Print argument usage based on whether or not the argument is
  568. **    positional, hidden, multi-valued (list or vector), etc ....
  569. **    Optional arguments and values are enclosed in square braces.
  570. ***^^**********************************************************************/
  571. #ifdef __ANSI_C__
  572. X   static int fmtarg( const ARGDESC *ad, char *buf )
  573. #endif
  574. {
  575. X      /* buf must already be large enough */
  576. X   char * pos;
  577. X   argName_t  keyword, name;
  578. X
  579. X   (VOID) get_name(arg_sname(ad), name);
  580. X
  581. X   if ( ARG_isPOSITIONAL(ad) ) {
  582. X      sprintf( buf, "<%s>", name );
  583. X   }
  584. X   else {
  585. X      (VOID) get_keyword(arg_sname(ad), keyword);
  586. X      (VOID) strcpy( buf, keyword );
  587. X      pos = buf + strlen(buf);
  588. X
  589. X      if ( ARG_isVALTAKEN(ad) && !ARG_isBOOLEAN(ad) && !ARG_isPSEUDOARG(ad) ) {
  590. X         if ( ARG_isVALOPTIONAL(ad) )
  591. X            sprintf( pos, " [<%s>]", name );
  592. X         else
  593. X            sprintf( pos, " <%s>", name );
  594. X      }
  595. X   }/*else*/
  596. X
  597. X   return  strlen(buf);
  598. }
  599. X
  600. X
  601. /***************************************************************************
  602. ** ^FUNCTION: amiga_usage - print a usage message
  603. **
  604. ** ^SYNOPSIS:
  605. */
  606. #ifndef __ANSI_C__
  607. X   VOID amiga_usage( argd, usage_flags )
  608. /*  
  609. ** ^PARAMETERS:
  610. */
  611. X   ARGDESC *argd;
  612. /*    -- the command-descriptor array
  613. */
  614. X   argMask_t usage_flags;
  615. /*    -- flags set by $USAGECNTL
  616. */
  617. #endif  /* !__ANSI_C__ */
  618. X
  619. /* ^DESCRIPTION:
  620. **    Amiga_usage will print the AmigaDOS command-line usage of the given
  621. **    command on standard diagnostic output (stderr). The content of the
  622. **    usage message is controlled by the bitmasks in usage_flags which
  623. **    correspond to the settings in the user's USAGECNTL variable.
  624. **
  625. ** ^REQUIREMENTS:
  626. **    argd should be a non-null command-line argument-descriptor array
  627. **
  628. ** ^SIDE-EFECTS:
  629. **    Prints on stderr.
  630. **
  631. ** ^RETURN-VALUE:
  632. **    None.
  633. **
  634. ** ^ALGORITHM:
  635. **    - if no usage is desired then exit
  636. **    - if paging is requested print to the pager instead of stderr
  637. **    - print the command-line syntax
  638. **    - if the description is requested print it
  639. **    - if verbose mode is requested, print the description of each argument
  640. ***^^**********************************************************************/
  641. #ifdef __ANSI_C__
  642. X   void amiga_usage( const ARGDESC *argd, argMask_t usage_flags )
  643. #endif
  644. {
  645. X   register CONST ARGDESC  *ad, *args, *cmd;
  646. X   int  max_cols = 80, max_lines  = 24;
  647. X   int  margin, ll, pl, keywords, longest, positionals;
  648. X   BOOL first = TRUE;
  649. X   FILE *fp;
  650. X
  651. X   if ( !argd )  return;
  652. X
  653. X      /* initialize command-structure */
  654. X   if ( !CMD_isINIT(argd) )  init_args( (ARGDESC *)argd );
  655. X   cmd = argd;
  656. X
  657. X      /* force verbose-mode if requested */
  658. X   if ( Usage_Requested )   BSET( usage_flags, usg_VERBOSE );
  659. X
  660. X   if ( BTEST(usage_flags, usg_NONE) )  return;
  661. X
  662. X   fp = ( BTEST(usage_flags, usg_PAGED) )
  663. X      ? pgopen( stderr, getenv("USAGE_PAGER") )
  664. X      : stderr;
  665. X
  666. X      /* get screen size */
  667. X   get_winsize( fileno(stderr), &max_lines, &max_cols );
  668. X
  669. X   fprintf(fp, "Format: %s", ProgName);
  670. X   ll = strlen( ProgName ) + 8;
  671. X   margin = ll + 1;
  672. X   longest = 0;
  673. X
  674. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  675. X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
  676. X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  677. X            argName_t  buf;
  678. X
  679. X               /* don't display hidden arguments */
  680. X            if ( ARG_isHIDDEN(ad) )  continue;
  681. X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  682. X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  683. X
  684. X               /* figure out how wide this parameter is (for printing) */
  685. X            pl = fmtarg(ad, buf);
  686. X
  687. X            if ( pl > longest)  longest = pl;
  688. X
  689. X            if ( !ARG_isREQUIRED(ad) ) {
  690. X               pl += 2;  /* [] */
  691. X            }
  692. X            if ( ARG_isMULTIVAL(ad) ) {
  693. X               strcat( buf, "..." );
  694. X               pl += 3;
  695. X            }
  696. X
  697. X               /* see if this will fit */
  698. X            if ( (ll + pl + 1) > (max_cols - first) ) {
  699. X                  /* no... start a new line */
  700. X               fprintf(fp, "\n%*s", margin, "");
  701. X               ll = margin;
  702. X            }
  703. X            else {
  704. X                  /* yes... just throw in a space */
  705. X               fputc(' ', fp);
  706. X               ++ll;
  707. X            }
  708. X            ll += pl;
  709. X
  710. X               /* show the argument */
  711. X            if ( !ARG_isREQUIRED(ad) )  fputc('[', fp);
  712. X            fprintf(fp, buf);
  713. X            if ( !ARG_isREQUIRED(ad) )  fputc(']', fp);
  714. X
  715. X            first = FALSE;  /* not first line anymore */
  716. X         }/*for each ad */
  717. X      }/* for each argd */
  718. X   }/* for each parm-type */
  719. X
  720. X   fputc('\n', fp);
  721. X
  722. X   if ( BTEST(usage_flags, usg_DESCRIPTION) ) {
  723. X      CONST char *description = cmd_description(cmd);
  724. X
  725. X      if ( description  &&  *description ) {
  726. X         fprintf( fp, "Description:\n" );
  727. X         indent_para(fp, max_cols, 8, "", 0, description);
  728. X         fputc( '\n', fp );
  729. X      }
  730. X   }/*if*/
  731. X
  732. X   if ( !BTEST(usage_flags, usg_VERBOSE) )  {
  733. X      if ( pgactive(fp) )  (VOID) pgclose( fp );
  734. X      return;
  735. X   }
  736. X
  737. X   keywords = 0;
  738. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  739. X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
  740. X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  741. X            argName_t  buf;
  742. X
  743. X               /* don't display hidden arguments */
  744. X            if ( ARG_isHIDDEN(ad) )  continue;
  745. X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  746. X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  747. X
  748. X            if( !(keywords++) )  fprintf(fp, "Keywords/Arguments:\n");
  749. X            (VOID) fmtarg(ad, buf);
  750. X            indent_para(fp, max_cols, 8, buf, longest+2, arg_description(ad));
  751. X         }/*for each ad */
  752. X      }/* for each argd */
  753. X   }/* for each parm-type */
  754. X
  755. X   if ( pgactive(fp) )  (VOID) pgclose( fp );
  756. }
  757. SHAR_EOF
  758. chmod 0664 parseargs/amiga_args.c ||
  759. echo 'restore of parseargs/amiga_args.c failed'
  760. Wc_c="`wc -c < 'parseargs/amiga_args.c'`"
  761. test 16890 -eq "$Wc_c" ||
  762.     echo 'parseargs/amiga_args.c: original size 16890, current size' "$Wc_c"
  763. rm -f _shar_wnt_.tmp
  764. fi
  765. # ============= parseargs/arglist.c ==============
  766. if test -f 'parseargs/arglist.c' -a X"$1" != X"-c"; then
  767.     echo 'x - skipping parseargs/arglist.c (File already exists)'
  768.     rm -f _shar_wnt_.tmp
  769. else
  770. > _shar_wnt_.tmp
  771. echo 'x - extracting parseargs/arglist.c (Text)'
  772. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/arglist.c' &&
  773. /*************************************************************************
  774. ** ^FILE: arglist.c - argList manipulation routines.
  775. **
  776. ** ^DESCRIPTION:
  777. **    This file contains routines to add an item to the end of an arglist,
  778. **    and to delete all items in an arglist.
  779. **
  780. ** ^HISTORY:
  781. **    01/02/91    Brad Appleton    <brad@ssd.csd.harris.com>
  782. **       - Added structured comments
  783. **       - Changed arglists to always be kept in FIFO order (hence
  784. **         reverse_list() and cleanup_list() were no longer needed).
  785. **         The lists are maintained in FIFO order by forcing the very
  786. **         first item of the list to maintain an additional link to the
  787. **         last item of the list (to make it easy to append an item).
  788. **       - Added listFree() function
  789. **
  790. **    --/--/--    Peter da Silva    <peter@ferranti.com>    Created
  791. ***^^**********************************************************************/
  792. X
  793. #include <stdio.h>
  794. #include <ctype.h>
  795. #include <useful.h>
  796. #include "strfuncs.h"
  797. X
  798. #define  PARSEARGS_NARGTYPES  /* exclude arg-type externs */
  799. #include "parseargs.h"
  800. X
  801. EXTERN  VOID    syserr  ARGS((const char *, ...));
  802. EXTERN  VOID    usrerr  ARGS((const char *, ...));
  803. X
  804. /***************************************************************************
  805. ** ^FUNCTION: listStr - string-list argument translation routine
  806. **
  807. ** ^SYNOPSIS:
  808. */
  809. #ifndef __ANSI_C__
  810. X   BOOL listStr( ad, vp, copyf )
  811. /*  
  812. ** ^PARAMETERS:
  813. */
  814. X   ARGDESC *ad;
  815. /*    -- the argument descriptor for this parameter.
  816. */
  817. X   char *vp;
  818. /*    -- a pointer to the string input value.
  819. */
  820. X   BOOL copyf;
  821. /*    -- if TRUE, the value will be destroyed later, and so should
  822. **       be copied if it will be retained (as for a string).
  823. */
  824. #endif  /* !__ANSI_C__ */
  825. X
  826. /* ^DESCRIPTION:
  827. **    ListStr converts a string-parameter value into its internal form,
  828. **    including validity checking. If <copyf> is TRUE then <vp> is copied
  829. **    to the end of the list, otherwise <vp> itself is placed at the end.
  830. **
  831. ** ^REQUIREMENTS:
  832. **    <ad> must point to the argdesc element corresponding to the matched
  833. **    string-list argument. The ad_valp field of ad MUST be either NULL or
  834. **    point to a valid arglist-head structure.
  835. **
  836. ** ^SIDE-EFECTS:
  837. **    If successful, arglist pointed to by arg_valp(ad) is appended with
  838. **    the given string, <vp> is unchanged.
  839. **
  840. ** ^RETURN-VALUE:
  841. **    TRUE -- if the conversion was successful.  The actual
  842. **            value should be added appended to the list.
  843. **    FALSE -- if the conversion failed.  The reason for failure
  844. **             should be diagnosed using usrerr().
  845. **
  846. ** ^ALGORITHM:
  847. **    - verify the validity of <vp> as a string argument
  848. **    - if ( isEmpty(arglist) )
  849. **       - allocate a listhead structure
  850. **       - assign the item pointer to <vp> (or a copy of <vp>)
  851. **       - assign the NEXT and LAST elements to NULL
  852. **    - else
  853. **       - allocate a new arglist structure and append it after
  854. **         listhead.LAST
  855. **       - assign listhead.LAST to the address of the new item
  856. **       - assign the NEXT element of the new item to NULL
  857. **      end-if
  858. ***^^**********************************************************************/
  859. #ifdef __ANSI_C__
  860. X   BOOL listStr( ARGDESC *ad, char *vp, BOOL copyf )
  861. #endif
  862. {
  863. X   char *cp;
  864. X   BOOL  badalloc = FALSE;
  865. X   argName_t   argname;
  866. X   ArgListHead *nl;
  867. X   ArgList *nd;
  868. X
  869. X   (VOID) get_name( arg_sname(ad), argname );
  870. X   if (copyf) {
  871. X      register int i;
  872. X
  873. X      i = strlen(vp) + 1;
  874. X      cp = (char *) malloc(i * sizeof(char));
  875. X      if(!cp) {
  876. X         usrerr("out of memory saving string %s", argname );
  877. X         return FALSE;
  878. X      }
  879. X      memcpy(cp, vp, i);
  880. X   }
  881. X   else {
  882. X      cp = vp;
  883. X   }
  884. X
  885. X      /* if list is empty - need to new up a listhead,
  886. X      ** otherwise just use a normal link.
  887. X      */
  888. X   nl = *((ArgListHead **) arg_valp(ad));
  889. X   if ( nl ) {
  890. X      nd = (ArgList *) malloc( sizeof(ArgList) );
  891. X      if ( !nd )  badalloc = TRUE;
  892. X   }
  893. X   else {
  894. X      nl = (ArgListHead *) malloc( sizeof(ArgListHead) );
  895. X      nd = (ArgList *)NULL;
  896. X      if ( !nl )  badalloc = TRUE;
  897. X   }
  898. X
  899. X   if ( badalloc ) {
  900. X      usrerr("out of memory saving arg %s", arg_sname(ad));
  901. X      if(copyf) free(cp);
  902. X      return FALSE;
  903. X   }
  904. X
  905. X   if ( nd ) {
  906. X      nl -> nl_tail -> nl_next = (ArgList *)nd;
  907. X      nl -> nl_tail  = (ArgList *)nd;
  908. X      nd -> nl_next  = (ArgList *)NULL;
  909. X      nd -> nl_val   = (ARBPTR)cp;
  910. X      nd -> nl_flags = arg_flags(ad);
  911. X      if ( copyf )  BSET( nd->nl_flags, ARGCOPYF );
  912. X   }
  913. X   else {
  914. X      *((ArgListHead **) arg_valp(ad)) = nl;
  915. X      nl -> nl_tail  = (ArgList *)nl;
  916. X      nl -> nl_next  = (ArgList *)NULL;
  917. X      nl -> nl_val   = (ARBPTR)cp;
  918. X      nl -> nl_flags = arg_flags(ad);
  919. X      if ( copyf )  BSET( nl->nl_flags, ARGCOPYF );
  920. X   }
  921. X
  922. X   return (TRUE);
  923. }
  924. X
  925. X
  926. /***************************************************************************
  927. ** ^FUNCTION: listFree - free the items in an arglist
  928. **
  929. ** ^SYNOPSIS:
  930. */
  931. #ifndef __ANSI_C__
  932. X   VOID listFree( argls )
  933. /*  
  934. ** ^PARAMETERS:
  935. */
  936. X   ArgList *argls;
  937. /*    -- the list to be freed
  938. */
  939. #endif  /* !__ANSI_C__ */
  940. X
  941. /* ^DESCRIPTION:
  942. **    ListFree will free storage for each node in <argls>. Furthermore,
  943. **    if <copyf> is true then the actual storage for each item in the
  944. **    list is also released.
  945. **
  946. ** ^REQUIREMENTS:
  947. **    argls must point to a valid arglist-head structure.
  948. **
  949. ** ^SIDE-EFECTS:
  950. **    each item in argls is removed, argls itself should be set to NULL
  951. **    after this routine is invoked.
  952. **
  953. ** ^RETURN-VALUE:
  954. **    None.
  955. **
  956. ** ^ALGORITHM:
  957. **    - For each node in argls
  958. **       - if ( copyf ) free the item storage
  959. **       - free the node
  960. **      end-for
  961. ***^^**********************************************************************/
  962. #ifdef __ANSI_C__
  963. X   void listFree( ArgList *argls )
  964. #endif
  965. {
  966. X   register  ArgList *ls = argls;
  967. X   ArgList  *nd;
  968. X
  969. X   if ( !ls )  return;
  970. X
  971. X   while ( ls ) {
  972. X      nd = L_NEXT(ls);
  973. X      if ( BTEST(L_FLAGS(ls), ARGCOPYF) )  free( ls->nl_val );
  974. X      free( ls );
  975. X      ls = nd;
  976. X   }/*while*/
  977. }
  978. X
  979. SHAR_EOF
  980. chmod 0664 parseargs/arglist.c ||
  981. echo 'restore of parseargs/arglist.c failed'
  982. Wc_c="`wc -c < 'parseargs/arglist.c'`"
  983. test 5961 -eq "$Wc_c" ||
  984.     echo 'parseargs/arglist.c: original size 5961, current size' "$Wc_c"
  985. rm -f _shar_wnt_.tmp
  986. fi
  987. # ============= parseargs/argtype.c ==============
  988. if test -f 'parseargs/argtype.c' -a X"$1" != X"-c"; then
  989.     echo 'x - skipping parseargs/argtype.c (File already exists)'
  990.     rm -f _shar_wnt_.tmp
  991. else
  992. > _shar_wnt_.tmp
  993. echo 'x - extracting parseargs/argtype.c (Text)'
  994. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/argtype.c' &&
  995. /*************************************************************************
  996. ** ^FILE: argtype.c - argument type definitions for parseargs(3)
  997. **
  998. ** ^DESCRIPTION:
  999. **    This file implements the argument conversion functions for
  1000. **    converting string, character, integer, floating-point,
  1001. **    boolean, and pseudo-arguments, from command-line strings.
  1002. **
  1003. ** ^HISTORY:
  1004. **    01/03/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1005. **       - Added structured block comments
  1006. **       - Added argUsage & argDummy dummy-functions
  1007. **       - Added argSBool, argTBool, and argUBool
  1008. **       - Added ARGVEC handling to all necessary functions
  1009. **       - Added argInput & argOutput for VMS
  1010. **       - put floating-point routines (argFloat & argDouble) into
  1011. **         this file (they may be excluded by #defining NOFLOAT)
  1012. **       - changed routines to return negative values (where appropriate)
  1013. **
  1014. **    --/--/--    Peter da Silva    <peter@ferranti.com>
  1015. **
  1016. **    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  1017. ***^^**********************************************************************/
  1018. X
  1019. #include <ctype.h>
  1020. #include <useful.h>
  1021. #include "strfuncs.h"
  1022. X
  1023. #define PARSEARGS_NARGTYPES  /* exclude arg-type externs */
  1024. #include "parseargs.h"
  1025. X
  1026. #ifdef __ANSI_C__
  1027. # define  PARMS(ad,vp,copyf) \
  1028. X    ( register ARGDESC *ad,  register char *vp,  BOOL copyf )
  1029. #else
  1030. # define  PARMS(ad,vp,copyf) \
  1031. X    ( ad, vp, copyf )  register ARGDESC *ad;  register char *vp;  BOOL copyf;
  1032. #endif
  1033. X
  1034. #define REALLOC(ptr,size)  (( ! ptr ) ? malloc(size) : realloc(ptr, size) )
  1035. EXTERN  VOID    syserr  ARGS((const char *, ...));
  1036. EXTERN  VOID    usrerr  ARGS((const char *, ...));
  1037. EXTERN  long    strtol  ARGS((char *, char **, int));
  1038. EXTERN  double  strtod  ARGS((const char *, char **));
  1039. X
  1040. X
  1041. /***************************************************************************
  1042. ** ^FUNCTION: argtype -- argument translation routines.
  1043. **
  1044. ** ^SYNOPSIS:
  1045. **    BOOL  argUsage( ad, vp, copyf )
  1046. **    BOOL  argEnd( ad, vp, copyf );
  1047. **    BOOL  argDummy( ad, vp, copyf );
  1048. **    BOOL  argBool( ad, vp, copyf );
  1049. **    BOOL  argSBool( ad, vp, copyf );
  1050. **    BOOL  argUBool( ad, vp, copyf );
  1051. **    BOOL  argTBool( ad, vp, copyf );
  1052. **    BOOL  argChar( ad, vp, copyf );
  1053. **    BOOL  argStr( ad, vp, copyf );
  1054. **    BOOL  argInt( ad, vp, copyf );
  1055. **    BOOL  argShort( ad, vp, copyf );
  1056. **    BOOL  argLong( ad, vp, copyf );
  1057. **    BOOL  argFloat( ad, vp, copyf );
  1058. **    BOOL  argDouble( ad, vp, copyf );
  1059. **    BOOL  argInput( ad, vp, copyf );
  1060. **    BOOL  argOutput( ad, vp, copyf );
  1061. **
  1062. ** ^PARAMETERS:
  1063. **    ARGDESC *ad;
  1064. **    -- the argument descriptor for this parameter.
  1065. **
  1066. **    char *vp;
  1067. **    -- a pointer to the string input value.
  1068. **
  1069. **    BOOL  copyf;
  1070. **    -- if TRUE, the value will be destroyed later, and so should be copied
  1071. **       if it will be retained (as for a string).
  1072. **
  1073. ** ^DESCRIPTION:
  1074. **    Each of these converts a parameter value to the internal form, includ-
  1075. **    ing validity checking.  Their parameters and return values all behave
  1076. **    similarly. One of these routines are called when an argunent of that
  1077. **    particular type is matched by one of the argument parsing function in
  1078. **    parseargs(3). When such an argument is matched, its argument transla-
  1079. **    tion routines is invoked and is passed (1) the address of the argument
  1080. **    descriptor for the matched argument, (2) the possible argument string
  1081. **    for that matched argument, and (3) a boolean filed that is TRUE only
  1082. **    if the second parameter points to temporary storage (indicating that
  1083. **    some copying may need to be done instead of just pointing to the same
  1084. **    object).
  1085. **
  1086. **    Once the argument translation routine is invoked, it is responsible
  1087. **    for converting the argument string to the desired internal form
  1088. **    (perhaps a number), and assigning the resultant value to the
  1089. **    arg_valp(ad) field of the argument descriptor (this includes handling
  1090. **    any necessary (re)allocation if the matched argument has the ARGVEC
  1091. **    flag enabled). If the argument is an ARGVEC or ARGLIST then the rou-
  1092. **    tine is responsible for allocating any space, copying the arg-flags to
  1093. **    the value-specific flags, and setting the ARGCOPYF flag for the value
  1094. **    if it needs to be allocated as well.
  1095. **
  1096. ** ^REQUIREMENTS:
  1097. **    ARGKEYWORD should be set if the argument was matched via its
  1098. **    string name (as opposed to by its character name).
  1099. **
  1100. **    ARGVALSEP should be set is the argument value was in a separate
  1101. **    argv element from the argument string-name (or character name).
  1102. **
  1103. ** ^SIDE-EFFECTS:
  1104. **    The value used should be stored in the location indicated by arg_valp(ad).
  1105. **
  1106. ** ^RETURN-VALUE:
  1107. **    TRUE : if the conversion was successful and the entire value was used.
  1108. **
  1109. **    FALSE : if the conversion failed.  The reason for failure should be
  1110. **            diagnosed using usrerr().
  1111. **
  1112. **    -N : if the conversion was successful but only N characters of the value
  1113. **         were used, the remaining characters may still match other arguments.
  1114. ** 
  1115. ** ^ALGORITHM:
  1116. **    Function-specific, but the basic idea is as follows:
  1117. **
  1118. **    - convert the value-string into the desired type
  1119. **    - if the value is invalid call usrerr and return FALSE
  1120. **      end-if
  1121. **    - if this ad is an ARGVEC
  1122. **        - expand the vector and insert the new item at the end
  1123. **        - update the item count
  1124. **    - else 
  1125. **        - set *ad_valp to the converted value
  1126. **      end-if
  1127. **    - return TRUE if we used the whole arg, -N if we only used N-characters
  1128. ***^^**********************************************************************/
  1129. X
  1130. /* vector types and defines */
  1131. #define BLOCKSIZE  5    /* number of items to allocate at once */
  1132. #define VEC_SIZE(vec,el_typ)  ( sizeof(el_typ *) * (BLOCKSIZE + vec->count) )
  1133. typedef ARGVEC_T(char *)  strvec_t;
  1134. typedef ARGVEC_T(char)    charvec_t;
  1135. typedef ARGVEC_T(int)     intvec_t;
  1136. typedef ARGVEC_T(short)   shortvec_t;
  1137. typedef ARGVEC_T(long)    longvec_t;
  1138. typedef ARGVEC_T(float)   floatvec_t;
  1139. typedef ARGVEC_T(double)  doublevec_t;
  1140. X
  1141. X
  1142. /***************************************************************************
  1143. ** ^SECTION: PSEUDO-TYPES -- argUsage, argEnd, argDummy
  1144. **    ArgUsage is used to specify an argument that causes the command
  1145. **    usage to be printed.
  1146. **
  1147. **    ArgDummy is used to force an item to show up in usage-messages but
  1148. **    the item itself is never matched against any argumenmts from the
  1149. **    command-line.
  1150. **
  1151. **    ArgEnd is used by amiga_args.c and vms_args.c to indicate an argument
  1152. **    that forces all remaining arguments to be considered positional args.
  1153. **
  1154. **    These three are dummy functions. The routines themselves do nothing
  1155. **    of importance, we just need to have their addresses available for
  1156. **    identification in the corresponding <os>_args.c file.
  1157. ***^^**********************************************************************/
  1158. X
  1159. /*ARGSUSED*/
  1160. BOOL argDummy  PARMS(ad, vp, copyf)
  1161. {
  1162. X   return   FALSE;
  1163. }
  1164. X
  1165. X
  1166. /*ARGSUSED*/
  1167. BOOL argEnd  PARMS(ad, vp, copyf)
  1168. {
  1169. X   return (FALSE);
  1170. }
  1171. X
  1172. X
  1173. /*ARGSUSED*/
  1174. BOOL argUsage  PARMS(ad, vp, copyf)
  1175. {
  1176. X   return   FALSE;
  1177. }
  1178. X
  1179. X
  1180. /***************************************************************************
  1181. ** ^SECTION: STRING-TYPES -- argStr
  1182. **    ArgStr is one of the few argument translation routines that actually
  1183. **    uses the <copyf> flag. If <copyf> is true then the string is duplicated.
  1184. **
  1185. **    ArgStr assigns the given string (or a copy of it) to the value referenced
  1186. **    by arg_valp(unless the argument is a vector in which case the given string
  1187. **    is appended to the end).
  1188. **
  1189. **    ArgStr ensures that the very last item in a vector of strings (the one
  1190. **    accessed as vec.array[ vec.count ]) will always be NULL.
  1191. ***^^**********************************************************************/
  1192. X
  1193. /*ARGSUSED*/
  1194. BOOL argStr  PARMS(ad, vp, copyf)
  1195. {
  1196. X   char *cp;
  1197. X   argName_t  argname;
  1198. X
  1199. X   (VOID) get_name( arg_sname(ad), argname );
  1200. X   if (copyf) {
  1201. X      register int i;
  1202. X
  1203. X      i = strlen(vp) + 1;
  1204. X      cp = (char *) malloc(i * sizeof(char));
  1205. X      if (!cp) {
  1206. X         usrerr("out of memory parsing %s", argname);
  1207. X         return FALSE;
  1208. X      }
  1209. X      memcpy(cp, vp, i);
  1210. X   }
  1211. X   else
  1212. X      cp = vp;
  1213. X
  1214. X   if ( ARG_isVEC(ad) ) {
  1215. X      strvec_t  *vec = (strvec_t *)arg_valp(ad);
  1216. X
  1217. X      if ( (vec->count % BLOCKSIZE) == 0 ) {
  1218. X         vec->array = (char **) REALLOC(vec->array, 1+VEC_SIZE(vec, char *));
  1219. X         if ( !vec->array ) {
  1220. X            if ( copyf )  free(cp);
  1221. X            syserr("out of memory saving arg %s", argname);
  1222. X         }
  1223. X         vec->flags = (argMask_t *) REALLOC(vec->flags, VEC_SIZE(vec, argMask_t));
  1224. X         if ( !vec->flags ) {
  1225. X            syserr("out of memory saving arg %s", argname);
  1226. X         }
  1227. X      }
  1228. X
  1229. X      vec->flags[ vec->count ] = arg_flags(ad);
  1230. X      if ( copyf )  BSET( vec->flags[vec->count], ARGCOPYF );
  1231. X      vec->array[ (vec->count)++ ] = cp;
  1232. X      vec->array[ vec->count ] = (char *)NULL;
  1233. X   }
  1234. X   else
  1235. X      *(char **) arg_valp(ad) = cp;
  1236. X
  1237. X   return (TRUE);
  1238. }
  1239. X
  1240. X
  1241. /***************************************************************************
  1242. ** ^SECTION: CHARACTER-TYPES -- argChar
  1243. **    ArgChar assigns the given character to the value referenced by ad_valp
  1244. **    (unless the argument is a vector in which case the given character
  1245. **    is appended to the end).
  1246. **
  1247. **    If an argChar argument is matched as a single character option, then
  1248. **    the immediately following character will be considered its argument
  1249. **    (but the characters after it may still be processed as option-letters).
  1250. **
  1251. **    ArgChar ensures that the very last item in a vector of character (the
  1252. **    one accessed as vec.array[ vec.count ]) will always be a NUL byte so
  1253. **    that the resulting vector may also be used as a NULL terminated string.
  1254. **
  1255. **    Unlike argStr, argChar will translate character escape sequences such
  1256. **    as '\n' and '\012'.
  1257. ***^^**********************************************************************/
  1258. X
  1259. /*ARGSUSED*/
  1260. BOOL argChar  PARMS(ad, vp, copyf)
  1261. {
  1262. X   auto char *vpp;
  1263. X   argName_t  argname;
  1264. X   int status = FALSE;
  1265. X   char c;
  1266. X
  1267. X   (VOID) get_name( arg_sname(ad), argname );
  1268. X   if (!vp || !*vp) {
  1269. X      status = FALSE;
  1270. X   }
  1271. X   if (strlen(vp) == 2 && vp[0]=='^') {
  1272. X      c = vp[1] ^ '@';
  1273. X      status = TRUE;
  1274. X   }
  1275. X   else if (strlen(vp) > 1 && vp[0]=='\\') {
  1276. X      c = (int) strtol(&vp[1], &vpp, 8);
  1277. X      if (*vpp == '\0')
  1278. X         status = TRUE;
  1279. X   }
  1280. X   else if (strlen(vp) == 1) {
  1281. X      c = *vp;
  1282. X      status = TRUE;
  1283. X   }
  1284. X   else if ( !BTEST(arg_flags(ad), ARGVALSEP | ARGKEYWORD) ) {
  1285. X      c = *vp;
  1286. X      status = TRUE;
  1287. X   }
  1288. X
  1289. X   if ( status ) {
  1290. X      if ( ARG_isVEC(ad) ) {
  1291. X         charvec_t  *vec = (charvec_t *)arg_valp(ad);
  1292. X
  1293. X         if ( (vec->count % BLOCKSIZE) == 0 ) {
  1294. X            vec->array = (char *) REALLOC(vec->array, 1+VEC_SIZE(vec, char));
  1295. X            if (!vec->array)  syserr("out of memory saving arg %s", argname);
  1296. X         }
  1297. X         vec->flags = (argMask_t *) REALLOC(vec->flags, VEC_SIZE(vec, argMask_t));
  1298. X         if ( !vec->flags ) {
  1299. X            syserr("out of memory saving arg %s", argname);
  1300. X         }
  1301. X
  1302. X         vec->flags[ vec->count ] = arg_flags(ad);
  1303. X         vec->array[ (vec->count)++ ] = c;
  1304. X         vec->array[ vec->count ] = '\0';
  1305. X      }
  1306. X      else
  1307. X         *(char *) arg_valp(ad) = c;
  1308. X   }
  1309. X   else {
  1310. X      usrerr("invalid character argument '%s' for %s",
  1311. X         vp, argname);
  1312. X   }
  1313. X   return (status) ? (BOOL) -1 : FALSE;
  1314. }
  1315. X
  1316. X
  1317. /***************************************************************************
  1318. ** ^SECTION: INTEGER-TYPES -- argInt, argShort, argLong
  1319. **    Each of these functions converts the given string to the desired
  1320. **    integral type. The value may be specified as an octal number by
  1321. **    specifying the first digit to be 0. Similarly, If the first two 
  1322. **    characters are '0x' then the number is treated as hexadecimal.
  1323. ***^^**********************************************************************/
  1324. X
  1325. X   /*
  1326. X   ** macro to define an integral argtype function
  1327. X   **
  1328. X   ** NOTE : do NOT use a terminating semicolon when invoking this macro!
  1329. X   */
  1330. #define  INTEGRAL_ARGTYPE(name,num_t,ls_t) \
  1331. BOOL name  PARMS(ad, vp, copyf) \
  1332. { \
  1333. X   auto char *vpp; \
  1334. X   argName_t  argname; \
  1335. X   num_t  value; \
  1336. X \
  1337. X   (VOID) get_name( arg_sname(ad), argname ); \
  1338. X   value = (num_t) strtol(vp, &vpp, 0); \
  1339. X   if (*vpp != '\0') { \
  1340. X      usrerr("invalid integer argument '%s' for %s", vp, argname); \
  1341. X      return (FALSE); \
  1342. X   } \
  1343. X   else { \
  1344. X      if ( ARG_isVEC(ad) ) { \
  1345. X         ls_t  *vec = (ls_t *)arg_valp(ad); \
  1346. X \
  1347. X         if ( (vec->count % BLOCKSIZE) == 0 ) { \
  1348. X            vec->array = (num_t *) REALLOC(vec->array, VEC_SIZE(vec, num_t)); \
  1349. X            if ( !vec->array ) \
  1350. X               syserr("out of memory saving arg %s", argname); \
  1351. X \
  1352. X            vec->flags = (argMask_t *) REALLOC(vec->flags, VEC_SIZE(vec, argMask_t)); \
  1353. X            if ( !vec->flags ) \
  1354. X               syserr("out of memory saving arg %s", argname); \
  1355. X         } \
  1356. X \
  1357. X         vec->flags[ vec->count ] = arg_flags(ad); \
  1358. X         vec->array[ (vec->count)++ ] = value; \
  1359. X      } \
  1360. X      else \
  1361. X         *(num_t *) arg_valp(ad) = value; \
  1362. X \
  1363. X      return (TRUE); \
  1364. X   } \
  1365. }
  1366. X
  1367. X
  1368. /* define argInt() */
  1369. INTEGRAL_ARGTYPE( argInt, int, intvec_t )
  1370. X
  1371. /* define argShort() */
  1372. INTEGRAL_ARGTYPE( argShort, short, shortvec_t )
  1373. X
  1374. /* define argLong() */
  1375. INTEGRAL_ARGTYPE( argLong, long, longvec_t )
  1376. X
  1377. X
  1378. #ifndef NOFLOAT
  1379. X
  1380. /***************************************************************************
  1381. ** ^SECTION: FLOATING-POINT-TYPES -- argFloat, argDouble
  1382. **    Each of these functions converts the given string to the desired
  1383. **    floating-point type.
  1384. ***^^**********************************************************************/
  1385. X
  1386. X   /*
  1387. X   ** macro to define a decimal argtype function
  1388. X   **
  1389. X   ** NOTE : do NOT use a terminating semicolon when invoking this macro!
  1390. X   */
  1391. #define  DECIMAL_ARGTYPE(name,dec_t,ls_t) \
  1392. BOOL name  PARMS(ad, vp, copyf) \
  1393. { \
  1394. X   auto char *vpp; \
  1395. X   argName_t  argname; \
  1396. X   dec_t  value; \
  1397. X \
  1398. X   (VOID) get_name( arg_sname(ad), argname ); \
  1399. X   value = (dec_t) strtod(vp, &vpp); \
  1400. X   if (*vpp != '\0') { \
  1401. X      usrerr("invalid decimal argument '%s' for %s", vp, argname); \
  1402. X      return (FALSE); \
  1403. X   } \
  1404. X   else { \
  1405. X      if ( ARG_isVEC(ad) ) { \
  1406. X         ls_t  *vec = (ls_t *)arg_valp(ad); \
  1407. X \
  1408. X         if ( (vec->count % BLOCKSIZE) == 0 ) { \
  1409. X            vec->array = (dec_t *) REALLOC(vec->array, VEC_SIZE(vec, dec_t)); \
  1410. X            if (!vec->array) \
  1411. X               syserr("out of memory saving arg %s", argname); \
  1412. X \
  1413. X            vec->flags = (argMask_t *) REALLOC(vec->flags, VEC_SIZE(vec, argMask_t)); \
  1414. X            if (!vec->flags) \
  1415. X               syserr("out of memory saving arg %s", argname); \
  1416. X         } \
  1417. X \
  1418. X         vec->flags[ vec->count ] = arg_flags(ad); \
  1419. X         vec->array[ (vec->count)++ ] = value; \
  1420. X      } \
  1421. X      else \
  1422. X         *(dec_t *) arg_valp(ad) = value; \
  1423. X \
  1424. X      return (TRUE); \
  1425. X   } \
  1426. }
  1427. X
  1428. /* define argFloat */
  1429. DECIMAL_ARGTYPE( argFloat, float, floatvec_t )
  1430. X
  1431. /* define argLong */
  1432. DECIMAL_ARGTYPE( argDouble, double, doublevec_t )
  1433. X
  1434. #endif  /* NOFLOAT */
  1435. X
  1436. X
  1437. /*************************************************************************
  1438. ** ^SECTION: BOOLEAN-TYPES -- argBool, argSBool, argUBool, argTBool
  1439. **    ArgBool and argSBool set a boolean value (if no value is given).
  1440. **    ArgUBool unsets a boolean value (if no value is given). ArgTBool
  1441. **    toggles a boolean value (if no value is given). If a value is
  1442. **    supplied to any of these routines, then the string is looked up
  1443. **    in a table and assigned the corresponding value.
  1444. **
  1445. **    If a value is supplied for an argument that was matched via its
  1446. **    single character name and is part of the same argv element as the
  1447. **    argument-name (so that both ARGKEYWORD and ARGVALSEP are not set),
  1448. **    then only the first character of the value is used (unless it is
  1449. **    not found in our table, in which case the value is ignored and the
  1450. **    default action is taken).
  1451. **
  1452. **    The only possible arguments for single-character options are the
  1453. **    following:
  1454. **
  1455. **       1, +         set the flag
  1456. **       0, -         unset the flag
  1457. **       ^, ~         toggle the flag
  1458. **
  1459. **    The possible argument strings for long-options (keywords) are as
  1460. **    follows (case-insensitive):
  1461. */
  1462. X
  1463. X   /* define a structure for an item in our boolean-lookup table */
  1464. struct booltab {
  1465. X   char   *bname;      /* string to match against */
  1466. X   char   bneedmatch;  /* number of characters that must match */
  1467. X   BOOL   bval;        /* value to use */
  1468. };
  1469. X
  1470. X   /* define the boolean-lookup table */
  1471. STATIC struct booltab    _BoolTab[] = {
  1472. X   "1",      1,   TRUE,
  1473. X   "0",      1,   FALSE,
  1474. X   "+",      1,   TRUE,
  1475. X   "-",      1,   FALSE,
  1476. X   "yes",    1,   TRUE,
  1477. X   "no",     1,   FALSE,
  1478. X   "true",   1,   TRUE,
  1479. X   "false",  1,   FALSE,
  1480. X   "on",     2,   TRUE,
  1481. X   "off",    3,   FALSE,
  1482. X   CHARNULL
  1483. };
  1484. X
  1485. /**^^**********************************************************************/
  1486. X
  1487. X
  1488. X   /*
  1489. X   ** NOTE: Lists and vectors of Boolean types are not supported!!!
  1490. X   **       (same goes for argEnd, argInput, & argOutput)
  1491. X   */
  1492. X
  1493. /*ARGSUSED*/
  1494. BOOL argBool  PARMS(ad, vp, copyf)
  1495. {
  1496. X   register struct booltab *b;
  1497. X   register char *cp;
  1498. X   argName_t  argname;
  1499. X   int len;
  1500. X
  1501. X   (VOID) get_name( arg_sname(ad), argname );
  1502. X
  1503. X   /* ARGVECs are not supported for this Boolean arg-types */
  1504. X   if ( ARG_isVEC(ad) )
  1505. X      syserr( "Error in '%s' arg-entry! Boolean argvecs are not supported!",
  1506. X            argname );
  1507. X
  1508. X   /* if vp is NULL, just set to TRUE
  1509. X   **    (needed for backward compatibility)
  1510. X   */
  1511. X   if ( !vp || !*vp ) {
  1512. X      *(BOOL *) arg_valp(ad) = TRUE;
  1513. X      return (TRUE);
  1514. X   }
  1515. X
  1516. X      /* allow single character arguments for non-keywords */
  1517. X   if ( !BTEST(arg_flags(ad), ARGKEYWORD | ARGVALSEP) ) {
  1518. X      if ( *vp == '+' || *vp == '1' ) {
  1519. X         *(BOOL *) arg_valp(ad) = TRUE;
  1520. X         return (BOOL) -1;
  1521. X      }
  1522. X      if ( *vp == '-' || *vp == '0' ) {
  1523. X         *(BOOL *) arg_valp(ad) = FALSE;
  1524. X         return (BOOL) -1;
  1525. X      }
  1526. X      if ( *vp == '~' || *vp == '^' ) {
  1527. X         *(BOOL *) arg_valp(ad) = (*(BOOL *) arg_valp(ad)) ? FALSE : TRUE;
  1528. X         return (BOOL) -1;
  1529. X      }
  1530. X
  1531. X         /* unmatched value, return FALSE for non-argBool (so the caller
  1532. X         ** can use whatever default) and return TRUE for argBool.
  1533. X         */
  1534. X      if ( arg_type(ad) == argBool ) {
  1535. X         *(BOOL *) arg_valp(ad) = TRUE;
  1536. X         return  TRUE;
  1537. X      }
  1538. X      return  FALSE;
  1539. X   }/* if single char option */
  1540. X
  1541. X   /* copy input & convert to lower case */
  1542. X   cp = strlwr( strdup(vp) );
  1543. X   len = strlen( cp );
  1544. X
  1545. X   /* search for a match in the table */
  1546. X   for (b = _BoolTab; b->bname ; b++) {
  1547. X      /* if too short, don't even bother trying */
  1548. X      if (len < b->bneedmatch)
  1549. X         continue;
  1550. X
  1551. X      if ( memcmp(cp, b->bname, len) == 0) {
  1552. X         /* got a match */
  1553. X         *(BOOL *) arg_valp(ad) = b->bval;
  1554. X         free( cp );
  1555. X         return (TRUE);
  1556. X      }
  1557. X   }/*if match*/
  1558. X
  1559. X   free( cp );
  1560. X   usrerr("invalid Boolean argument '%s' for %s", vp, argname);
  1561. X   return (FALSE);
  1562. }
  1563. X
  1564. X
  1565. /*ARGSUSED*/
  1566. BOOL argSBool  PARMS(ad, vp, copyf)
  1567. {
  1568. X   argName_t  argname;
  1569. X   BOOL  retval;
  1570. X
  1571. X   (VOID) get_name( arg_sname(ad), argname );
  1572. X
  1573. X   /* ARGVECs are not supported for this Boolean arg-types */
  1574. X   if ( ARG_isVEC(ad) )
  1575. X      syserr( "Error in '%s' arg-entry! Boolean argvecs are not supported!",
  1576. X            argname );
  1577. X
  1578. X   /* if vp is NULL, just set to TRUE */
  1579. X   if ( !vp || !*vp || !(retval = argBool(ad, vp, copyf)) ) {
  1580. X      *(BOOL *) arg_valp(ad) = TRUE;
  1581. X      return (TRUE);
  1582. X   }
  1583. X   else
  1584. X      return  retval;
  1585. }
  1586. X
  1587. /*ARGSUSED*/
  1588. BOOL argUBool  PARMS(ad, vp, copyf)
  1589. {
  1590. X   argName_t  argname;
  1591. X   BOOL  retval;
  1592. X
  1593. X   (VOID) get_name( arg_sname(ad), argname );
  1594. X
  1595. X   /* ARGVECs are not supported for this Boolean arg-types */
  1596. X   if ( ARG_isVEC(ad) )
  1597. X      syserr( "Error in '%s' arg-entry! Boolean argvecs are not supported!",
  1598. X            argname );
  1599. X
  1600. X   /* if vp is NULL, just set to FALSE */
  1601. X   if ( !vp || !*vp || !(retval = argBool(ad, vp, copyf)) ) {
  1602. X      *(BOOL *) arg_valp(ad) = FALSE;
  1603. X      return (TRUE);
  1604. X   }
  1605. X   else
  1606. X      return retval;
  1607. }
  1608. X
  1609. /*ARGSUSED*/
  1610. BOOL argTBool  PARMS(ad, vp, copyf)
  1611. {
  1612. X   argName_t  argname;
  1613. X   BOOL  retval;
  1614. X
  1615. X   (VOID) get_name( arg_sname(ad), argname );
  1616. X
  1617. X   /* ARGVECs are not supported for this Boolean arg-types */
  1618. X   if ( ARG_isVEC(ad) )
  1619. X      syserr( "Error in '%s' arg-entry! Boolean argvecs are not supported!",
  1620. X            argname );
  1621. X
  1622. X   /* if vp is NULL, just toggle value */
  1623. X   if ( !vp || !*vp || !(retval = argBool(ad, vp, copyf)) ) {
  1624. X      *(BOOL *) arg_valp(ad) = (*(BOOL *) arg_valp(ad)) ? FALSE : TRUE ;
  1625. X      return (TRUE);
  1626. X   }
  1627. X   else
  1628. X      return retval;
  1629. }
  1630. X
  1631. X
  1632. #ifdef vms_style
  1633. X
  1634. /***************************************************************************
  1635. ** ^SECTION: I/O-REDIRECTION-TYPES -- argInput, argOutput
  1636. **    ArgInput attempts to redirect the file-pointer addressed by ad_valp
  1637. **    to the file named by the given value. The file is opened for reading.
  1638. **
  1639. **    ArgOutput attempts to redirect the file-pointer addressed by ad_valp
  1640. **    to the file named by the given value. The file is opened for writing.
  1641. **
  1642. **    In either case, ad_valp should be of type (FILE *) (and not a pointer
  1643. **    to a file pointer as in (FILE **)!!!
  1644. **
  1645. **    If the given files cannot be opened, then an error message is printed
  1646. **    and the associated input/output streams are closed.
  1647. ***^^**********************************************************************/
  1648. X
  1649. /*ARGSUSED*/
  1650. BOOL argInput  PARMS(ad, vp, copyf)
  1651. {
  1652. X      /* note that ad_valp is a file pointer
  1653. X      ** (so dont use &fp in the arg-desc)
  1654. X      */
  1655. X   FILE *fp = (FILE *)arg_valp(ad);
  1656. X   BOOL error = FALSE;
  1657. X
  1658. X   /* redirect file pointer to read from file */
  1659. X   if ( !vp ) {
  1660. X      usrerr( "Error: no file name given" );
  1661. X      error = TRUE;
  1662. X   }
  1663. X
  1664. X   if ( !error  &&  !fp )
  1665. X      error = TRUE;
  1666. X   else if ( !error  &&  !freopen(vp, "r", fp) )
  1667. X      error = TRUE;
  1668. X
  1669. X   if ( error )  {
  1670. X      usrerr( "Error: unable to redirect input to file \"%s.\"", vp );
  1671. X      return  (FALSE);
  1672. X   }
  1673. X   return (TRUE);
  1674. }
  1675. X
  1676. X
  1677. /*ARGSUSED*/
  1678. BOOL argOutput  PARMS(ad, vp, copyf)
  1679. {
  1680. X      /* note that ad_valp is a file pointer
  1681. X      ** (so dont use &fp in the arg-desc)
  1682. X      */
  1683. X   FILE *fp = (FILE *)arg_valp(ad);
  1684. X   BOOL error = FALSE;
  1685. X
  1686. X   /* redirect file pointer to write to file */
  1687. X   if ( !vp ) {
  1688. X      usrerr( "Error: no file name given" );
  1689. X      error = TRUE;
  1690. X   }
  1691. X
  1692. X   if ( !error  &&  !fp )
  1693. X      error = TRUE;
  1694. X   else if ( !error  &&  !freopen(vp, "a", fp) )
  1695. X      error = TRUE;
  1696. X
  1697. X   if ( error )  {
  1698. X      usrerr( "Error: unable to redirect output to file \"%s.\"", vp );
  1699. X      return  (FALSE);
  1700. X   }
  1701. X   return (TRUE);
  1702. }
  1703. X
  1704. #endif  /* vms_style */
  1705. SHAR_EOF
  1706. chmod 0664 parseargs/argtype.c ||
  1707. echo 'restore of parseargs/argtype.c failed'
  1708. Wc_c="`wc -c < 'parseargs/argtype.c'`"
  1709. test 22590 -eq "$Wc_c" ||
  1710.     echo 'parseargs/argtype.c: original size 22590, current size' "$Wc_c"
  1711. rm -f _shar_wnt_.tmp
  1712. fi
  1713. # ============= parseargs/argtype3.txt ==============
  1714. if test -f 'parseargs/argtype3.txt' -a X"$1" != X"-c"; then
  1715.     echo 'x - skipping parseargs/argtype3.txt (File already exists)'
  1716.     rm -f _shar_wnt_.tmp
  1717. else
  1718. > _shar_wnt_.tmp
  1719. echo 'x - extracting parseargs/argtype3.txt (Text)'
  1720. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/argtype3.txt' &&
  1721. X
  1722. X
  1723. X
  1724. ARGTYPE(3)                           ARGTYPE(3)
  1725. X
  1726. X
  1727. X
  1728. NAME
  1729. X     argtype - argument    type functions used by parseargs(3)
  1730. X
  1731. SYNOPSIS
  1732. X     #include <parseargs.h>
  1733. X
  1734. X     BOOL  argUsage(  argdesc,    argstr,     copyf    );
  1735. X     BOOL  argEnd(  argdesc,  argstr,  copyf  );
  1736. X     BOOL  argDummy(  argdesc,    argstr,     copyf    );
  1737. X     BOOL  argBool(  argdesc,  argstr,    copyf  );
  1738. X     BOOL  argSBool(  argdesc,    argstr,     copyf    );
  1739. X     BOOL  argUBool(  argdesc,    argstr,     copyf    );
  1740. X     BOOL  argTBool(  argdesc,    argstr,     copyf    );
  1741. X     BOOL  argChar(  argdesc,  argstr,    copyf  );
  1742. X     BOOL  argStr(  argdesc,  argstr,  copyf  );
  1743. X     BOOL  argInt(  argdesc,  argstr,  copyf  );
  1744. X     BOOL  argShort(  argdesc,    argstr,     copyf    );
  1745. X     BOOL  argLong(  argdesc,  argstr,    copyf  );
  1746. X     BOOL  argFloat(  argdesc,    argstr,     copyf    );
  1747. X     BOOL  argDouble(  argdesc,     argstr,  copyf     );
  1748. X     BOOL  listStr(  argdesc,  argstr,    copyf  );
  1749. X     void  listFree(  arglist  );
  1750. X     void  vecFree(  argvec, type  );
  1751. X     void  vecDeepFree(     argvec, type  );
  1752. X
  1753. X     ARGDESC  *argdesc;
  1754. X     char  *argstr;
  1755. X     BOOL  copyf;
  1756. X     ArgList  *arglist;
  1757. X
  1758. DESCRIPTION
  1759. X     Each of these converts a parameter    value to the internal
  1760. X     form, including validity checking.     Their parameters and
  1761. X     return values all behave similarly. One of    these routines
  1762. X     are called    when an    argunent of that particular type is
  1763. X     matched by    one of the argument parsing function in    par-
  1764. X     seargs(3).    When such an argument is matched, its argument
  1765. X     translation routines is invoked and is passed (1) the
  1766. X     address of    the argument descriptor    for the    matched    argument,
  1767. X     (2) the possible argument string for that matched argument,
  1768. X     and (3) a boolean filed that is TRUE only if the second
  1769. X     parameter points to temporary storage (indicating that some
  1770. X     copying may need to be done instead of just pointing to the
  1771. X     same object).
  1772. X
  1773. X     Once the argument translation routine is invoked, it is
  1774. X     responsible for converting    the argument string to the
  1775. X     desired internal form (perhaps a number), and assigning the
  1776. X     resultant value to    the arg_valp(ad) field of the argument
  1777. X     descriptor    (this includes handling    any necessary
  1778. X     (re)allocation if the matched argument has    the ARGVEC flag
  1779. X     enabled). If the argument is an ARGVEC or ARGLIST then the
  1780. X
  1781. X
  1782. X
  1783. Page 1
  1784. X
  1785. X
  1786. X
  1787. X
  1788. X
  1789. X
  1790. ARGTYPE(3)                           ARGTYPE(3)
  1791. X
  1792. X
  1793. X
  1794. X     routine is    responsible for    allocating any space, copying the
  1795. X     arg-flags to the value-specific flags, and    setting    the
  1796. X     ARGCOPYF flag for the value if it needs to    be allocated as
  1797. X     well.
  1798. X
  1799. X
  1800. RETURN VALUE
  1801. X     TRUE    The conversion was    successful and the entire value
  1802. X         was used.
  1803. X
  1804. X
  1805. X     FALSE   The conversion failed.  The reason    for failure
  1806. X         should be diagnosed using usrerr(3).
  1807. X
  1808. X
  1809. X     -N         The conversion was    successful but only N characters
  1810. X         of    the value were used, the remaining characters may
  1811. X         still match other arguments.
  1812. X
  1813. X
  1814. PSEUDO-TYPES
  1815. X     ArgUsage is used to specify an argument that causes the com-
  1816. X     mand usage    to be printed.
  1817. X
  1818. X     ArgDummy is used to force an item to show up in usage-
  1819. X     messages but the item itself is never matched against any
  1820. X     argumenmts    from the command-line.
  1821. X
  1822. X     ArgEnd is used by Amiga style command-lines to indicate an
  1823. X     argument that forces all remaining    arguments to be    con-
  1824. X     sidered positional    args.
  1825. X
  1826. X     These three are dummy functions. The routines themselves do
  1827. X     nothing of    importance, we just need to have their addresses
  1828. X     available for identification in the corresponding command-
  1829. X     line styles.
  1830. X
  1831. STRING-TYPES
  1832. X     ArgStr is one of the few argument translation routines that
  1833. X     actually uses the copyf flag. If copyf is true then the
  1834. X     string is duplicated.
  1835. X
  1836. X     ArgStr assigns the    given string (or a copy    of it) to the
  1837. X     value referenced by arg_valp(ad) (unless the argument is a
  1838. X     vector in which case the given string is appended to the
  1839. SHAR_EOF
  1840. true || echo 'restore of parseargs/argtype3.txt failed'
  1841. fi
  1842. echo 'End of  part 2'
  1843. echo 'File parseargs/argtype3.txt is continued in part 3'
  1844. echo 3 > _shar_seq_.tmp
  1845. exit 0
  1846. exit 0 # Just in case...
  1847. -- 
  1848. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1849. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1850. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1851. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1852.