home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume17 / parseargs / part11 < 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: v17i056:  parseargs - functions to parse command line arguments, Part11/12
  4. Message-ID: <1991Mar18.155757.2290@sparky.IMD.Sterling.COM>
  5. Date: 18 Mar 91 15:57:57 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 44d684bb 87aa73f6 e00c92f4 f509ccbb
  8.  
  9. Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com>
  10. Posting-number: Volume 17, Issue 56
  11. Archive-name: parseargs/part11
  12.  
  13. This is part 11 of parseargs
  14.  
  15. #!/bin/sh
  16. # this is Part.11 (part 11 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file parseargs/useful.h 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" != 11; 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/useful.h'
  34. else
  35. echo 'x - continuing file parseargs/useful.h'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'parseargs/useful.h' &&
  37. X   EXTERN  ARBPTR  memcpy    ARGS(( ARBPTR, const ARBPTR, int ));
  38. X   EXTERN  ARBPTR  memmove   ARGS(( ARBPTR, const ARBPTR, int ));
  39. X   EXTERN  ARBPTR  memset    ARGS(( ARBPTR, int, int ));
  40. #  endif  /* MEMORY_H */
  41. X   
  42. # else
  43. #  define memcmp(b1,b2,n)  bcmp(b1,b2,n)
  44. #  define memcpy(b1,b2,n)  bcopy(b2,b1,n)
  45. #  ifndef BSTRING_H
  46. #    define BSTRING_H
  47. X   EXTERN  VOID   bcopy     ARGS(( const ARBPTR, ARBPTR, int ));
  48. X   EXTERN  int    bcmp      ARGS(( const ARBPTR, const ARBPTR, int ));
  49. X   EXTERN  VOID   bzero     ARGS(( ARBPTR, int ));
  50. X   EXTERN  int    ffs       ARGS(( int ));
  51. #  endif  /* BSTRING_H */
  52. # endif /* !BSD */
  53. #endif /* STRING_H */
  54. X
  55. EXTERN  ARBPTR  malloc   ARGS(( size_t ));
  56. EXTERN  ARBPTR  ckalloc  ARGS(( size_t ));
  57. EXTERN  ARBPTR  realloc  ARGS(( ARBPTR, size_t ));
  58. EXTERN  ARBPTR  free     ARGS(( ARBPTR ));
  59. EXTERN  VOID    exit     ARGS(( int ));
  60. X
  61. #define MAXINPUTLINE    200        /* maximum string input line */
  62. #define MAXWORDLEN    100        /* maximum word (token) length */
  63. X
  64. #endif /* _USEFUL_H_ */
  65. SHAR_EOF
  66. echo 'File parseargs/useful.h is complete' &&
  67. chmod 0664 parseargs/useful.h ||
  68. echo 'restore of parseargs/useful.h failed'
  69. Wc_c="`wc -c < 'parseargs/useful.h'`"
  70. test 7432 -eq "$Wc_c" ||
  71.     echo 'parseargs/useful.h: original size 7432, current size' "$Wc_c"
  72. rm -f _shar_wnt_.tmp
  73. fi
  74. # ============= parseargs/vms_args.c ==============
  75. if test -f 'parseargs/vms_args.c' -a X"$1" != X"-c"; then
  76.     echo 'x - skipping parseargs/vms_args.c (File already exists)'
  77.     rm -f _shar_wnt_.tmp
  78. else
  79. > _shar_wnt_.tmp
  80. echo 'x - extracting parseargs/vms_args.c (Text)'
  81. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/vms_args.c' &&
  82. /*************************************************************************
  83. ** ^FILE: vms_args.c - parse VMS/DCL argument vectors
  84. **
  85. ** ^DESCRIPTION:
  86. **    This file contains the routines used to parse VMS/DCL argument
  87. **    vectors and to print VMS/DCL usage messages.
  88. **
  89. ** ^HISTORY:
  90. **    12/03/90    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  91. ***^^**********************************************************************/
  92. X
  93. #include <stdio.h>
  94. #include <ctype.h>
  95. #include <useful.h>
  96. X
  97. #ifdef vms
  98. # include <descrip.h>
  99. #endif
  100. X
  101. #include "strfuncs.h"
  102. #include "pgopen.h"
  103. X
  104. #define PARSEARGS_PRIVATE   /* include private definitions */
  105. #include "parseargs.h"
  106. X
  107. EXTERN  VOID  syserr       ARGS((const char *, ...));
  108. EXTERN  VOID  usrerr       ARGS((const char *, ...));
  109. EXTERN  VOID  get_winsize  ARGS((int, int *, int *));
  110. EXTERN  BOOL  argInput     ARGS((ARGDESC *, char *, BOOL));
  111. EXTERN  BOOL  argOutput    ARGS((ARGDESC *, char *, BOOL));
  112. X
  113. VERSIONID("$Header: vms_args.c,v 1.1 90/08/23 18:00:00 brad Exp $");
  114. X
  115. /***************************************************************************
  116. ** ^GLOBAL-VARIABLE: Usage_Requested
  117. **
  118. ** ^VISIBILITY:
  119. **    static-global (visible to all functions in this file).
  120. **
  121. ** ^DESCRIPTION:
  122. **    Indicates whether a usage message was requested by the user
  123. **    (as opposed to triggerred by a syntax error).  If the message
  124. **    is requested by the user then it is always printed in verbose
  125. **    mode and does not return an error-status-code.
  126. ***^^**********************************************************************/
  127. static  BOOL  Usage_Requested = FALSE;
  128. X
  129. X
  130. #define MAXCMDLINE 255
  131. #define VNULL (VOID *) 0
  132. X
  133. #define TOGGLE(flag)  flag = (flag) ? FALSE : TRUE
  134. X
  135. X   /* define mappings */
  136. #define  c_SPACE   '\001'   /* whitespace */
  137. #define  c_QUAL    '\002'   /* qualifier-delimiter */
  138. #define  c_QSEP    '\003'   /* qualifier-argument separator */
  139. #define  c_LSEP    '\004'   /* list-item separator character */
  140. X
  141. X
  142. typedef enum {
  143. X   Parameter,   /* token is a parameter */
  144. X   Qualifier,   /* token is a qualifier */
  145. X   EndOfLine    /* NUL-token (signifies end of tokens) */
  146. } dcl_arg_t;
  147. X
  148. X
  149. typedef struct {
  150. X   dcl_arg_t  type;   /* token type */
  151. X   char      *token;  /* token value */
  152. } dcl_token_t;
  153. X
  154. X
  155. X
  156. /***************************************************************************
  157. ** ^FUNCTION: is_cmdline - retrieve the original command-line
  158. **
  159. ** ^SYNOPSIS:
  160. */
  161. #ifndef __ANSI_C__
  162. X   static BOOL is_cmdline( argv, result )
  163. /*
  164. ** ^PARAMETERS:
  165. */
  166. X   char *argv[];
  167. /*    -- array of strings
  168. */
  169. X   char **result;
  170. /*    -- pointer to resultant command-line
  171. */
  172. #endif  /* !__ANSI_C__ */
  173. X
  174. /* ^DESCRIPTION:
  175. **    Is_cmdline will compare the given vector of strings to the actual
  176. **    string given on the command-line. If the two are approximately 
  177. **    equivalent (modulo quotes and case) then the original command-line
  178. **    is copied to result, otherwise all the elements of argv are concat-
  179. **    enated together (in order and separated by whitespace) and assigned
  180. **    to *result.
  181. **
  182. ** ^REQUIREMENTS:
  183. **    argv must be non-null
  184. **
  185. ** ^SIDE-EFECTS:
  186. **    *result is assigned to either the concatenated argv string or the
  187. **    original command-line. The result shoub be freed using free().
  188. **
  189. ** ^RETURN-VALUE:
  190. **    FALSE if the argv given is different from the command-line;
  191. **    TRUE otherwise.
  192. **
  193. ** ^CAVEATS:
  194. **    The comparison is case blind and double quotes are ignored in the
  195. **    command-line.  This is because lib$get_foreign returns double quotes
  196. **    intact, while VAX-C strips them off.
  197. **
  198. ** ^ACKNOWLEDGEMENTS:
  199. **    Thanx to Jim Barbour for writing most of this code. --BDA
  200. **
  201. ** ^ALGORITHM:
  202. **    - Make a single string out of argv
  203. **    - compare the "big" string to the command-line
  204. **    - IF they are "equivalent" assign command-line to result & return TRUE.
  205. **      ELSE assign the "big" string to result and return FALSE.
  206. ***^^**********************************************************************/
  207. #ifdef __ANSI_C__
  208. X   static BOOL is_cmdline( const char *argv[], char **result )
  209. #endif
  210. {
  211. X   unsigned long int stat;
  212. X   unsigned short int len;
  213. X   register CONST char *aptr, *sptr, *avstr;
  214. X   static char str[ MAXCMDLINE ] = "" ;
  215. #ifdef vms
  216. X   $DESCRIPTOR(str_d, str);
  217. #endif
  218. X
  219. X      /* make a single string out of argv */
  220. X   avstr = strjoin( argv, " " );
  221. X
  222. #ifndef vms
  223. X   *result = (char *)avstr;
  224. X   return  FALSE;
  225. X
  226. #else
  227. X      /* get the original command-line */
  228. X   if ( !*str ) {
  229. X      stat = lib$get_foreign( &str_d, VNULL, &len, VNULL );
  230. X      str[len] = '\0';
  231. X      if (! (stat & 1))  exit( stat );
  232. X   }
  233. X
  234. X      /* compare the two */
  235. X   for ( aptr = avstr, sptr = str ; *aptr && *sptr ; sptr++ ) {
  236. X      if ( toupper(*sptr) == toupper(*aptr) ) {
  237. X         ++aptr;
  238. X      }
  239. X      else  if ( *sptr != '"' ) {
  240. X         *result = (char *)avstr;
  241. X         return  FALSE;
  242. X      }
  243. X   }
  244. X
  245. X   *result = strdup( str );
  246. X   free( avstr );
  247. X   return  TRUE;
  248. #endif
  249. }
  250. X
  251. X
  252. /***************************************************************************
  253. ** ^FUNCTION: dcl_strxlat - translate a string according to DCL syntax
  254. **
  255. ** ^SYNOPSIS:
  256. */
  257. #ifndef __ANSI_C__
  258. X   static char *dcl_strxlat( str )
  259. /*
  260. ** ^PARAMETERS:
  261. */
  262. X   char *str;
  263. /*    -- the string to translate.
  264. */
  265. #endif  /* !__ANSI_C__ */
  266. X
  267. /* ^DESCRIPTION:
  268. **    Dcl_strxlat will attempt to convert the given string to canonical
  269. **    form by escaping any unquoted special characters, and removing any
  270. **    unquoted whitespace around special characters (such as '=' and '/').
  271. **    Since the special characters are replaced with special codes, quotes
  272. **    are also removed.
  273. **
  274. ** ^REQUIREMENTS:
  275. **    <str> should be non-null and non-empty
  276. **
  277. ** ^SIDE-EFECTS:
  278. **    <str> is "trimmed" to canonical form and special characters are mapped
  279. **    to a unique code.
  280. **
  281. ** ^RETURN-VALUE:
  282. **    The address of the translated string.
  283. **
  284. ** ^ALGORITHM:
  285. **    - remove all unquoted whitespace following any unquoted "/:=+("
  286. **    - remove all unquoted whitespace preceding any unquoted "/:=+)"
  287. **    - compress all unquoted whitespace,
  288. **    - remove all unquoted parentheses,
  289. **    - re-map all other unquoted special characters and remove quotes.
  290. **      use the following mapping:
  291. **           whitespace   ==>   '\001'
  292. **             '/'        ==>   '\002'
  293. **             ':' & '='  ==>   '\003'
  294. **             ',' & '+'  ==>   '\004'
  295. ***^^**********************************************************************/
  296. #ifdef __ANSI_C__
  297. X   static char *dcl_strxlat( char *str )
  298. #endif
  299. {
  300. X   register char c, *pread = str, *pwrite = str;
  301. X   BOOL quoted = FALSE;
  302. X
  303. X   /*
  304. X   ** pass1 - scan forward, removing all whitespace after unquoted "/:=+,("
  305. X   */
  306. X   while ( c = *pwrite++ = *pread++ ) {
  307. X      if ( c == '"' )   TOGGLE(quoted);
  308. X      if ( !quoted   &&   strchr("/:=+,(", c) )
  309. X         while( isspace(*pread) )   ++pread;
  310. X   }
  311. X   *--pwrite = '\0';   /* NUL terminate */
  312. X
  313. X   /*
  314. X   ** pass2 - scan backward, removing all whitespace before unquoted "/:=+,)"
  315. X   */
  316. X   pread = --pwrite;  /* set to last NON-NUL char */
  317. X   quoted = FALSE;
  318. X   while ( pread >= str ) {
  319. X      c = *pwrite-- = *pread--;
  320. X      if ( c == '"' )   TOGGLE(quoted);
  321. X      if ( !quoted   &&   strchr("/:=+,)", c) )
  322. X         while( isspace(*pread) )   --pread;
  323. X   }
  324. X   strcpy(str, ++pwrite);   /* reset BOS */
  325. X
  326. X   /*
  327. X   ** pass3 - compress all unquoted whitespace,
  328. X   **         remove all unquoted parentheses,
  329. X   **         re-map all other unquoted special characters and remove quotes.
  330. X   **           use the following mapping:
  331. X   **    whitespace   ->   '\001'
  332. X   **      '/'        ->   '\002'
  333. X   **      ':' & '='  ->   '\003'
  334. X   **      ',' & '+'  ->   '\004'
  335. X   */
  336. X   pread = pwrite = str;
  337. X   quoted = FALSE;
  338. X   while ( c = *pread++ ) {
  339. X      if ( c == '"' )
  340. X         TOGGLE(quoted);
  341. X      else if ( !quoted   &&   isspace(c) ) {
  342. X         *pwrite++ = c_SPACE;
  343. X         while( isspace(*pread) )   ++pread;
  344. X      }
  345. X      else if ( !quoted   &&   (c == '(' || c == ')') )
  346. X         continue;
  347. X      else if ( !quoted   &&   c == '/' )
  348. X         *pwrite++ = c_QUAL;
  349. X      else if ( !quoted   &&   (c == ':' || c == '=') )
  350. X         *pwrite++ = c_QSEP;
  351. X      else if ( !quoted   &&   (c == ',' || c == '+') )
  352. X         *pwrite++ = c_LSEP;
  353. X      else
  354. X         *pwrite++ = c;
  355. X   }/*while*/
  356. X
  357. X   *pwrite = '\0';   /* NUL-terminate */
  358. X   return   str;
  359. }
  360. X
  361. X
  362. /***************************************************************************
  363. ** ^FUNCTION: dcl_split - split a string up into a vector of DCL tokens
  364. **
  365. ** ^SYNOPSIS:
  366. */
  367. #ifndef __ANSI_C__
  368. X   static dcl_token_t  *dcl_split( str )
  369. /*
  370. ** ^PARAMETERS:
  371. */
  372. X   char *str;
  373. /*    -- the string to split up into tokens
  374. */
  375. #endif  /* !__ANSI_C__ */
  376. X
  377. /* ^DESCRIPTION:
  378. **    Dcl_split will split a string up into tokens (according to DCL grammar
  379. **    rules) and will additionally associate each token with a type (namely:
  380. **    a qualifier, a positional paramater, or the End-of-Tokens symbol).
  381. **
  382. ** ^REQUIREMENTS:
  383. **    Assume dcl_strxlat(str) has already been performed.
  384. **
  385. ** ^SIDE-EFFECTS:
  386. **    <str> is modified in much the same manner as it would have 
  387. **    been modified if it were passed as the vector_string to strsplit().
  388. **
  389. ** ^RETURN-VALUE:
  390. **    A vector of dcl_tokens.
  391. **
  392. ** ^ALGORITHM:
  393. **    - first count the number of tokens and also try to interpret stuff
  394. **      like  "parm1.1/qual1,parm1.2" by replacing the comma with a space.
  395. **    - allocate space for the vector of DCL tokens.
  396. **    - assign the approriate value and type for each token.
  397. **
  398. ** ^CAVEATS:
  399. **    Does not treate "/qual=(val1,val2/str,..)" as illegal
  400. **        ( parses it as if it were "/qual=(val1,val2)/str" )
  401. **
  402. **    Replaces "parm1.1/qual,parm1.2" with "parm1.1/qual parm1.2"
  403. **        which works only because parseargs requires a VMS
  404. **        positional list to be comma OR whitespace separated
  405. **        (not just comma separated).
  406. ***^^**********************************************************************/
  407. #ifdef __ANSI_C__
  408. X   static dcl_token_t  *dcl_split( char *str )
  409. #endif
  410. {
  411. X   int tokc = 1;  /* number of tokens */
  412. X   dcl_token_t *tokv = (dcl_token_t *)NULL;  /* vector of tokens */
  413. X   register char *pread, c;
  414. X   register int i;
  415. X
  416. X   if ( !str  ||  !(*str) )  return  (dcl_token_t *)NULL;
  417. X
  418. X    /* 1st pass (left-to-right) : count tokens */
  419. X   pread = ( *str == c_QUAL ) ? (str + 1) : str;
  420. X   while ( c = *pread++ ) {
  421. X      if ( c == c_QUAL  ||  c == c_SPACE )  ++tokc;
  422. X      if ( c == c_QUAL ) {
  423. X           /* replace "p1.1/qual,p1.2" with "p1.1/qual p1.2" */
  424. X        char *p, delims[5];
  425. X
  426. X        sprintf( delims, "%c%c%c%c", c_QSEP, c_LSEP, c_QUAL, c_SPACE );
  427. X        if ( (p = strpbrk((str + 1), delims))  &&  (*p == c_LSEP) )
  428. X           *p == c_SPACE;
  429. X      }
  430. X   }
  431. X
  432. X
  433. X    /* allocate vector */
  434. X   tokv = (dcl_token_t *)malloc( (tokc + 1) * sizeof(dcl_token_t) );
  435. X   if ( tokv == (dcl_token_t *)NULL ) {
  436. X      syserr( "malloc() failed in dcl_split()" );
  437. X   }
  438. X   tokv[ tokc ].type = EndOfLine;
  439. X   tokv[ tokc ].token = CHARNULL;
  440. X
  441. X    /* 2nd pass (right-to-left) : assign tokens to strings */
  442. X   for ( i = 1, --pread ; pread >= str ; pread-- ) {
  443. X      if ( *pread == c_SPACE  ||  *pread == c_QUAL ) {
  444. X         tokv[ tokc - i ].token = pread + 1;
  445. X         tokv[ tokc - i ].type = ( *pread == c_QUAL ) ? Qualifier : Parameter;
  446. X         *pread = '\0';
  447. X         ++i;
  448. X      }
  449. X   }
  450. X
  451. X   if ( *str ) {  /* then 1st char could NOT have been '/' */
  452. X     tokv -> token = str;
  453. X     tokv -> type  = Parameter;
  454. X   }
  455. X
  456. X   return  tokv;
  457. }
  458. X
  459. X
  460. /***************************************************************************
  461. ** ^FUNCTION: dcl_restore - restore the `escaped' characters in a token
  462. **
  463. ** ^SYNOPSIS:
  464. */
  465. #ifndef __ANSI_C__
  466. X   static char *dcl_restore( tokstr )
  467. /*
  468. ** ^PARAMETERS:
  469. */
  470. X   char *tokstr;
  471. /*    -- the token string to restore
  472. */
  473. #endif  /* !__ANSI_C__ */
  474. X
  475. /* ^DESCRIPTION:
  476. **    Dcl_restore will attempt to restore any DCL special characters (such as
  477. **    '/' and '=') that may have been escaped by dcl_strxlat().
  478. **
  479. ** ^REQUIREMENTS:
  480. **    tokstr should be non-null and non-empty
  481. **
  482. ** ^SIDE-EFFECTS:
  483. **    Any escape characters (such as c_QUAL) are restored to their ascii
  484. **    representation.
  485. **
  486. ** ^RETURN-VALUE:
  487. **    The address of the restored string
  488. **
  489. ** ^ALGORITHM:
  490. **    - for each character in tokstr
  491. **      - if it is special then replace it with its ascii code
  492. **        end-if
  493. **      end-for
  494. **
  495. ** ^CAVEATS:
  496. **    The string is not restored to way it was before it was processed by
  497. **    dcl_strxlat(). Any characters that were removed are still missing.
  498. **    Furthermore, characters such as ':' and '=' which map to the same
  499. **    code are not always restored to what they were before but are always
  500. **    restored to one of the characters (e.g. c_QSEP is always restored to
  501. **    an '=' character even though it could have been '=' OR ':').
  502. ***^^**********************************************************************/
  503. #ifdef __ANSI_C__
  504. X   static char *dcl_restore( char *tokstr )
  505. #endif
  506. {
  507. X   register  char *str = tokstr;
  508. X
  509. X   if ( !str || !*str )  return  str;
  510. X
  511. X   for ( ; *str ; str++ ) {
  512. X      switch( *str ) {
  513. X         case c_SPACE : *str = ' '; break;
  514. X         case c_QUAL  : *str = '/'; break;
  515. X         case c_QSEP  : *str = '='; break;
  516. X         case c_LSEP  : *str = ','; break;
  517. X         default : break;
  518. X      }
  519. X   }
  520. X
  521. X   return  tokstr;
  522. }
  523. X
  524. X
  525. X
  526. X
  527. /***************************************************************************
  528. ** ^FUNCTION: split_list - function to handle ARGLISTs and ARGVECs
  529. **
  530. ** ^SYNOPSIS:
  531. */
  532. #ifndef __ANSI_C__
  533. X   static BOOL split_list( ad, vp, cmd )
  534. /*
  535. ** ^PARAMETERS:
  536. */
  537. X   ARGDESC *ad;
  538. /*    -- the argument which takes multiple values
  539. */
  540. X   char *vp;
  541. /*    -- the string of values for the argument
  542. */
  543. X   ARGDESC *cmd;
  544. /*    -- the command to which the argument belongs
  545. */
  546. #endif  /* !__ANSI_C__ */
  547. X
  548. /* ^DESCRIPTION:
  549. **    Split_list will split the string containing the set of values into
  550. **    a set of tokens and will then attempt to convert each token (in the
  551. **    order given) using the ad_type function of the argument structure.
  552. **
  553. ** ^REQUIREMENTS:
  554. **    <vp> must already be preprocessed by dcl_strxlat to escape any quoted
  555. **    characters and to map special characters to their corresponding values.
  556. **
  557. ** ^SIDE-EFECTS:
  558. **    Ad has some of its flags modified as well as any modifications that
  559. **    are made by the ad_type function.
  560. **
  561. **    <vp> is modified by strsplit().
  562. **
  563. ** ^RETURN-VALUE:
  564. **    TRUE if all is hunky-dory; FALSE otherwise
  565. **
  566. ** ^ALGORITHM:
  567. **    - Split vp into a vector of tokens
  568. **    - foreach token
  569. **      - call ad_type(ad, token, copyf)
  570. **      end-if
  571. **    - set the ARGGIVEN and ARGVALGIVEN flags accordingly
  572. ***^^**********************************************************************/
  573. #ifdef __ANSI_C__
  574. X   static BOOL  split_list( ARGDESC *ad, char *vp, ARGDESC *cmd )
  575. #endif
  576. {
  577. X   char **arg_vec = (char **)NULL;
  578. X   int  i, arg_num = 0;
  579. X   BOOL err = FALSE;
  580. X   char delims[2];
  581. X
  582. X      /* set-up delimiter string */
  583. X   *delims = c_LSEP;
  584. X   *(delims + 1) = '\0';
  585. X
  586. X      /* break string up into to tokens and handle each one */
  587. X   arg_num = strsplit( &arg_vec, vp, delims );
  588. X   for ( i = 0 ; i < arg_num ; i++ ) {
  589. X      vp = arg_vec[i];
  590. X
  591. X         /* try to convert the type */
  592. X      if ( !HANDLE(ad, dcl_restore(vp), cmd_flags(cmd)) )  err = TRUE;
  593. X   }
  594. X   if ( !err )  BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  595. X
  596. X   if ( ARG_isPOSITIONAL(ad) ) {
  597. X      cmd_list(cmd) = ad;
  598. X   }
  599. X   else {
  600. X      cmd_list(cmd) = ARGDESCNULL;
  601. X   }
  602. X
  603. X   free( arg_vec );
  604. X
  605. X   return  !err;
  606. }
  607. X
  608. X
  609. /***************************************************************************
  610. ** ^FUNCTION: vms_parse - parse VMS/DCL arg-vectors
  611. **
  612. ** ^SYNOPSIS:
  613. */
  614. #ifndef __ANSI_C__
  615. X   int vms_parse( argv, argd )
  616. /*
  617. ** ^PARAMETERS:
  618. */
  619. X   char *argv[];
  620. /*    -- the vector of string arguments from the command-line
  621. */
  622. X   ARGDESC argd[];
  623. /*    -- the programmer description of the command and its args
  624. */
  625. #endif  /* !__ANSI_C__ */
  626. X
  627. /* ^DESCRIPTION:
  628. **    Vms_parse will parse the arguments in the given vector of strings,
  629. **    assign the corresponding values to the command-line arguments specified
  630. **    in argd, and check the syntax of the command-line.
  631. **
  632. ** ^REQUIREMENTS:
  633. **    The final element in argv must be a NULL pointer.
  634. **
  635. ** ^SIDE-EFECTS:
  636. **    argd is modified according to the command-line description and parameters
  637. **
  638. ** ^RETURN-VALUE:
  639. **    pe_SUCCESS (0) if no errors are encountered
  640. **    pe_SYSTEM (-1) if a system error is encountered
  641. **    pe_SYNTAX if a syntax error is encountered
  642. **
  643. ** ^ALGORITHM:
  644. **    - compare argv to the command-line (use the command-line if equal)
  645. **    - put argv back into a single string and translate it using dcl_strxlat
  646. **    - reparse the string into DCL tokens using dcl_strsplit
  647. **    - for each DCL token
  648. **       - attempt to match the token as a qualifier
  649. **       - if it is a qualifier
  650. **          - record and convert its value (if any)
  651. **       - else it is a positional parameter
  652. **          - record and convert its value (if any)
  653. **       - else there are too many arguments
  654. **          - return pe_SYNTAX
  655. **         end-if
  656. **       end-for
  657. ***^^**********************************************************************/
  658. #ifdef __ANSI_C__
  659. X   int  vms_parse( char *argv[], ARGDESC argd[] )
  660. #endif
  661. {
  662. X   register ARGDESC *ad, *args, *cmd;
  663. X   register char *p;
  664. X   char *avstr;
  665. X   BOOL  is_match = FALSE;
  666. X   int  parse_error = pe_SUCCESS;
  667. X   dcl_token_t  *tok, *tokvec;
  668. X   argName_t  keyword;
  669. X   argMask_t  saveflags, flags;
  670. X
  671. X   if ( !argd )  return  parse_error;
  672. X
  673. X      /* initialize command-structure */
  674. X   if ( !CMD_isINIT(argd) )  init_args( argd );
  675. X   cmd = argd;
  676. X   saveflags = cmd_flags(cmd);
  677. X
  678. X   if ( !argv || !*argv )  return  parse_error;
  679. X
  680. X   (VOID) is_cmdline( (CONST char **)argv, &avstr );
  681. X   BSET( cmd_flags(cmd), pa_COPYF );
  682. X   (VOID) dcl_strxlat( avstr );
  683. X   if ( !avstr || !*avstr )  return  parse_error;
  684. X   tokvec = dcl_split( avstr );
  685. X
  686. X      /* run through the token vector */
  687. X   for ( tok = tokvec ; (p = tok -> token) ; tok++ ) {
  688. X
  689. X      if ( tok -> type == Qualifier  &&  !BTEST(cmd_state(cmd), ps_NOFLAGS) ) {
  690. X         char c = '\0', *s, delims[2];
  691. X
  692. X            /* set-up delimiter string */
  693. X         *delims = c_QSEP;
  694. X         *(delims + 1) = '\0';
  695. X
  696. X            /* skip past qualifier prefix and look for possible argument */
  697. X         s  = strpbrk(p, delims);
  698. X         if (s) {
  699. X            c = *s;
  700. X            *s++ = '\0';
  701. X         }
  702. X
  703. X         is_match = FALSE;
  704. X         for ( args = argd ; args && !is_match ; args = cmd_defargs(args) ) {
  705. X            for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  706. X               if (arg_type(ad) == argDummy)  continue;
  707. X
  708. X               if (!ARG_isPOSONLY(ad)  &&  match(p, arg_sname(ad)) == 0) {
  709. X                  is_match = TRUE;
  710. X                  break;
  711. X               }/*if*/
  712. X            }
  713. X         }
  714. X
  715. X         if (c)  *(s-1) = c;  /* restore the equal sign */
  716. X
  717. X         if ( !is_match ) {
  718. X            usrerr("qualifier %s unknown", p);
  719. X            parse_error = pe_SYNTAX;
  720. X            continue;
  721. X         }
  722. X
  723. X            /* end-qualifiers */
  724. X         if ( arg_type(ad) == argEnd ) {
  725. X            BSET( cmd_state(cmd), ps_NOFLAGS );
  726. X            continue;
  727. X         }
  728. X            /* if usage - just print usage and exit */
  729. X         if ( arg_type(ad) == argUsage ) {
  730. X            Usage_Requested = TRUE;
  731. X            usage( argd );
  732. X            free( avstr );
  733. X            if ( tokvec )  free( tokvec );
  734. X            cmd_flags(cmd) = saveflags;
  735. X            exit(1);
  736. X         }
  737. X            /* have we seen this one before */
  738. X         flags = arg_flags(ad);
  739. X         if ( ARG_isGIVEN(ad) )
  740. X            BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP );
  741. X
  742. X            /* ARGNOVALs are special, having no value */
  743. X         if ( ! ARG_isVALTAKEN(ad) ) {
  744. X            if ( !HANDLE(ad, dcl_restore(s), cmd_flags(cmd)) ) {
  745. X               arg_flags(ad) = flags;
  746. X               parse_error = pe_SYNTAX;
  747. X            }
  748. X            else {
  749. X               BSET( arg_flags(ad), ARGGIVEN );
  750. X               ad = ARGDESCNULL;
  751. X            }
  752. X            continue;
  753. X         }/*if ARGNOVAL*/
  754. X
  755. X            /* now get the real value */
  756. X         if ( !s || !(*s) ) {
  757. X            if ( ARG_isVALOPTIONAL(ad) ) {
  758. X               BSET( arg_flags(ad), ARGVALGIVEN );
  759. X            }
  760. X            else {
  761. X               (VOID) get_keyword( arg_sname(ad), keyword );
  762. X               usrerr("qualifier %s requires an argument", keyword);
  763. X               arg_flags(ad) = flags;
  764. X               parse_error = pe_SYNTAX;
  765. X            }
  766. X            continue;
  767. X         }/*if*/
  768. X
  769. X         if( ARG_isMULTIVAL(ad) ) {
  770. X            if( !split_list(ad, s, cmd) ) {
  771. X               arg_flags(ad) = flags;
  772. X               parse_error = pe_SYNTAX;
  773. X            }
  774. X            else {
  775. X               BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  776. X            }
  777. X            continue;
  778. X         }/*if list*/
  779. X
  780. X            /* try to convert the type */
  781. X         if ( !HANDLE(ad, s, cmd_flags(cmd)) ) {
  782. X            arg_flags(ad) = flags;
  783. X            parse_error = pe_SYNTAX;
  784. X         }
  785. X         else {
  786. X            BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  787. X         }
  788. X
  789. X         continue;
  790. X      }/*if qual*/
  791. X      else {
  792. X            /* parsing a vector of arguments */
  793. X         if ( cmd_list(cmd) ) {
  794. X            ad = cmd_list(cmd);
  795. X            flags = arg_flags(ad);
  796. X            if ( ARG_isGIVEN(ad) )
  797. X               BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP );
  798. X
  799. X            BSET( arg_flags(ad), ARGVALSEP );
  800. X
  801. X            if( ARG_isMULTIVAL(ad) ) {
  802. X               if( !split_list(ad, p, cmd) )  parse_error = pe_SYNTAX;
  803. X            }
  804. X            else if ( !HANDLE(ad, dcl_restore(p), cmd_flags(cmd)) ) {
  805. X               arg_flags(ad) = flags;
  806. X               parse_error = pe_SYNTAX;
  807. X            }
  808. X
  809. X            if ( !parse_error )  BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  810. X
  811. X            continue;
  812. X         }
  813. X            /* positional argument */
  814. X         is_match = FALSE;
  815. X         for ( args = argd ; args && !is_match ; args = cmd_defargs(args) ) {
  816. X            for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  817. X               if (arg_type(ad) == argDummy)  continue;
  818. X
  819. X               if ( ARG_isPOSITIONAL(ad)  &&
  820. X                    (!ARG_isGIVEN(ad) || ARG_isMULTIVAL(ad)) ) {
  821. X                  is_match = TRUE;
  822. X                  break;
  823. X               }/*if*/
  824. X            }
  825. X         }
  826. X
  827. X         if ( !is_match ) {
  828. X            usrerr("too many arguments");
  829. X            parse_error = pe_SYNTAX;
  830. X            continue;
  831. X         }
  832. X
  833. X         if ( BTEST(cmd_flags(cmd), pa_FLAGS1ST) ) {
  834. X            BSET( cmd_state(cmd), ps_NOFLAGS );
  835. X         }
  836. X         flags = arg_flags(ad);
  837. X         if ( ARG_isGIVEN(ad) )
  838. X            BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP );
  839. X
  840. X         BSET( arg_flags(ad), ARGVALSEP );
  841. X
  842. X         if( ARG_isMULTIVAL(ad) ) {
  843. X            if( !split_list(ad, p, cmd) ) {
  844. X               arg_flags(ad) = flags;
  845. X               parse_error = pe_SYNTAX;
  846. X            }
  847. X            else {
  848. X               BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  849. X            }
  850. X            continue;
  851. X         }/*if list*/
  852. X
  853. X            /* try to convert */
  854. X         if ( !HANDLE(ad, dcl_restore(p), cmd_flags(cmd)) ) {
  855. X            arg_flags(ad) = flags;
  856. X            parse_error = TRUE;
  857. X         }
  858. X         else {
  859. X            BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  860. X         }
  861. X
  862. X      }/*if parameter*/
  863. X   }/*while*/
  864. X
  865. X   free( avstr );
  866. X   if ( tokvec )  free( tokvec );
  867. X   cmd_flags(cmd) = saveflags;
  868. X   return  parse_error;
  869. }
  870. X
  871. X
  872. /***************************************************************************
  873. ** ^FUNCTION: fmtarg - format command-argument syntax
  874. **
  875. ** ^SYNOPSIS:
  876. */
  877. #ifndef __ANSI_C__
  878. X   static int fmtarg( ad, buf )
  879. /*
  880. ** ^PARAMETERS:
  881. */
  882. X   ARGDESC *ad;
  883. /*    -- pointer to the argument to format
  884. */
  885. X   char *buf;
  886. /*    -- character buffer to hold the formatted result
  887. */
  888. #endif  /* !__ANSI_C__ */
  889. X
  890. /* ^DESCRIPTION:
  891. **    Fmtarg will determine the proper command-line syntax for the
  892. **    given argument and write the result to the given buffer.
  893. **
  894. ** ^REQUIREMENTS:
  895. **    buf must be large enough to hold the formatted result (100 characters
  896. **    should do the trick).
  897. **
  898. ** ^SIDE-EFECTS:
  899. **    buf is overwritten.
  900. **
  901. ** ^RETURN-VALUE:
  902. **    The number of printable characters in the argument-syntax-string
  903. **
  904. ** ^ALGORITHM:
  905. **    Print argument usage based on whether or not the argument is
  906. **    positional, hidden, multi-valued (list or vector), etc ....
  907. **    Optional arguments and values are enclosed in square braces.
  908. ***^^**********************************************************************/
  909. #ifdef __ANSI_C__
  910. X   static int fmtarg( const ARGDESC *ad, char *buf )
  911. #endif
  912. {
  913. X   /* buf must already be large enough */
  914. X   char * pos;
  915. X   argName_t  keyword, name;
  916. X
  917. X   (VOID) get_name( arg_sname(ad), name );
  918. X
  919. X   if (ARG_isPOSITIONAL(ad)) {
  920. X      sprintf( buf, "<%s>", name );
  921. X   }
  922. X   else {
  923. X      (VOID) get_keyword( arg_sname(ad), keyword );
  924. X      sprintf( buf, "%c%s", *s_KWD_PFX, keyword );
  925. X      pos = buf + strlen(buf);
  926. X
  927. X      if ( ARG_isVALTAKEN(ad) && !ARG_isBOOLEAN(ad) && !ARG_isPSEUDOARG(ad) ) {
  928. X         if  ( ARG_isVALOPTIONAL(ad)) {
  929. X            sprintf( pos, "[%c<%s>]", *s_ARG_SEP, name );
  930. X         }
  931. X         else {
  932. X            sprintf( pos, "%c<%s>", *s_ARG_SEP, name );
  933. X         }
  934. X      }/*if*/
  935. X   }/*else*/
  936. X
  937. X   return  (int) strlen(buf);
  938. }
  939. X
  940. X
  941. /***************************************************************************
  942. ** ^FUNCTION: vms_usage - print a usage message
  943. **
  944. ** ^SYNOPSIS:
  945. */
  946. #ifndef __ANSI_C__
  947. X   VOID vms_usage( argd, usage_flags )
  948. /*
  949. ** ^PARAMETERS:
  950. */
  951. X   ARGDESC *argd;
  952. /*    -- the command-descriptor array
  953. */
  954. X   argMask_t usage_flags;
  955. /*    -- flags set by $USAGECNTL
  956. */
  957. #endif  /* !__ANSI_C__ */
  958. X
  959. /* ^DESCRIPTION:
  960. **    Vms_usage will print the VMS/DCL command-line usage of the given
  961. **    command on standard diagnostic output (stderr). The content of the
  962. **    usage message is controlled by the bitmasks in usage_flags which
  963. **    correspond to the settings in the user's USAGECNTL symbol.
  964. **
  965. ** ^REQUIREMENTS:
  966. **    argd should be a non-null command-line argument-descriptor array
  967. **
  968. ** ^SIDE-EFECTS:
  969. **    Prints on stderr.
  970. **
  971. ** ^RETURN-VALUE:
  972. **    None.
  973. **
  974. ** ^ALGORITHM:
  975. **    - if no usage is desired then exit
  976. **    - if paging is requested print to the pager instead of stderr
  977. **    - print the command-line syntax
  978. **    - if the description is requested print it
  979. **    - if verbose mode is requested, print the description of each argument
  980. ***^^**********************************************************************/
  981. #ifdef __ANSI_C__
  982. X   void vms_usage( const ARGDESC *argd, argMask_t usage_flags )
  983. #endif
  984. {
  985. X   register CONST ARGDESC  *ad, *args, *cmd;
  986. X   int  max_cols = 80, max_lines  = 24;
  987. X   int  margin, ll, pl, qualifiers, longest, positionals;
  988. X   BOOL first = TRUE;
  989. X   FILE *fp;
  990. X
  991. X   if ( !argd )  return;
  992. X
  993. X      /* initialize command-structure */
  994. X   if ( !CMD_isINIT(argd) )  init_args( (ARGDESC *)argd );
  995. X   cmd = argd;
  996. X
  997. X      /* get screen size */
  998. X   get_winsize( fileno(stderr), &max_lines, &max_cols );
  999. X
  1000. X      /* force verbose-mode if requested */
  1001. X   if ( Usage_Requested )   BSET( usage_flags, usg_VERBOSE );
  1002. X
  1003. X   if ( BTEST(usage_flags, usg_NONE) )  return;
  1004. X
  1005. X   fp = ( BTEST(usage_flags, usg_PAGED) )
  1006. X      ? pgopen( stderr, getenv("USAGE_PAGER") )
  1007. X      : stderr;
  1008. X
  1009. X      /* allow null argument descriptor */
  1010. X   fprintf(fp, "Format: %s", ProgName);
  1011. X
  1012. X   ll = strlen( ProgName ) + 8;
  1013. X   margin = ll + 1;
  1014. X   longest = 0;
  1015. X
  1016. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  1017. X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
  1018. X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1019. X            argName_t  buf, name;
  1020. X
  1021. X               /* don't display hidden arguments */
  1022. X            if ( ARG_isHIDDEN(ad) )  continue;
  1023. X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  1024. X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  1025. X
  1026. X               /* figure out how wide this parameter is (for printing) */
  1027. X            pl = fmtarg(ad, buf);
  1028. X
  1029. X            if ( pl > longest )  longest = pl;
  1030. X
  1031. X
  1032. X            if ( ARG_isMULTIVAL(ad) ) {
  1033. X               (VOID) get_name( arg_sname(ad), name );
  1034. X               strcat(buf, "[,<");
  1035. X               strcat(buf, name);
  1036. X               strcat(buf, ">...]");
  1037. X               pl += 8 + strlen(name);
  1038. X            }
  1039. X            if ( !ARG_isREQUIRED(ad) ) {
  1040. X               pl += 2;  /* [] */
  1041. X            }
  1042. X
  1043. X            /* see if this will fit */
  1044. X            if ( (ll + pl + 1) > (max_cols - first) ) {
  1045. X                  /* no... start a new line */
  1046. X               fprintf(fp, "\n%*s", margin, "");
  1047. X               ll = margin;
  1048. X            }
  1049. X            else {
  1050. X                  /* yes... just throw in a space */
  1051. X               fputc(' ', fp);
  1052. X               ++ll;
  1053. X            }
  1054. X            ll += pl;
  1055. X
  1056. X                /* show the argument */
  1057. X            if ( ARG_isREQUIRED(ad) )  fputc('[', fp);
  1058. X            fprintf(fp, buf);
  1059. X            if ( ARG_isREQUIRED(ad) )  fputc(']', fp);
  1060. X
  1061. X            first = FALSE;  /* not first line anymore */
  1062. X         }/*for each ad */
  1063. X      }/* for each argd */
  1064. X   }/* for each parm-type */
  1065. X
  1066. X   fputc('\n', fp);
  1067. X
  1068. X   if ( BTEST(usage_flags, usg_DESCRIPTION) ) {
  1069. X      CONST char *description = cmd_description(cmd);
  1070. X
  1071. X      if ( description  &&  *description ) {
  1072. X         fprintf( fp, "Description:\n" );
  1073. X         indent_para(fp, max_cols, 8, "", 0, description);
  1074. X         fputc( '\n', fp );
  1075. X      }
  1076. X   }/*if*/
  1077. X
  1078. X   if ( !BTEST(usage_flags, usg_VERBOSE) )  {
  1079. X      if ( pgactive(fp) )  (VOID) pgclose( fp );
  1080. X      return;
  1081. X   }
  1082. X
  1083. X   qualifiers = 0;
  1084. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  1085. X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
  1086. X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1087. X            argName_t  buf;
  1088. X
  1089. X               /* don't display hidden arguments */
  1090. X            if ( ARG_isHIDDEN(ad) )  continue;
  1091. X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  1092. X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  1093. X
  1094. X            if ( !qualifiers++ )  fprintf(fp, "Qualifiers/Parameters:\n");
  1095. X            (VOID) fmtarg(ad, buf);
  1096. X            indent_para(fp, max_cols, 8, buf, longest+2, arg_description(ad) );
  1097. X         }/*for each ad */
  1098. X      }/* for each argd */
  1099. X   }/* for each parm-type */
  1100. X
  1101. X   if ( pgactive(fp) )  (VOID) pgclose( fp );
  1102. }
  1103. X
  1104. SHAR_EOF
  1105. chmod 0664 parseargs/vms_args.c ||
  1106. echo 'restore of parseargs/vms_args.c failed'
  1107. Wc_c="`wc -c < 'parseargs/vms_args.c'`"
  1108. test 30360 -eq "$Wc_c" ||
  1109.     echo 'parseargs/vms_args.c: original size 30360, current size' "$Wc_c"
  1110. rm -f _shar_wnt_.tmp
  1111. fi
  1112. # ============= parseargs/vprintf.c ==============
  1113. if test -f 'parseargs/vprintf.c' -a X"$1" != X"-c"; then
  1114.     echo 'x - skipping parseargs/vprintf.c (File already exists)'
  1115.     rm -f _shar_wnt_.tmp
  1116. else
  1117. > _shar_wnt_.tmp
  1118. echo 'x - extracting parseargs/vprintf.c (Text)'
  1119. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/vprintf.c' &&
  1120. /* Portable vsprintf  by Robert A. Larson <blarson@skat.usc.edu> */
  1121. X
  1122. /* Copyright 1989 Robert A. Larson.
  1123. X * Distribution in any form is allowed as long as the author
  1124. X * retains credit, changes are noted by their author and the
  1125. X * copyright message remains intact.  This program comes as-is
  1126. X * with no warentee of fitness for any purpose.
  1127. X *
  1128. X * Thanks to Doug Gwyn, Chris Torek, and others who helped clarify
  1129. X * the ansi printf specs.
  1130. X *
  1131. X * Please send any bug fixes and improvements to blarson@skat.usc.edu .
  1132. X * The use of goto is NOT a bug.
  1133. X */
  1134. X
  1135. /* Feb    7, 1989        blarson        First usenet release */
  1136. /* Oct 20, 1990     Brad Appleton -- enclosed in #ifdef BSD for parseargs */
  1137. /* Oct 21, 1990     Brad Appleton -- added test in #ifdef VPRINTF_TEST */
  1138. /* Feb 25, 1990     Brad Appleton -- #included "useful.h" and added #ifdefs
  1139. X *                                   to compile for ANSI-C as well as K&R
  1140. X */
  1141. X
  1142. X
  1143. /* This code implements the vsprintf function, without relying on
  1144. X * the existance of _doprint or other system specific code.
  1145. X *
  1146. X * Define NOVOID if void * is not a supported type.
  1147. X *
  1148. X * Two compile options are available for efficency:
  1149. X *    INTSPRINTF    should be defined if sprintf is int and returns
  1150. X *                the number of chacters formated.
  1151. X *    LONGINT        should be defined if sizeof(long) == sizeof(int)
  1152. X *
  1153. X *    They only make the code smaller and faster, they need not be
  1154. X *    defined.
  1155. X *
  1156. X * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
  1157. X * than int in argument passing.  If this is definded, and LONGINT is not,
  1158. X * the compiler must support the type unsingned long.
  1159. X *
  1160. X * Most quirks and bugs of the available sprintf fuction are duplicated,
  1161. X * however * in the width and precision fields will work correctly
  1162. X * even if sprintf does not support this, as will the n format.
  1163. X *
  1164. X * Bad format strings, or those with very long width and precision
  1165. X * fields (including expanded * fields) will cause undesired results.
  1166. X */
  1167. X
  1168. X   /* Parseargs only needs this stuff for BSD Unix  -- Brad Appleton */
  1169. #include <useful.h>
  1170. X
  1171. #ifdef BSD
  1172. #include <stdio.h>
  1173. #include <ctype.h>
  1174. X
  1175. #ifdef OSK        /* os9/68k can take advantage of both */
  1176. # define LONGINT
  1177. # define INTSPRINTF
  1178. #endif
  1179. X
  1180. /* This must be a typedef not a #define! */
  1181. #ifdef NOVOID
  1182. X  typedef char *pointer;
  1183. #else
  1184. X  typedef void *pointer;
  1185. #endif
  1186. X
  1187. #ifdef    INTSPRINTF
  1188. # define Sprintf(string,format,arg)    (sprintf((string),(format),(arg)))
  1189. #else
  1190. # define Sprintf(string,format,arg)    (\
  1191. X   sprintf((string),(format),(arg)),\
  1192. X   strlen(string)\
  1193. )
  1194. #endif
  1195. X
  1196. typedef int *intp;
  1197. X
  1198. #ifdef __ANSI_C__
  1199. X  int vsprintf(char *dest, register const char *format, va_list args)
  1200. #else
  1201. X  int vsprintf(dest, format, args)
  1202. X  char *dest;
  1203. X  register char *format;
  1204. X  va_list args;
  1205. #endif
  1206. {
  1207. X      register char *dp = dest;
  1208. X      register char c;
  1209. X      register char *tp;
  1210. X      char tempfmt[64];
  1211. #ifndef LONGINT
  1212. X      int longflag;
  1213. #endif
  1214. X
  1215. X      tempfmt[0] = '%';
  1216. X      while( (c = *format++) != 0) {
  1217. X   if(c=='%') {
  1218. X       tp = &tempfmt[1];
  1219. #ifndef LONGINT
  1220. X       longflag = 0;
  1221. #endif
  1222. continue_format:
  1223. X       switch(c = *format++) {
  1224. X      case 's':
  1225. X          *tp++ = c;
  1226. X          *tp = '\0';
  1227. X          dp += Sprintf(dp, tempfmt, VA_ARG(args, char *));
  1228. X          break;
  1229. X      case 'u':
  1230. X      case 'x':
  1231. X      case 'o':
  1232. X      case 'X':
  1233. #ifdef UNSIGNEDSPECIAL
  1234. X          *tp++ = c;
  1235. X          *tp = '\0';
  1236. #ifndef LONGINT
  1237. X          if(longflag)
  1238. X         dp += Sprintf(dp, tempfmt, VA_ARG(args, unsigned long));
  1239. X          else
  1240. #endif
  1241. X         dp += Sprintf(dp, tempfmt, VA_ARG(args, unsigned));
  1242. X          break;
  1243. #endif
  1244. X      case 'd':
  1245. X      case 'c':
  1246. X      case 'i':
  1247. X          *tp++ = c;
  1248. X          *tp = '\0';
  1249. #ifndef LONGINT
  1250. X          if(longflag)
  1251. X         dp += Sprintf(dp, tempfmt, VA_ARG(args, long));
  1252. X          else
  1253. #endif
  1254. X         dp += Sprintf(dp, tempfmt, VA_ARG(args, int));
  1255. X          break;
  1256. X      case 'f':
  1257. X      case 'e':
  1258. X      case 'E':
  1259. X      case 'g':
  1260. X      case 'G':
  1261. X          *tp++ = c;
  1262. X          *tp = '\0';
  1263. X          dp += Sprintf(dp, tempfmt, VA_ARG(args, double));
  1264. X          break;
  1265. X      case 'p':
  1266. X          *tp++ = c;
  1267. X          *tp = '\0';
  1268. X          dp += Sprintf(dp, tempfmt, VA_ARG(args, pointer));
  1269. X          break;
  1270. X      case '-':
  1271. X      case '+':
  1272. X      case '0':
  1273. X      case '1':
  1274. X      case '2':
  1275. X      case '3':
  1276. X      case '4':
  1277. X      case '5':
  1278. X      case '6':
  1279. X      case '7':
  1280. X      case '8':
  1281. X      case '9':
  1282. X      case '.':
  1283. X      case ' ':
  1284. X      case '#':
  1285. X      case 'h':
  1286. X          *tp++ = c;
  1287. X          goto continue_format;
  1288. X      case 'l':
  1289. #ifndef LONGINT
  1290. X          longflag = 1;
  1291. X          *tp++ = c;
  1292. #endif
  1293. X          goto continue_format;
  1294. X      case '*':
  1295. X          tp += Sprintf(tp, "%d", VA_ARG(args, int));
  1296. X          goto continue_format;
  1297. X      case 'n':
  1298. X          *VA_ARG(args, intp) = dp - dest;
  1299. X          break;
  1300. X      case '%':
  1301. X      default:
  1302. X          *dp++ = c;
  1303. X          break;
  1304. X       }
  1305. X   } else *dp++ = c;
  1306. X      }
  1307. X      *dp = '\0';
  1308. X      return dp - dest;
  1309. }
  1310. X
  1311. X
  1312. #ifdef __ANSI_C__
  1313. X  int vfprintf(FILE *dest, register const char *format, va_list args)
  1314. #else
  1315. X  int vfprintf(dest, format, args)
  1316. X  FILE *dest;
  1317. X  register char *format;
  1318. X  va_list args;
  1319. #endif
  1320. {
  1321. X      register char c;
  1322. X      register char *tp;
  1323. X      register int count = 0;
  1324. X      char tempfmt[64];
  1325. #ifndef LONGINT
  1326. X      int longflag;
  1327. #endif
  1328. X
  1329. X      tempfmt[0] = '%';
  1330. X      while(c = *format++) {
  1331. X   if(c=='%') {
  1332. X       tp = &tempfmt[1];
  1333. #ifndef LONGINT
  1334. X       longflag = 0;
  1335. #endif
  1336. continue_format:
  1337. X       switch(c = *format++) {
  1338. X      case 's':
  1339. X          *tp++ = c;
  1340. X          *tp = '\0';
  1341. X          count += fprintf(dest, tempfmt, VA_ARG(args, char *));
  1342. X          break;
  1343. X      case 'u':
  1344. X      case 'x':
  1345. X      case 'o':
  1346. X      case 'X':
  1347. #ifdef UNSIGNEDSPECIAL
  1348. X          *tp++ = c;
  1349. X          *tp = '\0';
  1350. #ifndef LONGINT
  1351. X          if(longflag)
  1352. X         count += fprintf(dest, tempfmt, VA_ARG(args, unsigned long));
  1353. X          else
  1354. #endif
  1355. X         count += fprintf(dest, tempfmt, VA_ARG(args, unsigned));
  1356. X          break;
  1357. #endif
  1358. X      case 'd':
  1359. X      case 'c':
  1360. X      case 'i':
  1361. X          *tp++ = c;
  1362. X          *tp = '\0';
  1363. #ifndef LONGINT
  1364. X          if(longflag)
  1365. X         count += fprintf(dest, tempfmt, VA_ARG(args, long));
  1366. X          else
  1367. #endif
  1368. X         count += fprintf(dest, tempfmt, VA_ARG(args, int));
  1369. X          break;
  1370. X      case 'f':
  1371. X      case 'e':
  1372. X      case 'E':
  1373. X      case 'g':
  1374. X      case 'G':
  1375. X          *tp++ = c;
  1376. X          *tp = '\0';
  1377. X          count += fprintf(dest, tempfmt, VA_ARG(args, double));
  1378. X          break;
  1379. X      case 'p':
  1380. X          *tp++ = c;
  1381. X          *tp = '\0';
  1382. X          count += fprintf(dest, tempfmt, VA_ARG(args, pointer));
  1383. X          break;
  1384. X      case '-':
  1385. X      case '+':
  1386. X      case '0':
  1387. X      case '1':
  1388. X      case '2':
  1389. X      case '3':
  1390. X      case '4':
  1391. X      case '5':
  1392. X      case '6':
  1393. X      case '7':
  1394. X      case '8':
  1395. X      case '9':
  1396. X      case '.':
  1397. X      case ' ':
  1398. X      case '#':
  1399. X      case 'h':
  1400. X          *tp++ = c;
  1401. X          goto continue_format;
  1402. X      case 'l':
  1403. #ifndef LONGINT
  1404. X          longflag = 1;
  1405. X          *tp++ = c;
  1406. #endif
  1407. X          goto continue_format;
  1408. X      case '*':
  1409. X          tp += Sprintf(tp, "%d", VA_ARG(args, int));
  1410. X          goto continue_format;
  1411. X      case 'n':
  1412. X          *VA_ARG(args, intp) = count;
  1413. X          break;
  1414. X      case '%':
  1415. X      default:
  1416. X          putc(c, dest);
  1417. X          count++;
  1418. X          break;
  1419. X       }
  1420. X   } else {
  1421. X       putc(c, dest);
  1422. X       count++;
  1423. X   }
  1424. X      }
  1425. X      return count;
  1426. }
  1427. X
  1428. #ifdef __ANSI_C__
  1429. X  int vprintf(const char *format, va_list args)
  1430. #else
  1431. X  int vprintf(format, args)
  1432. X  char *format;
  1433. X  va_list args;
  1434. #endif
  1435. {
  1436. X      return vfprintf(stdout, format, args);
  1437. }
  1438. #endif  /* BSD Unix ONLY */
  1439. X
  1440. X    /* use a VERY SIMPLE test case to test this out -- Brad Appleton */
  1441. #ifdef VPRINTF_TEST
  1442. X
  1443. /*VARARGS1*/
  1444. #ifdef __ANSI_C__
  1445. X  int vtest( char *fmt, ... )
  1446. #else
  1447. X  int vtest( fmt, va_alist )
  1448. X  char *fmt;
  1449. X  va_dcl
  1450. #endif
  1451. {
  1452. X   va_list   ap;
  1453. X   int   rc;
  1454. X
  1455. X   VA_START(ap, fmt);
  1456. X   rc = vprintf( fmt, ap );
  1457. X   VA_END(ap);
  1458. X
  1459. X   return   rc;
  1460. }
  1461. X
  1462. void main()
  1463. {
  1464. X   printf( "its a %s %% day in the %d neighborhood for %*s\n",
  1465. X          "pitiful", 4, 8, "fun" );
  1466. X
  1467. X   vtest( "its a %s %% day in the %d neighborhood for %*s\n",
  1468. X          "pitiful", 4, 8, "fun" );
  1469. }
  1470. X
  1471. #endif  /* VPRINTF_TEST */
  1472. SHAR_EOF
  1473. chmod 0664 parseargs/vprintf.c ||
  1474. echo 'restore of parseargs/vprintf.c failed'
  1475. Wc_c="`wc -c < 'parseargs/vprintf.c'`"
  1476. test 8146 -eq "$Wc_c" ||
  1477.     echo 'parseargs/vprintf.c: original size 8146, current size' "$Wc_c"
  1478. rm -f _shar_wnt_.tmp
  1479. fi
  1480. # ============= parseargs/winsize.c ==============
  1481. if test -f 'parseargs/winsize.c' -a X"$1" != X"-c"; then
  1482.     echo 'x - skipping parseargs/winsize.c (File already exists)'
  1483.     rm -f _shar_wnt_.tmp
  1484. else
  1485. > _shar_wnt_.tmp
  1486. echo 'x - extracting parseargs/winsize.c (Text)'
  1487. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/winsize.c' &&
  1488. /*************************************************************************
  1489. ** ^FILE: winsize.c - implement the routine get_winsize()
  1490. **
  1491. ** ^DESCRIPTION:
  1492. **    Implement the get_winsize() function for various windowing and
  1493. **    operating systems.
  1494. **
  1495. ** ^HISTORY:
  1496. **    10/01/90     Brad Appleton     <brad@ssd.csd.harris.com>     Created
  1497. ***^^**********************************************************************/
  1498. X
  1499. X
  1500. /***************************************************************************
  1501. ** ^FUNCTION: get_winsize - get the current window size
  1502. **
  1503. ** ^SYNOPSIS:
  1504. **    void get_winsize( fd, nrows, ncols )
  1505. **
  1506. ** ^PARAMETERS:
  1507. **    int fd;
  1508. **    -- file-descriptor associated with the "output-window"
  1509. **
  1510. **    int *nrows;
  1511. **    -- pointer to number of rows in window
  1512. **
  1513. **    int *ncols;
  1514. **    -- pointer to number of columns in window
  1515. **
  1516. ** ^DESCRIPTION:
  1517. **    Get_winsize will attempt to determine the maximum number of
  1518. **    rows and colums that will fit on one screen-full of the associated
  1519. **    output device. If it fails to do this, it will assume the "window"
  1520. **    is a 24x80 (rows by columns) display.
  1521. **
  1522. ** ^REQUIREMENTS:
  1523. **    fd must correspond to a valid output device.
  1524. **
  1525. ** ^SIDE-EFFECTS:
  1526. **    The memory addressed by nrows and ncols is assigned the corresponding
  1527. **    appropriate value(s).
  1528. **
  1529. ** ^RETURN-VALUE:
  1530. **    None.
  1531. **
  1532. ** ^ALGORITHM:
  1533. **     System dependent.
  1534. ***^^**********************************************************************/
  1535. X
  1536. #if ( defined(__STDC__) || defined(c_plusplus) || defined(__cplusplus) )
  1537. # define  GET_WINSIZE(fd,nrows,ncols)  \
  1538. X    void get_winsize( int fd, int *nrows, int *ncols )
  1539. #else
  1540. # define  GET_WINSIZE(fd,nrows,ncols)  \
  1541. X    void get_winsize( fd, nrows, ncols ) \
  1542. X    int fd, *nrows, *ncols;   /* nrows and ncols are passed by reference */
  1543. #endif
  1544. X
  1545. #include <stdio.h>
  1546. #include <useful.h>
  1547. X
  1548. #define  DEFAULT_ROWS  24
  1549. #define  DEFAULT_COLS  80
  1550. X
  1551. #ifdef vms
  1552. X
  1553. #include <stdio.h>
  1554. #include <iodef.h>
  1555. #include <ssdef.h>
  1556. #include <descrip.h>
  1557. X
  1558. X   /* structure to contain terminal characteristics */
  1559. typedef  struct {
  1560. X      short garb1, cols;
  1561. X      char   garb2, garb3, garb4, rows;
  1562. } termchar_t;
  1563. X
  1564. int sys$assign();
  1565. int sys$qiow();
  1566. int sys$dassgn();
  1567. X
  1568. GET_WINSIZE( fd, nrows, ncols )
  1569. {
  1570. X   int c, charlen = 8;
  1571. X   termchar_t   termchar;
  1572. X   int chan;
  1573. X   $DESCRIPTOR( devnam,"SYS$COMMAND" );
  1574. X
  1575. X   sys$assign( &devnam, &chan, 0, 0 );
  1576. X   sys$qiow( 0, chan, IO$_SENSEMODE, 0, 0, 0, &termchar, &charlen, 0, 0, 0, 0 );
  1577. X   sys$dassgn( chan );
  1578. X
  1579. X   *nrows = ( termchar.rows > 0 ) ? (int) termchar.rows : DEFAULT_ROWS;
  1580. X   *ncols = ( termchar.cols > 0 ) ? (int) termchar.cols : DEFAULT_COLS;
  1581. }
  1582. X
  1583. #else
  1584. #ifdef unix
  1585. X
  1586. X   /*
  1587. X   ** we will either try to access terminfo through the termcap-interface
  1588. X   ** in the curses library (which would require linking with -lcurses)
  1589. X   ** or use termcap directly (which would require linking with -ltermcap)
  1590. X   */
  1591. #ifndef USE_TERMCAP
  1592. #if ( defined(USE_TERMINFO) || defined(USE_CURSES) )
  1593. #define USE_TERMCAP
  1594. #endif
  1595. #endif
  1596. X
  1597. X
  1598. #ifdef USE_TERMCAP
  1599. # define TERMBUFSIZ    1024
  1600. # define UNKNOWN_TERM  "unknown"
  1601. # define DUMB_TERMBUF  "dumb:co#80:hc:"
  1602. extern int  tgetent();
  1603. extern int  tgetnum();
  1604. #endif
  1605. X
  1606. X
  1607. X   /* try to get TIOCGWINSZ from termios.h, then from sys/ioctl.h */
  1608. #include <termios.h>
  1609. #if ( !defined(TIOCGWINSZ)  &&  !defined(TIOCGSIZE)  &&  !defined(WIOCGETD) )
  1610. #include <sys/ioctl.h>
  1611. #endif
  1612. X
  1613. X   /* if still dont have TIOCGWINSZ (or TIOCGSIZE) try for WIOCGETD */
  1614. #if ( !defined(TIOCGWINSZ)  &&  !defined(TIOCGSIZE)  &&  !defined(WIOCGETD) )
  1615. #include <sgtty.h>
  1616. #endif
  1617. X
  1618. /*
  1619. ** get_winsize() -- determine # of rows/columns that will fit on the screen.
  1620. **
  1621. **     The environment variables $LINES and $COLUMNS will be used if they exist.
  1622. **     If not, then the TIOCGWINSZ call to ioctl() is used (if it is defined).
  1623. **     If not, then the TIOCGSIZE call to ioctl() is used (if it is defined).
  1624. **     If not, then the WIOCGETD call to ioctl() is used (if it is defined).
  1625. **     If not, then get the info from terminfo/termcap (if it is there)
  1626. **     Otherwise, assume we have a 24x80 screen.
  1627. */
  1628. X
  1629. extern  int   ioctl();
  1630. extern  int   isatty();
  1631. extern  long  atol();
  1632. extern  char *getenv();
  1633. X
  1634. GET_WINSIZE( fd, nrows, ncols )
  1635. {
  1636. X   char  *lines_env, *cols_env;
  1637. X   long  lrow = 0, lcol = 0;
  1638. X   int   lines = 0, cols = 0;
  1639. #ifdef USE_TERMCAP
  1640. X   char  term_buf[ TERMBUFSIZ ], *term_env;
  1641. #endif
  1642. #ifdef TIOCGWINSZ
  1643. X   struct winsize  win;
  1644. #else
  1645. #ifdef TIOCGSIZE
  1646. X   struct ttysize  win;
  1647. #else
  1648. #ifdef WIOCGETD
  1649. X   struct uwdata  win;
  1650. #endif
  1651. #endif
  1652. #endif
  1653. X
  1654. X      /* make sure that fd corresponds to a terminal */
  1655. X   if ( !isatty( fd ) ) {
  1656. X      *nrows = DEFAULT_ROWS;
  1657. X      *ncols = DEFAULT_COLS;
  1658. X      return;
  1659. X   }
  1660. X
  1661. X      /* LINES & COLUMNS environment variables override everything else */
  1662. X   lines_env = getenv( "LINES" );
  1663. X   if ( lines_env  &&  (lrow = atol(lines_env)) > 0 ) {
  1664. X      *nrows = lines = (int) lrow;
  1665. X   }
  1666. X
  1667. X   cols_env = getenv( "COLUMNS" );
  1668. X   if ( cols_env  &&  (lcol = atol(cols_env)) > 0 ) {
  1669. X      *ncols = cols = (int) lcol;
  1670. X   }
  1671. X
  1672. #ifdef TIOCGWINSZ
  1673. X      /* see what ioctl() has to say (overrides terminfo & termcap) */
  1674. X   if ( (!lines || !cols)  &&  ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
  1675. X      if ( !lines  &&  win.ws_row > 0 ) {
  1676. X         *nrows = lines = (int) win.ws_row;
  1677. X      }
  1678. X
  1679. X      if ( !cols  &&  win.ws_col > 0 ) {
  1680. X         *ncols = cols = (int) win.ws_col;
  1681. X      }
  1682. X   }/*if*/
  1683. #else
  1684. #ifdef TIOCGSIZE
  1685. X      /* see what ioctl() has to say (overrides terminfo & termcap) */
  1686. X   if ( (!lines || !cols)  &&  ioctl(fd, TIOCGSIZE, &win) != -1 ) {
  1687. X      if ( !lines  &&  win.ts_lines > 0 )
  1688. X         *nrows = lines = (int) win.ts_lines;
  1689. X
  1690. X      if ( !cols  &&  win.ts_cols > 0 )
  1691. X         *ncols = cols = (int) win.ts_cols;
  1692. X   }/*if*/
  1693. #else
  1694. #ifdef WIOCGETD
  1695. X      /* see what ioctl() has to say (overrides terminfo & termcap) */
  1696. X   if ( (!lines || !cols)  &&  ioctl(fd, WIOCGETD, &win) != -1 ) {
  1697. X      if ( !lines  &&  win.uw_height > 0 )
  1698. X         *nrows = lines = (int) (win.uw_height / win.uw_vs);
  1699. X
  1700. X      if ( !cols  &&  win.uw_width > 0 )
  1701. X         *ncols = cols = (int) (win.uw_width / win.uw_hs);
  1702. X   }/*if*/
  1703. #endif
  1704. #endif
  1705. #endif
  1706. X
  1707. #ifdef USE_TERMCAP
  1708. X      /* see what terminfo/termcap has to say */
  1709. X   if ( !lines || !cols ) {
  1710. X      if ( !(term_env = getenv("TERM")) )
  1711. X         term_env = UNKNOWN_TERM;
  1712. X
  1713. X      if ( (tgetent(term_buf, term_env) <= 0) )
  1714. X         strcpy( term_buf, DUMB_TERMBUF );
  1715. X
  1716. X          if ( !lines   &&   (lrow = tgetnum("li")) > 0 )
  1717. X            *nrows = lines = (int) lrow;
  1718. X
  1719. X          if ( !cols   &&   (lcol = tgetnum("co")) > 0 )
  1720. X            *ncols = cols = (int) lcol;
  1721. X   }
  1722. #endif
  1723. X
  1724. X      /* use 80x24 if all else fails */
  1725. X   if ( !lines )  *nrows = DEFAULT_ROWS;
  1726. X   if ( !cols )   *ncols = DEFAULT_COLS;
  1727. X
  1728. }/*get_winsize()*/
  1729. X
  1730. #else
  1731. X
  1732. GET_WINSIZE( fd, nrows, ncols )
  1733. {
  1734. X      /* just use 80x24 */
  1735. X   *nrows = DEFAULT_ROWS;
  1736. X   *ncols = DEFAULT_COLS;
  1737. }
  1738. X
  1739. #endif  /* not a vms system */
  1740. #endif  /* not a unix-system */
  1741. X
  1742. #ifdef WINSIZE_TEST
  1743. X   /* test get_winsize to see if it works */
  1744. main()
  1745. {
  1746. X   int rows, cols;
  1747. X
  1748. X   get_winsize( fileno(stderr), &rows, &cols );
  1749. X   printf( "Output will be %d rows by %d columns\n", rows, cols );
  1750. X   exit( 0 );
  1751. }
  1752. X
  1753. #endif
  1754. SHAR_EOF
  1755. chmod 0664 parseargs/winsize.c ||
  1756. echo 'restore of parseargs/winsize.c failed'
  1757. Wc_c="`wc -c < 'parseargs/winsize.c'`"
  1758. test 7121 -eq "$Wc_c" ||
  1759.     echo 'parseargs/winsize.c: original size 7121, current size' "$Wc_c"
  1760. rm -f _shar_wnt_.tmp
  1761. fi
  1762. # ============= parseargs/xparse.c ==============
  1763. if test -f 'parseargs/xparse.c' -a X"$1" != X"-c"; then
  1764.     echo 'x - skipping parseargs/xparse.c (File already exists)'
  1765.     rm -f _shar_wnt_.tmp
  1766. else
  1767. > _shar_wnt_.tmp
  1768. echo 'x - extracting parseargs/xparse.c (Text)'
  1769. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/xparse.c' &&
  1770. /*************************************************************************
  1771. ** ^FILE: xparse.c - library functions for the parsargs(3) package
  1772. **
  1773. ** ^DESCRIPTION:
  1774. **    This file implements the following functions in the parseargs library:
  1775. **
  1776. **       init_args()  -- constructor for a command-object
  1777. **       usage()      -- pretty-print the command-usage
  1778. **       parsecntl()  -- control parsing, get/set command-attributes
  1779. **       parseargs()  -- parse argumenst from a string vector
  1780. **       fparseargs() -- parse arguments from a file pointer
  1781. **       lparseargs() -- parse arguments from an arglist
  1782. **       sparseargs() -- parse arguyments in a string
  1783. **       vparseargs() -- parse arguments from a variable argument list
  1784. **
  1785. **    It should be noted that sparseargs() splits the given string up into
  1786. **    a whitespace separated series of tokens, whereas vparseargs assumes
  1787. **    that each parameter is already a single token (hence performs no
  1788. **    token splitting).
  1789. **
  1790. **    Each of these functions returns 0 upon success and non-zero otherwise
  1791. **    (except for usage() & init_args, which have no return value).
  1792. **
  1793. ** ^FILES:
  1794. **    <useful.h>
  1795. **    <parseargs.h>
  1796. **
  1797. ** ^SEE_ALSO:
  1798. **    argtype(3), parseargs(1), parseargs(3), parsecntl(3),
  1799. **
  1800. ** ^CAVEATS:
  1801. **    Because of the way argument parsing is implemented under UNIX, MS-DOS
  1802. **    and OS/2, option arguments which contain a leading dash (`-') (or
  1803. **    whatever the option prefix character is defined to be) may not be
  1804. **    specified as a separate argument on the command line, it must be part
  1805. **    of the same argument.  That is to say that if a program has a -f option
  1806. **    that requires a string argument, then the following:
  1807. **          -f-arg
  1808. **
  1809. **    will properly assign the string "-arg" to the option whereas the
  1810. **    following:
  1811. **          -f -arg
  1812. **
  1813. **    will be interpreted by parseargs as two option strings: the first of
  1814. **    which ("-f") is missing a required argument and the second of which
  1815. **    ("-arg") will most likely be flagged as an invalid option.
  1816. **
  1817. **    Similarly, if the user requires an ARGLIST option to take multiple
  1818. **    arguments with leading dashes then the following method must be used:
  1819. **    It is a "feature" of parseargs that ARGLIST arguments are always
  1820. **    appended to the current list of arguments for the given option. Thus,
  1821. **    if "-f" is an option taking a list of arguments, then the following
  1822. **    are all equivalent:
  1823. **          -farg1 arg2
  1824. **          -f arg1 arg2
  1825. **          -farg1 -farg2
  1826. **          -f arg1 -f arg2
  1827. **
  1828. **     Hence multiple "leading dash" arguments may specified as follows:
  1829. **          -f-dash_arg1 -f-dash_arg2  ...
  1830. **
  1831. ** ^BUGS:
  1832. **    When a non-multivalued argument appears more than once on the
  1833. **    command-line then only the last value supplied is used. A problem
  1834. **    occurs however in the following scenario: suppose `-s' is an option
  1835. **    that takes an optional string argument (nd suppose `-x' is some
  1836. **    boolean flag). Then if the following command-line is issued:
  1837. **
  1838. **         command  -s string  -x  -s
  1839. **
  1840. **    then, the argument flags will properly correspond to the second
  1841. **    instance of the `-s' option (namely ARGGIVEN will be set but ARGVAL-
  1842. **    GIVEN will be unset) but the value associated with the option will be
  1843. **    "string" (because the first instance overwrote the default).
  1844. **    Because of this, it may be safest to reassign the default value if
  1845. **    ARGGIVEN is set but ARGVALGIVEN is unset.
  1846. **
  1847. ** ^HISTORY:
  1848. **    01/02/91     Brad Appleton     <brad@ssd.csd.harris.com>     Created
  1849. ***^^**********************************************************************/
  1850. X
  1851. #include <stdio.h>
  1852. #include <ctype.h>
  1853. #include <useful.h>
  1854. #include "strfuncs.h"
  1855. X
  1856. #define PARSEARGS_PRIVATE   /* include private definitions */
  1857. #define PARSEARGS_NEXTERNS  /* exclude external declarations */
  1858. #include "parseargs.h"
  1859. X
  1860. #ifdef amiga_style
  1861. #  define  pa_DEFAULTS  0x000
  1862. #  define  parse_argv_style   amiga_parse
  1863. #  define  print_usage_style  amiga_usage
  1864. X   EXTERN  int   amiga_parse  ARGS(( char **, ARGDESC * ));
  1865. X   EXTERN  VOID  amiga_usage  ARGS(( const ARGDESC *, argMask_t ));
  1866. #endif
  1867. #ifdef ibm_style
  1868. #  define  pa_DEFAULTS  pa_ANYCASE
  1869. #  define  parse_argv_style   ibm_parse
  1870. #  define  print_usage_style  ibm_usage
  1871. X   EXTERN  int   ibm_parse  ARGS(( char **, ARGDESC * ));
  1872. X   EXTERN  VOID  ibm_usage  ARGS(( const ARGDESC *, argMask_t ));
  1873. #endif
  1874. #ifdef unix_style
  1875. #  define  pa_DEFAULTS  pa_FLAGS1ST
  1876. #  define  parse_argv_style   unix_parse
  1877. #  define  print_usage_style  unix_usage
  1878. X   EXTERN  int   unix_parse   ARGS(( char **, ARGDESC * ));
  1879. X   EXTERN  VOID  unix_usage   ARGS(( const ARGDESC *, argMask_t ));
  1880. #endif
  1881. #ifdef vms_style
  1882. #  define  pa_DEFAULTS  pa_PROMPT
  1883. #  define  parse_argv_style   vms_parse
  1884. #  define  print_usage_style  vms_usage
  1885. X   EXTERN  int   vms_parse    ARGS(( char **, ARGDESC * ));
  1886. X   EXTERN  VOID  vms_usage    ARGS(( const ARGDESC *, argMask_t ));
  1887. #endif
  1888. X
  1889. X
  1890. #if vms
  1891. #  define  USER_VARIABLE "symbol"
  1892. #else
  1893. #  define  USER_VARIABLE "environment variable"
  1894. #endif
  1895. X
  1896. X
  1897. /***************************************************************************
  1898. ** ^MACRO: SYNTAX_ERROR -  check for syntax errors & missing required arguments
  1899. **
  1900. ** ^SYNOPSIS:
  1901. **    SYNTAX_ERROR(status, argd)
  1902. **
  1903. ** ^PARAMETERS:
  1904. **    status
  1905. **    -- current parsing status returned by last xparsexxx() call
  1906. **
  1907. **    argd
  1908. **    --argdesc-array
  1909. **
  1910. ** ^RETURN-VALUE:
  1911. **    Evaluates to TRUE if need to exit, FALSE otherwise
  1912. **
  1913. ** ^ALGORITHM:
  1914. **    - if (!pa_NOCHECK) and (verify_argreqs == error) then return TRUE
  1915. **    - else return FALSE
  1916. ***^^**********************************************************************/
  1917. #define  SYNTAX_ERROR(status, argd)  ( !verify_argreqs(argd, &status) )
  1918. X
  1919. X
  1920. /***************************************************************************
  1921. ** ^GLOBAL-VARIABLE: ProgName
  1922. **
  1923. ** ^VISIBILITY:
  1924. **    external global (visible to functions in all files)
  1925. **
  1926. ** ^DESCRIPTION:
  1927. **    ProgName (which is initially NULL) will be used to point to the
  1928. **    command-name (specified on the command-line) of the command that
  1929. **    has most recently invoked a function in the parseargs library.
  1930. ***^^**********************************************************************/
  1931. CONST char *ProgName = (char *)NULL;
  1932. X
  1933. EXTERN  VOID  syserr   ARGS((const char *, ...));
  1934. EXTERN  VOID  usrerr   ARGS((const char *, ...));
  1935. EXTERN  VOID  eprintf  ARGS((const char *, ...));
  1936. X
  1937. #ifdef vms_style
  1938. X   EXTERN BOOL argInput        ARGS((ARGDESC *, char *, BOOL));
  1939. X   EXTERN BOOL argOutput       ARGS((ARGDESC *, char *, BOOL));
  1940. #endif
  1941. X
  1942. #define  MAXLINE  256
  1943. X
  1944. X
  1945. /* override argument descriptor, if none given by user */
  1946. static ARGDESC    Empty_ArgDesc[] = { START_ARGUMENTS, END_ARGUMENTS };
  1947. X
  1948. /***************************************************************************
  1949. ** ^SECTION: DEFAULT-ARGUMENTS
  1950. **    Each argdesc-array has an initial default argument list (which may be
  1951. **    reset using the pc_DEFARGS function code with parsecntl). This initial
  1952. **    default argument-list contains `?' and `H' which may be used as single
  1953. **    character keywords to display command-usage for all command-line
  1954. **    styles.  Similarly, "?", "H", and "Help" may be used as long-keywords
  1955. **    to display command-usage for all command-line styles.  In Addition,
  1956. **    for VMS style commands, the qualifiers /INPUT=file, /OUTPUT=file, and
  1957. **    /ERROR=file, may be used to redirect stdin, stdout, and stderr
  1958. **    (respectively) to a file.  For AmigaDOS style commands, the keyword
  1959. **    "ENDKWDS" may be used to disable parsing for any more keywords on
  1960. **    the command-line.
  1961. ***^^**********************************************************************/
  1962. static  ARGDESC  Default_ArgDesc[] = {
  1963. X   START_ARGUMENTS,
  1964. X
  1965. /* <name> <flags>    <type>     <valp>         <prompt>      */
  1966. X   { '?', ARGHIDDEN, argUsage, __ NULL,    "? (print usage and exit)" },
  1967. X   { 'H', ARGHIDDEN, argUsage, __ NULL,    "Help (print usage and exit)" },
  1968. X
  1969. #ifdef amiga_style
  1970. X   { '-', ARGHIDDEN, argEnd,   __ NULL,    "ENDKeyWorDS" },
  1971. #endif
  1972. X
  1973. #ifdef vms_style
  1974. X   { '<', ARGHIDDEN, argInput, __ stdin,   "INPUT (redirect SYS$INPUT)" },
  1975. X   { '>', ARGHIDDEN, argOutput, __ stdout, "OUTPUT (redirect SYS$OUTPUT)" },
  1976. X   { '%', ARGHIDDEN, argOutput, __ stderr, "ERROR (redirect SYS$ERROR)" },
  1977. #endif
  1978. X
  1979. X   END_ARGUMENTS
  1980. };
  1981. X
  1982. X
  1983. #ifdef AmigaDOS
  1984. #  define  getenv(s)   CHARNULL
  1985. #  define  envfree(s)  s = CHARNULL
  1986. #endif
  1987. X
  1988. #if ( defined(MSDOS) || defined(OS2) )
  1989. X   EXTERN  char *getenv ARGS(( const char * ));
  1990. #  define  envfree(s)  s = CHARNULL
  1991. #endif
  1992. X
  1993. #ifdef unix
  1994. X   EXTERN  char *getenv ARGS(( const char * ));
  1995. #  define  envfree(s)  s = CHARNULL
  1996. #endif
  1997. X
  1998. #ifdef vms
  1999. #  define  getenv(s)   getsymbol(s)
  2000. #  define  envfree(s)  (s) = ( !(s) ) ? CHARNULL : (free(s), CHARNULL)
  2001. #  include <descrip.h>
  2002. #  include <libdef.h>
  2003. X
  2004. #  define  MAXLEN 255
  2005. X
  2006. X   /***************************************************************************
  2007. X   ** ^FUNCTION: get_symbol - retrieve the value of a VMS symbol
  2008. X   **
  2009. X   ** ^SYNOPSIS:
  2010. X   */
  2011. #  ifndef __ANSI_C__
  2012. X      char *get_symbol( sym_name )
  2013. X   /*
  2014. X   ** ^PARAMETERS:
  2015. X   */
  2016. X      char *sym_name;
  2017. X   /*    -- name of the symbol to retrieve
  2018. X   */
  2019. #  endif  /* !__ANSI_C__ */
  2020. X
  2021. X   /* ^DESCRIPTION:
  2022. X   **    Get_symbol will lookup the named symbol and return its value
  2023. X   **    as a string.
  2024. X   **
  2025. X   ** ^REQUIREMENTS:
  2026. X   **    sym_name should correspond to the name of a pre-defined symbol.
  2027. X   **
  2028. X   ** ^SIDE-EFECTS:
  2029. X   **    None.
  2030. X   **
  2031. X   ** ^RETURN-VALUE:
  2032. X   **    NULL if the symbol is not found, otherwise it copies the symbol
  2033. X   **    value and returns the address of the copy (which may later be
  2034. X   **    deallocated using free()).
  2035. X   **
  2036. X   ** ^ACKNOWLEDGEMENTS:
  2037. X   **    Thanx to Jim Barbour for writing most of this code. --BDA
  2038. X   **
  2039. X   ** ^ALGORITHM:
  2040. X   **    Trivial - just use the LIB$GET_SYMBOL system service.
  2041. X   ***^^**********************************************************************/
  2042. #  ifdef __ANSI_C__
  2043. X      char *get_symbol( const char *sym_name )
  2044. #  endif
  2045. X   {
  2046. X      unsigned long stat, lib$get_symbol();
  2047. X      unsigned short buflen;
  2048. X      char sym_value[ MAXLEN ];
  2049. X      $DESCRIPTOR( sym_name_d, sym_name );
  2050. X      $DESCRIPTOR( sym_value_d, sym_value );
  2051. X
  2052. X      sym_value_d.dsc$w_length =  MAXLEN;
  2053. X      sym_name_d.dsc$w_length = strlen( sym_name );
  2054. X      stat = lib$get_symbol( &sym_name_d, &sym_value_d, &buflen, (void *)0 );
  2055. X      if ( stat == LIB$_NOSUCHSYM ) {
  2056. X         return  CHARNULL;
  2057. X      }
  2058. X      else if ( ! (stat & 1) ) {
  2059. X         exit(stat);
  2060. X      }
  2061. X      sym_value[ buflen ] = '\0';
  2062. X      return  strdup( sym_value );
  2063. X   }
  2064. #endif /* vms */
  2065. X
  2066. X
  2067. /***************************************************************************
  2068. ** ^FUNCTION: is_interactive - determine if a stream is "interactive"
  2069. **
  2070. ** ^SYNOPSIS:
  2071. */
  2072. #ifndef __ANSI_C__
  2073. X   static BOOL is_interactive( fd )
  2074. /*
  2075. ** ^PARAMETERS:
  2076. */
  2077. X   int fd;
  2078. /*    -- file descriptor associated with the input stream
  2079. */
  2080. #endif  /* !__ANSI_C__ */
  2081. X
  2082. /* ^DESCRIPTION:
  2083. **    Is_interactive determines whether or not the given i/o stream is
  2084. **    associated with a terminal.
  2085. **
  2086. ** ^REQUIREMENTS:
  2087. **    Fd must correspond to a valid, open, file-descriptor.
  2088. SHAR_EOF
  2089. true || echo 'restore of parseargs/xparse.c failed'
  2090. fi
  2091. echo 'End of  part 11'
  2092. echo 'File parseargs/xparse.c is continued in part 12'
  2093. echo 12 > _shar_seq_.tmp
  2094. exit 0
  2095. exit 0 # Just in case...
  2096. -- 
  2097. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2098. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2099. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2100. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2101.