home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume29 / parseargs / part05 / argtype.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-19  |  22.3 KB  |  727 lines

  1. /*************************************************************************
  2. ** ^FILE: argtype.c - argument type definitions for parseargs(3)
  3. **
  4. ** ^DESCRIPTION:
  5. **    This file implements the argument conversion functions for
  6. **    converting string, character, integer, floating-point,
  7. **    boolean, and pseudo-arguments, from command-line strings.
  8. **
  9. ** ^HISTORY:
  10. **    01/03/91    Brad Appleton    <brad@ssd.csd.harris.com>
  11. **       - Added structured block comments
  12. **       - Added argUsage & argDummy dummy-functions
  13. **       - Added argSBool, argTBool, and argUBool
  14. **       - Added ARGVEC handling to all necessary functions
  15. **       - Added argInput & argOutput for VMS
  16. **       - put floating-point routines (argFloat & argDouble) into
  17. **         this file (they may be excluded by #defining NOFLOAT)
  18. **       - changed routines to return negative values (where appropriate)
  19. **
  20. **    --/--/--    Peter da Silva    <peter@ferranti.com>
  21. **
  22. **    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  23. ***^^**********************************************************************/
  24.  
  25. #include <ctype.h>
  26. #include <useful.h>
  27. #include "strfuncs.h"
  28.  
  29. #define PARSEARGS_NARGTYPES  /* exclude arg-type externs */
  30. #include "parseargs.h"
  31.  
  32. #ifdef __ANSI_C__
  33. # define  PARMS(ad,vp,copyf) \
  34.     ( register ARGDESC *ad,  register char *vp,  BOOL copyf )
  35. #else
  36. # define  PARMS(ad,vp,copyf) \
  37.     ( ad, vp, copyf )  register ARGDESC *ad;  register char *vp;  BOOL copyf;
  38. #endif
  39.  
  40. #define REALLOC(ptr,size)  (( ! ptr ) ? malloc(size) : realloc(ptr, size) )
  41. EXTERN  VOID    syserr  ARGS((const char *, ...));
  42. EXTERN  VOID    usrerr  ARGS((const char *, ...));
  43.  
  44. #ifndef __ANSI_C__
  45.    EXTERN  long    strtol  ARGS((char *, char **, int));
  46.    EXTERN  double  strtod  ARGS((const char *, char **));
  47. #endif
  48.  
  49. /***************************************************************************
  50. ** ^FUNCTION: argtype -- argument translation routines.
  51. **
  52. ** ^SYNOPSIS:
  53. **    BOOL  argUsage( ad, vp, copyf )
  54. **    BOOL  argEnd( ad, vp, copyf );
  55. **    BOOL  argDummy( ad, vp, copyf );
  56. **    BOOL  argBool( ad, vp, copyf );
  57. **    BOOL  argSBool( ad, vp, copyf );
  58. **    BOOL  argUBool( ad, vp, copyf );
  59. **    BOOL  argTBool( ad, vp, copyf );
  60. **    BOOL  argChar( ad, vp, copyf );
  61. **    BOOL  argStr( ad, vp, copyf );
  62. **    BOOL  argInt( ad, vp, copyf );
  63. **    BOOL  argShort( ad, vp, copyf );
  64. **    BOOL  argLong( ad, vp, copyf );
  65. **    BOOL  argFloat( ad, vp, copyf );
  66. **    BOOL  argDouble( ad, vp, copyf );
  67. **    BOOL  argInput( ad, vp, copyf );
  68. **    BOOL  argOutput( ad, vp, copyf );
  69. **
  70. ** ^PARAMETERS:
  71. **    ARGDESC *ad;
  72. **    -- the argument descriptor for this parameter.
  73. **
  74. **    char *vp;
  75. **    -- a pointer to the string input value.
  76. **
  77. **    BOOL  copyf;
  78. **    -- if TRUE, the value will be destroyed later, and so should be copied
  79. **       if it will be retained (as for a string).
  80. **
  81. ** ^DESCRIPTION:
  82. **    Each of these converts a parameter value to the internal form, includ-
  83. **    ing validity checking.  Their parameters and return values all behave
  84. **    similarly. One of these routines is called when an argument of that
  85. **    particular type is matched by one of the argument parsing function in
  86. **    parseargs(3). When such an argument is matched, its argument transla-
  87. **    tion routine is invoked and is passed (1) the address of the argument
  88. **    descriptor for the matched argument, (2) the possible argument string
  89. **    for that matched argument, and (3) a boolean field that is TRUE only
  90. **    if the second parameter points to temporary storage (indicating that
  91. **    some copying may need to be done instead of just pointing to the same
  92. **    object).
  93. **
  94. **    Once the argument translation routine is invoked, it is responsible
  95. **    for converting the argument string to the desired internal form
  96. **    (perhaps a number), and assigning the resultant value to the
  97. **    arg_valp(ad) field of the argument descriptor (this includes handling
  98. **    any necessary (re)allocation if the matched argument has the ARGVEC
  99. **    flag enabled). If the argument is an ARGVEC or ARGLIST then the rou-
  100. **    tine is responsible for allocating any space, copying the arg-flags to
  101. **    the value-specific flags, and setting the ARGCOPYF flag for the value
  102. **    if it needs to be allocated as well.
  103. **
  104. ** ^REQUIREMENTS:
  105. **    ARGKEYWORD should be set if the argument was matched via its
  106. **    string name (as opposed to by its character name).
  107. **
  108. **    ARGVALSEP should be set is the argument value was in a separate
  109. **    argv element from the argument string-name (or character name).
  110. **
  111. ** ^SIDE-EFFECTS:
  112. **    The value used should be stored in the location indicated by arg_valp(ad).
  113. **
  114. ** ^RETURN-VALUE:
  115. **    TRUE : if the conversion was successful and the entire value was used.
  116. **
  117. **    FALSE : if the conversion failed.  The reason for failure should be
  118. **            diagnosed using usrerr().
  119. **
  120. **    -N : if the conversion was successful but only N characters of the value
  121. **         were used, the remaining characters may still match other arguments.
  122. ** 
  123. ** ^ALGORITHM:
  124. **    Function-specific, but the basic idea is as follows:
  125. **
  126. **    - convert the value-string into the desired type
  127. **    - if the value is invalid call usrerr and return FALSE
  128. **      end-if
  129. **    - if this ad is an ARGVEC
  130. **        - expand the vector and insert the new item at the end
  131. **        - update the item count
  132. **    - else 
  133. **        - set *ad_valp to the converted value
  134. **      end-if
  135. **    - return TRUE if we used the whole arg, -N if we only used N-characters
  136. ***^^**********************************************************************/
  137.  
  138. /* vector types and defines */
  139. #define BLOCKSIZE  5    /* number of items to allocate at once */
  140. #define VEC_SIZE(vec,el_typ)  ( sizeof(el_typ *) * (BLOCKSIZE + vec->count) )
  141. typedef ARGVEC_T(char *)  strvec_t;
  142. typedef ARGVEC_T(char)    charvec_t;
  143. typedef ARGVEC_T(int)     intvec_t;
  144. typedef ARGVEC_T(short)   shortvec_t;
  145. typedef ARGVEC_T(long)    longvec_t;
  146. typedef ARGVEC_T(float)   floatvec_t;
  147. typedef ARGVEC_T(double)  doublevec_t;
  148.  
  149.  
  150. /***************************************************************************
  151. ** ^SECTION: PSEUDO-TYPES -- argUsage, argEnd, argDummy
  152. **    ArgUsage is used to specify an argument that causes the command
  153. **    usage to be printed.
  154. **
  155. **    ArgDummy is used to force an item to show up in usage-messages but
  156. **    the item itself is never matched against any arguments from the
  157. **    command-line.
  158. **
  159. **    ArgEnd is used by amiga_args.c and vms_args.c to indicate an argument
  160. **    that forces all remaining arguments to be considered positional args.
  161. **
  162. **    These three are dummy functions. The routines themselves do nothing
  163. **    of importance, we just need to have their addresses available for
  164. **    identification in the corresponding <os>_args.c file.
  165. ***^^**********************************************************************/
  166.  
  167. /*ARGSUSED*/
  168. BOOL argDummy  PARMS(ad, vp, copyf)
  169. {
  170.    return   FALSE;
  171. }
  172.  
  173.  
  174. /*ARGSUSED*/
  175. BOOL argEnd  PARMS(ad, vp, copyf)
  176. {
  177.    return (FALSE);
  178. }
  179.  
  180.  
  181. /*ARGSUSED*/
  182. BOOL argUsage  PARMS(ad, vp, copyf)
  183. {
  184.    return   FALSE;
  185. }
  186.  
  187.  
  188. /***************************************************************************
  189. ** ^SECTION: STRING-TYPES -- argStr
  190. **    ArgStr is one of the few argument translation routines that actually
  191. **    uses the <copyf> flag. If <copyf> is true then the string is duplicated.
  192. **
  193. **    ArgStr assigns the given string (or a copy of it) to the value referenced
  194. **    by arg_valp(unless the argument is a vector in which case the given string
  195. **    is appended to the end).
  196. **
  197. **    ArgStr ensures that the very last item in a vector of strings (the one
  198. **    accessed as vec.array[ vec.count ]) will always be NULL.
  199. ***^^**********************************************************************/
  200.  
  201. /*ARGSUSED*/
  202. BOOL argStr  PARMS(ad, vp, copyf)
  203. {
  204.    char *cp;
  205.    argName_t  argname;
  206.  
  207.    (VOID) get_argname( arg_sname(ad), argname );
  208.    if (copyf) {
  209.       register int i;
  210.  
  211.       i = strlen(vp) + 1;
  212.       cp = (char *) malloc(i * sizeof(char));
  213.       if (!cp) {
  214.          usrerr("out of memory parsing %s", argname);
  215.          return FALSE;
  216.       }
  217.       memcpy(cp, vp, i);
  218.    }
  219.    else
  220.       cp = vp;
  221.  
  222.    if ( ARG_isVEC(ad) ) {
  223.       strvec_t  *vec = (strvec_t *)arg_valp(ad);
  224.  
  225.       if ( (vec->count % BLOCKSIZE) == 0 ) {
  226.          vec->array = (char **) REALLOC(vec->array, 1+VEC_SIZE(vec, char *));
  227.          if ( !vec->array ) {
  228.             if ( copyf )  free(cp);
  229.             syserr("out of memory saving arg %s", argname);
  230.          }
  231.          vec->flags = (argMask_t *) REALLOC(vec->flags, VEC_SIZE(vec, argMask_t));
  232.          if ( !vec->flags ) {
  233.             syserr("out of memory saving arg %s", argname);
  234.          }
  235.       }
  236.  
  237.       vec->flags[ vec->count ] = arg_flags(ad);
  238.       if ( copyf )  BSET( vec->flags[vec->count], ARGCOPYF );
  239.       vec->array[ (vec->count)++ ] = cp;
  240.       vec->array[ vec->count ] = (char *)NULL;
  241.    }
  242.    else
  243.       *(char **) arg_valp(ad) = cp;
  244.  
  245.    return (TRUE);
  246. }
  247.  
  248.  
  249. /***************************************************************************
  250. ** ^SECTION: CHARACTER-TYPES -- argChar
  251. **    ArgChar assigns the given character to the value referenced by ad_valp
  252. **    (unless the argument is a vector in which case the given character
  253. **    is appended to the end).
  254. **
  255. **    If an argChar argument is matched as a single character option, then
  256. **    the immediately following character will be considered its argument
  257. **    (but the characters after it may still be processed as option-letters).
  258. **
  259. **    ArgChar ensures that the very last item in a vector of character (the
  260. **    one accessed as vec.array[ vec.count ]) will always be a NUL byte so
  261. **    that the resulting vector may also be used as a NULL terminated string.
  262. **
  263. **    Unlike argStr, argChar will translate character escape sequences such
  264. **    as '\n' and '\012'.
  265. ***^^**********************************************************************/
  266.  
  267. /*ARGSUSED*/
  268. BOOL argChar  PARMS(ad, vp, copyf)
  269. {
  270.    auto char *vpp;
  271.    argName_t  argname;
  272.    int status = FALSE;
  273.    char c;
  274.  
  275.    (VOID) get_argname( arg_sname(ad), argname );
  276.    if (!vp || !*vp) {
  277.       status = FALSE;
  278.    }
  279.    if (strlen(vp) == 2 && vp[0]=='^') {
  280.       c = vp[1] ^ '@';
  281.       status = TRUE;
  282.    }
  283.    else if (strlen(vp) > 1 && vp[0]=='\\') {
  284.       c = (int) strtol(&vp[1], &vpp, 8);
  285.       if (*vpp == '\0')
  286.          status = TRUE;
  287.    }
  288.    else if (strlen(vp) == 1) {
  289.       c = *vp;
  290.       status = TRUE;
  291.    }
  292.    else if ( !BTEST(arg_flags(ad), ARGVALSEP | ARGKEYWORD) ) {
  293.       c = *vp;
  294.       status = TRUE;
  295.    }
  296.  
  297.    if ( status ) {
  298.       if ( ARG_isVEC(ad) ) {
  299.          charvec_t  *vec = (charvec_t *)arg_valp(ad);
  300.  
  301.          if ( (vec->count % BLOCKSIZE) == 0 ) {
  302.             vec->array = (char *) REALLOC(vec->array, 1+VEC_SIZE(vec, char));
  303.             if (!vec->array)  syserr("out of memory saving arg %s", argname);
  304.          }
  305.          vec->flags = (argMask_t *) REALLOC(vec->flags, VEC_SIZE(vec, argMask_t));
  306.          if ( !vec->flags ) {
  307.             syserr("out of memory saving arg %s", argname);
  308.          }
  309.  
  310.          vec->flags[ vec->count ] = arg_flags(ad);
  311.          vec->array[ (vec->count)++ ] = c;
  312.          vec->array[ vec->count ] = '\0';
  313.       }
  314.       else
  315.          *(char *) arg_valp(ad) = c;
  316.    }
  317.    else {
  318.       usrerr("invalid character argument '%s' for %s",
  319.          vp, argname);
  320.    }
  321.    return (status) ? (BOOL) -1 : FALSE;
  322. }
  323.  
  324.  
  325. /***************************************************************************
  326. ** ^SECTION: INTEGER-TYPES -- argInt, argShort, argLong
  327. **    Each of these functions converts the given string to the desired
  328. **    integral type. The value may be specified as an octal number by
  329. **    specifying the first digit to be 0. Similarly, If the first two 
  330. **    characters are '0x' then the number is treated as hexadecimal.
  331. ***^^**********************************************************************/
  332.  
  333.    /*
  334.    ** macro to define an integral argtype function
  335.    **
  336.    ** NOTE : do NOT use a terminating semicolon when invoking this macro!
  337.    */
  338. #define  INTEGRAL_ARGTYPE(name,num_t,ls_t) \
  339. BOOL name  PARMS(ad, vp, copyf) \
  340. { \
  341.    auto char *vpp; \
  342.    argName_t  argname; \
  343.    num_t  value; \
  344.  \
  345.    (VOID) get_argname( arg_sname(ad), argname ); \
  346.    value = (num_t) strtol(vp, &vpp, 0); \
  347.    if (*vpp != '\0') { \
  348.       usrerr("invalid integer argument '%s' for %s", vp, argname); \
  349.       return (FALSE); \
  350.    } \
  351.    else { \
  352.       if ( ARG_isVEC(ad) ) { \
  353.          ls_t  *vec = (ls_t *)arg_valp(ad); \
  354.  \
  355.          if ( (vec->count % BLOCKSIZE) == 0 ) { \
  356.             vec->array = (num_t *) REALLOC(vec->array, VEC_SIZE(vec, num_t)); \
  357.             if ( !vec->array ) \
  358.                syserr("out of memory saving arg %s", argname); \
  359.  \
  360.             vec->flags = (argMask_t *) REALLOC(vec->flags, VEC_SIZE(vec, argMask_t)); \
  361.             if ( !vec->flags ) \
  362.                syserr("out of memory saving arg %s", argname); \
  363.          } \
  364.  \
  365.          vec->flags[ vec->count ] = arg_flags(ad); \
  366.          vec->array[ (vec->count)++ ] = value; \
  367.       } \
  368.       else \
  369.          *(num_t *) arg_valp(ad) = value; \
  370.  \
  371.       return (TRUE); \
  372.    } \
  373. }
  374.  
  375.  
  376. /* define argInt() */
  377. INTEGRAL_ARGTYPE( argInt, int, intvec_t )
  378.  
  379. /* define argShort() */
  380. INTEGRAL_ARGTYPE( argShort, short, shortvec_t )
  381.  
  382. /* define argLong() */
  383. INTEGRAL_ARGTYPE( argLong, long, longvec_t )
  384.  
  385.  
  386. #ifndef NOFLOAT
  387.  
  388. /***************************************************************************
  389. ** ^SECTION: FLOATING-POINT-TYPES -- argFloat, argDouble
  390. **    Each of these functions converts the given string to the desired
  391. **    floating-point type.
  392. ***^^**********************************************************************/
  393.  
  394.    /*
  395.    ** macro to define a decimal argtype function
  396.    **
  397.    ** NOTE : do NOT use a terminating semicolon when invoking this macro!
  398.    */
  399. #define  DECIMAL_ARGTYPE(name,dec_t,ls_t) \
  400. BOOL name  PARMS(ad, vp, copyf) \
  401. { \
  402.    auto char *vpp; \
  403.    argName_t  argname; \
  404.    dec_t  value; \
  405.  \
  406.    (VOID) get_argname( arg_sname(ad), argname ); \
  407.    value = (dec_t) strtod(vp, &vpp); \
  408.    if (*vpp != '\0') { \
  409.       usrerr("invalid decimal argument '%s' for %s", vp, argname); \
  410.       return (FALSE); \
  411.    } \
  412.    else { \
  413.       if ( ARG_isVEC(ad) ) { \
  414.          ls_t  *vec = (ls_t *)arg_valp(ad); \
  415.  \
  416.          if ( (vec->count % BLOCKSIZE) == 0 ) { \
  417.             vec->array = (dec_t *) REALLOC(vec->array, VEC_SIZE(vec, dec_t)); \
  418.             if (!vec->array) \
  419.                syserr("out of memory saving arg %s", argname); \
  420.  \
  421.             vec->flags = (argMask_t *) REALLOC(vec->flags, VEC_SIZE(vec, argMask_t)); \
  422.             if (!vec->flags) \
  423.                syserr("out of memory saving arg %s", argname); \
  424.          } \
  425.  \
  426.          vec->flags[ vec->count ] = arg_flags(ad); \
  427.          vec->array[ (vec->count)++ ] = value; \
  428.       } \
  429.       else \
  430.          *(dec_t *) arg_valp(ad) = value; \
  431.  \
  432.       return (TRUE); \
  433.    } \
  434. }
  435.  
  436. /* define argFloat */
  437. DECIMAL_ARGTYPE( argFloat, float, floatvec_t )
  438.  
  439. /* define argLong */
  440. DECIMAL_ARGTYPE( argDouble, double, doublevec_t )
  441.  
  442. #endif  /* NOFLOAT */
  443.  
  444.  
  445. /*************************************************************************
  446. ** ^SECTION: BOOLEAN-TYPES -- argBool, argSBool, argUBool, argTBool
  447. **    ArgBool and argSBool set a boolean value (if no value is given).
  448. **    ArgUBool unsets a boolean value (if no value is given). ArgTBool
  449. **    toggles a boolean value (if no value is given). If a value is
  450. **    supplied to any of these routines, then the string is looked up
  451. **    in a table and assigned the corresponding value.
  452. **
  453. **    If a value is supplied for an argument that was matched via its
  454. **    single character name and is part of the same argv element as the
  455. **    argument-name (so that both ARGKEYWORD and ARGVALSEP are not set),
  456. **    then only the first character of the value is used (unless it is
  457. **    not found in our table, in which case the value is ignored and the
  458. **    default action is taken).
  459. **
  460. **    The only possible arguments for single-character options are the
  461. **    following:
  462. **
  463. **       1, +         set the flag
  464. **       0, -         unset the flag
  465. **       ^, ~         toggle the flag
  466. **
  467. **    The possible argument strings for long-options (keywords) are as
  468. **    follows (case-insensitive):
  469. */
  470.  
  471.    /* define a structure for an item in our boolean-lookup table */
  472. struct booltab {
  473.    char   *bname;      /* string to match against */
  474.    char   bneedmatch;  /* number of characters that must match */
  475.    BOOL   bval;        /* value to use */
  476. };
  477.  
  478.    /* define the boolean-lookup table */
  479. STATIC struct booltab    _BoolTab[] = {
  480.    "1",      1,   TRUE,
  481.    "0",      1,   FALSE,
  482.    "+",      1,   TRUE,
  483.    "-",      1,   FALSE,
  484.    "yes",    1,   TRUE,
  485.    "no",     1,   FALSE,
  486.    "true",   1,   TRUE,
  487.    "false",  1,   FALSE,
  488.    "on",     2,   TRUE,
  489.    "off",    3,   FALSE,
  490.    CHARNULL
  491. };
  492.  
  493. /**^^**********************************************************************/
  494.  
  495.  
  496.    /*
  497.    ** NOTE: Lists and vectors of Boolean types are not supported!!!
  498.    **       (same goes for argEnd, argInput, & argOutput)
  499.    */
  500.  
  501. /*ARGSUSED*/
  502. BOOL argBool  PARMS(ad, vp, copyf)
  503. {
  504.    register struct booltab *b;
  505.    register char *cp;
  506.    argName_t  argname;
  507.    int len;
  508.  
  509.    (VOID) get_argname( arg_sname(ad), argname );
  510.  
  511.    /* ARGVECs are not supported for this Boolean arg-types */
  512.    if ( ARG_isVEC(ad) )
  513.       syserr( "Error in '%s' arg-entry! Boolean argvecs are not supported!",
  514.             argname );
  515.  
  516.    /* if vp is NULL, just set to TRUE
  517.    **    (needed for backward compatibility)
  518.    */
  519.    if ( !vp || !*vp ) {
  520.       *(BOOL *) arg_valp(ad) = TRUE;
  521.       return (TRUE);
  522.    }
  523.  
  524.       /* allow single character arguments for non-keywords */
  525.    if ( !BTEST(arg_flags(ad), ARGKEYWORD | ARGVALSEP) ) {
  526.       if ( *vp == '+' || *vp == '1' ) {
  527.          *(BOOL *) arg_valp(ad) = TRUE;
  528.          return (BOOL) -1;
  529.       }
  530.       if ( *vp == '-' || *vp == '0' ) {
  531.          *(BOOL *) arg_valp(ad) = FALSE;
  532.          return (BOOL) -1;
  533.       }
  534.       if ( *vp == '~' || *vp == '^' ) {
  535.          *(BOOL *) arg_valp(ad) = (*(BOOL *) arg_valp(ad)) ? FALSE : TRUE;
  536.          return (BOOL) -1;
  537.       }
  538.  
  539.          /* unmatched value, return FALSE for non-argBool (so the caller
  540.          ** can use whatever default) and return TRUE for argBool.
  541.          */
  542.       if ( arg_type(ad) == argBool ) {
  543.          *(BOOL *) arg_valp(ad) = TRUE;
  544.          return  TRUE;
  545.       }
  546.       return  FALSE;
  547.    }/* if single char option */
  548.  
  549.    /* copy input & convert to lower case */
  550.    cp = strlwr( strdup(vp) );
  551.    len = strlen( cp );
  552.  
  553.    /* search for a match in the table */
  554.    for (b = _BoolTab; b->bname ; b++) {
  555.       /* if too short, don't even bother trying */
  556.       if (len < b->bneedmatch)
  557.          continue;
  558.  
  559.       if ( memcmp(cp, b->bname, len) == 0) {
  560.          /* got a match */
  561.          *(BOOL *) arg_valp(ad) = b->bval;
  562.          free( cp );
  563.          return (TRUE);
  564.       }
  565.    }/*if match*/
  566.  
  567.    free( cp );
  568.    usrerr("invalid Boolean argument '%s' for %s", vp, argname);
  569.    return (FALSE);
  570. }
  571.  
  572.  
  573. /*ARGSUSED*/
  574. BOOL argSBool  PARMS(ad, vp, copyf)
  575. {
  576.    argName_t  argname;
  577.    BOOL  retval;
  578.  
  579.    (VOID) get_argname( arg_sname(ad), argname );
  580.  
  581.    /* ARGVECs are not supported for this Boolean arg-types */
  582.    if ( ARG_isVEC(ad) )
  583.       syserr( "Error in '%s' arg-entry! Boolean argvecs are not supported!",
  584.             argname );
  585.  
  586.    /* if vp is NULL, just set to TRUE */
  587.    if ( !vp || !*vp || !(retval = argBool(ad, vp, copyf)) ) {
  588.       *(BOOL *) arg_valp(ad) = TRUE;
  589.       return (TRUE);
  590.    }
  591.    else
  592.       return  retval;
  593. }
  594.  
  595. /*ARGSUSED*/
  596. BOOL argUBool  PARMS(ad, vp, copyf)
  597. {
  598.    argName_t  argname;
  599.    BOOL  retval;
  600.  
  601.    (VOID) get_argname( arg_sname(ad), argname );
  602.  
  603.    /* ARGVECs are not supported for this Boolean arg-types */
  604.    if ( ARG_isVEC(ad) )
  605.       syserr( "Error in '%s' arg-entry! Boolean argvecs are not supported!",
  606.             argname );
  607.  
  608.    /* if vp is NULL, just set to FALSE */
  609.    if ( !vp || !*vp || !(retval = argBool(ad, vp, copyf)) ) {
  610.       *(BOOL *) arg_valp(ad) = FALSE;
  611.       return (TRUE);
  612.    }
  613.    else
  614.       return retval;
  615. }
  616.  
  617. /*ARGSUSED*/
  618. BOOL argTBool  PARMS(ad, vp, copyf)
  619. {
  620.    argName_t  argname;
  621.    BOOL  retval;
  622.  
  623.    (VOID) get_argname( arg_sname(ad), argname );
  624.  
  625.    /* ARGVECs are not supported for this Boolean arg-types */
  626.    if ( ARG_isVEC(ad) )
  627.       syserr( "Error in '%s' arg-entry! Boolean argvecs are not supported!",
  628.             argname );
  629.  
  630.    /* if vp is NULL, just toggle value */
  631.    if ( !vp || !*vp || !(retval = argBool(ad, vp, copyf)) ) {
  632.       *(BOOL *) arg_valp(ad) = (*(BOOL *) arg_valp(ad)) ? FALSE : TRUE ;
  633.       return (TRUE);
  634.    }
  635.    else
  636.       return retval;
  637. }
  638.  
  639.  
  640. #ifdef vms_style
  641.  
  642. /***************************************************************************
  643. ** ^SECTION: I/O-REDIRECTION-TYPES -- argInput, argOutput
  644. **    ArgInput attempts to redirect the file-pointer addressed by ad_valp
  645. **    to the file named by the given value. The file is opened for reading.
  646. **
  647. **    ArgOutput attempts to redirect the file-pointer addressed by ad_valp
  648. **    to the file named by the given value. The file is opened for writing.
  649. **
  650. **    In either case, ad_valp should be of type (FILE **) (a pointer to a
  651. **    file pointer) and not a mere file pointer as in (FILE *)!!!
  652. **
  653. **    If the given files cannot be opened, then an error message is printed
  654. **    and the associated input/output streams are closed.
  655. ***^^**********************************************************************/
  656.  
  657.    /*
  658.    ** slight problem here - on VMS, as_valp should be of type FILE **
  659.    ** but on Unix (emulating VMS) it needs to be of type FILE *.
  660.    ** we get around this using the following:
  661.    */
  662. # ifdef vms
  663. #  define FP *fp
  664. # else
  665. #  define FP fp
  666. # endif
  667.  
  668. /*ARGSUSED*/
  669. BOOL argInput  PARMS(ad, vp, copyf)
  670. {
  671. #ifdef vms
  672.    FILE **fp = (FILE **)arg_valp(ad);
  673. #else
  674.    FILE *fp = (FILE *)arg_valp(ad);
  675. #endif
  676.    BOOL error = FALSE;
  677.  
  678.    /* redirect file pointer to read from file */
  679.    if ( !vp ) {
  680.       usrerr( "Error: no file name given" );
  681.       error = TRUE;
  682.    }
  683.  
  684.    if ( !error  &&  !FP )
  685.       error = TRUE;
  686.    else if ( !error  &&  !freopen(vp, "r", FP) )
  687.       error = TRUE;
  688.  
  689.    if ( error )  {
  690.       usrerr( "Error: unable to redirect input to file \"%s.\"", vp );
  691.       return  (FALSE);
  692.    }
  693.    return (TRUE);
  694. }
  695.  
  696.  
  697. /*ARGSUSED*/
  698. BOOL argOutput  PARMS(ad, vp, copyf)
  699. {
  700. #ifdef vms
  701.    FILE **fp = (FILE **)arg_valp(ad);
  702. #else
  703.    FILE *fp = (FILE *)arg_valp(ad);
  704. #endif
  705.    BOOL error = FALSE;
  706.  
  707.    /* redirect file pointer to write to file */
  708.    if ( !vp ) {
  709.       usrerr( "Error: no file name given" );
  710.       error = TRUE;
  711.    }
  712.  
  713.    if ( !error  &&  !FP )
  714.       error = TRUE;
  715.    else if ( !error  &&  !freopen(vp, "a", FP) )
  716.       error = TRUE;
  717.  
  718.    if ( error )  {
  719.       usrerr( "Error: unable to redirect output to file \"%s.\"", vp );
  720.       return  (FALSE);
  721.    }
  722.    return (TRUE);
  723. }
  724.  
  725. # undef FP
  726. #endif  /* vms_style */
  727.