home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / parseargs / part06 < prev    next >
Internet Message Format  |  1991-03-17  |  63KB

  1. From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i051:  parseargs - functions to parse command line arguments, Part06/12
  4. Message-ID: <1991Mar17.200733.17985@sparky.IMD.Sterling.COM>
  5. Date: 17 Mar 91 20:07:33 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 6591537f 439c2bbf 7a5900e7 66cacf7c
  8.  
  9. Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com>
  10. Posting-number: Volume 17, Issue 51
  11. Archive-name: parseargs/part06
  12.  
  13. This is part 6 of parseargs
  14.  
  15. #!/bin/sh
  16. # this is Part.06 (part 6 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file parseargs/parseargs.c 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" != 6; 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/parseargs.c'
  34. else
  35. echo 'x - continuing file parseargs/parseargs.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'parseargs/parseargs.c' &&
  37. X                  Cmd_Name, ArgdFname );
  38. X         cleanup();
  39. X         if ( errno )  perror( Cmd_Name );
  40. X         exit( e_SYSTEM );
  41. X      }
  42. X   }
  43. X
  44. X      /* get initial block for buffer */
  45. X   buf = (char *)ckalloc( BUFFER_SIZE * sizeof(char) );
  46. X
  47. X   /*
  48. X   ** Loop reading characters into buffer and resizing as needed
  49. X   */
  50. X   do {
  51. X         /* read fildes into the buffer */
  52. X      nchars = fread( &(buf[bufsiz]), sizeof(char), BUFFER_SIZE, fp );
  53. X      if ( nchars < 0 )   {
  54. X         eprintf( "\
  55. %s: Fatal Error:\n\
  56. \tBad status from read() while reading argument descriptor table\n",
  57. X                  Cmd_Name );
  58. X         free(buf);
  59. X         cleanup();
  60. X         if ( errno )  perror( "" );
  61. X         exit( e_SYSTEM );
  62. X      }
  63. X      errno = 0;  /* errno is undefined after a succesful fread() */
  64. X      bufsiz += nchars;
  65. X
  66. X         /* see if we need to grow the buffer */
  67. X      if ( nchars == BUFFER_SIZE )
  68. X         buf = (char *)ckrealloc( buf, (bufsiz + BUFFER_SIZE) * sizeof(char) );
  69. X   } while ( nchars == BUFFER_SIZE );
  70. X
  71. X      /* shrink the buffer down to the exact size used */
  72. X   buf = (char *)ckrealloc( buf, (bufsiz + 1) * sizeof(char) );
  73. X
  74. X      /* close file if necessary */
  75. X   if ( !UseStdin )  (VOID) fclose( fp );
  76. X
  77. X   return   buf;
  78. }
  79. X
  80. X
  81. /***************************************************************************
  82. ** ^FUNCTION: get_shell_type - return shell corresponding to given string
  83. **
  84. ** ^SYNOPSIS:
  85. */
  86. #ifndef __ANSI_C__
  87. X   static shell_t get_shell_type( sh_str )
  88. /*
  89. ** ^PARAMETERS:
  90. */
  91. X   char *sh_str;
  92. /*    -- string corresponding tp the basename of a shell/command-interpreter
  93. */
  94. #endif  /* !__ANSI_C__ */
  95. X
  96. /* ^DESCRIPTION:
  97. **    Get_shell_type will retrun the shell-type for the named shell. If
  98. **    No corresponding shell is known, then an error message is printed
  99. **    and execution is terminated.
  100. **
  101. ** ^REQUIREMENTS:
  102. **    sh_str should be non-NULL and non-empty.
  103. **
  104. ** ^SIDE-EFECTS:
  105. **    None.
  106. **
  107. ** ^RETURN-VALUE:
  108. **    The corresponding shell-type.
  109. **
  110. ** ^ALGORITHM:
  111. **    Trivial.
  112. ***^^**********************************************************************/
  113. #ifdef __ANSI_C__
  114. X   static shell_t get_shell_type ( const char *sh_str )
  115. #endif
  116. {
  117. X    if      ( strEQ( sh_str, BOURNE_SHELL ) )
  118. X       return   SH;
  119. X    else if ( strEQ( sh_str, TC_SHELL ) )
  120. X       return   TCSH;
  121. X    else if ( strEQ( sh_str, C_SHELL ) )
  122. X       return   CSH;
  123. X    else if ( strEQ( sh_str, KORN_SHELL ) )
  124. X       return   KSH;
  125. X    else if ( strEQ( sh_str, BOURNE_AGAIN_SHELL ) )
  126. X       return   BASH;
  127. X    else if ( strEQ( sh_str, RC_SHELL ) )
  128. X       return   RC;
  129. X    else if ( strEQ( sh_str, AWK_LANG ) )
  130. X       return   AWK;
  131. X    else if ( strEQ( sh_str, PERL_LANG ) )
  132. X       return   PERL;
  133. X
  134. X    else {
  135. X       eprintf( "%s: Fatal Error: unknown shell '%s'\n",
  136. X                Cmd_Name, sh_str );
  137. X       eprintf( "\tKnown shells are: %s, %s, %s, %s, %s, %s, %s, and %s\n",
  138. X                AWK_LANG, BOURNE_AGAIN_SHELL, C_SHELL, KORN_SHELL, RC_SHELL,
  139. X                PERL_LANG, BOURNE_SHELL, TC_SHELL );
  140. X       cleanup();
  141. X       exit( e_SYNTAX );
  142. X    }
  143. }
  144. X
  145. X
  146. /***************************************************************************
  147. ** ^FUNCTION: build_tables - build the Argument and Value tables
  148. **
  149. ** ^SYNOPSIS:
  150. */
  151. #ifndef __ANSI_C__
  152. X   static int build_tables( argd_str )
  153. /*
  154. ** ^PARAMETERS:
  155. */
  156. X   char argd_str[];
  157. /*    -- the comma-separated table of argument descriptions
  158. */
  159. #endif  /* !__ANSI_C__ */
  160. X
  161. /* ^DESCRIPTION:
  162. **    Build_tables will read the contents of the argument-descriptor-table
  163. **    string and build the corresponding Argument and Value tables to be
  164. **    used by parseargs(3).
  165. **
  166. ** ^REQUIREMENTS:
  167. **    argd_str should be non-NULL and non-empty
  168. **
  169. ** ^SIDE-EFECTS:
  170. **    The global variables UsrVals and UsrArgd are allocated and initialized
  171. **
  172. ** ^RETURN-VALUE:
  173. **    The number of argument entries interpreted from the given string.
  174. **
  175. ** ^ALGORITHM:
  176. **    - split argd_str into a vector of tokens
  177. **    - make sure the first and last tokens are syntactically correct
  178. **    - make sure that the number of tokens is a multiple of 5 (the number
  179. **      of fields in an argument descriptor)
  180. **    - num-args = num-tokens / 5
  181. **    - allocate space for UsrVals and UsrArgd
  182. **    - i = 0
  183. **    - for every 5 tokens
  184. **      - UsrArgd[i].ad_name = token#1
  185. **      - UsrArgd[i].ad_flags = 0
  186. **      - split token#2 into a subvector of '|' separated fields
  187. **      - for each '|' separated token
  188. **        - UsrArgd[i].ad_flags |= bitmask( subfield )
  189. **        end-for
  190. **      - UsrArgd[i].ad_type = argtype( token#3 )
  191. **      - UsrVals[i].name = token#4
  192. **      - UsrArgd[i].ad_valp = &(UsrVals[i].value)
  193. **      - UsrArgd[i].ad_prompt = token#5
  194. **      - increment i by one
  195. **    end-for
  196. **    - Initialize first and last entries in UsrArgd
  197. **    - return  num-args
  198. ***^^**********************************************************************/
  199. #ifdef __ANSI_C__
  200. X   static int build_tables( char argd_str[] )
  201. #endif
  202. {
  203. X   char **token_vec, **flags_vec, *type_name;
  204. X   int   i = 0, j = 0, idx, token_num = 0, flags_num = 0;
  205. X   int   argc = 0, ad_idx;
  206. X   BOOL  start_string_used = FALSE, is_braces = FALSE;
  207. X
  208. X      /* what about NULL or empty-string */
  209. X   if ( !argd_str  ||  !*argd_str )  return  0;
  210. X
  211. X      /* escape all commas inside of single or double quotes */
  212. X   escape_char( argd_str, ',', ESCAPED_COMMA );
  213. X
  214. X      /* parse Argument Table String */
  215. X   token_num = strsplit( &token_vec, argd_str, ArgTableDelims );
  216. X   if ( token_num )  (VOID) strtrim( token_vec[ token_num - 1 ], WhiteSpace );
  217. X
  218. X      /* see if we need to build the tables at all */
  219. X   if ( token_num == 0 || isEND_ARGS(*token_vec) ) {
  220. X      free( token_vec );
  221. X      return   0;    /* nothing to parse */
  222. X   }
  223. X
  224. X      /* make sure table is properly terminated */
  225. X   if ( !isEND_ARGS( token_vec[ --token_num ] ) )  {
  226. X      restore_char( token_vec[ token_num ], ',', ESCAPED_COMMA );
  227. X      eprintf( "\
  228. %s: Fatal Error:\n\
  229. \tArgument descriptor table is not terminated with the string:\n\
  230. \t\t\"%s\"\n\
  231. \tLast entry in table is: \"%s\"\n",
  232. X               Cmd_Name, s_END_ARGS, token_vec[ token_num ] );
  233. X      free( token_vec );
  234. X      cleanup();
  235. X      exit( e_ARGD );
  236. X   }
  237. X
  238. X      /* check for optional start-string */
  239. X   (VOID) strtrim( *token_vec, WhiteSpace );
  240. X   if ( isSTART_ARGS(*token_vec) ) {
  241. X      start_string_used = TRUE;
  242. X      --token_num;
  243. X      ++token_vec;
  244. X   }
  245. X
  246. X      /* make sure table has proper number of arguments */
  247. X   if ( (token_num % NFIELDS) != 0 ) {
  248. X      eprintf( "\
  249. %s: Fatal Error:\n\
  250. \tArgument descriptor table has an invalid number of arguments\n\
  251. \tThe number of comma-separated arguments MUST be a multiple of %d\n\
  252. \t(not including terminating \"%s\")\n",
  253. X               Cmd_Name, NFIELDS, s_END_ARGS );
  254. X      free( (start_string_used) ? (token_vec - 1) : token_vec );
  255. X      cleanup();
  256. X      exit( e_ARGD );
  257. X   }
  258. X
  259. X      /* determine number of arg-descriptors and allocate arg-tables */
  260. X   argc = token_num / NFIELDS;
  261. X   UsrArgd = (ARGDESC *) ckalloc( (argc + 2) * sizeof(ARGDESC) );
  262. X   UsrVals = (cmdarg_t *) ckalloc( argc * sizeof(cmdarg_t) );
  263. X
  264. X      /* start filling in the tables */
  265. X   i = 0;
  266. X   while ( i < token_num )  {
  267. X      restore_char( token_vec[i], ',', ESCAPED_COMMA );
  268. X      (VOID) strtrim( token_vec[i], WhiteSpace );
  269. X      idx = (i / NFIELDS); /* save index into UsrVals table */
  270. X      ad_idx = (idx + 1);   /* save index into UsrArgd table */
  271. X      is_braces = FALSE;
  272. X
  273. X         /* remove first curly-brace if its present (this has the drawback
  274. X         ** of disallowing a left curly-brace from being an option character).
  275. X         */
  276. X      if ( token_vec[i][0] == c_BEGIN_STRUCT ) {
  277. X         token_vec[i][0] = ' ';
  278. X         (VOID) strltrim( token_vec[i], WhiteSpace );
  279. X         is_braces = TRUE;
  280. X      }
  281. X
  282. X         /* get argument name */
  283. X      UsrArgd[ ad_idx ].ad_name = *(token_vec[i++]);
  284. X      if ( !UsrArgd[ ad_idx ].ad_name )  UsrArgd[ ad_idx ].ad_name = ' ';
  285. X
  286. X         /*
  287. X         ** get argument flags, flags may be ORed together so I
  288. X         ** need to parse the flags for each individual flag used
  289. X         */
  290. X      UsrArgd[ ad_idx ].ad_flags = (argMask_t) 0;   /* initialize */
  291. X      flags_num = strsplit( &flags_vec, token_vec[i++] , ArgFlagsDelims );
  292. X      for ( j = 0 ; j < flags_num ; j++ ) {
  293. X            (VOID) strtrim( flags_vec[j], WhiteSpace );
  294. X            UsrArgd[ ad_idx ].ad_flags |= get_arg_flag( flags_vec[j] );
  295. X      }
  296. X      free( flags_vec );
  297. X
  298. X         /* get argument type and name for Value table */
  299. X      type_name = strtrim( token_vec[i++], WhiteSpace );
  300. X      restore_char( token_vec[i], ',', ESCAPED_COMMA );
  301. X      UsrVals[ idx ].name = strtrim( token_vec[i++], WhiteSpace );
  302. X
  303. X         /* remove any leading "__" from the name */
  304. X      if ( strnEQ("__", UsrVals[ idx ].name, 2) ) {
  305. X         (VOID) strltrim( (char *)UsrVals[idx].name, "_ \t\n\r\v\f" );
  306. X      }
  307. X
  308. X         /* remove any leading '&', '$', and '@' from the name */
  309. X      if ( strchr("&$@", UsrVals[ idx ].name[0]) ) {
  310. X         (VOID) strltrim( (char *)UsrVals[idx].name, "&$@ \t\n\r\v\f" );
  311. X      }
  312. X
  313. X         /* get type and value pointer for Arg table */
  314. X      UsrArgd[ ad_idx ].ad_type = get_arg_type( type_name );
  315. X      UsrArgd[ ad_idx ].ad_valp = __ &(UsrVals[ idx ].value);
  316. X
  317. X         /* if we have a vector we need to initialize it */
  318. X      if ( ARG_isVEC((UsrArgd + ad_idx)) )  {
  319. X         UsrVals[ idx ].value.Vector.count = 0;
  320. X         UsrVals[ idx ].value.Vector.array = (VOID *)NULL;
  321. X      }
  322. X
  323. X         /* get argument prompt/description */
  324. X      restore_char( token_vec[i], ',', ESCAPED_COMMA );
  325. X      UsrArgd[ ad_idx ].ad_prompt = strtrim( token_vec[i++], WhiteSpace );
  326. X
  327. X         /* if in curly-braces, remove the trailing brace */
  328. X      if ( is_braces ) {
  329. X        int  last = strlen( UsrArgd[ad_idx].ad_prompt ) - 1;
  330. X        if ( UsrArgd[ ad_idx ].ad_prompt[ last ] == c_END_STRUCT ) {
  331. X           *((char *)(UsrArgd[ ad_idx ].ad_prompt) + last) = '\0';
  332. X           (VOID) strrtrim( (char *)UsrArgd[ad_idx].ad_prompt, WhiteSpace );
  333. X        }
  334. X      }/*end-if*/
  335. X   }/*while*/
  336. X
  337. X      /* free up token tables (just the arrays, not the actual elements) */
  338. X   free( flags_vec );
  339. X   free( (start_string_used) ? (token_vec - 1) : token_vec );
  340. X
  341. X      /* set up first & last argument entries */
  342. X   (UsrArgd -> ad_name)    =   UsrArgd[ argc+1 ].ad_name    = '\0';
  343. X   (UsrArgd -> ad_flags)   =   UsrArgd[ argc+1 ].ad_flags   = (argMask_t) 0;
  344. X   (UsrArgd -> ad_type)    =   UsrArgd[ argc+1 ].ad_type    = argNULL;
  345. X   (UsrArgd -> ad_valp)    =   UsrArgd[ argc+1 ].ad_valp    = ARBNULL;
  346. X   UsrArgd[ argc+1 ].ad_prompt = CHARNULL;
  347. X
  348. X      /* try to get a command-description */
  349. X   cmd_description(UsrArgd) = getenv( "DESCRIPTION" );
  350. X   if ( !cmd_description(UsrArgd) ) {
  351. X      cmd_description(UsrArgd) = getenv( "CMD_DESCRIPTION" );
  352. X   }
  353. X
  354. X   return  argc;
  355. }
  356. X
  357. X
  358. /***************************************************************************
  359. ** ^FUNCTION: put_char_arg - print a character
  360. **
  361. ** ^SYNOPSIS:
  362. */
  363. #ifndef __ANSI_C__
  364. X   static put_char_arg( fp, ch )
  365. /*
  366. ** ^PARAMETERS:
  367. */
  368. X   FILE *fp;
  369. /*    -- the output stream to write to.
  370. */
  371. X   int ch;
  372. /*    -- the character to print
  373. */
  374. #endif  /* !__ANSI_C__ */
  375. X
  376. /* ^DESCRIPTION:
  377. **    Put_char_arg will write the given character on the specified output
  378. **    stream. If the character is metacharacter for the current shell, then
  379. **    it is "escaped" according to the given shell syntax.
  380. **
  381. ** ^REQUIREMENTS:
  382. **    <fp> should be non-NULL and open for writing.
  383. **    <ch> should be a printable character.
  384. **
  385. ** ^SIDE-EFECTS:
  386. **    output is written to <fp>.
  387. **
  388. ** ^RETURN-VALUE:
  389. **    None.
  390. **
  391. ** ^ALGORITHM:
  392. **    print a character argument on standard output
  393. **    and make sure we preserve the evaluation of
  394. **    any special characters such as: double-quotes,
  395. **    back-quotes, back-slash, dollar-signs, etc ....
  396. ***^^**********************************************************************/
  397. #ifdef __ANSI_C__
  398. X   static void put_char_arg( FILE *fp, int ch )
  399. #endif
  400. {
  401. X      /* newline needs to be escaped specially for CSH, TCSH, and PERL */
  402. X   if ( ch == '\n' ) {
  403. X      if ( UsrSh == CSH   || UsrSh == TCSH ) {
  404. X         fprintf( fp, "\\\n" );
  405. X         return;
  406. X      }
  407. X      else if ( UsrSh == PERL ) {
  408. X         fprintf( fp, "\\n" );
  409. X         return;
  410. X      }
  411. X   }/*if newline*/
  412. X
  413. X   if ( strchr( Shell[ UsrSh ].metachars, ch ) ) {
  414. X      fprintf( fp, Shell[ UsrSh ].escape, ch );
  415. X   }
  416. X   else {
  417. X      fputc( ch, fp );
  418. X   }
  419. }
  420. X
  421. X
  422. /***************************************************************************
  423. ** ^FUNCTION: put_str_arg - same as put_char_arg but for a string!
  424. **
  425. ** ^SYNOPSIS:
  426. */
  427. #ifndef __ANSI_C__
  428. X   static VOID put_str_arg( fp, str )
  429. /*
  430. ** ^PARAMETERS:
  431. */
  432. X   FILE *fp;
  433. /*    -- the output stream to write to
  434. */
  435. X   char str[];
  436. /*    -- the string to print
  437. */
  438. #endif  /* !__ANSI_C__ */
  439. X
  440. /* ^DESCRIPTION:
  441. **    Put_str_arg will print the given string to the given output stream
  442. **    and will escape any shell meta-characters for the current shell.
  443. **
  444. ** ^REQUIREMENTS:
  445. **    <fp> should be non-NULL and open for writing.
  446. **    <str> should be non-NULL and non-empty.
  447. **
  448. ** ^SIDE-EFECTS:
  449. **    Output is written to <fp>
  450. **
  451. ** ^RETURN-VALUE:
  452. **    None.
  453. **
  454. ** ^ALGORITHM:
  455. **    - foreach character in str
  456. **     - put_char_arg(fp, character)
  457. **    end-for
  458. ***^^**********************************************************************/
  459. #ifdef __ANSI_C__
  460. X   static void put_str_arg( FILE *fp, const char str[] )
  461. #endif
  462. {
  463. X   if ( !str )   return;
  464. X
  465. X   for ( ; *str ; str++ )
  466. X      put_char_arg( fp, *str );
  467. }
  468. X
  469. X
  470. /***************************************************************************
  471. ** ^FUNCTION: put_arg - convert & print the given value into the given buffer
  472. **
  473. ** ^SYNOPSIS:
  474. */
  475. #ifndef __ANSI_C__
  476. X   static VOID put_arg( fp, ad, val, idx )
  477. /*
  478. ** ^PARAMETERS:
  479. */
  480. X   FILE *fp;
  481. /*    -- the output stream to write to
  482. */
  483. X   ARGDESC *ad;
  484. /*    -- the argument-descriptor of the argument to print.
  485. */
  486. X   cmdarg_t *val;
  487. /*    -- the value of the argument to print
  488. */
  489. X   short idx;
  490. /*    -- the index in the argument-vector of the item to be printed
  491. **       (only used when ad corresponds to an ARGVEC argument).
  492. */
  493. #endif  /* !__ANSI_C__ */
  494. X
  495. /* ^DESCRIPTION:
  496. **    Put_arg will print the given variable/array setting on the given
  497. **    output stream using the syntax of the user-sepcified shell.
  498. **
  499. ** ^REQUIREMENTS:
  500. **    <val> should be the value corresponing to the argument-descriptor <ad>
  501. **
  502. ** ^SIDE-EFECTS:
  503. **    Output is written to <fp>.
  504. **
  505. ** ^RETURN-VALUE:
  506. **    None.
  507. **
  508. ** ^ALGORITHM:
  509. **    - if we have a vector, make sure we were given a valid index.
  510. **    - if we have a vector, then value=val.vec[idx],
  511. **      else value = val.value
  512. **    - print the beginning of the variable setting
  513. **    - case (argument-type) of
  514. **        INTEGRAL-TYPE: print the integer value
  515. **        DECIMAL-TYPE: print the floating point value
  516. **        CHARACTER: print the character value and escape it if necessary
  517. **        STRING: print the string value and escape it if necessary
  518. **        BOOLEAN: print the string StrTrue if value is TRUE
  519. **                 print the string StrFalse if value is FALSE
  520. **    - print the end of the variable setting
  521. ***^^**********************************************************************/
  522. #ifdef __ANSI_C__
  523. X   static void put_arg(
  524. X      FILE *fp, const ARGDESC *ad, const cmdarg_t *val, short idx
  525. X   )
  526. #endif
  527. {
  528. X   if ( ARG_isVEC(ad) ) {
  529. X      if ( idx < 0  ||  idx >= val->value.Vector.count ) {
  530. X         return;   /* bad index given */
  531. X      }
  532. X
  533. X      if ( arg_type(ad) == argStr ) {
  534. X         if ( UsrSh == PERL )  fputc( '\'', fp );
  535. X         put_str_arg( fp, val->value.Str_vec.array[idx] );
  536. X         if ( UsrSh == PERL )  fputc( '\'', fp );
  537. X      }
  538. X      else if ( arg_type(ad) == argChar ) {
  539. X         if ( UsrSh == PERL )  fputc( '\'', fp );
  540. X         put_char_arg( fp, val->value.Char_vec.array[idx] );
  541. X         if ( UsrSh == PERL )  fputc( '\'', fp );
  542. X      }
  543. X      else if ( arg_type(ad) == argDouble ) {
  544. X         fprintf( fp, "%lf", val->value.Double_vec.array[idx] );
  545. X      }
  546. X      else if ( arg_type(ad) == argFloat ) {
  547. X         fprintf( fp, "%f", val->value.Float_vec.array[idx] );
  548. X      }
  549. X      else if ( arg_type(ad) == argLong ) {
  550. X         fprintf( fp, "%ld", val->value.Long_vec.array[idx] );
  551. X      }
  552. X      else if ( arg_type(ad) == argInt ) {
  553. X         fprintf( fp, "%d", val->value.Int_vec.array[idx] );
  554. X      }
  555. X      else if ( arg_type(ad) == argShort ) {
  556. X         fprintf( fp, "%ld", val->value.Short_vec.array[idx] );
  557. X      }
  558. X
  559. X      /* Boolean vectors are not supported */
  560. X   }/*if vector*/
  561. X   else {
  562. X      if ( arg_type(ad) == argStr ) {
  563. X         put_str_arg( fp, val->value.Str_val );
  564. X      }
  565. X      else if ( arg_type(ad) == argChar ) {
  566. X         put_char_arg( fp, val->value.Char_val );
  567. X      }
  568. X      else if ( arg_type(ad) == argDouble ) {
  569. X         fprintf( fp, "%lf", val->value.Double_val );
  570. X      }
  571. X      else if ( arg_type(ad) == argFloat ) {
  572. X         fprintf( fp, "%f", val->value.Float_val );
  573. X      }
  574. X      else if ( arg_type(ad) == argLong ) {
  575. X         fprintf( fp, "%ld", val->value.Long_val );
  576. X      }
  577. X      else if ( arg_type(ad) == argInt ) {
  578. X         fprintf( fp, "%d", val->value.Int_val );
  579. X      }
  580. X      else if ( arg_type(ad) == argShort ) {
  581. X         fprintf( fp, "%ld", val->value.Short_val );
  582. X      }
  583. X      else if ( ARG_isBOOLEAN(ad) ) {
  584. X         fprintf( fp, "%s", (val->value.Bool_val) ? StrTrue : StrFalse );
  585. X      }
  586. X   }/*else !vector*/
  587. }
  588. X
  589. X
  590. /***************************************************************************
  591. ** ^FUNCTION: print_argvector - print shell variable settings for an ARGVEC
  592. **
  593. ** ^SYNOPSIS:
  594. */
  595. #ifndef __ANSI_C__
  596. X   static VOID print_argvector( ad, val )
  597. /*
  598. ** ^PARAMETERS:
  599. */
  600. X   ARGDESC *ad;
  601. /*    -- the argument-descriptor of the vector to print
  602. */
  603. X   cmdarg_t *val;
  604. /*    -- the value of the vector to print
  605. */
  606. #endif  /* !__ANSI_C__ */
  607. X
  608. /* ^DESCRIPTION:
  609. **    Parseargs treats ARGLIST and ARGVEC arguments in a special way. The
  610. **    method used for setting up an argument list depends largely upon the
  611. **    syntax of shell that was specified on the command line via the -s option
  612. **    (although an ARGLIST argument is treated the same as an ARGVEC argument).
  613. **
  614. ** ^Resetting_the_Positional_Parameters_to_an_Argument_List:
  615. **    For the Bourne, Bourne-Again, and Korn shells, if the variable name
  616. **    corresponding to the ARGLIST argument is "--", then the positional
  617. **    parameters of the calling program will be re-assigned to the contents
  618. **    of the argument list ($1 will be the first item, $2 the second item,
  619. **    and so on). In this particular case, the calling program may wish to
  620. **    use the -u option to reset the positional parameters to NULL before
  621. **    making any shell-variable assignments (this way, the positional
  622. **    parameters will be unset if the associated list of command line
  623. **    arguments is not encountered).
  624. **
  625. **    Similarly for the C and TC shells, if the variable name corresponding
  626. **    to the ARGLIST argument is "argv", then the positional parameters
  627. **    of the calling program will be re-assigned to the contents of the
  628. **    argument list.
  629. **
  630. **    For the Plan 9 shell (rc), if the variable name corresponding to the
  631. **    ARGLIST argument is "*", then the positional parameters of the calling
  632. **    program will be re-assigned to the contents of the argument list.
  633. **
  634. **    For awk and perl, if the variable name corresponding to the ARGLIST
  635. **    argument is "ARGV", then the positional parameters of the calling
  636. **    program will be re-assigned to the contents of the argument list.
  637. **
  638. ** ^Bourne_Shell_Argument_Lists:
  639. **    For the Bourne shell, if the associated variable name is NOT "--"
  640. **    and the -A option was NOT specified, then that variable is treated as
  641. **    a regular shell variable and is assigned using the following syntax:
  642. **
  643. **         name='arg1 arg2  ...'
  644. **
  645. **    After invoking parseargs, if you wish to go through all the words in
  646. **    the variable name and one of the words in name contains an IFS charac-
  647. **    ter (such as a space or a tab), then that particular word will be
  648. **    treated by the Bourne shell as two distinct words.
  649. **
  650. **    Also for the Bourne shell, If the associated variable name is NOT
  651. **    "--" and the -A option WAS specified, then that variable is treated
  652. **    as the root name of an array that is set using the following syntax:
  653. **
  654. **         name1='arg1'
  655. **         name2='arg2'
  656. **             ...
  657. **
  658. **    and the variable "name_count" will be set to contain the number of
  659. **    items in the array.  The user may then step through all the items in
  660. **    the array using the following syntax:
  661. **
  662. **         i=1
  663. **         while [ $i -le $name_count ] ; do
  664. **           eval echo "item #$i is: " \$name$i
  665. **           i=`expr $i + 1`
  666. **         done
  667. **
  668. ** ^Korn_Shell_Argument_Lists:
  669. **    For the Korn shell, if the associated variable name is NOT "--",
  670. **    then that variable is treated as an array and is assigned using the -A
  671. **    option of the set command. The first item will be in ${name[0]}, the
  672. **    second item will be in ${name[1]}, etc ..., and all items may be given
  673. **    by ${name[*]} or ${name[@]}.  If the associated variable name is NOT
  674. **    "--" and the -A option WAS specified, then that variable is assigned
  675. **    using the +A option of the set command (which preserves any array
  676. **    elements that were not overwritten by the set command).
  677. **
  678. **    It should be noted that there is a bug in versions of the Korn shell
  679. **    earlier than 11/16/88a, in which the following:
  680. **
  681. **         set  -A  name  'arg1'  'arg2'  ...
  682. **
  683. **    causes the positional parameters to be overwritten as an unintentional
  684. **    side-effect. If your version of the Korn shell is earlier than this
  685. **    and you wish to keep the contents of your positional parameters after
  686. **    invoking parseargs than you must save them yourself before you call
  687. **    parseargs. This may be accomplished by the following:
  688. **
  689. **         set  -A  save_parms  "$@"
  690. **
  691. ** ^C_and_TC_Shell_Argument_Lists:
  692. **    For the C and TC shells, ARGLIST variables are treated as word-lists
  693. **    and are assigned using the following syntax:
  694. **
  695. **         set  name = ( 'arg1'  'arg2'  ... )
  696. **
  697. **    The first item will be in $name[1], the second item will be in
  698. **    $name[2], etc ..., and all items may be given by $name.  Notice that
  699. **    Korn shell arrays start at index zero whereas C and TC shell word-
  700. **    lists start at index one.
  701. **
  702. ** ^Bourne-Again_Shell_Argument_Lists:
  703. **    At present, the Free Software Foundation's Bourne-Again shell is
  704. **    treated exactly the same as the Bourne Shell. This will change when
  705. **    bash supports arrays.
  706. **
  707. ** ^Plan_9_Shell_Argument_Lists:
  708. **    For the Plan 9 shell, if the associated variable name is not "*" then
  709. **    it is considered to be word-list and set using the following syntax:
  710. **
  711. **         name=( 'arg1'  'arg2'  ... )
  712. **
  713. ** ^Awk_Argument_Lists:
  714. **    For awk, if the -A option is not given, then the output for thes
  715. **    variable-list will be a line with the variable name, followed by a
  716. **    line with each of the values (each value will be separated with the
  717. **    field separator specified using the -S option - which defaults to a
  718. **    space character):
  719. **
  720. **         name
  721. **         arg1  arg2  ...
  722. **
  723. **    If the -A option is given, then the associated variable is considered
  724. **    the root name of an array. The ouput for the array will consist of two
  725. **    lines for each item in the list (as in the following expample):
  726. **
  727. **         name1
  728. **         arg1
  729. **
  730. **         name2
  731. **         arg2
  732. **
  733. **    and the variable "name_count" will have an output line showing the
  734. **    number of items in the array.
  735. **
  736. ** ^Perl_Argument_Lists:
  737. **    For perl, each argument list is considered an array and is set using
  738. **    the following syntax:
  739. **
  740. **         @name=( arg1 , arg2 ,  ... )
  741. **
  742. ** ^A_Final_Note_on_Argument_Lists:
  743. **    The word-lists used by the C shell, the arrays used by the Korn shell,
  744. **    The Plan 9 shell, awk, & perl, and the positional parameters used by
  745. **    all shells (if overwritten by parseargs) will preserve any IFS
  746. **    characters in their contents.  That us to say that if an item in one
  747. **    of the aforementioned multi-word lists contains any IFS characters,
  748. **    it will not be split up into multiple items but will remain a single
  749. **    item which contains IFS characters.
  750. **
  751. ** ^REQUIREMENTS:
  752. **    <val> should correspond to the vlue of the argument indicated by <ad>
  753. **
  754. ** ^SIDE-EFECTS:
  755. **    prints the array assignment statement on standard output
  756. **
  757. ** ^RETURN-VALUE:
  758. **    None.
  759. **
  760. ** ^ALGORITHM:
  761. **    - print the beginning of the array assigment statement
  762. **    - print each item in the array (escaping characters where needed)
  763. **    - print the end of the array assignment statement
  764. ***^^**********************************************************************/
  765. #ifdef __ANSI_C__
  766. X   static void print_argvector( const ARGDESC *ad, const cmdarg_t *val )
  767. #endif
  768. {
  769. X   BOOL   is_array = TRUE;
  770. X   int    i;
  771. X   char   *varname;
  772. X
  773. X   switch( UsrSh ) {
  774. X      case KSH :
  775. X         if ( strEQ( val->name, Shell[ UsrSh ].varname ) ) {
  776. X            fputs( "set -- ", stdout );
  777. X         }
  778. X         else {
  779. X            printf( "set %cA %s ", ((ModArr) ? '+' : '-'), val->name );
  780. X         }
  781. X         break;
  782. X
  783. X      case TCSH : case CSH : case RC: case PERL :
  784. X         if ( UsrSh == PERL )
  785. X            printf( "@%s = ", val->name );
  786. X         else if ( UsrSh == RC )
  787. X            printf( "%s=", val->name );
  788. X         else /* UsrSh == CSH/TCSH */
  789. X            printf( "set %s=", val->name );
  790. X         fputc( '(', stdout );
  791. X         break;
  792. X
  793. X      case BASH: case SH : case AWK:
  794. X         if ( UsrSh == AWK )  is_array = FALSE;
  795. X         if ( strEQ( val->name, Shell[ UsrSh ].varname ) ) {
  796. X            fputs( ((UsrSh == AWK) ? "ARGV\n" : "set -- "), stdout );
  797. X         }
  798. X         else {
  799. X            if ( ModArr )   { /* use fake array syntax */
  800. X               i = strlen( val->name );
  801. X               varname = (char *)ckalloc( (i + 4) * sizeof(char) );
  802. X               for ( i = 0 ; i < val->value.Vector.count ; i++ ) {
  803. X                  sprintf( varname, "%s%d", val->name, i+1 );
  804. X                  printf( Shell[ UsrSh ].setcmd, varname );
  805. X                  printf( Shell[ UsrSh ].prefix );
  806. X                  put_arg( stdout, ad, val, i );
  807. X                  printf( "%s", Shell[ UsrSh ].suffix );
  808. X               }
  809. X               sprintf( varname, "%s_count", val->name );
  810. X               printf( Shell[ UsrSh ].setcmd, varname );
  811. X               printf( Shell[ UsrSh ].prefix );
  812. X               printf( "%d", val->value.Vector.count );
  813. X               printf( "%s", Shell[ UsrSh ].suffix );
  814. X               free( varname );
  815. X               if ( val->value.Vector.array ) {
  816. X                  free( val->value.Vector.array );
  817. X                  val->value.Vector.array = NULL;
  818. X               }
  819. X               return;
  820. X            }/*if ModArr*/
  821. X            else {
  822. X               is_array = FALSE;
  823. X               printf( Shell[ UsrSh ].setcmd, val->name );
  824. X               printf( Shell[ UsrSh ].prefix );
  825. X            }
  826. X         }/*else !positional-parms*/
  827. X         break;
  828. X
  829. X   }/*switch*/
  830. X
  831. X   for ( i = 0 ; i < val->value.Vector.count ; i++ ) {
  832. X      if ( is_array )  printf( Shell[ UsrSh ].prefix );
  833. X      put_arg( stdout, ad, val, i );
  834. X      if ( is_array )  printf( Shell[ UsrSh ].prefix );
  835. X      if ( i != (val->value.Vector.count - 1) ) {
  836. X         fputs( ((UsrSh == PERL) ? ", " : FieldSep), stdout );
  837. X      }
  838. X   }/* end-for */
  839. X
  840. X   if ( val->value.Vector.array ) {
  841. X      free( val->value.Vector.array );
  842. X      val->value.Vector.array = NULL;
  843. X   }
  844. X
  845. X   if ( UsrSh == CSH  ||  UsrSh == TCSH  || UsrSh == RC  ||  UsrSh == PERL ) {
  846. X     fputc( ')', stdout );
  847. X   }
  848. X
  849. X   fputs( ((! is_array) ? Shell[ UsrSh ].suffix : ";\n"), stdout );
  850. }
  851. X
  852. X
  853. /***************************************************************************
  854. ** ^FUNCTION: print_args - print the shell variable settings for the usr args
  855. **
  856. ** ^SYNOPSIS:
  857. */
  858. #ifndef __ANSI_C__
  859. X   static VOID print_args( vals, argd )
  860. /*
  861. ** ^PARAMETERS:
  862. */
  863. X   cmdarg_t *vals;
  864. /*    -- the table of argument values.
  865. */
  866. X   ARGDESC *argd;
  867. /*    -- the table of argument-descriptors.
  868. */
  869. #endif  /* !__ANSI_C__ */
  870. X
  871. /* ^DESCRIPTION:
  872. **    Print_args prints the actual shell variable assignment statement(s) for
  873. **    each argument found on the command line. If a command-line argument was
  874. **    specified withch may take an optional value, then regargdless of whether
  875. **    or not the optional value was supplied, the variable <name>_flag is set 
  876. **    to the value indicated by StrTrue.
  877. **
  878. ** ^REQUIREMENTS:
  879. **    The argument values have already been set due to the fact that parseargs
  880. **    should already have been invoked to parse the command-line
  881. **
  882. ** ^SIDE-EFECTS:
  883. **    Variable assignment statements are printed on standard output.
  884. **
  885. ** ^RETURN-VALUE:
  886. **    None.
  887. **
  888. ** ^ALGORITHM:
  889. **    - for each argument in the argument table
  890. **      - if this argument was supplied on the command-line
  891. **        - if the argument takes an optional value
  892. **            then set argname_flag = TRUE
  893. **        - if the argument is a vector
  894. **          - call print_argvector to print the vector elements
  895. **        - else
  896. **          - print the beginning of the variable assignment statement for 
  897. **            the shell indicated by UsrSh
  898. **          - print the argument value using put_arg
  899. **          - print the end of the variable assignment statement for the shell
  900. **            indicated by UsrSh
  901. **        end-if vector
  902. **      end-if supplied
  903. **    end-for
  904. ***^^**********************************************************************/
  905. #ifdef __ANSI_C__
  906. X   static void print_args( const cmdarg_t *vals, const ARGDESC *argd )
  907. #endif
  908. {
  909. X   register CONST  ARGDESC *ad;
  910. X   register  int i;
  911. X   argName_t  buf;
  912. X
  913. X      /* print values for all options given */
  914. X   for ( ad = ARG_FIRST(argd), i = 0 ; !ARG_isEND(ad) ; ARG_ADVANCE(ad), i++ ) {
  915. X      if ( ARG_isGIVEN(ad) ) {
  916. X         /******************************************************************
  917. X         ** ^SECTION: ARGVALOPT
  918. X         **    Options that may take an optional argument need special
  919. X         **    consideration.  The shell programmer needs to know whether
  920. X         **    or not the option was given, and (if given) if it was
  921. X         **    accompanied by an argument. In order to accommodate this
  922. X         **    need, parseargs will set an additional shell variable for
  923. X         **    each argument that is given the ARGVALOPT flag if it is
  924. X         **    supplied on the command line regardless of whether or not
  925. X         **    it was accompanied by its optional argument.  If the user
  926. X         **    has defined an option which may optionally take an argument 
  927. X         **    and the option appears on the command line with or without
  928. X         **    its associated argument, then the shell variable <name>_flag
  929. X         **    will be assigned the value "TRUE" (or the value supplied with
  930. X         **    the -T option to parseargs) where <name> is the name of the
  931. X         **    shell variable associated with the option in the argument
  932. X         **    description string.
  933. X         ***^^*************************************************************/
  934. X         if ( ARG_isVALOPTIONAL(ad) ) {
  935. X            sprintf(buf, "%s_flag", vals[i].name);
  936. X            printf( Shell[ UsrSh ].setcmd, buf);
  937. X            printf( Shell[ UsrSh ].prefix );
  938. X            printf( "%s%s", StrTrue, Shell[ UsrSh ].suffix );
  939. X
  940. X            if ( !ARG_isVALGIVEN(ad) )  continue;
  941. X         }/*if OPTARG*/
  942. X
  943. X            /* vectors are special */
  944. X         if ( ARG_isVEC(ad) ) {
  945. X            print_argvector( ad, (vals + i) );
  946. X            continue;
  947. X         }
  948. X
  949. X            /* print shell-specific variable prefix and name */
  950. X         printf( Shell[ UsrSh ].setcmd, vals[i].name );
  951. X         printf( Shell[ UsrSh ].prefix );
  952. X
  953. X            /* print shell-variable value */
  954. X         put_arg( stdout, ad, (vals + i), 0 );
  955. X
  956. X            /* print the shell-specific suffix */
  957. X         printf( "%s", Shell[ UsrSh ].suffix );
  958. X      }/*if ARGGIVEN*/
  959. X   }/* end-for */
  960. }
  961. X
  962. X
  963. /***************************************************************************
  964. ** ^FUNCTION: unset_positional_parameters - unset shell parameters
  965. **
  966. ** ^SYNOPSIS:
  967. */
  968. #ifndef __ANSI_C__
  969. X   static void unset_positional_parameters()
  970. #endif
  971. /*
  972. ** ^PARAMETERS:
  973. **    None.
  974. **
  975. ** ^DESCRIPTION:
  976. **    Unset_positional_parameters will print (on standard output) the
  977. **    shell commands to unset the positional parameters of the invoking
  978. **    shell_script.
  979. **
  980. ** ^REQUIREMENTS:
  981. **    The currenty shell-type has already been determined.
  982. **
  983. ** ^SIDE-EFECTS:
  984. **    Prints on stdout.
  985. **
  986. ** ^RETURN-VALUE:
  987. **    None.
  988. **
  989. ** ^ALGORITHM:
  990. **    - Use the syntax of the current shell to unset the positional parameters
  991. ***^^**********************************************************************/
  992. #ifdef __ANSI_C__
  993. X   static void unset_positional_parameters( void )
  994. #endif
  995. {
  996. X   switch( UsrSh ) {
  997. X      case TCSH: case CSH:
  998. X         printf( "set argv=();\n" );
  999. X         break;
  1000. X
  1001. X      case PERL:
  1002. X         printf( "@ARGV = ();\n" );
  1003. X         break;
  1004. X
  1005. X      case KSH:
  1006. X         printf( "set --;\n" );
  1007. X         break;
  1008. X
  1009. X      case BASH: case SH:
  1010. X         printf( "shift $#;\n" );
  1011. X         break;
  1012. X
  1013. X      case RC:
  1014. X         printf( "*=();\n" );
  1015. X         break;
  1016. X
  1017. X      case AWK:
  1018. X         printf( "%s%s", Shell[ UsrSh ].varname, Shell[ UsrSh ].suffix );
  1019. X         break;
  1020. X
  1021. X      default:
  1022. X         break;
  1023. X   }/*switch*/
  1024. }
  1025. X
  1026. X
  1027. /***************************************************************************
  1028. ** ^FUNCTION: ck_cmd_errs - check for command syntax errors
  1029. **
  1030. ** ^SYNOPSIS:
  1031. */
  1032. #ifndef __ANSI_C__
  1033. X   static int ck_cmd_errs()
  1034. #endif
  1035. /*
  1036. ** ^PARAMETERS:
  1037. **    None.
  1038. **
  1039. ** ^DESCRIPTION:
  1040. **    Ck_cmd_errs will check for the improper specification of arguments
  1041. **    from the command-line.
  1042. **
  1043. ** ^REQUIREMENTS:
  1044. **    The command-line should already have been parsed by parseargs(3)
  1045. **
  1046. ** ^SIDE-EFECTS:
  1047. **    - Exits the program if an error is encountered.
  1048. **    - Assigns any needed defaults for StrTrue and StrFalse.
  1049. **    - Gets the argd-string from an environment variable if needed
  1050. **      (or sets UseStdin if it is to be read from standard input)
  1051. **    - Determines the shell specified by the user (default=Bourne)
  1052. **
  1053. ** ^RETURN-VALUE:
  1054. **    e_SUCCESS if everything checks out all right
  1055. **    Exits with one of the following exit-codes upon failure:
  1056. **
  1057. **      e_SYNTAX : command-line sytntax error
  1058. **
  1059. **      e_NOENV : AN environment variable was "purported" to contain the
  1060. **                description string that describes all the arguments but
  1061. **                upon examination, the variable was unset or empty.
  1062. **
  1063. ** ^ALGORITHM:
  1064. **    - make sure only one of '-a', '-e', and '-f' was given
  1065. **    - turn OFF UseStdin if any of the above were given
  1066. **    - make sure only one of '-l' and '-o' was given
  1067. **    - if '-e' was specified, read the environment-variable and
  1068. **      make sure it is non-NULL and non-empty
  1069. **    - assign default values for StrTrue and StrFalse if they were not
  1070. **      supplied on the command-line
  1071. **    - determine the type of the user's shell
  1072. **    - return
  1073. ***^^**********************************************************************/
  1074. #ifdef __ANSI_C__
  1075. X   static int ck_cmd_errs( void )
  1076. #endif
  1077. {
  1078. X      /* make sure certain arg-combos were NOT used */
  1079. X   if ( (ArgdString && (ArgdFname || ArgdEnv)) || (ArgdFname && ArgdEnv) )  {
  1080. X      eprintf( "%s: only one of `-a', `-e', or `-f' may be given.\n\n",
  1081. X               Cmd_Name );
  1082. X      usage( Args );
  1083. X      exit( e_SYNTAX );
  1084. X   }
  1085. X
  1086. X      /* make sure at least ONE of KeyWords and Options are enabled */
  1087. X   if ( OptsOnly  &&  KwdsOnly ) {
  1088. X      eprintf( "%s: only one of `-o' or `l' may be given.\n\n",
  1089. X               Cmd_Name );
  1090. X      exit( e_SYNTAX );
  1091. X   }
  1092. X
  1093. X      /* turn OFF UseStdin if `-a', `-e', or `-f' was given */
  1094. X   if (ArgdString || ArgdEnv || ArgdFname)
  1095. X      UseStdin = FALSE;
  1096. X
  1097. X      /* get the argd-string from an environment variable if so specified */
  1098. X   if ( ArgdEnv ) {
  1099. X      ArgdString = getenv( ArgdEnv );
  1100. X      if ( !ArgdString   ||   !*ArgdString ) {
  1101. X         eprintf( "%s: variable \"%s\" is NULL or does not exist\n",
  1102. X                  Cmd_Name, ArgdEnv);
  1103. X         exit( e_NOENV );
  1104. X      }
  1105. X   }
  1106. X
  1107. X      /* set up default boolean value strings if needed */
  1108. X   if ( !StrTrue ) {
  1109. X      StrTrue  = (char *)Default_StrTrue;
  1110. X   }
  1111. X   if ( !StrFalse ) {
  1112. X      StrFalse = (char *)Default_StrFalse;
  1113. X   }
  1114. X
  1115. X      /* see if we need to "default" the shell name */
  1116. X   if ( !PrUsage   &&   !PrManual ) {
  1117. X      if ( !ShellName ) {
  1118. X         UsrSh = SH;   /* default to Bourne Shell */
  1119. X      }
  1120. X      else {
  1121. X         UsrSh = get_shell_type( basename( ShellName ) );
  1122. X      }
  1123. X   }
  1124. X
  1125. X      /* everything is a-ok */
  1126. X   return   e_SUCCESS;
  1127. } /* ck_cmd_errs */
  1128. X
  1129. X
  1130. /***************************************************************************
  1131. ** ^FUNCTION: main
  1132. **
  1133. ** ^SYNOPSIS:
  1134. **    main( argc, argv )
  1135. **
  1136. ** ^PARAMETERS:
  1137. **    int argc;
  1138. **    -- the number of argumenst on the command-line
  1139. **
  1140. **    char *argv[];
  1141. **    -- the NULL terminated vector of arguments from the command-line
  1142. **       (the first of which is the name of the paraseargs(1) command).
  1143. **
  1144. ** ^DESCRIPTION:
  1145. **    This is the main program for parseargs(1). It parses the user's command-
  1146. **    line and outputs the approriate variable assignment statements (or prints
  1147. **    a usage message or manual template).
  1148. **
  1149. ** ^REQUIREMENTS:
  1150. **    All the static local variables that are used to define the argument
  1151. **    table and the values it points to (for parseargs(1) not for the user's
  1152. **    command) should be properly initialized).
  1153. **
  1154. ** ^SIDE-EFFECTS:
  1155. **    Shell variable assignment statements, A usage message, or a manual
  1156. **    page template is printed on standard output. Any diagnostic messages
  1157. **    are printed on standard error.
  1158. **
  1159. ** ^RETURN-VALUE:
  1160. **    Execution is terminated and the corresponding exit-code is returned
  1161. **    to the calling progarm (see the RETURN-CODES section).
  1162. **
  1163. ** ^ALGORITHM:
  1164. **    - save the name of this program
  1165. **    - parse the command-line
  1166. **    - read the argument descriptor string into memory (if needed)
  1167. **    - build the argument and value tables
  1168. **    - set ProgName to the name of the user's program
  1169. **    - if need to print usage, then do so and exit with status e_USAGE
  1170. **    - if need to print manual template, then do so, exit-status=e_USAGE
  1171. **    - modify parsing-behavior as specified on the command-line
  1172. **    - parse the user's command-line arguments
  1173. **    - unset the positional parameters if required
  1174. **    - print thye resulting shell variable assignments
  1175. **    - deallocate any remaining storage
  1176. **    - exit, status=e_SUCCESS
  1177. ***^^**********************************************************************/
  1178. MAIN( argc, argv )
  1179. {
  1180. X   int  rc;
  1181. X   argMask_t   flags = pa_ARGV0;
  1182. X
  1183. X   Cmd_Name = *argv = basename( *argv );
  1184. X
  1185. X      /* parse command-line */
  1186. X   parseargs( argv, Args );
  1187. X
  1188. X      /* see if there is any reason to exit now */
  1189. X   (VOID) ck_cmd_errs();
  1190. X
  1191. X      /* set desired option-syntax */
  1192. X   if ( KwdsOnly )   BSET(flags, pa_KWDSONLY);
  1193. X   if ( OptsOnly )   BSET(flags, pa_OPTSONLY);
  1194. X
  1195. X      /* if needed - allocate and read in the argument descriptor string */
  1196. X   if ( !ArgdString ) {
  1197. X      ArgdString = get_argtable_string();
  1198. X      if ( ArgdString ) {
  1199. X         strrtrim( ArgdString, WhiteSpace );
  1200. X         if ( !*ArgdString )   ArgdString = CHARNULL;
  1201. X      }
  1202. X   }
  1203. X
  1204. X      /* fill in the argument tables from the environment variable */
  1205. X   if ( ArgdString )   UsrArgc = build_tables( ArgdString );
  1206. X
  1207. X      /* if no arguments or options taken, use NULL */
  1208. X   if ( !UsrArgc )   UsrArgd = ARGDESCNULL;
  1209. X
  1210. X   ProgName = UsrName;      /* set up program name */
  1211. X
  1212. X   if ( PrUsage ) {   /* just print usage and exit */
  1213. X      usage( UsrArgd );
  1214. X   }
  1215. X   else if ( PrManual ) { /* print man pages and exit */
  1216. X      manpage( UsrArgd );
  1217. X   }
  1218. X   else {   /* parse callers command-line & print variable settings */
  1219. X      if ( Prompt )  BSET(flags, pa_PROMPT);
  1220. X      if ( Ignore )  BSET(flags, pa_IGNORE);
  1221. X      if ( flags )  (VOID) parsecntl( UsrArgd, pc_PARSEFLAGS, pc_WRITE, flags );
  1222. X
  1223. X      if ( (rc = parseargs( UsrArgv.array, UsrArgd )) != 0 ) {
  1224. X         if ( rc > 0 ) {
  1225. X            rc = e_SYNTAX;
  1226. X         }
  1227. X         else {  /* (rc < 0) means a system error */
  1228. X            cleanup();
  1229. X            if ( errno )  perror( UsrName );
  1230. X            exit( e_SYSTEM );
  1231. X         }
  1232. X      }/*if*/
  1233. X
  1234. X      if ( Unset )  unset_positional_parameters();
  1235. X
  1236. X      print_args( UsrVals, UsrArgd );
  1237. X   }
  1238. X
  1239. X   cleanup();
  1240. X   exit( rc );
  1241. } /* main */
  1242. SHAR_EOF
  1243. echo 'File parseargs/parseargs.c is complete' &&
  1244. chmod 0664 parseargs/parseargs.c ||
  1245. echo 'restore of parseargs/parseargs.c failed'
  1246. Wc_c="`wc -c < 'parseargs/parseargs.c'`"
  1247. test 70264 -eq "$Wc_c" ||
  1248.     echo 'parseargs/parseargs.c: original size 70264, current size' "$Wc_c"
  1249. rm -f _shar_wnt_.tmp
  1250. fi
  1251. # ============= parseargs/parseargs.h ==============
  1252. if test -f 'parseargs/parseargs.h' -a X"$1" != X"-c"; then
  1253.     echo 'x - skipping parseargs/parseargs.h (File already exists)'
  1254.     rm -f _shar_wnt_.tmp
  1255. else
  1256. > _shar_wnt_.tmp
  1257. echo 'x - extracting parseargs/parseargs.h (Text)'
  1258. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/parseargs.h' &&
  1259. /*************************************************************************
  1260. ** ^FILE: parseargs.h -- definitions for argument parsing library
  1261. **
  1262. ** ^DESCRIPTION:
  1263. **    This file contains all the necessary macros, type, and function
  1264. **    declarations necessary to use the parseargs library. For most purposes,
  1265. **    no special symbols need be #defined before including this file; however,
  1266. **    for implementors (and more sophisticated uses), the following symbols
  1267. **    may be #defined before including this file in order to include/exclude
  1268. **    various portions of the file:
  1269. **
  1270. **    PARSEARGS_PRIVATE
  1271. **       Include private definitions that are needed to implement/enhance
  1272. **       various functions in the parseargs library.
  1273. **
  1274. **    PARSEARGS_NEXTERNS
  1275. **       Do NOT include the external function declarations for the members
  1276. **       of the parseargs library.
  1277. **
  1278. **    PARSEARGS_NARGTYPES
  1279. **       Do NOT include the external function declarations any of the
  1280. **       pre-defined argument-type (argXxxx) functions.
  1281. **
  1282. ** ^HISTORY:
  1283. **    12/03/90    Brad Appleton    <brad@ssd.csd.harris.com>
  1284. **    - Added all the #ifdef stuff
  1285. **    - Added public and private macros for getting and setting
  1286. **      the attributes of an argdesc-array and an argdesc
  1287. **
  1288. **    --/--/--    Peter da Silva    <peter@ferranti.com>
  1289. **
  1290. **    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  1291. ***^^**********************************************************************/
  1292. X
  1293. /* $Header: parseargs.h,v 2.0 89/12/24 00:56:29 eric Exp $ */
  1294. X
  1295. #ifndef PARSEARGS_H
  1296. #define  PARSEARGS_H
  1297. X
  1298. #include <useful.h>
  1299. X
  1300. X   /* type definition for argument prompt strings */
  1301. #define  MAX_ARGNAME  80
  1302. typedef char argName_t[ MAX_ARGNAME ];
  1303. X
  1304. X   /* type definition for bitmasks */
  1305. typedef unsigned short  argMask_t;
  1306. X
  1307. /**********************************************************************
  1308. ** ^STRUCT: ARGDESC - argument-descriptor
  1309. **
  1310. ** ^DESCRIPTION:
  1311. **    The basic type used by the parseargs library is the argument descriptor
  1312. **    (or "argdesc" for short). An ARGDESC structure is used to describe a
  1313. **    command-line argument. Each command line argument contains various
  1314. **    fields which need to be set and/or queried by the programmer. Each
  1315. **    field is described in further detail below:
  1316. */ 
  1317. typedef struct _argdesc {
  1318. X   char ad_name;
  1319. /*    -- This is a single character which corresponds to the option-letter
  1320. **       (case-sensitive) from the command-line that matches the argument
  1321. **       described by this structure. Positional-arguments are denoted by
  1322. **       putting a a space character in this field.
  1323. */ 
  1324. X   argMask_t  ad_flags;
  1325. /*    -- This field contains the various bitflags that describe the semantics
  1326. **       of this argument. See the ARGFLAGS section for more information on
  1327. **       the possible combinations of bitmasks for this field.
  1328. */ 
  1329. X   BOOL (*ad_type) ARGS((struct _argdesc *, char *, BOOL));
  1330. /*    -- This field is a pointer to a type conversion function (such as the
  1331. **       ones provided in argtype(3). The type conversion function is respon-
  1332. **       sible for verifying the validity of the argument, allocating any
  1333. **       necessary storage for its internal representation, and converting
  1334. **       the command-line argument into its required internal form. The type
  1335. **       conversion function used may be one of the pre-defined argtype(3)
  1336. **       functions. The function is given three parameters: The first is
  1337. **       a pointer to the ARGDESC struct in question, the second is the
  1338. **       string-value (if any) supplied on the command-line, and the third
  1339. **       is a boolean value that is TRUE only if the second parameter points
  1340. **       to temporary storage (and hence may need to be copied).
  1341. **       In the case of parseargs(1) this field must correspond to the name
  1342. **       of one of the argument type functions described in argtype(3).
  1343. */ 
  1344. X   ARBPTR ad_valp;
  1345. /*    -- This field is a generic pointer to the storage used to represent
  1346. **       the internal value of the command-line argument. It may be a
  1347. **       pointer to a number, a boolean value, a string, a list, or anything
  1348. **       else for which there exists a corresponding arg-type function to
  1349. **       use in the ad_type field. In the case of of parseargs(1) this field
  1350. **       must be the name of the corresponding shell variable which eventually
  1351. **       hold the value of the argument given on the command-line.
  1352. */ 
  1353. X   CONST char *ad_prompt;
  1354. /*    -- This field contains the long-name of the argument and an optional
  1355. **       description (the description must be separated from the long-name by
  1356. **       at least one whitespace characters and may optionally be enclosed in
  1357. **       a set of balanced delimiters (such as parentheses, curly-braces,
  1358. **       square-brackets, or angle-brackets. If the long-name contains any
  1359. **       uppercase characters, then the substring of long-name consisting of
  1360. **       all uppercase characters is used as the argument name and the entire
  1361. **       long-name is used as the name of the argument-value (if a value my be
  1362. **       supplied). The long-name may be matched by supplying a unique prefix
  1363. **       of either the argument name or the argument-value name.
  1364. */ 
  1365. } ARGDESC;
  1366. /**^^**********************************************************************/
  1367. X
  1368. X
  1369. X   /* define a NULL pointer to an arg-descriptor */
  1370. #define ARGDESCNULL   (ARGDESC *)NULL
  1371. X
  1372. X   /* define a pointer to an argtype function */
  1373. typedef BOOL (*argTypePtr_t) ARGS((ARGDESC *, char *, BOOL));
  1374. X
  1375. X
  1376. /**********************************************************************
  1377. ** ^SECTION: RETURN-CODES
  1378. **    The XparseXXXX functions in the parseargs library may return any of
  1379. **    the following return codes (which are #define'd below):
  1380. */
  1381. #define  pe_SYSTEM   -1
  1382. /*    -- a system error occurred. The global variable errno may indicate
  1383. **       the problem (then again, it may not).
  1384. */
  1385. #define  pe_SUCCESS   0
  1386. /*    -- success, no errors encountered.
  1387. */
  1388. #define  pe_SYNTAX    1
  1389. /*    -- a command-line syntax error was encountered
  1390. */
  1391. #define  pe_DEFARGS   2
  1392. /*    -- an attempt (using parsecntl()) was made to change the
  1393. **       default arg-search list of a command to point to an argdesc-array
  1394. **       which already has the given command on its default arg-search list
  1395. **       (which would cause an infinite loop when attempting to match an
  1396. **       unknown command-line argument).
  1397. */
  1398. #define  pe_NOMATCH   3
  1399. /*    -- unable to match the named argument. This occurs
  1400. **       when the argument keyword name passed to parsecntl() (using the 
  1401. **       pc_ARGFLAGS functions code) was found in the given argdesc-array
  1402. **       or in its default-list.
  1403. */
  1404. #define  pe_BADMODE   4
  1405. /*    -- bad mode for given command in parsecntl(). This occurs when 
  1406. **       pc_WRITE or pc_RDWR mode is passed to parsecntl() in conjunction
  1407. **       with the pc_ARGFLAGS functions code. Parsecntl will not modify
  1408. **       existing arguments.
  1409. */
  1410. #define  pe_BADCNTL   5
  1411. /*    -- bad command for parsecntl. This occurs if an unknown function-code
  1412. **       was passed to parsecntl().
  1413. */
  1414. #define  pe_BADOPEN   6
  1415. /*    -- error opening file
  1416. */
  1417. #define  pe_BADREAD   7
  1418. /*    -- error reading file
  1419. */
  1420. /**^^**********************************************************************/
  1421. X
  1422. X
  1423. /**********************************************************************
  1424. ** ^SECTION: ARGUMENT-FLAGS
  1425. **    These are the possible bitmasks that may be turned ON or OFF in
  1426. **    the ad_flags field of an ARGDESC structure.
  1427. */
  1428. #define ARGOPT       0x0000
  1429. /*    -- This flag is actually a dummy flag (i.e. it is the default). This flag
  1430. **       specifies that the command-line argument is optional (need not appear
  1431. **       on the command-line). It is only needed if no other flags are used to
  1432. **       define the given argument.  If other flags are given and ARGREQ is NOT
  1433. **       one of them, then ARGOPT is always assumed.
  1434. */
  1435. #define ARGREQ       0x0001
  1436. /*    -- The associated command argument is required on the command-line.
  1437. */
  1438. #define ARGPOS       0x0002
  1439. /*    -- The associated command argument is positonal. The difference between
  1440. **       using this flag to indicate a positional argument and between using
  1441. **       a blank in the ad_name field to indicate a positional arguments is
  1442. **       the following: If this flag is set but the ad_name of the argument
  1443. **       is non-blank, then this argument may be matched either positionally
  1444. **       or by keyword. If the ad_name field is blank, then this argument may
  1445. **       only be matched positionally.
  1446. */
  1447. #define ARGNOVAL     0x0004
  1448. /*    -- The associated command argument takes no value (as in "-x value");
  1449. **       Its mere presence (or lack thereof) on the command-line is sufficient
  1450. **       to determine the necessary action(s) to take (as in "-x").
  1451. **
  1452. **       NOTE: all argBool, and arg[STU]Bool arguments are always forced to be
  1453. **       ARGNOVAL (as are argUsage arguments).
  1454. */
  1455. #define ARGVALOPT    0x0008
  1456. /*    -- This flag is used to indicate that the command-line argument takes a
  1457. **       value (as in "-s string" or "/str=string") but that the value to this
  1458. **       command-line argument is NOT required (hence simply "-s" or "/str" is
  1459. **       also permissable).
  1460. */
  1461. #define ARGVALREQ    0x0000
  1462. /*    -- Another "dummy" flag. Unless ARGNOVAL or ARGVALOPT is specified,
  1463. **       ARGVALREQ is always assumed. This flag indicates that the value to a
  1464. **       command-line argument is required (hence "-s string" is okay but just
  1465. **       "-s" is not).
  1466. */
  1467. #define ARGHIDDEN    0x0010
  1468. /*    -- Don't display this argument in usage messages but still attempt to
  1469. **       match it against strings given on the command-line.
  1470. */
  1471. #define ARGLIST      0x0020
  1472. /*    -- A variable number of values are used for this argument (and hence may
  1473. **       use more than one or two argv elements from the command-line as in
  1474. **       "-l val1 val2 ..."). The list of values must be stored in an arglist
  1475. **       structure (NOT a vector structure), an the corresponding argument-type
  1476. **       function should be one of the listXxxx functions.
  1477. */
  1478. #define ARGVEC       0x0040
  1479. /*    -- A variable number of values are used for this argument (and hence may
  1480. **       use more than one or two argv elements from the command-line as in
  1481. **       in "-v val1 val2 ..."). The list of values must be stored in a vector
  1482. **       structure (NOT an arglist structure).
  1483. */
  1484. X
  1485. /*   The following bitmasks may also be present, but, unlike the above masks
  1486. **   which must be specified by the programmer at initialization time, the
  1487. **   following masks must only be read (never set) by the programmer:
  1488. */
  1489. #define ARGGIVEN     0x0080
  1490. /*    -- The argument WAS given on the command-line.
  1491. */
  1492. #define ARGVALGIVEN  0x0100
  1493. /*    -- The value for this argument was given on the command-line.
  1494. */
  1495. #define ARGVALSEP    0x0200
  1496. /*    -- The value to this argument was supplied in a separate argv element
  1497. **       from the argument itself (as in "-x value" as opposed to "-xvalue").
  1498. */
  1499. #define ARGKEYWORD   0x0400
  1500. /*    -- This argument was matched as a keyword (long-form) on the command-line
  1501. **       and not as a single character.
  1502. */
  1503. #define ARGDESCRIBED 0x0800
  1504. /*    -- This argument was given a description by the programmer at
  1505. **       initialization.
  1506. */
  1507. #define ARGCOPYF     0x1000
  1508. /*    -- This flag is only used for lists and vectors (multivalued arguments)
  1509. **       and is used on a per-item basis. If it is set, it means that the
  1510. **       corresponding value in the vector/list required space to be allocated
  1511. **       (such as the duplication of a temporary string).
  1512. */
  1513. /**^^**********************************************************************/
  1514. X
  1515. X
  1516. /**********************************************************************
  1517. ** ^SECTION: ARGDESC-MACROS
  1518. **    The following macros are used to extract and query the attributes
  1519. **    of a pointer to a preprocessed arg-descriptor:
  1520. */
  1521. #define  arg_cname(ad)        ((ad) -> ad_name)
  1522. /*    -- return the single-character name of an argument.
  1523. */
  1524. #define  arg_flags(ad)        ((ad) -> ad_flags)
  1525. /*    -- return the argument flags of an argument.  The flags themselves
  1526. **       may be manipulated using the BTEST, BSET, and BCLEAR macros
  1527. **       #defined in <useful.h>.
  1528. */
  1529. #define  arg_type(ad)         ((ad) -> ad_type)
  1530. /*    -- return the pointer to the value-translation-routine of an argument.
  1531. */
  1532. #define  arg_valp(ad)         ((ad) -> ad_valp)
  1533. /*    -- return the pointer to the value of this argument.
  1534. */
  1535. #define  arg_sname(ad)        ((ad) -> ad_prompt)
  1536. /*    -- return the string name of an argument.
  1537. */
  1538. #define  arg_sdesc(ad)        ( arg_sname(ad) + strlen(arg_sname(ad)) + 1 )
  1539. /*    -- return the description of an argument. If a description was supplied,
  1540. **       the ARGDESCRIBED flag will be set and the description will immediately
  1541. **       follow the NUL byte of the string name.
  1542. */
  1543. #define  ARG_isDESCRIBED(ad)  BTEST( arg_flags(ad), ARGDESCRIBED )
  1544. /*    -- Evaluates to TRUE only if an argument description was provided.
  1545. */
  1546. #define  arg_description(ad)  ( ARG_isDESCRIBED(ad) ? arg_sdesc(ad) : "" )
  1547. /*    -- Return the description string (or an empty string if no description
  1548. **       was given) for this argument.
  1549. */
  1550. #define  ARG_isPOSITIONAL(ad) BTEST( arg_flags(ad), ARGPOS )
  1551. /*    -- Evaluates to TRUE if this argument may be positionally matched.
  1552. */
  1553. #define  ARG_isPOSONLY(ad) ( arg_cname(ad) == ' ' )
  1554. /*    -- Evaluates to TRUE if this argument may only be positionally matched.
  1555. */
  1556. #define  ARG_isLIST(ad)       ( BTEST(arg_flags(ad), ARGLIST) )
  1557. /*    -- Evaluates to TRUE if this argument is an arglist.
  1558. */
  1559. #define  ARG_isVEC(ad)        ( BTEST(arg_flags(ad), ARGVEC) )
  1560. /*    -- Evaluates to TRUE if this argument is a vector.
  1561. */
  1562. #define  ARG_isMULTIVAL(ad)   ( BTEST(arg_flags(ad), ARGVEC | ARGLIST) )
  1563. /*    -- Evaluates to TRUE if this argument is an arglist or a vector.
  1564. */
  1565. #define  ARG_isVALTAKEN(ad)      ( ! BTEST(arg_flags(ad), ARGNOVAL) )
  1566. /*    -- Evaluates to TRUE if this argument does NOT take a value.
  1567. */
  1568. #define  ARG_isGIVEN(ad)      ( BTEST(arg_flags(ad), ARGGIVEN) )
  1569. /*    -- Evaluates to TRUE if this argument was given on the command-line.
  1570. */
  1571. #define  ARG_isVALGIVEN(ad)      ( BTEST(arg_flags(ad), ARGVALGIVEN) )
  1572. /*    -- Evaluates to TRUE if the argument value was given on the command-line.
  1573. */
  1574. #define  ARG_isREQUIRED(ad)   ( BTEST(arg_flags(ad), ARGREQ) )
  1575. /*    -- Evaluates to TRUE if this argument is required.
  1576. */
  1577. #define  ARG_isVALOPTIONAL(ad)   ( BTEST(arg_flags(ad), ARGVALOPT) )
  1578. /*    -- Evaluates to TRUE if the argument value is optional.
  1579. */
  1580. #define  ARG_isVALSEPARATE(ad)   ( BTEST(arg_flags(ad), ARGVALSEP) )
  1581. /*    -- Evaluates to TRUE if the argument value is optional.
  1582. */
  1583. #define  ARG_isHIDDEN(ad)     ( BTEST(arg_flags(ad), ARGHIDDEN) )
  1584. /*    -- Evaluates to TRUE if this argument is omitted from usage messages.
  1585. */
  1586. /**^^**********************************************************************/
  1587. X
  1588. X
  1589. X   /* macro to define a NULL argument-type function */
  1590. #define argNULL    (argTypePtr_t)NULL
  1591. X
  1592. X   /* macro for an empty argument descriptor */
  1593. #define ARG_EMPTY   { '\0', 0x0000, argNULL, ARBNULL, CHARNULL }
  1594. X
  1595. X   /*
  1596. X   ** macro to denote start & end of an ARGDESC array declared without
  1597. X   ** the CMD_XXXXXXX macros which follow.
  1598. X   */
  1599. #define STARTOFARGS  ARG_EMPTY
  1600. #define ENDOFARGS    ARG_EMPTY, ARG_EMPTY
  1601. X
  1602. /***************************************************************************
  1603. ** ^SECTION: CMD-MACROS
  1604. **    Parseargs.h defines a set of macros to allow a more "self documenting"
  1605. **    approach to declaring argument-descriptor arrays. The "old-style" is
  1606. **    still accepted (but if used it is recommended that the STARTOFARGS
  1607. **    macro is used in conjunction with ENDOFARGS).  An example use of these
  1608. **    macros (which, with one exception, all begin with "CMD") follows:
  1609. **
  1610. **         #include <parseargs.h>
  1611. **    
  1612. **         static BOOL bflag = FALSE;
  1613. **         static char *arg1 = CHARNULL;
  1614. **         static char *arg2 = CHARNULL;
  1615. **    
  1616. **         static
  1617. **         CMD_OBJECT
  1618. **            MyCmd
  1619. **
  1620. **         CMD_NAME
  1621. **            "mycmd -- one line statement of purpose"
  1622. **    
  1623. **         CMD_DESCRIPTION
  1624. **            "Mycmd will try really really hard to run without errors \
  1625. **         and do whatever the heck it is supposed to do. If (God forbid) \
  1626. **         something should actually go wrong it will say so."
  1627. **    
  1628. **         CMD_ARGUMENTS
  1629. **            'b', ARGOPT, argSBool, __ &bflag,
  1630. **            "bflag -- turn on `b'-mode (whatever that is)",
  1631. **    
  1632. **            ' ', ARGREQ, argStr, __ &arg1,
  1633. **            "arg1 -- first argument to this spiffy program",
  1634. **    
  1635. **            ' ', ARGOPT, argStr, __ &arg2,
  1636. **            "arg2 -- optional second argument to this spiffy program",
  1637. **    
  1638. **            END_ARGUMENTS
  1639. **         CMD_END
  1640. **    
  1641. **         main( argc, argv )
  1642. **            int argc;
  1643. **            char *argv[];
  1644. **         {
  1645. **            (void) parseargs( argv, MyCmd );
  1646. **            (void) dostuff();
  1647. **            exit( 0 );
  1648. **         }
  1649. ***^^**********************************************************************/
  1650. #define CMD_OBJECT       ARGDESC
  1651. #define CMD_NAME         [] = { { '\0', (argMask_t)0x0000, (argTypePtr_t)
  1652. #define CMD_DESCRIPTION  , ARBNULL,
  1653. #define CMD_ARGUMENTS    },
  1654. #define START_ARGUMENTS  ARG_EMPTY
  1655. #define END_ARGUMENTS    ARG_EMPTY
  1656. #define CMD_END          };
  1657. X
  1658. X   /*
  1659. X   ** shorthand for declaring main program
  1660. X   */
  1661. #ifdef __ANSI_C__
  1662. # define MAIN(argc,argv)  int main( int argc, char *argv[] )
  1663. #else
  1664. # define MAIN(argc,argv)  int main( argc, argv ) int argc; char *argv[];
  1665. #endif
  1666. X
  1667. /***************************************************************************
  1668. ** ^SECTION: MULTI-VALUED_ARGUMENTS
  1669. **    Parseargs supports two different types of multi-valued arguments:
  1670. **    linked-lists and vectors. The linked-lists are called argument lists
  1671. **    (or arg-lists) and are specified by supplying the ARGLIST flag along
  1672. **    with an associated listXxxx argument-translation routine. The value
  1673. **    associated with an arg-list should be a list structure of type ArgList.
  1674. **    The include file <parseargs.h> defines four macros for manipulating
  1675. **    ArgList structures:  ARGLISTNULL, L_NEXT, L_STRING, and L_FLAGS.
  1676. **
  1677. **    ARGLISTNULL is simply the NULL argument-list pointer.  L_NEXT and
  1678. **    L_STRING each take a pointer to a non-NULL ArgList structure. L_NEXT
  1679. **    returns the address of the next item in the list and L_STRING returns
  1680. **    the string-value of the current list-item.  L_FLAGS return the arg-
  1681. **    flags for a given item in the list. With non-multivalued, only the
  1682. **    flags in the argument descriptor are needed; lists and vectors however
  1683. **    need a set of flags for each item they contain. Once an arg-list has
  1684. **    been created, it may be deallocated using the function listFree. List-
  1685. **    Free takes two parameters, the first of which is the address of the
  1686. **    first item in the arg-list, and the second of which is a boolean value
  1687. **    that is TRUE only if each value pointed to by each item should also be
  1688. **    deallocated.
  1689. **
  1690. **    An alternative to argument-lists is argument vectors (or arg-vectors).
  1691. **    Arg-vectors use the ARGVEC flag instead of the ARGLIST flag and do not
  1692. **    require a special listXxxx function for each vector-type.  Each of the
  1693. **    argXxxx functions is responsible for handling vectors of its type
  1694. **    (although some argXxx functions such as the boolean types do not sup-
  1695. SHAR_EOF
  1696. true || echo 'restore of parseargs/parseargs.h failed'
  1697. fi
  1698. echo 'End of  part 6'
  1699. echo 'File parseargs/parseargs.h is continued in part 7'
  1700. echo 7 > _shar_seq_.tmp
  1701. exit 0
  1702. exit 0 # Just in case...
  1703. -- 
  1704. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1705. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1706. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1707. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1708.