home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / sources / misc / 3773 < prev    next >
Encoding:
Text File  |  1992-07-26  |  67.3 KB  |  2,229 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  4. Subject:  v31i049:  cmdline - C++ Library for parsing command-line arguments, Part02/07
  5. Message-ID: <1992Jul27.020449.29205@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: e9bf53b499e5f1510c09ca67ca0dae2c
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Reply-To: brad@travis.csd.harris.com
  10. Organization: Harris Computer Systems
  11. References: <csm-v31i047=cmdline.205609@sparky.IMD.Sterling.COM>
  12. Date: Mon, 27 Jul 1992 02:04:49 GMT
  13. Approved: kent@sparky.imd.sterling.com
  14. Lines: 2213
  15.  
  16. Submitted-by: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  17. Posting-number: Volume 31, Issue 49
  18. Archive-name: cmdline/part02
  19. Environment: C++
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then unpack
  23. # it by saving it into a file and typing "sh file".  To overwrite existing
  24. # files, type "sh file -c".  You can also feed this as standard input via
  25. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  26. # will see the following message at the end:
  27. #        "End of archive 2 (of 7)."
  28. # Contents:  Config.mk doc/cmdargs.man3 doc/cmdline.man3
  29. #   doc/parsing.man src/cmd/argtypes.c src/cmd/argtypes.h
  30. #   src/cmd/cmdparse.pl src/cmd/fsm.c src/cmd/quoted.c
  31. #   src/lib/argiter.c src/lib/fifolist.h src/lib/parse.c
  32. # Wrapped by brad@hcx1 on Mon Jul 20 10:41:27 1992
  33. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  34. if test -f 'Config.mk' -a "${1}" != "-c" ; then 
  35.   echo shar: Will not clobber existing file \"'Config.mk'\"
  36. else
  37. echo shar: Extracting \"'Config.mk'\" \(4632 characters\)
  38. sed "s/^X//" >'Config.mk' <<'END_OF_FILE'
  39. X##########################################################################
  40. X## ^FILE: Config.mk - configuration flags for the CmdLine product
  41. X##
  42. X## ^DESCRIPTION:
  43. X##    This file is included in each makefile in the directory hierarchy.
  44. X##    It defines the Make macros used throughout the product build process.
  45. X##    These values represent the global defaults. At any level you run make,
  46. X##    you may override any of these by specifying a new value on the command
  47. X##    line.
  48. X##
  49. X## ^HISTORY:
  50. X##    04/28/92    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  51. X###^^#####################################################################
  52. X
  53. X   ## Universe to compile in (use "att" for SYSV Unix and "ucb" for BSD Unix).
  54. X.UNIVERSE=att
  55. X
  56. X   ## Host operating system
  57. XOS=unix
  58. X
  59. X#------------------------------------------------------------------------------
  60. X# Define some OS dependent stuff for file extensions
  61. X#
  62. X   ## C++ file extension
  63. XCEXT=.c
  64. X
  65. X   ## object file extension
  66. XOBJEXT=.o
  67. X
  68. X   ## library file extension
  69. XLIBEXT=.a
  70. X
  71. X   ## executable file extension
  72. XEXECEXT=
  73. X
  74. X#------------------------------------------------------------------------------
  75. X# Define some OS dependent stuff for directory names
  76. X#
  77. X   ## current working directory
  78. XCURDIR=./
  79. X
  80. X   ## parent of current working directory
  81. XPARENTDIR=../
  82. X
  83. X#------------------------------------------------------------------------------
  84. X# Define some common commands
  85. X#
  86. X   ## remove files
  87. XRM=rm -f
  88. X
  89. X   ## remove directories
  90. XRMDIR=rm -rf
  91. X
  92. X   ## create directories
  93. XMKDIR=mkdir -p
  94. X
  95. X   ## change directories
  96. XCHDIR=cd
  97. X
  98. X   ## echo current directory
  99. XPWD=pwd
  100. X
  101. X   ## print to standard output
  102. XECHO=echo
  103. X
  104. X   ## copy files
  105. XCP=cp
  106. X
  107. X   ## move/rename files
  108. XMV=mv
  109. X
  110. X   ## print file on standard output
  111. XCAT=cat
  112. X
  113. X   ## maintain archives
  114. XAR=ar -r
  115. X
  116. X   ## maintain library archives
  117. XRANLIB=ranlib
  118. X
  119. X   ## remove symbol table info
  120. XSTRIP=strip
  121. X
  122. X   ## filter to remove non-ascii characters
  123. XCOL=col -xb
  124. X
  125. X   ## eliminate includes from a manpage
  126. XSOELIM=soelim
  127. X
  128. X   ## compress a manpage
  129. XMANTOCATMAN=mantocatman
  130. X
  131. X   ## print docs on printer
  132. XTROFF=roff -man
  133. X
  134. X   ## print docs to screen
  135. XNROFF=nroff -man
  136. X
  137. X   ## spell-checker
  138. XSPELL=spell
  139. X
  140. X#------------------------------------------------------------------------------
  141. X# Define some target directories (where things are installed)
  142. X#
  143. X#    NOTE: if you change BINDIR, INCDIR, or LIBDIR then dont forget to change
  144. X#          their corresponding strings at the end of doc/macros.man!
  145. X#
  146. X   ## common local directory
  147. XLOCAL=/usr/local/
  148. X
  149. X   ## where to install executables
  150. XBINDIR=$(LOCAL)bin/
  151. X
  152. X   ## where to install object libraries
  153. XLIBDIR=$(LOCAL)lib/
  154. X
  155. X   ## where to install object include files
  156. XINCDIR=$(LOCAL)include/
  157. X
  158. X   ## where to install perl libraries
  159. XPERLLIB=$(LIBDIR)perl/
  160. X
  161. X   ## where to install tcl libraries
  162. XTCLLIB=$(LIBDIR)tcl/
  163. X
  164. X   ## subdirectory where local man-pages are installed
  165. XLOCALMAN=local_man/
  166. X
  167. X   ## where to install man-pages
  168. XMANDIR=/usr/man/$(LOCALMAN)
  169. X
  170. X   ## where to install catman-pages (preformatted manual pages)
  171. XCATMANDIR=/usr/catman/$(LOCALMAN)
  172. X
  173. X   ## subdirectory of MANDIR and CATMANDIR for section 1 of man-pages
  174. XMAN1DIR=man1/
  175. X
  176. X   ## subdirectory of MANDIR and CATMANDIR for section 3 of man-pages
  177. XMAN3DIR=man3/
  178. X
  179. X#------------------------------------------------------------------------------
  180. X# Define some product specific stuff
  181. X#
  182. XPROGLIBDIR=$(PARENTDIR)lib/
  183. XPROGNAME=cmdparse
  184. XLIBNAME=cmdline
  185. X
  186. X#------------------------------------------------------------------------------
  187. X# Define C++ compilation stuff
  188. X#
  189. X   ## name of C++ compiler
  190. XCC=CC
  191. X
  192. X   ## option to specify other include directories to search
  193. XINC=-I
  194. X
  195. X   ## option to specify constants to #define
  196. XDEF=-D
  197. X
  198. X   ## option to produce optimized code
  199. XOPT=-O
  200. X
  201. X   ## option to produce debugging information
  202. XDBG=-g
  203. X
  204. X   ## option to indicate the name of the executable file
  205. XEXE=-o
  206. X
  207. X   ## option to suppress the loading phase
  208. XNOLD=-c
  209. X
  210. X#------------------------------------------------------------------------------
  211. X# Define rules for C++ files
  212. X#
  213. X.SUFFIXES : $(CEXT) $(OBJEXT)
  214. X
  215. X$(CEXT)$(OBJEXT):
  216. X    $(CC) $(CFLAGS) $(NOLD) $<
  217. X
  218. X#------------------------------------------------------------------------------
  219. X# Define some configurable compilation flags
  220. X#
  221. XFLAG=$(OPT)
  222. X# FLAG=$(DBG)
  223. XTESTDEFS=
  224. X# USRDEFS=$(DEF)DEBUG_CMDLINE
  225. XOPTIONS=
  226. X
  227. X#------------------------------------------------------------------------------
  228. X# Define the macro to pass to recursive makes
  229. X#
  230. XRECUR= FLAG=$(FLAG) \
  231. X   TESTDEFS=$(TESTDEFS) \
  232. X   USRDEFS=$(USRDEFS) \
  233. X   OPTIONS=$(OPTIONS)
  234. X
  235. X#------------------------------------------------------------------------------
  236. X# Define the command for recursive makes
  237. X#
  238. XBUILD=$(MAKE) -$(MAKEFLAGS) $(RECUR)
  239. X
  240. END_OF_FILE
  241. if test 4632 -ne `wc -c <'Config.mk'`; then
  242.     echo shar: \"'Config.mk'\" unpacked with wrong size!
  243. fi
  244. # end of 'Config.mk'
  245. fi
  246. if test -f 'doc/cmdargs.man3' -a "${1}" != "-c" ; then 
  247.   echo shar: Will not clobber existing file \"'doc/cmdargs.man3'\"
  248. else
  249. echo shar: Extracting \"'doc/cmdargs.man3'\" \(4505 characters\)
  250. sed "s/^X//" >'doc/cmdargs.man3' <<'END_OF_FILE'
  251. X.\"========== TO PRINT, USE: {n,t}roff -man file ==========
  252. X.if n .po 1
  253. X.if n .ll 78
  254. X.ds NM \f4CmdLine\fP
  255. X.so macros.man
  256. X.\"===================================
  257. X.TH cmdargs 3\*(C+
  258. X.\"===================================
  259. X.SH NAME
  260. Xcmdargs \- predefined command argument types for \*(NM(3\*(C+)
  261. X.\"===================================
  262. X.SH SYNOPSIS
  263. X.nf
  264. X.ft 4
  265. X#include <cmdargs.h>
  266. X
  267. Xclass  CmdArgDummy : public CmdArg ;
  268. Xclass  CmdArgUsage : public CmdArg ;
  269. X
  270. Xclass  CmdArgIntCompiler : public CmdArg ;
  271. Xclass  CmdArgInt     : public CmdArgIntCompiler ;
  272. Xclass  CmdArgIntList : public CmdArgIntCompiler ;
  273. X
  274. Xclass  CmdArgFloatCompiler : public CmdArg ;
  275. Xclass  CmdArgFloat     : public CmdArgFloatCompiler ;
  276. Xclass  CmdArgFloatList : public CmdArgFloatCompiler ;
  277. X
  278. Xclass  CmdArgCharCompiler : public CmdArg ;
  279. Xclass  CmdArgChar : public CmdArgCharCompiler ;
  280. X
  281. Xclass  CmdArgStrCompiler : public CmdArg ;
  282. Xclass  CmdArgStr     : public CmdArgStrCompiler ;
  283. Xclass  CmdArgStrList : public CmdArgStrCompiler ;
  284. X
  285. Xclass  CmdArgBoolCompiler : public CmdArg ;
  286. Xclass  CmdArgBool : public CmdArgBoolCompiler ;
  287. Xclass  CmdArgClear  : public CmdArgBool ;
  288. Xclass  CmdArgToggle : public CmdArgBool ;
  289. X
  290. Xclass  CmdArgBoolRef   : public CmdArg ;
  291. Xclass  CmdArgClearRef  : public CmdArg ;
  292. Xclass  CmdArgToggleRef : public CmdArg ;
  293. X
  294. X.ft R
  295. X.fi
  296. X.\"===================================
  297. X.SH DESCRIPTION
  298. X.PP
  299. X\f4cmdargs\fP(3\*(C+) is the portion of the \*(NM(3\*(C+) library
  300. Xthat contains the predefined argument types to use in conjunction
  301. Xwith one or more \*(NM objects.
  302. XThe include file \f4<cmdargs.h>\fP defines classes derived from class
  303. X\f4CmdArg\fP (which is defined in \f4<cmdline.h>\fP) for the most
  304. Xcommonly used types of command-line arguments.  Most command-line
  305. Xarguments are either boolean-flags, a number, a character, or a string
  306. X(or a list of numbers or strings).  In each of these cases, the call
  307. Xoperator (\f4operator()\fP) of the argument just compiles the value
  308. Xgiven into some internal value and waits for the programmer to query
  309. Xthe value at some later time.
  310. X
  311. XThese types of arguments are referred to as "\fIArgCompilers\fP".
  312. XFor each of the most common argument types, a corresponding abstract
  313. XArgCompiler class is declared.  All that this class does is to add a member
  314. Xfunction named "\f4compile\fP" to the class.  The \f4compile()\fP function
  315. Xlooks exactly like the call operator but it takes an additional
  316. Xparameter: a reference to the value to be modified by compiling
  317. Xthe argument value.  In all other respects, the \f4compile()\fP member
  318. Xfunction behaves exactly like the call operator.  In fact, most
  319. Xof the call operator member functions simply call the ArgCompiler's
  320. X\f4compile()\fP member function with the appropriate value and return
  321. Xwhatever the compile function returned.
  322. X
  323. XOnce all of these ArgCompilers are declared, it is a simple matter
  324. Xto declare a class that holds a single item, or a list of items,
  325. Xby deriving it from the corresponding ArgCompiler type.
  326. X
  327. XFor derived classes of these ArgCompilers that hold a single item,
  328. XThe derived class implements some operators (such as \f4operator=\fP
  329. Xand an appropriate cast operator) to treat the argument as if it
  330. Xwere simply an item (instead of an argument that contains an item).
  331. XThe output operator (\f4ostream & operator<<\fP) is also defined.
  332. X
  333. XFor derived classes of ArgCompilers that hold a list of items,
  334. Xthe subscript operator (\f4operator[]\fP) is defined in order to
  335. Xtreat the argument as if it were simply an array of items and not
  336. Xan argument that contains a list of items.
  337. X
  338. X.IP "\fBNote:\fP" 3
  339. XIt is important to remember that each subclass of \f4CmdArg\fP \s-1MUST\s+1
  340. Xbe able to handle \f4NULL\fP as the first argument to the call-operator
  341. X(and it should \s-1NOT\s+1 be considered an error).  This is because
  342. X\f4NULL\fP will be passed if the argument takes no value, or if it takes
  343. Xan optional value that was \s-1NOT\s+1 provided on the command-line.
  344. XWhenever an argument is correctly specified on the command-line, its call
  345. Xoperator is always invoked (regardless of whether or not there
  346. Xis a corresponding value from the command-line).
  347. X
  348. X.\"===================================
  349. X.so example.man
  350. X.\"===================================
  351. X.so classes.man
  352. X.\"===================================
  353. X.so files.man
  354. X.\"===================================
  355. X.SH SEE ALSO
  356. X\f4CmdLine\fP(3\*(C+), \f4cmdparse\fP(1)
  357. X.br
  358. X\f4<cmdline.h>\fP, \f4<cmdargs.h>\fP
  359. X.\"===================================
  360. X.SH AUTHOR
  361. XBrad Appleton, Harris Computer Systems, <\f4brad@ssd.csd.harris.com\fP>.
  362. END_OF_FILE
  363. if test 4505 -ne `wc -c <'doc/cmdargs.man3'`; then
  364.     echo shar: \"'doc/cmdargs.man3'\" unpacked with wrong size!
  365. fi
  366. # end of 'doc/cmdargs.man3'
  367. fi
  368. if test -f 'doc/cmdline.man3' -a "${1}" != "-c" ; then 
  369.   echo shar: Will not clobber existing file \"'doc/cmdline.man3'\"
  370. else
  371. echo shar: Extracting \"'doc/cmdline.man3'\" \(4365 characters\)
  372. sed "s/^X//" >'doc/cmdline.man3' <<'END_OF_FILE'
  373. X.\"========== TO PRINT, USE: {n,t}roff -man file ==========
  374. X.if n .po 1
  375. X.if n .ll 78
  376. X.ds NM \f4CmdLine\fP
  377. X.so macros.man
  378. X.\"===================================
  379. X.TH CmdLine 3\*(C+
  380. X.\"===================================
  381. X.SH NAME
  382. XCmdLine \- A \*(C+ class library for parsing command-line arguments
  383. X.\"===================================
  384. X.SH SYNOPSIS
  385. X.ft 4
  386. X.nf
  387. X#include <cmdline.h>
  388. X
  389. Xclass  CmdArg ;  // An abstract command-argument
  390. X
  391. Xclass  CmdLineArgIter ;  // abstract iterator for command-line-arguments
  392. Xclass  CmdArgvIter    : public CmdLineArgIter ;
  393. Xclass  CmdStrTokIter  : public CmdLineArgIter ;
  394. Xclass  CmdIstreamIter : public CmdLineArgIter ;
  395. X
  396. Xclass  CmdLine ;  // A command-line object
  397. Xclass  CmdLineCmdArgIter ;  // iterator for a CmdLine's CmdArgs
  398. X
  399. X.fi
  400. X.ft R
  401. X.\"===================================
  402. X.SH DESCRIPTION
  403. X.PP
  404. X\*(NM is a set of classes to parse command-line arguments.  Unlike
  405. X\f4getopt(3C)\fP and its variants, \*(NM does more than just split up the
  406. Xcommand-line into some canonical form.  \*(NM will actually parse
  407. Xthe command-line, assigning the appropriate command-line values to
  408. Xthe corresponding variables, and will verify the command-line syntax
  409. X(and print a usage message if necessary) all in one member function
  410. Xcall.  Furthermore, many features of \*(NM's parsing behavior are
  411. Xconfigurable at run-time.  These features include the following:
  412. X
  413. X.RS
  414. X.IP "\(bu" 3
  415. XPrompting the user for missing arguments.
  416. X.IP "\(bu" 3
  417. XAllowing keywords (\fB\-count\fP=4) and/or options (\fB\-c\fP4).
  418. X.IP "\(bu" 3
  419. XIgnoring bad syntax instead of terminating.
  420. X.IP "\(bu" 3
  421. XIgnoring upper/lower case on the command-line.
  422. X.IP "\(bu" 3
  423. XSuppressing the printing of syntax error messages.
  424. X.IP "\(bu" 3
  425. XControlling the verboseness of usage messages.
  426. X.IP "\(bu" 3
  427. XControlling whether or not options may be processed
  428. Xafter positional parameters have been seen.
  429. X.RE
  430. X
  431. X.PP
  432. X\*(NM also allows for options that take an optional argument, options
  433. Xthat take a (possibly optional) list of one or more arguments, options
  434. Xwhose argument must reside in the same token as the option itself, and
  435. Xoptions whose argument must reside in a separate token from the option
  436. Xitself.
  437. X
  438. X.PP
  439. X\*(NM consists of a set of \*(C+ classes to parse arguments from an
  440. Xinput source called a \f4CmdLineArgIter\fP (which is a base class for
  441. Xiterating over arguments from an arbitrary input source).  Argument
  442. Xiterators are defined for an \f4argv[]\fP array (with or without a
  443. Xcorresponding \f4argc\fP), for a string of tokens that are separated
  444. Xby a given set of delimiters, and for an input-stream.  Users can easily
  445. Xextend \*(NM to parse arguments from other input sources simply by creating
  446. Xtheir own argument iterator classes derived from the \f4CmdLineArgIter\fP
  447. Xclass defined in \f4<cmdline.h>\fP.
  448. X
  449. XCommand-line arguments are themselves objects that contain a specific
  450. Xcommand-line interface, and a function that performs the desired actions
  451. Xwhen its corresponding argument is seen on the command line.  Predefined
  452. Xcommand-line argument types (derived from the abstract class \f4CmdArg\fP
  453. Xin \f4<cmdline.h>\fP) exist for boolean, integer, floating-point, character,
  454. Xand string arguments, and for lists of integers, floats, and strings.  These
  455. Xpredefined subclasses of \f4CmdArg\fP may be found in \f4<cmdargs.h>\fP.
  456. XUsers can also create their own command-argument types on the fly by defining
  457. Xand implementing an appropriate subclass of the \f4CmdArg\fP class.
  458. X
  459. X.IP "\fBNote:\fP" 3
  460. XThe \*(NM library does not check for any freestore allocation errors.
  461. XIt is assumed that any desired freestore allocation checking will be
  462. Xperformed by the user by including the file \f4<new.h>\fP and using
  463. Xthe \f4set_new_handler\fP function to set up a freestore exception
  464. Xhandler.
  465. X.\"===================================
  466. X.so example.man
  467. X.\"===================================
  468. X.so parsing.man
  469. X.\"===================================
  470. X.so environ.man
  471. X.\"===================================
  472. X.so classes.man
  473. X.\"===================================
  474. X.so files.man
  475. X.\"===================================
  476. X.SH SEE ALSO
  477. X\f4cmdargs\fP(3\*(C+), \f4cmdparse\fP(1)
  478. X.br
  479. X\f4<cmdline.h>\fP, \f4<cmdargs.h>\fP
  480. X.\"===================================
  481. X.so caveats.man
  482. X.\"===================================
  483. X.so bugs.man
  484. X.\"===================================
  485. X.SH AUTHOR
  486. XBrad Appleton, Harris Computer Systems, <\f4brad@ssd.csd.harris.com\fP>.
  487. END_OF_FILE
  488. if test 4365 -ne `wc -c <'doc/cmdline.man3'`; then
  489.     echo shar: \"'doc/cmdline.man3'\" unpacked with wrong size!
  490. fi
  491. # end of 'doc/cmdline.man3'
  492. fi
  493. if test -f 'doc/parsing.man' -a "${1}" != "-c" ; then 
  494.   echo shar: Will not clobber existing file \"'doc/parsing.man'\"
  495. else
  496. echo shar: Extracting \"'doc/parsing.man'\" \(4557 characters\)
  497. sed "s/^X//" >'doc/parsing.man' <<'END_OF_FILE'
  498. X.SH PARSING
  499. XAlthough, much of the parsing behavior of \*(NM can be configured at run-time
  500. Xthere are some \fIcommon rules\fP that are used when parsing command-line
  501. Xarguments.  Many of these so called \fIrules\fP are just a formalization
  502. Xof things that have become an informal standard over the years.
  503. X
  504. X.SS "LONG AND SHORT OPTIONS"
  505. X.RS
  506. XBy default, \*(NM will allow both single-character options \fIand\fP
  507. Xkeywords (long-options) to be matched on the command-line.
  508. XUnder Unix, a single character option is prefixed by the string ``\-''.
  509. Xand a long-option is prefixed by the string ``\*(--''.  If a token
  510. Xon the command-line exactly matches the string ``\*(--'', then all
  511. Xfurther matching of options (both long and short) are disabled and
  512. Xany remaining arguments are considered to be positional parameters
  513. X(even if they look like options).
  514. X
  515. XIf short-option processing is disabled, then the prefix ``\-'' may be used
  516. Xto indicate a long-option (the ``\*(--'' prefix will still be accepted).
  517. X
  518. XIf desired, the string ``+'' may be used as the long-option prefix
  519. Xinstead of ``\*(--'' by defining the constant \s-1USE_PLUS\s+1 when
  520. Xbuilding \f4CmdLine\fP.
  521. X.RE
  522. X
  523. X.SS "OPTION MATCHING"
  524. X.RS
  525. XBy default, short-option matching is case-sensitive (but case-insensitive
  526. Xmatching may be used if desired). Long-options are always matched 
  527. Xcase-insensitive and only a unique prefix of the long-option name needs
  528. Xto be given in order for it to be matched successfully.
  529. X.RE
  530. X
  531. X.SS "SPECIFYING VALUES TO OPTIONS"
  532. X.RS
  533. XBy default, \*(NM will allow the value for an option to be in the
  534. Xsame command-line token as the option itself, or in a separate
  535. Xcommand-line token.  For short-options, specifying the value in
  536. Xthe same token simply means immediately following the option
  537. Xcharacter with the intended value as in "\fB\-c\fIvalue\fR".
  538. XFor long-options, specifying the value in the same token requires
  539. Xthat the value be separated from the keyword name by an equal-sign
  540. X(`=') or by a colon (`:') as in ``\fB\*(--keyword\fP=\fIvalue\fP''
  541. Xor ``\fB\*(--keyword\fP:\fIvalue\fP''.
  542. X
  543. XWhen specifying values to short-options in the same token as the option
  544. Xitself, the "portion" of the value that is consumed depends upon
  545. Xthe option type. For options that represent a character value, only
  546. Xthe character immediately following the option-character is consumed
  547. Xand the remaining characters in the token may match other options.
  548. XFor options that represent a numeric value, only the portion of the
  549. Xtoken that "looks" like a number will be consumed and the remaining
  550. Xcharacters in the token may match other options. For options that
  551. Xrepresent a string value, all remaining characters in the token
  552. Xare consumed. What this means is that if I have an integer option
  553. X\fB\-i\fP, a character option \fB\-c\fP and a string option \fB\-s\fP,
  554. Xthen they may all be specified on the command-line using the single token
  555. X``\fB\-i\fI100\fBc\fIc\fBs\fIstring\fR''.
  556. X
  557. XIt should be noted that integer valued options may be specified on the
  558. Xcommand-line in decimal, hexadecimal, or octal notation.
  559. XHexadecimal notation is assumed if the first two characters of the
  560. Xinteger are ``\f40x\fP'' or ``\f40X\fP'';
  561. Xoctal notation is assumed if the first digit of the integer is `0';
  562. Xdecimal notation is assumed for all other cases.
  563. X.RE
  564. X
  565. X.SS "VALUES FOR BOOLEAN OPTIONS"
  566. X.RS
  567. X\*(NM allows boolean options to take optional values. If a boolean option
  568. Xappears by itself without a value then the default action (which is
  569. Xusually to turn itself \fIon\fP) is used.  One may also explicitly specify
  570. Xthe boolean value to use by supplying a value \fIin the same token as the
  571. Xoption\fP.
  572. X
  573. XFor short options, a single character is used as the boolean value.
  574. XOther short-option characters may immediately follow the boolean
  575. Xvalue (in the same token as the boolean option) because only one
  576. Xcharacter is consumed for the boolean value. 
  577. XThe following strings may be used to indicate a value to a boolean option
  578. X(those strings that contain more than 1 character may only be used in
  579. Xconjunction with long-options):
  580. X.RS
  581. X.TP
  582. X"\f40\fP", "\f4\-\fP", "\f4OFF\fP", "\f4NO\fP", "\f4FALSE\fP"
  583. XEach of these indicates that the option should be turned \fIoff\fP.
  584. X
  585. X.TP
  586. X"\f41\fP", "\f4+\fP", "\f4ON\fP", "\f4YES\fP", "\f4TRUE\fP"
  587. XEach of these indicates that the option should be turned \fIon\fP.
  588. X
  589. X.TP
  590. X"\f4^\fP", "\f4~\fP", "\f4!\fP"
  591. XEach of these indicates that the option should be \fItoggled\fP.
  592. XIn the case of a long-option, any of the above characters may also be followed
  593. Xby the keyword-name of the option (as in ``\fB\*(--mode\f4=!mode\fR'').
  594. X.RE
  595. X
  596. X.RE
  597. END_OF_FILE
  598. if test 4557 -ne `wc -c <'doc/parsing.man'`; then
  599.     echo shar: \"'doc/parsing.man'\" unpacked with wrong size!
  600. fi
  601. # end of 'doc/parsing.man'
  602. fi
  603. if test -f 'src/cmd/argtypes.c' -a "${1}" != "-c" ; then 
  604.   echo shar: Will not clobber existing file \"'src/cmd/argtypes.c'\"
  605. else
  606. echo shar: Extracting \"'src/cmd/argtypes.c'\" \(5191 characters\)
  607. sed "s/^X//" >'src/cmd/argtypes.c' <<'END_OF_FILE'
  608. X#include <stdlib.h>
  609. X#include <iostream.h>
  610. X#include <string.h>
  611. X#include <ctype.h>
  612. X
  613. X#include "argtypes.h"
  614. X
  615. X
  616. X//-----------------------------------------------------------------------------
  617. X// ^FUNCTION: operator() - handle an argument from the command-line
  618. X//
  619. X// ^SYNOPSIS:
  620. X//    int  operator()(arg, cmd);
  621. X//
  622. X// ^PARAMETERS:
  623. X//    const char * & arg;
  624. X//    -- the prospective value for this command argument.
  625. X//       upon returning this value should be updated to point to the first
  626. X//       character of "arg" that was NOT used as part of the value for this
  627. X//       argument (set "arg" to NULL if all of it was used).
  628. X//
  629. X//    CmdLine & cmd;
  630. X//    -- the command that matched this argument on its command-line
  631. X//
  632. X// ^DESCRIPTION:
  633. X//    These member functions are responsible for taking whatever action
  634. X//    is appropriate when its corresponding command argument is matched
  635. X//    on the command-line.
  636. X//
  637. X//    All the argument-types in this file correspond to argument of some
  638. X//    kind of shell script, hence all of the command-argument objects are
  639. X//    not just derived from CmdArg but from ShellCmdArg as well.  All we
  640. X//    need to do is check the syntax of the argument (without compiling it)
  641. X//    and if it is valid then use the argument as the value for the 
  642. X//    corresponding shell variable.
  643. X//
  644. X// ^REQUIREMENTS:
  645. X//    The "arg_flags" data member of this command-argument must have been
  646. X//    set appropriately (by "cmd") to indicate to us exactly how "arg" was
  647. X//    specified on the command-line for this (and only this) occurrence of
  648. X//    "arg".
  649. X//
  650. X// ^SIDE-EFFECTS:
  651. X//    - If (cmd.flags() & QUIET) is NOT TRUE and FAILURE is to be returned,
  652. X//      then error messages should be printed using cmd.error().
  653. X//
  654. X//    - arg is modified to be NULL of to point to the unused portion of itself.
  655. X//      
  656. X//    - If (cmd.flags() & TEMP) is TRUE and we need the value of "arg"
  657. X//      to stick around, then storage is allocated in order to make
  658. X//      a copy of "arg" (and the command-argument is responsible for
  659. X//      de-allocating this storage).
  660. X//
  661. X// ^RETURN-VALUE:
  662. X//    FAILURE (non-zero)  If something went wrong when performing the
  663. X//                        desired actions for this command-argument.
  664. X//                        A common problem would be that "arg" is
  665. X//                        syntactically incorrect.
  666. X//
  667. X//    SUCCESS (zero)  If "arg" is NULL and/or we were able to succesfully
  668. X//                    perform all desired actions for this command argument.
  669. X//-^^--------------------------------------------------------------------------
  670. X
  671. X
  672. X//-------------------------------------------------------------- ShellCmdArgInt
  673. X
  674. XShellCmdArgInt::~ShellCmdArgInt(void)
  675. X{
  676. X}
  677. X
  678. Xint
  679. XShellCmdArgInt::operator()(const char * & arg, CmdLine & cmd)
  680. X{
  681. X   CmdArgInt  int_arg(*this);
  682. X   const char * save_arg = arg;
  683. X   int  badval = int_arg(arg, cmd);
  684. X   if (save_arg && !badval)  set(save_arg);
  685. X   return  badval;
  686. X}
  687. X
  688. X//------------------------------------------------------------ ShellCmdArgFloat
  689. X
  690. XShellCmdArgFloat::~ShellCmdArgFloat(void)
  691. X{
  692. X}
  693. X
  694. Xint
  695. XShellCmdArgFloat::operator()(const char * & arg, CmdLine & cmd)
  696. X{
  697. X   CmdArgFloat  float_arg(*this);
  698. X   const char * save_arg = arg;
  699. X   int  badval = float_arg(arg, cmd);
  700. X   if (save_arg && !badval)  set(save_arg);
  701. X   return  badval;
  702. X}
  703. X
  704. X//------------------------------------------------------------- ShellCmdArgChar
  705. X
  706. XShellCmdArgChar::~ShellCmdArgChar(void)
  707. X{
  708. X}
  709. X
  710. Xint
  711. XShellCmdArgChar::operator()(const char * & arg, CmdLine & cmd)
  712. X{
  713. X   CmdArgChar  char_arg(*this);
  714. X   const char * save_arg = arg;
  715. X   int  badval = char_arg(arg, cmd);
  716. X   if (save_arg && !badval)  set(save_arg);
  717. X   return  badval;
  718. X}
  719. X
  720. X//-------------------------------------------------------------- ShellCmdArgStr
  721. X
  722. XShellCmdArgStr::~ShellCmdArgStr(void)
  723. X{
  724. X}
  725. X
  726. Xint
  727. XShellCmdArgStr::operator()(const char * & arg, CmdLine & cmd)
  728. X{
  729. X   CmdArgStr  str_arg(*this);
  730. X   const char * save_arg = arg;
  731. X   int  badval = str_arg(arg, cmd);
  732. X   if (save_arg && !badval)  set(save_arg);
  733. X   return  badval;
  734. X}
  735. X
  736. X//------------------------------------------------------------- ShellCmdArgBool
  737. X
  738. Xconst char * ShellCmdArgBool::true_string  = "TRUE" ;
  739. Xconst char * ShellCmdArgBool::false_string = "" ;
  740. X
  741. XShellCmdArgBool::~ShellCmdArgBool(void)
  742. X{
  743. X}
  744. X
  745. Xint
  746. XShellCmdArgBool::operator()(const char * & arg, CmdLine & cmd)
  747. X{
  748. X   CmdArgBool  bool_arg(*this);
  749. X   int  badval = bool_arg(arg, cmd);
  750. X   if (! badval) {
  751. X      set((bool_arg) ? True() : False());
  752. X   }
  753. X   return  badval;
  754. X}
  755. X
  756. X//------------------------------------------------------------ ShellCmdArgClear
  757. X
  758. XShellCmdArgClear::~ShellCmdArgClear(void)
  759. X{
  760. X}
  761. X
  762. Xint
  763. XShellCmdArgClear::operator()(const char * & arg, CmdLine & cmd)
  764. X{
  765. X   CmdArgClear  bool_arg(*this);
  766. X   int  badval = bool_arg(arg, cmd);
  767. X   if (! badval) {
  768. X      set((bool_arg) ? True() : False());
  769. X   }
  770. X   return  badval;
  771. X}
  772. X
  773. X//----------------------------------------------------------- ShellCmdArgToggle
  774. X
  775. XShellCmdArgToggle::~ShellCmdArgToggle(void)
  776. X{
  777. X}
  778. X
  779. Xint
  780. XShellCmdArgToggle::operator()(const char * & arg, CmdLine & cmd)
  781. X{
  782. X   CmdArgToggle  bool_arg(*this);
  783. X   int  badval = bool_arg(arg, cmd);
  784. X   if (! badval) {
  785. X      set((bool_arg) ? True() : False());
  786. X   }
  787. X   return  badval;
  788. X}
  789. X
  790. END_OF_FILE
  791. if test 5191 -ne `wc -c <'src/cmd/argtypes.c'`; then
  792.     echo shar: \"'src/cmd/argtypes.c'\" unpacked with wrong size!
  793. fi
  794. # end of 'src/cmd/argtypes.c'
  795. fi
  796. if test -f 'src/cmd/argtypes.h' -a "${1}" != "-c" ; then 
  797.   echo shar: Will not clobber existing file \"'src/cmd/argtypes.h'\"
  798. else
  799. echo shar: Extracting \"'src/cmd/argtypes.h'\" \(6706 characters\)
  800. sed "s/^X//" >'src/cmd/argtypes.h' <<'END_OF_FILE'
  801. X//------------------------------------------------------------------------
  802. X// ^FILE: argtypes.h - argument types for use by shell-scripts
  803. X//
  804. X// ^DESCRIPTION:
  805. X//   This file defines the specific types of shell-script command-line
  806. X//   arguments.  All such argument types are derived from the class
  807. X//   ShellCmdArg.
  808. X//
  809. X// ^HISTORY:
  810. X//    04/26/92    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  811. X//-^^---------------------------------------------------------------------
  812. X
  813. X#ifndef _argtypes_h
  814. X#define _argtypes_h
  815. X
  816. X#include "shell_arg.h"
  817. X
  818. X//-------------------------------------------------------------- ShellCmdArgInt
  819. X
  820. X   // A ShellCmdArgInt is a CmdArg object that maintains an integer
  821. X   // valued shell-variable.
  822. X
  823. Xclass ShellCmdArgInt : public ShellCmdArg {
  824. Xpublic:
  825. X   ShellCmdArgInt(char *       name,
  826. X                  char         optchar,
  827. X                  char *       keyword,
  828. X                  char *       value,
  829. X                  char *       description,
  830. X                  unsigned     syntax_flags =CmdArg::isOPTVALREQ)
  831. X      : ShellCmdArg(name, optchar, keyword, value, description, syntax_flags)
  832. X      {}
  833. X
  834. X   ShellCmdArgInt(char *       name,
  835. X                  char *       value,
  836. X                  char *       description,
  837. X                  unsigned     syntax_flags =CmdArg::isPOSVALREQ)
  838. X      : ShellCmdArg(name, value, description, syntax_flags)
  839. X      {}
  840. X
  841. X   virtual ~ShellCmdArgInt(void);
  842. X
  843. X   virtual  int
  844. X   operator()(const char * & arg, CmdLine & cmd);
  845. X} ;
  846. X
  847. X//------------------------------------------------------------ ShellCmdArgFloat
  848. X
  849. X   // A ShellCmdArgFloat is a CmdArg object that maintains a floating-point
  850. X   // valued shell-variable.
  851. X
  852. Xclass ShellCmdArgFloat : public ShellCmdArg {
  853. Xpublic:
  854. X   ShellCmdArgFloat(char *       name,
  855. X                    char         optchar,
  856. X                    char *       keyword,
  857. X                    char *       value,
  858. X                    char *       description,
  859. X                    unsigned     syntax_flags =CmdArg::isOPTVALREQ)
  860. X      : ShellCmdArg(name, optchar, keyword, value, description, syntax_flags)
  861. X      {}
  862. X
  863. X   ShellCmdArgFloat(char *       name,
  864. X                    char *       value,
  865. X                    char *       description,
  866. X                    unsigned     syntax_flags =CmdArg::isPOSVALREQ)
  867. X      : ShellCmdArg(name, value, description, syntax_flags)
  868. X      {}
  869. X
  870. X   virtual ~ShellCmdArgFloat(void);
  871. X
  872. X   virtual  int
  873. X   operator()(const char * & arg, CmdLine & cmd);
  874. X} ;
  875. X
  876. X//------------------------------------------------------------- ShellCmdArgChar
  877. X
  878. X   // A ShellCmdArgChar is a CmdArg object that maintains a character
  879. X   // valued shell-variable.
  880. X
  881. Xclass ShellCmdArgChar : public ShellCmdArg {
  882. Xpublic:
  883. X   ShellCmdArgChar(char *       name,
  884. X                   char         optchar,
  885. X                   char *       keyword,
  886. X                   char *       value,
  887. X                   char *       description,
  888. X                   unsigned     syntax_flags =CmdArg::isOPTVALREQ)
  889. X      : ShellCmdArg(name, optchar, keyword, value, description, syntax_flags)
  890. X      {}
  891. X
  892. X   ShellCmdArgChar(char *       name,
  893. X                   char *       value,
  894. X                   char *       description,
  895. X                   unsigned     syntax_flags =CmdArg::isPOSVALREQ)
  896. X      : ShellCmdArg(name, value, description, syntax_flags)
  897. X      {}
  898. X
  899. X   virtual ~ShellCmdArgChar(void);
  900. X
  901. X   virtual  int
  902. X   operator()(const char * & arg, CmdLine & cmd);
  903. X} ;
  904. X
  905. X//-------------------------------------------------------------- ShellCmdArgStr
  906. X
  907. X   // A ShellCmdArgStr is a CmdArg object that maintains a string
  908. X   // valued shell-variable.
  909. X
  910. Xclass ShellCmdArgStr : public ShellCmdArg {
  911. Xpublic:
  912. X   ShellCmdArgStr(char *       name,
  913. X                  char         optchar,
  914. X                  char *       keyword,
  915. X                  char *       value,
  916. X                  char *       description,
  917. X                  unsigned     syntax_flags =CmdArg::isOPTVALREQ)
  918. X      : ShellCmdArg(name, optchar, keyword, value, description, syntax_flags)
  919. X      {}
  920. X
  921. X   ShellCmdArgStr(char *       name,
  922. X                  char *       value,
  923. X                  char *       description,
  924. X                  unsigned     syntax_flags =CmdArg::isPOSVALREQ)
  925. X      : ShellCmdArg(name, value, description, syntax_flags)
  926. X      {}
  927. X
  928. X   virtual ~ShellCmdArgStr(void);
  929. X
  930. X   virtual  int
  931. X   operator()(const char * & arg, CmdLine & cmd);
  932. X} ;
  933. X
  934. X//------------------------------------------------------------- ShellCmdArgBool
  935. X
  936. X   // A ShellCmdArgBool is a CmdArg object that maintains a boolean valued
  937. X   // shell variable.
  938. X
  939. Xclass ShellCmdArgBool : public ShellCmdArg {
  940. Xpublic:
  941. X   ShellCmdArgBool(char *       name,
  942. X                   char         optchar,
  943. X                   char *       keyword,
  944. X                   char *       description,
  945. X                   unsigned     syntax_flags =CmdArg::isOPT)
  946. X      : ShellCmdArg(name, optchar, keyword, description, syntax_flags)
  947. X      {}
  948. X
  949. X   virtual ~ShellCmdArgBool(void);
  950. X
  951. X   virtual  int
  952. X   operator()(const char * & arg, CmdLine & cmd);
  953. X
  954. X   // Need to know what the values to use for TRUE and FALSE are
  955. X   //
  956. X
  957. X   static const char *
  958. X   True(void) { return  true_string ; }
  959. X
  960. X   static const char *
  961. X   False(void) { return  false_string ; }
  962. X
  963. X   // Need to be able to set the values to use for TRUE and FALSE
  964. X
  965. X   static void
  966. X   True(const char * t_str) { true_string = t_str; }
  967. X
  968. X   static void
  969. X   False(const char * f_str) { false_string = f_str; }
  970. X
  971. Xprivate:
  972. X   static  const char * true_string ;
  973. X   static  const char * false_string ;
  974. X
  975. X} ;
  976. X
  977. Xtypedef  ShellCmdArgBool  ShellCmdArgSet ;
  978. X
  979. X//------------------------------------------------------------ ShellCmdArgClear
  980. X
  981. Xclass ShellCmdArgClear : public ShellCmdArgBool {
  982. Xpublic:
  983. X   ShellCmdArgClear(char *       name,
  984. X                    char         optchar,
  985. X                    char *       keyword,
  986. X                    char *       description,
  987. X                    unsigned     syntax_flags =CmdArg::isOPT)
  988. X      : ShellCmdArgBool(name, optchar, keyword, description, syntax_flags)
  989. X      {}
  990. X
  991. X   virtual ~ShellCmdArgClear(void);
  992. X
  993. X   virtual  int
  994. X   operator()(const char * & arg, CmdLine & cmd);
  995. X} ;
  996. X
  997. X//----------------------------------------------------------- ShellCmdArgToggle
  998. X
  999. Xclass ShellCmdArgToggle : public ShellCmdArgBool {
  1000. Xpublic:
  1001. X   ShellCmdArgToggle(char *       name,
  1002. X                     char         optchar,
  1003. X                     char *       keyword,
  1004. X                     char *       description,
  1005. X                     unsigned     syntax_flags =CmdArg::isOPT)
  1006. X      : ShellCmdArgBool(name, optchar, keyword, description, syntax_flags)
  1007. X      {}
  1008. X
  1009. X   virtual ~ShellCmdArgToggle(void);
  1010. X
  1011. X   virtual  int
  1012. X   operator()(const char * & arg, CmdLine & cmd);
  1013. X} ;
  1014. X
  1015. X#endif  /* _argtypes_h */
  1016. X
  1017. END_OF_FILE
  1018. if test 6706 -ne `wc -c <'src/cmd/argtypes.h'`; then
  1019.     echo shar: \"'src/cmd/argtypes.h'\" unpacked with wrong size!
  1020. fi
  1021. # end of 'src/cmd/argtypes.h'
  1022. fi
  1023. if test -f 'src/cmd/cmdparse.pl' -a "${1}" != "-c" ; then 
  1024.   echo shar: Will not clobber existing file \"'src/cmd/cmdparse.pl'\"
  1025. else
  1026. echo shar: Extracting \"'src/cmd/cmdparse.pl'\" \(3824 characters\)
  1027. sed "s/^X//" >'src/cmd/cmdparse.pl' <<'END_OF_FILE'
  1028. X#########################################################################
  1029. X# ^FILE: cmdparse.pl - cmdparse for perl programs
  1030. X#
  1031. X# ^DESCRIPTION:
  1032. X#    This file defines a perl function named cmdparse to parse
  1033. X#    command-line arguments for perl scripts.
  1034. X#
  1035. X# ^HISTORY:
  1036. X#    05/14/91    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  1037. X##^^#####################################################################
  1038. X
  1039. X
  1040. X########
  1041. X# ^FUNCTION: cmdparse - parse command-line argument vectors
  1042. X#
  1043. X# ^SYNOPSIS:
  1044. X#    eval  &cmdparse(@args);
  1045. X#
  1046. X# ^PARAMETERS:
  1047. X#    args -- The vector of arguments to pass to cmdparse(1);
  1048. X#            This will usually be the list ("-decls=$ARGS", "--", $0, @ARGV)
  1049. X#            where $ARGS is the variable containing all the argument
  1050. X#            declaration strings.
  1051. X#
  1052. X# ^DESCRIPTION:
  1053. X#    Cmdparse will invoke cmdparse(1) to parse the command-line.
  1054. X#
  1055. X# ^REQUIREMENTS:
  1056. X#    Any desired initial values for variables from the argument-description
  1057. X#    string should be assigned BEFORE calling this function.
  1058. X#
  1059. X# ^SIDE-EFFECTS:
  1060. X#    Terminates perl-script execution if command-line syntax errors are found
  1061. X#
  1062. X# ^RETURN-VALUE:
  1063. X#    A string of perl-variable settings to be evaluated.
  1064. X#
  1065. X# ^EXAMPLE:
  1066. X#     #!/usr/bin/perl
  1067. X#
  1068. X#     require  'cmdparse.pl';
  1069. X#
  1070. X#     $ARGS = '
  1071. X#       ArgStr   string  "[S|Str string]" : STICKY    "optional string argument"
  1072. X#       ArgStr   groups  "[g|groups newsgroups ...]"  "groups to test"
  1073. X#       ArgInt   count   "[c|count number]"           "group repeat count"
  1074. X#       ArgStr   dirname "[d|directory pathname]"     "directory to use"
  1075. X#       ArgBool  xflag   "[x|xmode]"                  "turn on X-mode"
  1076. X#       ArgClear yflag   "[y|ymode]"                  "turn off Y-mode"
  1077. X#       ArgChar  sepch   "[s|separator char]"         "field separator"
  1078. X#       ArgStr   files   "[f|files filenames ...]"    "files to process"
  1079. X#       ArgStr   name    "[n|name] name"              "name to use"
  1080. X#       ArgStr   ARGV    "[args ...]"                 "any remaining arguments"
  1081. X#     ';
  1082. X#
  1083. X#     $count = 1;
  1084. X#     $dirname = '.';
  1085. X#     $sepch = ',';
  1086. X#     $yflag = 'TRUE';
  1087. X#
  1088. X#     eval &cmdparse("-decls=$ARGS", "--", $0, @ARGV);
  1089. X#
  1090. X##^^####
  1091. X
  1092. Xsub cmdparse {
  1093. X   local(@args) = @_ ;
  1094. X   local($output) = ("");
  1095. X   local($nforks, $tmpfile, $tmpdir, $exitrc, $_) = (0, "tmp$$");
  1096. X
  1097. X   $tmpdir = $ENV{'TMP'};  ## use ${TMP:-/tmp}/tmp$$ as the temporary file
  1098. X   if (! $tmpdir) {
  1099. X      $tmpdir = '/tmp';
  1100. X   }
  1101. X   $tmpfile = $tmpdir . '/' . $tmpfile;
  1102. X
  1103. X   ## I could just call cmdparse(1) using `cmdparse <options> <args>`
  1104. X   ## but then I would need to escape all shell meta-characters in each
  1105. X   ## argument. By using exec(), the arguments are passed directly to
  1106. X   ## the system and are not "globbed" or expanded by the shell.
  1107. X   ##
  1108. X   ## Hence I will need to fork off a child, redirect its standard output
  1109. X   ## to a temporary file, and then exec cmdparse(1).
  1110. X
  1111. XFORK: {
  1112. X      ++$nforks;
  1113. X      if ($pid = fork) {
  1114. X            # parent here
  1115. X         waitpid($pid, 0);  ## wait for child to die
  1116. X         $exitrc = $?;
  1117. X         $output = `cat $tmpfile` unless $exitrc;   ## save the output-script
  1118. X         unlink($tmpfile);  ## remove the temporary file
  1119. X         if ($exitrc) {
  1120. X            $! = 0;
  1121. X            die "\n";
  1122. X         }
  1123. X      } elsif (defined $pid) { ## pid is zero here if defined
  1124. X            # child here
  1125. X         open(STDOUT, "> $tmpfile") || die "Can't redirect stdout";
  1126. X         exec("cmdparse", "-shell=perl", @args);
  1127. X      } elsif ($! =~ /No more process/ ) {
  1128. X            # EAGAIN, supposedly recoverable fork error
  1129. X         if ($nforks > 10) {
  1130. X            die "$0: Can't fork cmdparse(1) after 10 tries.\n" ;
  1131. X         } else {
  1132. X            sleep 1;
  1133. X            redo FORK;
  1134. X         }
  1135. X      } else {
  1136. X         die "$0: Can't fork cmdparse(1): $!\n" ;
  1137. X      }
  1138. X   } ##FORK
  1139. X
  1140. X   return $output;
  1141. X}
  1142. X
  1143. X1;
  1144. END_OF_FILE
  1145. if test 3824 -ne `wc -c <'src/cmd/cmdparse.pl'`; then
  1146.     echo shar: \"'src/cmd/cmdparse.pl'\" unpacked with wrong size!
  1147. fi
  1148. # end of 'src/cmd/cmdparse.pl'
  1149. fi
  1150. if test -f 'src/cmd/fsm.c' -a "${1}" != "-c" ; then 
  1151.   echo shar: Will not clobber existing file \"'src/cmd/fsm.c'\"
  1152. else
  1153. echo shar: Extracting \"'src/cmd/fsm.c'\" \(6273 characters\)
  1154. sed "s/^X//" >'src/cmd/fsm.c' <<'END_OF_FILE'
  1155. X//------------------------------------------------------------------------
  1156. X// ^FILE: fsm.c - implement a finite staet machine
  1157. X//
  1158. X// ^DESCRIPTION:
  1159. X//     This file implements a finite state machine tailored to the task of
  1160. X//     parsing syntax strings for command-line arguments.
  1161. X//
  1162. X// ^HISTORY:
  1163. X//    03/27/92    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  1164. X//-^^---------------------------------------------------------------------
  1165. X
  1166. X#include <stdlib.h>
  1167. X#include <iostream.h>
  1168. X#include <ctype.h>
  1169. X#include <string.h>
  1170. X
  1171. X#include "fsm.h"
  1172. X
  1173. X   // define the characters that have a "special" meaning
  1174. Xenum {
  1175. X  c_LBRACE = '[',
  1176. X  c_RBRACE = ']',
  1177. X  c_ALT    = '|',
  1178. X  c_LIST   = '.',
  1179. X} ;
  1180. X
  1181. X
  1182. X//-------------------
  1183. X// ^FUNCTION: SyntaxFSM::skip - skip to the next token
  1184. X//
  1185. X// ^SYNOPSIS:
  1186. X//    SyntaxFSM::skip(input)
  1187. X//
  1188. X// ^PARAMETERS:
  1189. X//    const char * & input;
  1190. X//    -- the current "read" position in the syntax string.
  1191. X//
  1192. X// ^DESCRIPTION:
  1193. X//    Skip past all whitespace and past square braced (recording the
  1194. X//    current brace-nesting level and the number of balanced braces
  1195. X//    parsed).
  1196. X//
  1197. X// ^REQUIREMENTS:
  1198. X//    None.
  1199. X//
  1200. X// ^SIDE-EFFECTS:
  1201. X//    Updates "input" to point to the next token (or eos)
  1202. X//
  1203. X// ^RETURN-VALUE:
  1204. X//    None.
  1205. X//
  1206. X// ^ALGORITHM:
  1207. X//    Trivial.
  1208. X//-^^----------------
  1209. Xvoid
  1210. XSyntaxFSM::skip(const char * & input) {
  1211. X   if ((! input) || (! *input))  return;
  1212. X
  1213. X   while (isspace(*input))  ++input;
  1214. X   while ((*input == c_LBRACE) || (*input == c_RBRACE)) {
  1215. X      if (*input == c_LBRACE) {
  1216. X         ++lev;
  1217. X      } else {
  1218. X         if (lev > 0) {
  1219. X            ++nbpairs;
  1220. X         } else {
  1221. X            fsm_state = ERROR;
  1222. X            cerr << "too many '" << char(c_RBRACE) << "' characters." << endl;
  1223. X         }
  1224. X         --lev;
  1225. X      }
  1226. X      ++input;
  1227. X      while (isspace(*input))  ++input;
  1228. X   }//while
  1229. X}
  1230. X
  1231. X
  1232. X//-------------------
  1233. X// ^FUNCTION: SyntaxFSM::parse_token - parse a token
  1234. X//
  1235. X// ^SYNOPSIS:
  1236. X//    SyntaxFSM::parse_token(input)
  1237. X//
  1238. X// ^PARAMETERS:
  1239. X//    const char * & input;
  1240. X//    -- the current "read" position in the syntax string.
  1241. X//
  1242. X// ^DESCRIPTION:
  1243. X//    Get the next token from the input string.
  1244. X//
  1245. X// ^REQUIREMENTS:
  1246. X//    input should be non-NULL.
  1247. X//
  1248. X// ^SIDE-EFFECTS:
  1249. X//    Updates "input" to point to the next token (or eos)
  1250. X//
  1251. X// ^RETURN-VALUE:
  1252. X//    None.
  1253. X//
  1254. X// ^ALGORITHM:
  1255. X//    Trivial.
  1256. X//-^^----------------
  1257. Xvoid
  1258. XSyntaxFSM::parse_token(const char * & input)
  1259. X{
  1260. X   while (*input && (! isspace(*input)) &&
  1261. X          (*input != c_LBRACE) && (*input != c_RBRACE) &&
  1262. X          ((*input != c_LIST) || (fsm_state == OPTION)))
  1263. X   {
  1264. X      ++input;
  1265. X   }
  1266. X}
  1267. X
  1268. X
  1269. X//-------------------
  1270. X// ^FUNCTION: SyntaxFSM::operator() - get a token
  1271. X//
  1272. X// ^SYNOPSIS:
  1273. X//    SyntaxFSM::operator()(input, token)
  1274. X//
  1275. X// ^PARAMETERS:
  1276. X//    const char * & input;
  1277. X//    -- the current "read" position in the syntax string.
  1278. X//
  1279. X//    token_t & token;
  1280. X//    -- where to place the token that we will find.
  1281. X//
  1282. X// ^DESCRIPTION:
  1283. X//    Get the next token from the input string.
  1284. X//
  1285. X// ^REQUIREMENTS:
  1286. X//    None.
  1287. X//
  1288. X// ^SIDE-EFFECTS:
  1289. X//    - updates "input" to point to the next token (or eos)
  1290. X//    - updates "token" to be the token that we found
  1291. X//
  1292. X// ^RETURN-VALUE:
  1293. X//    0 if we are in a non-FINAL state; non-zero otherwise..
  1294. X//
  1295. X// ^ALGORITHM:
  1296. X//    It gets complicated so follow along.
  1297. X//-^^----------------
  1298. Xint
  1299. XSyntaxFSM::operator()(const char * & input, token_t & token)
  1300. X{
  1301. X   token.set(NULL, 0);
  1302. X
  1303. X      // if inout is NULL or empty - then we are finished
  1304. X   if ((! input) || (! *input)) {
  1305. X      if (lev) {
  1306. X         cerr << "not enough '" << char(c_RBRACE) << "' characters." << endl ;
  1307. X         fsm_state = ERROR;
  1308. X         return  (fsm_state != FINAL);
  1309. X      } else {
  1310. X         fsm_state = FINAL;
  1311. X         return  (fsm_state != FINAL);
  1312. X      }
  1313. X   }
  1314. X
  1315. X   skip(input);  // skip whitespace
  1316. X
  1317. X   const char * start = input;
  1318. X
  1319. X      // the token we are to parse depends on what state we are in
  1320. X   switch(fsm_state) {
  1321. X   case  START :
  1322. X      // We are parsing either an option-character name or a value.
  1323. X      // If it is an option-character name, the character that stops
  1324. X      // the input scan will be c_ALT.
  1325. X      //
  1326. X      if (*input != c_ALT)  ++input;
  1327. X      if (*input == c_ALT) {
  1328. X         fsm_state = OPTION;
  1329. X         if (start != input)  token.set(start, 1);
  1330. X      } else {
  1331. X         parse_token(input);
  1332. X         fsm_state = VALUE;
  1333. X         token.set(start, (input - start));
  1334. X      }
  1335. X      ++ntoks;
  1336. X      break;
  1337. X
  1338. X   case  OPTION :
  1339. X      // We parsed an option-character already so we had better see a keyword
  1340. X      // name this time around.
  1341. X      //
  1342. X      start = ++input;  // skip past the '|' character
  1343. X      if (! isspace(*input)) {
  1344. X         parse_token(input);
  1345. X         token.set(start, (input - start));
  1346. X      }
  1347. X      fsm_state = KEYWORD;
  1348. X      ++ntoks;
  1349. X      break;
  1350. X
  1351. X   case  KEYWORD :
  1352. X      // We parsed a keyword already - if anything is here then it better be a
  1353. X      // value name.
  1354. X      //
  1355. X      if (*input) {
  1356. X         parse_token(input);
  1357. X         fsm_state = VALUE;
  1358. X         token.set(start, (input - start));
  1359. X         ++ntoks;
  1360. X      } else {
  1361. X         fsm_state = FINAL;
  1362. X      } 
  1363. X      break;
  1364. X
  1365. X   case  VALUE :
  1366. X      // We already parsed a value name - all that could possibly be left
  1367. X      // (that we be valid) is an ellipsis ("...") indicating a list.
  1368. X      //
  1369. X      if (! *input) {
  1370. X         fsm_state = FINAL;
  1371. X      } else if (::strncmp(input, "...", 3) == 0) {
  1372. X         fsm_state = LIST;
  1373. X         token.set(input, 3);
  1374. X         input += 3;
  1375. X         ++ntoks;
  1376. X      } else {
  1377. X         fsm_state = ERROR;
  1378. X         cerr << "unexpected token \"" << input << "\"." << endl ;
  1379. X      }
  1380. X      break;
  1381. X
  1382. X   case  LIST :
  1383. X      // We already parsed an ellipsis, there better not be anything left
  1384. X      if (! *input) {
  1385. X         fsm_state = FINAL;
  1386. X      } else {
  1387. X         fsm_state = ERROR;
  1388. X         cerr << "unexpected token \"" << input << "\"." << endl ;
  1389. X      }
  1390. X      break;
  1391. X
  1392. X   case  ERROR :
  1393. X   case  FINAL :
  1394. X   default :
  1395. X      break;
  1396. X   }
  1397. X
  1398. X   if (fsm_state == FINAL) {
  1399. X      skip(input);
  1400. X      if ((! *input) && lev) {
  1401. X         cerr << "not enough '" << char(c_RBRACE) << "' characters." << endl ;
  1402. X         fsm_state = ERROR;
  1403. X      } else if (*input) {
  1404. X         cerr << "unexpected token \"" << input << "\"." << endl ;
  1405. X         fsm_state = ERROR;
  1406. X      }
  1407. X   }
  1408. X
  1409. X   return  (fsm_state != FINAL);
  1410. X}
  1411. X
  1412. END_OF_FILE
  1413. if test 6273 -ne `wc -c <'src/cmd/fsm.c'`; then
  1414.     echo shar: \"'src/cmd/fsm.c'\" unpacked with wrong size!
  1415. fi
  1416. # end of 'src/cmd/fsm.c'
  1417. fi
  1418. if test -f 'src/cmd/quoted.c' -a "${1}" != "-c" ; then 
  1419.   echo shar: Will not clobber existing file \"'src/cmd/quoted.c'\"
  1420. else
  1421. echo shar: Extracting \"'src/cmd/quoted.c'\" \(3984 characters\)
  1422. sed "s/^X//" >'src/cmd/quoted.c' <<'END_OF_FILE'
  1423. X//------------------------------------------------------------------------
  1424. X// ^FILE: quoted.c - implement quoted strings
  1425. X//
  1426. X// ^DESCRIPTION:
  1427. X//     This file implements that class defined in "quoted.h"
  1428. X//
  1429. X// ^HISTORY:
  1430. X//    05/01/92    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  1431. X//-^^---------------------------------------------------------------------
  1432. X
  1433. X#include <stdlib.h>
  1434. X#include <iostream.h>
  1435. X#include <string.h>
  1436. X#include <ctype.h>
  1437. X
  1438. X#include "quoted.h"
  1439. X
  1440. X//--------------------------------------------------------------- Constructors
  1441. X
  1442. XQuotedString::QuotedString(unsigned  max_size)
  1443. X   : size(max_size)
  1444. X{
  1445. X   buffer = new char[size] ;
  1446. X}
  1447. X   
  1448. X
  1449. XQuotedString::QuotedString(const char * str)
  1450. X{
  1451. X   size = ::strlen(str + 1);
  1452. X   buffer = new char[size];
  1453. X   if (buffer)  ::strcpy(buffer, str);
  1454. X}
  1455. X
  1456. XQuotedString::QuotedString(const char * str, unsigned  max_size)
  1457. X   : size(max_size)
  1458. X{
  1459. X   buffer = new char[size];
  1460. X   if (buffer)  ::strcpy(buffer, str);
  1461. X}
  1462. X
  1463. XQuotedString::QuotedString(const QuotedString & qstr)
  1464. X   : size(qstr.size)
  1465. X{
  1466. X   buffer = new char[size];
  1467. X   if (buffer)  ::strcpy(buffer, qstr.buffer);
  1468. X}
  1469. X
  1470. X//--------------------------------------------------------------- Destructor
  1471. X
  1472. XQuotedString::~QuotedString(void)
  1473. X{
  1474. X   delete [] buffer ;
  1475. X}
  1476. X
  1477. X//--------------------------------------------------------------- Assignment
  1478. X
  1479. XQuotedString &
  1480. XQuotedString::operator=(const QuotedString & qstr)
  1481. X{
  1482. X   delete [] buffer ;
  1483. X   size = qstr.size;
  1484. X   buffer = new char[size];
  1485. X   if (buffer)  ::strcpy(buffer, qstr.buffer);
  1486. X   return  *this ;
  1487. X}
  1488. X
  1489. XQuotedString &
  1490. XQuotedString::operator=(const char * str)
  1491. X{
  1492. X   delete [] buffer ;
  1493. X   size = ::strlen(str) + 1;
  1494. X   buffer = new char[size];
  1495. X   if (buffer)  ::strcpy(buffer, str);
  1496. X   return  *this ;
  1497. X}
  1498. X
  1499. X//--------------------------------------------------------------- operator>>
  1500. X
  1501. Xistream &
  1502. Xoperator>>(istream & is, QuotedString & qstr)
  1503. X{
  1504. X      // get the first non-white character
  1505. X   char  ch;
  1506. X   is >> ch;
  1507. X   if (! is) {
  1508. X      if (is.eof()) {
  1509. X         cerr << "Premature end of input.\n"
  1510. X              << "\texpecting a single or a double quote." << endl ;
  1511. X      } else {
  1512. X         cerr << "Unable to extract quoted string from input." << endl ;
  1513. X      }
  1514. X      return  is;
  1515. X   }
  1516. X
  1517. X   int  single_quote = 0, double_quote = 0;
  1518. X
  1519. X   switch (ch) {
  1520. X   case '\'' :
  1521. X      single_quote = 1;  break;
  1522. X   case '"'  :
  1523. X      double_quote = 1;  break;
  1524. X   default :
  1525. X      cerr << "Unexpected character '" << ch << "'.\n" 
  1526. X           << "\texpecting a single or a double quotation mark." << endl ;
  1527. X      is.clear(ios::failbit);
  1528. X      return  is;
  1529. X   } //switch
  1530. X
  1531. X
  1532. X   // Now fetch into "dest" until we see the ending quote.
  1533. X   char    * dest = qstr.buffer;
  1534. X   unsigned  end_quote = 0;
  1535. X   unsigned  len = 0;
  1536. X   int  c;
  1537. X   while (! end_quote) {
  1538. X      int  escape = 0;
  1539. X      c = is.get();
  1540. X      if (! is) {
  1541. X         if (is.eof()) {
  1542. X            cerr << "Unmatched " << (single_quote ? "\"'\"" : "'\"'")
  1543. X                 << "quote." << endl ;
  1544. X         } else {
  1545. X            cerr << "Unable to extract quoted string from input." << endl ;
  1546. X         }
  1547. X         return  is;
  1548. X      }
  1549. X      if (c == '\\') {
  1550. X         escape = 1;
  1551. X         c = is.get();
  1552. X         if (! is) {
  1553. X            if (is.eof()) {
  1554. X               cerr << "Unmatched " << (single_quote ? "\"'\"" : "'\"'")
  1555. X                    << " quote." << endl ;
  1556. X            } else {
  1557. X               cerr << "Unable to extract quoted string from input." << endl ;
  1558. X            }
  1559. X            return  is;
  1560. X         }
  1561. X      }
  1562. X      if ((c == '\'') && single_quote && !escape) {
  1563. X         end_quote = 1;
  1564. X      } else if ((c == '"') && double_quote && !escape) {
  1565. X         end_quote = 1;
  1566. X      } else if (len < qstr.size) {
  1567. X         dest[len++] = c;
  1568. X      } else {
  1569. X         cerr << "Error - quoted string is too long.\n\tmust be less than "
  1570. X              << qstr.size << " characters." << endl ;
  1571. X         is.clear(ios::failbit);
  1572. X         return  is;
  1573. X      }
  1574. X   } //while
  1575. X   
  1576. X   dest[len++] = '\0' ;   // dont forget to NUL-terminate
  1577. X   return  is;
  1578. X}
  1579. X
  1580. END_OF_FILE
  1581. if test 3984 -ne `wc -c <'src/cmd/quoted.c'`; then
  1582.     echo shar: \"'src/cmd/quoted.c'\" unpacked with wrong size!
  1583. fi
  1584. # end of 'src/cmd/quoted.c'
  1585. fi
  1586. if test -f 'src/lib/argiter.c' -a "${1}" != "-c" ; then 
  1587.   echo shar: Will not clobber existing file \"'src/lib/argiter.c'\"
  1588. else
  1589. echo shar: Extracting \"'src/lib/argiter.c'\" \(3891 characters\)
  1590. sed "s/^X//" >'src/lib/argiter.c' <<'END_OF_FILE'
  1591. X//------------------------------------------------------------------------
  1592. X// ^FILE: argiter.c - implementation of CmdLineArgIter subclasses
  1593. X//
  1594. X// ^DESCRIPTION:
  1595. X//    This file implements the derived classes of a CmdLineArgIter that
  1596. X//    are declazred in <cmdline.h>.
  1597. X//
  1598. X// ^HISTORY:
  1599. X//    04/03/92    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  1600. X//-^^---------------------------------------------------------------------
  1601. X
  1602. X#include <stdlib.h>
  1603. X#include <iostream.h>
  1604. X#include <string.h>
  1605. X#include <ctype.h>
  1606. X
  1607. X#include "cmdline.h"
  1608. X
  1609. X//-------------------------------------------------------- class CmdLineArgIter
  1610. X
  1611. XCmdLineArgIter::CmdLineArgIter(void) {}
  1612. X
  1613. XCmdLineArgIter::~CmdLineArgIter(void) {}
  1614. X
  1615. X//----------------------------------------------------------- class CmdArgvIter
  1616. X
  1617. XCmdArgvIter::~CmdArgvIter(void) {}
  1618. X
  1619. Xconst char *
  1620. XCmdArgvIter::operator()(void) {
  1621. X   return  ((index != count) && (array[index])) ? array[index++] : 0 ;
  1622. X}
  1623. X
  1624. Xint
  1625. XCmdArgvIter::is_temporary(void) const { return  0; }
  1626. X
  1627. X//--------------------------------------------------------- class CmdStrTokIter
  1628. X
  1629. Xstatic const char WHITESPACE[] = " \t\n\r\v\f" ;
  1630. X
  1631. X   // Constructor
  1632. XCmdStrTokIter::CmdStrTokIter(const char * tokens, const char * delimiters)
  1633. X   : tokstr(NULL), seps(NULL), token(NULL)
  1634. X{
  1635. X   reset(tokens, delimiters);
  1636. X}
  1637. X
  1638. X   // Destructor
  1639. XCmdStrTokIter::~CmdStrTokIter(void)
  1640. X{
  1641. X   delete  tokstr;
  1642. X}
  1643. X
  1644. X   // Use a new string and a new set of delimiters
  1645. Xvoid
  1646. XCmdStrTokIter::reset(const char * tokens, const char * delimiters)
  1647. X{
  1648. X   seps = delimiters;
  1649. X   if (seps == NULL)  seps = WHITESPACE ;  // use default delimiters
  1650. X
  1651. X   delete  tokstr;
  1652. X   tokstr = NULL;
  1653. X   token = NULL;
  1654. X   if (tokens) {
  1655. X      // Make a copy of the token-string (because ::strtok() modifies it)
  1656. X      // and get the first token from the string
  1657. X      //
  1658. X      tokstr = new char[::strlen(tokens) + 1] ;
  1659. X      (void) ::strcpy(tokstr, tokens);
  1660. X      token = ::strtok(tokstr, seps);
  1661. X   }
  1662. X}
  1663. X
  1664. X   // Iterator function -- operator()
  1665. X   //   Just use ::strtok to get the next token from the string
  1666. X   //
  1667. Xconst char *
  1668. XCmdStrTokIter::operator()(void)
  1669. X{
  1670. X   if (seps == NULL)  seps = WHITESPACE ;
  1671. X   const char * result = token;
  1672. X   if (token) token = ::strtok(NULL, seps);
  1673. X   return  result;
  1674. X}
  1675. X
  1676. X   // The storage that we return pointers to (in operator())
  1677. X   // always points to temporary space.
  1678. X   //
  1679. Xint
  1680. XCmdStrTokIter::is_temporary(void) const
  1681. X{
  1682. X   return  1;
  1683. X}
  1684. X
  1685. X//-------------------------------------------------------- class CmdIstreamIter
  1686. X
  1687. Xstatic const unsigned  MAX_LINE_LEN = 1024 ;
  1688. X
  1689. X#ifdef vms
  1690. X   enum { c_COMMENT = '!' } ;
  1691. X#else
  1692. X   enum { c_COMMENT = '#' } ;
  1693. X#endif
  1694. X
  1695. X   // Constructor
  1696. XCmdIstreamIter::CmdIstreamIter(istream & input) : is(input), tok_iter(NULL)
  1697. X{
  1698. X}
  1699. X
  1700. X   // Destructor
  1701. XCmdIstreamIter::~CmdIstreamIter(void)
  1702. X{
  1703. X   delete  tok_iter;
  1704. X}
  1705. X
  1706. X   // Iterator function -- operator()
  1707. X   //
  1708. X   // What we do is this: for each line of text in the istream, we use
  1709. X   // a CmdStrTokIter to iterate over each token on the line.
  1710. X   //
  1711. X   // If the first non-white character on a line is c_COMMENT, then we
  1712. X   // consider the line to be a comment and we ignore it.
  1713. X   //
  1714. Xconst char *
  1715. XCmdIstreamIter::operator()(void)
  1716. X{
  1717. X   const char * result = NULL;
  1718. X   if (tok_iter)  result = tok_iter->operator()();
  1719. X   if (result)  return  result;
  1720. X   if (! is)  return  NULL;
  1721. X
  1722. X   char buf[MAX_LINE_LEN];
  1723. X   do {
  1724. X      *buf = '\0';
  1725. X      is.getline(buf, sizeof(buf));
  1726. X      char * ptr = buf;
  1727. X      while (isspace(*ptr)) ++ptr;
  1728. X      if (*ptr && (*ptr != c_COMMENT)) {
  1729. X         if (tok_iter) {
  1730. X            tok_iter->reset(ptr);
  1731. X         } else {
  1732. X            tok_iter = new CmdStrTokIter(ptr);
  1733. X         }
  1734. X         return  tok_iter->operator()();
  1735. X      }
  1736. X   } while (is);
  1737. X   return  NULL;
  1738. X}
  1739. X
  1740. X   // We use a CmdStrTokIterator that is always temporary, thus the
  1741. X   // the tokens we return are always in temporary storage
  1742. X   //
  1743. Xint
  1744. XCmdIstreamIter::is_temporary(void) const
  1745. X{
  1746. X   return  1;
  1747. X}
  1748. END_OF_FILE
  1749. if test 3891 -ne `wc -c <'src/lib/argiter.c'`; then
  1750.     echo shar: \"'src/lib/argiter.c'\" unpacked with wrong size!
  1751. fi
  1752. # end of 'src/lib/argiter.c'
  1753. fi
  1754. if test -f 'src/lib/fifolist.h' -a "${1}" != "-c" ; then 
  1755.   echo shar: Will not clobber existing file \"'src/lib/fifolist.h'\"
  1756. else
  1757. echo shar: Extracting \"'src/lib/fifolist.h'\" \(7182 characters\)
  1758. sed "s/^X//" >'src/lib/fifolist.h' <<'END_OF_FILE'
  1759. X//------------------------------------------------------------------------
  1760. X// ^FILE: fifolist.h - generic FIFO list classes
  1761. X//
  1762. X// ^DESCRIPTION:
  1763. X//    This file defines a generic FIFO linked list class and two types
  1764. X//    of iterators for the list.  The first iterator is just your basic
  1765. X//    run-of-the-mill iterator.  The second iterator treats the list
  1766. X//    as if it were an array and allows you to index into the list.
  1767. X//
  1768. X//    Once these generic classes are declared, macros are defined to allow
  1769. X//    the programmer to declare lists (and iterators) that contain a
  1770. X//    particular type of item.  On systems where your C++ compiler supports
  1771. X//    templates, templates are used, otherwise we "fake it".
  1772. X//
  1773. X//    The macro defined is named DECLARE_FIFO_LIST and is used as follows:
  1774. X//
  1775. X//       DECLARE_FIFO_LIST(Name, Type);
  1776. X//
  1777. X//    This declares a type named "Name" that is a list of pointers to
  1778. X//    items of type "Type".  Also, the types "NameIter" and "NameArray"
  1779. X//    are declared as the iterators for this type of list.
  1780. X//
  1781. X// ^HISTORY:
  1782. X//    03/21/92    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  1783. X//-^^---------------------------------------------------------------------
  1784. X
  1785. X#ifndef _fifolist_h
  1786. X#define _fifolist_h
  1787. X
  1788. X#ifndef  name2
  1789. X# if defined(__STDC__) || defined(__ANSI_CPP__)
  1790. X#  define  name2(x,y) x##y
  1791. X# else
  1792. X#  define  name2(x,y) x/**/y
  1793. X# endif
  1794. X#endif
  1795. X
  1796. X
  1797. X   // GenericFifoList - a FIFO linked list of void * pointers
  1798. X   //
  1799. Xclass  GenericFifoList {
  1800. Xprivate:
  1801. X
  1802. Xprotected:
  1803. X   // Need to define what a "node" in the list looks like
  1804. X   struct GenericFifoListNode {
  1805. X      GenericFifoListNode * next;
  1806. X      void * contents;
  1807. X
  1808. X      GenericFifoListNode(GenericFifoListNode * nd =0, void * val =0)
  1809. X         : next(nd), contents(val) {}
  1810. X   } ;
  1811. X
  1812. X   unsigned  mod : 1;
  1813. X   unsigned  del_items : 1;
  1814. X   unsigned  num_items ;
  1815. X   GenericFifoListNode * head;
  1816. X   GenericFifoListNode * tail;
  1817. X
  1818. Xpublic:
  1819. X   GenericFifoList(void)
  1820. X      : head(0), tail(0), num_items(0), del_items(0), mod(0) {}
  1821. X
  1822. X   virtual  ~GenericFifoList(void);
  1823. X
  1824. X   // Remove the first item from the list
  1825. X   void *
  1826. X   remove(void);
  1827. X
  1828. X   // Add an item to the end of the list
  1829. X   void
  1830. X   add(void * item);
  1831. X
  1832. X   // Was the list modified since the last time we checked?
  1833. X   int
  1834. X   modified(void) { return (mod) ? (mod = 0, 1) : 0 ; }
  1835. X
  1836. X   // Is the list empty?
  1837. X   int
  1838. X   is_empty(void) const { return  (num_items == 0); }
  1839. X
  1840. X   // How many items are in the list?
  1841. X   unsigned
  1842. X   count(void) const { return  num_items; }
  1843. X
  1844. X   // Is the list responsible for deleting the items it contains?
  1845. X   int
  1846. X   self_cleaning(void) const { return  int(del_items); }
  1847. X
  1848. X   // Tell the list who is responsible for deleting the items it contains?
  1849. X   void
  1850. X   self_cleaning(int  bool_val)  { del_items = (bool_val) ? 1 : 0; }
  1851. X
  1852. X   friend class GenericFifoListIter;
  1853. X   friend class GenericFifoListArray;
  1854. X} ;
  1855. X
  1856. X
  1857. X   // GenericFifoListIter -- an iterator for a GenericFifoList
  1858. Xclass  GenericFifoListIter {
  1859. Xprivate:
  1860. X   GenericFifoList::GenericFifoListNode * current;
  1861. X
  1862. Xpublic:
  1863. X   GenericFifoListIter(GenericFifoList & fifo_list)
  1864. X      : current(fifo_list.head) {}
  1865. X
  1866. X   GenericFifoListIter(GenericFifoList * fifo_list)
  1867. X      : current(fifo_list->head) {}
  1868. X
  1869. X   virtual  ~GenericFifoListIter(void);
  1870. X
  1871. X   // Return the current item in the list and advance to the next item.
  1872. X   // returns NULL if at end-of-list
  1873. X   //
  1874. X   void *
  1875. X   operator()(void);
  1876. X} ;
  1877. X
  1878. X
  1879. X   // GenericFifoListArray -- an array-style iterator for a GenericFifoList
  1880. Xclass  GenericFifoListArray {
  1881. Xprivate:
  1882. X   GenericFifoList &  list;
  1883. X   unsigned           index;
  1884. X   GenericFifoList::GenericFifoListNode * current;
  1885. X
  1886. Xpublic:
  1887. X   GenericFifoListArray(GenericFifoList & fifo_list)
  1888. X      : list(fifo_list), index(0), current(fifo_list.head) {}
  1889. X
  1890. X   GenericFifoListArray(GenericFifoList * fifo_list)
  1891. X      : list(*fifo_list), index(0), current(fifo_list->head) {}
  1892. X
  1893. X   virtual  ~GenericFifoListArray(void);
  1894. X
  1895. X   // How many items are in the array?
  1896. X   unsigned  count(void) const  { return  list.count(); }
  1897. X
  1898. X   // Return a specified item in the array.
  1899. X   //   NOTE: the programmer is responsible for making sure the given index
  1900. X   //         is not out of range. For this base class, NULL is returned
  1901. X   //         when the index is out of range. Derived classes however
  1902. X   //         dereference the value returned by this function so using
  1903. X   //         an out-of-range index in one of the derived classes will
  1904. X   //         cause a NULL pointer dereferencing error!
  1905. X   //
  1906. X   void *
  1907. X   operator[](unsigned  ndx);
  1908. X} ;
  1909. X
  1910. X#ifdef TEMPLATES
  1911. X
  1912. Xtemplate <class Type>
  1913. Xclass FifoList : public GenericFifoList {
  1914. Xpublic:
  1915. X   FifoList(void) {}
  1916. X
  1917. X   virtual ~FifoList(void);
  1918. X
  1919. X   void
  1920. X   add(Type * item)  { GenericFifoList::add((void *)item); }
  1921. X
  1922. X   Type *
  1923. X   remove(void)  { return  (Type *) GenericFifoList::remove(); }
  1924. X} ;
  1925. X
  1926. Xtemplate <class Type>
  1927. Xclass FifoListIter : public GenericFifoListIter {
  1928. Xpublic:
  1929. X   FifoListIter(FifoList<Type> & list) : GenericFifoListIter(list) {}
  1930. X   FifoListIter(FifoList<Type> * list) : GenericFifoListIter(list) {}
  1931. X
  1932. X   virtual  ~FifoListIter(void);
  1933. X
  1934. X   Type *
  1935. X   operator()(void)  {  return  (Type *) GenericFifoListIter::operator()(); }
  1936. X} ;
  1937. X
  1938. Xtemplate <class Type>
  1939. Xclass FifoListArray : public GenericFifoListArray {
  1940. Xpublic:
  1941. X   FifoListArray(FifoList<Type> & list) : GenericFifoListArray(list) {}
  1942. X   FifoListArray(FifoList<Type> * list) : GenericFifoListArray(list) {}
  1943. X
  1944. X   virtual  ~FifoListArray(void);
  1945. X
  1946. X   Type &
  1947. X   operator[](unsigned  ndx)
  1948. X      { return  *((Type *) GenericFifoListArray::operator[](ndx)) }
  1949. X} ;
  1950. X
  1951. X#define  DECLARE_FIFO_LIST(Name,Type) \
  1952. X   typedef  FifoList<Type> Name; \
  1953. X   typedef  FifoListIter<Type>  name2(Name,Iter) \
  1954. X   typedef  FifoListArray<Type> name2(Name,Array)
  1955. X
  1956. X#else  /* dont have templates -- have to fake it */
  1957. X
  1958. X#define  DECLARE_FIFO_LIST(Name,Type) \
  1959. X   class Name : public GenericFifoList {  \
  1960. X   public:  \
  1961. X      Name(void) {}  \
  1962. X\
  1963. X      virtual ~Name(void) {  \
  1964. X         GenericFifoListNode * nd = head;  \
  1965. X         head = 0; \
  1966. X         while (nd) {  \
  1967. X            GenericFifoListNode * to_delete = nd;  \
  1968. X            nd = nd->next;  \
  1969. X            if (del_items)  delete (Type *)to_delete->contents;  \
  1970. X            delete  to_delete;  \
  1971. X         }  \
  1972. X      }  \
  1973. X\
  1974. X      void  \
  1975. X      add(Type * item)  { GenericFifoList::add((void *)item); }  \
  1976. X\
  1977. X      Type *  \
  1978. X      remove(void)  { return  (Type *) GenericFifoList::remove(); }  \
  1979. X\
  1980. X      friend  class name2(Name,Iter);  \
  1981. X   } ;  \
  1982. X\
  1983. Xclass name2(Name,Iter) : public GenericFifoListIter {  \
  1984. Xpublic:  \
  1985. X   name2(Name,Iter)(Name & list) : GenericFifoListIter(list) {}  \
  1986. X   name2(Name,Iter)(Name * list) : GenericFifoListIter(list) {}  \
  1987. X\
  1988. X   virtual ~ name2(Name,Iter)(void) {} \
  1989. X\
  1990. X   Type *  \
  1991. X   operator()(void)  {  return  (Type *) GenericFifoListIter::operator()(); } \
  1992. X} ; \
  1993. X\
  1994. Xclass name2(Name,Array) : public GenericFifoListArray {  \
  1995. Xpublic:  \
  1996. X   name2(Name,Array)(Name & list) : GenericFifoListArray(list) {}  \
  1997. X   name2(Name,Array)(Name * list) : GenericFifoListArray(list) {}  \
  1998. X\
  1999. X   virtual ~ name2(Name,Array)(void) {} \
  2000. X\
  2001. X   Type &  \
  2002. X   operator[](unsigned  ndx)  \
  2003. X      { return  *((Type *) GenericFifoListArray::operator[](ndx)); }  \
  2004. X}
  2005. X
  2006. X#endif  /* TEMPLATES */
  2007. X
  2008. X
  2009. X#endif /* _fifolist_h */
  2010. X
  2011. END_OF_FILE
  2012. if test 7182 -ne `wc -c <'src/lib/fifolist.h'`; then
  2013.     echo shar: \"'src/lib/fifolist.h'\" unpacked with wrong size!
  2014. fi
  2015. # end of 'src/lib/fifolist.h'
  2016. fi
  2017. if test -f 'src/lib/parse.c' -a "${1}" != "-c" ; then 
  2018.   echo shar: Will not clobber existing file \"'src/lib/parse.c'\"
  2019. else
  2020. echo shar: Extracting \"'src/lib/parse.c'\" \(5024 characters\)
  2021. sed "s/^X//" >'src/lib/parse.c' <<'END_OF_FILE'
  2022. X//------------------------------------------------------------------------
  2023. X// ^FILE: parse.c - parsing portion of the CmdLine library
  2024. X//
  2025. X// ^DESCRIPTION:
  2026. X//     The following functions defined in <cmdline.h> are implemented:
  2027. X//
  2028. X//        CmdLine::prologue() -- initialize stuff for parsing
  2029. X//        CmdLine::epilogue() -- finish up stuff for parsing
  2030. X//        CmdLine::parse()     -- parse arguments from an iterator
  2031. X//
  2032. X// ^HISTORY:
  2033. X//    12/05/91    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  2034. X//-^^---------------------------------------------------------------------
  2035. X
  2036. X#include <stdlib.h>
  2037. X#include <iostream.h>
  2038. X#include <ctype.h>
  2039. X#include <string.h>
  2040. X
  2041. X#include "exits.h"
  2042. X#include "states.h"
  2043. X#include "arglist.h"
  2044. X#include "cmdline.h"
  2045. X
  2046. X
  2047. X//-------
  2048. X// ^FUNCTION: CmdLine::prologue - initialize before parsing
  2049. X//
  2050. X// ^SYNOPSIS:
  2051. X//    unsigned CmdLine::prologue(void)
  2052. X//
  2053. X// ^PARAMETERS:
  2054. X//    None.
  2055. X//
  2056. X// ^DESCRIPTION:
  2057. X//    Before we can begin parsing argument from the command-line, we need
  2058. X//    to set (or reset) certain attributes of the CmdLine object. Among
  2059. X//    other things, we need to reset its state and status, and we need to
  2060. X//    reset the state of each of its arguments.
  2061. X//
  2062. X// ^REQUIREMENTS:
  2063. X//    None.
  2064. X//
  2065. X// ^SIDE-EFFECTS:
  2066. X//    Modifies all parts of the CmdLine object and its arguments.
  2067. X//
  2068. X// ^RETURN-VALUE:
  2069. X//    A combination of bitmasks of type CmdLine::CmdStatus corresponding to
  2070. X//    what (if anything) went wrong.
  2071. X//
  2072. X// ^ALGORITHM:
  2073. X//    Follow along - its not too complicated.
  2074. X//-^^----
  2075. Xunsigned
  2076. XCmdLine::prologue(void)
  2077. X{
  2078. X   // reset parse-specific attributes
  2079. X   cmd_parse_state = cmd_START_STATE ;
  2080. X   cmd_state = 0 ;
  2081. X   cmd_status = NO_ERROR ;
  2082. X
  2083. X   // reset parse-specific attributes for each argument
  2084. X   CmdArgListListIter  list_iter(cmd_args);
  2085. X   for (CmdArgList * alist = list_iter() ; alist ; alist = list_iter()) {
  2086. X      CmdArgListIter  iter(alist);
  2087. X      for (CmdArg * cmdarg = iter() ; cmdarg ; cmdarg = iter()) {
  2088. X         cmdarg->clear();
  2089. X      }
  2090. X   }
  2091. X
  2092. X   return  cmd_status ;
  2093. X}
  2094. X
  2095. X//-------
  2096. X// ^FUNCTION: CmdLine::epilogue - clean up after parsing
  2097. X//
  2098. X// ^SYNOPSIS:
  2099. X//    unsigned CmdLine::epilogue(void)
  2100. X//
  2101. X// ^PARAMETERS:
  2102. X//    None.
  2103. X//
  2104. X// ^DESCRIPTION:
  2105. X//
  2106. X// ^REQUIREMENTS:
  2107. X//    None.
  2108. X//
  2109. X// ^SIDE-EFFECTS:
  2110. X//    Modifies the command-line obejct.
  2111. X//
  2112. X//    Prints messages on cerr (if QUIET is not set) if there are
  2113. X//    missing required arguments or values (and prompts for them if
  2114. X//    PROMPT_USER is set of $PROMPT_USER is exists and is non-empty).
  2115. X//
  2116. X//    Prints a usage message if there were syntax error.
  2117. X//
  2118. X//    Terminates program execution by calling ::exit(e_SYNTAX) if
  2119. X//    (NO_ABORT is NOT set and the command-status is NOT NO_ERROR).
  2120. X//
  2121. X// ^RETURN-VALUE:
  2122. X//    A combination of bitmasks of type CmdLine::CmdStatus corresponding to
  2123. X//    what (if anything) went wrong.
  2124. X//
  2125. X// ^ALGORITHM:
  2126. X//    - See if we left an argument dangling without a required value,
  2127. X//    - Check for missing required arguments
  2128. X//    - Print usage if required
  2129. X//    - Exit if required
  2130. X//-^^----
  2131. Xunsigned
  2132. XCmdLine::epilogue(void)
  2133. X{
  2134. X   if (cmd_err == NULL)  cmd_err = &cerr;
  2135. X
  2136. X   // see if we left an argument dangling without a value
  2137. X   ck_need_val() ;
  2138. X
  2139. X   // check for any missing required arguments
  2140. X   cmd_status |= missing_args();
  2141. X
  2142. X   // print usage if necessary
  2143. X   if (cmd_status & ARG_MISSING) {
  2144. X      usage();
  2145. X      ::exit(e_SYNTAX);
  2146. X   } else if (cmd_status && (! (cmd_flags & NO_ABORT))) {
  2147. X      usage();
  2148. X      ::exit(e_SYNTAX);
  2149. X   }
  2150. X
  2151. X   return  cmd_status ;
  2152. X}
  2153. X
  2154. X//-------------------
  2155. X// ^FUNCTION: parse - parse arguments from an iterator
  2156. X//
  2157. X// ^SYNOPSIS:
  2158. X//    parse(arg_iter, auto_processing)
  2159. X//
  2160. X// ^PARAMETERS:
  2161. X//    CmdLineArgIter & arg_iter;
  2162. X//    -- collection of string arguments from the command-line
  2163. X//
  2164. X//    int  auto_processing;
  2165. X//    -- if this is NON-zero, then automatically call prologue() and
  2166. X//       epilogue() to do pre- and post- processing.
  2167. X//
  2168. X// ^DESCRIPTION:
  2169. X//    Parse all the argument in a given argument iterator.
  2170. X//    If auto_processing is NON-zero then the programmer is
  2171. X//    directly responsible for calling prologue() and epilogue().
  2172. X//
  2173. X// ^REQUIREMENTS:
  2174. X//    None.
  2175. X//
  2176. X// ^SIDE-EFFECTS:
  2177. X//    - Uses up all remaining arguments in arg_iter
  2178. X//    - Modifies the CmdLine
  2179. X//
  2180. X// ^RETURN-VALUE:
  2181. X//    The resultant status of the CmdLine:
  2182. X//
  2183. X// ^ALGORITHM:
  2184. X//    Trivial - just iterate through calling parse_arg.
  2185. X//-^^----------------
  2186. Xunsigned
  2187. XCmdLine::parse(CmdLineArgIter & arg_iter, int  auto_processing)
  2188. X{
  2189. X   // NOTE: If arg_iter.is_temporary() is TRUE then we MUST remember
  2190. X   //       to set the CmdLine::TEMP flags before parsing (and put it
  2191. X   //       back the way it was when we are finished.
  2192. X   //
  2193. X   if (auto_processing)  (void) prologue();
  2194. X   unsigned  save_flags = cmd_flags;
  2195. X   if (arg_iter.is_temporary())  cmd_flags |= TEMP;
  2196. X   for (const char * arg = arg_iter() ; arg ; arg = arg_iter()) {
  2197. X      (void) parse_arg(arg);
  2198. X   }
  2199. X   if (arg_iter.is_temporary())  cmd_flags = save_flags;
  2200. X   if (auto_processing)  (void) epilogue();
  2201. X   return  cmd_status ;
  2202. X}
  2203. X
  2204. END_OF_FILE
  2205. if test 5024 -ne `wc -c <'src/lib/parse.c'`; then
  2206.     echo shar: \"'src/lib/parse.c'\" unpacked with wrong size!
  2207. fi
  2208. # end of 'src/lib/parse.c'
  2209. fi
  2210. echo shar: End of archive 2 \(of 7\).
  2211. cp /dev/null ark2isdone
  2212. MISSING=""
  2213. for I in 1 2 3 4 5 6 7 ; do
  2214.     if test ! -f ark${I}isdone ; then
  2215.     MISSING="${MISSING} ${I}"
  2216.     fi
  2217. done
  2218. if test "${MISSING}" = "" ; then
  2219.     echo You have unpacked all 7 archives.
  2220.     rm -f ark[1-9]isdone
  2221. else
  2222.     echo You still need to unpack the following archives:
  2223.     echo "        " ${MISSING}
  2224. fi
  2225. ##  End of shell archive.
  2226. exit 0
  2227.  
  2228. exit 0 # Just in case...
  2229.