home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / cmdline / part02 < prev    next >
Encoding:
Text File  |  1992-07-26  |  67.0 KB  |  2,222 lines

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