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

  1. From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i055:  parseargs - functions to parse command line arguments, Part10/12
  4. Message-ID: <1991Mar18.155742.2233@sparky.IMD.Sterling.COM>
  5. Date: 18 Mar 91 15:57:42 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: bafdb38f 65b57117 4603162b c5b9f135
  8.  
  9. Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com>
  10. Posting-number: Volume 17, Issue 55
  11. Archive-name: parseargs/part10
  12.  
  13. This is part 10 of parseargs
  14.  
  15. #!/bin/sh
  16. # this is Part.10 (part 10 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file parseargs/syserr.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" != 10; 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/syserr.c'
  34. else
  35. echo 'x - continuing file parseargs/syserr.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'parseargs/syserr.c' &&
  37. /*    -- the formatted message-string to print.
  38. */
  39. X   va_list ap;
  40. /*    -- the list of variable arguments for vfprintf().
  41. */
  42. #endif  /* !__ANSI_C__ */
  43. X
  44. /* ^DESCRIPTION:
  45. **    _error_message will print the program name followed by the
  46. **    formatted message. If errno is non-zero, the corresponding
  47. **    system message will also be printed.
  48. **
  49. ** ^REQUIREMENTS:
  50. **    None.
  51. **
  52. ** ^SIDE-EFECTS:
  53. **    Writes to stderr.
  54. **
  55. ** ^RETURN-VALUE:
  56. **    None.
  57. **
  58. ** ^ALGORITHM:
  59. **    - print the program name
  60. **    - print the message
  61. **    - if errno is non-zero, call perror()
  62. ***^^**********************************************************************/
  63. #ifdef __ANSI_C__
  64. X   static void _error_message( const char *format, va_list ap )
  65. #endif
  66. {
  67. X   int save_err;
  68. X
  69. X   save_err = errno;
  70. X   if (ProgName  &&  *ProgName)  fprintf(stderr, "%s: ", ProgName);
  71. X
  72. X   (VOID) vfprintf(stderr, format, ap);
  73. X
  74. X   fputc('\n', stderr);
  75. X   if ( save_err ) {
  76. X      errno = save_err;
  77. X      perror("System error");
  78. X   }
  79. X   fflush(stderr);
  80. }
  81. X
  82. X
  83. /***************************************************************************
  84. ** ^FUNCTION: syserr - print a formatted message and exit
  85. **
  86. ** ^SYNOPSIS:
  87. */
  88. #ifndef __ANSI_C__
  89. X   VOID syserr( format, va_alist )
  90. /*
  91. ** ^PARAMETERS:
  92. */
  93. X   char *format;
  94. /*    -- the format string to pass to vfprintf()
  95. */
  96. X   va_dcl  
  97. /*    -- the arguments to be formatted
  98. */
  99. #endif  /* !__ANSI_C__ */
  100. X
  101. /* ^DESCRIPTION:
  102. **    Syserr will print the current program name followed by the
  103. **    formatted message. If errno is non-zero, it will use perror
  104. **    to print the corresponding system error message. Lastly, Syserr
  105. **    will terminate execution with an exit code of 1.
  106. **
  107. ** ^REQUIREMENTS:
  108. **    No special requirements.
  109. **
  110. ** ^SIDE-EFECTS:
  111. **    All output is written to stderr. Program execution is terminated.
  112. **
  113. ** ^RETURN-VALUE:
  114. **    None (Does not return).
  115. **
  116. ** ^ALGORITHM:
  117. **    - print the error message(s)
  118. **    - take care of recursive calls to syserr()
  119. **    - exit
  120. ***^^**********************************************************************/
  121. #ifdef __ANSI_C__
  122. X   void syserr( const char *format, ... )
  123. #endif
  124. {
  125. X   static BOOL exiting = FALSE;
  126. X   va_list ap;
  127. X
  128. X   /* print the error message */
  129. X   VA_START(ap, format);
  130. X   _error_message(format, ap);
  131. X   VA_END(ap);
  132. X
  133. X   /* if we recursively syserr during exit, drop out now! */
  134. X   if (exiting)  exit(1);
  135. X
  136. X   /* try a clean exit */
  137. X   exiting = TRUE;
  138. X   exit(1);
  139. X   /*NOTREACHED*/
  140. }
  141. X
  142. X
  143. /***************************************************************************
  144. ** ^FUNCTION: eprintf - print a formatted message on stderr.
  145. **
  146. ** ^SYNOPSIS:
  147. */
  148. #ifndef __ANSI_C__
  149. X   int eprintf( format, va_alist )
  150. /*
  151. ** ^PARAMETERS:
  152. */
  153. X   char *format;
  154. /*    -- the printf() message to print.
  155. */
  156. X   va_dcl
  157. /*    -- the arguments to be formatted
  158. */
  159. #endif  /* !__ANSI_C__ */
  160. X
  161. /* ^DESCRIPTION:
  162. **    Eprintf() will behaves exactly like printf with the sole
  163. **    exception being that it writes to stderr instead of stdout.
  164. **
  165. ** ^REQUIREMENTS:
  166. **    None.
  167. **
  168. ** ^SIDE-EFECTS:
  169. **    Writes to stderr.
  170. **
  171. ** ^RETURN-VALUE:
  172. **    Same as printf(3).
  173. **
  174. ** ^ALGORITHM:
  175. **    Trivial.
  176. ***^^**********************************************************************/
  177. #ifdef __ANSI_C__
  178. X   int eprintf( const char *format, ... )
  179. #endif
  180. {
  181. X   int rc;
  182. X   va_list ap;
  183. X
  184. X   VA_START(ap, format);
  185. X   rc = vfprintf( stderr, format, ap );
  186. X   VA_END(ap);
  187. X
  188. X   fflush(stderr);
  189. X   return rc;
  190. }
  191. X
  192. X
  193. /***************************************************************************
  194. ** ^FUNCTION: usrerr - print a user error message
  195. **
  196. ** ^SYNOPSIS:
  197. */
  198. #ifndef __ANSI_C__
  199. X   VOID usrerr( format, va_alist )
  200. /*
  201. ** ^PARAMETERS:
  202. */
  203. X   char *format;
  204. /*    -- the format string to pass to vfprintf()
  205. */
  206. X   va_dcl
  207. /*    -- the arguments to be formatted
  208. */
  209. #endif  /* !__ANSI_C__ */
  210. X
  211. /* ^DESCRIPTION:
  212. **    Usrerr will print the current program name followed by the
  213. **    formatted message. If errno is non-zero, it will use perror
  214. **    to print the corresponding system error message.
  215. **
  216. ** ^REQUIREMENTS:
  217. **    No special requirements.
  218. **
  219. ** ^SIDE-EFECTS:
  220. **    All output is written to stderr.  Errno is cleared.
  221. **
  222. ** ^RETURN-VALUE:
  223. **    None.
  224. **
  225. ** ^ALGORITHM:
  226. **    - print the error message(s)
  227. **    - set errno to zero
  228. ***^^**********************************************************************/
  229. #ifdef __ANSI_C__
  230. X   void usrerr( const char *format, ... )
  231. #endif
  232. {
  233. X   va_list ap;
  234. X
  235. X   /* print the error message */
  236. X   VA_START(ap, format);
  237. X   _error_message(format, ap);
  238. X   VA_END(ap);
  239. X
  240. X   /* give us a clean slate */
  241. X   errno = 0;
  242. }
  243. SHAR_EOF
  244. echo 'File parseargs/syserr.c is complete' &&
  245. chmod 0664 parseargs/syserr.c ||
  246. echo 'restore of parseargs/syserr.c failed'
  247. Wc_c="`wc -c < 'parseargs/syserr.c'`"
  248. test 5916 -eq "$Wc_c" ||
  249.     echo 'parseargs/syserr.c: original size 5916, current size' "$Wc_c"
  250. rm -f _shar_wnt_.tmp
  251. fi
  252. # ============= parseargs/test.awk ==============
  253. if test -f 'parseargs/test.awk' -a X"$1" != X"-c"; then
  254.     echo 'x - skipping parseargs/test.awk (File already exists)'
  255.     rm -f _shar_wnt_.tmp
  256. else
  257. > _shar_wnt_.tmp
  258. echo 'x - extracting parseargs/test.awk (Text)'
  259. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.awk' &&
  260. #!/usr/bin/awk -f
  261. X
  262. ##########################################################################
  263. ## ^FILE: test.awk - parseargs for awk programs
  264. ##
  265. ## ^DESCRIPTION:
  266. ##    This file defines an awk function named parseargs to parse
  267. ##    command-line arguments for awk scripts. It also contains a
  268. ##    bare-bones template of what such an awk-script might contain.
  269. ##
  270. ## ^HISTORY:
  271. ##    02/21/91    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  272. ###^^#####################################################################
  273. X
  274. X
  275. #########
  276. ## ^FUNCTION: parseargs - parse command-line argument vectors
  277. ##
  278. ## ^SYNOPSIS:
  279. ##    parseargs( argc, argv, argd, arr )
  280. ##
  281. ## ^PARAMETERS:
  282. ##    argc -- the number of elements in argv (usually ARGC-1).
  283. ##    argv -- the vector of command-line arguments (usually ARGV).
  284. ##    argd -- the argument-description string
  285. ##    arr  -- the associative array to assign command-line values from
  286. ##
  287. ## ^DESCRIPTION:
  288. ##    Parseargs will invoke parseargs(1) to parse the command-line given
  289. ##    in <argv> for the command defined by <argd>.  The resulting values
  290. ##    will be assigned to elements of the associative array given by <arr>.
  291. ##    Values are assigned using using the syntax: arr [ "argname" ] = value;
  292. ##    The exception to this is that if the <argname> is "ARGV" then the global
  293. ##    array ARGV is reset to the given array (using tab separated fields).
  294. ##
  295. ## ^REQUIREMENTS:
  296. ##    Any desired initial values for items in <arr> should be assigned BEFORE
  297. ##    calling this function (using the syntax: arr[ "argname" ] = initial-val).
  298. ##
  299. ##    The following global variables may be assigned before calling parseargs:
  300. ##
  301. ##       PROGNAME -- name of the current awk script (default= ARGV[0])
  302. ##       PARSEOPTS -- any extra options to pass toi parseargs() (default="-ul")
  303. ##       PARSEINPUT -- input file for parseargs(1) (default=unique-name)
  304. ##       PARSEOUTPUT -- output file for parseargs(1) (default=unique-name)
  305. ##
  306. ## ^SIDE-EFFECTS:
  307. ##    The files PARSEINPUT and PARSEOUTPUT are created and then deleted.
  308. ##
  309. ##    The return value from parseargs(1) will be stored in the global-variable
  310. ##    named PARSESTATUS.
  311. ##
  312. ##    The global variable PARSEARGS will contain the command-line used to
  313. ##    invoke parseargs(1).
  314. ##
  315. ##    ARGV and ARGC may be reset, all other values are (re)set in <arr>.
  316. ##
  317. ## ^RETURN-VALUE:
  318. ##    The exit code returned by parseargs(1).
  319. ##
  320. ## ^BUGS:
  321. ##    Due to the limited ability of awk, scripts using parseargs(1) cannot
  322. ##    use short-options (with a  dash '-') because awk will attempt to interpret
  323. ##    any such arguments as options to awk and remove them from ARGV (regardless
  324. ##    of whether or not they are valid awk-options). Keyword options (with a
  325. ##    plus sign '+') may still be used without this difficulty. Dash-options
  326. ##    may be successfully processed if they did not first appear on the command
  327. ##    to the awk-script, so the full syntax of unix-style options could be 
  328. ##    provided in an array other than ARGV.
  329. ##
  330. ## ^ALGORITHM:
  331. ##    - set defaults for PROGNAME, PARSEOPTS, PARSEINPUT, and PARSEOUTPUT.
  332. ##    - build the parseargs command (dont forget to quote arguments).
  333. ##    - redirect input and output of the parseargs command.
  334. ##    - run parseargs(1)
  335. ##    - assign the exit-code from parseargs(1) to PARSESTATUS
  336. ##    - remove PARSEINPUT
  337. ##    - if PARSESTATUS != 0
  338. ##      - save RS and FS and reset RS = "" and FS = "\n"
  339. ##      - for each record in PARSEOUTPUT
  340. ##        - $1 is the argname and $2 is the value
  341. ##        - if $1 is "ARGV" reset ARGV and ARGC ($2 is a tab separated array)
  342. ##        - else assign arr[ $1 ] = $2
  343. ##      end-for
  344. ##      - restore RS and FS to previous values
  345. ##      - remove PARSEOUTPUT
  346. ##      - return PARSESTATUS
  347. ###^^####
  348. X
  349. function parseargs(argc, argv, argd, arr) {
  350. X      ## set defaults -- use $$ to get a unique suffix string
  351. X   if ( ! PROGNAME )     PROGNAME = ARGV[0];
  352. X   if ( ! PARSEOPTS )    PARSEOPTS = "-u -l";
  353. X
  354. X   "echo  ${TMP:-/tmp}/parseargs.${$}_"  |  getline TMPFILE;
  355. X   if ( ! PARSEINPUT )   PARSEINPUT = TMPFILE "in";
  356. X   if ( ! PARSEOUTPUT )  PARSEOUTPUT = TMPFILE "out";
  357. X
  358. X      ## build the options and required arguments for parseargs(1)
  359. X   PARSEARGS = sprintf( "parseargs -s awk %s -- '%s'", PARSEOPTS, PROGNAME );
  360. X
  361. X      ## quote each elemnt in argv and append it to the parseargs-command
  362. X   for ( i = 1 ; i <= argc ; i++ ) {
  363. X      arg = argv[i];
  364. X      gsub( /'/, "'\\''", arg );
  365. X      PARSEARGS = PARSEARGS " '" arg "'";
  366. X   }
  367. X
  368. X      ## set up i/o redirection
  369. X   PARSEARGS = PARSEARGS  " <" PARSEINPUT  " >" PARSEOUTPUT;
  370. X   print  argd > PARSEINPUT;
  371. X
  372. X      ## invoke parseargs(1) and save the status
  373. X   PARSESTATUS = system( PARSEARGS );
  374. X   system( "/bin/rm -f " PARSEINPUT );  ## dont need input anymore
  375. X
  376. X      ## if successful status, read the result
  377. X   if ( PARSESTATUS == 0 ) {
  378. X      save_RS = RS; save_FS = FS;
  379. X      RS = ""; FS = "\n";
  380. X      while ( getline  < PARSEOUTPUT  > 0 ) {
  381. X         gsub( /\034/, "\n" );
  382. X         if ( $1 == "ARGV" ) {
  383. X            ARGC = 1 + split( $2, ARGV, "\t" );
  384. X            ARGV[0] = PROGNAME;
  385. X         }
  386. X         else  arr[ $1 ] = $2;
  387. X      }
  388. X      RS = save_RS; FS = save_FS;
  389. X   }
  390. X   system( "/bin/rm -f " PARSEOUTPUT );
  391. X
  392. X   return  PARSESTATUS;
  393. }
  394. X
  395. X
  396. BEGIN {
  397. X  PROGNAME = "test.awk";
  398. X  ARGD = sprintf( "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
  399. X    "'?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit'" ,
  400. X    "'S', ARGVALOPT, argStr,   string,  'STRing : optional string arg'" ,
  401. X    "'g', ARGLIST,   argStr,   groups,  'newsGROUPS : groups to test'" ,
  402. X    "'r', ARGOPT,    argInt,   count,   'REPcount : group repeat count'" ,
  403. X    "'d', ARGOPT,    argStr,   dirname, 'DIRectory : working directory'" ,
  404. X    "'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode'" ,
  405. X    "'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode'" ,
  406. X    "'s', ARGOPT,    argChar,  sepch,   'SEPchar : field separator'" ,
  407. X    "'f', ARGLIST,   argStr,   files,   'files : files to process'" ,
  408. X    "'n', ARGREQ|ARGPOS, argStr, name,  'name : name to use'" ,
  409. X    "' ', ARGLIST,   argStr,   argv,    'argv : any remaining arguments'" ,
  410. X    "ENDOFARGS" );
  411. X
  412. X  Args[ "count" ] = 1;
  413. X  Args[ "dirname" ] = ".";
  414. X  Args[ "sepch" ] = ",";
  415. X  Args[ "yflag" ] = "TRUE";
  416. X
  417. X  rc = parseargs( ARGC-1, ARGV, ARGD, Args );
  418. X  if ( rc != 0 )  exit( rc );
  419. X
  420. X  ## print  the parsed arguments (use defaults if not defined)
  421. X  print "ARGUMENTS:";
  422. X  print "==========";
  423. X
  424. X  for ( i in Args )
  425. X    printf( "Args[\"%s\"] = \"%s\"\n", i, Args[i] );
  426. X
  427. X  argc = split( Args[ "argv" ], argv, "\t" );
  428. X  for ( i = 1 ; i <= argc ; i++ )
  429. X    printf( "argv[%d] = \"%s\"\n", i, argv[i] );
  430. X    
  431. }
  432. SHAR_EOF
  433. chmod 0775 parseargs/test.awk ||
  434. echo 'restore of parseargs/test.awk failed'
  435. Wc_c="`wc -c < 'parseargs/test.awk'`"
  436. test 6643 -eq "$Wc_c" ||
  437.     echo 'parseargs/test.awk: original size 6643, current size' "$Wc_c"
  438. rm -f _shar_wnt_.tmp
  439. fi
  440. # ============= parseargs/test.csh ==============
  441. if test -f 'parseargs/test.csh' -a X"$1" != X"-c"; then
  442.     echo 'x - skipping parseargs/test.csh (File already exists)'
  443.     rm -f _shar_wnt_.tmp
  444. else
  445. > _shar_wnt_.tmp
  446. echo 'x - extracting parseargs/test.csh (Text)'
  447. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.csh' &&
  448. #!/bin/csh -f
  449. #
  450. #    test.csh - C-shell script to test out the parseargs command!
  451. #
  452. set NAME="`basename $0`"
  453. X
  454. setenv ARGUMENTS "\
  455. X  '?', ARGHIDDEN, argUsage, NULL,    'Help {print usage and exit}', \
  456. X  'S', ARGVALOPT, argStr,   string,  'STRing {optional string arg}', \
  457. X  'g', ARGLIST,   argStr,   groups,  'newsGROUPS {groups to test}', \
  458. X  'r', ARGOPT,    argInt,   count,   'REPcount {# to repeat each group}', \
  459. X  'd', ARGOPT,    argStr,   dirname, 'DIRectory {working directory}', \
  460. X  'x', ARGOPT,    argBool,  xflag,   'Xflag {turn on X-mode}', \
  461. X  'y', ARGOPT,    argUBool, yflag,   'Yflag {turn off Y-mode}', \
  462. X  's', ARGOPT,    argChar,  sepch,   'SEPchar {field separator}', \
  463. X  'f', ARGLIST,   argStr,   files,   'files {files to process}', \
  464. X  'n', ARGREQ|ARGPOS, argStr, name,  'name {name to use}', \
  465. X  ' ', ARGLIST,   argStr,   argv,    'argv {any remaining arguments}', \
  466. X  ENDOFARGS \
  467. "
  468. ## set defaults ##
  469. set groups='mygroup'   ## default group used by everyone
  470. set count='1'          ## only do once unless otherwise specified
  471. set dirname='.'        ## default to current directory
  472. set xflag=''           ## default xflag is false
  473. set yflag='TRUE'       ## default yflag is true
  474. set sepch=','          ## default separator is a comma
  475. set files=()
  476. X
  477. ## parse command-line ##
  478. parseargs -s csh -e ARGUMENTS -u -- "$NAME" $argv:q >/tmp/tmp$$
  479. if ( $status != 0 ) then  ## improper syntax (or just wanted usage)
  480. X    rm -f /tmp/tmp$$
  481. X    exit 2
  482. endif
  483. X
  484. ## evaluate output from parseargs & remove temporary file
  485. source /tmp/tmp$$
  486. rm -f /tmp/tmp$$
  487. X
  488. ## echo arguments ##
  489. echo "ARGUMENTS:"
  490. echo "=========="
  491. echo Groups=$groups:q
  492. echo Count=$count:q
  493. echo Directory=$dirname:q
  494. echo XFlag=$xflag:q
  495. echo YFlag=$yflag:q
  496. echo SepChar=$sepch:q
  497. echo Name=$name:q
  498. echo Files=$files:q
  499. if ( $?string_flag ) then
  500. X  if ( ! $?string ) set string="\!string arg ommited on cmd-line\!"
  501. else
  502. X  set string="default string"
  503. endif
  504. echo String=$string:q
  505. echo New Positional Parameters=$argv:q
  506. X
  507. ## print usage ##
  508. parseargs -e ARGUMENTS -U "$NAME"
  509. SHAR_EOF
  510. chmod 0775 parseargs/test.csh ||
  511. echo 'restore of parseargs/test.csh failed'
  512. Wc_c="`wc -c < 'parseargs/test.csh'`"
  513. test 2023 -eq "$Wc_c" ||
  514.     echo 'parseargs/test.csh: original size 2023, current size' "$Wc_c"
  515. rm -f _shar_wnt_.tmp
  516. fi
  517. # ============= parseargs/test.ksh ==============
  518. if test -f 'parseargs/test.ksh' -a X"$1" != X"-c"; then
  519.     echo 'x - skipping parseargs/test.ksh (File already exists)'
  520.     rm -f _shar_wnt_.tmp
  521. else
  522. > _shar_wnt_.tmp
  523. echo 'x - extracting parseargs/test.ksh (Text)'
  524. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.ksh' &&
  525. #!/bin/ksh
  526. #
  527. #    test.ksh - Korn shell script to test out the parseargs command!
  528. #
  529. X
  530. NAME="$(basename $0)"
  531. X
  532. ARGUMENTS="
  533. X  '?', ARGHIDDEN, argUsage, NULL,    'Help -- print usage and exit',
  534. X  'S', ARGVALOPT, argStr,   string,  'STRing -- optional string arg',
  535. X  'g', ARGLIST,   argStr,   groups,  'newsGROUPS -- groups to test',
  536. X  'r', ARGOPT,    argInt,   count,   'REPcount -- number to repeat each group',
  537. X  'd', ARGOPT,    argStr,   dirname, 'DIRectory -- working directory',
  538. X  'x', ARGOPT,    argBool,  xflag,   'Xflag -- turn on X-mode',
  539. X  'y', ARGOPT,    argUBool, yflag,   'Yflag -- turn off Y-mode',
  540. X  's', ARGOPT,    argChar,  sepch,   'SEPchar -- field separator',
  541. X  'f', ARGLIST,   argStr,   files,   'files -- files to process',
  542. X  'n', ARGREQ|ARGPOS, argStr, name,  'name -- name to use',
  543. X  ' ', ARGLIST,   argStr,    -- ,    'argv -- any remaining arguments',
  544. X  ENDOFARGS
  545. "
  546. export ARGUMENTS
  547. X
  548. ## set defaults ##
  549. typeset groups[]           ## default group used by everyone
  550. typeset count='1'          ## only do once unless otherwise specified
  551. typeset dirname='.'        ## default to current directory
  552. typeset xflag=''           ## default xflag is false
  553. typeset yflag='TRUE'       ## default yflag is true
  554. typeset sepch=','          ## default separator is a comma
  555. typeset files[]
  556. X
  557. ## parse command-line ##
  558. parseargs -s ksh -e ARGUMENTS -uip -- "$NAME" "$@" >/tmp/tmp$$
  559. if [ $? -ne 0 ] ; then
  560. X  rm -f /tmp/tmp$$
  561. X  exit 2  ## improper syntax (or just wanted usage)
  562. fi
  563. X
  564. ## evaluate results from parseargs and remove temporary file ##
  565. INTERPRET="."
  566. $INTERPRET /tmp/tmp$$
  567. rm -f /tmp/tmp$$
  568. X
  569. ## print arguments ##
  570. print "ARGUMENTS:"
  571. print "=========="
  572. print "Groups='${groups[@]}'"
  573. print "Count='$count'"
  574. print "Directory='$dirname'"
  575. print "XFlag='$xflag'"
  576. print "YFlag='$yflag'"
  577. print "SepChar='$sepch'"
  578. print "Name='$name'"
  579. print "Files='${files[@]}'"
  580. if [ "$string_flag" ] ; then
  581. X  string=${string:-"!string arg ommitted on cmd-line!"}
  582. else
  583. X  string="default string"
  584. fi
  585. print "String='$string'"
  586. print "New Positional Parameters='$*'"
  587. X
  588. ## print usage ##
  589. parseargs -a "$ARGUMENTS" -U "$NAME"
  590. SHAR_EOF
  591. chmod 0775 parseargs/test.ksh ||
  592. echo 'restore of parseargs/test.ksh failed'
  593. Wc_c="`wc -c < 'parseargs/test.ksh'`"
  594. test 2097 -eq "$Wc_c" ||
  595.     echo 'parseargs/test.ksh: original size 2097, current size' "$Wc_c"
  596. rm -f _shar_wnt_.tmp
  597. fi
  598. # ============= parseargs/test.pl ==============
  599. if test -f 'parseargs/test.pl' -a X"$1" != X"-c"; then
  600.     echo 'x - skipping parseargs/test.pl (File already exists)'
  601.     rm -f _shar_wnt_.tmp
  602. else
  603. > _shar_wnt_.tmp
  604. echo 'x - extracting parseargs/test.pl (Text)'
  605. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.pl' &&
  606. #!/usr/bin/perl
  607. X
  608. require  'parseargs.pl';
  609. X
  610. $ARGD = '
  611. X  { "?", ARGHIDDEN, argUsage, NULL,    "Help : print usage and exit" },
  612. X  { "S", ARGVALOPT, argStr,   string,  "STRing : optional string arg" },
  613. X  { "g", ARGLIST,   argStr,   groups,  "newsGROUPS : groups to test" },
  614. X  { "r", ARGOPT,    argInt,   count,   "REPcount : group repeat count" },
  615. X  { "d", ARGOPT,    argStr,   dirname, "DIRectory : working directory" },
  616. X  { "x", ARGOPT,    argBool,  xflag,   "Xflag : turn on X-mode" },
  617. X  { "y", ARGOPT,    argUBool, yflag,   "Yflag : turn off Y-mode" },
  618. X  { "s", ARGOPT,    argChar,  sepch,   "SEPchar : field separator" },
  619. X  { "f", ARGLIST,   argStr,   files,   "files : files to process" },
  620. X  { "n", ARGREQ|ARGPOS, argStr, name,  "name : name to use" },
  621. X  { " ", ARGLIST,   argStr,   ARGV,    "ARGV : any remaining arguments" },
  622. X  "ENDOFARGS" ';
  623. X
  624. $count = 1;
  625. $dirname = '.';
  626. $sepch = ',';
  627. $yflag = 'TRUE';
  628. X
  629. &parseargs( @ARGV, $ARGD );
  630. X
  631. ## print  the parsed arguments (use defaults if not defined)
  632. print "ARGUMENTS:\n";
  633. print "==========\n";
  634. for ( $i = $[ ; $i <= $#groups ; $i++ ) {
  635. X  printf( "Groups[%d] = '%s'\n", $i, $groups[$i] );
  636. }
  637. printf( "Count = %d\n", $count );
  638. printf( "Directory = '%s'\n", $dirname );
  639. printf( "XFlag = '%s'\n", $xflag );
  640. printf( "YFlag = '%s'\n", $yflag );
  641. printf( "SepChar = '%s'\n", $sepch );
  642. printf( "Name = '%s'\n", $name );
  643. for ( $i = $[ ; $i <= $#files ; $i++ ) {
  644. X  printf( "Files[%d] = '%s'\n", $i, $files[$i] );
  645. }
  646. if ( $string_flag ) {
  647. X  if ( ! $string ) {
  648. X    $string = '!string arg ommitted on cmd-line!';
  649. X  }
  650. }
  651. else {
  652. X  $string = 'default string';
  653. }
  654. printf( "String = '%s'\n", $string );
  655. for ( $i = $[ ; $i <= $#ARGV ; $i++ ) {
  656. X  printf( "ARGV[%d] = '%s'\n", $i, $ARGV[$i] );
  657. }
  658. SHAR_EOF
  659. chmod 0775 parseargs/test.pl ||
  660. echo 'restore of parseargs/test.pl failed'
  661. Wc_c="`wc -c < 'parseargs/test.pl'`"
  662. test 1718 -eq "$Wc_c" ||
  663.     echo 'parseargs/test.pl: original size 1718, current size' "$Wc_c"
  664. rm -f _shar_wnt_.tmp
  665. fi
  666. # ============= parseargs/test.rc ==============
  667. if test -f 'parseargs/test.rc' -a X"$1" != X"-c"; then
  668.     echo 'x - skipping parseargs/test.rc (File already exists)'
  669.     rm -f _shar_wnt_.tmp
  670. else
  671. > _shar_wnt_.tmp
  672. echo 'x - extracting parseargs/test.rc (Text)'
  673. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.rc' &&
  674. #!/bin/rc
  675. #    test.rc - rc shell script to test out the parseargs command!
  676. #
  677. NAME=`{basename $0}
  678. X
  679. ARGUMENTS='
  680. X  "?", ARGHIDDEN, argUsage, NULL,    "Help : print usage and exit",
  681. X  "S", ARGVALOPT, argStr,   string,  "STRing : optional string arg",
  682. X  "g", ARGLIST,   argStr,   groups,  "newsGROUPS : groups to test",
  683. X  "r", ARGOPT,    argInt,   count,   "REPcount <# to repeat each group>",
  684. X  "d", ARGOPT,    argStr,   dirname, "DIRectory : working directory",
  685. X  "x", ARGOPT,    argBool,  xflag,   "Xflag : turn on X-mode",
  686. X  "y", ARGOPT,    argUBool, yflag,   "Yflag : turn off Y-mode",
  687. X  "s", ARGOPT,    argChar,  sepch,   "SEPchar : field separator",
  688. X  "f", ARGLIST,   argStr,   files,   "files : files to process",
  689. X  "n", ARGREQ|ARGPOS, argStr, name,  "name : name to use",
  690. X  " ", ARGLIST,   argStr,   * ,      "argv : any remaining arguments",
  691. X  ENDOFARGS
  692. '
  693. X
  694. yflag='TRUE'     ## set defaults (dir="."; count=1; sepch=',') ##
  695. X
  696. ## parse command-line and save assignments in a temporary file ##
  697. parseargs -s rc -e ARGUMENTS -u -- $^NAME "$@" >/tmp/tmp$$
  698. if ( $status != 0 ) {
  699. X  rm -f /tmp/tmp$$;
  700. X  exit 2  ## non-zero status (usage given)
  701. }
  702. X
  703. ## evaluate results from parseargs and remove temporary file
  704. . /tmp/tmp$$;  rm -f /tmp/tmp$$
  705. X
  706. ## echo  the parsed arguments (use defaults if not defined)
  707. echo 'ARGUMENTS:'
  708. echo '=========='
  709. echo Name="$name", Count=${count:-1}
  710. echo XFlag="$xflag", YFlag="$yflag"
  711. echo Directory="${dirname:-'.'}", SepChar="${sepch:-','}"
  712. echo Groups="$groups"
  713. echo Files="$files"
  714. if ( $^string_flag )
  715. X  string=${string:-'!string arg ommitted on cmd-line!'}
  716. else
  717. X  string='default string'
  718. echo String="$string"
  719. echo New Positional Parameters="$^*"
  720. X
  721. parseargs -a $^ARGUMENTS -U $^NAME     ## print usage ##
  722. SHAR_EOF
  723. chmod 0775 parseargs/test.rc ||
  724. echo 'restore of parseargs/test.rc failed'
  725. Wc_c="`wc -c < 'parseargs/test.rc'`"
  726. test 1728 -eq "$Wc_c" ||
  727.     echo 'parseargs/test.rc: original size 1728, current size' "$Wc_c"
  728. rm -f _shar_wnt_.tmp
  729. fi
  730. # ============= parseargs/test.sh ==============
  731. if test -f 'parseargs/test.sh' -a X"$1" != X"-c"; then
  732.     echo 'x - skipping parseargs/test.sh (File already exists)'
  733.     rm -f _shar_wnt_.tmp
  734. else
  735. > _shar_wnt_.tmp
  736. echo 'x - extracting parseargs/test.sh (Text)'
  737. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.sh' &&
  738. #!/bin/sh
  739. #    test.sh - Bourne shell script to test out the parseargs command!
  740. #
  741. NAME="`basename $0`";  DOT=".";
  742. X
  743. ARGUMENTS="
  744. X  '?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit',
  745. X  'S', ARGVALOPT, argStr,   string,  'STRing : optional string arg',
  746. X  'g', ARGLIST,   argStr,   groups,  'newsGROUPS : groups to test',
  747. X  'r', ARGOPT,    argInt,   count,   'REPcount <# to repeat each group>',
  748. X  'd', ARGOPT,    argStr,   dirname, 'DIRectory : working directory',
  749. X  'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode',
  750. X  'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode',
  751. X  's', ARGOPT,    argChar,  sepch,   'SEPchar : field separator',
  752. X  'f', ARGLIST,   argStr,   files,   'files : files to process',
  753. X  'n', ARGREQ|ARGPOS, argStr, name,  'name : name to use',
  754. X  ' ', ARGLIST,   argStr,   -- ,     'argv : any remaining arguments',
  755. X  ENDOFARGS
  756. "
  757. export ARGUMENTS
  758. X
  759. yflag='TRUE'     ## set defaults (dir="."; count=1; sepch=',') ##
  760. X
  761. ## parse command-line and save assignments in a temporary file ##
  762. parseargs -s sh -e ARGUMENTS -u -- "$NAME" "$@" >/tmp/tmp$$
  763. if [ $? -ne 0 ]
  764. X  then rm -f /tmp/tmp$$; exit 2  ## non-zero status (usage given)
  765. fi
  766. X
  767. ## evaluate results from parseargs and remove temporary file
  768. $DOT /tmp/tmp$$;  rm -f /tmp/tmp$$
  769. X
  770. ## echo  the parsed arguments (use defaults if not defined)
  771. echo "ARGUMENTS:"
  772. echo "=========="
  773. echo "Name='$name', Count='${count:-1}'"
  774. echo "XFlag='$xflag', YFlag='$yflag'"
  775. echo "Directory='${dirname:-"."}', SepChar='${sepch:-","}'"
  776. echo "Groups='$groups'"
  777. echo "Files='$files'"
  778. if [ "$string_flag" ]
  779. X  then string=${string:-"!string arg ommitted on cmd-line!"}
  780. X  else string="default string"
  781. fi
  782. echo "String='$string'"
  783. echo "New Positional Parameters='$*'"
  784. X
  785. parseargs -a "$ARGUMENTS" -U "$NAME"     ## print usage ##
  786. SHAR_EOF
  787. chmod 0775 parseargs/test.sh ||
  788. echo 'restore of parseargs/test.sh failed'
  789. Wc_c="`wc -c < 'parseargs/test.sh'`"
  790. test 1789 -eq "$Wc_c" ||
  791.     echo 'parseargs/test.sh: original size 1789, current size' "$Wc_c"
  792. rm -f _shar_wnt_.tmp
  793. fi
  794. # ============= parseargs/unix_args.c ==============
  795. if test -f 'parseargs/unix_args.c' -a X"$1" != X"-c"; then
  796.     echo 'x - skipping parseargs/unix_args.c (File already exists)'
  797.     rm -f _shar_wnt_.tmp
  798. else
  799. > _shar_wnt_.tmp
  800. echo 'x - extracting parseargs/unix_args.c (Text)'
  801. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/unix_args.c' &&
  802. /*************************************************************************
  803. ** ^FILE: unix_args.c - parse Unix argument vectors
  804. **
  805. ** ^DESCRIPTION:
  806. **    This file contains the routines used to parse Unix argument
  807. **    vectors and to print Unix usage messages.
  808. **
  809. ** ^HISTORY:
  810. **    01/02/91     Brad Appleton     <brad@ssd.csd.harris.com>
  811. **    - Added structured block comments
  812. **    - Added optional arguments to keywords and options
  813. **
  814. **    --/--/--    Peter da Silva    <peter@ferranti.com>    
  815. **
  816. **    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  817. ***^^**********************************************************************/
  818. X
  819. #include <ctype.h>
  820. #include <useful.h>
  821. #include "strfuncs.h"
  822. #include "pgopen.h"
  823. X
  824. #define PARSEARGS_PRIVATE   /* include private definitions */
  825. #include "parseargs.h"
  826. X
  827. EXTERN  VOID  syserr       ARGS((const char *, ...));
  828. EXTERN  VOID  usrerr       ARGS((const char *, ...));
  829. EXTERN  char *getenv       ARGS((const char *));
  830. EXTERN  VOID  get_winsize  ARGS((int, int *, int *));
  831. X
  832. VERSIONID("$Header: parseargs.c,v 2.1 89/12/30 20:59:48 eric Exp $");
  833. X
  834. X
  835. /***************************************************************************
  836. ** ^GLOBAL-VARIABLE: Usage_Requested
  837. **
  838. ** ^VISIBILITY:
  839. **    static-global (visible to all functions in this file).
  840. **
  841. ** ^DESCRIPTION:
  842. **    Indicates whether a usage message was requested by the user
  843. **    (as opposed to triggered by a syntax error).  If the message
  844. **    is requested by the user then it is always printed in verbose
  845. **    mode and does not return an error-status-code.
  846. ***^^**********************************************************************/
  847. static  BOOL  Usage_Requested = (BOOL) FALSE;
  848. X
  849. X
  850. X   /* macros to detect an option/keyword -- watch out for side effects!! */
  851. #define isOPT(s)  \
  852. X   ( !BTEST(cmd_flags(cmd), pa_KWDSONLY)  && \
  853. X     !BTEST(cmd_state(cmd), ps_NOFLAGS)  && \
  854. X     *s == c_OPT_PFX  &&  *(s+1) \
  855. X   )
  856. X
  857. #define isKWD(s)  \
  858. X   ( !BTEST(cmd_flags(cmd), pa_OPTSONLY)  && \
  859. X     !BTEST(cmd_state(cmd), ps_NOFLAGS)  && \
  860. X     *s == c_KWD_PFX  &&  *(s+1) \
  861. X   )
  862. X
  863. X
  864. /***************************************************************************
  865. ** ^FUNCTION: unix_parse - parse Unix arg-vectors
  866. **
  867. ** ^SYNOPSIS:
  868. */
  869. #ifndef __ANSI_C__
  870. X   int unix_parse( argv, argd )
  871. /*  
  872. ** ^PARAMETERS:
  873. */
  874. X   char *argv[];
  875. /*    -- the vector of string arguments from the command-line
  876. */
  877. X   ARGDESC argd[];
  878. /*    -- the programmer description of the command and its args
  879. */
  880. #endif  /* !__ANSI_C__ */
  881. X
  882. /* ^DESCRIPTION:
  883. **    Unix_parse will parse the arguments in the given vector of strings,
  884. **    assign the corresponding values to the command-line arguments specified
  885. **    in argd, and check the syntax of the command-line.
  886. **
  887. ** ^REQUIREMENTS:
  888. **    The final element in argv must be a NULL pointer.
  889. **
  890. ** ^SIDE-EFECTS:
  891. **    argd is modified according to the command-line description and parameters
  892. **
  893. ** ^RETURN-VALUE:
  894. **    pe_SUCCESS (0) if no errors are encountered
  895. **    pe_SYSTEM (-1) if a system error is encountered
  896. **    pe_SYNTAX if a syntax error is encountered
  897. **
  898. ** ^ALGORITHM:
  899. **    - for each command-line argument
  900. **       - attempt to match the argument as a keyword
  901. **       - if it is a keyword argument
  902. **          - record and convert its value (if any)
  903. **         else attempt to match the argument as an option
  904. **         if it is an option
  905. **          - record and convert its value (if any)
  906. **         else it is a positional parameter
  907. **          - record and convert its value (if any)
  908. **         else there are too many arguments
  909. **          - return pe_SYNTAX
  910. **         end-if
  911. **       end-for
  912. ***^^**********************************************************************/
  913. #ifdef __ANSI_C__
  914. X   int unix_parse( char *argv[], ARGDESC argd[] )
  915. #endif
  916. {
  917. X   register ARGDESC *ad, *args, *cmd;
  918. X   register char **av = argv;
  919. X   register char *p;
  920. X   argName_t  name;
  921. X   argMask_t  flags;
  922. X   int  parse_error = pe_SUCCESS;
  923. X   BOOL  ad_okay, is_match = FALSE;
  924. X
  925. X   if ( !argd )  return  parse_error;
  926. X
  927. X      /* initialize command-structure */
  928. X   if ( !CMD_isINIT(argd) )  init_args( argd );
  929. X   cmd = argd;
  930. X
  931. X   while ( av  &&  (p = *av++) ) {
  932. X      if ( isKWD(p) ) {
  933. X         char *s, c = '\0';
  934. X
  935. X         /* check for `++' to end flags */
  936. X         if ( *(p+1) == c_KWD_PFX  &&  !*(p+2) ) {
  937. X            BSET( cmd_state(cmd), ps_NOFLAGS );
  938. X            cmd_list(cmd) = ARGDESCNULL;
  939. X            continue;
  940. X         }
  941. X
  942. X            /* get past prefix and look for possible argument */
  943. X         s = strpbrk(++p, s_ARG_SEP);
  944. X         if(s) {
  945. X            c = *s;
  946. X            *s++ = '\0';
  947. X         }
  948. X
  949. X         is_match = FALSE;
  950. X         for ( args = argd ; args  &&  !is_match ; args = cmd_defargs(args) ) {
  951. X            for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  952. X               if ( arg_type(ad) == argDummy )  continue;
  953. X
  954. X               if ( !ARG_isPOSONLY(ad)  &&  match(p, arg_sname(ad)) == 0 ) {
  955. X                  is_match = TRUE;
  956. X                  break;
  957. X               }/*if*/
  958. X            }
  959. X         }
  960. X
  961. X         if ( c )  *(s-1) = c;  /* restore the equal sign */
  962. X
  963. X         if ( !is_match ) {
  964. X            usrerr("option %c%s unknown", c_KWD_PFX, p);
  965. X            parse_error = pe_SYNTAX;
  966. X            cmd_list(cmd) = ARGDESCNULL;
  967. X            continue;
  968. X         }
  969. X
  970. X         flags = arg_flags(ad);
  971. X         if ( ARG_isGIVEN(ad) )
  972. X            BCLEAR( arg_flags(ad), ARGVALSEP | ARGVALGIVEN | ARGKEYWORD );
  973. X
  974. X         BSET( arg_flags(ad), ARGKEYWORD );
  975. X
  976. X         if( ARG_isMULTIVAL(ad) ) {
  977. X            cmd_list(cmd) = ad;
  978. X         }
  979. X         else {
  980. X            cmd_list(cmd) = ARGDESCNULL;
  981. X         }
  982. X
  983. X            /* if usage - just print usage and exit */
  984. X         if ( arg_type(ad) == argUsage ) {
  985. X            Usage_Requested = TRUE;
  986. X            usage(argd);
  987. X            exit(1);
  988. X         }
  989. X
  990. X            /* ARGNOVALs are special, having no value */
  991. X         if ( ! ARG_isVALTAKEN(ad) ) {
  992. X            ad_okay = HANDLE(ad, s, cmd_flags(cmd));
  993. X            if ( !ad_okay ) {
  994. X               arg_flags(ad) = flags;
  995. X               parse_error = pe_SYNTAX;
  996. X            }
  997. X            else {
  998. X               BSET( arg_flags(ad), ARGGIVEN );
  999. X               ad = ARGDESCNULL;
  1000. X            }
  1001. X            continue;
  1002. X         }/*if ARGNOVAL*/
  1003. X
  1004. X            /* now get the real value */
  1005. X         if (!s) {
  1006. X            s = *av++;
  1007. X            if ( !s  ||  isOPT(s)  ||  isKWD(s) ) {
  1008. X               if ( ARG_isVALOPTIONAL(ad) ) {
  1009. X                  BSET( arg_flags(ad), ARGGIVEN );
  1010. X               }
  1011. X               else {
  1012. X                  (VOID) get_keyword( arg_sname(ad), name );
  1013. X                  usrerr("option %c%s requires an argument", c_KWD_PFX, name);
  1014. X                  arg_flags(ad) = flags;
  1015. X                  parse_error = pe_SYNTAX;
  1016. X               }
  1017. X
  1018. X               av--;
  1019. X               continue;
  1020. X            }/*if arg*/
  1021. X            BSET( arg_flags(ad), ARGVALSEP );
  1022. X         }/*if empty*/
  1023. X
  1024. X            /* try to convert the type */
  1025. X         ad_okay = HANDLE(ad, s, cmd_flags(cmd));
  1026. X         if ( !ad_okay ) {
  1027. X            arg_flags(ad) = flags;
  1028. X            parse_error = pe_SYNTAX;
  1029. X         }
  1030. X         else {
  1031. X            BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  1032. X         }
  1033. X
  1034. X         continue;
  1035. X      }/*if keyword*/
  1036. X
  1037. X      else if ( isOPT(p) ) {
  1038. X         p++;  /* skip over option prefix */
  1039. X
  1040. X            /* check for `--' to end flags */
  1041. X         if ( *p == c_OPT_PFX  &&  !*(p+1) ) {
  1042. X            BSET( cmd_state(cmd), ps_NOFLAGS );
  1043. X            cmd_list(cmd) = ARGDESCNULL;
  1044. X            continue;
  1045. X         }
  1046. X
  1047. X            /* flag argument */
  1048. X         while (*p) {
  1049. X
  1050. X               /* find the flag in the list */
  1051. X            is_match = FALSE;
  1052. X            for (args = argd; args  &&  !is_match ; args = cmd_defargs(args)) {
  1053. X               for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1054. X                  register char c1 = arg_cname(ad);
  1055. X                  register char c2 = *p;
  1056. X
  1057. X                  if ( arg_type(ad) == argDummy )   continue;
  1058. X                  if ( ARG_isPOSONLY(ad) )   continue;
  1059. X
  1060. X                  if ( BTEST(cmd_flags(cmd), pa_ANYCASE) ) {
  1061. X                     c1 = TOUPPER( c1 );
  1062. X                     c2 = TOUPPER( c2 );
  1063. X                  }/*if*/
  1064. X
  1065. X                  if ( c1 == c2 ) {
  1066. X                     is_match = TRUE;
  1067. X                     break;
  1068. X                  }/*if*/
  1069. X               }
  1070. X            }
  1071. X            if ( !is_match ) {
  1072. X                  usrerr("option %c%c unknown", c_OPT_PFX, *p++);
  1073. X                  parse_error = pe_SYNTAX;
  1074. X                  cmd_list(cmd) = ARGDESCNULL;
  1075. X                  continue;
  1076. X            }/* if unknown-option */
  1077. X
  1078. X            flags = arg_flags(ad);
  1079. X            if ( ARG_isGIVEN(ad) )
  1080. X               BCLEAR( arg_flags(ad), ARGVALSEP | ARGVALGIVEN | ARGKEYWORD );
  1081. X
  1082. X            if( ARG_isMULTIVAL(ad) ) {
  1083. X               cmd_list(cmd) = ad;
  1084. X            }
  1085. X            else {
  1086. X               cmd_list(cmd) = ARGDESCNULL;
  1087. X            }
  1088. X
  1089. X               /* move p up to point to the (possible) value */
  1090. X            p++;
  1091. X
  1092. X            /* if usage - just print usage and exit */
  1093. X            if (arg_type(ad) == argUsage) {
  1094. X               Usage_Requested = TRUE;
  1095. X               usage(argd);
  1096. X               exit(1);
  1097. X            }
  1098. X
  1099. X               /* ARGNOVALs are special, having no value */
  1100. X            if (! ARG_isVALTAKEN(ad)) {
  1101. X               ad_okay = HANDLE(ad, p, cmd_flags(cmd));
  1102. X
  1103. X               if ( !ad_okay ) {
  1104. X                  arg_flags(ad) = flags;
  1105. X                  parse_error = pe_SYNTAX;
  1106. X               }/*if*/
  1107. X               else {
  1108. X                  BSET( arg_flags(ad), ARGGIVEN );
  1109. X                  ad = ARGDESCNULL;
  1110. X                  if ( ad_okay < 0 )  p -= ad_okay;
  1111. X               }/*else*/
  1112. X
  1113. X               continue;
  1114. X            }/*if*/
  1115. X
  1116. X               /* now get the real value */
  1117. X            if ( !(*p) ) {
  1118. X               p = *av++;
  1119. X               if ( !p  ||  isOPT(p)  ||  isKWD(p) ) {
  1120. X                  if ( ARG_isVALOPTIONAL(ad) ) {
  1121. X                     BSET( arg_flags(ad), ARGGIVEN );
  1122. X                  }
  1123. X                  else {
  1124. X                     (VOID) get_name(arg_sname(ad), name);
  1125. X                     usrerr( "%s required for %c%c flag",
  1126. X                             name, c_OPT_PFX, arg_cname(ad) );
  1127. X                     arg_flags(ad) = flags;
  1128. X                     parse_error = pe_SYNTAX;
  1129. X                  }/*else*/
  1130. X
  1131. X                  av--;
  1132. X                  break;
  1133. X               }/*if arg*/
  1134. X               BSET( arg_flags(ad), ARGVALSEP );
  1135. X            }/*if empty*/
  1136. X
  1137. X               /* try to convert the type */
  1138. X            ad_okay = HANDLE(ad, p, cmd_flags(cmd));
  1139. X            if ( !ad_okay ) {
  1140. X               arg_flags(ad) = flags;
  1141. X               parse_error = pe_SYNTAX;
  1142. X               p += strlen(p);
  1143. X            }/*if*/
  1144. X            else {
  1145. X               BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  1146. X               if ( ad_okay < 0  &&  !ARG_isVALSEPARATE(ad) ) {
  1147. X                  p -= ad_okay;
  1148. X               }
  1149. X               else {
  1150. X                  p += strlen(p);
  1151. X               }
  1152. X            }/*else*/
  1153. X
  1154. X         }/*while*/
  1155. X      }/*elif option*/
  1156. X      else {
  1157. X            /* parsing a list of arguments */
  1158. X         if( cmd_list(cmd) ) {
  1159. X            ad = cmd_list(cmd);
  1160. X            flags = arg_flags(ad);
  1161. X            if ( ARG_isGIVEN(ad) )
  1162. X               BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP | ARGKEYWORD );
  1163. X
  1164. X            BSET( arg_flags(ad), ARGVALSEP );
  1165. X
  1166. X            ad_okay = HANDLE(ad, p, cmd_flags(cmd));
  1167. X            if ( !ad_okay ) {
  1168. X               arg_flags(ad) = flags;
  1169. X               parse_error = pe_SYNTAX;
  1170. X            }
  1171. X
  1172. X            continue;
  1173. X         }
  1174. X            /* positional argument */
  1175. X         is_match = FALSE;
  1176. X         for (args = argd; args  &&  !is_match ; args = cmd_defargs(args)) {
  1177. X            for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1178. X               if (arg_type(ad) == argDummy)  continue;
  1179. X
  1180. X               if ( ARG_isPOSITIONAL(ad)  &&
  1181. X                    (!ARG_isGIVEN(ad) ||  ARG_isMULTIVAL(ad)) ) {
  1182. X                  is_match = TRUE;
  1183. X                  break;
  1184. X               }/*if*/
  1185. X            }
  1186. X         }
  1187. X
  1188. X         if ( !is_match ) {
  1189. X            usrerr("too any arguments");
  1190. X            parse_error = pe_SYNTAX;
  1191. X            continue;
  1192. X         }
  1193. X
  1194. X         flags = arg_flags(ad);
  1195. X         if ( ARG_isGIVEN(ad) )
  1196. X            BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGKEYWORD | ARGVALSEP );
  1197. X
  1198. X         if ( ARG_isMULTIVAL(ad) ) {
  1199. X            cmd_list(cmd) = ad;
  1200. X         }
  1201. X
  1202. X         if ( BTEST(cmd_flags(cmd), pa_FLAGS1ST) ) {
  1203. X            BSET( cmd_state(cmd), ps_NOFLAGS );
  1204. X         }
  1205. X
  1206. X         BSET( arg_flags(ad), ARGVALSEP );
  1207. X
  1208. X            /* try to convert */
  1209. X         ad_okay = HANDLE(ad, p, cmd_flags(cmd));
  1210. X         if ( !ad_okay ) {
  1211. X            arg_flags(ad) = flags;
  1212. X            parse_error = pe_SYNTAX;
  1213. X         }
  1214. X         else {
  1215. X            BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
  1216. X         }
  1217. X      }/*else*/
  1218. X   }/*while*/
  1219. X
  1220. X   return  parse_error;
  1221. }
  1222. X
  1223. X
  1224. /***************************************************************************
  1225. ** ^FUNCTION: fmtarg - format command-argument syntax
  1226. **
  1227. ** ^SYNOPSIS:
  1228. */
  1229. #ifndef __ANSI_C__
  1230. X   static int fmtarg( ad, buf, usgflags )
  1231. /*
  1232. ** ^PARAMETERS:
  1233. */
  1234. X   ARGDESC *ad;
  1235. /*    -- pointer to the argument to format
  1236. */
  1237. X   char *buf;
  1238. /*    -- character buffer to hold the formatted result
  1239. */
  1240. X   argMask_t usgflags;
  1241. /*    -- set of bitmasks corresponding to the value of the user's USAGECNTL
  1242. **       environment variable
  1243. */
  1244. #endif  /* !__ANSI_C__ */
  1245. X
  1246. /* ^DESCRIPTION:
  1247. **    Fmtarg will determine the proper command-line syntax for the
  1248. **    given argument and write the result to the given buffer.
  1249. **
  1250. ** ^REQUIREMENTS:
  1251. **    buf must be large enough to hold the formatted result (100 characters
  1252. **    should do the trick).
  1253. **
  1254. ** ^SIDE-EFECTS:
  1255. **    buf is overwritten.
  1256. **
  1257. ** ^RETURN-VALUE:
  1258. **    The number of printable characters in the argument-syntax-string
  1259. **
  1260. ** ^ALGORITHM:
  1261. **    Print argument usage based on whether or not the argument is
  1262. **    positional, hidden, multi-valued (list or vector), etc ....
  1263. **    Optional arguments and values are enclosed in square braces.
  1264. **
  1265. **    Any syntax biases reflected in usgflags will be used.
  1266. ***^^**********************************************************************/
  1267. #ifdef __ANSI_C__
  1268. X   static int fmtarg ( const ARGDESC *ad, char *buf, argMask_t usgflags )
  1269. #endif
  1270. {
  1271. X   /* buf must already be large enough */
  1272. X   char *pos;
  1273. X   argName_t   name, keyword;
  1274. X
  1275. X   (VOID) get_name( arg_sname(ad), name );
  1276. X
  1277. X   if (ARG_isPOSITIONAL(ad)) {
  1278. X      sprintf( buf, "<%s>", name );
  1279. X   }
  1280. X   else {
  1281. X      (VOID) get_keyword( arg_sname(ad), keyword );
  1282. X
  1283. X      if ( isupper(arg_cname(ad))  &&  toupper(*keyword) == arg_cname(ad) ) {
  1284. X         *keyword = toupper(*keyword);
  1285. X      }
  1286. X
  1287. X      if ( !(usgflags & usg_LONGOPTS) ) {
  1288. X         sprintf( buf, "%c%c", c_OPT_PFX, arg_cname(ad) );
  1289. X      }
  1290. X      else if ( !(usgflags & usg_OPTS) ) {
  1291. X         sprintf( buf, "%c%s", c_KWD_PFX, keyword );
  1292. X      }
  1293. X      else  {  /* use both */
  1294. X         sprintf( buf, "%c%c|%c%s", c_OPT_PFX, arg_cname(ad),
  1295. X                                    c_KWD_PFX, keyword );
  1296. X      }
  1297. X
  1298. X      pos = buf + strlen(buf);
  1299. X
  1300. X      if ( ARG_isVALTAKEN(ad)  &&  !ARG_isBOOLEAN(ad) &&  !ARG_isPSEUDOARG(ad) )
  1301. X      {
  1302. X         *(pos++) = ' ';
  1303. X
  1304. X         if  (ARG_isVALOPTIONAL(ad)) {
  1305. X            sprintf( pos, "[<%s>]", name);
  1306. X         }
  1307. X         else {
  1308. X            sprintf( pos, "<%s>", name );
  1309. X         }
  1310. X      }/*if*/
  1311. X   }/*else*/
  1312. X
  1313. X   return  strlen(buf);
  1314. }
  1315. X
  1316. X
  1317. /***************************************************************************
  1318. ** ^FUNCTION: unix_usage - print a usage message
  1319. **
  1320. ** ^SYNOPSIS:
  1321. */
  1322. #ifndef __ANSI_C__
  1323. X   VOID unix_usage( argd, usage_flags )
  1324. /*
  1325. ** ^PARAMETERS:
  1326. */
  1327. X   ARGDESC *argd;
  1328. /*    -- the command-descriptor array
  1329. */
  1330. X   argMask_t usage_flags;
  1331. /*    -- flags set by $USAGECNTL
  1332. */
  1333. #endif  /* !__ANSI_C__ */
  1334. X
  1335. /* ^DESCRIPTION:
  1336. **    Unix_usage will print the Unix command-line usage of the given
  1337. **    command on standard diagnostic output (stderr). The content of the
  1338. **    usage message is controlled by the bitmasks in usage_flags which
  1339. **    correspond to the settings in the user's USAGECNTL variable.
  1340. **
  1341. ** ^REQUIREMENTS:
  1342. **    argd should be a non-null command-line argument-descriptor array
  1343. **
  1344. ** ^SIDE-EFECTS:
  1345. **    Prints on stderr.
  1346. **
  1347. ** ^RETURN-VALUE:
  1348. **    None.
  1349. **
  1350. ** ^ALGORITHM:
  1351. **    - if no usage is desired then exit
  1352. **    - if paging is requested print to the pager instead of stderr
  1353. **    - print the command-line syntax
  1354. **    - if the description is requested print it
  1355. **    - if verbose mode is requested, print the description of each argument
  1356. ***^^**********************************************************************/
  1357. #ifdef __ANSI_C__
  1358. X   void unix_usage ( const ARGDESC *argd, argMask_t usage_flags )
  1359. #endif
  1360. {
  1361. X   register CONST ARGDESC *ad, *args, *cmd;
  1362. X   int  max_cols = 80, max_lines  = 24;
  1363. X   int  ll, margin, options, longest, positionals;
  1364. X   BOOL first = TRUE;
  1365. X   FILE *fp;
  1366. X
  1367. X   if ( !argd )  return;
  1368. X
  1369. X      /* initialize command-structure */
  1370. X   if ( !CMD_isINIT(argd) )  init_args( (ARGDESC *)argd );
  1371. X   cmd = argd;
  1372. X
  1373. X      /* force verbose-mode if requested */
  1374. X   if ( Usage_Requested )   BSET( usage_flags, usg_VERBOSE );
  1375. X
  1376. X   if ( BTEST(usage_flags, usg_NONE) )  return;
  1377. X
  1378. X   fp = ( BTEST(usage_flags, usg_PAGED) )
  1379. X      ? pgopen( stderr, getenv("USAGE_PAGER") )
  1380. X      : stderr;
  1381. X
  1382. X      /* get screen size */
  1383. X   get_winsize( fileno(fp), &max_lines, &max_cols );
  1384. X
  1385. X   fprintf(fp, "Usage: %s", ProgName);
  1386. X
  1387. X   ll = strlen( ProgName ) + 7;
  1388. X   margin = ll + 1;
  1389. X   longest = 0;
  1390. X
  1391. X      /* print Synopsis */
  1392. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  1393. X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
  1394. X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1395. X            argName_t  buf;
  1396. X            int pl;
  1397. X
  1398. X               /* don't display hidden arguments */
  1399. X            if ( ARG_isHIDDEN(ad) )  continue;
  1400. X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  1401. X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  1402. X
  1403. X               /* figure out how wide this parameter is (for printing) */
  1404. X            pl = fmtarg(ad, buf, usage_flags);
  1405. X
  1406. X            if ( pl > longest)  longest = pl;
  1407. X
  1408. X            if  ( ARG_isMULTIVAL(ad) ) {
  1409. X               strcat( buf, "..." );
  1410. X               pl += 3;
  1411. X            }
  1412. X            if ( !ARG_isREQUIRED(ad) ) {
  1413. X               pl += 2;
  1414. X            }
  1415. X
  1416. X            /* see if this will fit */
  1417. X            if ( (ll + pl + 1) > (max_cols - first) ) {
  1418. X                  /* no... start a new line */
  1419. X               fprintf(fp, "\n%*s", margin, "");
  1420. X               ll = margin;
  1421. X            }
  1422. X            else {
  1423. X                  /* yes... just throw in a space */
  1424. X               fputc(' ', fp);
  1425. X               ++ll;
  1426. X            }
  1427. X            ll += pl;
  1428. X
  1429. X               /* show the argument */
  1430. X            if ( !ARG_isREQUIRED(ad) )  fputc('[', fp);
  1431. X            fprintf(fp, buf);
  1432. X            if ( !ARG_isREQUIRED(ad) )  fputc(']', fp);
  1433. X
  1434. X            first = FALSE;  /* not first line anymore */
  1435. X         }/*for each ad */
  1436. X      }/* for each argd */
  1437. X   }/* for each parm-type */
  1438. X
  1439. X   fputc('\n', fp);
  1440. X
  1441. X   if ( BTEST(usage_flags, usg_DESCRIPTION) ) {
  1442. X      CONST char *description = cmd_description(cmd);
  1443. X
  1444. X      if ( description  &&  *description ) {
  1445. X         fprintf( fp, "Description:\n" );
  1446. X         indent_para(fp, max_cols, 8, "", 0, description);
  1447. X         fputc( '\n', fp );
  1448. X      }
  1449. X   }/*if*/
  1450. X
  1451. X   if ( !BTEST(usage_flags, usg_VERBOSE) )  {
  1452. X      if ( pgactive(fp) )  (VOID) pgclose( fp );
  1453. X      return;
  1454. X   }
  1455. X
  1456. X   options = 0;
  1457. X
  1458. X      /* print Argument descriptions */
  1459. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  1460. X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
  1461. X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1462. X            argName_t  buf;
  1463. X
  1464. X               /* don't display hidden arguments */
  1465. X            if ( ARG_isHIDDEN(ad) )  continue;
  1466. X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  1467. X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  1468. X
  1469. X            if ( !options++ )   fprintf(fp, "Options/Arguments:\n");
  1470. X            fmtarg(ad, buf, usage_flags);
  1471. X            indent_para( fp, max_cols, 8, buf, longest+2, arg_description(ad) );
  1472. X         }/*for each ad */
  1473. X      }/* for each argd */
  1474. X   }/* for each parm-type */
  1475. X
  1476. X   if ( pgactive(fp) )  (VOID) pgclose( fp );
  1477. }
  1478. X
  1479. SHAR_EOF
  1480. chmod 0664 parseargs/unix_args.c ||
  1481. echo 'restore of parseargs/unix_args.c failed'
  1482. Wc_c="`wc -c < 'parseargs/unix_args.c'`"
  1483. test 20417 -eq "$Wc_c" ||
  1484.     echo 'parseargs/unix_args.c: original size 20417, current size' "$Wc_c"
  1485. rm -f _shar_wnt_.tmp
  1486. fi
  1487. # ============= parseargs/unix_man.c ==============
  1488. if test -f 'parseargs/unix_man.c' -a X"$1" != X"-c"; then
  1489.     echo 'x - skipping parseargs/unix_man.c (File already exists)'
  1490.     rm -f _shar_wnt_.tmp
  1491. else
  1492. > _shar_wnt_.tmp
  1493. echo 'x - extracting parseargs/unix_man.c (Text)'
  1494. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/unix_man.c' &&
  1495. /*************************************************************************
  1496. ** ^FILE: unix_man.c - print manual templates for user command
  1497. **
  1498. ** ^DESCRIPTION:
  1499. **    This file is the portion of parseargs(1) that prints a Unix
  1500. **    manual template of a given command on the standard output.
  1501. **    The template is formatted for {n|t}roff using the -man macros.
  1502. **
  1503. ** ^HISTORY:
  1504. **    01/02/91     Brad Appleton     <brad@ssd.csd.harris.com>     Created
  1505. ***^^**********************************************************************/
  1506. X
  1507. #include <stdio.h>
  1508. #include <ctype.h>
  1509. #include <useful.h>
  1510. #include "strfuncs.h"
  1511. X
  1512. #define PARSEARGS_PRIVATE   /* include private definitions */
  1513. #include "parseargs.h"
  1514. X
  1515. EXTERN  VOID  syserr  ARGS((const char *, ...));
  1516. EXTERN  VOID  usrerr  ARGS((const char *, ...));
  1517. X
  1518. #define MAXCOLS  65
  1519. #define VAL(str)           ((str) ? str : "")
  1520. #define COMMENT            printf(".\\\"-----------------------------------\n")
  1521. #define TH(title,section)  printf(".TH %s %d\n", title, section )
  1522. #define SH(title)          printf(".SH %s\n", title )
  1523. #define TP(cols,title)     printf(".TP %d\n%s\n", cols, title )
  1524. #define PP                 printf(".PP\n" )
  1525. X
  1526. X
  1527. /***************************************************************************
  1528. ** ^FUNCTION: fmtarg - format command-argument syntax
  1529. **
  1530. ** ^SYNOPSIS:
  1531. */
  1532. #ifndef __ANSI_C__
  1533. X   static int fmtarg( ad, buf )
  1534. /*
  1535. ** ^PARAMETERS:
  1536. */
  1537. X   ARGDESC *ad;
  1538. /*    -- pointer to the argument to format
  1539. */
  1540. X   char *buf;
  1541. /*    -- character buffer to hold the formatted result
  1542. */
  1543. #endif  /* !__ANSI_C__ */
  1544. X
  1545. /* ^DESCRIPTION:
  1546. **    Fmtarg will determine the proper command-line syntax for the
  1547. **    given argument and write the result to the given buffer.
  1548. **
  1549. ** ^REQUIREMENTS:
  1550. **    buf must be large enough to hold the formatted result (100 characters
  1551. **    should do the trick).
  1552. **
  1553. ** ^SIDE-EFECTS:
  1554. **    buf is overwritten.
  1555. **
  1556. ** ^RETURN-VALUE:
  1557. **    The number of printable characters in the argument-syntax-string
  1558. **
  1559. ** ^ALGORITHM:
  1560. **    Print argument usage based on whether or not the argument is
  1561. **    positional, hidden, multi-valued (list or vector), etc ....
  1562. **    Optional arguments and values are enclosed in square braces.
  1563. ***^^**********************************************************************/
  1564. #ifdef __ANSI_C__
  1565. X   static int fmtarg( const ARGDESC *ad , char *buf )
  1566. #endif
  1567. {
  1568. X      /* buf must already be large enough */
  1569. X   char *pos;
  1570. X   argName_t   name;
  1571. X
  1572. X   (VOID) get_name( arg_sname(ad), name );
  1573. X
  1574. X   if (ARG_isPOSITIONAL(ad)) {
  1575. X       if ( ARG_isMULTIVAL(ad) ) {
  1576. X          sprintf( buf, "\\fI%s\\fP\\ ...", name );
  1577. X          return   (strlen(name) + 4);
  1578. X       }/*if list*/
  1579. X
  1580. X       sprintf( buf, "\\fI%s\\fP", name );
  1581. X       return  strlen(name);
  1582. X   }/*if parm*/
  1583. X
  1584. X   sprintf(buf, "\\fB\-%c\\fP", arg_cname(ad));
  1585. X   pos = buf + strlen(buf);
  1586. X
  1587. X   if ( ARG_isVALTAKEN(ad)  &&  !ARG_isBOOLEAN(ad)  &&  !ARG_isPSEUDOARG(ad) ) {
  1588. X       if ( ARG_isMULTIVAL(ad) ) {
  1589. X          if ( ARG_isVALOPTIONAL(ad) ) {
  1590. X             sprintf(pos, "\\ \\s-1[\\s+1\\fI%s\\fP\\ ...\\s-1]\\s+1", name);
  1591. X             return  (strlen(name) + 9);
  1592. X          }/*if optarg*/
  1593. X
  1594. X          sprintf( pos, "\\ \\fI%s\\ ...\\fP", name );
  1595. X          return  (strlen(name) + 7);
  1596. X       }/*if list*/
  1597. X
  1598. X       if ( ARG_isVALOPTIONAL(ad) ) {
  1599. X          sprintf( pos, "\\ \\s-1[\\s+1\\fI%s\\fP\\s-1]\\s+1", name );
  1600. X          return  (strlen(name) + 5);
  1601. X       }/*if optarg*/
  1602. X
  1603. X       sprintf( pos, "\\ \\fI%s\\fP", name );
  1604. X       return  (strlen(name) + 3);
  1605. X   }/*if*/
  1606. X
  1607. X   return  2;
  1608. }
  1609. X
  1610. X
  1611. /***************************************************************************
  1612. ** ^FUNCTION: manpage - print the manual template
  1613. **
  1614. ** ^SYNOPSIS:
  1615. */
  1616. #ifndef __ANSI_C__
  1617. X   VOID manpage ( argd )
  1618. /*
  1619. ** ^PARAMETERS:
  1620. */
  1621. X   ARGDESC *argd;
  1622. /*    -- the command-argdesc-array
  1623. */
  1624. #endif  /* !__ANSI_C__ */
  1625. X
  1626. /* ^DESCRIPTION:
  1627. **    Manpage print on standard output, a Unix manual template for the
  1628. **    given command. The NAME, SYNOPSIS, and OPTIONS sections are filled
  1629. **    in and the DESCRIPTION section is partially filled in with any
  1630. **    known command-description. The FILES, SEE ALSO, DIAGNOSTICS, CAVEATS,
  1631. **    BUGS, AUTHOR, and HISTORY section titles are provided but the body
  1632. **    of each section must be composed by the documentor.
  1633. **
  1634. ** ^REQUIREMENTS:
  1635. **    Argd should be a valid command-line descriptor array.
  1636. **
  1637. ** ^SIDE-EFECTS:
  1638. **    Prints on standard-output.
  1639. **
  1640. ** ^RETURN-VALUE:
  1641. **    None.
  1642. **
  1643. ** ^ALGORITHM:
  1644. **    - print .TH setting followed by NAME section.
  1645. **    - cycle through each argument and print is syntax for the SYNOPSIS.
  1646. **    - print the description (if it exists).
  1647. **    - cycle through each argument again and print its syntax and description
  1648. **      for the OPTIONS section.
  1649. **    - print just the headings for the remaining sections.
  1650. ***^^**********************************************************************/
  1651. #ifdef __ANSI_C__
  1652. X   void manpage( const ARGDESC *argd )
  1653. #endif
  1654. {
  1655. X   register CONST ARGDESC *ad, *args, *cmd;
  1656. X   argName_t  name;
  1657. X   CONST char *program, *purpose, *description;
  1658. X   int   len, maxlen, positionals;
  1659. X
  1660. X      /* allow null argument descriptor */
  1661. X   if ( !argd )  return;
  1662. X
  1663. X   if ( !CMD_isINIT(argd) )   init_args( (ARGDESC *)argd );
  1664. X   cmd = argd;
  1665. X
  1666. X   (VOID) strcpy( name, cmd_name(cmd) );
  1667. X   if ( cmd_name(cmd) ) {
  1668. X      program = cmd_name(cmd);
  1669. X   }
  1670. X   else if ( cmd_argv0(cmd) ) {
  1671. X      program = cmd_argv0(cmd);
  1672. X   }
  1673. X
  1674. X   purpose = cmd_purpose(cmd);
  1675. X   description = cmd_description(cmd);
  1676. X
  1677. X   printf(".\\\"---------- TO PRINT, USE: {n,t}roff -man file ----------\n");
  1678. X   printf(".if n .po 1\n");
  1679. X   printf(".if n .ll 78\n");
  1680. X
  1681. X   COMMENT;
  1682. X   TH( strupr(name), 1 );
  1683. X
  1684. X   COMMENT;
  1685. X   SH( "NAME" );
  1686. X   printf( "%s \\- %s\n", VAL(program), VAL(purpose) );
  1687. X
  1688. X   COMMENT;
  1689. X   SH( "SYNOPSIS" );
  1690. X
  1691. X   len = strlen( program ) + 1;
  1692. X   sprintf( name, "\\fB%s\\fP", program );
  1693. X   TP( len, name );
  1694. X
  1695. X   maxlen = 0;
  1696. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  1697. X     for ( args = argd ; args ; args = cmd_defargs(args) ) {
  1698. X        for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1699. X           argName_t  buf;
  1700. X
  1701. X              /* don't display hidden arguments */
  1702. X           if ( ARG_isHIDDEN(ad) )  continue;
  1703. X           if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  1704. X           if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  1705. X
  1706. X           len = fmtarg( ad, buf );
  1707. X           if ( len > maxlen )   maxlen = len;
  1708. X
  1709. X           if ( ARG_isREQUIRED(ad) ) {
  1710. X               printf( "%s\n", buf );
  1711. X           }
  1712. X           else {
  1713. X               printf( "[%s]\n", buf );
  1714. X           }
  1715. X        }/*for each ad */
  1716. X     }/* for each argd */
  1717. X   }/* for each parm-type */
  1718. X
  1719. X   COMMENT;
  1720. X   SH( "DESCRIPTION" );
  1721. X   PP;
  1722. X   indent_para(stdout, MAXCOLS, 0, "", 0, VAL(description) );
  1723. X
  1724. X   COMMENT;
  1725. X   SH( "OPTIONS" );
  1726. X
  1727. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  1728. X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
  1729. X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1730. X            argName_t  buf;
  1731. X
  1732. X               /* don't display hidden arguments */
  1733. X            if ( ARG_isHIDDEN(ad) )  continue;
  1734. X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  1735. X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  1736. X
  1737. X            (VOID) fmtarg( ad, buf );
  1738. X            TP( maxlen + 2, buf );
  1739. X            indent_para(stdout, MAXCOLS, 0, "", 0, arg_description(ad) );
  1740. X         }/*for each ad */
  1741. X      }/* for each argd */
  1742. X   }/* for each parm-type */
  1743. X
  1744. X   COMMENT;
  1745. X   SH( "FILES" );
  1746. X   PP;
  1747. X
  1748. X   COMMENT;
  1749. X   SH( "SEE ALSO" );
  1750. X   PP;
  1751. X
  1752. X   COMMENT;
  1753. X   SH( "DIAGNOSTICS" );
  1754. X   PP;
  1755. X
  1756. X   COMMENT;
  1757. X   SH( "CAVEATS" );
  1758. X   PP;
  1759. X
  1760. X   COMMENT;
  1761. X   SH( "BUGS" );
  1762. X   PP;
  1763. X
  1764. X   COMMENT;
  1765. X   SH( "AUTHOR" );
  1766. X   PP;
  1767. X
  1768. X   COMMENT;
  1769. X   SH( "HISTORY" );
  1770. X   PP;
  1771. }
  1772. SHAR_EOF
  1773. chmod 0664 parseargs/unix_man.c ||
  1774. echo 'restore of parseargs/unix_man.c failed'
  1775. Wc_c="`wc -c < 'parseargs/unix_man.c'`"
  1776. test 7749 -eq "$Wc_c" ||
  1777.     echo 'parseargs/unix_man.c: original size 7749, current size' "$Wc_c"
  1778. rm -f _shar_wnt_.tmp
  1779. fi
  1780. # ============= parseargs/useful.h ==============
  1781. if test -f 'parseargs/useful.h' -a X"$1" != X"-c"; then
  1782.     echo 'x - skipping parseargs/useful.h (File already exists)'
  1783.     rm -f _shar_wnt_.tmp
  1784. else
  1785. > _shar_wnt_.tmp
  1786. echo 'x - extracting parseargs/useful.h (Text)'
  1787. sed 's/^X//' << 'SHAR_EOF' > 'parseargs/useful.h' &&
  1788. /*************************************************************************
  1789. ** ^FILE: useful.h - various definitions of general interest
  1790. **
  1791. ** ^DESCRIPTION:
  1792. **    This file #defines several macros that are either of very general
  1793. **    use, or that assist in writing portable programs between various
  1794. **    systems and/or compilers.
  1795. **
  1796. ** ^HISTORY:
  1797. **    --/--/--    Brad Appleton    <brad@ssd.csd.harris.com>    
  1798. **    - Added structured block comments
  1799. **    - Added varargs/stdarg macros
  1800. **    - Added BSET, BCLEAR, BTEST macros for handling bitmasks
  1801. **    - #defined EXTERN to be extern "C" for C++
  1802. **    - Added #defines for STDIN, STDOUT, and STDERR file descriptors
  1803. **
  1804. **    --/--/--    Peter da Silva    <peter@ferranti.com>    
  1805. **
  1806. **    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  1807. ***^^**********************************************************************/
  1808. X
  1809. /* $Header: useful.h,v 2.0 89/12/24 00:56:33 eric Exp $ */
  1810. X
  1811. #ifndef _USEFUL_H_
  1812. #define _USEFUL_H_
  1813. X
  1814. #ifndef unix
  1815. # if (defined(_unix) || defined(_unix_) || defined(__unix) || defined(__unix__) || defined(UNIX) || defined(_UNIX) || defined(_UNIX_) || defined(__UNIX) || defined(__UNIX__) || defined(Unix) || defined(_Unix) || defined(_Unix_) || defined(__Unix) || defined(__Unix__) || defined(sun))
  1816. #   define unix
  1817. # endif /* _UNIX */
  1818. #endif /* unix */
  1819. X
  1820. #ifndef BSD
  1821. # if (defined(ucb_universe) || defined(UCB) || defined(_BSD) || defined(_BSD_) || defined(__BSD) || defined(__BSD__) || defined(BSD_UNIX) || defined(_BSD_UNIX) || defined(_BSD_UNIX_) || defined(__BSD_UNIX) || defined(__BSD_UNIX__) || defined(sun))
  1822. #   define BSD
  1823. # endif /* _BSD */
  1824. #endif /* BSD */
  1825. X
  1826. #ifndef AmigaDOS
  1827. # if (defined(MANX) || defined(AZTEC))
  1828. #   define AmigaDOS
  1829. # endif
  1830. #endif /* AmigaDOS */
  1831. X
  1832. #ifndef vms
  1833. # if (defined(_vms) || defined(_vms_) || defined(__vms) || defined(__vms__) || defined(VMS) || defined(_VMS) || defined(_VMS_) || defined(__VMS) || defined(__VMS__))
  1834. #   define vms
  1835. # endif /* _VMS */
  1836. #endif /* vms */
  1837. X
  1838. #ifndef MSDOS
  1839. # if (defined(_MSDOS) || defined(_MSDOS_) || defined(__MSDOS) || defined(__MSDOS__) || defined(MS_DOS) || defined(_MS_DOS) || defined(_MS_DOS_) || defined(__MS_DOS) || defined(__MS_DOS__))
  1840. #   define MSDOS
  1841. # endif /* _MSDOS */
  1842. #endif /* MSDOS */
  1843. X
  1844. #ifndef OS2
  1845. # if (defined(_OS2) || defined(_OS2_) || defined(__OS2) || defined(__OS2__))
  1846. #   define OS2
  1847. # endif /* _OS2 */
  1848. #endif /* OS2 */
  1849. X
  1850. X
  1851. #ifndef FILE
  1852. # include <stdio.h>
  1853. #endif
  1854. X
  1855. #ifndef STDIN
  1856. # define STDIN   0
  1857. # define STDOUT  1
  1858. # define STDERR  2
  1859. #endif
  1860. X
  1861. X   /* macros to portably convert character case */
  1862. #define TOUPPER(c)  ( islower(c) ) ? toupper(c) : (c)
  1863. #define TOLOWER(c)  ( isupper(c) ) ? tolower(c) : (c)
  1864. X
  1865. X   /* give a stab at the multiple-language dilemma */
  1866. #ifdef __STDC__
  1867. #  define ARGS(x)        x
  1868. #  define NOARGS        ( void )
  1869. #  define __ANSI_C__
  1870. #else
  1871. #  if defined(c_plusplus) || defined(__cplusplus)
  1872. #    define ARGS(x)        x
  1873. #    define NOARGS        ()
  1874. #    define __ANSI_C__
  1875. #  else
  1876. #    define ARGS(x)        ()
  1877. #    define NOARGS        ()
  1878. #  endif
  1879. #endif
  1880. X
  1881. X   /* give a stab at the variable arguments dilemma  --BDA */
  1882. #ifdef __STDC__
  1883. #  ifndef va_arg
  1884. #    include <stdarg.h>
  1885. #  endif
  1886. #  define  VA_START(ap,last)  va_start(ap, last)
  1887. #  define  VA_ARG(ap,type)    va_arg(ap, type)
  1888. #  define  VA_END(ap)         va_end(ap)
  1889. #else
  1890. #  ifndef va_arg
  1891. #    include  <varargs.h>
  1892. #  endif
  1893. #  define  VA_START(ap,last)  va_start(ap)
  1894. #  define  VA_ARG(ap,type)    va_arg(ap, type)
  1895. #  define  VA_END(ap)         va_end(ap)
  1896. #endif
  1897. X
  1898. #if ( !defined(__ANSI_C__)  &&  !defined(_SIZE_T_DEFINED) )
  1899. X  typedef unsigned int size_t;
  1900. # define _SIZE_T_DEFINED 1
  1901. #endif
  1902. X
  1903. #ifndef VOID
  1904. #  if ( defined(__ANSI_C__)  ||  !defined(NOVOID) )
  1905. #    define VOID        void
  1906. #  else
  1907. #    define VOID        int
  1908. #  endif
  1909. #endif
  1910. X
  1911. #ifndef TRUE
  1912. #  define TRUE        1
  1913. #  define FALSE        0
  1914. #endif
  1915. X
  1916. #ifndef STATIC
  1917. #  ifndef NODEBUG
  1918. #    define STATIC
  1919. #  else
  1920. #    define STATIC        static
  1921. #  endif
  1922. #endif
  1923. X
  1924. #ifndef EXTERN
  1925. #  if defined(c_plusplus) || defined(__cplusplus)
  1926. #    define EXTERN        extern "C"
  1927. #  else
  1928. #    define EXTERN        extern
  1929. #  endif
  1930. #endif
  1931. X
  1932. #ifndef CONST
  1933. #  ifdef __ANSI_C__
  1934. #    define CONST        const
  1935. #  else
  1936. #    define CONST
  1937. #  endif
  1938. #endif
  1939. X
  1940. #ifndef NULL
  1941. #  define NULL        0
  1942. #endif
  1943. X
  1944. #ifndef CHARNULL
  1945. #  define CHARNULL    ((char *) NULL)
  1946. #endif
  1947. X
  1948. #ifndef FILENULL
  1949. #  define FILENULL    ((FILE *) NULL)
  1950. #endif
  1951. X
  1952. #ifdef __ANSI_C__
  1953. X   typedef   void *ARBPTR;
  1954. #else
  1955. X   typedef   char *ARBPTR;
  1956. #endif
  1957. X
  1958. #define __        (ARBPTR)
  1959. #define ARBNULL        (__ NULL)
  1960. X
  1961. #ifndef BOOL
  1962. X   typedef   char   BOOL;
  1963. #endif
  1964. X
  1965. #ifdef lint
  1966. #  define VERSIONID(v)
  1967. #else
  1968. #  define VERSIONID(v)    static char _Version[] = v
  1969. #endif
  1970. X
  1971. X   /* keep BITSET for compatibilty
  1972. X   ** but use BSET, BCLEAR, etc... instead   --BDA
  1973. X   */
  1974. #define BITSET(bstr,mask)    ( ((bstr) & (mask)) != 0 )
  1975. X
  1976. #define BTEST(bstr,mask)    ( ((bstr) & (mask)) != 0 )
  1977. #define BSET(bstr,mask)     (bstr) |= (mask)
  1978. #define BCLEAR(bstr,mask)   (bstr) &= ~(mask)
  1979. X
  1980. #ifndef STRING_H
  1981. # define STRING_H
  1982. X   EXTERN  char  *strcat    ARGS(( char *, const char * ));
  1983. X   EXTERN  char  *strncat   ARGS(( char *, const char *, int ));
  1984. X   EXTERN  int    strcmp    ARGS(( const char *, const char * ));
  1985. X   EXTERN  int    strncmp   ARGS(( const char *, const char *, int ));
  1986. X   EXTERN  char  *strcpy    ARGS(( char *, const char * ));
  1987. X   EXTERN  char  *strncpy   ARGS(( char *, const char *, int ));
  1988. X   EXTERN  int    strlen    ARGS(( const char * ));
  1989. X   
  1990. # ifndef BSD
  1991. #  define index(s,c)   strchr(s,c)
  1992. #  define rindex(s,c)  strrchr(s,c)
  1993. X   EXTERN  char  *strchr    ARGS(( const char *, int ));
  1994. X   EXTERN  char  *strrchr   ARGS(( const char *, int ));
  1995. X   EXTERN  char  *strpbrk   ARGS(( const char *, const char * ));
  1996. X   EXTERN  int    strspn    ARGS(( const char *, const char * ));
  1997. X   EXTERN  int    strcspn   ARGS(( const char *, const char * ));
  1998. X   EXTERN  char  *strtok    ARGS(( char *, char * ));
  1999. X   EXTERN  char  *strdup    ARGS(( const char * ));
  2000. X   
  2001. # else
  2002. #  define strchr(s,c)   index(s,c)
  2003. #  define strrchr(s,c)  rindex(s,c)
  2004. X   EXTERN  char  *index     ARGS(( const char *, int ));
  2005. X   EXTERN  char  *rindex    ARGS(( const char *, int ));
  2006. # endif /* !BSD */
  2007. X   
  2008. # ifdef BSD
  2009. #  define bcmp(b1,b2,n)   memcmp(b1,b2,n)
  2010. #  define bcopy(b1,b2,n)  memcpy(b2,b1,n)
  2011. #  define bzero(b,n)      memset(b,'\0',n)
  2012. #  ifndef MEMORY_H
  2013. #    define MEMORY_H
  2014. X   EXTERN  ARBPTR  memccpy   ARGS(( ARBPTR, const ARBPTR, int, int ));
  2015. X   EXTERN  ARBPTR  memchr    ARGS(( ARBPTR, int, int ));
  2016. X   EXTERN  int     memcmp    ARGS(( const ARBPTR, const ARBPTR, int ));
  2017. SHAR_EOF
  2018. true || echo 'restore of parseargs/useful.h failed'
  2019. fi
  2020. echo 'End of  part 10'
  2021. echo 'File parseargs/useful.h is continued in part 11'
  2022. echo 11 > _shar_seq_.tmp
  2023. exit 0
  2024. exit 0 # Just in case...
  2025. -- 
  2026. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2027. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2028. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2029. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2030.