home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / parsearg / part03 < prev    next >
Encoding:
Text File  |  1992-05-18  |  74.9 KB  |  2,254 lines

  1. Newsgroups: comp.sources.misc
  2. From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  3. Subject:  v29i118:  parseargs - functions to parse command line arguments, Part03/10
  4. Message-ID: <1992May17.182317.28636@sparky.imd.sterling.com>
  5. X-Md4-Signature: 1fcf04e7ebe1ade2be1e35eed3760767
  6. Date: Sun, 17 May 1992 18:23:17 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  10. Posting-number: Volume 29, Issue 118
  11. Archive-name: parseargs/part03
  12. Environment: UNIX, VMS, MS-DOS, OS/2, Amiga
  13. Supersedes: parseargs: Volume 17, Issue 46-57
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 3 (of 10)."
  22. # Contents:  arglist.c doc/argtype.man3 doc/parseflags.inc
  23. #   doc/sh_arrays.inc parseargs.awk patchlevel.h syserr.c test.awk
  24. #   vprintf.c winsize.c
  25. # Wrapped by brad@hcx1 on Thu May  7 12:12:21 1992
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'arglist.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'arglist.c'\"
  29. else
  30. echo shar: Extracting \"'arglist.c'\" \(6159 characters\)
  31. sed "s/^X//" >'arglist.c' <<'END_OF_FILE'
  32. X/*************************************************************************
  33. X** ^FILE: arglist.c - argList manipulation routines.
  34. X**
  35. X** ^DESCRIPTION:
  36. X**    This file contains routines to add an item to the end of an arglist,
  37. X**    and to delete all items in an arglist.
  38. X**
  39. X** ^HISTORY:
  40. X**    27/08/91     Earl Chew     <cechew@bruce.cs.monash.edu.au>
  41. X**       - Use get_argpfx() when accessing arg_sname().
  42. X**
  43. X**    01/02/91    Brad Appleton    <brad@ssd.csd.harris.com>
  44. X**       - Added structured comments
  45. X**       - Changed arglists to always be kept in FIFO order (hence
  46. X**         reverse_list() and cleanup_list() were no longer needed).
  47. X**         The lists are maintained in FIFO order by forcing the very
  48. X**         first item of the list to maintain an additional link to the
  49. X**         last item of the list (to make it easy to append an item).
  50. X**       - Added listFree() function
  51. X**
  52. X**    --/--/--    Peter da Silva    <peter@ferranti.com>    Created
  53. X***^^**********************************************************************/
  54. X
  55. X#include <stdio.h>
  56. X#include <ctype.h>
  57. X#include <useful.h>
  58. X#include "strfuncs.h"
  59. X
  60. X#define  PARSEARGS_NARGTYPES  /* exclude arg-type externs */
  61. X#include "parseargs.h"
  62. X
  63. XEXTERN  VOID    syserr  ARGS((const char *, ...));
  64. XEXTERN  VOID    usrerr  ARGS((const char *, ...));
  65. X
  66. X/***************************************************************************
  67. X** ^FUNCTION: listStr - string-list argument translation routine
  68. X**
  69. X** ^SYNOPSIS:
  70. X*/
  71. X#ifndef __ANSI_C__
  72. X   BOOL listStr( ad, vp, copyf )
  73. X/*  
  74. X** ^PARAMETERS:
  75. X*/
  76. X   ARGDESC *ad;
  77. X/*    -- the argument descriptor for this parameter.
  78. X*/
  79. X   char *vp;
  80. X/*    -- a pointer to the string input value.
  81. X*/
  82. X   BOOL copyf;
  83. X/*    -- if TRUE, the value will be destroyed later, and so should
  84. X**       be copied if it will be retained (as for a string).
  85. X*/
  86. X#endif  /* !__ANSI_C__ */
  87. X
  88. X/* ^DESCRIPTION:
  89. X**    ListStr converts a string-parameter value into its internal form,
  90. X**    including validity checking. If <copyf> is TRUE then <vp> is copied
  91. X**    to the end of the list, otherwise <vp> itself is placed at the end.
  92. X**
  93. X** ^REQUIREMENTS:
  94. X**    <ad> must point to the argdesc element corresponding to the matched
  95. X**    string-list argument. The ad_valp field of ad MUST be either NULL or
  96. X**    point to a valid arglist-head structure.
  97. X**
  98. X** ^SIDE-EFFECTS:
  99. X**    If successful, arglist pointed to by arg_valp(ad) is appended with
  100. X**    the given string, <vp> is unchanged.
  101. X**
  102. X** ^RETURN-VALUE:
  103. X**    TRUE -- if the conversion was successful.  The actual
  104. X**            value should be added appended to the list.
  105. X**    FALSE -- if the conversion failed.  The reason for failure
  106. X**             should be diagnosed using usrerr().
  107. X**
  108. X** ^ALGORITHM:
  109. X**    - verify the validity of <vp> as a string argument
  110. X**    - if ( isEmpty(arglist) )
  111. X**       - allocate a listhead structure
  112. X**       - assign the item pointer to <vp> (or a copy of <vp>)
  113. X**       - assign the NEXT and LAST elements to NULL
  114. X**    - else
  115. X**       - allocate a new arglist structure and append it after
  116. X**         listhead.LAST
  117. X**       - assign listhead.LAST to the address of the new item
  118. X**       - assign the NEXT element of the new item to NULL
  119. X**      end-if
  120. X***^^**********************************************************************/
  121. X#ifdef __ANSI_C__
  122. X   BOOL listStr( ARGDESC *ad, char *vp, BOOL copyf )
  123. X#endif
  124. X{
  125. X   char *cp;
  126. X   BOOL  badalloc = FALSE;
  127. X   argName_t   argname;
  128. X   ArgListHead *nl;
  129. X   ArgList *nd;
  130. X
  131. X   (VOID) get_argname( arg_sname(ad), argname );
  132. X   if (copyf) {
  133. X      register int i;
  134. X
  135. X      i = strlen(vp) + 1;
  136. X      cp = (char *) malloc(i * sizeof(char));
  137. X      if(!cp) {
  138. X         usrerr("out of memory saving string %s", argname );
  139. X         return FALSE;
  140. X      }
  141. X      memcpy(cp, vp, i);
  142. X   }
  143. X   else {
  144. X      cp = vp;
  145. X   }
  146. X
  147. X      /* if list is empty - need to new up a listhead,
  148. X      ** otherwise just use a normal link.
  149. X      */
  150. X   nl = *((ArgListHead **) arg_valp(ad));
  151. X   if ( nl ) {
  152. X      nd = (ArgList *) malloc( sizeof(ArgList) );
  153. X      if ( !nd )  badalloc = TRUE;
  154. X   }
  155. X   else {
  156. X      nl = (ArgListHead *) malloc( sizeof(ArgListHead) );
  157. X      nd = (ArgList *)NULL;
  158. X      if ( !nl )  badalloc = TRUE;
  159. X   }
  160. X
  161. X   if ( badalloc ) {
  162. X      usrerr("out of memory saving arg %.*s", get_argpfx(arg_sname(ad)),
  163. X                                              arg_sname(ad));
  164. X      if(copyf) free(cp);
  165. X      return FALSE;
  166. X   }
  167. X
  168. X   if ( nd ) {
  169. X      nl -> nl_tail -> nl_next = (ArgList *)nd;
  170. X      nl -> nl_tail  = (ArgList *)nd;
  171. X      nd -> nl_next  = (ArgList *)NULL;
  172. X      nd -> nl_val   = (ARBPTR)cp;
  173. X      nd -> nl_flags = arg_flags(ad);
  174. X      if ( copyf )  BSET( nd->nl_flags, ARGCOPYF );
  175. X   }
  176. X   else {
  177. X      *((ArgListHead **) arg_valp(ad)) = nl;
  178. X      nl -> nl_tail  = (ArgList *)nl;
  179. X      nl -> nl_next  = (ArgList *)NULL;
  180. X      nl -> nl_val   = (ARBPTR)cp;
  181. X      nl -> nl_flags = arg_flags(ad);
  182. X      if ( copyf )  BSET( nl->nl_flags, ARGCOPYF );
  183. X   }
  184. X
  185. X   return (TRUE);
  186. X}
  187. X
  188. X
  189. X/***************************************************************************
  190. X** ^FUNCTION: listFree - free the items in an arglist
  191. X**
  192. X** ^SYNOPSIS:
  193. X*/
  194. X#ifndef __ANSI_C__
  195. X   VOID listFree( argls )
  196. X/*  
  197. X** ^PARAMETERS:
  198. X*/
  199. X   ArgList *argls;
  200. X/*    -- the list to be freed
  201. X*/
  202. X#endif  /* !__ANSI_C__ */
  203. X
  204. X/* ^DESCRIPTION:
  205. X**    ListFree will free storage for each node in <argls>. Furthermore,
  206. X**    if <copyf> is true then the actual storage for each item in the
  207. X**    list is also released.
  208. X**
  209. X** ^REQUIREMENTS:
  210. X**    argls must point to a valid arglist-head structure.
  211. X**
  212. X** ^SIDE-EFFECTS:
  213. X**    each item in argls is removed, argls itself should be set to NULL
  214. X**    after this routine is invoked.
  215. X**
  216. X** ^RETURN-VALUE:
  217. X**    None.
  218. X**
  219. X** ^ALGORITHM:
  220. X**    - For each node in argls
  221. X**       - if ( copyf ) free the item storage
  222. X**       - free the node
  223. X**      end-for
  224. X***^^**********************************************************************/
  225. X#ifdef __ANSI_C__
  226. X   void listFree( ArgList *argls )
  227. X#endif
  228. X{
  229. X   register  ArgList *ls = argls;
  230. X   ArgList  *nd;
  231. X
  232. X   if ( !ls )  return;
  233. X
  234. X   while ( ls ) {
  235. X      nd = L_NEXT(ls);
  236. X      if ( BTEST(L_FLAGS(ls), ARGCOPYF) )  free( ls->nl_val );
  237. X      free( ls );
  238. X      ls = nd;
  239. X   }/*while*/
  240. X}
  241. X
  242. END_OF_FILE
  243. if test 6159 -ne `wc -c <'arglist.c'`; then
  244.     echo shar: \"'arglist.c'\" unpacked with wrong size!
  245. fi
  246. # end of 'arglist.c'
  247. fi
  248. if test -f 'doc/argtype.man3' -a "${1}" != "-c" ; then 
  249.   echo shar: Will not clobber existing file \"'doc/argtype.man3'\"
  250. else
  251. echo shar: Extracting \"'doc/argtype.man3'\" \(7369 characters\)
  252. sed "s/^X//" >'doc/argtype.man3' <<'END_OF_FILE'
  253. X.\" $Header: argtype.3,v 1.0 90/11/17 11:34:06 brad Exp $
  254. X.TH ARGTYPE 3
  255. X.SH NAME
  256. Xargtype \- argument type functions used by parseargs(3)
  257. X.SH SYNOPSIS
  258. X#include <parseargs.h>
  259. X.PP
  260. X.nf
  261. X\s-1BOOL\s+1  argUsage(  argdesc,  argstr,  copyf  );
  262. X\s-1BOOL\s+1  argEnd(  argdesc,  argstr,  copyf  );
  263. X\s-1BOOL\s+1  argDummy(  argdesc,  argstr,  copyf  );
  264. X\s-1BOOL\s+1  argBool(  argdesc,  argstr,  copyf  );
  265. X\s-1BOOL\s+1  argSBool(  argdesc,  argstr,  copyf  );
  266. X\s-1BOOL\s+1  argUBool(  argdesc,  argstr,  copyf  );
  267. X\s-1BOOL\s+1  argTBool(  argdesc,  argstr,  copyf  );
  268. X\s-1BOOL\s+1  argChar(  argdesc,  argstr,  copyf  );
  269. X\s-1BOOL\s+1  argStr(  argdesc,  argstr,  copyf  );
  270. X\s-1BOOL\s+1  argInt(  argdesc,  argstr,  copyf  );
  271. X\s-1BOOL\s+1  argShort(  argdesc,  argstr,  copyf  );
  272. X\s-1BOOL\s+1  argLong(  argdesc,  argstr,  copyf  );
  273. X\s-1BOOL\s+1  argFloat(  argdesc,  argstr,  copyf  );
  274. X\s-1BOOL\s+1  argDouble(  argdesc,  argstr,  copyf  );
  275. X\s-1BOOL\s+1  listStr(  argdesc,  argstr,  copyf  );
  276. X\s-1void\s+1  listFree(  arglist  );
  277. X\s-1void\s+1  vecFree(  argvec, type  );
  278. X\s-1void\s+1  vecDeepFree(  argvec, type  );
  279. X
  280. X\s-1ARGDESC\s+1  *argdesc;
  281. Xchar  *argstr;
  282. X\s-1BOOL\s+1  copyf;
  283. XArgList  *arglist;
  284. X.fi
  285. X.SH "DESCRIPTION"
  286. X.PP
  287. XEach of these converts a parameter value to the internal form,
  288. Xincluding validity checking.  Their parameters and return values
  289. Xall behave similarly. One of these routines is called when an
  290. Xargument of that particular type is matched by one of the argument
  291. Xparsing function in \fIparseargs\fP(3). When such an argument is matched,
  292. Xits argument translation routine is invoked and is passed (1) the address of
  293. Xthe argument descriptor for the matched argument, (2) the possible argument
  294. Xstring for that matched argument, and (3) a boolean field that is \s-1TRUE\s+1
  295. Xonly if the second parameter points to temporary storage (indicating that
  296. Xsome copying may need to be done instead of just pointing to the same object).
  297. X
  298. XOnce the argument translation routine is invoked, it is responsible for
  299. Xconverting the argument string to the desired internal form (perhaps a number),
  300. Xand assigning the resultant value to the \fIarg_valp(ad)\fP field of the
  301. Xargument descriptor (this includes handling any necessary (re)allocation if
  302. Xthe matched argument has the \s-1ARGVEC\s+1 flag enabled). If the argument is
  303. Xan \s-1ARGVEC\s+1 or \s-1ARGLIST\s+1 then the routine is responsible for
  304. Xallocating any space, copying the arg-flags to the value-specific flags, and
  305. Xsetting the \s-1ARGCOPYF\s+1 flag for the value if it needs to be allocated
  306. Xas well.
  307. X
  308. X.SH "RETURN VALUE"
  309. X.IP "TRUE" 8
  310. XThe conversion was successful and the entire value was used.
  311. X
  312. X.IP "FALSE" 8
  313. XThe conversion failed.  The reason for failure should be
  314. Xdiagnosed using \fIusrerr\fP(3).
  315. X
  316. X.IP "-\fIN\fP" 8
  317. XThe conversion was successful but only \fIN\fP characters of the value
  318. Xwere used, the remaining characters may still match other arguments.
  319. X
  320. X.SH "PSEUDO-TYPES: argUsage, argDummy, argEnd"
  321. X.PP
  322. X.I ArgUsage
  323. Xis used to specify an argument that causes the command usage to be printed.
  324. X
  325. X.I ArgDummy
  326. Xis used to force an item to show up in usage-messages but
  327. Xthe item itself is never matched against any arguments from the
  328. Xcommand-line.
  329. X
  330. X.I ArgEnd
  331. Xis used by Amiga style command-lines to indicate an argument
  332. Xthat forces all remaining arguments to be considered positional args.
  333. X
  334. XThese three are dummy functions. The routines themselves do nothing
  335. Xof importance, we just need to have their addresses available for
  336. Xidentification in the corresponding command-line styles.
  337. X.SH "STRING-TYPES: argStr"
  338. X.PP
  339. X\fIArgStr\fP is one of the few argument translation routines that actually
  340. Xuses the \fIcopyf\fP flag. If \fIcopyf\fP is true then the string is
  341. Xduplicated.
  342. X
  343. X\fIArgStr\fP assigns the given string (or a copy of it) to the value
  344. Xreferenced by \fIarg_valp(ad)\fP (unless the argument is a vector in which
  345. Xcase the given string is appended to the end).
  346. X
  347. X\fIArgStr\fP ensures that the very last item in a vector of strings (the one
  348. Xaccessed as \f4vec.array[ vec.count ]\fP) will always be \s-1NULL\s+1.
  349. X.SH "CHARACTER-TYPES: argChar"
  350. X.PP
  351. X.I ArgChar
  352. Xassigns the given character to the value referenced by \fIarg_valp(ad)\fP
  353. X(unless the argument is a vector in which case the given character
  354. Xis appended to the end).
  355. X
  356. X.I ArgChar
  357. Xensures that the very last item in a vector of character (the one
  358. Xaccessed as \f4vec.array[ vec.count ]\fP) will always be a \s-1NULL\s+1
  359. Xbyte so that the resulting vector may also be used as a \s-1NULL\s+1
  360. Xterminated string.
  361. X
  362. XUnlike \fIargStr\fP, \fIargChar\fP will translate character escape sequences
  363. Xsuch as `\\n' and `\\012'.
  364. X.SH "INTEGER-TYPES: argInt, argShort, argLong"
  365. X.PP
  366. XEach of these functions converts the given string to the desired
  367. Xintegral type. The value may be specified as an octal number by
  368. Xspecifying the first digit to be 0. Similarly, If the first two 
  369. Xcharacters are `0x' then the number is treated as hexadecimal.
  370. X.SH "FLOATING-POINT-TYPES: argFloat, argDouble"
  371. X.PP
  372. XEach of these functions converts the given string to the desired
  373. Xfloating-point type.
  374. X.SH "BOOLEAN-TYPES: argBool, argSBool, argTBool, argUBool"
  375. X.PP
  376. X\fIArgBool\fP and \fIargSBool\fP set a boolean value (if no value is given).
  377. X\fIArgUBool\fP unsets a boolean value (if no value is given). \fIArgTBool\fP
  378. Xtoggles a boolean value (if no value is given). If a value is
  379. Xsupplied to any of these routines, then the string is looked up
  380. Xin a table and assigned the corresponding value.
  381. X
  382. XIf a value is supplied for an argument that was matched via its
  383. Xsingle character name and is part of the same \f4argv\fP element as the
  384. Xargument-name (so that both \fBARGKEYWORD\fP and \fBARGVALSEP\fP
  385. Xare not set),
  386. Xthen only the first character of the value is used (unless it is
  387. Xnot found in our table, in which case the value is ignored and the
  388. Xdefault action is taken). The table used for single-character-options
  389. Xis the following:
  390. X.IP "`0' or `-'"
  391. XThe corresponding boolean flag is set to \s-1FALSE\s+1.
  392. X.IP "`1' or `+'"
  393. XThe corresponding boolean flag is set to \s-1TRUE\s+1.
  394. X.IP "`^' or `~'"
  395. XThe corresponding boolean flag is toggled.
  396. X.PP
  397. XThe possible argument strings for long-options (keywords) are as follows
  398. X(case-insensitive):
  399. X.IP "``0'', ``-'', ``OFF'', or ``FALSE''"
  400. XThe corresponding boolean flag is set to \s-1FALSE\s+1.
  401. X.IP "``1'', ``+'', ``ON'', or ``TRUE''"
  402. XThe corresponding boolean flag is set to \s-1TRUE\s+1.
  403. X.SH "LIST TYPES: listStr"
  404. X.PP
  405. XThe \fIlistStr\fP argument translation routine is only intended for use
  406. Xon behalf of arguments that have the \s-1ARGLIST\s+1 flag enabled. It will
  407. Xallocate space for a new node (and for the new string if \fIcopyf\fP is
  408. Xset) and append it to the end of the list. The argument-list may later
  409. Xbe deallocated by invoking the function \fIlistFree\fP and passing it
  410. Xthe address of the first item in the list.
  411. X
  412. X.PP
  413. X\fIVecFree\fP is a macro that is used to deallocate argument-vectors.
  414. XIt will free the array and flags fields of a vector, set them to
  415. X\s-1NULL\s+1, and set the count field to zero. \fIVecDeepFree\fP is
  416. Xa macro that is similar to \fIvecFree\fP but will additionally look
  417. Xat each item in the array; any component of the array that had
  418. X\s-1ARGCOPYF\s+1 enabled will also be deallocated.
  419. XBoth macros are given the vector structure to free followed by the
  420. Xtype of the items in the vector.
  421. X.SH SEE ALSO
  422. X.IR parseargs (3),
  423. X.IR parseargs (1),
  424. X.IR parsecntl (3)
  425. END_OF_FILE
  426. if test 7369 -ne `wc -c <'doc/argtype.man3'`; then
  427.     echo shar: \"'doc/argtype.man3'\" unpacked with wrong size!
  428. fi
  429. # end of 'doc/argtype.man3'
  430. fi
  431. if test -f 'doc/parseflags.inc' -a "${1}" != "-c" ; then 
  432.   echo shar: Will not clobber existing file \"'doc/parseflags.inc'\"
  433. else
  434. echo shar: Extracting \"'doc/parseflags.inc'\" \(5352 characters\)
  435. sed "s/^X//" >'doc/parseflags.inc' <<'END_OF_FILE'
  436. X.\"----------------------------------------------------------------------------
  437. X.\"-- This text was extracted using the following command:
  438. X.\"--   xdoc -man -p '[ \t]*' -s PARSE-FLAGS ../parseargs.h
  439. X.\"----------------------------------------------------------------------------
  440. X.SH "PARSE FLAGS"
  441. X.PP
  442. XThe following bitmasks may be combined in order to modify the
  443. Xbehavior of the \fIparseargs\fP library. The parse flags for a given
  444. Xmay be set through the use of the \fIparsecntl\fP(3) function.
  445. X.\"---------------------------------------------
  446. X.IP "\fIpa_\s-1PROMPT\s+1\fP"
  447. XPrompt the user for any missing arguments that are required on the
  448. Xcommand-line. No special escaping or quoting is performed on the
  449. Xuser input. Required arguments that expect a list of values will
  450. Xbe repeatedly prompted for (one item per line) until a blank line
  451. X(followed by a carriage return) is entered.
  452. X.\"---------------------------------------------
  453. X.IP "\fIpa_\s-1IGNORE\s+1\fP"
  454. XIgnore any unrecognized or improperly specified command-line arguments
  455. Xand continue execution of the program. Normally, if a required argument is
  456. Xunmatched (or an argument is improperly specified), a usage message is printed
  457. Xprogram execution is terminated.
  458. X.\"---------------------------------------------
  459. X.IP "\fIpa_\s-1OPTSONLY\s+1\fP"
  460. XUnder \s-1UNIX\s+1, setting this flag will disable the parsing of long-option
  461. Xsyntax. This will cause all arguments starting with `+' to always be
  462. Xtreated as a positional parameter (instead of a long-option).
  463. X.\"---------------------------------------------
  464. X.IP "\fIpa_\s-1KWDSONLY\s+1\fP"
  465. XUnder \s-1UNIX\s+1, setting this flag disables the parsing of single-character
  466. Xoptions.  This will cause all arguments starting with `\-' to always
  467. Xbe treated as a positional parameter (instead of an option).
  468. X.\"---------------------------------------------
  469. X.IP "\fIpa_\s-1FLAGS1ST\s+1\fP"
  470. XSetting this flag causes the parseargs library to force any and all
  471. Xnon-positional arguments to be specified before any positional ones.
  472. XAs an example, under \s-1UNIX\s+1, if this flag is \s-1SET\s+1 then
  473. X.I parseargs
  474. Xwill consider the command line "\fBcmd \-x\fI arg\fR" to consist of one
  475. Xoption and one positional argument; however the command line
  476. X"\fBcmd\fI arg -x\fR" would be considered to consist of two positional
  477. Xarguments (the \fB\-x\fP option will be unmatched).
  478. X
  479. XIf this flag is \s-1UNSET\s+1, then both of the previous examples are
  480. Xconsidered to consist of one option and one positional argument.
  481. X.\"---------------------------------------------
  482. X.IP "\fIpa_\s-1ANYCASE\s+1\fP"
  483. XSetting this flag will cause character-case to be ignored when attempting
  484. Xto match single-character argument names (i.e. causes "\fB\-i\fP" and
  485. X"\fB\-I\fP" to be considered equivalent).
  486. X.\"---------------------------------------------
  487. X.IP "\fIpa_\s-1ARGV0\s+1\fP"
  488. XNormally, the \fIparseargs\fP library will assume that the first argument
  489. Xon the command-line is the name of the command. Setting this flag tells
  490. X\fIparseargs\fP that this is \s-1NOT\s+1 the case and that the very first
  491. Xargument on the command-line is a bona-fide argument to the command.
  492. X.\"---------------------------------------------
  493. X.IP "\fIpa_\s-1NOCHECK\s+1\fP"
  494. XSetting this flag will prevent \fIparseargs\fP from checking for any 
  495. Xrequired arguments that were not given on the command-line. This
  496. Xis useful when more than one call to the \fIparseargs\fP library is needed
  497. Xto parse all the command-line arguments (which could occur if the
  498. Xcommand-line argument came from a file or from two \f4argv\fP-vectors).
  499. XWhen this flag is set, then each call to parseargs will check for missing
  500. Xrequired arguments (and will prompt the user for them if desired).
  501. X
  502. XKeeping this flag on until the final set of arguments is parsed will
  503. Xcause \fIparseargs\fP to not check for missing arguments until the last set
  504. Xof arguments has been parsed (by the final call to one of the functions 
  505. Xin the \fIparseargs\fP library).
  506. X.\"---------------------------------------------
  507. X.IP "\fIpa_\s-1CONTINUE\s+1\fP"
  508. XSetting this flag will cause subsequent calls to the parseargs library
  509. Xto \s-1NOT\s+1 reset the current command-state. Hence, all arguments will not
  510. Xbe initially set to "\s-1NOT GIVEN\s+1" and other (normal) initializations are
  511. Xnot be performed.  This is useful in conjunction with the
  512. X\fIpa_\s-1NOCHECK\s+1\fP flag when more than one call to
  513. X.I parseargs
  514. Xis required to parse all the command arguments. In this scenario,
  515. X\fIpa_\s-1CONTINUE\s+1\fP should be unset (the default setting) for the very
  516. Xfirst call to
  517. X.I parseargs,
  518. Xbut should then be set before any subsequent calls to
  519. X.I parseargs
  520. Xare made.
  521. X.\"---------------------------------------------
  522. X.IP "\fIpa_\s-1NOCMDENV\s+1\fP"
  523. XSetting this flag prevents parseargs from checking the
  524. X\s-1\fICMD-NAME\fP_ARGS\s+1 environment variable (or symbol) for any
  525. Xuser-defined default command arguments.
  526. X.\"---------------------------------------------
  527. X.IP "\fIpa_\s-1COPYF\s+1\fP"
  528. XWhen this flag is \s-1OFF\s+1 (the default), a value of \s-1FALSE\s+1 is
  529. Xprovided as the \fIcopyf\fP argument to all the arg-type
  530. X.I (argXxxxx)
  531. Xfunctions when an argument is matched. Setting this flag will cause a value of
  532. X\s-1TRUE\s+1 to be provided as the \fIcopyf\fP argument to all the arg-type
  533. X.I (argXxxxx)
  534. Xfunctions when an argument is matched.
  535. X.\"---------------------------------------------
  536. END_OF_FILE
  537. if test 5352 -ne `wc -c <'doc/parseflags.inc'`; then
  538.     echo shar: \"'doc/parseflags.inc'\" unpacked with wrong size!
  539. fi
  540. # end of 'doc/parseflags.inc'
  541. fi
  542. if test -f 'doc/sh_arrays.inc' -a "${1}" != "-c" ; then 
  543.   echo shar: Will not clobber existing file \"'doc/sh_arrays.inc'\"
  544. else
  545. echo shar: Extracting \"'doc/sh_arrays.inc'\" \(7679 characters\)
  546. sed "s/^X//" >'doc/sh_arrays.inc' <<'END_OF_FILE'
  547. X.\"----------------------------------------------------------------------------
  548. X.\"-- This text was extracted using the following command:
  549. X.\"--   xdoc -man -n -p '[ \t]*' -I DESCRIPTION -f put_argvector ../parseargs.c
  550. X.\"----------------------------------------------------------------------------
  551. X.SH ARGUMENT LISTS
  552. X.PP
  553. X.B Parseargs
  554. Xtreats \s-1ARGLIST\s+1 arguments in a special way. The method used for
  555. Xsetting up an argument list depends largely upon the syntax of shell
  556. Xthat was specified on the command line via the \fB\-s\fP option
  557. X(although \s-1ARGLIST\s+1 arguments are treated exactly the same as
  558. X\s-1ARGVEC\s+1 arguments). With the exception of \fIperl\fP which always
  559. Xuses a comma to separate array elements, all shells will use the string
  560. Xspecified with the \fB\-S\fP option as the field separator between elements
  561. Xof an array (the default field separator is a space character).
  562. X.\"---------------
  563. X.SS "Resetting the Positional Parameters to an Argument List"
  564. X.PP
  565. XFor the Bourne, Bourne-Again, and Korn shells,
  566. Xif the variable name corresponding to the \s-1ARGLIST\s+1 argument is
  567. X``\fB\-\^\-\fP'', then the positional parameters of the calling program
  568. Xwill be re-assigned to the contents of the argument list ($1 will be the
  569. Xfirst item, $2 the second item, and so on). In this particular case, the
  570. Xcalling program may wish to use the \fB\-u\fP option to reset the positional
  571. Xparameters to \s-1NULL\s+1 before making any shell-variable assignments
  572. X(this way, the positional parameters will be unset if the associated list
  573. Xof command line arguments is not encountered).
  574. X.PP
  575. XSimilarly for the C & Z shells (\fIzsh, csh, tcsh, itcsh\fP),
  576. Xif the variable name corresponding to the \s-1ARGLIST\s+1 argument is
  577. X``\fBargv\fP'', then the positional parameters of the calling program
  578. Xwill be re-assigned to the contents of the argument list.
  579. X.PP
  580. XFor the Plan 9 shell (rc),
  581. Xif the variable name corresponding to the \s-1ARGLIST\s+1 argument is
  582. X``\fB*\fP'', then the positional parameters of the calling program
  583. Xwill be re-assigned to the contents of the argument list.
  584. X.PP
  585. XFor \fIawk\fP and \fIperl\fP,
  586. Xif the variable name corresponding to the \s-1ARGLIST\s+1 argument is
  587. X``\fBARGV\fP'', then the positional parameters of the calling program
  588. Xwill be re-assigned to the contents of the argument list.
  589. X.SS "Bourne Shell Argument Lists"
  590. X.PP
  591. XFor the Bourne shell, if the associated variable name is \s-1NOT\s+1
  592. X``\fB\-\^\-\fP'' and the \fB\-A\fP option was \s-1NOT\s+1 specified,
  593. Xthen that variable is treated as a regular shell variable and is assigned
  594. Xusing the following syntax:
  595. X.sp 2p
  596. X.RS
  597. X\f4name\^=\^'arg1 arg2\fP  \fI...\fP\f4'\fP
  598. X.RE
  599. X.sp 2p
  600. XAfter invoking \fBparseargs\fP, if you wish to go through all the
  601. Xwords in the variable \fIname\fP and one of the words in \fIname\fP
  602. Xcontains an \s-1IFS\s+1 character (such as a space or a tab), then
  603. Xthat particular word will be treated by the Bourne shell as two distinct words.
  604. X.sp 8p
  605. XAlso for the Bourne shell,
  606. XIf the associated variable name is \s-1NOT\s+1 ``\fB\-\^\-\fP'' and the
  607. X\fB\-A\fP option \s-1WAS\s+1 specified, then that variable is treated as
  608. Xthe root name of an array that is set using the following syntax:
  609. X.sp 2p
  610. X.RS
  611. X.nf
  612. X\f4name1\^=\^'arg1'\fP
  613. X\f4name2\^=\^'arg2'\fP
  614. X\0\0\0 ...
  615. X.fi
  616. X.RE
  617. X.sp 2p
  618. Xand the variable ``\f4name_count\fP'' will be set to contain the number of
  619. Xitems in the array.  The user may then step through all the items in the array
  620. Xusing the following syntax:
  621. X.sp 2p
  622. X.RS
  623. X.nf
  624. X.ft 4
  625. Xi=1
  626. Xwhile [ $i -le $name_count ] ; do
  627. X  eval echo "item #$i is: " \\$name$i
  628. X  i=`expr $i + 1`
  629. Xdone
  630. X.ft R
  631. X.fi
  632. X.RE
  633. X.SS "Korn Shell Argument Lists"
  634. X.PP
  635. XFor the Korn shell, if the associated variable name is \s-1NOT\s+1
  636. X``\fB\-\^\-\fP'', then that variable is treated as an array and is assigned
  637. Xusing the \fB\-A\fP option of the set command. The first item will be in
  638. X\f4${name[0]}\fP, the second item will be in \f4${name[1]}\fP, etc ...,
  639. Xand all items may be given by \f4${name[*]}\fP or \f4${name[@]}\fP.
  640. XIf the associated variable name is \s-1NOT\s+1 ``\fB\-\^\-\fP'' and the
  641. X\fB\-A\fP option \s-1WAS\s+1 specified, then that variable is assigned
  642. Xusing the \fB+A\fP option of the set command (which preserves any array
  643. Xelements that were not overwritten by the set command).
  644. X.sp 2p
  645. XIt should be noted that there is a bug in versions of the Korn shell
  646. Xearlier than 11/16/88a, in which the following:
  647. X.sp 2p
  648. X.RS
  649. X\f4set  \-A  name  'arg1'  'arg2'\fP  \fI...\fP
  650. X.RE
  651. X.sp 2p
  652. Xcauses the positional parameters to be overwritten as an unintentional
  653. Xside-effect. If your version of the Korn shell is earlier than this and you
  654. Xwish to keep the contents of your positional parameters after invoking
  655. X\fBparseargs\fP than you must save them yourself before you call
  656. X\fBparseargs\fP. This may be accomplished by the following:
  657. X.sp 2p
  658. X.RS
  659. X\f4set  \-A  save_parms  "$@"\fP
  660. X.RE
  661. X.SS "C Shell Argument Lists"
  662. X.PP
  663. XFor the C shells (\fIcsh, tcsh, itcsh\fP),
  664. X\s-1ARGLIST\s+1 variables are treated as word-lists
  665. Xand are assigned using the following syntax:
  666. X.sp 2p
  667. X.RS
  668. X\f4set  name = ( 'arg1'  'arg2'\fP  \fI...\fP\f4 )\fP
  669. X.RE
  670. X.sp 2p
  671. XThe first item will be in \f4$name[1]\fP, the second item will be in
  672. X\f4$name[2]\fP, etc ..., and all items may be given by \f4$name\fP.
  673. XNotice that Korn shell arrays start at index zero whereas C shell
  674. Xword-lists start at index one.
  675. X.SS "Bourne-Again Shell Argument Lists"
  676. X.PP
  677. XAt present, the Free Software Foundation's Bourne-Again shell is treated
  678. Xexactly the same as the Bourne Shell. This will change when \fIbash\fP
  679. Xsupports arrays.
  680. X.SS "Plan 9 Shell Argument Lists"
  681. X.PP
  682. XFor the Plan 9 shell, if the associated variable name is not ``*'' then
  683. Xit is considered to be a word-list and set using the following syntax:
  684. X.nf
  685. X.RS
  686. X.ft 4
  687. Xname=( 'arg1'  'arg2'  ... )
  688. X.ft R
  689. X.RE
  690. X.fi
  691. X.SS "Z Shell Argument Lists"
  692. X.PP
  693. XFor the Z shell, \s-1ARGLIST\s+1 variables are treated as word-lists
  694. Xand are assigned using the following syntax:
  695. X.sp 2p
  696. X.RS
  697. X\f4name = ( 'arg1'  'arg2'\fP  \fI...\fP\f4 )\fP
  698. X.RE
  699. X.sp 2p
  700. XThe first item will be in \f4$name[1]\fP, the second item will be in
  701. X\f4$name[2]\fP, etc ..., and all items may be given by \f4$name\fP.
  702. XNotice that Korn shell arrays start at index zero whereas Z and C shell
  703. Xword-lists start at index one.
  704. X.SS "Awk Argument Lists"
  705. XFor \fIawk\fP, if the \fB\-A\fP option is not given, then the output for the
  706. Xvariable-list will be a line with the variable name, followed by a line with
  707. Xeach of the values (each value will be separated with the field separator
  708. Xspecified using the \fB\-S\fP option - which defaults to a space). 
  709. X.nf
  710. X.RS
  711. X.ft 4
  712. Xname
  713. Xarg1  arg2  ...
  714. X.ft R
  715. X.RE
  716. X.fi
  717. XIf the \fB\-A\fP option is given, then the associated variable is considered
  718. Xthe root name of an array. The ouput for the array
  719. Xwill consist of two lines for each item in the list (as in the following
  720. Xexample):
  721. X.nf
  722. X.RS
  723. X.ft 4
  724. Xname1
  725. Xarg1
  726. X
  727. Xname2
  728. Xarg2
  729. X
  730. X\...
  731. X.ft R
  732. X.RE
  733. X.fi
  734. Xand the variable ``\f4name_count\fP'' will have an output line showing the
  735. Xnumber of items in the array.
  736. X.PP
  737. X.SS "Perl Argument Lists"
  738. X.PP
  739. XFor \fIperl\fP, each argument list is considered an array and is set using 
  740. Xthe following syntax:
  741. X.nf
  742. X.RS
  743. X.ft 4
  744. X@name=( 'arg1' , 'arg2' ,  ... );
  745. X.ft R
  746. X.RE
  747. X.fi
  748. X.SS "A Final Note on Argument Lists"
  749. X.PP
  750. XThe word-lists used by the C and Z shells, the arrays used by the Korn shell,
  751. Xthe Plan 9 shell, \fIawk\fP, \fIperl\fP, and the positional parameters used by
  752. Xall shells (if overwritten by \fBparseargs\fP) will preserve any \s-1IFS\s+1
  753. Xcharacters in their contents.  That is to say that if an item in one of the
  754. Xaforementioned multi-word lists contains any \s-1IFS\s+1 characters, it will
  755. Xnot be split up into multiple items but will remain a single item which
  756. Xcontains \s-1IFS\s+1 characters.
  757. END_OF_FILE
  758. if test 7679 -ne `wc -c <'doc/sh_arrays.inc'`; then
  759.     echo shar: \"'doc/sh_arrays.inc'\" unpacked with wrong size!
  760. fi
  761. # end of 'doc/sh_arrays.inc'
  762. fi
  763. if test -f 'parseargs.awk' -a "${1}" != "-c" ; then 
  764.   echo shar: Will not clobber existing file \"'parseargs.awk'\"
  765. else
  766. echo shar: Extracting \"'parseargs.awk'\" \(6751 characters\)
  767. sed "s/^X//" >'parseargs.awk' <<'END_OF_FILE'
  768. X#!/usr/bin/awk -f
  769. X
  770. X##########################################################################
  771. X## ^FILE: parseargs.awk - parseargs for awk programs
  772. X##
  773. X## ^DESCRIPTION:
  774. X##    This file defines an awk function named parseargs to parse
  775. X##    command-line arguments for awk scripts. It also contains a
  776. X##    bare-bones template of what such an awk-script might contain.
  777. X##
  778. X## ^HISTORY:
  779. X##    02/21/91    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  780. X###^^#####################################################################
  781. X
  782. X
  783. X#########
  784. X## ^FUNCTION: parseargs - parse command-line argument vectors
  785. X##
  786. X## ^SYNOPSIS:
  787. X##    parseargs( argc, argv, argd, arr )
  788. X##
  789. X## ^PARAMETERS:
  790. X##    argc -- the number of elements in argv (usually ARGC-1).
  791. X##    argv -- the vector of command-line arguments (usually ARGV).
  792. X##    argd -- the argument-description string
  793. X##    arr  -- the associative array to assign command-line values from
  794. X##
  795. X## ^DESCRIPTION:
  796. X##    Parseargs will invoke parseargs(1) to parse the command-line given
  797. X##    in <argv> for the command defined by <argd>.  The resulting values
  798. X##    will be assigned to elements of the associative array given by <arr>.
  799. X##    Values are assigned using using the syntax: arr [ "argname" ] = value;
  800. X##    The exception to this is that if the <argname> is "ARGV" then the global
  801. X##    array ARGV is reset to the given array (using tab separated fields).
  802. X##
  803. X## ^REQUIREMENTS:
  804. X##    Any desired initial values for items in <arr> should be assigned BEFORE
  805. X##    calling this function (using the syntax: arr[ "argname" ] = initial-val).
  806. X##
  807. X##    The following global variables may be assigned before calling parseargs:
  808. X##
  809. X##       PROGNAME -- name of the current awk script (default= ARGV[0])
  810. X##       PARSEOPTS -- any extra options to pass to parseargs() (default="-ul")
  811. X##       PARSEINPUT -- input file for parseargs(1) (default=unique-name)
  812. X##       PARSEOUTPUT -- output file for parseargs(1) (default=unique-name)
  813. X##
  814. X## ^SIDE-EFFECTS:
  815. X##    The files PARSEINPUT and PARSEOUTPUT are created and then deleted.
  816. X##
  817. X##    The return value from parseargs(1) will be stored in the global-variable
  818. X##    named PARSESTATUS.
  819. X##
  820. X##    The global variable PARSEARGS will contain the command-line used to
  821. X##    invoke parseargs(1).
  822. X##
  823. X##    ARGV and ARGC may be reset, all other values are (re)set in <arr>.
  824. X##
  825. X## ^RETURN-VALUE:
  826. X##    The exit code returned by parseargs(1).
  827. X##
  828. X## ^BUGS:
  829. X##    Assumes that short-options are NOT disabled by $PARSECNTL.
  830. X##
  831. X##    Due to the limited ability of awk, scripts using parseargs(1) cannot
  832. X##    use short-options (with a  dash '-') because awk will attempt to interpret
  833. X##    any such arguments as options to awk and remove them from ARGV (regardless
  834. X##    of whether or not they are valid awk-options). Keyword options (with a
  835. X##    plus sign '+') may still be used without this difficulty. Dash-options
  836. X##    may be successfully processed if they did not first appear on the command
  837. X##    to the awk-script, so the full syntax of unix-style options could be 
  838. X##    provided in an array other than ARGV.
  839. X##
  840. X## ^ALGORITHM:
  841. X##    - set defaults for PROGNAME, PARSEOPTS, PARSEINPUT, and PARSEOUTPUT.
  842. X##    - build the parseargs command (dont forget to quote arguments).
  843. X##    - redirect input and output of the parseargs command.
  844. X##    - run parseargs(1)
  845. X##    - assign the exit-code from parseargs(1) to PARSESTATUS
  846. X##    - remove PARSEINPUT
  847. X##    - if PARSESTATUS != 0
  848. X##      - save RS and FS and reset RS = "" and FS = "\n"
  849. X##      - for each record in PARSEOUTPUT
  850. X##        - $1 is the argname and $2 is the value
  851. X##        - if $1 is "ARGV" reset ARGV and ARGC ($2 is a tab separated array)
  852. X##        - else assign arr[ $1 ] = $2
  853. X##      end-for
  854. X##      - restore RS and FS to previous values
  855. X##      - remove PARSEOUTPUT
  856. X##      - return PARSESTATUS
  857. X###^^####
  858. X
  859. Xfunction parseargs(argc, argv, argd, arr) {
  860. X      ## set defaults -- use $$ to get a unique suffix string
  861. X   if ( ! PROGNAME )     PROGNAME = ARGV[0];
  862. X   if ( ! PARSEOPTS )    PARSEOPTS = "-u -l";
  863. X
  864. X   "echo  ${TMP:-/tmp}/parseargs.${$}_"  |  getline TMPFILE;
  865. X   if ( ! PARSEINPUT )   PARSEINPUT = TMPFILE "in";
  866. X   if ( ! PARSEOUTPUT )  PARSEOUTPUT = TMPFILE "out";
  867. X
  868. X      ## build the options and required arguments for parseargs(1)
  869. X   PARSEARGS = sprintf( "parseargs -s awk %s -S '\t' -- '%s'",
  870. X                            PARSEOPTS, PROGNAME );
  871. X
  872. X      ## quote each elemnt in argv and append it to the parseargs-command
  873. X   for ( i = 1 ; i <= argc ; i++ ) {
  874. X      arg = argv[i];
  875. X      gsub( /'/, "'\\''", arg );
  876. X      PARSEARGS = PARSEARGS " '" arg "'";
  877. X   }
  878. X
  879. X      ## set up i/o redirection
  880. X   PARSEARGS = PARSEARGS  " <" PARSEINPUT  " >" PARSEOUTPUT;
  881. X   print  argd > PARSEINPUT;
  882. X
  883. X      ## invoke parseargs(1) and save the status
  884. X   PARSESTATUS = system( PARSEARGS );
  885. X   system( "/bin/rm -f " PARSEINPUT );  ## dont need input anymore
  886. X
  887. X      ## if successful status, read the result
  888. X   if ( PARSESTATUS == 0 ) {
  889. X      save_RS = RS; save_FS = FS;
  890. X      RS = ""; FS = "\n";
  891. X      while ( getline  < PARSEOUTPUT  > 0 ) {
  892. X         gsub( /\034/, "\n" );
  893. X         if ( $1 == "ARGV" ) {
  894. X            ARGC = 1 + split( $2, ARGV, "\t" );
  895. X            ARGV[0] = PROGNAME;
  896. X         }
  897. X         else  arr[ $1 ] = $2;
  898. X      }
  899. X      RS = save_RS; FS = save_FS;
  900. X   }
  901. X   system( "/bin/rm -f " PARSEOUTPUT );
  902. X
  903. X   return  PARSESTATUS;
  904. X}
  905. X
  906. X
  907. XBEGIN {
  908. X  PROGNAME = "test.awk";
  909. X  ARGD = sprintf( "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
  910. X    "'?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit'" ,
  911. X    "'S', ARGVALOPT, argStr,   string,  'STRing : optional string arg'" ,
  912. X    "'g', ARGLIST,   argStr,   groups,  'newsGROUPS : groups to test'" ,
  913. X    "'r', ARGOPT,    argInt,   count,   'REPcount : group repeat count'" ,
  914. X    "'d', ARGOPT,    argStr,   dirname, 'DIRectory : working directory'" ,
  915. X    "'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode'" ,
  916. X    "'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode'" ,
  917. X    "'s', ARGOPT,    argChar,  sepch,   'SEPchar : field separator'" ,
  918. X    "'f', ARGLIST,   argStr,   files,   'files : files to process'" ,
  919. X    "' ', ARGREQ,    argStr,   name,    'name : name to use'" ,
  920. X    "' ', ARGLIST,   argStr,   argv,    'argv : any remaining arguments'" ,
  921. X    "ENDOFARGS" );
  922. X
  923. X  Args[ "count" ] = 1;
  924. X  Args[ "dirname" ] = ".";
  925. X  Args[ "sepch" ] = ",";
  926. X  Args[ "yflag" ] = "TRUE";
  927. X
  928. X  rc = parseargs( ARGC-1, ARGV, ARGD, Args );
  929. X  if ( rc != 0 )  exit( rc );
  930. X
  931. X  ## print  the parsed arguments (use defaults if not defined)
  932. X  print "ARGUMENTS:";
  933. X  print "==========";
  934. X
  935. X  for ( i in Args )
  936. X    printf( "Args[\"%s\"] = \"%s\"\n", i, Args[i] );
  937. X
  938. X  argc = split( Args[ "argv" ], argv, "\t" );
  939. X  for ( i = 1 ; i <= argc ; i++ )
  940. X    printf( "argv[%d] = \"%s\"\n", i, argv[i] );
  941. X    
  942. X}
  943. END_OF_FILE
  944. if test 6751 -ne `wc -c <'parseargs.awk'`; then
  945.     echo shar: \"'parseargs.awk'\" unpacked with wrong size!
  946. fi
  947. # end of 'parseargs.awk'
  948. fi
  949. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  950.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  951. else
  952. echo shar: Extracting \"'patchlevel.h'\" \(7694 characters\)
  953. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  954. X/*************************************************************************
  955. X** ^FILE: patchlevel.h - current patchlevel for parseargs
  956. X**
  957. X** ^HISTORY:
  958. X**
  959. X**    01/02/92    Brad Appleton    <brad@ssd.csd.harris.com>
  960. X**    Patch11
  961. X**    - Added strndup() to strfuncs.[ch]
  962. X**    - vms_args.c:vms_parse was not setting avstr if ps_NOTCMDLINE was set.
  963. X**    - made a few other fixes for VMS. Gratuitous "thank you"s go out to
  964. X**      Mike Levin for helping me find and test these fixes (thanx Mike!).
  965. X**    - added VMSbuild.com (contributed by Luke Brennan) to build parseargs
  966. X**      on VAX/VMS.
  967. X**    - fixed unix_man.c to call indent_para() properly.
  968. X**    - added support for TCL to parseargs(1).
  969. X**    - changed the way that parseargs(1) handles escape-sequences.
  970. X**
  971. X**    12/05/91    Brad Appleton    <brad@ssd.csd.harris.com>
  972. X**    Patch10
  973. X**    - Fix bug that was introduced in last patch. Pgopen() was not
  974. X**      using $USAGE_PAGER, it was only using $PAGER.
  975. X**    - When Earl added the extra argument to indent_para(), he forgot to
  976. X**      include the argument when printing the command description. I added
  977. X**      this into *_args.c
  978. X**    - Added #ifdef POSIX_SOURCE stuff to unix_args.c to allow the use 
  979. X**      of '--' instead of '+' as the long option prefix.
  980. X**
  981. X**    08/27/91    Brad Appleton    <brad@ssd.csd.harris.com>
  982. X**    08/27/91    Earl Chew    <cechew@bruce.cs.monash.edu.au>
  983. X**    Patch09
  984. X**    - Added proper support for unwritable strings
  985. X**    - strfuncs.c/strsplit():
  986. X**      Leading, and in particular, trailing space trimming may spin off
  987. X**      the end of the token string. This occurs when the string is empty,
  988. X**      or when it has trailing space.
  989. X**      Out of memory error doesn't call syserr() like the rest of the
  990. X**      routines do.
  991. X**    - xparse.c/parsecntl():
  992. X**      Documentation says that the fourth parameter for pc_ARGFLAGS and
  993. X**      pc_PARSEARGS should be either argMask_t (promoted to int) in the
  994. X**      case of writes, or argMask_t * in the case of reads. The code is 
  995. X**      at odds with the documentation and requires (int *) on reads.
  996. X**      Also, should check for NULL cmd-name before passing it to strdup().
  997. X**    - vms_args.c/is_cmdline():
  998. X**      Mike Levin pointed out to me that if lib$get_foreign returns a
  999. X**      zero-length string then the proper actions are not taken. This
  1000. X**      has been fixed.
  1001. X**    - vms_args.c, parseargs.h, xparse.c
  1002. X**      For vms_style I added a new parse-state called ps_NOTCMDLINE.
  1003. X**      When this flag is SET, then vms_parse() knows for a fact that
  1004. X**      the given argv[] array is NOT from the cmdline so it doesnt even
  1005. X**      need to call is_cmdline(). SO Now I just have the proper routines
  1006. X**      in xparse.c set this flag before calling vms_parse() (and unset
  1007. X**      the flag when they are done).
  1008. X**    - vms_args.c/vms_parse():
  1009. X**      ARGVALGIVEN was set instead of ARGGIVEN (this was wrong).
  1010. X**
  1011. X**
  1012. X**    08/15/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1013. X**    Patch08
  1014. X**    - fixed some typos in the comments (SIDE-EFFECTS was misspelled
  1015. X**      everywhere in the comments for the functions).
  1016. X**    - fixed up external definition of ProgName to work for C++
  1017. X**      (added extern "C").
  1018. X**    - fixed up lparseargs() and vparseargs to free the argument vector
  1019. X**      when it was finished with it.
  1020. X**    - added some more comments to xparse.c and parseargs.c.
  1021. X**
  1022. X**    06/05/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1023. X**    Patch07
  1024. X**    - fixed the "Intro" file to correctly show how to invoke parseargs(3)
  1025. X**      (the arguments where in the wrong order).
  1026. X**    - added stuff in #ifdef UNWRITABLE_STRING_LITERALS to work for machines
  1027. X**      and compilers that dont allow the programmer to modify string literals.
  1028. X**    - documented in the README file, all the various compile-time constants
  1029. X**      that may change the behavior of parseargs.
  1030. X**    - sparseargs neglected to free the argument-vector when it was done
  1031. X**      using it.
  1032. X**
  1033. X**    05/11/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1034. X**    Patch06
  1035. X**    - parsecntl(3) now correctly handles mispelled keywords for the
  1036. X**      pc_ARGFLAGS request (it was looping forever).
  1037. X**    - fixed an error in the documentation (a "NOT" was omitted).
  1038. X**    - added #ifdef SVR4 stuff to unix_man.c to print System V Release 4
  1039. X**      style manual pages.
  1040. X**    - allowed "sname=aname" syntax in the ad_prompt field of an ARGDESC
  1041. X**      in addition to the existing syntax. This new syntax allows argument
  1042. X**      names to be be completely different from keyword names.
  1043. X**    - changed get_name() & get_keyword to get_argname() & get_kwdname()
  1044. X**      (respectively) in strfuncs.[ch]. Also sped up the algorithm to get
  1045. X**      the keyword (since it no longer needs malloc).
  1046. X**
  1047. X**    04/25/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1048. X**    Patch05
  1049. X**    - documented support for zsh in parseargs(1)
  1050. X**    - added missing call to pclose() in pgopen.c:pgclose()
  1051. X**    - added zsh to the list of shells supported by parseargs(1)
  1052. X**      (I have yet to document this in the man-pages)
  1053. X**    - changed the shell_info structure used by parseargs(1) to 
  1054. X**      represent different shells. It should now be much simpler
  1055. X**      to add new shells to parseargs.c
  1056. X**    - fixed a bug in strfuncs.c:basename() for VMS systems
  1057. X**    - added more comments to explain whats going on in each <os>_args.c
  1058. X**    - updated the README file to correspond with the patchlevel(s)
  1059. X**    - updated dependencies in doc/Makefile
  1060. X**
  1061. X**    04/10/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1062. X**    Patch04
  1063. X**    - fixed problem with prompting in xparse.c:prompt_user()
  1064. X**    - under VMS, getenv was defined to be 'getsymbol', it should
  1065. X**      be 'get_symbol' (note the underscore).
  1066. X**    - now includes <errno.h> to declare errno
  1067. X**    - parseargs no longer includes <fcntl.h>
  1068. X**    - fix bug in vms_args.c printing '[]' for required args and vis-a-vis
  1069. X**    - fixed bug in argInput and argOutput in argtype.c for VMS
  1070. X**    - fixed bug in <os>_args.c where ARGVALGIVEN was improperly being
  1071. X**      cleared if the argument was a list or a vector. This was causing
  1072. X**      parseargs(1) to screw up on optional lists.
  1073. X**    - fixed bug in strfuncs.c:strnicmp() (it was ignoring the length)
  1074. X**    - changed strfuncs.[ch] so that my version of strdup is always used
  1075. X**      (my version exits if malloc failed, others return NULL).
  1076. X**    - Added some changes for SUN and VAX
  1077. X**    - Added -1 option to parseargs(1)
  1078. X**    - Unhid the -# option to parseargs(1)
  1079. X**    - More documentation fixes
  1080. X**
  1081. X**    04/04/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1082. X**    Patch04 (continued)
  1083. X**    - fixed bug in xparse.c with PARSECNTL='Prompt' being ignored.
  1084. X**    - fixed newline printing error in perl-scripts for parseargs(1)
  1085. X**    - added -C option to parseargs(1) and to the docs
  1086. X**    - added "patchlevel.h" to distribution
  1087. X**    - added "what" string with version and patch level for parseargs(1)
  1088. X**    - added hidden -# option to parseargs(1)
  1089. X**    - add "doc/effects.inc" to distribution
  1090. X**    - fix docs
  1091. X**    - fix test.rc for Plan 9 shell
  1092. X**    - fix parseargs(1) quoting for perl
  1093. X**
  1094. X**    03/22/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1095. X**    Patch03
  1096. X**    - ascii docs fix
  1097. X**
  1098. X**    03/21/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1099. X**    Patch02
  1100. X**    - documentation fix
  1101. X**
  1102. X**    03/12/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1103. X**    Patch01
  1104. X**    - documentation fix
  1105. X**
  1106. X**    03/02/91    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  1107. X***^^********************************************************************/
  1108. X
  1109. X#define  VERSION     2
  1110. X#define  REVISION    0
  1111. X#define  PATCHLEVEL  11
  1112. X
  1113. X#ifdef __STDC__
  1114. X   static const char
  1115. X#else
  1116. X   static char
  1117. X#endif
  1118. X   _Ident[] = "@(#)parseargs  2.0  patchlevel 11";
  1119. END_OF_FILE
  1120. if test 7694 -ne `wc -c <'patchlevel.h'`; then
  1121.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  1122. fi
  1123. # end of 'patchlevel.h'
  1124. fi
  1125. if test -f 'syserr.c' -a "${1}" != "-c" ; then 
  1126.   echo shar: Will not clobber existing file \"'syserr.c'\"
  1127. else
  1128. echo shar: Extracting \"'syserr.c'\" \(6183 characters\)
  1129. sed "s/^X//" >'syserr.c' <<'END_OF_FILE'
  1130. X/*************************************************************************
  1131. X** ^FILE: syserr.c - error-message printing routines
  1132. X**
  1133. X** ^DESCRIPTION:
  1134. X**    This fill implements various routines for printing diagnostic
  1135. X**    messages on standard diagnostic output (stderr). The routines are:
  1136. X**
  1137. X**       usrerr()  --  print message and any system message(s) and return
  1138. X**       syserr()  --  print message and any system message(s) and exit
  1139. X**       eprintf() --  print to stderr and return
  1140. X**
  1141. X** ^HISTORY:
  1142. X**    27/08/91     Earl Chew     <cechew@bruce.cs.monash.edu.au>
  1143. X**    - Use ProgNameLen when accessing ProgName
  1144. X**
  1145. X**    01/02/91    Brad Appleton    <brad@ssd.csd.harris.com>
  1146. X**       - Changed to use varargs/stdargs
  1147. X**       - Added structured comment blocks
  1148. X**       - Added eprintf()
  1149. X**
  1150. X**    --/--/--    Peter da Silva    <peter@ferranti.com>
  1151. X**
  1152. X**    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  1153. X***^^**********************************************************************/
  1154. X
  1155. X#include <stdio.h>
  1156. X#include <errno.h>
  1157. X#include <useful.h>
  1158. X/* #include <funclist.h> */
  1159. X
  1160. X#ifdef vms
  1161. X# include <ssdef.h>
  1162. X# define  e_FATAL  SS$_CANCEL
  1163. X#else
  1164. X# define  e_FATAL  127
  1165. X#endif
  1166. X
  1167. XVERSIONID("$Header: syserr.c,v 2.0 89/12/24 00:56:31 eric Exp $");
  1168. X
  1169. Xextern  char *ProgName;
  1170. Xextern  int ProgNameLen;
  1171. XEXTERN  int   vfprintf  ARGS((FILE *, const char *, va_list));
  1172. X
  1173. X
  1174. X/***************************************************************************
  1175. X** ^FUNCTION: _error_message - generic message printing routine.
  1176. X**
  1177. X** ^SYNOPSIS:
  1178. X*/
  1179. X#ifndef __ANSI_C__
  1180. X   static VOID _error_message( format, ap )
  1181. X/*
  1182. X** ^PARAMETERS:
  1183. X*/
  1184. X   char *format;
  1185. X/*    -- the formatted message-string to print.
  1186. X*/
  1187. X   va_list ap;
  1188. X/*    -- the list of variable arguments for vfprintf().
  1189. X*/
  1190. X#endif  /* !__ANSI_C__ */
  1191. X
  1192. X/* ^DESCRIPTION:
  1193. X**    _error_message will print the program name followed by the
  1194. X**    formatted message. If errno is non-zero, the corresponding
  1195. X**    system message will also be printed.
  1196. X**
  1197. X** ^REQUIREMENTS:
  1198. X**    None.
  1199. X**
  1200. X** ^SIDE-EFFECTS:
  1201. X**    Writes to stderr.
  1202. X**
  1203. X** ^RETURN-VALUE:
  1204. X**    None.
  1205. X**
  1206. X** ^ALGORITHM:
  1207. X**    - print the program name
  1208. X**    - print the message
  1209. X**    - if errno is non-zero, call perror()
  1210. X***^^**********************************************************************/
  1211. X#ifdef __ANSI_C__
  1212. X   static void _error_message( const char *format, va_list ap )
  1213. X#endif
  1214. X{
  1215. X   int save_err;
  1216. X
  1217. X   save_err = errno;
  1218. X   if (ProgName  &&  *ProgName)
  1219. X      fprintf(stderr, "%.*s: ", ProgNameLen, ProgName);
  1220. X
  1221. X   (VOID) vfprintf(stderr, format, ap);
  1222. X
  1223. X   fputc('\n', stderr);
  1224. X   if ( save_err ) {
  1225. X      errno = save_err;
  1226. X      perror("System error");
  1227. X   }
  1228. X   fflush(stderr);
  1229. X}
  1230. X
  1231. X
  1232. X/***************************************************************************
  1233. X** ^FUNCTION: syserr - print a formatted message and exit
  1234. X**
  1235. X** ^SYNOPSIS:
  1236. X*/
  1237. X#ifndef __ANSI_C__
  1238. X   VOID syserr( format, va_alist )
  1239. X/*
  1240. X** ^PARAMETERS:
  1241. X*/
  1242. X   char *format;
  1243. X/*    -- the format string to pass to vfprintf()
  1244. X*/
  1245. X   va_dcl  
  1246. X/*    -- the arguments to be formatted
  1247. X*/
  1248. X#endif  /* !__ANSI_C__ */
  1249. X
  1250. X/* ^DESCRIPTION:
  1251. X**    Syserr will print the current program name followed by the
  1252. X**    formatted message. If errno is non-zero, it will use perror
  1253. X**    to print the corresponding system error message. Lastly, Syserr
  1254. X**    will terminate execution with an exit code of 1.
  1255. X**
  1256. X** ^REQUIREMENTS:
  1257. X**    No special requirements.
  1258. X**
  1259. X** ^SIDE-EFFECTS:
  1260. X**    All output is written to stderr. Program execution is terminated.
  1261. X**
  1262. X** ^RETURN-VALUE:
  1263. X**    None (Does not return).
  1264. X**
  1265. X** ^ALGORITHM:
  1266. X**    - print the error message(s)
  1267. X**    - take care of recursive calls to syserr()
  1268. X**    - exit
  1269. X***^^**********************************************************************/
  1270. X#ifdef __ANSI_C__
  1271. X   void syserr( const char *format, ... )
  1272. X#endif
  1273. X{
  1274. X   static BOOL exiting = FALSE;
  1275. X   va_list ap;
  1276. X
  1277. X   /* print the error message */
  1278. X   VA_START(ap, format);
  1279. X   _error_message(format, ap);
  1280. X   VA_END(ap);
  1281. X
  1282. X   /* if we recursively syserr during exit, drop out now! */
  1283. X   if (exiting)  exit(e_FATAL);
  1284. X
  1285. X   /* try a clean exit */
  1286. X   exiting = TRUE;
  1287. X   exit(e_FATAL);
  1288. X   /*NOTREACHED*/
  1289. X}
  1290. X
  1291. X
  1292. X/***************************************************************************
  1293. X** ^FUNCTION: eprintf - print a formatted message on stderr.
  1294. X**
  1295. X** ^SYNOPSIS:
  1296. X*/
  1297. X#ifndef __ANSI_C__
  1298. X   int eprintf( format, va_alist )
  1299. X/*
  1300. X** ^PARAMETERS:
  1301. X*/
  1302. X   char *format;
  1303. X/*    -- the printf() message to print.
  1304. X*/
  1305. X   va_dcl
  1306. X/*    -- the arguments to be formatted
  1307. X*/
  1308. X#endif  /* !__ANSI_C__ */
  1309. X
  1310. X/* ^DESCRIPTION:
  1311. X**    Eprintf() will behaves exactly like printf with the sole
  1312. X**    exception being that it writes to stderr instead of stdout.
  1313. X**
  1314. X** ^REQUIREMENTS:
  1315. X**    None.
  1316. X**
  1317. X** ^SIDE-EFFECTS:
  1318. X**    Writes to stderr.
  1319. X**
  1320. X** ^RETURN-VALUE:
  1321. X**    Same as printf(3).
  1322. X**
  1323. X** ^ALGORITHM:
  1324. X**    Trivial.
  1325. X***^^**********************************************************************/
  1326. X#ifdef __ANSI_C__
  1327. X   int eprintf( const char *format, ... )
  1328. X#endif
  1329. X{
  1330. X   int rc;
  1331. X   va_list ap;
  1332. X
  1333. X   VA_START(ap, format);
  1334. X   rc = vfprintf( stderr, format, ap );
  1335. X   VA_END(ap);
  1336. X
  1337. X   fflush(stderr);
  1338. X   return rc;
  1339. X}
  1340. X
  1341. X
  1342. X/***************************************************************************
  1343. X** ^FUNCTION: usrerr - print a user error message
  1344. X**
  1345. X** ^SYNOPSIS:
  1346. X*/
  1347. X#ifndef __ANSI_C__
  1348. X   VOID usrerr( format, va_alist )
  1349. X/*
  1350. X** ^PARAMETERS:
  1351. X*/
  1352. X   char *format;
  1353. X/*    -- the format string to pass to vfprintf()
  1354. X*/
  1355. X   va_dcl
  1356. X/*    -- the arguments to be formatted
  1357. X*/
  1358. X#endif  /* !__ANSI_C__ */
  1359. X
  1360. X/* ^DESCRIPTION:
  1361. X**    Usrerr will print the current program name followed by the
  1362. X**    formatted message. If errno is non-zero, it will use perror
  1363. X**    to print the corresponding system error message.
  1364. X**
  1365. X** ^REQUIREMENTS:
  1366. X**    No special requirements.
  1367. X**
  1368. X** ^SIDE-EFFECTS:
  1369. X**    All output is written to stderr.  Errno is cleared.
  1370. X**
  1371. X** ^RETURN-VALUE:
  1372. X**    None.
  1373. X**
  1374. X** ^ALGORITHM:
  1375. X**    - print the error message(s)
  1376. X**    - set errno to zero
  1377. X***^^**********************************************************************/
  1378. X#ifdef __ANSI_C__
  1379. X   void usrerr( const char *format, ... )
  1380. X#endif
  1381. X{
  1382. X   va_list ap;
  1383. X
  1384. X   /* print the error message */
  1385. X   VA_START(ap, format);
  1386. X   _error_message(format, ap);
  1387. X   VA_END(ap);
  1388. X
  1389. X   /* give us a clean slate */
  1390. X   errno = 0;
  1391. X}
  1392. END_OF_FILE
  1393. if test 6183 -ne `wc -c <'syserr.c'`; then
  1394.     echo shar: \"'syserr.c'\" unpacked with wrong size!
  1395. fi
  1396. # end of 'syserr.c'
  1397. fi
  1398. if test -f 'test.awk' -a "${1}" != "-c" ; then 
  1399.   echo shar: Will not clobber existing file \"'test.awk'\"
  1400. else
  1401. echo shar: Extracting \"'test.awk'\" \(6643 characters\)
  1402. sed "s/^X//" >'test.awk' <<'END_OF_FILE'
  1403. X#!/usr/bin/awk -f
  1404. X
  1405. X##########################################################################
  1406. X## ^FILE: test.awk - parseargs for awk programs
  1407. X##
  1408. X## ^DESCRIPTION:
  1409. X##    This file defines an awk function named parseargs to parse
  1410. X##    command-line arguments for awk scripts. It also contains a
  1411. X##    bare-bones template of what such an awk-script might contain.
  1412. X##
  1413. X## ^HISTORY:
  1414. X##    02/21/91    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  1415. X###^^#####################################################################
  1416. X
  1417. X
  1418. X#########
  1419. X## ^FUNCTION: parseargs - parse command-line argument vectors
  1420. X##
  1421. X## ^SYNOPSIS:
  1422. X##    parseargs( argc, argv, argd, arr )
  1423. X##
  1424. X## ^PARAMETERS:
  1425. X##    argc -- the number of elements in argv (usually ARGC-1).
  1426. X##    argv -- the vector of command-line arguments (usually ARGV).
  1427. X##    argd -- the argument-description string
  1428. X##    arr  -- the associative array to assign command-line values from
  1429. X##
  1430. X## ^DESCRIPTION:
  1431. X##    Parseargs will invoke parseargs(1) to parse the command-line given
  1432. X##    in <argv> for the command defined by <argd>.  The resulting values
  1433. X##    will be assigned to elements of the associative array given by <arr>.
  1434. X##    Values are assigned using using the syntax: arr [ "argname" ] = value;
  1435. X##    The exception to this is that if the <argname> is "ARGV" then the global
  1436. X##    array ARGV is reset to the given array (using tab separated fields).
  1437. X##
  1438. X## ^REQUIREMENTS:
  1439. X##    Any desired initial values for items in <arr> should be assigned BEFORE
  1440. X##    calling this function (using the syntax: arr[ "argname" ] = initial-val).
  1441. X##
  1442. X##    The following global variables may be assigned before calling parseargs:
  1443. X##
  1444. X##       PROGNAME -- name of the current awk script (default= ARGV[0])
  1445. X##       PARSEOPTS -- any extra options to pass toi parseargs() (default="-ul")
  1446. X##       PARSEINPUT -- input file for parseargs(1) (default=unique-name)
  1447. X##       PARSEOUTPUT -- output file for parseargs(1) (default=unique-name)
  1448. X##
  1449. X## ^SIDE-EFFECTS:
  1450. X##    The files PARSEINPUT and PARSEOUTPUT are created and then deleted.
  1451. X##
  1452. X##    The return value from parseargs(1) will be stored in the global-variable
  1453. X##    named PARSESTATUS.
  1454. X##
  1455. X##    The global variable PARSEARGS will contain the command-line used to
  1456. X##    invoke parseargs(1).
  1457. X##
  1458. X##    ARGV and ARGC may be reset, all other values are (re)set in <arr>.
  1459. X##
  1460. X## ^RETURN-VALUE:
  1461. X##    The exit code returned by parseargs(1).
  1462. X##
  1463. X## ^BUGS:
  1464. X##    Due to the limited ability of awk, scripts using parseargs(1) cannot
  1465. X##    use short-options (with a  dash '-') because awk will attempt to interpret
  1466. X##    any such arguments as options to awk and remove them from ARGV (regardless
  1467. X##    of whether or not they are valid awk-options). Keyword options (with a
  1468. X##    plus sign '+') may still be used without this difficulty. Dash-options
  1469. X##    may be successfully processed if they did not first appear on the command
  1470. X##    to the awk-script, so the full syntax of unix-style options could be 
  1471. X##    provided in an array other than ARGV.
  1472. X##
  1473. X## ^ALGORITHM:
  1474. X##    - set defaults for PROGNAME, PARSEOPTS, PARSEINPUT, and PARSEOUTPUT.
  1475. X##    - build the parseargs command (dont forget to quote arguments).
  1476. X##    - redirect input and output of the parseargs command.
  1477. X##    - run parseargs(1)
  1478. X##    - assign the exit-code from parseargs(1) to PARSESTATUS
  1479. X##    - remove PARSEINPUT
  1480. X##    - if PARSESTATUS != 0
  1481. X##      - save RS and FS and reset RS = "" and FS = "\n"
  1482. X##      - for each record in PARSEOUTPUT
  1483. X##        - $1 is the argname and $2 is the value
  1484. X##        - if $1 is "ARGV" reset ARGV and ARGC ($2 is a tab separated array)
  1485. X##        - else assign arr[ $1 ] = $2
  1486. X##      end-for
  1487. X##      - restore RS and FS to previous values
  1488. X##      - remove PARSEOUTPUT
  1489. X##      - return PARSESTATUS
  1490. X###^^####
  1491. X
  1492. Xfunction parseargs(argc, argv, argd, arr) {
  1493. X      ## set defaults -- use $$ to get a unique suffix string
  1494. X   if ( ! PROGNAME )     PROGNAME = ARGV[0];
  1495. X   if ( ! PARSEOPTS )    PARSEOPTS = "-u -l";
  1496. X
  1497. X   "echo  ${TMP:-/tmp}/parseargs.${$}_"  |  getline TMPFILE;
  1498. X   if ( ! PARSEINPUT )   PARSEINPUT = TMPFILE "in";
  1499. X   if ( ! PARSEOUTPUT )  PARSEOUTPUT = TMPFILE "out";
  1500. X
  1501. X      ## build the options and required arguments for parseargs(1)
  1502. X   PARSEARGS = sprintf( "parseargs -s awk %s -- '%s'", PARSEOPTS, PROGNAME );
  1503. X
  1504. X      ## quote each elemnt in argv and append it to the parseargs-command
  1505. X   for ( i = 1 ; i <= argc ; i++ ) {
  1506. X      arg = argv[i];
  1507. X      gsub( /'/, "'\\''", arg );
  1508. X      PARSEARGS = PARSEARGS " '" arg "'";
  1509. X   }
  1510. X
  1511. X      ## set up i/o redirection
  1512. X   PARSEARGS = PARSEARGS  " <" PARSEINPUT  " >" PARSEOUTPUT;
  1513. X   print  argd > PARSEINPUT;
  1514. X
  1515. X      ## invoke parseargs(1) and save the status
  1516. X   PARSESTATUS = system( PARSEARGS );
  1517. X   system( "/bin/rm -f " PARSEINPUT );  ## dont need input anymore
  1518. X
  1519. X      ## if successful status, read the result
  1520. X   if ( PARSESTATUS == 0 ) {
  1521. X      save_RS = RS; save_FS = FS;
  1522. X      RS = ""; FS = "\n";
  1523. X      while ( getline  < PARSEOUTPUT  > 0 ) {
  1524. X         gsub( /\034/, "\n" );
  1525. X         if ( $1 == "ARGV" ) {
  1526. X            ARGC = 1 + split( $2, ARGV, "\t" );
  1527. X            ARGV[0] = PROGNAME;
  1528. X         }
  1529. X         else  arr[ $1 ] = $2;
  1530. X      }
  1531. X      RS = save_RS; FS = save_FS;
  1532. X   }
  1533. X   system( "/bin/rm -f " PARSEOUTPUT );
  1534. X
  1535. X   return  PARSESTATUS;
  1536. X}
  1537. X
  1538. X
  1539. XBEGIN {
  1540. X  PROGNAME = "test.awk";
  1541. X  ARGD = sprintf( "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
  1542. X    "'?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit'" ,
  1543. X    "'S', ARGVALOPT, argStr,   string,  'STRing : optional string arg'" ,
  1544. X    "'g', ARGLIST,   argStr,   groups,  'newsGROUPS : groups to test'" ,
  1545. X    "'r', ARGOPT,    argInt,   count,   'REPcount : group repeat count'" ,
  1546. X    "'d', ARGOPT,    argStr,   dirname, 'DIRectory : working directory'" ,
  1547. X    "'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode'" ,
  1548. X    "'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode'" ,
  1549. X    "'s', ARGOPT,    argChar,  sepch,   'SEPchar : field separator'" ,
  1550. X    "'f', ARGLIST,   argStr,   files,   'files : files to process'" ,
  1551. X    "'n', ARGREQ|ARGPOS, argStr, name,  'name : name to use'" ,
  1552. X    "' ', ARGLIST,   argStr,   argv,    'argv : any remaining arguments'" ,
  1553. X    "ENDOFARGS" );
  1554. X
  1555. X  Args[ "count" ] = 1;
  1556. X  Args[ "dirname" ] = ".";
  1557. X  Args[ "sepch" ] = ",";
  1558. X  Args[ "yflag" ] = "TRUE";
  1559. X
  1560. X  rc = parseargs( ARGC-1, ARGV, ARGD, Args );
  1561. X  if ( rc != 0 )  exit( rc );
  1562. X
  1563. X  ## print  the parsed arguments (use defaults if not defined)
  1564. X  print "ARGUMENTS:";
  1565. X  print "==========";
  1566. X
  1567. X  for ( i in Args )
  1568. X    printf( "Args[\"%s\"] = \"%s\"\n", i, Args[i] );
  1569. X
  1570. X  argc = split( Args[ "argv" ], argv, "\t" );
  1571. X  for ( i = 1 ; i <= argc ; i++ )
  1572. X    printf( "argv[%d] = \"%s\"\n", i, argv[i] );
  1573. X    
  1574. X}
  1575. END_OF_FILE
  1576. if test 6643 -ne `wc -c <'test.awk'`; then
  1577.     echo shar: \"'test.awk'\" unpacked with wrong size!
  1578. fi
  1579. chmod +x 'test.awk'
  1580. # end of 'test.awk'
  1581. fi
  1582. if test -f 'vprintf.c' -a "${1}" != "-c" ; then 
  1583.   echo shar: Will not clobber existing file \"'vprintf.c'\"
  1584. else
  1585. echo shar: Extracting \"'vprintf.c'\" \(8146 characters\)
  1586. sed "s/^X//" >'vprintf.c' <<'END_OF_FILE'
  1587. X/* Portable vsprintf  by Robert A. Larson <blarson@skat.usc.edu> */
  1588. X
  1589. X/* Copyright 1989 Robert A. Larson.
  1590. X * Distribution in any form is allowed as long as the author
  1591. X * retains credit, changes are noted by their author and the
  1592. X * copyright message remains intact.  This program comes as-is
  1593. X * with no warentee of fitness for any purpose.
  1594. X *
  1595. X * Thanks to Doug Gwyn, Chris Torek, and others who helped clarify
  1596. X * the ansi printf specs.
  1597. X *
  1598. X * Please send any bug fixes and improvements to blarson@skat.usc.edu .
  1599. X * The use of goto is NOT a bug.
  1600. X */
  1601. X
  1602. X/* Feb    7, 1989        blarson        First usenet release */
  1603. X/* Oct 20, 1990     Brad Appleton -- enclosed in #ifdef BSD for parseargs */
  1604. X/* Oct 21, 1990     Brad Appleton -- added test in #ifdef VPRINTF_TEST */
  1605. X/* Feb 25, 1990     Brad Appleton -- #included "useful.h" and added #ifdefs
  1606. X *                                   to compile for ANSI-C as well as K&R
  1607. X */
  1608. X
  1609. X
  1610. X/* This code implements the vsprintf function, without relying on
  1611. X * the existance of _doprint or other system specific code.
  1612. X *
  1613. X * Define NOVOID if void * is not a supported type.
  1614. X *
  1615. X * Two compile options are available for efficency:
  1616. X *    INTSPRINTF    should be defined if sprintf is int and returns
  1617. X *                the number of chacters formated.
  1618. X *    LONGINT        should be defined if sizeof(long) == sizeof(int)
  1619. X *
  1620. X *    They only make the code smaller and faster, they need not be
  1621. X *    defined.
  1622. X *
  1623. X * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
  1624. X * than int in argument passing.  If this is definded, and LONGINT is not,
  1625. X * the compiler must support the type unsingned long.
  1626. X *
  1627. X * Most quirks and bugs of the available sprintf fuction are duplicated,
  1628. X * however * in the width and precision fields will work correctly
  1629. X * even if sprintf does not support this, as will the n format.
  1630. X *
  1631. X * Bad format strings, or those with very long width and precision
  1632. X * fields (including expanded * fields) will cause undesired results.
  1633. X */
  1634. X
  1635. X   /* Parseargs only needs this stuff for BSD Unix  -- Brad Appleton */
  1636. X#include <useful.h>
  1637. X
  1638. X#ifdef BSD
  1639. X#include <stdio.h>
  1640. X#include <ctype.h>
  1641. X
  1642. X#ifdef OSK        /* os9/68k can take advantage of both */
  1643. X# define LONGINT
  1644. X# define INTSPRINTF
  1645. X#endif
  1646. X
  1647. X/* This must be a typedef not a #define! */
  1648. X#ifdef NOVOID
  1649. X  typedef char *pointer;
  1650. X#else
  1651. X  typedef void *pointer;
  1652. X#endif
  1653. X
  1654. X#ifdef    INTSPRINTF
  1655. X# define Sprintf(string,format,arg)    (sprintf((string),(format),(arg)))
  1656. X#else
  1657. X# define Sprintf(string,format,arg)    (\
  1658. X   sprintf((string),(format),(arg)),\
  1659. X   strlen(string)\
  1660. X)
  1661. X#endif
  1662. X
  1663. Xtypedef int *intp;
  1664. X
  1665. X#ifdef __ANSI_C__
  1666. X  int vsprintf(char *dest, register const char *format, va_list args)
  1667. X#else
  1668. X  int vsprintf(dest, format, args)
  1669. X  char *dest;
  1670. X  register char *format;
  1671. X  va_list args;
  1672. X#endif
  1673. X{
  1674. X      register char *dp = dest;
  1675. X      register char c;
  1676. X      register char *tp;
  1677. X      char tempfmt[64];
  1678. X#ifndef LONGINT
  1679. X      int longflag;
  1680. X#endif
  1681. X
  1682. X      tempfmt[0] = '%';
  1683. X      while( (c = *format++) != 0) {
  1684. X   if(c=='%') {
  1685. X       tp = &tempfmt[1];
  1686. X#ifndef LONGINT
  1687. X       longflag = 0;
  1688. X#endif
  1689. Xcontinue_format:
  1690. X       switch(c = *format++) {
  1691. X      case 's':
  1692. X          *tp++ = c;
  1693. X          *tp = '\0';
  1694. X          dp += Sprintf(dp, tempfmt, VA_ARG(args, char *));
  1695. X          break;
  1696. X      case 'u':
  1697. X      case 'x':
  1698. X      case 'o':
  1699. X      case 'X':
  1700. X#ifdef UNSIGNEDSPECIAL
  1701. X          *tp++ = c;
  1702. X          *tp = '\0';
  1703. X#ifndef LONGINT
  1704. X          if(longflag)
  1705. X         dp += Sprintf(dp, tempfmt, VA_ARG(args, unsigned long));
  1706. X          else
  1707. X#endif
  1708. X         dp += Sprintf(dp, tempfmt, VA_ARG(args, unsigned));
  1709. X          break;
  1710. X#endif
  1711. X      case 'd':
  1712. X      case 'c':
  1713. X      case 'i':
  1714. X          *tp++ = c;
  1715. X          *tp = '\0';
  1716. X#ifndef LONGINT
  1717. X          if(longflag)
  1718. X         dp += Sprintf(dp, tempfmt, VA_ARG(args, long));
  1719. X          else
  1720. X#endif
  1721. X         dp += Sprintf(dp, tempfmt, VA_ARG(args, int));
  1722. X          break;
  1723. X      case 'f':
  1724. X      case 'e':
  1725. X      case 'E':
  1726. X      case 'g':
  1727. X      case 'G':
  1728. X          *tp++ = c;
  1729. X          *tp = '\0';
  1730. X          dp += Sprintf(dp, tempfmt, VA_ARG(args, double));
  1731. X          break;
  1732. X      case 'p':
  1733. X          *tp++ = c;
  1734. X          *tp = '\0';
  1735. X          dp += Sprintf(dp, tempfmt, VA_ARG(args, pointer));
  1736. X          break;
  1737. X      case '-':
  1738. X      case '+':
  1739. X      case '0':
  1740. X      case '1':
  1741. X      case '2':
  1742. X      case '3':
  1743. X      case '4':
  1744. X      case '5':
  1745. X      case '6':
  1746. X      case '7':
  1747. X      case '8':
  1748. X      case '9':
  1749. X      case '.':
  1750. X      case ' ':
  1751. X      case '#':
  1752. X      case 'h':
  1753. X          *tp++ = c;
  1754. X          goto continue_format;
  1755. X      case 'l':
  1756. X#ifndef LONGINT
  1757. X          longflag = 1;
  1758. X          *tp++ = c;
  1759. X#endif
  1760. X          goto continue_format;
  1761. X      case '*':
  1762. X          tp += Sprintf(tp, "%d", VA_ARG(args, int));
  1763. X          goto continue_format;
  1764. X      case 'n':
  1765. X          *VA_ARG(args, intp) = dp - dest;
  1766. X          break;
  1767. X      case '%':
  1768. X      default:
  1769. X          *dp++ = c;
  1770. X          break;
  1771. X       }
  1772. X   } else *dp++ = c;
  1773. X      }
  1774. X      *dp = '\0';
  1775. X      return dp - dest;
  1776. X}
  1777. X
  1778. X
  1779. X#ifdef __ANSI_C__
  1780. X  int vfprintf(FILE *dest, register const char *format, va_list args)
  1781. X#else
  1782. X  int vfprintf(dest, format, args)
  1783. X  FILE *dest;
  1784. X  register char *format;
  1785. X  va_list args;
  1786. X#endif
  1787. X{
  1788. X      register char c;
  1789. X      register char *tp;
  1790. X      register int count = 0;
  1791. X      char tempfmt[64];
  1792. X#ifndef LONGINT
  1793. X      int longflag;
  1794. X#endif
  1795. X
  1796. X      tempfmt[0] = '%';
  1797. X      while(c = *format++) {
  1798. X   if(c=='%') {
  1799. X       tp = &tempfmt[1];
  1800. X#ifndef LONGINT
  1801. X       longflag = 0;
  1802. X#endif
  1803. Xcontinue_format:
  1804. X       switch(c = *format++) {
  1805. X      case 's':
  1806. X          *tp++ = c;
  1807. X          *tp = '\0';
  1808. X          count += fprintf(dest, tempfmt, VA_ARG(args, char *));
  1809. X          break;
  1810. X      case 'u':
  1811. X      case 'x':
  1812. X      case 'o':
  1813. X      case 'X':
  1814. X#ifdef UNSIGNEDSPECIAL
  1815. X          *tp++ = c;
  1816. X          *tp = '\0';
  1817. X#ifndef LONGINT
  1818. X          if(longflag)
  1819. X         count += fprintf(dest, tempfmt, VA_ARG(args, unsigned long));
  1820. X          else
  1821. X#endif
  1822. X         count += fprintf(dest, tempfmt, VA_ARG(args, unsigned));
  1823. X          break;
  1824. X#endif
  1825. X      case 'd':
  1826. X      case 'c':
  1827. X      case 'i':
  1828. X          *tp++ = c;
  1829. X          *tp = '\0';
  1830. X#ifndef LONGINT
  1831. X          if(longflag)
  1832. X         count += fprintf(dest, tempfmt, VA_ARG(args, long));
  1833. X          else
  1834. X#endif
  1835. X         count += fprintf(dest, tempfmt, VA_ARG(args, int));
  1836. X          break;
  1837. X      case 'f':
  1838. X      case 'e':
  1839. X      case 'E':
  1840. X      case 'g':
  1841. X      case 'G':
  1842. X          *tp++ = c;
  1843. X          *tp = '\0';
  1844. X          count += fprintf(dest, tempfmt, VA_ARG(args, double));
  1845. X          break;
  1846. X      case 'p':
  1847. X          *tp++ = c;
  1848. X          *tp = '\0';
  1849. X          count += fprintf(dest, tempfmt, VA_ARG(args, pointer));
  1850. X          break;
  1851. X      case '-':
  1852. X      case '+':
  1853. X      case '0':
  1854. X      case '1':
  1855. X      case '2':
  1856. X      case '3':
  1857. X      case '4':
  1858. X      case '5':
  1859. X      case '6':
  1860. X      case '7':
  1861. X      case '8':
  1862. X      case '9':
  1863. X      case '.':
  1864. X      case ' ':
  1865. X      case '#':
  1866. X      case 'h':
  1867. X          *tp++ = c;
  1868. X          goto continue_format;
  1869. X      case 'l':
  1870. X#ifndef LONGINT
  1871. X          longflag = 1;
  1872. X          *tp++ = c;
  1873. X#endif
  1874. X          goto continue_format;
  1875. X      case '*':
  1876. X          tp += Sprintf(tp, "%d", VA_ARG(args, int));
  1877. X          goto continue_format;
  1878. X      case 'n':
  1879. X          *VA_ARG(args, intp) = count;
  1880. X          break;
  1881. X      case '%':
  1882. X      default:
  1883. X          putc(c, dest);
  1884. X          count++;
  1885. X          break;
  1886. X       }
  1887. X   } else {
  1888. X       putc(c, dest);
  1889. X       count++;
  1890. X   }
  1891. X      }
  1892. X      return count;
  1893. X}
  1894. X
  1895. X#ifdef __ANSI_C__
  1896. X  int vprintf(const char *format, va_list args)
  1897. X#else
  1898. X  int vprintf(format, args)
  1899. X  char *format;
  1900. X  va_list args;
  1901. X#endif
  1902. X{
  1903. X      return vfprintf(stdout, format, args);
  1904. X}
  1905. X#endif  /* BSD Unix ONLY */
  1906. X
  1907. X    /* use a VERY SIMPLE test case to test this out -- Brad Appleton */
  1908. X#ifdef VPRINTF_TEST
  1909. X
  1910. X/*VARARGS1*/
  1911. X#ifdef __ANSI_C__
  1912. X  int vtest( char *fmt, ... )
  1913. X#else
  1914. X  int vtest( fmt, va_alist )
  1915. X  char *fmt;
  1916. X  va_dcl
  1917. X#endif
  1918. X{
  1919. X   va_list   ap;
  1920. X   int   rc;
  1921. X
  1922. X   VA_START(ap, fmt);
  1923. X   rc = vprintf( fmt, ap );
  1924. X   VA_END(ap);
  1925. X
  1926. X   return   rc;
  1927. X}
  1928. X
  1929. Xvoid main()
  1930. X{
  1931. X   printf( "its a %s %% day in the %d neighborhood for %*s\n",
  1932. X          "pitiful", 4, 8, "fun" );
  1933. X
  1934. X   vtest( "its a %s %% day in the %d neighborhood for %*s\n",
  1935. X          "pitiful", 4, 8, "fun" );
  1936. X}
  1937. X
  1938. X#endif  /* VPRINTF_TEST */
  1939. END_OF_FILE
  1940. if test 8146 -ne `wc -c <'vprintf.c'`; then
  1941.     echo shar: \"'vprintf.c'\" unpacked with wrong size!
  1942. fi
  1943. # end of 'vprintf.c'
  1944. fi
  1945. if test -f 'winsize.c' -a "${1}" != "-c" ; then 
  1946.   echo shar: Will not clobber existing file \"'winsize.c'\"
  1947. else
  1948. echo shar: Extracting \"'winsize.c'\" \(7176 characters\)
  1949. sed "s/^X//" >'winsize.c' <<'END_OF_FILE'
  1950. X/*************************************************************************
  1951. X** ^FILE: winsize.c - implement the routine get_winsize()
  1952. X**
  1953. X** ^DESCRIPTION:
  1954. X**    Implement the get_winsize() function for various windowing and
  1955. X**    operating systems.
  1956. X**
  1957. X** ^HISTORY:
  1958. X**    10/01/90     Brad Appleton     <brad@ssd.csd.harris.com>     Created
  1959. X***^^**********************************************************************/
  1960. X
  1961. X
  1962. X/***************************************************************************
  1963. X** ^FUNCTION: get_winsize - get the current window size
  1964. X**
  1965. X** ^SYNOPSIS:
  1966. X**    void get_winsize( fd, nrows, ncols )
  1967. X**
  1968. X** ^PARAMETERS:
  1969. X**    int fd;
  1970. X**    -- file-descriptor associated with the "output-window"
  1971. X**
  1972. X**    int *nrows;
  1973. X**    -- pointer to number of rows in window
  1974. X**
  1975. X**    int *ncols;
  1976. X**    -- pointer to number of columns in window
  1977. X**
  1978. X** ^DESCRIPTION:
  1979. X**    Get_winsize will attempt to determine the maximum number of
  1980. X**    rows and colums that will fit on one screen-full of the associated
  1981. X**    output device. If it fails to do this, it will assume the "window"
  1982. X**    is a 24x80 (rows by columns) display.
  1983. X**
  1984. X** ^REQUIREMENTS:
  1985. X**    fd must correspond to a valid output device.
  1986. X**
  1987. X** ^SIDE-EFFECTS:
  1988. X**    The memory addressed by nrows and ncols is assigned the corresponding
  1989. X**    appropriate value(s).
  1990. X**
  1991. X** ^RETURN-VALUE:
  1992. X**    None.
  1993. X**
  1994. X** ^ALGORITHM:
  1995. X**     System dependent.
  1996. X***^^**********************************************************************/
  1997. X
  1998. X#include <stdio.h>
  1999. X
  2000. X#ifdef __ANSI_C__
  2001. X# define  GET_WINSIZE(fd,nrows,ncols)  \
  2002. X    void get_winsize( int fd, int *nrows, int *ncols )
  2003. X#else
  2004. X# define  GET_WINSIZE(fd,nrows,ncols)  \
  2005. X    void get_winsize( fd, nrows, ncols ) \
  2006. X    int fd, *nrows, *ncols;   /* nrows and ncols are passed by reference */
  2007. X#endif
  2008. X
  2009. X#define  DEFAULT_ROWS  24
  2010. X#define  DEFAULT_COLS  80
  2011. X
  2012. X#ifdef vms
  2013. X
  2014. X#include <stdio.h>
  2015. X#include <iodef.h>
  2016. X#include <ssdef.h>
  2017. X#include <descrip.h>
  2018. X#include <useful.h>
  2019. X
  2020. X   /* structure to contain terminal characteristics */
  2021. Xtypedef  struct {
  2022. X      short garb1, cols;
  2023. X      char   garb2, garb3, garb4, rows;
  2024. X} termchar_t;
  2025. X
  2026. Xint sys$assign();
  2027. Xint sys$qiow();
  2028. Xint sys$dassgn();
  2029. X
  2030. XGET_WINSIZE( fd, nrows, ncols )
  2031. X{
  2032. X   int c, charlen = 8;
  2033. X   termchar_t   termchar;
  2034. X   int chan;
  2035. X   $DESCRIPTOR( devnam,"SYS$COMMAND" );
  2036. X
  2037. X   sys$assign( &devnam, &chan, 0, 0 );
  2038. X   sys$qiow( 0, chan, IO$_SENSEMODE, 0, 0, 0, &termchar, &charlen, 0, 0, 0, 0 );
  2039. X   sys$dassgn( chan );
  2040. X
  2041. X   *nrows = ( termchar.rows > 0 ) ? (int) termchar.rows : DEFAULT_ROWS;
  2042. X   *ncols = ( termchar.cols > 0 ) ? (int) termchar.cols : DEFAULT_COLS;
  2043. X}
  2044. X
  2045. X#else
  2046. X#ifdef unix
  2047. X
  2048. X   /*
  2049. X   ** we will either try to access terminfo through the termcap-interface
  2050. X   ** in the curses library (which would require linking with -lcurses)
  2051. X   ** or use termcap directly (which would require linking with -ltermcap)
  2052. X   */
  2053. X#ifndef USE_TERMCAP
  2054. X#if ( defined(USE_TERMINFO) || defined(USE_CURSES) )
  2055. X#define USE_TERMCAP
  2056. X#endif
  2057. X#endif
  2058. X
  2059. X
  2060. X#ifdef USE_TERMCAP
  2061. X# define TERMBUFSIZ    1024
  2062. X# define UNKNOWN_TERM  "unknown"
  2063. X# define DUMB_TERMBUF  "dumb:co#80:hc:"
  2064. Xextern int  tgetent();
  2065. Xextern int  tgetnum();
  2066. X#endif
  2067. X
  2068. X
  2069. X   /* try to get TIOCGWINSZ from termios.h, then from sys/ioctl.h */
  2070. X#include <termios.h>
  2071. X#if ( !defined(TIOCGWINSZ)  &&  !defined(TIOCGSIZE)  &&  !defined(WIOCGETD) )
  2072. X#include <sys/ioctl.h>
  2073. X#endif
  2074. X
  2075. X   /* if still dont have TIOCGWINSZ (or TIOCGSIZE) try for WIOCGETD */
  2076. X#if ( !defined(TIOCGWINSZ)  &&  !defined(TIOCGSIZE)  &&  !defined(WIOCGETD) )
  2077. X#include <sgtty.h>
  2078. X#endif
  2079. X
  2080. X#include <useful.h>
  2081. X
  2082. X/*
  2083. X** get_winsize() -- determine # of rows/columns that will fit on the screen.
  2084. X**
  2085. X**     The environment variables $LINES and $COLUMNS will be used if they exist.
  2086. X**     If not, then the TIOCGWINSZ call to ioctl() is used (if it is defined).
  2087. X**     If not, then the TIOCGSIZE call to ioctl() is used (if it is defined).
  2088. X**     If not, then the WIOCGETD call to ioctl() is used (if it is defined).
  2089. X**     If not, then get the info from terminfo/termcap (if it is there)
  2090. X**     Otherwise, assume we have a 24x80 screen.
  2091. X*/
  2092. X
  2093. Xextern  int   ioctl();
  2094. Xextern  int   isatty();
  2095. Xextern  long  atol();
  2096. Xextern  char *getenv();
  2097. X
  2098. XGET_WINSIZE( fd, nrows, ncols )
  2099. X{
  2100. X   char  *lines_env, *cols_env;
  2101. X   long  lrow = 0, lcol = 0;
  2102. X   int   lines = 0, cols = 0;
  2103. X#ifdef USE_TERMCAP
  2104. X   char  term_buf[ TERMBUFSIZ ], *term_env;
  2105. X#endif
  2106. X#ifdef TIOCGWINSZ
  2107. X   struct winsize  win;
  2108. X#else
  2109. X#ifdef TIOCGSIZE
  2110. X   struct ttysize  win;
  2111. X#else
  2112. X#ifdef WIOCGETD
  2113. X   struct uwdata  win;
  2114. X#endif
  2115. X#endif
  2116. X#endif
  2117. X
  2118. X      /* make sure that fd corresponds to a terminal */
  2119. X   if ( !isatty( fd ) ) {
  2120. X      *nrows = DEFAULT_ROWS;
  2121. X      *ncols = DEFAULT_COLS;
  2122. X      return;
  2123. X   }
  2124. X
  2125. X      /* LINES & COLUMNS environment variables override everything else */
  2126. X   lines_env = getenv( "LINES" );
  2127. X   if ( lines_env  &&  (lrow = atol(lines_env)) > 0 ) {
  2128. X      *nrows = lines = (int) lrow;
  2129. X   }
  2130. X
  2131. X   cols_env = getenv( "COLUMNS" );
  2132. X   if ( cols_env  &&  (lcol = atol(cols_env)) > 0 ) {
  2133. X      *ncols = cols = (int) lcol;
  2134. X   }
  2135. X
  2136. X#ifdef TIOCGWINSZ
  2137. X      /* see what ioctl() has to say (overrides terminfo & termcap) */
  2138. X   if ( (!lines || !cols)  &&  ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
  2139. X      if ( !lines  &&  win.ws_row > 0 ) {
  2140. X         *nrows = lines = (int) win.ws_row;
  2141. X      }
  2142. X
  2143. X      if ( !cols  &&  win.ws_col > 0 ) {
  2144. X         *ncols = cols = (int) win.ws_col;
  2145. X      }
  2146. X   }/*if*/
  2147. X#else
  2148. X#ifdef TIOCGSIZE
  2149. X      /* see what ioctl() has to say (overrides terminfo & termcap) */
  2150. X   if ( (!lines || !cols)  &&  ioctl(fd, TIOCGSIZE, &win) != -1 ) {
  2151. X      if ( !lines  &&  win.ts_lines > 0 )
  2152. X         *nrows = lines = (int) win.ts_lines;
  2153. X
  2154. X      if ( !cols  &&  win.ts_cols > 0 )
  2155. X         *ncols = cols = (int) win.ts_cols;
  2156. X   }/*if*/
  2157. X#else
  2158. X#ifdef WIOCGETD
  2159. X      /* see what ioctl() has to say (overrides terminfo & termcap) */
  2160. X   if ( (!lines || !cols)  &&  ioctl(fd, WIOCGETD, &win) != -1 ) {
  2161. X      if ( !lines  &&  win.uw_height > 0 )
  2162. X         *nrows = lines = (int) (win.uw_height / win.uw_vs);
  2163. X
  2164. X      if ( !cols  &&  win.uw_width > 0 )
  2165. X         *ncols = cols = (int) (win.uw_width / win.uw_hs);
  2166. X   }/*if*/
  2167. X#endif
  2168. X#endif
  2169. X#endif
  2170. X
  2171. X#ifdef USE_TERMCAP
  2172. X      /* see what terminfo/termcap has to say */
  2173. X   if ( !lines || !cols ) {
  2174. X      if ( !(term_env = getenv("TERM")) )
  2175. X         term_env = UNKNOWN_TERM;
  2176. X
  2177. X      if ( (tgetent(term_buf, term_env) <= 0) )
  2178. X         strcpy( term_buf, DUMB_TERMBUF );
  2179. X
  2180. X          if ( !lines   &&   (lrow = tgetnum("li")) > 0 )
  2181. X            *nrows = lines = (int) lrow;
  2182. X
  2183. X          if ( !cols   &&   (lcol = tgetnum("co")) > 0 )
  2184. X            *ncols = cols = (int) lcol;
  2185. X   }
  2186. X#endif
  2187. X
  2188. X      /* use 80x24 if all else fails */
  2189. X   if ( !lines )  *nrows = DEFAULT_ROWS;
  2190. X   if ( !cols )   *ncols = DEFAULT_COLS;
  2191. X
  2192. X}/*get_winsize()*/
  2193. X
  2194. X#else
  2195. X
  2196. XGET_WINSIZE( fd, nrows, ncols )
  2197. X{
  2198. X      /* just use 80x24 */
  2199. X   *nrows = DEFAULT_ROWS;
  2200. X   *ncols = DEFAULT_COLS;
  2201. X}
  2202. X
  2203. X#endif  /* not a vms system */
  2204. X#endif  /* not a unix-system */
  2205. X
  2206. X#ifdef WINSIZE_TEST
  2207. X
  2208. X#ifdef vms
  2209. X# include <ssdef.h>
  2210. X#endif
  2211. X
  2212. X   /* test get_winsize to see if it works */
  2213. Xmain()
  2214. X{
  2215. X   int rows, cols;
  2216. X
  2217. X   get_winsize( fileno(stderr), &rows, &cols );
  2218. X   printf( "Output will be %d rows by %d columns\n", rows, cols );
  2219. X
  2220. X#ifdef vms
  2221. X   exit( SS$_NORMAL );
  2222. X#else
  2223. X   exit( 0 );
  2224. X#endif
  2225. X
  2226. X}
  2227. X
  2228. X#endif
  2229. END_OF_FILE
  2230. if test 7176 -ne `wc -c <'winsize.c'`; then
  2231.     echo shar: \"'winsize.c'\" unpacked with wrong size!
  2232. fi
  2233. # end of 'winsize.c'
  2234. fi
  2235. echo shar: End of archive 3 \(of 10\).
  2236. cp /dev/null ark3isdone
  2237. MISSING=""
  2238. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  2239.     if test ! -f ark${I}isdone ; then
  2240.     MISSING="${MISSING} ${I}"
  2241.     fi
  2242. done
  2243. if test "${MISSING}" = "" ; then
  2244.     echo You have unpacked all 10 archives.
  2245.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2246. else
  2247.     echo You still need to unpack the following archives:
  2248.     echo "        " ${MISSING}
  2249. fi
  2250. ##  End of shell archive.
  2251. exit 0
  2252.  
  2253. exit 0 # Just in case...
  2254.