[comp.sources.mac] Flex for the Mac

earleh@eleazar.dartmouth.edu (Earle R. Horton) (06/29/88)

[Flex for the Mac - part 1 of 7]

What follows are the sources to Flex, a generator of lexical analysis
programs in the style of UNIX lex.  These sources are compatible with
MPW C 2.0.2, and with 4.3 BSD UNIX.  The code is relatively clean, so
porting to other systems doesn't look too bad.  See my notes in
README_for_Macintosh if you want to port to another Macintosh
development system.  There are some "gotcha"s.

My contribution to these sources is the port to MPW (trivial) and fixes
to the original code to allow it to scan Macintosh option characters
(non-trivial).  Macintosh option characters are generally speaking
non-ASCII characters, i.e. the high bit of the byte holding an
option-char is set.  The modifications I have made to the source code
now allow Flex to scan for these characters in all systems (I think),
and will be of interest for any system where non-ASCII characters might
be used (e.g. VMS).

The files "makefile", "makefile.MPW", and "flexit" contain Macintosh
option-chars (you are warned).  There is a UNIX Makefile also, if you
want to use this with Aztec.

[Moderator's Note: makefile.Hqx, makefile.MPW.Hqx, and flexit.Hqx are
 provided here.]

Earle Horton
*********************************************************************
*Earle R. Horton, H.B. 8000, Dartmouth College, Hanover, NH 03755   *
*********************************************************************

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	flex/Changes
#	flex/README
#	flex/README_for_Mac
#	flex/Timings
#	flex/flexit.Hqx
#	flex/makefile.Hqx
#	flex/makefile.MPW.Hqx
#	flex/makefile.UNIX
#	flex/manifest
#	flex/flex.fastskel
#	flex/flex.skel
# This archive created: Wed Jun 29 07:03:10 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Changes'" '(861 characters)'
if test -f 'Changes'
then
	echo shar: will not over-write existing file "'Changes'"
else
sed 's/^X//' << \SHAR_EOF > 'Changes'
XChanges between beta-test release of Feb. '88 and initial release:
X
X	- many files renamed to remove "flex" prefix
X	- input() routine added to compressed and fast skeletons
X	- unput() routine added to compressed skeleton
X	- -d, -ce support for fast scanners
X	- symbol table extended to avoid ugly casts of ints <-> char *'s;
X	  this may relieve MS-DOS woes
X	- actions are now separated with YY_BREAK instead of simple "break"'s
X	- fixed bug causing core-dumps if skeleton file could not be opened
X	- fixed bugs in logic deciding which options cannot be intermixed
X	- initial start condition can now be referred to as <INITIAL>
X	- fixed bug which would incorrectly computer trailing context
X	  count for a pattern like "(foo){3}"; now this is considered
X	  "variable length", even though it isn't.
X	- block comments allowed between rules
X	- misc. typos corrected
SHAR_EOF
if test 861 -ne "`wc -c < 'Changes'`"
then
	echo shar: error transmitting "'Changes'" '(should have been 861 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README'" '(3402 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XThis is the initial release of flex, a replacement for the lex(1)
Xtool.  As the copyright indicates, this distribution can be freely
Xredistributed.
X
XSome notes on the distribution:
X
X    Yes, there are some niggling lex features which are not available which
X    seem like they'd be easy to add.  They're not, or if they are then the
X    straight-forward implementation of them would slow down the scanner.
X    Unfortunately I am unable to do any further work on flex other than bug
X    fixes, so if there's something you've just gotta have, you'd better
X    be willing to dive into the code.  I'll be happy to give (fairly
X    high-level) advice on how to proceed.
X
X    The compressed tables have been tested pretty thoroughly in the past,
X    though may be suffering from bit-rot.  The fast/full tables have been
X    recently implemented and are more likely to have bugs.
X
X    For a System V machine, add the #define "SV".  Not guaranteed to do
X    the full job, but a step in the right direction.
X
X    Flex has been successfully ported to Sun Unix and 4.3BSD Vax Unix.
X
X
XThe flex distribution consists of the following files:
X
X	README		This message
X
X	Changes		Differences between this release and the beta-test
X
X	Makefile
X	flexdef.h
X	parse.y
X	scan.l
X	ccl.c
X	dfa.c		flex sources
X	ecs.c
X	main.c
X	misc.c
X	nfa.c
X	sym.c
X	tblcmp.c
X	yylex.c
X
X	scan.c.dist	pre-flex'd version of scan.l
X
X	flex.skel
X	flex.fastskel
X	flexskelcom.h	skeleton scanner sources
X	flexskeldef.h
X	fastskeldef.h
X
X	flex.1		manual entry
X
X	Timings		a brief note comparing timings of flex vs. lex
X
X[  The following section is only true if you got the files from FTP
X    to LBL, directly, and not from the more widely-distributed
X    comp.sources.unix publication.  --Rich $alz
XThe files are packaged as a compressed shell archive, which in turn
Xcontains seven shell archives.  Create a directory where you want flex
Xto live, cd there, and use
X
X	uncompress flex.shar.Z
X	sh flex.shar
X
X	sh flex.shar.1
X	sh flex.shar.2
X	sh flex.shar.3
X	sh flex.shar.4
X	sh flex.shar.5
X	sh flex.shar.6
X	sh flex.shar.7
X
Xto extract them.
X]
X
XEither move {flexskelcom.h,flexskeldef.h,fastskeldef.h} into /usr/include
Xor edit {flex.skel,flex.fastskel,flexskeldef.h,fastskeldef.h,scan.c.dist}
Xand wire in the full pathname of where you are going to keep the include files.
X
XDecide where you want to keep {flex.skel,flex.fastskel} (suggestion:
X/usr/local/lib) and move it there.  Edit "Makefile" and change the
Xdefinitions of SKELETON_FILE and F_SKELETON_FILE to reflect the full
Xpathnames of {flex.skel,flex.fastskel}.
X
XTo make flex for the first time, use:
X
X    make first_flex
X
Xwhich uses a pre-generated copy of the scanner whose source is in flex.
X
XAssuming it builds successfully, you can test it using
X
X    make test
X
XThe "diff" should not show any differences.
X
XIf you're feeling adventurous, rebuild scan.c using various
Xcombinations of FLEX_FLAGS, each time trying "make test" when
Xyou're done.  To rebuild it, do
X
X	rm scan.c
X	make FLEX_FLAGS="..."
X
Xwhere "..." is one of:
X
X	-ist -c
X	-ist -ce
X	-ist -cm
X	-ist -cfe
X	-ist -cFe
X
Xand testing using:
X
X	make FLEX_FLAGS="..." test
X
X
XFormat the manual entry using
X
X    nroff -man flex.1
X
X
XPlease send problems and feedback to:
X
X	vern@lbl-{csam,rtsg}.arpa  or  ucbvax!lbl-csam.arpa!vern
X
X	Vern Paxson
X	Real Time Systems Group
X	Bldg. 46A
X	Lawrence Berkeley Laboratory
X	1 Cyclotron Rd.
X	Berkeley, CA 94720
X
X	(415) 486-6411
SHAR_EOF
if test 3402 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 3402 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README_for_Mac'" '(3938 characters)'
if test -f 'README_for_Mac'
then
	echo shar: will not over-write existing file "'README_for_Mac'"
else
sed 's/^X//' << \SHAR_EOF > 'README_for_Mac'
XFlex for the Mac (MPW).  Port by Earle Horton, May 1988
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
XThis document consists of general comments regarding the implementation
Xof Flex as a Macintosh Programmer's Workshop tool.  Comments regarding
Xthe building of flex and its use are freely interspersed.
X
XMPW 2.0.2 tools are limited to 32k of global data.  This necessitates use of
Xmalloc() to obtain space for a number of Flex's work buffers.  This is
Xdone both in the source code for Flex and in the scanners produced by
XFlex, and is determined by definition of the pre-processor macro
XMALLOC_BUFFERS.  Scanners produced by Flex can save 5k of global data
Xspace if compiled with MALLOC_BUFFERS #defined.  Still, the fast scanner
Xoptions will probably not work in this environment because of the large
Xtables used.
X
XI have supplied a function gettime() which returns a string produced
Xby IUTimeString().  Results may not be the same as those produced by
Xversions of Flex running on UNIX systems.  If you are interested in
Xporting Flex to another Macintosh development system, then you should
Xlook in misc.c and verify that the calling sequence is correct for 
Xyour compiler.  This is the only Macintosh-specific system call used.
X
XThe Macintosh "newline" character is decimal 13.  MPW C treats all 
Xreferences to '\n' to mean 13, and not 10.  Other development systems
Xinclude code in stdio to translate carriage returns to line feeds on
Xinput, so that code compiled in these systems sees decimal 10 at the
Xend of lines, and not the 13 which is actually there.  This means that
Xstate tables generated by MPW Flex may not be suitable for compilation
Xusing the compiler of another development system, unless the input
Xstream read by the macro YY_INPUT is in binary mode. 
X
XThe files "flex.skel" and "flex.fastskel" are found by use of environment
Xvariables thusly:
X
X	set SKELETON_FILE "{clibraries}flex.skel"
X	export SKELETON_FILE
X	set F_SKELETON_FILE "{clibraries}flex.fastskel"
X	export F_SKELETON_FILE
X
X{Clibraries} is where I keep my copies.  Copies of the three #include
Xfiles flexskelcom.h,flexskeldef.h and fastskeldef.h should also be
Xput where the C compiler can find them, usually {CIncludes}.
X
XThe temporary file used by Flex has a constant name.  If you are batty
Xenough to have files named "/tmp/flexXXXXXX" lying around you will 
Xlose them.
X
XThe MPW Makefile uses stubs.c.o.  Stubs.c is included in the MPW C
Xdistribution in the "CExamples" folder, and provides dummy functions
Xfor those routines which are not needed by tools.  This causes the
Xlinker to emit duplicate entry warnings, unless "-d" is turned on,
Xwhich it is in the supplied Makefile.
X
XThis distribution contains files which are not used in the MPW
Ximplementation, but which will be needed in case anyone wants to 
Xcompile Flex on a non-Mac system.  For this reason, I request that
Xif you redistribute the Flex sources, you distribute ALL the files
Xwhich I supply.  In particular, "scan.c.dist" will be essential to
Xanyone attempting to compile these sources on a non-Mac, and possibly
Xon a Mac using another Mac development system.
X
XThis code incorporates fixes to a bug in the original code which did
Xnot allow scanning of Macintosh option-characters (those with the
Xhigh bit set).  This fix should also allow it work with character 
Xsets such as DEC multi-nationals.   I have verified that this fix
Xallows Flex to scan non-ASCII characters properly on a 4.3 BSD
Xsystem, but have not tried it with any other systems at this time.
X
XHappy scanning!
X
XEarle
SHAR_EOF
if test 3938 -ne "`wc -c < 'README_for_Mac'`"
then
	echo shar: error transmitting "'README_for_Mac'" '(should have been 3938 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Timings'" '(857 characters)'
if test -f 'Timings'
then
	echo shar: will not over-write existing file "'Timings'"
else
sed 's/^X//' << \SHAR_EOF > 'Timings'
Xflex vs. lex timings for a C tokenizer which includes keywords:
X
XGeneration times:
X
X	lex	    83.0 secs
X	flex	     3.9
X	flex -cfe    7.1	# uncompressed table, equivalence classes
X	flex -cf    15.0	# uncompressed table, no equivalence classes
X
XScanner object file sizes:
X
X	lex	   41.0K bytes
X	flex	    9.4K
X	flex -cfe  49.6K
X	flex -cf  126.5K
X
XRunning times on a 28,088 line input (685K characters):
X
X	lex	   29.8 secs
X	flex	   19.3
X	flex -cfe   9.0
X	flex -cf    7.8
X
XThe timings were made on a Sun 3/60.  All times are user + system CPU time,
Xand don't include hashing of identifiers.
X
XSummary:
X
X    For about the same sized scanner, you get a factor of 3 in performance.
X    For a 30% faster scanner, you get a scanner 1/4th the size, and it's
X	generated in 1/20th the time.
X    For a scanner that's 3 times larger, you get a factor of 3.8 in
X	performance.
SHAR_EOF
if test 857 -ne "`wc -c < 'Timings'`"
then
	echo shar: error transmitting "'Timings'" '(should have been 857 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'flexit.Hqx'" '(499 characters)'
if test -f 'flexit.Hqx'
then
	echo shar: will not over-write existing file "'flexit.Hqx'"
else
sed 's/^X//' << \SHAR_EOF > 'flexit.Hqx'
X(This file must be converted with BinHex 4.0)
X
X:"QCXCAKTG!"849K869"6)!#3"!%Z!*!%FH%M)%e39cSJ3fpZGQ9bG#!mFh4ND@i
Xq)'PZG'mJB5"XCAKTBf&X)(0MB@jZCA)JEQ&YC@3JE'PZDbj[GA3Z$@CXCAJJ,A3
XJI#"M)#eR)#e%HAPXCAJpE@&TEJeXD@jV)!NYGb!YBL!YBb!R69"6)#FJ,A3J69"
X69##f$3N*Bbj[),B0#3NLHd0-D@*bBA*TCA0p)R0dG@*c,Q-ZEb#f$3N*)RY$6'P
XLFQ&bD@9cI5*$8R9ZG'PYC5j[),B0#3NLHd0-D@*bBA*TCA0p)P0dC%0-D@)ZEb#
Xf$3N*)RY$6'PLFQ&bD@9cI5*$8d&148aTBLj[),B0#3NLHd0-D@*bBA*TCA0p)N0
X*ER4PFQCKBf8ZEb#f$3N*)RY-D@*bBA*TCA0p)NPZG'9bCQ&MC5j[$@2h!!!:
SHAR_EOF
if test 499 -ne "`wc -c < 'flexit.Hqx'`"
then
	echo shar: error transmitting "'flexit.Hqx'" '(should have been 499 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile.Hqx'" '(2872 characters)'
if test -f 'makefile.Hqx'
then
	echo shar: will not over-write existing file "'makefile.Hqx'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile.Hqx'
X(This file must be converted with BinHex 4.0)
X
X:#'eKDf9QD@aP!&4&@&408&-J!*!%#!8!N!6cUL-JE@&VC5"QD@aP)'C[FL!LCQa
XPH#)JG'p[E!dM)%e39b"YB@YP)(CPFR0TEfiJBRNJ4@&bE'8J5'pbG'pZ,#"0BAN
XJ-6Ni1!d0)b"dD'8JCQPbFh3JG'PYC5"KFQpeEQ3JGA0P)#*YB@YP)'CTFR0dAfC
XXCAJL$3e*6N0-984&8b!p)#*lBfPZBfaeC'9cI5)03NP14%P5)$dJ)RY08&Gp)P4
X[Efac1Je-58*%59)J25!LHf0XD@*bBA*TCA0p)Je65d9-49426Pp'58a&Adj"688
XJ25"RCA4PERBSYL*65d9-49426Pp'58a&YL)T$8CI8dY&6%986djI4NP-49p138e
X&)$dJCf9dC@jf+,BL4Pp65d9-49426Pp'58a&YL)T$90,48a'6%&(8b!p)#e%4%9
X'399-9&p65d9-49426Pp'58a&2AY65d9-49426Pp'58a&Adj"689p),B0#5#3"#e
X%4N&69&p65d9-49426Pp'58a&2AY'Ae0,48a&9%p1AdC*6%9I6N&04Ad03dC-38G
X6)$dJ,@FJ,8408&FJ,84038a-6d0I3P9'4N958`e-4%C-38G6)$dJ#5eN)#eL)#e
XM)#G08&-J*b!YG#"08&08),B0#3NLHd0-D@*bBA*TCA0p)R0dG@*c,Q-ZEb#f$3N
X*)RY$6'PLFQ&bD@9cI5*$8R9ZG'PYC5j[),B0#3NLHd0-D@*bBA*TCA0p)P0dC%0
X-D@)ZEb#f$3N*)RY$6'PLFQ&bD@9cI5*$8d&148aTBLj[),B0#3NLHd0-D@*bBA*
XTCA0p)N0*ER4PFQCKBf8ZEb#f$3N*)RY-D@*bBA*TCA0p)NPZG'9bCQ&MC5j[$3N
X*$5jM,Qm*a!NZB`d*3b"lC'9QBA9XG(dZBb"l3dC-38G6I5!YEb"lC'9QBA9XG(d
XZBbj[$3e'6%9BAdC-38G6)$dJ,@PcG!e'6%9B)$dJCQaPH!d04Na&@%p#5P-J25#
Xf$3PKE'a[Bf%ZB5j[),B0#@*kCA*[,Q-ZEb#f$3PMBf`ZBbj[),B0#@4QB5jM,Qm
XJYJd*C@0c,Q-ZEb#f$3PYB@PZ,Q-ZEb#f$3PYDA0M,Q-ZEb#f$3PZCQ%ZBbj[),B
X0#A"KFR0P,Q-ZEb#f$3PcBf&Z,Q-ZEb#f$3PcH@dZBbj[),B0#A4LE'0YF#jM,Qm
XJYJd*HAPXCAJZBbj[$3e'6%9BAd0I8dp98N0&8b!p),B0#@*kCA*[,Q-JYJd*Bf0
XX,Q-JYJd*C'CK,Q-JYJd*C@0c,Q-JYJd*E@&TELjM),B0#@eTFf-ZBb#f$3PZCQ%
XZBb#f$3P`BA*cC5jM),B0#A0MB@iZBb#f$3PcH@dZBb#f$3PdBQaMEA!ZBb#f$3P
XjH@aPH#jM$3eQE'9i)-3JHdC-49K23NT6I3d*6'PZDb!YEb"QE'9i)(Y'6%9B6d*
X+8hdJHda%4Na"4e0p$3eQDA*cG&pQE'9i)-30#@4eF'aTBf&dC5"cBf&Z,Q-ZC'P
XcG#"cBf&Z,Q-0#@eKDf8JHde'6%&(8hdJCQaPH!d*$A"KFR0P,Q-Ja#"`BA*cC5j
Xj$3PjB@0M)#eN)("KFR0P,RN0#@e[GQ8J,ANJH5jdB@)ZBb"`BA*cC5jM$3PYEhC
XP)#ej)(NZG'&L,QJJF'&bFf8ZD!d0F'&bFf8ZD!R%)("KFR0P,Q-0$5-JBfpYE@9
XZG#e[GA3JG'KP)'jPH(3JG(G[)'aTEQ9c)'&QG'9b)'%JFh9MBf9cFfCeE#!LE@&
XVC5"dCA0d)L"KEQ30)b"MEfeYC@jd,@PZ)(4SC5"QEfaXEhGTEQFJG(G[)'aTEQ9
Xc,Jd0Ff0KELjM)-3JFf0KELjX$3Pl4Na&@(dJHdC-49KI4Na"4e0p)(0MB@iZE#!
XqFf0KELjM$3ecBf&Z,Q-ZEb$%)(0MB@iZBb"`BA*cC5jS$3eYB@PZ,Q-ZEb$%)'e
XKD@iZB`d*Bb"l3dC-38G6I5"l8dY&6%C-38G6I5"YB@PZ,Q-0$5-J3@jjBQpNH5"
XSBACP)'aTER3r$3eQE'9i,QaTER3Ja#"l4Na&@&p$Ae0299*$490p$3PPBfK[)#*
X&H("PBh3JB5#f)QeKH5"LC5"eFf9N)'*PCQpbC5"cCA5f)L"KEQ3J-L#f)R9ZGA0
XPC,BL*h-0#@aTER3JHdC-49KI3ep66e953d96I5!q)'CXCAJZE'PZG!d0BfaPB@i
XJa!d*C'9XCA4P)#eT)'CXCAJJa5j[)("KFR0P,Q-JF'&bFf8ZD#"cBf&Z,Q-0$A4
XPFh3Ja!d*C@0SEb!L9'KTFb"cG'9`)'4PFh4bEhPc)'TeEQXZBbiL$3Pl4Na&@(d
XJHdC-49KI4Na"4e0p)(0MB@iZE#!q)'TeEQXZBb!0#@0[EA"KFQ8JFf0KELjM)'T
XeEQXZB`d*C'9XCA4P)'TeEQXZB`d0D@jcG'&XE#$%)(Y'6%9BI3d*C(9`E'PMBA4
XP)#ej)(Y'6%9BI5"l3NP14%P5I3d*C(9`E'PMBA4P)#ej)'CXCAKcDf9XBfpY,QJ
XJHdP13da94%96I3d*C(9`E'PMBA4P)#ej)'CXCAKcDf9XC'9Q,QJJHdP13da94%9
X6I3d*C(9`E'PMBA4P)#ej)'CKFh4cDf9XC'9Q,QJJHdP13da94%96I3d*C(9`E'P
XMBA4P)#ej)'CXCAJZFfYPE#"l6%P#4%P5I3d*C(9`E'PMBA4P)#ej)'CXCAJZCQ&
XcG(0VC@`JHda*3N4*8Rd0$Gr6!!!:
SHAR_EOF
if test 2872 -ne "`wc -c < 'makefile.Hqx'`"
then
	echo shar: error transmitting "'makefile.Hqx'" '(should have been 2872 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile.MPW.Hqx'" '(3313 characters)'
if test -f 'makefile.MPW.Hqx'
then
	echo shar: will not over-write existing file "'makefile.MPW.Hqx'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile.MPW.Hqx'
X(This file must be converted with BinHex 4.0)
X
X:$'eKDf9QD@aP,Ne39`"849K869"6)!#3"!J&!!!"IYC1)b"YB@YP)'CTE'8JCQp
Xb)#*QE'9i)L"dEfpX$5-J69"A)'eKDf8JGQ9bFfP[EL"LH5"&BA*XC5")Eh*dEfi
XX)%eKH5!a16Ji$3dM)(4SC5"QDA*cG#"dD@eP)'&bEh9ZC#"eFf8J)QeKDf8JCQP
XbFh4ICQaPH#)0$8P13da94%96)$dJ)RYMD@jME(9NCA0p)Je#58j%59)J25!LHde
X39hdL9'p[E(-k$8a*3N4*8L!p)#*lBfaTBR*KFQPPFhdL$90,48a&9%p1AdC*6%9
XI6N&045!p)'GPG'9ZGLLf)P0,48a&9%p1AdC*6%@f)LN04Pp65d9-49426Pp'58a
X&Adj"688J25"RCA4PERBSYL*'Ae0,48a&9%p1AdC*6%@f)LN08dY&6%C-38G6)$d
XJ,84%48C"98a8Ae0,48a&9%p1AdC*6%8pHe0,48a&9%p1AdC*6%9I6N&04AdJYJd
X*)*!%,84'3908Ae0,48a&9%p1AdC*6%8pHdCI8dY&6%986djI4NP-49p138e&I3e
X$4Na"4e-J25!YCb!Y4%e39b!Y4%e"6%a23ep#98C'49*6$8a%4Na"4e-J25!*,@3
XJ,@)J,@-J*de38b!R)#ed)%e38e3JYJd*#5*l3daTBR*KFQPPFhdLFh4eBR-ZBbj
X[),B0#3NLHd0-D@*bBA*TCA0p)N05G@jdD@eP,QmJYJd*#5*l3daTBR*KFQPPFhd
XL8h4N3daTBLj[),B0#3NLHd0-D@*bBA*TCA0p)N0638j&6'PL,QmJYJd*#5*l3da
XTBR*KFQPPFhdL3dPZG'9bCQ&MC5j[),B0#3NLHdaTBR*KFQPPFhdL5@jdCA*QB@0
XP,Qm0#3N0,Q-ZE`R%#5jM$3P$)(YNC@CKG@adI5jM)(Y$4Na"4e0p)#e[)(YNC@C
XKG@adI5jM,Qm0$8C-49KI4Na"4e-J25!YDA0d$8C-49JJ25"QE'9i$3e'6%9B6d*
X+8b!p),B0#@&XE'pMB5jK,QmJYJd*BRTPFQmZBbj[),B0#@0ME#jM,QmJYJd*C'C
XK,Q-ZEb#f$3PPBh-ZBbj[),B0#@eKD@iZBbj[),B0#@eTFf-ZBbj[),B0#@jQB5j
XM,QmJYJd*F'&bFf8ZBbj[),B0#A0MB@iZBbj[),B0#A0jE5jM,QmJYJd*G'*XBfe
X`,Q-ZEb#f$3PjH@aPH#jM,Qm0$8C-49KI3ep66e953d96)$dJYJd*BRTPFQmZBb#
Xf$3PMBf`ZBb#f$3PNCQ%ZBb#f$3PPBh-ZBb#f$3PYB@PZ,Q-JYJd*E@PcBbjM),B
X0#@jQB5jM),B0#A"KFR0P,Q-JYJd*Ff0KELjM),B0#A0jE5jM),B0#A4LE'0YF#j
XM),B0#APjE'9i,Q-0$@CXCAJJa#"l4Na&@%p#5P0p$3P-D@jV)#e[)'CXCAJJHdC
X-49K23NT6I5"l6%4'6%&(8hd0$@CTFR0dAfCXCAJJa!d*C(9`E'PMBA4P)(0MB@i
XZBbjNDA0d)(0MB@iZB`d*E@&VC5"l68C-38G6I5"QE'9i$3N0F'&bFf8ZBb$%)("
XKFR0P,RN0#APKBf-J,@3JF'&bFf8ZH3d*E@pfC5!YH5"j,R4KBLjM)("KFR0P,Q-
X0#@e[GQ8J,ANJH5jdB@)ZD#"`BA*cC5jS$3e`BA*cC5jS#F3JF'&bFf8ZB`d0)b"
XMEfeYC@jd,@peG#"dD'8JEQ9iG#"dGfmJE'PZCA-JB@CdCA)JB5"cG@0MCA0cCR9
XX)#*YB@YP)(4PFh3L)'&ZC!dM)'0[E@ePER3YD@iJG'KP)'C[E'a[GfPZCb"dGfm
XJE'PZCA-Z$3ecBf&Z,Q-Ja#"cBf&Z,Q`0#AY'6%9BI5"l4Na&@&p'6%&(8hdJFf0
XKELjX)$jcBf&Z,Q-0$A0MB@iZBbj[)-3JFf0KELjM)("KFR0P,QJ0$@eKD@iZBbj
X[)-3JE@&TELjM$3PM)(Y$4Na"4e0p)(Y65d9-4Na"4e0p)'eKD@iZB`d0)b""ERP
XLEf4j)'KKGQ8JE'PZG$m0$@CXCAJZE'PZG#$%)(Y'6%9BAd0I8dp98N0&8hd0#@9
XMD'mJ)N9iF'9MG#"K),BLE@&j)'*P)(9cC@3JBQ9QEh*P)(0PG,BL)'&ZC#!b),B
XLG@jeFf9NYL)RF`d*E'PZG#"l4Na&@&p$Ae0299*$490p)$iJCQaPH#jXD@jd$3e
XME'9KEL$%$3PNC@aPG'8J,@NJCQaPH#$&,QmJF'&bFf8ZBb"`BA*cC5jS)(0MB@i
XZB`d0G'9cG#$%$3PPBfK[)#*8D'Pc)(0dCA!JC'9cG(*[HA-JDR9ZDbjM,L)0#AY
X'6%9BI5"l4Na&@&p'6%&(8hdJFf0KELjX)$iJDR9ZDbjM)!d*BfpYF'&bC5"cBf&
XZ,Q-JDR9ZDbjM$3PNC@aPG'8JDR9ZDbjM$3eTER0dB@aX)-3JHdC-49Kp$3PNGA"
XXD@0KG'8J,ANJHdC-49Kp)(Y#58j%59*p$3PNGA"XD@0KG'8J,ANJCQaPH(0VC@a
XMEfdZD#"l58j$6&9%490p$3PNGA"XD@0KG'8J,ANJCQaPH(0VC@aNC@BZD#"l58j
X$6&9%490p$3PNGA"XD@0KG'8J,ANJCQ&cG(0VC@aNC@BZD#"l58j$6&9%490p$3P
XNGA"XD@0KG'8J,ANJCQaPH#jcDf9X)(Y-58*%59*p$3PNGA"XD@0KG'8J,ANJCQa
XPH#jQBA0dFfYPE#"l6%P#4%P5I3d0hp-!!!%!N!-"6!#3!d`!N!-b+3eB)(0MB@i
XZBbjNDA0d)#Jc1*!$0#"LHA4PFbN0@#!-E@&VC@CTE'8Z69"A8!)!N$1Hl4)'!*!
X'!Aie0b"LHA4PFbN0@#"jH@aPH#jM)#Jc068d)'*jG'9c+3eYB@0MEfe`FQ9cFc)
XZ-3eVFfKPCA4p)L#cXb"%CABk8h4N6h9d*`e"C'40C@je)%*eD@aN)#G6D'ph)%C
XeE'`J3R9TE'3J3fpYE@&ZC(2**b!R3Q9RD@il)!NJ8f9d)&"b!*!$5!!*6@pZB@0
X[!(d!+!!S!Gd#ICl%CK`!!!DZ!!!'VJ!!!V-!"J!%!$`!*!(G!Rd!2!!N!Gd#ICl
X$Ur8!N!`"!*!$!3#3!`&-!*!$6!#3!c)!!GT)!T3!N!-F!$)!!%e38e)!N!-+!qh
Xrr`#3"3,EA0$h!:
SHAR_EOF
if test 3313 -ne "`wc -c < 'makefile.MPW.Hqx'`"
then
	echo shar: error transmitting "'makefile.MPW.Hqx'" '(should have been 3313 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile.UNIX'" '(1264 characters)'
if test -f 'makefile.UNIX'
then
	echo shar: will not over-write existing file "'makefile.UNIX'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile.UNIX'
X# make file for "flex" tool
X
X# the first time around use "make first_flex"
X
XSKELETON_FILE = \"/usr/local/lib/flex.skel\"
XF_SKELETON_FILE = \"/usr/local/lib/flex.fastskel\"
XSKELFLAGS = -DDEFAULT_SKELETON_FILE=$(SKELETON_FILE) \
X	    -DFAST_SKELETON_FILE=$(F_SKELETON_FILE)
XCFLAGS = -O
XLDFLAGS =
X
XFLEX_FLAGS = -ist
XFLEX = flex
X
XFLEXOBJS = \
X	ccl.o \
X	dfa.o \
X	ecs.o \
X	main.o \
X	misc.o \
X	nfa.o \
X	parse.o \
X	scan.o \
X	sym.o \
X	tblcmp.o \
X	yylex.o
X
XFLEX_C_SOURCES = \
X	ccl.c \
X	dfa.c \
X	ecs.c \
X	main.c \
X	misc.c \
X	nfa.c \
X	parse.c \
X	scan.c \
X	sym.c \
X	tblcmp.c \
X	yylex.c
X
Xflex : $(FLEXOBJS)
X	cc $(CFLAGS) -o flex $(LDFLAGS) $(FLEXOBJS)
X
Xfirst_flex:
X	cp scan.c.dist scan.c
X	make $(MFLAGS) flex
X
Xparse.h parse.c : parse.y
X	yacc -d parse.y
X	@mv y.tab.c parse.c
X	@mv y.tab.h parse.h
X
X# comment-out the next two lines after a successful "make test" and
X# comment-in the following two lines.
X
Xscan.c : scan.l
X	$(FLEX) $(FLEX_FLAGS) scan.l >scan.c
X
Xscan.o : scan.c parse.h
X
Xmain.o : main.c
X	cc $(CFLAGS) -c $(SKELFLAGS) main.c
X
Xflex.lint : $(FLEX_C_SOURCES)
X	@echo "Expect a \"may be used before set\" and 2 \"unused\"'s
X	lint $(FLEX_C_SOURCES) > flex.lint
X
Xclean :
X	rm -f core errs flex *.o parse.c *.lint parse.h
X
Xtest :
X	$(FLEX) $(FLEX_FLAGS) scan.l | diff scan.c -
SHAR_EOF
if test 1264 -ne "`wc -c < 'makefile.UNIX'`"
then
	echo shar: error transmitting "'makefile.UNIX'" '(should have been 1264 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'manifest'" '(312 characters)'
if test -f 'manifest'
then
	echo shar: will not over-write existing file "'manifest'"
else
sed 's/^X//' << \SHAR_EOF > 'manifest'
XName     
X--------
Xalloca.a 
Xbzero.c 
Xccl.c
XChanges
Xdfa.c
Xecs.c
Xfastskeldef.h
Xflex.1
Xflex.fastskel
Xflex.man.page
Xflex.skel
Xflexdef.h
Xflexit 
Xflexskelcom.h 
Xflexskeldef.h
Xmain.c
Xmakefile.MPW
Xmakefile.UNIX
Xmanifest
Xmisc.c
Xnfa.c
Xparse.y
XREADME
XREADME_for_Macintosh
Xscan.c.dist
Xscan.l
Xsym.c
Xtblcmp.c
XTimings
Xyylex.c
SHAR_EOF
if test 312 -ne "`wc -c < 'manifest'`"
then
	echo shar: error transmitting "'manifest'" '(should have been 312 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'flex.fastskel'" '(9560 characters)'
if test -f 'flex.fastskel'
then
	echo shar: will not over-write existing file "'flex.fastskel'"
else
sed 's/^X//' << \SHAR_EOF > 'flex.fastskel'
X/* A lexical scanner generated by flex */
X
X#define FLEX_FAST_SKEL
X
X#include "fastskeldef.h"
X
X%% section 1 code and the definition of YY_TRANS_OFFSET_TYPE, if needed, go here
X
X#ifndef FLEX_FULL_TABLE
X    /* struct for yy_transition */
X    struct yy_trans_info
X	{
X	/* v is a verify for a transition. */
X	short v;
X
X	/* In cases where its sister v *is* a "yes, there is a transition",
X         * n is* the offset (in records) to the next state.  In most cases
X         * where there is no transition, the value of n is irrelevant.  If n
X         * is the -1th  record of a state, though, then n is the action
X	 * number for that state
X	 */
X	YY_TRANS_OFFSET_TYPE n;
X	};
X#endif
X
X%% data tables for DFA go here
X
X/* these declarations have to come after the section 1 code or lint gets
X * confused about whether the variables are used
X */
XFILE *yyin = stdin, *yyout = stdout;
X
X/* these variables are all declared out here so that section 3 code can
X * manipulate them
X */
Xstatic char *yy_c_buf_p;	/* points to current character in buffer */
Xstatic char *yy_b_buf_p;	/* points to start of current scan */
Xstatic int yy_init = 1;	/* whether we need to initialize */
Xstatic int yy_start;	/* start state number */
X
X/* true when we've seen an EOF for the current input file */
Xstatic int yy_eof_has_been_seen;
X
Xstatic int yy_n_chars;		/* number of characters read into yy_ch_buf */
X
X/* yy_ch_buf has to be 2 characters longer than YY_BUF_SIZE because we need
X * to put in 2 end-of-buffer characters (this is explained where it is
X * done) at the end of yy_ch_buf
X */
X#ifdef MALLOC_BUFFERS
Xstatic char *yy_ch_buf = 0L;
X#else
Xstatic char yy_ch_buf[YY_BUF_SIZE + 2];
X#endif
X
X/* yy_hold_char holds the character lost when yytext is formed */
Xstatic char yy_hold_char;
Xchar *yytext;
Xstatic int yyleng;	/* length of yytext */
X
Xstatic YY_CS_TYPE yy_last_accepting_state;
Xstatic char *yy_last_accepting_cpos;
X
Xstatic YY_CS_TYPE yy_get_previous_state();
Xstatic int yy_get_next_buffer();
X
X#define FLEX_USES_BACKTRACKING
X
X#ifdef FLEX_USES_BACKTRACKING
X#    ifdef FLEX_FULL_TABLE
X#	define YY_BACKTRACKING_ACTION \
X		if ( l[yy_current_state] ) \
X			{ \
X			yy_last_accepting_state = yy_current_state; \
X			yy_last_accepting_cpos = yy_c_buf_p; \
X			}
X#    else
X#	define YY_BACKTRACKING_ACTION \
X		if ( yy_current_state[-1].n ) \
X			{ \
X			yy_last_accepting_state = yy_current_state; \
X			yy_last_accepting_cpos = yy_c_buf_p; \
X			}
X#    endif
X#else
X#    define YY_BACKTRACKING_ACTION
X#endif
X
XYY_DECL
X    {
X    register YY_CS_TYPE yy_current_state;
X    register int yy_c;
X    register struct yy_trans_info *yy_trans_info;
X    register int yy_act;
X
X%% user's declarations go here
X
X#ifdef MALLOC_BUFFERS
X	if(yy_ch_buf == 0L){
X		yy_ch_buf = (char *)malloc(YY_BUF_SIZE + 2);
X		if(yy_ch_buf == 0L){
X			fprintf( stderr, "Out of memory\n");
X			exit(-1);
X		}
X	}
X#endif
X    if ( yy_init )
X	{
X	yy_start = 1;	/* first start state */
X
Xnew_file:
X	/* this is where we enter upon encountering and end-of-file and
X	 * yywrap() indicating that we should continue processing
X	 */
X
X	/* we put in the '\n' and start reading from [1] so that an
X	 * initial match-at-newline will be true.
X	 */
X
X	yy_ch_buf[0] = '\n';
X	yy_n_chars = 1;
X
X	/* we always need two end-of-buffer characters.  The first causes
X	 * a transition to the end-of-buffer state.  The second causes
X	 * a jam in that state.
X	 */
X	yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
X	yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
X
X	yy_eof_has_been_seen = 0;
X
X	YY_FAST_INIT;
X	yy_init = 0;
X	}
X
X    while ( 1 )		/* loops until end-of-file is reached */
X	{
X	/* support of yytext and yyleng */
X	YY_DO_BEFORE_SCAN;
X
X	/* yy_b_buf_p points to the position in yy_ch_buf of the start of the
X	 * current run.
X	 */
X	yy_b_buf_p = yy_c_buf_p;
X
X        YY_FIND_START_STATE( yy_current_state );
X
X        YY_FIND_NEXT_MATCH;
X
X	YY_DO_BEFORE_ACTION;
X
X/* we need this label to process the very last action (right before the end of
X * the file)
X */
Xdo_action:
X	YY_FIND_ACTION( yy_act );
X
X#ifdef FLEX_DEBUG
X	fprintf( stderr, "--accepting rule #%d\n", yy_act );
X#endif
X	switch ( yy_act )
X	    {
X%% actions go here
X
X	    case YY_BACK_TRACK:
X		YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
X		yy_c_buf_p = yy_last_accepting_cpos + 1;
X		yy_current_state = yy_last_accepting_state;
X		YY_DO_BEFORE_ACTION;
X		goto do_action;
X
X	    case YY_NEW_FILE:
X		break; /* begin reading from new file */
X
X	    case YY_DO_DEFAULT:
X		/* we have to eat up one character and recompute yytext and
X		 * yyleng
X		 */
X		YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
X		++yy_c_buf_p;
X		YY_DO_BEFORE_ACTION;
X		YY_DEFAULT_ACTION;
X		break;
X
X	    case YY_END_OF_BUFFER:
X		YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
X
X		switch ( yy_get_next_buffer() )
X		    {
X		    case EOB_ACT_END_OF_FILE:
X			{
X			if ( yywrap() )
X			    {
X			    /* note: because we've taken care in
X			     * yy_get_next_buffer() to have set up yy_b_buf_p,
X			     * we can now set up yy_c_buf_p so that if some
X			     * total hoser (like flex itself) wants
X			     * to call the scanner after we return the
X			     * YY_NULL, it'll still work - another YY_NULL
X 			     * will get returned.
X			     */
X			    yy_c_buf_p = yy_b_buf_p;
X			    return ( YY_NULL );
X			    }
X
X			else
X			    goto new_file;
X			}
X			break;
X
X		    case EOB_ACT_RESTART_SCAN:
X			yy_c_buf_p = yy_b_buf_p;
X
X			YY_DO_BEFORE_RESTART;
X			break;
X
X		    case EOB_ACT_LAST_MATCH:
X			yy_c_buf_p = &yy_ch_buf[yy_n_chars];
X
X			yy_current_state = yy_get_previous_state();
X
X			YY_DO_BEFORE_ACTION;
X
X			goto do_action;
X		    }
X		break;
X
X	    default:
X		printf( "action # %d\n", yy_act );
X		YY_FATAL_ERROR( "fatal flex scanner internal error" );
X	    }
X	}
X    }
X
X
X/* yy_get_next_buffer - try to read in new buffer
X *
X * synopsis
X *     int yy_get_next_buffer();
X *     
X * returns a code representing an action
X *     EOB_ACT_LAST_MATCH - 
X *     EOB_ACT_RESTART_SCAN - restart the scanner
X *     EOB_ACT_END_OF_FILE - end of file
X */
X
Xstatic int yy_get_next_buffer()
X
X    {
X    if ( yy_c_buf_p != &yy_ch_buf[yy_n_chars + 1] )
X	{
X	YY_FATAL_ERROR( "NULL in input" );
X	/*NOTREACHED*/
X	}
X
X    else
X	{ /* try to read more data */
X	register char *dest = yy_ch_buf;
X	register char *source = yy_b_buf_p - 1; /* copy prev. char, too */
X	register int number_to_move, i;
X	int ret_val;
X	
X	/* first move last chars to start of buffer */
X	number_to_move = yy_c_buf_p - yy_b_buf_p;
X
X	for ( i = 0; i < number_to_move; ++i )
X	    *(dest++) = *(source++);
X
X	if ( yy_eof_has_been_seen )
X	    /* don't do the read, it's not guaranteed to return an EOF,
X	     * just force an EOF
X	     */
X	    yy_n_chars = 0;
X
X	else
X	    /* read in more data */
X	    YY_INPUT( (&yy_ch_buf[number_to_move]), yy_n_chars,
X		      YY_BUF_SIZE - number_to_move - 1 );
X
X	if ( yy_n_chars == 0 )
X	    {
X	    if ( number_to_move == 1 )
X		ret_val = EOB_ACT_END_OF_FILE;
X	    else
X		ret_val = EOB_ACT_LAST_MATCH;
X
X	    yy_eof_has_been_seen = 1;
X	    }
X
X	else
X	    ret_val = EOB_ACT_RESTART_SCAN;
X
X	yy_n_chars += number_to_move;
X	yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
X	yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
X
X	/* yy_b_buf_p begins at the second character in
X	 * yy_ch_buf; the first character is the one which
X	 * preceded it before reading in the latest buffer;
X	 * it needs to be kept around in case it's a
X	 * newline, so yy_get_previous_state() will have
X	 * with '^' rules active
X	 */
X
X	yy_b_buf_p = &yy_ch_buf[1];
X
X	return ( ret_val );
X	}
X    }
X
X
X/* yy_get_previous_state - get the state just before the eob char was reached
X *
X * synopsis
X *     YY_CS_TYPE yy_get_previous_state();
X */
X
Xstatic YY_CS_TYPE yy_get_previous_state()
X
X    {
X    register YY_CS_TYPE yy_cur_state;
X    register char *yy_temp_char_ptr;
X
X    YY_FIND_START_STATE( yy_cur_state );
X
X    for ( yy_temp_char_ptr = yy_b_buf_p; yy_temp_char_ptr < yy_c_buf_p; )
X	YY_GET_NEXT_STATE;
X
X    return ( yy_cur_state );
X    }
X
X
Xstatic unput( c )
Xint c;
X
X    {
X    YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
X
X    if ( yy_c_buf_p < yy_ch_buf + 2 )
X	{ /* need to shift things up to make room */
X	register int number_to_move = yy_n_chars + 2; /* +2 for EOB chars */
X	register char *dest = &yy_ch_buf[YY_BUF_SIZE + 2];
X	register char *source = &yy_ch_buf[number_to_move];
X
X	while ( source > yy_ch_buf )
X	    *--dest = *--source;
X
X	yy_c_buf_p += dest - source;
X	yy_b_buf_p += dest - source;
X
X	if ( yy_c_buf_p < yy_ch_buf + 2 )
X	    YY_FATAL_ERROR( "flex scanner push-back overflow" );
X	}
X
X    if ( yy_c_buf_p > yy_b_buf_p && yy_c_buf_p[-1] == '\n' )
X	yy_c_buf_p[-2] = '\n';
X
X    *--yy_c_buf_p = c;
X
X    YY_DO_BEFORE_ACTION; /* set up yytext again */
X    }
X
X
Xstatic int input()
X
X    {
X    int c;
X
X    YY_DO_BEFORE_SCAN;
X
X    if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
X	{ /* need more input */
X	yy_b_buf_p = yy_c_buf_p;
X	++yy_c_buf_p;
X
X	switch ( yy_get_next_buffer() )
X	    {
X	    /* this code, unfortunately, is somewhat redundant with
X	     * that above
X	     */
X	    case EOB_ACT_END_OF_FILE:
X		{
X		if ( yywrap() )
X		    {
X		    yy_c_buf_p = yy_b_buf_p;
X		    return ( EOF );
X		    }
X
X		yy_ch_buf[0] = '\n';
X		yy_n_chars = 1;
X		yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
X		yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
X		yy_eof_has_been_seen = 0;
X
X		YY_FAST_INIT;
X
X		return ( input() );
X		}
X		break;
X
X	    case EOB_ACT_RESTART_SCAN:
X		yy_c_buf_p = yy_b_buf_p;
X		break;
X
X	    case EOB_ACT_LAST_MATCH:
X		YY_FATAL_ERROR( "unexpected last match in input()" );
X	    }
X	}
X
X    c = *yy_c_buf_p++ & BYTEMASK;
X
X    YY_DO_BEFORE_RESTART;
X
X    return ( c );
X    }
SHAR_EOF
if test 9560 -ne "`wc -c < 'flex.fastskel'`"
then
	echo shar: error transmitting "'flex.fastskel'" '(should have been 9560 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'flex.skel'" '(6916 characters)'
if test -f 'flex.skel'
then
	echo shar: will not over-write existing file "'flex.skel'"
else
sed 's/^X//' << \SHAR_EOF > 'flex.skel'
X/* A lexical scanner generated by flex */
X
X#include "flexskeldef.h"
X
X%% section 1 code and data tables for DFA go here
X
X/* these declarations have to come after the section 1 code or lint gets
X * confused about whether the variables are used
X */
XFILE *yyin = stdin, *yyout = stdout;
X
X/* these variables are all declared out here so that section 3 code can
X * manipulate them
X */
Xstatic int yy_start, yy_b_buf_p, yy_c_buf_p, yy_e_buf_p;
Xstatic int yy_saw_eof, yy_init = 1;
X
X/* yy_ch_buf has to be 1 character longer than YY_BUF_SIZE, since when
X * setting up yytext we can try to put a '\0' just past the end of the
X * matched text
X */
X#ifdef MALLOC_BUFFERS
Xstatic char *yy_ch_buf = 0L;
Xstatic int *yy_st_buf = 0L;
X#else
Xstatic char yy_ch_buf[YY_BUF_SIZE + 1];
Xstatic int yy_st_buf[YY_BUF_SIZE];
X#endif
Xstatic char yy_hold_char;
Xchar *yytext;
Xstatic int yyleng;
X
XYY_DECL
X    {
X    int yy_n_chars, yy_lp, yy_iii, yy_buf_pos, yy_act;
X
X%% user's declarations go here
X
X#ifdef MALLOC_BUFFERS
X	if(yy_ch_buf == 0L){
X		yy_ch_buf = (char *)malloc(YY_BUF_SIZE + 1);
X		yy_st_buf = (int *)malloc(YY_BUF_SIZE * sizeof(int));
X		if(yy_ch_buf == 0L || yy_st_buf == 0L){
X			fprintf( stderr, "Out of memory\n");
X			exit(-1);
X		}
X	}
X#endif
X    if ( yy_init )
X	{
X	YY_INIT;
X	yy_start = 1;
X	yy_init = 0;
X	}
X
X    goto get_next_token;
X
Xdo_action:
X    for ( ; ; )
X	{
X	YY_DO_BEFORE_ACTION
X
X#ifdef FLEX_DEBUG
X	fprintf( stderr, "--accepting rule #%d\n", yy_act );
X#endif
X	switch ( yy_act )
X	    {
X%% actions go here
X
Xcase YY_NEW_FILE:
Xbreak; /* begin reading from new file */
X
Xcase YY_DO_DEFAULT:
XYY_DEFAULT_ACTION;
Xbreak;
X
Xcase YY_END_TOK:
Xreturn ( YY_END_TOK );
X
Xdefault:
XYY_FATAL_ERROR( "fatal flex scanner internal error" );
X	    }
X
Xget_next_token:
X	{
X	register int yy_curst;
X	register char yy_sym;
X
X	YY_DO_BEFORE_SCAN
X
X	/* set up to begin running DFA */
X
X	yy_curst = yy_start;
X
X	if ( yy_ch_buf[yy_c_buf_p] == '\n' )
X	    ++yy_curst;
X
X	/* yy_b_buf_p points to the position in yy_ch_buf
X	 * of the start of the current run.
X	 */
X
X	yy_b_buf_p = yy_c_buf_p + 1;
X
X	do /* until the machine jams */
X	    {
X	    if ( yy_c_buf_p == yy_e_buf_p )
X		{ /* need more input */
X		if ( yy_e_buf_p >= YY_BUF_LIM )
X		    { /* not enough room to do another read */
X		    /* see if we can make some room for more chars */
X
X		    yy_n_chars = yy_e_buf_p - yy_b_buf_p;
X
X		    if ( yy_n_chars >= 0 )
X			/* shift down buffer to make room */
X			for ( yy_iii = 0; yy_iii <= yy_n_chars; ++yy_iii )
X			    {
X			    yy_buf_pos = yy_b_buf_p + yy_iii;
X			    yy_ch_buf[yy_iii] = yy_ch_buf[yy_buf_pos];
X			    yy_st_buf[yy_iii] = yy_st_buf[yy_buf_pos];
X			    }
X
X		    yy_b_buf_p = 0;
X		    yy_e_buf_p = yy_n_chars;
X
X		    if ( yy_e_buf_p >= YY_BUF_LIM )
X			YY_FATAL_ERROR( "flex input buffer overflowed" );
X
X		    yy_c_buf_p = yy_e_buf_p;
X		    }
X
X		else if ( yy_saw_eof )
X		    {
Xsaweof:		    if ( yy_b_buf_p > yy_e_buf_p )
X			{
X			if ( yywrap() )
X			    {
X			    yy_act = YY_END_TOK;
X			    goto do_action;
X			    }
X			
X			else
X			    {
X			    YY_INIT;
X			    yy_act = YY_NEW_FILE;
X			    goto do_action;
X			    }
X			}
X
X		    else /* do a jam to eat up more input */
X			{
X#ifndef FLEX_INTERACTIVE_SCANNER
X			/* we're going to decrement yy_c_buf_p upon doing
X			 * the jam.  In this case, that's wrong, since
X			 * it points to the last non-jam character.  So
X			 * we increment it now to counter the decrement.
X			 */
X			++yy_c_buf_p;
X#endif
X			break;
X			}
X		    }
X
X		YY_INPUT( (yy_ch_buf + yy_c_buf_p + 1), yy_n_chars,
X			  YY_MAX_LINE );
X
X		if ( yy_n_chars == YY_NULL )
X		    {
X		    if ( yy_saw_eof )
X	YY_FATAL_ERROR( "flex scanner saw EOF twice - shouldn't happen" );
X		    yy_saw_eof = 1;
X		    goto saweof;
X		    }
X
X		yy_e_buf_p += yy_n_chars;
X		}
X
X	    ++yy_c_buf_p;
X
X#ifdef FLEX_USE_ECS
X	    yy_sym = e[(yy_ch_buf[yy_c_buf_p] & BYTEMASK)];
X#else
X	    yy_sym = yy_ch_buf[yy_c_buf_p];
X#endif
X
X#ifdef FLEX_FULL_TABLE
X	    yy_curst = n[yy_curst][yy_sym];
X
X#else /* get next state from compressed table */
X
X	    while ( c[b[yy_curst] + yy_sym] != yy_curst )
X		{
X		yy_curst = d[yy_curst];
X
X#ifdef FLEX_USE_MECS
X		/* we've arrange it so that templates are never chained
X		 * to one another.  This means we can afford make a
X		 * very simple test to see if we need to convert to
X		 * yy_sym's meta-equivalence class without worrying
X		 * about erroneously looking up the meta-equivalence
X		 * class twice
X		 */
X
X		if ( yy_curst >= YY_TEMPLATE )
X		    yy_sym = m[yy_sym];
X#endif
X		}
X
X	    yy_curst = n[b[yy_curst] + yy_sym];
X
X#endif
X
X	    yy_st_buf[yy_c_buf_p] = yy_curst;
X
X	    }
X#ifdef FLEX_INTERACTIVE_SCANNER
X	while ( b[yy_curst] != YY_JAM_BASE );
X#else
X	while ( yy_curst != YY_JAM );
X	--yy_c_buf_p; /* put back character we jammed on */
X
X#endif
X
X	if ( yy_c_buf_p >= yy_b_buf_p )
X	    { /* we matched some text */
X	    yy_curst = yy_st_buf[yy_c_buf_p];
X	    yy_lp = l[yy_curst];
X
X#ifdef FLEX_REJECT_ENABLED
Xfind_rule: /* we branch to this label when doing a REJECT */
X#endif
X
X	    for ( ; ; ) /* until we find what rule we matched */
X		{
X#ifdef FLEX_REJECT_ENABLED
X		if ( yy_lp && yy_lp < l[yy_curst + 1] )
X		    {
X		    yy_act = a[yy_lp];
X		    goto do_action; /* "continue 2" */
X		    }
X#else
X		if ( yy_lp )
X		    {
X		    yy_act = yy_lp;
X		    goto do_action; /* "continue 2" */
X		    }
X#endif
X
X		if ( --yy_c_buf_p < yy_b_buf_p )
X		    break;
X
X		yy_curst = yy_st_buf[yy_c_buf_p];
X		yy_lp = l[yy_curst];
X		}
X	    }
X
X	/* if we got this far, then we didn't find any accepting
X	 * states
X	 */
X
X	/* so that the default applies to the first char read */
X	++yy_c_buf_p;
X
X	yy_act = YY_DO_DEFAULT;
X	}
X	}
X
X    /*NOTREACHED*/
X    }
X
X
Xstatic int unput( c )
Xchar c;
X
X    {
X    YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
X
X    if ( yy_c_buf_p == 0 )
X	{
X	register int i;
X	register int yy_buf_pos = YY_BUF_MAX;
X
X	for ( i = yy_e_buf_p; i >= yy_c_buf_p; --i )
X	    {
X	    yy_ch_buf[yy_buf_pos] = yy_ch_buf[i];
X	    yy_st_buf[yy_buf_pos] = yy_st_buf[i];
X	    --yy_buf_pos;
X	    }
X
X	yy_c_buf_p = YY_BUF_MAX - yy_e_buf_p;
X	yy_e_buf_p = YY_BUF_MAX;
X	}
X
X    if ( yy_c_buf_p <= 0 )
X	YY_FATAL_ERROR( "flex scanner push-back overflow" );
X
X    if ( yy_c_buf_p >= yy_b_buf_p && yy_ch_buf[yy_c_buf_p] == '\n' )
X	yy_ch_buf[yy_c_buf_p - 1] = '\n';
X
X    yy_ch_buf[yy_c_buf_p--] = c;
X
X    YY_DO_BEFORE_ACTION; /* set up yytext again */
X    }
X
X
Xstatic int input()
X
X    {
X    int c;
X
X    YY_DO_BEFORE_SCAN
X
X    if ( yy_c_buf_p == yy_e_buf_p )
X	{ /* need more input */
X	int yy_n_chars;
X
X	/* we can throw away the entire current buffer */
X	if ( yy_saw_eof )
X	    {
X	    if ( yywrap() )
X		return ( EOF );
X
X	    YY_INIT;
X	    }
X
X	yy_b_buf_p = 0;
X	YY_INPUT( yy_ch_buf, yy_n_chars, YY_MAX_LINE );
X
X	if ( yy_n_chars == YY_NULL )
X	    {
X	    yy_saw_eof = 1;
X
X	    if ( yywrap() )
X		return ( EOF );
X
X	    YY_INIT;
X
X	    return ( input() );
X	    }
X
X	yy_c_buf_p = -1;
X	yy_e_buf_p = yy_n_chars - 1;
X	}
X
X    c = yy_ch_buf[++yy_c_buf_p];
X
X    YY_DO_BEFORE_ACTION;
X
X    return ( c & BYTEMASK);
X    }
SHAR_EOF
if test 6916 -ne "`wc -c < 'flex.skel'`"
then
	echo shar: error transmitting "'flex.skel'" '(should have been 6916 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 1 ---

earleh@eleazar.dartmouth.edu (Earle R. Horton) (06/30/88)

[Flex for the Mac - part 2 of 7]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	flex/flex.1
#	flex/flex.man.page
# This archive created: Wed Jun 29 07:03:13 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'flex.1'" '(15558 characters)'
if test -f 'flex.1'
then
	echo shar: will not over-write existing file "'flex.1'"
else
sed 's/^X//' << \SHAR_EOF > 'flex.1'
X.TH FLEX 1 "13 May 1987"
X.SH NAME
Xflex - fast lexical analyzer generator
X.SH SYNOPSIS
X.B flex
X[
X.B -dfirstvFILT -c[efmF] -Sskeleton_file
X] [ 
X.I filename
X]
X.SH DESCRIPTION
X.I flex
Xis a rewrite of
X.I lex
Xintended to right some of that tool's deficiencies: in particular,
X.I flex
Xgenerates lexical analyzers much faster, and the analyzers use
Xsmaller tables and run faster.
X.SH OPTIONS
XIn addition to lex's
X.B -t
Xflag, flex has the following options:
X.TP
X.B -d
Xmakes the generated scanner run in
X.I debug
Xmode.  Whenever a pattern is recognized the scanner will
Xwrite to
X.I stderr
Xa line of the form:
X.nf
X
X    --accepting rule #n
X
X.fi
XRules are numbered sequentially with the first one being 1.
X.TP
X.B -f
Xhas the same effect as lex's -f flag (do not compress the scanner
Xtables); the mnemonic changes from
X.I fast compilation
Xto (take your pick)
X.I full table
Xor
X.I fast scanner.
XThe actual compilation takes
X.I longer,
Xsince flex is I/O bound writing out the big table.
X.IP
XThis option is equivalent to
X.B -cf
X(see below).
X.TP
X.B -i
Xinstructs flex to generate a
X.I case-insensitive
Xscanner.  The case of letters given in the flex input patterns will
Xbe ignored, and the rules will be matched regardless of case.  The
Xmatched text given in
X.I yytext
Xwill have the preserved case (i.e., it will not be folded).
X.TP
X.B -r
Xspecifies that the scanner uses the
X.B REJECT
Xaction.
X.TP
X.B -s
Xcauses the
X.I default rule
X(that unmatched scanner input is echoed to
X.I stdout)
Xto be suppressed.  If the scanner encounters input that does not
Xmatch any of its rules, it aborts with an error.  This option is
Xuseful for finding holes in a scanner's rule set.
X.TP
X.B -v
Xhas the same meaning as for lex (print to
X.I stderr
Xa summary of statistics of the generated scanner).  Many more statistics
Xare printed, though, and the summary spans several lines.  Most
Xof the statistics are meaningless to the casual flex user.
X.TP
X.B -F
Xspecifies that the
X.ul
Xfast
Xscanner table representation should be used.  This representation is
Xabout as fast as the full table representation
X.ul
X(-f),
Xand for some sets of patterns will be considerably smaller (and for
Xothers, larger).  In general, if the pattern set contains both "keywords"
Xand a catch-all, "identifier" rule, such as in the set:
X.nf
X
X	"case"    return ( TOK_CASE );
X	"switch"  return ( TOK_SWITCH );
X	...
X	"default" return ( TOK_DEFAULT );
X	[a-z]+    return ( TOK_ID );
X
X.fi
Xthen you're better off using the full table representation.  If only
Xthe "identifier" rule is present and you then use a hash table or some such
Xto detect the keywords, you're better off using
X.ul
X-F.
X.IP
XThis option is equivalent to
X.B -cF
X(see below).
X.TP
X.B -I
Xinstructs flex to generate an
X.I interactive
Xscanner.  Normally, scanners generated by flex always look ahead one character
Xbefore deciding that a rule has been matched.  At the possible cost of some
Xscanning overhead (it's not clear that more overhead is involved), flex will
Xgenerate a scanner which only looks ahead when needed.  Such scanners are
Xcalled
X.I interactive
Xbecause if you want to write a scanner for an interactive system such
Xas a command shell, you will probably want the user's input to be terminated
Xwith a newline, and without
X.B -I
Xthe user will have to type a character in addition to the newline in order
Xto have the newline recognized.  This leads to dreadful interactive performance.
X.IP
XIf all this seems to confusing, here's the general rule: if a human will
Xbe typing in input to your scanner, use
X.B -I,
Xotherwise don't; if you don't care about how fast your scanners run and
Xdon't want to make any assumptions about the input to your scanner,
Xalways use
X.B -I.
X.IP
XNote,
X.B -I
Xcannot be used in conjunction with
X.I full
Xor
X.I fast tables,
Xi.e., the
X.B -f, -F, -cf,
Xor
X.B -cF
Xflags.
X.TP
X.B -L
Xinstructs flex to not generate
X.B #line
Xdirectives (see below).
X.TP
X.B -T
Xmakes flex run in
X.I trace
Xmode.  It will generate a lot of messages to standard out concerning
Xthe form of the input and the resultant non-deterministic and deterministic
Xfinite automatons.  This option is mostly for use in maintaining flex.
X.TP 
X.B -c[efmF]
Xcontrols the degree of table compression.
X.B -ce
Xdirects flex to construct
X.I equivalence classes,
Xi.e., sets of characters
Xwhich have identical lexical properties (for example, if the only
Xappearance of digits in the flex input is in the character class
X"[0-9]" then the digits '0', '1', ..., '9' will all be put
Xin the same equivalence class).
X.B -cf
Xspecifies that the
X.I full
Xscanner tables should be generated - flex should not compress the
Xtables by taking advantages of similar transition functions for
Xdifferent states.
X.B -cF
Xspecifies that the alternate fast scanner representation (described
Xabove under the
X.B -F
Xflag)
Xshould be used.
X.B -cm
Xdirects flex to construct
X.I meta-equivalence classes,
Xwhich are sets of equivalence classes (or characters, if equivalence
Xclasses are not being used) that are commonly used together.
XA lone
X.B -c
Xspecifies that the scanner tables should be compressed but neither
Xequivalence classes nor meta-equivalence classes should be used.
X.IP
XThe options
X.B -cf
Xor
X.B -cF
Xand
X.B -cm
Xdo not make sense together - there is no opportunity for meta-equivalence
Xclasses if the table is not being compressed.  Otherwise the options
Xmay be freely mixed.
X.IP
XThe default setting is
X.B -cem
Xwhich specifies that flex should generate equivalence classes
Xand meta-equivalence classes.  This setting provides the highest
Xdegree of table compression.  You can trade off
Xfaster-executing scanners at the cost of larger tables with
Xthe following generally being true:
X.nf
X
X    slowest            smallest
X               -cem
X               -ce
X               -cm
X               -c
X               -c{f,F}e
X               -c{f,F}
X    fastest            largest
X
X.fi
X.TP
X.B -Sskeleton_file
Xoverrides the default skeleton file from which flex constructs
Xits scanners.  You'll never need this option unless you are doing
Xflex maintenance or development.
X.SH INCOMPATIBILITIES WITH LEX
X.I flex
Xis fully compatible with
X.I lex
Xwith the following exceptions:
X.IP -
XThere is no run-time library to link with.  You needn't
Xspecify
X.I -ll
Xwhen linking, and you must supply a main program.  (Hacker's note: since
Xthe lex library contains a main() which simply calls yylex(), you actually
X.I can
Xbe lazy and not supply your own main program and link with
X.I -ll.)
X.IP -
Xlex's
X.B %r
X(Ratfor scanners) and
X.B %t
X(translation table) options
Xare not supported.
X.IP -
XThe do-nothing
X.ul
X-n
Xflag is not supported.
X.IP -
XWhen definitions are expanded, flex encloses them in parentheses.
XWith lex, the following
X.nf
X
X    NAME    [A-Z][A-Z0-9]*
X    %%
X    foo{NAME}?      printf( "Found it\\n" );
X    %%
X
X.fi
Xwill not match the string "foo" because when the macro
Xis expanded the rule is equivalent to "foo[A-Z][A-Z0-9]*?"
Xand the precedence is such that the '?' is associated with
X"[A-Z0-9]*".  With flex, the rule will be expanded to
X"foo([A-z][A-Z0-9]*)?" and so the string "foo" will match.
X.IP -
X.B yymore()
Xis not supported.
X.IP -
XThe undocumented lex-scanner internal variable
X.B yylineno
Xis not supported.
X.IP -
XIf your input uses
X.B REJECT,
Xyou must run flex with the
X.B -r
Xflag.  If you leave out the flag, the scanner will abort at run-time
Xwith a message that the scanner was compiled without the flag being
Xspecified.
X.IP -
XThe
X.B input()
Xroutine is not redefinable, though may be called to read characters
Xfollowing whatever has been matched by a rule.  If
X.B input()
Xencounters and end-of-file the normal
X.B yywrap()
Xprocessing is done.  A ``real'' end-of-file is returned as
X.I EOF.
X.IP
XInput can be controlled by redefining the
X.B YY_INPUT
Xmacro.
XYY_INPUT's calling sequence is "YY_INPUT(buf,result,max_size)".  Its
Xaction is to place up to max_size characters in the character buffer "buf"
Xand return in the integer variable "result" either the
Xnumber of characters read or the constant YY_NULL (0 on Unix systems)
Xsystems) to indicate EOF.  The default YY_INPUT reads from the
Xfile-pointer "yyin" (which is by default
X.I stdin),
Xso if you
Xjust want to change the input file, you needn't redefine
XYY_INPUT - just point yyin at the input file.
X.IP
XA sample redefinition of YY_INPUT (in the first section of the input
Xfile):
X.nf
X
X    %{
X    #undef YY_INPUT
X    #define YY_INPUT(buf,result,max_size) \\
X        result = (buf[0] = getchar()) == EOF ? YY_NULL : 1;
X    %}
X
X.fi
XYou also can add in things like counting keeping track of the
Xinput line number this way; but don't expect your scanner to
Xgo very fast.
X.IP -
X.B output()
Xis not supported.
XOutput from the ECHO macro is done to the file-pointer
X"yyout" (default
X.I stdout).
X.IP -
XTrailing context is restricted to patterns which have either
Xa fixed-sized leading part or a fixed-sized trailing part.
XFor example, "a*/b" and "a/b*" are okay, but not "a*/b*".
XThis restriction is due to a bug in the trailing context
Xalgorithm given in
X.I Principles of Compiler Design
X(and
X.I Compilers - Principles, Techniques, and Tools)
Xwhich can result in mismatches.  Try the following lex program
X.nf
X
X    %%
X    x+/xy           printf( "I found \\"%s\\"\\n", yytext );
X
X.fi
Xon the input "xxy".  (If anyone knows of a fast algorithm for
Xfinding the beginning of trailing context for an arbitrary
Xpair of regular expressions, please let me know!)
XIf you must have arbitrary trailing context, you can use
X.B yyless()
Xto effect it.
X.IP -
Xflex reads only one input file, while lex's input is made
Xup of the concatenation of its input files.
X.SH ENHANCEMENTS
X.IP -
X.I Exclusive start-conditions
Xcan be declared by using
X.B %x
Xinstead of
X.B %s.
XThese start-conditions have the property that when they are active,
X.I no other rules are active.
XThus a set of rules governed by the same exclusive start condition
Xdescribe a scanner which is independent of any of the other rules in
Xthe flex input.  This feature makes it easy to specify "mini-scanners"
Xwhich scan portions of the input that are syntactically different
Xfrom the rest (e.g., comments).
X.IP -
Xflex dynamically resizes its internal tables, so directives like "%a 3000"
Xare not needed when specifying large scanners.
X.IP -
XThe scanning routine generated by flex is declared using the macro
X.B YY_DECL.
XBy redefining this macro you can change the routine's name and
Xits calling sequence.  For example, you could use:
X.nf
X
X    #undef YY_DECL
X    #define YY_DECL float lexscan( a, b ) float a, b;
X
X.fi
Xto give it the name
X.I lexscan,
Xreturning a float, and taking two floats as arguments.
X.IP -
Xflex generates
X.B #line
Xdirectives mapping lines in the output to
Xtheir origin in the input file.
X.IP -
XYou can put multiple actions on the same line, separated with
Xsemi-colons.  With lex, the following
X.nf
X
X    foo    handle_foo(); return 1;
X
X.fi
Xis truncated to
X.nf
X
X    foo    handle_foo();
X
X.fi
Xflex does not truncate the action.  Actions that are not enclosed in
Xbraces are terminated at the end of the line.
X.IP -
XActions can be begun with
X.B %{
Xand terminated with
X.B %}.
XIn this case, flex does not count braces to figure out where the
Xaction ends - actions are terminated by the closing
X.B %}.
XThis feature is useful when the enclosed action has extraneous
Xbraces in it (usually in comments or inside inactive #ifdef's)
Xthat throw off the brace-count.
X.IP -
XAll of the scanner actions (e.g.,
X.B ECHO, yywrap ...)
Xexcept the
X.B unput()
Xand
X.B input()
Xroutines,
Xare written as macros, so they can be redefined if necessary
Xwithout requiring a separate library to link to.
X.SH FILES
X.TP
X.I flex.skel
Xskeleton scanner
X.TP
X.I flex.fastskel
Xskeleton scanner for -f and -F
X.TP
X.I flexskelcom.h
Xcommon definitions for skeleton files
X.TP
X.I flexskeldef.h
Xdefinitions for compressed skeleton file
X.TP
X.I fastskeldef.h
Xdefinitions for -f, -F skeleton file
X.SH "SEE ALSO"
X.LP
Xlex(1)
X.LP
XM. E. Lesk and E. Schmidt,
X.I LEX - Lexical Analyzer Generator
X.SH AUTHOR
XVern Paxson, with the help of many ideas and much inspiration from
XVan Jacobson.  Original version by Jef Poskanzer.  Fast table
Xrepresentation is a partial implementation of a design done by Van
XJacobson.  The implementation was done by Kevin Gong and Vern Paxson.
X.LP
XThanks to the many flex beta-testers, especially Casey Leedom,
XNick Christopher, Chris Faylor, Eric Goldman, Craig Leres, Mohamed el Lozy,
XEsmond Pitt, Jef Poskanzer, and Dave Tallman.  Thanks to John Gilmore,
XBob Mulcahy,
XRich Salz, and Richard Stallman for help with various distribution headaches.
X.LP
XSend comments to:
X.nf
X
X     Vern Paxson
X     Real Time Systems
X     Bldg. 46A
X     Lawrence Berkeley Laboratory
X     1 Cyclotron Rd.
X     Berkeley, CA 94720
X
X     (415) 486-6411
X
X     vern@lbl-{csam,rtsg}.arpa
X     ucbvax!lbl-csam.arpa!vern
X
X.fi
X.SH DIAGNOSTICS
X.LP
X.I flex scanner jammed -
Xa scanner compiled with
X.B -s
Xhas encountered an input string which wasn't matched by
Xany of its rules.
X.LP
X.I flex input buffer overflowed -
Xa scanner rule matched a string long enough to overflow the
Xscanner's internal input buffer (as large as
X.B BUFSIZ
Xin "/usr/include/stdio.h").  You can edit
X.I flexskelcom.h
Xand increase
X.B YY_BUF_SIZE
Xand
X.B YY_MAX_LINE
Xto increase this limit.
X.LP
X.I REJECT used and scanner was
X.I not generated using -r -
Xjust like it sounds.  Your scanner uses
X.B REJECT.
XYou must run flex on the scanner description using the
X.B -r
Xflag.
X.LP
X.I old-style lex command ignored -
Xthe flex input contains a lex command (e.g., "%n 1000") which
Xis being ignored.
X.SH BUGS
X.LP
XUse of unput() or input() trashes the current yytext and yyleng.
X.LP
XUse of unput() to push back more text than was matched can
Xresult in the pushed-back text matching a beginning-of-line ('^')
Xrule even though it didn't come at the beginning of the line.
X.LP
XNulls are not allowed in flex inputs or in the inputs to
Xscanners generated by flex.  Their presence generates fatal
Xerrors.
X.LP
XDo not mix trailing context with the '|' operator used to
Xspecify that multiple rules use the same action.  That is,
Xavoid constructs like:
X.nf
X
X        foo/bar      |
X        bletch       |
X        bugprone     { ... }
X
X.fi
XThey can result in subtle mismatches.  This is actually not
Xa problem if there is only one rule
Xusing trailing context and it is the first in the list (so the
Xabove example will actually work okay).  The
Xproblem is due to fall-through in the action switch statement,
Xcausing non-trailing-context rules to execute the
Xtrailing-context code of their fellow rules.  This should
Xbe fixed, as it's a nasty bug and not obvious.  The proper fix is
Xfor flex to spit out a FLEX_TRAILING_CONTEXT_USED #define and then
Xhave the backup logic in a separate table which is consulted for
Xeach rule-match, rather than as part of the rule action.  The
Xplace to do the tweaking is in add_accept() - any kind soul want
Xto be a hero?
X.LP
XThe pattern:
X.nf
X
X	x{3}
X
X.fi
Xis considered to be variable-length for the purposes of trailing
Xcontext, even though it has a clear fixed length.
X.LP
XDue to both buffering of input and read-ahead, you cannot intermix
Xcalls to, for example,
X.B getchar()
Xwith flex rules and expect it to work.  Call
X.B input()
Xinstead.
X.LP
XThe total table entries listed by the
X.B -v
Xflag excludes the number of table entries needed to determine
Xwhat rule has been matched.  The number of entries is equal
Xto the number of DFA states if the scanner was not compiled
Xwith
X.B -r,
Xand greater than the number of states if it was.
X.LP
XThe scanner run-time speeds have not been optimized as much
Xas they deserve.  Van Jacobson's work shows that the can go quite
Xa bit faster still.
SHAR_EOF
if test 15558 -ne "`wc -c < 'flex.1'`"
then
	echo shar: error transmitting "'flex.1'" '(should have been 15558 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'flex.man.page'" '(17746 characters)'
if test -f 'flex.man.page'
then
	echo shar: will not over-write existing file "'flex.man.page'"
else
sed 's/^X//' << \SHAR_EOF > 'flex.man.page'
X
X
X
XFLEX(1)             UNIX Programmer's Manual              FLEX(1)
X
X
X
XNAME
X     flex - fast lexical analyzer generator
X
XSYNOPSIS
X     flex [ -dfirstvFILT -c[efmF] -Sskeleton_file ] [ filename ]
X
XDESCRIPTION
X     flex is a rewrite of lex intended to right some of that
X     tool's deficiencies: in particular, flex generates lexical
X     analyzers much faster, and the analyzers use smaller tables
X     and run faster.
X
XOPTIONS
X     In addition to lex's -t flag, flex has the following
X     options:
X
X     -d   makes the generated scanner run in debug mode.  When-
X          ever a pattern is recognized the scanner will write to
X          stderr a line of the form:
X
X              --accepting rule #n
X
X          Rules are numbered sequentially with the first one
X          being 1.
X
X     -f   has the same effect as lex's -f flag (do not compress
X          the scanner tables); the mnemonic changes from fast
X          compilation to (take your pick) full table or fast
X          scanner. The actual compilation takes longer, since
X          flex is I/O bound writing out the big table.
X
X          This option is equivalent to -cf (see below).
X
X     -i   instructs flex to generate a case-insensitive scanner.
X          The case of letters given in the flex input patterns
X          will be ignored, and the rules will be matched regard-
X          less of case.  The matched text given in yytext will
X          have the preserved case (i.e., it will not be folded).
X
X     -r   specifies that the scanner uses the REJECT action.
X
X     -s   causes the default rule (that unmatched scanner input
X          is echoed to stdout) to be suppressed.  If the scanner
X          encounters input that does not match any of its rules,
X          it aborts with an error.  This option is useful for
X          finding holes in a scanner's rule set.
X
X     -v   has the same meaning as for lex (print to stderr a sum-
X          mary of statistics of the generated scanner).  Many
X          more statistics are printed, though, and the summary
X          spans several lines.  Most of the statistics are mean-
X          ingless to the casual flex user.
X
X     -F   specifies that the fast scanner table representation
X          should be used.  This representation is about as fast
X          as the full table representation (-f), and for some
X          sets of patterns will be considerably smaller (and for
X          others, larger).  In general, if the pattern set con-
X          tains both "keywords" and a catch-all, "identifier"
X          rule, such as in the set:
X
X               "case"    return ( TOK_CASE );
X               "switch"  return ( TOK_SWITCH );
X               ...
X               "default" return ( TOK_DEFAULT );
X               [a-z]+    return ( TOK_ID );
X
X          then you're better off using the full table representa-
X          tion.  If only the "identifier" rule is present and you
X          then use a hash table or some such to detect the key-
X          words, you're better off using -F.
X
X          This option is equivalent to -cF (see below).
X
X     -I   instructs flex to generate an interactive scanner.
X          Normally, scanners generated by flex always look ahead
X          one character before deciding that a rule has been
X          matched.  At the possible cost of some scanning over-
X          head (it's not clear that more overhead is involved),
X          flex will generate a scanner which only looks ahead
X          when needed.  Such scanners are called interactive
X          because if you want to write a scanner for an interac-
X          tive system such as a command shell, you will probably
X          want the user's input to be terminated with a newline,
X          and without -I the user will have to type a character
X          in addition to the newline in order to have the newline
X          recognized.  This leads to dreadful interactive perfor-
X          mance.
X
X          If all this seems to confusing, here's the general
X          rule: if a human will be typing in input to your
X          scanner, use -I, otherwise don't; if you don't care
X          about how fast your scanners run and don't want to make
X          any assumptions about the input to your scanner, always
X          use -I.
X
X          Note, -I cannot be used in conjunction with full or
X          fast tables, i.e., the -f, -F, -cf, or -cF flags.
X
X     -L   instructs flex to not generate #line directives (see
X          below).
X
X     -T   makes flex run in trace mode.  It will generate a lot
X          of messages to standard out concerning the form of the
X          input and the resultant non-deterministic and
X          deterministic finite automatons.  This option is mostly
X          for use in maintaining flex.
X
X     -c[efmF]
X          controls the degree of table compression.  -ce directs
X          flex to construct equivalence classes, i.e., sets of
X          characters which have identical lexical properties (for
X          example, if the only appearance of digits in the flex
X          input is in the character class "[0-9]" then the digits
X          '0', '1', ..., '9' will all be put in the same
X          equivalence class).  -cf specifies that the full
X          scanner tables should be generated - flex should not
X          compress the tables by taking advantages of similar
X          transition functions for different states.  -cF speci-
X          fies that the alternate fast scanner representation
X          (described above under the -F flag) should be used.  -
X          cm directs flex to construct meta-equivalence classes,
X          which are sets of equivalence classes (or characters,
X          if equivalence classes are not being used) that are
X          commonly used together.  A lone -c specifies that the
X          scanner tables should be compressed but neither
X          equivalence classes nor meta-equivalence classes should
X          be used.
X
X          The options -cf or -cF and -cm do not make sense
X          together - there is no opportunity for meta-equivalence
X          classes if the table is not being compressed.  Other-
X          wise the options may be freely mixed.
X
X          The default setting is -cem which specifies that flex
X          should generate equivalence classes and meta-
X          equivalence classes.  This setting provides the highest
X          degree of table compression.  You can trade off
X          faster-executing scanners at the cost of larger tables
X          with the following generally being true:
X
X              slowest            smallest
X                         -cem
X                         -ce
X                         -cm
X                         -c
X                         -c{f,F}e
X                         -c{f,F}
X              fastest            largest
X
X
X     -Sskeleton_file
X          overrides the default skeleton file from which flex
X          constructs its scanners.  You'll never need this option
X          unless you are doing flex maintenance or development.
X
XINCOMPATIBILITIES WITH LEX
X     flex is fully compatible with lex with the following excep-
X     tions:
X
X     -    There is no run-time library to link with.  You needn't
X          specify -ll when linking, and you must supply a main
X          program.  (Hacker's note: since the lex library con-
X          tains a main() which simply calls yylex(), you actually
X          can be lazy and not supply your own main program and
X          link with -ll.)
X
X     -    lex's %r (Ratfor scanners) and %t (translation table)
X          options are not supported.
X
X     -    The do-nothing -n flag is not supported.
X
X     -    When definitions are expanded, flex encloses them in
X          parentheses.  With lex, the following
X
X              NAME    [A-Z][A-Z0-9]*
X              %%
X              foo{NAME}?      printf( "Found it\n" );
X              %%
X
X          will not match the string "foo" because when the macro
X          is expanded the rule is equivalent to "foo[A-Z][A-Z0-
X          9]*?" and the precedence is such that the '?' is asso-
X          ciated with "[A-Z0-9]*".  With flex, the rule will be
X          expanded to "foo([A-z][A-Z0-9]*)?" and so the string
X          "foo" will match.
X
X     -    yymore() is not supported.
X
X     -    The undocumented lex-scanner internal variable yylineno
X          is not supported.
X
X     -    If your input uses REJECT, you must run flex with the
X          -r flag.  If you leave out the flag, the scanner will
X          abort at run-time with a message that the scanner was
X          compiled without the flag being specified.
X
X     -    The input() routine is not redefinable, though may be
X          called to read characters following whatever has been
X          matched by a rule.  If input() encounters and end-of-
X          file the normal yywrap() processing is done.  A
X          ``real'' end-of-file is returned as EOF.
X
X          Input can be controlled by redefining the YY_INPUT
X          macro.  YY_INPUT's calling sequence is
X          "YY_INPUT(buf,result,max_size)".  Its action is to
X          place up to max_size characters in the character buffer
X          "buf" and return in the integer variable "result"
X          either the number of characters read or the constant
X          YY_NULL (0 on Unix systems) systems) to indicate EOF.
X          The default YY_INPUT reads from the file-pointer "yyin"
X          (which is by default stdin), so if you just want to
X          change the input file, you needn't redefine YY_INPUT -
X          just point yyin at the input file.
X
X          A sample redefinition of YY_INPUT (in the first section
X          of the input file):
X
X              %{
X              #undef YY_INPUT
X              #define YY_INPUT(buf,result,max_size) \
X                  result = (buf[0] = getchar()) == EOF ? YY_NULL : 1;
X              %}
X
X          You also can add in things like counting keeping track
X          of the input line number this way; but don't expect
X          your scanner to go very fast.
X
X     -    output() is not supported.  Output from the ECHO macro
X          is done to the file-pointer "yyout" (default stdout).
X
X     -    Trailing context is restricted to patterns which have
X          either a fixed-sized leading part or a fixed-sized
X          trailing part.  For example, "a*/b" and "a/b*" are
X          okay, but not "a*/b*".  This restriction is due to a
X          bug in the trailing context algorithm given in Princi-
X          ples of Compiler Design (and Compilers - Principles,
X          Techniques, and Tools) which can result in mismatches.
X          Try the following lex program
X
X              %%
X              x+/xy           printf( "I found \"%s\"\n", yytext );
X
X          on the input "xxy".  (If anyone knows of a fast algo-
X          rithm for finding the beginning of trailing context for
X          an arbitrary pair of regular expressions, please let me
X          know!) If you must have arbitrary trailing context, you
X          can use yyless() to effect it.
X
X     -    flex reads only one input file, while lex's input is
X          made up of the concatenation of its input files.
X
XENHANCEMENTS
X     -    Exclusive start-conditions can be declared by using %x
X          instead of %s. These start-conditions have the property
X          that when they are active, no other rules are active.
X          Thus a set of rules governed by the same exclusive
X          start condition describe a scanner which is independent
X          of any of the other rules in the flex input.  This
X          feature makes it easy to specify "mini-scanners" which
X          scan portions of the input that are syntactically dif-
X          ferent from the rest (e.g., comments).
X
X     -    flex dynamically resizes its internal tables, so direc-
X          tives like "%a 3000" are not needed when specifying
X          large scanners.
X
X     -    The scanning routine generated by flex is declared
X          using the macro YY_DECL. By redefining this macro you
X          can change the routine's name and its calling sequence.
X          For example, you could use:
X
X              #undef YY_DECL
X              #define YY_DECL float lexscan( a, b ) float a, b;
X
X          to give it the name lexscan, returning a float, and
X          taking two floats as arguments.
X
X     -    flex generates #line directives mapping lines in the
X          output to their origin in the input file.
X
X     -    You can put multiple actions on the same line,
X          separated with semi-colons.  With lex, the following
X
X              foo    handle_foo(); return 1;
X
X          is truncated to
X
X              foo    handle_foo();
X
X          flex does not truncate the action.  Actions that are
X          not enclosed in braces are terminated at the end of the
X          line.
X
X     -    Actions can be begun with %{ and terminated with %}. In
X          this case, flex does not count braces to figure out
X          where the action ends - actions are terminated by the
X          closing %}. This feature is useful when the enclosed
X          action has extraneous braces in it (usually in comments
X          or inside inactive #ifdef's) that throw off the brace-
X          count.
X
X     -    All of the scanner actions (e.g., ECHO, yywrap ...)
X          except the unput() and input() routines, are written as
X          macros, so they can be redefined if necessary without
X          requiring a separate library to link to.
X
XFILES
X     flex.skel
X          skeleton scanner
X
X     flex.fastskel
X          skeleton scanner for -f and -F
X
X     flexskelcom.h
X          common definitions for skeleton files
X
X     flexskeldef.h
X          definitions for compressed skeleton file
X
X     fastskeldef.h
X          definitions for -f, -F skeleton file
X
XSEE ALSO
X     lex(1)
X
X     M. E. Lesk and E. Schmidt, LEX - Lexical Analyzer Generator
X
XAUTHOR
X     Vern Paxson, with the help of many ideas and much inspira-
X     tion from Van Jacobson.  Original version by Jef Poskanzer.
X     Fast table representation is a partial implementation of a
X     design done by Van Jacobson.  The implementation was done by
X     Kevin Gong and Vern Paxson.
X
X     Thanks to the many flex beta-testers, especially Casey Lee-
X     dom, Nick Christopher, Chris Faylor, Eric Goldman, Craig
X     Leres, Mohamed el Lozy, Esmond Pitt, Jef Poskanzer, and Dave
X     Tallman.  Thanks to John Gilmore, Bob Mulcahy, Rich Salz,
X     and Richard Stallman for help with various distribution
X     headaches.
X
X     Send comments to:
X
X          Vern Paxson
X          Real Time Systems
X          Bldg. 46A
X          Lawrence Berkeley Laboratory
X          1 Cyclotron Rd.
X          Berkeley, CA 94720
X
X          (415) 486-6411
X
X          vern@lbl-{csam,rtsg}.arpa
X          ucbvax!lbl-csam.arpa!vern
X
X
XDIAGNOSTICS
X     flex scanner jammed - a scanner compiled with -s has encoun-
X     tered an input string which wasn't matched by any of its
X     rules.
X
X     flex input buffer overflowed - a scanner rule matched a
X     string long enough to overflow the scanner's internal input
X     buffer (as large as BUFSIZ in "/usr/include/stdio.h").  You
X     can edit flexskelcom.h and increase YY_BUF_SIZE and
X     YY_MAX_LINE to increase this limit.
X
X     REJECT used and scanner was not generated using -r - just
X     like it sounds.  Your scanner uses REJECT. You must run flex
X     on the scanner description using the -r flag.
X
X     old-style lex command ignored - the flex input contains a
X     lex command (e.g., "%n 1000") which is being ignored.
X
XBUGS
X     Use of unput() or input() trashes the current yytext and
X     yyleng.
X
X     Use of unput() to push back more text than was matched can
X     result in the pushed-back text matching a beginning-of-line
X     ('^') rule even though it didn't come at the beginning of
X     the line.
X
X     Nulls are not allowed in flex inputs or in the inputs to
X     scanners generated by flex.  Their presence generates fatal
X     errors.
X
X     Do not mix trailing context with the '|' operator used to
X     specify that multiple rules use the same action.  That is,
X     avoid constructs like:
X
X             foo/bar      |
X             bletch       |
X             bugprone     { ... }
X
X     They can result in subtle mismatches.  This is actually not
X     a problem if there is only one rule using trailing context
X     and it is the first in the list (so the above example will
X     actually work okay).  The problem is due to fall-through in
X     the action switch statement, causing non-trailing-context
X     rules to execute the trailing-context code of their fellow
X     rules.  This should be fixed, as it's a nasty bug and not
X     obvious.  The proper fix is for flex to spit out a
X     FLEX_TRAILING_CONTEXT_USED #define and then have the backup
X     logic in a separate table which is consulted for each rule-
X     match, rather than as part of the rule action.  The place to
X     do the tweaking is in add_accept() - any kind soul want to
X     be a hero?
X
X     The pattern:
X
X          x{3}
X
X     is considered to be variable-length for the purposes of
X     trailing context, even though it has a clear fixed length.
X
X     Due to both buffering of input and read-ahead, you cannot
X     intermix calls to, for example, getchar() with flex rules
X     and expect it to work.  Call input() instead.
X
X     The total table entries listed by the -v flag excludes the
X     number of table entries needed to determine what rule has
X     been matched.  The number of entries is equal to the number
X     of DFA states if the scanner was not compiled with -r, and
X     greater than the number of states if it was.
X
X     The scanner run-time speeds have not been optimized as much
X     as they deserve.  Van Jacobson's work shows that they can go
X     quite a bit faster still.
SHAR_EOF
if test 17746 -ne "`wc -c < 'flex.man.page'`"
then
	echo shar: error transmitting "'flex.man.page'" '(should have been 17746 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 2 ---

macintosh@dhw68k.UUCP (07/01/88)

[Flex for the Mac - part 3 of 7]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	flex/alloca.a
#	flex/bzero.c
#	flex/ccl.c
#	flex/dfa.c
#	flex/ecs.c
#	flex/main.c
# This archive created: Wed Jun 29 07:03:15 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'alloca.a'" '(646 characters)'
if test -f 'alloca.a'
then
	echo shar: will not over-write existing file "'alloca.a'"
else
sed 's/^X//' << \SHAR_EOF > 'alloca.a'
X;;
X;; Alloca() for Macintosh Programmer's Workshop C.
X;; alloca(n) allocates n bytes of storage in the stack
X;; frame of the caller.
X;;
X	CASE ON
X	
Xalloca PROC EXPORT
X        move.l  (sp)+,a0        ; pop return address
X        move.l  (sp)+,d0        ; pop parameter = size in bytes
X        add.l   #3,d0       	; round size up to long word
X        and.l   #-4,d0        	; mask out lower two bits of size
X        sub.l   d0,sp           ; allocate by moving stack pointer
X        move.l  sp,d0           ; return pointer
X        add.l   #-4,sp          ; new top of stack
X        jmp     (a0)            ; return to caller
X        ENDP
X		END
X		
SHAR_EOF
if test 646 -ne "`wc -c < 'alloca.a'`"
then
	echo shar: error transmitting "'alloca.a'" '(should have been 646 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bzero.c'" '(84 characters)'
if test -f 'bzero.c'
then
	echo shar: will not over-write existing file "'bzero.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bzero.c'
Xbzero(x,size)
Xchar *x;
Xint size;
X{
X int i;
X for(i=0;i<size;i++){
X  *(x+i) = 0;
X }
X}
SHAR_EOF
if test 84 -ne "`wc -c < 'bzero.c'`"
then
	echo shar: error transmitting "'bzero.c'" '(should have been 84 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ccl.c'" '(2257 characters)'
if test -f 'ccl.c'
then
	echo shar: will not over-write existing file "'ccl.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ccl.c'
X/* ccl - routines for character classes */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include "flexdef.h"
X
X/* ccladd - add a single character to a ccl
X *
X * synopsis
X *    int cclp;
X *    char ch;
X *    ccladd( cclp, ch );
X */
X
Xccladd( cclp, ch )
Xint cclp;
Xchar ch;
X
X    {
X    int ind, len, newpos, i;
X
X    len = ccllen[cclp];
X    ind = cclmap[cclp];
X
X    /* check to see if the character is already in the ccl */
X
X    for ( i = 0; i < len; ++i )
X	if ( ccltbl[ind + i] == ch )
X	    return;
X
X    newpos = ind + len;
X
X    if ( newpos >= current_max_ccl_tbl_size )
X	{
X	current_max_ccl_tbl_size += MAX_CCL_TBL_SIZE_INCREMENT;
X
X	++num_reallocs;
X
X	ccltbl = reallocate_character_array( ccltbl, current_max_ccl_tbl_size );
X	}
X
X    ccllen[cclp] = len + 1;
X    ccltbl[newpos] = ch;
X    }
X
X
X/* cclinit - make an empty ccl
X *
X * synopsis
X *    int cclinit();
X *    new_ccl = cclinit();
X */
X
Xint cclinit()
X
X    {
X    if ( ++lastccl >= current_maxccls )
X	{
X	current_maxccls += MAXCCLS_INCREMENT;
X
X	++num_reallocs;
X
X	cclmap = reallocate_integer_array( cclmap, current_maxccls );
X	ccllen = reallocate_integer_array( ccllen, current_maxccls );
X	cclng = reallocate_integer_array( cclng, current_maxccls );
X	}
X
X    if ( lastccl == 1 )
X	/* we're making the first ccl */
X	cclmap[lastccl] = 0;
X
X    else
X	/* the new pointer is just past the end of the last ccl.  Since
X	 * the cclmap points to the \first/ character of a ccl, adding the
X	 * length of the ccl to the cclmap pointer will produce a cursor
X	 * to the first free space
X	 */
X	cclmap[lastccl] = cclmap[lastccl - 1] + ccllen[lastccl - 1];
X
X    ccllen[lastccl] = 0;
X    cclng[lastccl] = 0;	/* ccl's start out life un-negated */
X
X    return ( lastccl );
X    }
X
X
X/* cclnegate - negate a ccl
X *
X * synopsis
X *    int cclp;
X *    cclnegate( ccl );
X */
X
Xcclnegate( cclp )
Xint cclp;
X
X    {
X    cclng[cclp] = 1;
X    }
SHAR_EOF
if test 2257 -ne "`wc -c < 'ccl.c'`"
then
	echo shar: error transmitting "'ccl.c'" '(should have been 2257 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'dfa.c'" '(10776 characters)'
if test -f 'dfa.c'
then
	echo shar: will not over-write existing file "'dfa.c'"
else
sed 's/^X//' << \SHAR_EOF > 'dfa.c'
X/* dfa - DFA construction routines */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include "flexdef.h"
X
X/* epsclosure - construct the epsilon closure of a set of ndfa states
X *
X * synopsis
X *    int t[current_max_dfa_size], numstates, accset[accnum + 1], nacc;
X *    int hashval;
X *    int *epsclosure();
X *    t = epsclosure( t, &numstates, accset, &nacc, &hashval );
X *
X * NOTES
X *    the epsilon closure is the set of all states reachable by an arbitrary
X *  number of epsilon transitions which themselves do not have epsilon
X *  transitions going out, unioned with the set of states which have non-null
X *  accepting numbers.  t is an array of size numstates of nfa state numbers.
X *  Upon return, t holds the epsilon closure and numstates is updated.  accset
X *  holds a list of the accepting numbers, and the size of accset is given
X *  by nacc.  t may be subjected to reallocation if it is not large enough
X *  to hold the epsilon closure.
X *
X *    hashval is the hash value for the dfa corresponding to the state set
X */
X
Xint *epsclosure( t, ns_addr, accset, nacc_addr, hv_addr )
Xint *t, *ns_addr, accset[], *nacc_addr, *hv_addr;
X
X    {
X    register int stkpos, ns, tsp;
X    int numstates = *ns_addr, nacc, hashval, transsym, nfaccnum;
X    int stkend, nstate;
X    static int did_stk_init = false, *stk; 
X
X#define MARK_STATE(state) \
X	trans1[state] = trans1[state] - MARKER_DIFFERENCE;
X
X#define IS_MARKED(state) (trans1[state] < 0)
X
X#define UNMARK_STATE(state) \
X	trans1[state] = trans1[state] + MARKER_DIFFERENCE;
X
X#define CHECK_ACCEPT(state) \
X	{ \
X	nfaccnum = accptnum[state]; \
X	if ( nfaccnum != NIL ) \
X	    accset[++nacc] = nfaccnum; \
X	}
X
X#define DO_REALLOCATION \
X	{ \
X	current_max_dfa_size += MAX_DFA_SIZE_INCREMENT; \
X	++num_reallocs; \
X	t = reallocate_integer_array( t, current_max_dfa_size ); \
X	stk = reallocate_integer_array( stk, current_max_dfa_size ); \
X	} \
X
X#define PUT_ON_STACK(state) \
X	{ \
X	if ( ++stkend >= current_max_dfa_size ) \
X	    DO_REALLOCATION \
X	stk[stkend] = state; \
X	MARK_STATE(state) \
X	}
X
X#define ADD_STATE(state) \
X	{ \
X	if ( ++numstates >= current_max_dfa_size ) \
X	    DO_REALLOCATION \
X	t[numstates] = state; \
X	hashval = hashval + state; \
X	}
X
X#define STACK_STATE(state) \
X	{ \
X	PUT_ON_STACK(state) \
X	CHECK_ACCEPT(state) \
X	if ( nfaccnum != NIL || transchar[state] != SYM_EPSILON ) \
X	    ADD_STATE(state) \
X	}
X
X    if ( ! did_stk_init )
X	{
X	stk = allocate_integer_array( current_max_dfa_size );
X	did_stk_init = true;
X	}
X
X    nacc = stkend = hashval = 0;
X
X    for ( nstate = 1; nstate <= numstates; ++nstate )
X	{
X	ns = t[nstate];
X
X	/* the state could be marked if we've already pushed it onto
X	 * the stack
X	 */
X	if ( ! IS_MARKED(ns) )
X	    PUT_ON_STACK(ns)
X
X	CHECK_ACCEPT(ns)
X	hashval = hashval + ns;
X	}
X
X    for ( stkpos = 1; stkpos <= stkend; ++stkpos )
X	{
X	ns = stk[stkpos];
X	transsym = transchar[ns];
X
X	if ( transsym == SYM_EPSILON )
X	    {
X	    tsp = trans1[ns] + MARKER_DIFFERENCE;
X
X	    if ( tsp != NO_TRANSITION )
X		{
X		if ( ! IS_MARKED(tsp) )
X		    STACK_STATE(tsp)
X
X		tsp = trans2[ns];
X
X		if ( tsp != NO_TRANSITION )
X		    if ( ! IS_MARKED(tsp) )
X			STACK_STATE(tsp)
X		}
X	    }
X	}
X
X    /* clear out "visit" markers */
X
X    for ( stkpos = 1; stkpos <= stkend; ++stkpos )
X	{
X	if ( IS_MARKED(stk[stkpos]) )
X	    {
X	    UNMARK_STATE(stk[stkpos])
X	    }
X	else
X	    flexfatal( "consistency check failed in epsclosure()" );
X	}
X
X    *ns_addr = numstates;
X    *hv_addr = hashval;
X    *nacc_addr = nacc;
X
X    return ( t );
X    }
X
X
X
X/* increase_max_dfas - increase the maximum number of DFAs */
X
Xincrease_max_dfas()
X
X    {
X    int old_max = current_max_dfas;
X
X    current_max_dfas += MAX_DFAS_INCREMENT;
X
X    ++num_reallocs;
X
X    base = reallocate_integer_array( base, current_max_dfas );
X    def = reallocate_integer_array( def, current_max_dfas );
X    dfasiz = reallocate_integer_array( dfasiz, current_max_dfas );
X    accsiz = reallocate_integer_array( accsiz, current_max_dfas );
X    dhash = reallocate_integer_array( dhash, current_max_dfas );
X    todo = reallocate_integer_array( todo, current_max_dfas );
X    dss = reallocate_integer_pointer_array( dss, current_max_dfas );
X    dfaacc = reallocate_dfaacc_union( dfaacc, current_max_dfas );
X
X    /* fix up todo queue */
X    if ( todo_next < todo_head )
X	{ /* queue was wrapped around the end */
X	register int i;
X
X	for ( i = 0; i < todo_next; ++i )
X	    todo[old_max + i] = todo[i];
X	
X	todo_next += old_max;
X	}
X    }
X
X
X/* snstods - converts a set of ndfa states into a dfa state
X *
X * synopsis
X *    int sns[numstates], numstates, newds, accset[accnum + 1], nacc, hashval;
X *    int snstods();
X *    is_new_state = snstods( sns, numstates, accset, nacc, hashval, &newds );
X *
X * on return, the dfa state number is in newds.
X */
X
Xint snstods( sns, numstates, accset, nacc, hashval, newds_addr )
Xint sns[], numstates, accset[], nacc, hashval, *newds_addr;
X
X    {
X    int didsort = 0;
X    register int i, j;
X    int newds, *oldsns;
X    char *malloc();
X
X    for ( i = 1; i <= lastdfa; ++i )
X	if ( hashval == dhash[i] )
X	    {
X	    if ( numstates == dfasiz[i] )
X		{
X		oldsns = dss[i];
X
X		if ( ! didsort )
X		    {
X		    /* we sort the states in sns so we can compare it to
X		     * oldsns quickly.  we use bubble because there probably
X		     * aren't very many states
X		     */
X		    bubble( sns, numstates );
X		    didsort = 1;
X		    }
X
X		for ( j = 1; j <= numstates; ++j )
X		    if ( sns[j] != oldsns[j] )
X			break;
X
X		if ( j > numstates )
X		    {
X		    ++dfaeql;
X		    *newds_addr = i;
X		    return ( 0 );
X		    }
X
X		++hshcol;
X		}
X
X	    else
X		++hshsave;
X	    }
X
X    /* make a new dfa */
X
X    if ( ++lastdfa >= current_max_dfas )
X	increase_max_dfas();
X
X    newds = lastdfa;
X
X    if ( ! (dss[newds] = (int *) malloc( (unsigned) ((numstates + 1) * sizeof( int )) )) )
X	flexfatal( "dynamic memory failure in snstods()" );
X
X    /* if we haven't already sorted the states in sns, we do so now, so that
X     * future comparisons with it can be made quickly
X     */
X
X    if ( ! didsort )
X	bubble( sns, numstates );
X
X    for ( i = 1; i <= numstates; ++i )
X	dss[newds][i] = sns[i];
X
X    dfasiz[newds] = numstates;
X    dhash[newds] = hashval;
X
X    if ( nacc == 0 )
X	{
X	dfaacc[newds].dfaacc_state = 0;
X	accsiz[newds] = 0;
X	}
X
X    else if ( reject )
X	{
X	/* we sort the accepting set in increasing order so the disambiguating
X	 * rule that the first rule listed is considered match in the event of
X	 * ties will work.  We use a bubble sort since the list is probably
X	 * quite small.
X	 */
X
X	bubble( accset, nacc );
X
X	dfaacc[newds].dfaacc_state =
X	    (int) malloc( (unsigned) ((nacc + 1) * sizeof( int )) );
X
X	if ( ! dfaacc[newds].dfaacc_state )
X	    flexfatal( "dynamic memory failure in snstods()" );
X
X	/* save the accepting set for later */
X	for ( i = 1; i <= nacc; ++i )
X	    dfaacc[newds].dfaacc_set[i] = accset[i];
X
X	accsiz[newds] = nacc;
X	}
X
X    else
X	{ /* find lowest numbered rule so the disambiguating rule will work */
X	j = accnum + 1;
X
X	for ( i = 1; i <= nacc; ++i )
X	    if ( accset[i] < j )
X		j = accset[i];
X
X	dfaacc[newds].dfaacc_state = j;
X	}
X
X    *newds_addr = newds;
X
X    return ( 1 );
X    }
X
X
X/* symfollowset - follow the symbol transitions one step
X *
X * synopsis
X *    int ds[current_max_dfa_size], dsize, transsym;
X *    int nset[current_max_dfa_size], numstates;
X *    numstates = symfollowset( ds, dsize, transsym, nset );
X */
X
Xint symfollowset( ds, dsize, transsym, nset )
Xint ds[], dsize, transsym, nset[];
X
X    {
X    int ns, tsp, sym, i, j, lenccl, ch, numstates;
X    int ccllist;
X
X    numstates = 0;
X
X    for ( i = 1; i <= dsize; ++i )
X	{ /* for each nfa state ns in the state set of ds */
X	ns = ds[i];
X	sym = transchar[ns];
X	tsp = trans1[ns];
X
X	if ( sym < 0 )
X	    { /* it's a character class */
X	    sym = -sym;
X	    ccllist = cclmap[sym];
X	    lenccl = ccllen[sym];
X
X	    if ( cclng[sym] )
X		{
X		for ( j = 0; j < lenccl; ++j )
X		    { /* loop through negated character class */
X		    ch = ccltbl[ccllist + j] & BYTEMASK;
X
X		    if ( ch > transsym )
X			break;	/* transsym isn't in negated ccl */
X
X		    else if ( ch == transsym )
X			/* next 2 */ goto bottom;
X		    }
X
X		/* didn't find transsym in ccl */
X		nset[++numstates] = tsp;
X		}
X
X	    else
X		for ( j = 0; j < lenccl; ++j )
X		    {
X		    ch = ccltbl[ccllist + j] & BYTEMASK;
X
X		    if ( ch > transsym )
X			break;
X
X		    else if ( ch == transsym )
X			{
X			nset[++numstates] = tsp;
X			break;
X			}
X		    }
X	    }
X
X	else if ( sym >= 'A' && sym <= 'Z' && caseins )
X	    flexfatal( "consistency check failed in symfollowset" );
X
X	else if ( sym == SYM_EPSILON )
X	    { /* do nothing */
X	    }
X
X	else if ( ecgroup[sym] == transsym )
X	    nset[++numstates] = tsp;
X
Xbottom:
X	;
X	}
X
X    return ( numstates );
X    }
X
X
X/* sympartition - partition characters with same out-transitions
X *
X * synopsis
X *    integer ds[current_max_dfa_size], numstates, duplist[numecs];
X *    symlist[numecs];
X *    sympartition( ds, numstates, symlist, duplist );
X */
X
Xsympartition( ds, numstates, symlist, duplist )
Xint ds[], numstates, duplist[];
Xint symlist[];
X
X    {
X    int tch, i, j, k, ns, dupfwd[CSIZE + 1], lenccl, cclp, ich;
X
X    /* partitioning is done by creating equivalence classes for those
X     * characters which have out-transitions from the given state.  Thus
X     * we are really creating equivalence classes of equivalence classes.
X     */
X
X    for ( i = 1; i <= numecs; ++i )
X	{ /* initialize equivalence class list */
X	duplist[i] = i - 1;
X	dupfwd[i] = i + 1;
X	}
X
X    duplist[1] = NIL;
X    dupfwd[numecs] = NIL;
X
X    for ( i = 1; i <= numstates; ++i )
X	{
X	ns = ds[i];
X	tch = transchar[ns];
X
X	if ( tch != SYM_EPSILON )
X	    {
X	    if ( tch < -lastccl || tch > CSIZE )
X		flexfatal( "bad transition character detected in sympartition()" );
X
X	    if ( tch > 0 )
X		{ /* character transition */
X		mkechar( ecgroup[tch], dupfwd, duplist );
X		symlist[ecgroup[tch]] = 1;
X		}
X
X	    else
X		{ /* character class */
X		tch = -tch;
X
X		lenccl = ccllen[tch];
X		cclp = cclmap[tch];
X		mkeccl( ccltbl + cclp, lenccl, dupfwd, duplist, numecs );
X
X		if ( cclng[tch] )
X		    {
X		    j = 0;
X
X		    for ( k = 0; k < lenccl; ++k )
X			{
X			ich = ccltbl[cclp + k] & BYTEMASK;
X
X			for ( ++j; j < ich; ++j )
X			    symlist[j] = 1;
X			}
X
X		    for ( ++j; j <= numecs; ++j )
X			symlist[j] = 1;
X		    }
X
X		else
X		    for ( k = 0; k < lenccl; ++k )
X			{
X			ich = ccltbl[cclp + k] & BYTEMASK;
X			symlist[ich] = 1;
X			}
X		}
X	    }
X	}
X    }
SHAR_EOF
if test 10776 -ne "`wc -c < 'dfa.c'`"
then
	echo shar: error transmitting "'dfa.c'" '(should have been 10776 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ecs.c'" '(5206 characters)'
if test -f 'ecs.c'
then
	echo shar: will not over-write existing file "'ecs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ecs.c'
X/* ecs - equivalence class routines */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include "flexdef.h"
X
X/* ccl2ecl - convert character classes to set of equivalence classes
X *
X * synopsis
X *    ccl2ecl();
X */
X
Xccl2ecl()
X
X    {
X    int i, ich, newlen, cclp, ccls, cclmec;
X
X    for ( i = 1; i <= lastccl; ++i )
X	{
X	/* we loop through each character class, and for each character
X	 * in the class, add the character's equivalence class to the
X	 * new "character" class we are creating.  Thus when we are all
X	 * done, character classes will really consist of collections
X	 * of equivalence classes
X	 */
X
X	newlen = 0;
X	cclp = cclmap[i];
X
X	for ( ccls = 0; ccls < ccllen[i]; ++ccls )
X	    {
X	    ich = ccltbl[cclp + ccls] & BYTEMASK;
X	    cclmec = ecgroup[ich];
X	    if ( cclmec > 0 )
X		{
X		ccltbl[cclp + newlen] = cclmec;
X		++newlen;
X		}
X	    }
X
X	ccllen[i] = newlen;
X	}
X    }
X
X
X/* cre8ecs - associate equivalence class numbers with class members
X *
X * synopsis
X *    int cre8ecs();
X *    number of classes = cre8ecs( fwd, bck, num );
X *
X *  fwd is the forward linked-list of equivalence class members.  bck
X *  is the backward linked-list, and num is the number of class members.
X *  Returned is the number of classes.
X */
X
Xint cre8ecs( fwd, bck, num )
Xint fwd[], bck[], num;
X
X    {
X    int i, j, numcl;
X
X    numcl = 0;
X
X    /* create equivalence class numbers.  From now on, abs( bck(x) )
X     * is the equivalence class number for object x.  If bck(x)
X     * is positive, then x is the representative of its equivalence
X     * class.
X     */
X
X    for ( i = 1; i <= num; ++i )
X	if ( bck[i] == NIL )
X	    {
X	    bck[i] = ++numcl;
X	    for ( j = fwd[i]; j != NIL; j = fwd[j] )
X		bck[j] = -numcl;
X	    }
X
X    return ( numcl );
X    }
X
X
X/* mkeccl - update equivalence classes based on character class xtions
X *
X * synopsis
X *    char ccls[];
X *    int lenccl, fwd[llsiz], bck[llsiz], llsiz;
X *    mkeccl( ccls, lenccl, fwd, bck, llsiz );
X *
X * where ccls contains the elements of the character class, lenccl is the
X * number of elements in the ccl, fwd is the forward link-list of equivalent
X * characters, bck is the backward link-list, and llsiz size of the link-list
X *
X * Modified by Earle R. Horton, May, 1988 to allow for the possibility that
X * negative characters may be valid in the character set of the compiler.
X */
X
Xmkeccl( ccls, lenccl, fwd, bck, llsiz )
Xchar ccls[];
Xint lenccl, fwd[], bck[], llsiz;
X
X    {
X    int cclp, oldec, newec;
X    int cclm, i, j;
X	short *tmpccl;
X	
X	/* [ERH] Read chars into a short array on the stack. */
X	tmpccl = (short *)alloca(current_max_ccl_tbl_size * sizeof(short));
X	for (i=0; i < current_max_ccl_tbl_size; i++)
X		tmpccl[i] = ccls[i] & BYTEMASK;
X
X    /* note that it doesn't matter whether or not the character class is
X     * negated.  The same results will be obtained in either case.
X     */
X
X    cclp = 0;
X
X    while ( cclp < lenccl )
X	{
X	cclm = tmpccl[cclp];
X	oldec = bck[cclm];
X	newec = cclm;
X
X	j = cclp + 1;
X
X	for ( i = fwd[cclm]; i != NIL && i <= llsiz; i = fwd[i] )
X	    { /* look for the symbol in the character class */
X	    for ( ; j < lenccl && tmpccl[j] <= i; ++j )
X		if ( tmpccl[j] == i )
X		    {
X		    /* we found an old companion of cclm in the ccl.
X		     * link it into the new equivalence class and flag it as
X		     * having been processed
X		     */
X
X		    bck[i] = newec;
X		    fwd[newec] = i;
X		    newec = i;
X		    tmpccl[j] = -i;	/* set flag so we don't reprocess */
X			/*
X			 * [ERH]  This trick will not work if negative characters are
X			 * valid.  E.g. DEC multi-nationals, Macintosh option-characters.
X			 */
X
X		    /* get next equivalence class member */
X		    /* next 2 */ goto next_pt;
X		    }
X
X	    /* symbol isn't in character class.  Put it in the old equivalence
X	     * class
X	     */
X
X	    bck[i] = oldec;
X
X	    if ( oldec != NIL )
X		fwd[oldec] = i;
X
X	    oldec = i;
Xnext_pt:
X	    ;
X	    }
X
X	if ( bck[cclm] != NIL || oldec != bck[cclm] )
X	    {
X	    bck[cclm] = NIL;
X	    fwd[oldec] = NIL;
X	    }
X
X	fwd[newec] = NIL;
X
X	/* find next ccl member to process */
X
X	for ( ++cclp; tmpccl[cclp] < 0 && cclp < lenccl; ++cclp )
X	    {
X	    /* reset "doesn't need processing" flag */
X	    tmpccl[cclp] = -tmpccl[cclp];
X	    }
X	}
X	/* [ERH] Feed shorts back into chars. */
X	for (i=0; i < current_max_ccl_tbl_size; i++)
X		ccls[i] = tmpccl[i];
X    }
X
X
X/* mkechar - create equivalence class for single character
X *
X * synopsis
X *    int tch, fwd[], bck[];
X *    mkechar( tch, fwd, bck );
X */
X
Xmkechar( tch, fwd, bck )
Xint tch, fwd[], bck[];
X
X    {
X    /* if until now the character has been a proper subset of
X     * an equivalence class, break it away to create a new ec
X     */
X
X    if ( fwd[tch] != NIL )
X	bck[fwd[tch]] = bck[tch];
X
X    if ( bck[tch] != NIL )
X	fwd[bck[tch]] = fwd[tch];
X
X    fwd[tch] = NIL;
X    bck[tch] = NIL;
X    }
SHAR_EOF
if test 5206 -ne "`wc -c < 'ecs.c'`"
then
	echo shar: error transmitting "'ecs.c'" '(should have been 5206 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'main.c'" '(14297 characters)'
if test -f 'main.c'
then
	echo shar: will not over-write existing file "'main.c'"
else
sed 's/^X//' << \SHAR_EOF > 'main.c'
X/* flex - tool to generate fast lexical analyzers
X *
X *
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X *
X *
X * ver   date  who    remarks
X * ---   ----  ------ -------------------------------------------------------
X * 04b 30sep87 kg, vp .implemented (part of) Van Jacobson's fast scanner design
X * 04a 27jun86 vp     .translated from Ratfor into C
X * 01a 22aug83 vp     .written.  Original version by Jef Poskanzer.
X */
X
X#include "flexdef.h"
X
X
X/* these globals are all defined and commented in flexdef.h */
Xint printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
Xint interactive, caseins, useecs, fulltbl, usemecs, reject;
Xint fullspd, gen_line_dirs;
Xint datapos, dataline, linenum;
XFILE *skelfile = NULL;
Xchar *infilename = NULL;
X#ifdef MALLOC_BUFFERS
Xint *onestate,*onesym,*onenext,*onedef,onesp;
X#else
Xint onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
Xint onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
X#endif
Xint current_mns;
Xint accnum, *firstst, *lastst, *finalst, *transchar;
Xint *trans1, *trans2, *accptnum, lastnfa;
X#ifdef MALLOC_BUFFERS
Xint numtemps, numprots, *protprev, *protnext, *prottbl;
Xint *protcomst, firstprot, lastprot,
X#else
Xint numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
Xint protcomst[MSP], firstprot, lastprot,
X#endif
X#ifdef MALLOC_BUFFERS
X	*protsave;
X#else
X	protsave[PROT_SAVE_SIZE];
X#endif
X#ifdef MALLOC_BUFFERS
Xint numecs, *nextecm, *ecgroup, nummecs;
Xint *tecfwd, *tecbck;
X#else
Xint numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs;
Xint tecfwd[CSIZE + 1], tecbck[CSIZE + 1];
X#endif
Xint lastsc, current_max_scs, *scset, *scbol, *scxclu, *actvsc;
Xint current_max_dfa_size, current_max_xpairs;
Xint current_max_template_xpairs, current_max_dfas;
Xint lastdfa, *nxt, *chk, *tnxt;
Xint *base, *def, tblend, firstfree, numtemps, **dss, *dfasiz;
Xunion dfaacc_union *dfaacc;
Xint *accsiz, *dhash, *todo, todo_head, todo_next, numas;
Xint numsnpairs, jambase, jamstate;
Xint lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
Xint current_max_ccl_tbl_size;
Xchar *ccltbl;
Xchar *starttime, *endtime, nmstr[MAXLINE];
Xint sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
Xint tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
XFILE *temp_action_file;
Xint end_of_buffer_state;
Xchar *action_file_name = "/tmp/flexXXXXXX";
X
X
X/* flex - main program
X *
X * synopsis (from the shell)
X *    flex [-v] [file ...]
X */
X
Xmain( argc, argv )
Xint argc;
Xchar **argv;
X
X    {
X#ifdef MALLOC_BUFFERS
X#define GETBUF(a,b) a = (int *)(malloc((b)*sizeof(int)))
X	GETBUF(onestate,ONE_STACK_SIZE);
X	GETBUF(onesym,ONE_STACK_SIZE);
X	GETBUF(onenext,ONE_STACK_SIZE);
X	GETBUF(onedef,ONE_STACK_SIZE);
X	GETBUF(protprev,MSP);
X	GETBUF(protnext,MSP);
X	GETBUF(prottbl,MSP);
X	GETBUF(protcomst,MSP);
X	GETBUF(protsave,PROT_SAVE_SIZE);
X	GETBUF(nextecm,CSIZE + 1);
X	GETBUF(ecgroup,CSIZE + 1);
X	GETBUF(tecfwd,CSIZE + 1);
X	GETBUF(tecbck,CSIZE + 1);
X	if(onestate == NULL || onesym == NULL || onenext == NULL || onedef
X		== NULL || protprev == NULL || protnext  == NULL || prottbl  == NULL || 
X		protcomst == NULL || protsave == NULL || nextecm  == NULL || ecgroup 
X		== NULL || tecfwd == NULL || tecbck == NULL){
X		fprintf(stderr,"%s: Out of memory\n",argv[0]);
X		exit(-1);
X	}
X#endif
X    flexinit( argc, argv );
X
X    readin();
X
X    if ( ! syntaxerror )
X	{
X	/* convert the ndfa to a dfa */
X	ntod();
X
X	/* generate the C state transition tables from the DFA */
X	make_tables();
X	}
X
X    /* note, flexend does not return.  It exits with its argument as status. */
X
X    flexend( 0 );
X    }
X
X
X/* flexend - terminate flex
X *
X * synopsis
X *    int status;
X *    flexend( status );
X *
X *    status is exit status.
X *
X * note
X *    This routine does not return.
X */
X
Xflexend( status )
Xint status;
X
X    {
X    int tblsiz;
X    char *gettime();
X
X    if ( skelfile != NULL )
X	(void) fclose( skelfile );
X
X    if ( temp_action_file )
X	{
X	(void) fclose( temp_action_file );
X	(void) unlink( action_file_name );
X	}
X
X    if ( printstats )
X	{
X	endtime = gettime();
X
X	fprintf( stderr, "flex usage statistics:\n" );
X	fprintf( stderr, "  started at %s, finished at %s\n",
X		 starttime, endtime );
X
X	fprintf( stderr, "  %d/%d NFA states\n", lastnfa, current_mns );
X	fprintf( stderr, "  %d/%d DFA states (%d words)\n", lastdfa,
X			 current_max_dfas, totnst );
X	fprintf( stderr, "  %d rules\n", accnum );
X	fprintf( stderr, "  %d/%d start conditions\n", lastsc,
X			 current_max_scs );
X	fprintf( stderr, "  %d epsilon states, %d double epsilon states\n",
X		 numeps, eps2 );
X
X	if ( lastccl == 0 )
X	    fprintf( stderr, "  no character classes\n" );
X	else
X	    fprintf( stderr,
X	"  %d/%d character classes needed %d/%d words of storage, %d reused\n",
X		     lastccl, current_maxccls,
X		     cclmap[lastccl] + ccllen[lastccl] - 1,
X		     current_max_ccl_tbl_size, cclreuse );
X
X	fprintf( stderr, "  %d state/nextstate pairs created\n", numsnpairs );
X	fprintf( stderr, "  %d/%d unique/duplicate transitions\n",
X		 numuniq, numdup );
X
X	if ( fulltbl )
X	    {
X	    tblsiz = lastdfa * numecs;
X	    fprintf( stderr, "  %d table entries\n", tblsiz );
X	    }
X
X	else
X	    {
X	    tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
X
X	    fprintf( stderr, "  %d/%d base/def entries created\n",
X		     lastdfa + numtemps, current_max_dfas );
X	    fprintf( stderr, "  %d/%d (peak %d) nxt/chk entries created\n",
X		     tblend, current_max_xpairs, peakpairs );
X	    fprintf( stderr,
X		     "  %d/%d (peak %d) template nxt/chk entries created\n",
X		     numtemps * nummecs, current_max_template_xpairs,
X		     numtemps * numecs );
X	    fprintf( stderr, "  %d empty table entries\n", nummt );
X	    fprintf( stderr, "  %d protos created\n", numprots );
X	    fprintf( stderr, "  %d templates created, %d uses\n",
X		     numtemps, tmpuses );
X	    }
X
X	if ( useecs )
X	    {
X	    tblsiz = tblsiz + CSIZE;
X	    fprintf( stderr, "  %d/%d equivalence classes created\n",
X		     numecs, CSIZE );
X	    }
X
X	if ( usemecs )
X	    {
X	    tblsiz = tblsiz + numecs;
X	    fprintf( stderr, "  %d/%d meta-equivalence classes created\n",
X		     nummecs, CSIZE );
X	    }
X
X	fprintf( stderr, "  %d (%d saved) hash collisions, %d DFAs equal\n",
X		 hshcol, hshsave, dfaeql );
X	fprintf( stderr, "  %d sets of reallocations needed\n", num_reallocs );
X	fprintf( stderr, "  %d total table entries needed\n", tblsiz );
X	}
X
X    exit( status );
X    }
X
X
X/* flexinit - initialize flex
X *
X * synopsis
X *    int argc;
X *    char **argv;
X *    flexinit( argc, argv );
X */
X
Xflexinit( argc, argv )
Xint argc;
Xchar **argv;
X
X    {
X    int i, sawcmpflag, use_stdout;
X    char *arg, *skelname = NULL, *gettime(), clower(), *mktemp();
X
X    printstats = syntaxerror = trace = spprdflt = interactive = caseins = false;
X    ddebug = fulltbl = reject = fullspd = false;
X    gen_line_dirs = usemecs = useecs = true;
X
X    sawcmpflag = false;
X    use_stdout = false;
X
X    /* read flags */
X    for ( --argc, ++argv; argc ; --argc, ++argv )
X	{
X	if ( argv[0][0] != '-' || argv[0][1] == '\0' )
X	    break;
X
X	arg = argv[0];
X
X	for ( i = 1; arg[i] != '\0'; ++i )
X	    switch ( arg[i] )
X		{
X		case 'c':
X		    if ( i != 1 )
X			flexerror( "-c flag must be given separately" );
X
X		    if ( ! sawcmpflag )
X			{
X			useecs = false;
X			usemecs = false;
X			fulltbl = false;
X			sawcmpflag = true;
X			}
X
X		    for ( ++i; arg[i] != '\0'; ++i )
X			switch ( clower( arg[i] ) )
X			    {
X			    case 'e':
X				useecs = true;
X				break;
X
X			    case 'F':
X				fullspd = true;
X				break;
X
X			    case 'f':
X				fulltbl = true;
X				break;
X
X			    case 'm':
X				usemecs = true;
X				break;
X
X			    default:
X				lerrif( "unknown -c option %c",
X					(int) arg[i] );
X				break;
X			    }
X		    
X		    goto get_next_arg;
X
X		case 'd':
X		    ddebug = true;
X		    break;
X
X		case 'f':
X		    useecs = usemecs = false;
X		    fulltbl = true;
X		    break;
X
X		case 'I':
X		    interactive = true;
X		    break;
X
X		case 'i':
X		    caseins = true;
X		    break;
X
X		case 'L':
X		    gen_line_dirs = false;
X		    break;
X
X		case 'r':
X		    reject = true;
X		    break;
X
X		case 'F':
X		    useecs = usemecs = false;
X		    fullspd = true;
X		    break;
X
X		case 'S':
X		    if ( i != 1 )
X			flexerror( "-S flag must be given separately" );
X
X		    skelname = arg + i + 1;
X		    goto get_next_arg;
X
X		case 's':
X		    spprdflt = true;
X		    break;
X
X		case 't':
X		    use_stdout = true;
X		    break;
X
X		case 'T':
X		    trace = true;
X		    break;
X
X		case 'v':
X		    printstats = true;
X		    break;
X
X		default:
X		    lerrif( "unknown flag %c", (int) arg[i] );
X		    break;
X		}
X
Xget_next_arg: /* used by -c and -S flags in lieu of a "continue 2" control */
X	;
X	}
X
X    if ( (fulltbl || fullspd) && usemecs )
X	flexerror( "full table and -cm don't make sense together" );
X
X    if ( (fulltbl || fullspd) && interactive )
X	flexerror( "full table and -I are (currently) incompatible" );
X
X    if ( (fulltbl || fullspd) && reject )
X	flexerror( "reject (-r) cannot be used with -f or -F" );
X
X    if ( fulltbl && fullspd )
X	flexerror( "full table and -F are mutually exclusive" );
X
X    if ( ! skelname )
X	{
X	static char skeleton_name_storage[400];
X
X	skelname = skeleton_name_storage;
X
X	if ( fullspd || fulltbl )
X	    (void) strcpy( skelname, FAST_SKELETON_FILE );
X	else
X	    (void) strcpy( skelname, DEFAULT_SKELETON_FILE );
X	}
X
X    if ( ! use_stdout )
X	{
X	FILE *prev_stdout = freopen( "lex.yy.c", "w", stdout );
X
X	if ( prev_stdout == NULL )
X	    flexerror( "could not create lex.yy.c" );
X	}
X
X    if ( argc )
X	{
X	if ( argc > 1 )
X	    flexerror( "extraneous argument(s) given" );
X
X	yyin = fopen( infilename = argv[0], "r" );
X
X	if ( yyin == NULL )
X	    lerrsf( "can't open %s", argv[0] );
X	}
X
X    else
X	yyin = stdin;
X
X    lastccl = 0;
X    lastsc = 0;
X
X    /* initialize the statistics */
X    starttime = gettime();
X
X    if ( (skelfile = fopen( skelname, "r" )) == NULL )
X	lerrsf( "can't open skeleton file %s", skelname );
X
X#ifndef MPW			/* Single-user system. */
X    (void) mktemp( action_file_name );
X#endif
X
X    if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL )
X	lerrsf( "can't open temporary action file %s", action_file_name );
X
X    lastdfa = lastnfa = accnum = numas = numsnpairs = tmpuses = 0;
X    numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
X    numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
X    onesp = numprots = 0;
X
X    linenum = sectnum = 1;
X    firstprot = NIL;
X
X    /* used in mkprot() so that the first proto goes in slot 1
X     * of the proto queue
X     */
X    lastprot = 1;
X
X    if ( useecs )
X	{
X	/* set up doubly-linked equivalence classes */
X	ecgroup[1] = NIL;
X
X	for ( i = 2; i <= CSIZE; ++i )
X	    {
X	    ecgroup[i] = i - 1;
X	    nextecm[i - 1] = i;
X	    }
X
X	nextecm[CSIZE] = NIL;
X	}
X
X    else
X	{ /* put everything in its own equivalence class */
X	for ( i = 1; i <= CSIZE; ++i )
X	    {
X	    ecgroup[i] = i;
X	    nextecm[i] = BAD_SUBSCRIPT;	/* to catch errors */
X	    }
X	}
X
X    set_up_initial_allocations();
X    }
X
X
X/* readin - read in the rules section of the input file(s)
X *
X * synopsis
X *    readin();
X */
X
Xreadin()
X
X    {
X    fputs( "#define YY_DEFAULT_ACTION ", stdout );
X
X    if ( spprdflt )
X	fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )", stdout );
X    else
X	fputs( "ECHO", stdout );
X
X    fputs( ";\n", stdout );
X
X    if ( ddebug )
X	puts( "#define FLEX_DEBUG" );
X    if ( useecs )
X	puts( "#define FLEX_USE_ECS" );
X    if ( usemecs )
X	puts( "#define FLEX_USE_MECS" );
X    if ( interactive )
X	puts( "#define FLEX_INTERACTIVE_SCANNER" );
X    if ( reject )
X	puts( "#define FLEX_REJECT_ENABLED" );
X    if ( fulltbl )
X	puts( "#define FLEX_FULL_TABLE" );
X
X    skelout();
X
X    line_directive_out( stdout );
X
X    if ( yyparse() )
X#ifdef MPW		/* See tool interface guidelines in MPW manual. */
X	{
X		char *panicmsg;
X		char *alloca();
X		panicmsg = alloca(128);
X		sprintf(panicmsg,"File %s ; %%d # Fatal parse error.");
X		lerrif(panicmsg,linenum);
X	}
X#else
X	lerrif( "fatal parse error at line %d", linenum );
X#endif
X
X    if ( useecs )
X	{
X	numecs = cre8ecs( nextecm, ecgroup, CSIZE );
X	ccl2ecl();
X	}
X
X    else
X	numecs = CSIZE;
X
X    }
X
X
X
X/* set_up_initial_allocations - allocate memory for internal tables */
X
Xset_up_initial_allocations()
X
X    {
X    current_mns = INITIAL_MNS;
X    firstst = allocate_integer_array( current_mns );
X    lastst = allocate_integer_array( current_mns );
X    finalst = allocate_integer_array( current_mns );
X    transchar = allocate_integer_array( current_mns );
X    trans1 = allocate_integer_array( current_mns );
X    trans2 = allocate_integer_array( current_mns );
X    accptnum = allocate_integer_array( current_mns );
X
X    current_max_scs = INITIAL_MAX_SCS;
X    scset = allocate_integer_array( current_max_scs );
X    scbol = allocate_integer_array( current_max_scs );
X    scxclu = allocate_integer_array( current_max_scs );
X    actvsc = allocate_integer_array( current_max_scs );
X
X    current_maxccls = INITIAL_MAXCCLS;
X    cclmap = allocate_integer_array( current_maxccls );
X    ccllen = allocate_integer_array( current_maxccls );
X    cclng = allocate_integer_array( current_maxccls );
X
X    current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
X    ccltbl = allocate_character_array( current_max_ccl_tbl_size );
X
X    current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
X
X    current_max_xpairs = INITIAL_MAX_XPAIRS;
X    nxt = allocate_integer_array( current_max_xpairs );
X    chk = allocate_integer_array( current_max_xpairs );
X
X    current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
X    tnxt = allocate_integer_array( current_max_template_xpairs );
X
X    current_max_dfas = INITIAL_MAX_DFAS;
X    base = allocate_integer_array( current_max_dfas );
X    def = allocate_integer_array( current_max_dfas );
X    dfasiz = allocate_integer_array( current_max_dfas );
X    accsiz = allocate_integer_array( current_max_dfas );
X    dhash = allocate_integer_array( current_max_dfas );
X    todo = allocate_integer_array( current_max_dfas );
X    dss = allocate_integer_pointer_array( current_max_dfas );
X    dfaacc = allocate_dfaacc_union( current_max_dfas );
X    }
SHAR_EOF
if test 14297 -ne "`wc -c < 'main.c'`"
then
	echo shar: error transmitting "'main.c'" '(should have been 14297 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 3 ---

earleh@eleazar.dartmouth.edu (Earle R. Horton) (07/01/88)

[Flex for the Mac - part 4 of 7]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	flex/misc.c
#	flex/nfa.c
#	flex/parse.y
#	flex/scan.l
# This archive created: Wed Jun 29 07:03:20 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'misc.c'" '(10335 characters)'
if test -f 'misc.c'
then
	echo shar: will not over-write existing file "'misc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'misc.c'
X/* misc - miscellaneous flex routines */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include <ctype.h>
X#include "flexdef.h"
X
Xchar *malloc(), *realloc();
X
X
X/* action_out - write the actions from the temporary file to lex.yy.c
X *
X * synopsis
X *     action_out();
X *
X *     Copies the action file up to %% (or end-of-file) to lex.yy.c
X */
X
Xaction_out()
X
X    {
X    char buf[MAXLINE];
X
X    while ( fgets( buf, MAXLINE, temp_action_file ) != NULL )
X	if ( buf[0] == '%' && buf[1] == '%' )
X	    break;
X	else
X	    fputs( buf, stdout );
X    }
X
X
X/* allocate_array - allocate memory for an integer array of the given size */
X
Xchar *allocate_array( size, element_size )
Xint size, element_size;
X
X    {
X    register char *mem = malloc( (unsigned) (element_size * size) );
X
X    if ( mem == NULL )
X	flexfatal( "memory allocation failed in allocate_array()" );
X
X    return ( mem );
X    }
X
X
X/* bubble - bubble sort an integer array in increasing order
X *
X * synopsis
X *   int v[n], n;
X *   bubble( v, n );
X *
X * description
X *   sorts the first n elements of array v and replaces them in
X *   increasing order.
X *
X * passed
X *   v - the array to be sorted
X *   n - the number of elements of 'v' to be sorted */
X
Xbubble( v, n )
Xint v[], n;
X
X    {
X    register int i, j, k;
X
X    for ( i = n; i > 1; --i )
X	for ( j = 1; j < i; ++j )
X	    if ( v[j] > v[j + 1] )	/* compare */
X		{
X		k = v[j];	/* exchange */
X		v[j] = v[j + 1];
X		v[j + 1] = k;
X		}
X    }
X
X
X/* clower - replace upper-case letter to lower-case
X *
X * synopsis:
X *    char clower(), c;
X *    c = clower( c );
X */
X
Xchar clower( c )
Xregister char c;
X
X    {
X    return ( isupper(c) ? tolower(c) : c );
X    }
X
X
X/* copy_string - returns a dynamically allocated copy of a string
X *
X * synopsis
X *    char *str, *copy, *copy_string();
X *    copy = copy_string( str );
X */
X
Xchar *copy_string( str )
Xregister char *str;
X
X    {
X    register char *c;
X    char *copy;
X
X    /* find length */
X    for ( c = str; *c; ++c )
X	;
X
X    copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) );
X
X    if ( copy == NULL )
X	flexfatal( "dynamic memory failure in copy_string()" );
X
X    for ( c = copy; (*c++ = *str++); )
X	;
X    
X    return ( copy );
X    }
X
X
X/* cshell - shell sort a character array in increasing order
X *
X * synopsis
X *
X *   char v[n];
X *   int n;
X *   cshell( v, n );
X *
X * description
X *   does a shell sort of the first n elements of array v.
X *
X * passed
X *   v - array to be sorted
X *   n - number of elements of v to be sorted
X */
Xcshell( v, n )
Xchar v[];
Xint n;
X
X    {
X    int gap, i, j, jg;
X    char k;
X
X    for ( gap = n / 2; gap > 0; gap = gap / 2 )
X	for ( i = gap; i < n; ++i )
X	    for ( j = i - gap; j >= 0; j = j - gap )
X		{
X		jg = j + gap;
X
X		if ( v[j] <= v[jg] )
X		    break;
X
X		k = v[j];
X		v[j] = v[jg];
X		v[jg] = k;
X		}
X    }
X
X
X/* dataend - finish up a block of data declarations
X *
X * synopsis
X *    dataend();
X */
Xdataend()
X
X    {
X    if ( datapos > 0 )
X	dataflush();
X
X    /* add terminator for initialization */
X    puts( "    } ;\n" );
X
X    dataline = 0;
X    }
X
X
X
X/* dataflush - flush generated data statements
X *
X * synopsis
X *    dataflush();
X */
Xdataflush()
X
X    {
X    putchar( '\n' );
X
X    if ( ++dataline >= NUMDATALINES )
X	{
X	/* put out a blank line so that the table is grouped into
X	 * large blocks that enable the user to find elements easily
X	 */
X	putchar( '\n' );
X	dataline = 0;
X	}
X
X    /* reset the number of characters written on the current line */
X    datapos = 0;
X    }
X
X/* gettime - return current time
X *
X * synopsis
X *    char *gettime(), *time_str;
X *    time_str = gettime();
X */
X#ifdef MPW
Xpascal void IUTIMESTRING(dateTime, wantSeconds, result)
X	long dateTime;
X	short wantSeconds;
X	char *result;
X	extern;
Xchar *p2cstr();
Xchar *gettime()
X
X    {
X	char *copy_string();
X	long curtime;
X	char strbuf[256];
X	GetDateTime(&curtime);
X	IUTIMESTRING(curtime,true,strbuf);
X	p2cstr(strbuf);
X	return (copy_string(strbuf));
X}
X
X#else
X/* include sys/types.h to use time_t and make lint happy */
X
X#include <sys/types.h>
X
Xchar *gettime()
X
X    {
X    time_t t, time();
X    char *result, *ctime(), *copy_string();
X
X    t = time( (long *) 0 );
X
X    result = copy_string( ctime( &t ) );
X
X    /* get rid of trailing newline */
X    result[24] = '\0';
X
X    return ( result );
X    }
X#endif
X
X/* lerrif - report an error message formatted with one integer argument
X *
X * synopsis
X *    char msg[];
X *    int arg;
X *    lerrif( msg, arg );
X */
X
Xlerrif( msg, arg )
Xchar msg[];
Xint arg;
X
X    {
X    char errmsg[MAXLINE];
X    (void) sprintf( errmsg, msg, arg );
X    flexerror( errmsg );
X    }
X
X
X/* lerrsf - report an error message formatted with one string argument
X *
X * synopsis
X *    char msg[], arg[];
X *    lerrsf( msg, arg );
X */
X
Xlerrsf( msg, arg )
Xchar msg[], arg[];
X
X    {
X    char errmsg[MAXLINE];
X
X    (void) sprintf( errmsg, msg, arg );
X    flexerror( errmsg );
X    }
X
X
X/* flexerror - report an error message and terminate
X *
X * synopsis
X *    char msg[];
X *    flexerror( msg );
X */
X
Xflexerror( msg )
Xchar msg[];
X
X    {
X    fprintf( stderr, "flex: %s\n", msg );
X    flexend( 1 );
X    }
X
X
X/* flexfatal - report a fatal error message and terminate
X *
X * synopsis
X *    char msg[];
X *    flexfatal( msg );
X */
X
Xflexfatal( msg )
Xchar msg[];
X
X    {
X    fprintf( stderr, "flex: fatal internal error %s\n", msg );
X    flexend( 1 );
X    }
X
X
X/* line_directive_out - spit out a "# line" statement */
X
Xline_directive_out( output_file_name )
XFILE *output_file_name;
X
X    {
X    if ( infilename && gen_line_dirs ) 
X        fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename );
X    }
X
X
X/* mk2data - generate a data statement for a two-dimensional array
X *
X * synopsis
X *    int value;
X *    mk2data( value );
X *
X *  generates a data statement initializing the current 2-D array to "value"
X */
Xmk2data( value )
Xint value;
X
X    {
X    if ( datapos >= NUMDATAITEMS )
X	{
X	putchar( ',' );
X	dataflush();
X	}
X
X    if ( datapos == 0 )
X	/* indent */
X	fputs( "    ", stdout );
X
X    else
X	putchar( ',' );
X
X    ++datapos;
X
X    printf( "%5d", value );
X    }
X
X
X/* mkdata - generate a data statement
X *
X * synopsis
X *    int value;
X *    mkdata( value );
X *
X *  generates a data statement initializing the current array element to
X *  "value"
X */
Xmkdata( value )
Xint value;
X
X    {
X    if ( datapos >= NUMDATAITEMS )
X	{
X	putchar( ',' );
X	dataflush();
X	}
X
X    if ( datapos == 0 )
X	/* indent */
X	fputs( "    ", stdout );
X
X    else
X	putchar( ',' );
X
X    ++datapos;
X
X    printf( "%5d", value );
X    }
X
X
X/* myctoi - return the integer represented by a string of digits
X *
X * synopsis
X *    char array[];
X *    int val, myctoi();
X *    val = myctoi( array );
X *
X */
X
Xint myctoi( array )
Xchar array[];
X
X    {
X    int val = 0;
X
X    (void) sscanf( array, "%d", &val );
X
X    return ( val );
X    }
X
X
X/* myesc - return character corresponding to escape sequence
X *
X * synopsis
X *    char array[], c, myesc();
X *    c = myesc( array );
X *
X */
X
Xchar myesc( array )
Xchar array[];
X
X    {
X    switch ( array[1] )
X	{
X	case 'n': return ( '\n' );
X	case 't': return ( '\t' );
X	case 'f': return ( '\f' );
X	case 'r': return ( '\r' );
X	case 'b': return ( '\b' );
X
X	case '0':
X	    if ( isdigit(array[2]) )
X		{ /* \0<octal> */
X		char c, esc_char;
X		register int sptr = 2;
X
X		while ( isdigit(array[sptr]) )
X		    /* don't increment inside loop control because the
X		     * macro will expand it to two increments!  (Not a
X		     * problem with the C version of the macro)
X		     */
X		    ++sptr;
X
X		c = array[sptr];
X		array[sptr] = '\0';
X
X		esc_char = otoi( array + 2 );
X		array[sptr] = c;
X
X		if ( esc_char == '\0' )
X		    {
X		    synerr( "escape sequence for null not allowed" );
X		    return ( 1 );
X		    }
X
X		return ( esc_char );
X		}
X
X	    else
X		{
X		synerr( "escape sequence for null not allowed" );
X		return ( 1 );
X		}
X
X#ifdef NOTDEF
X	case '^':
X	    {
X	    register char next_char = array[2];
X
X	    if ( next_char == '?' )
X		return ( 0x7f );
X	    
X	    else if ( next_char >= 'A' && next_char <= 'Z' )
X		return ( next_char - 'A' + 1 );
X    
X	    else if ( next_char >= 'a' && next_char <= 'z' )
X		return ( next_char - 'z' + 1 );
X    
X	    synerr( "illegal \\^ escape sequence" );
X
X	    return ( 1 );
X	    }
X#endif
X	}
X    
X    return ( array[1] );
X    }
X
X
X/* otoi - convert an octal digit string to an integer value
X *
X * synopsis:
X *    int val, otoi();
X *    char str[];
X *    val = otoi( str );
X */
X
Xint otoi( str )
Xchar str[];
X
X    {
X#ifdef FTLSOURCE
X    fortran int gctoi()
X    int dummy = 1;
X
X    return ( gctoi( str, dummy, 8 ) );
X#else
X    int result;
X
X    (void) sscanf( str, "%o", &result );
X
X    return ( result );
X#endif
X    }
X
X
X
X
X/* reallocate_array - increase the size of a dynamic array */
X
Xchar *reallocate_array( array, size, element_size )
Xchar *array;
Xint size, element_size;
X
X    {
X    register char *new_array = realloc( array,
X					(unsigned) (size * element_size ));
X
X    if ( new_array == NULL )
X	flexfatal( "attempt to increase array size failed" );
X    
X    return ( new_array );
X    }
X
X
X/* skelout - write out one section of the skeleton file
X *
X * synopsis
X *    skelout();
X *
X * DESCRIPTION
X *    Copies from skelfile to stdout until a line beginning with "%%" or
X *    EOF is found.
X */
Xskelout()
X
X    {
X    char buf[MAXLINE];
X
X    while ( fgets( buf, MAXLINE, skelfile ) != NULL )
X	if ( buf[0] == '%' && buf[1] == '%' )
X	    break;
X	else
X	    fputs( buf, stdout );
X    }
X
X
X/* transition_struct_out - output a yy_trans_info structure
X *
X * synopsis
X *     int element_v, element_n;
X *     transition_struct_out( element_v, element_n );
X *
X * outputs the yy_trans_info structure with the two elements, element_v and
X * element_n.  Formats the output with spaces and carriage returns.
X */
X
Xtransition_struct_out( element_v, element_n )
Xint element_v, element_n;
X
X    {
X    printf( "%7d, %5d,", element_v, element_n );
X
X    datapos += TRANS_STRUCT_PRINT_LENGTH;
X
X    if ( datapos >= 75 )
X	{
X	printf( "\n" );
X
X	if ( ++dataline % 10 == 0 )
X	    printf( "\n" );
X
X	datapos = 0;
X	}
X    }
SHAR_EOF
if test 10335 -ne "`wc -c < 'misc.c'`"
then
	echo shar: error transmitting "'misc.c'" '(should have been 10335 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'nfa.c'" '(13633 characters)'
if test -f 'nfa.c'
then
	echo shar: will not over-write existing file "'nfa.c'"
else
sed 's/^X//' << \SHAR_EOF > 'nfa.c'
X/* nfa - NFA construction routines */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include "flexdef.h"
X
X/* add_accept - add an accepting state to a machine
X *
X * synopsis
X *
X *   add_accept( mach, headcnt, trailcnt );
X *
X * the global ACCNUM is incremented and the new value becomes mach's
X * accepting number.  if headcnt or trailcnt is non-zero then the machine
X * recognizes a pattern with trailing context.  headcnt is the number of
X * characters in the matched part of the pattern, or zero if the matched
X * part has variable length.  trailcnt is the number of trailing context
X * characters in the pattern, or zero if the trailing context has variable
X * length.
X */
X
Xadd_accept( mach, headcnt, trailcnt )
Xint mach, headcnt, trailcnt;
X
X    {
X    int astate;
X
X    fprintf( temp_action_file, "case %d:\n", ++accnum );
X
X    if ( headcnt > 0 || trailcnt > 0 )
X	{ /* do trailing context magic to not match the trailing characters */
X	fprintf( temp_action_file,
X	    "YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */\n" );
X
X	if ( headcnt > 0 )
X	    {
X	    int head_offset = headcnt - 1;
X
X	    if ( fullspd || fulltbl )
X		/* with the fast skeleton, yy_c_buf_p points to the *next*
X		 * character to scan, rather than the one that was last
X		 * scanned
X		 */
X		++head_offset;
X
X	    if ( head_offset > 0 )
X		fprintf( temp_action_file, "yy_c_buf_p = yy_b_buf_p + %d;\n",
X			 head_offset );
X
X	    else
X		fprintf( temp_action_file, "yy_c_buf_p = yy_b_buf_p;\n" );
X	    }
X
X	else
X	    fprintf( temp_action_file, "yy_c_buf_p -= %d;\n", trailcnt );
X    
X	fprintf( temp_action_file, "YY_DO_BEFORE_ACTION; /* set up yytext again */\n" );
X	}
X
X    line_directive_out( temp_action_file );
X
X    /* hang the accepting number off an epsilon state.  if it is associated
X     * with a state that has a non-epsilon out-transition, then the state
X     * will accept BEFORE it makes that transition, i.e., one character
X     * too soon
X     */
X
X    if ( transchar[finalst[mach]] == SYM_EPSILON )
X	accptnum[finalst[mach]] = accnum;
X
X    else
X	{
X	astate = mkstate( SYM_EPSILON );
X	accptnum[astate] = accnum;
X	mach = link_machines( mach, astate );
X	}
X    }
X
X
X/* copysingl - make a given number of copies of a singleton machine
X *
X * synopsis
X *
X *   newsng = copysingl( singl, num );
X *
X *     newsng - a new singleton composed of num copies of singl
X *     singl  - a singleton machine
X *     num    - the number of copies of singl to be present in newsng
X */
X
Xint copysingl( singl, num )
Xint singl, num;
X
X    {
X    int copy, i;
X
X    copy = mkstate( SYM_EPSILON );
X
X    for ( i = 1; i <= num; ++i )
X	copy = link_machines( copy, dupmachine( singl ) );
X
X    return ( copy );
X    }
X
X
X/* dumpnfa - debugging routine to write out an nfa
X *
X * synopsis
X *    int state1;
X *    dumpnfa( state1 );
X */
X
Xdumpnfa( state1 )
Xint state1;
X
X    {
X    int sym, tsp1, tsp2, anum, ns;
X
X    fprintf( stderr, "\n\n********** beginning dump of nfa with start state %d\n",
X	     state1 );
X
X    /* we probably should loop starting at firstst[state1] and going to
X     * lastst[state1], but they're not maintained properly when we "or"
X     * all of the rules together.  So we use our knowledge that the machine
X     * starts at state 1 and ends at lastnfa.
X     */
X
X    /* for ( ns = firstst[state1]; ns <= lastst[state1]; ++ns ) */
X    for ( ns = 1; ns <= lastnfa; ++ns )
X	{
X	fprintf( stderr, "state # %4d\t", ns );
X
X	sym = transchar[ns];
X	tsp1 = trans1[ns];
X	tsp2 = trans2[ns];
X	anum = accptnum[ns];
X
X	fprintf( stderr, "%3d:  %4d, %4d", sym, tsp1, tsp2 );
X
X	if ( anum != NIL )
X	    fprintf( stderr, "  [%d]", anum );
X
X	fprintf( stderr, "\n" );
X	}
X
X    fprintf( stderr, "********** end of dump\n" );
X    }
X
X
X/* dupmachine - make a duplicate of a given machine
X *
X * synopsis
X *
X *   copy = dupmachine( mach );
X *
X *     copy - holds duplicate of mach
X *     mach - machine to be duplicated
X *
X * note that the copy of mach is NOT an exact duplicate; rather, all the
X * transition states values are adjusted so that the copy is self-contained,
X * as the original should have been.
X *
X * also note that the original MUST be contiguous, with its low and high
X * states accessible by the arrays firstst and lastst
X */
X
Xint dupmachine( mach )
Xint mach;
X
X    {
X    int i, state, init, last = lastst[mach], state_offset;
X
X    for ( i = firstst[mach]; i <= last; ++i )
X	{
X	state = mkstate( transchar[i] );
X
X	if ( trans1[i] != NO_TRANSITION )
X	    {
X	    mkxtion( finalst[state], trans1[i] + state - i );
X
X	    if ( transchar[i] == SYM_EPSILON && trans2[i] != NO_TRANSITION )
X		mkxtion( finalst[state], trans2[i] + state - i );
X	    }
X
X	accptnum[state] = accptnum[i];
X	}
X
X    state_offset = state - i + 1;
X
X    init = mach + state_offset;
X    firstst[init] = firstst[mach] + state_offset;
X    finalst[init] = finalst[mach] + state_offset;
X    lastst[init] = lastst[mach] + state_offset;
X
X    return ( init );
X    }
X
X
X/* link_machines - connect two machines together
X *
X * synopsis
X *
X *   new = link_machines( first, last );
X *
X *     new    - a machine constructed by connecting first to last
X *     first  - the machine whose successor is to be last
X *     last   - the machine whose predecessor is to be first
X *
X * note: this routine concatenates the machine first with the machine
X *  last to produce a machine new which will pattern-match first first
X *  and then last, and will fail if either of the sub-patterns fails.
X *  FIRST is set to new by the operation.  last is unmolested.
X */
X
Xint link_machines( first, last )
Xint first, last;
X
X    {
X    if ( first == NIL )
X	return ( last );
X
X    else if ( last == NIL )
X	return ( first );
X
X    else
X	{
X	mkxtion( finalst[first], last );
X	finalst[first] = finalst[last];
X	lastst[first] = max( lastst[first], lastst[last] );
X	firstst[first] = min( firstst[first], firstst[last] );
X
X	return ( first );
X	}
X    }
X
X
X/* mkbranch - make a machine that branches to two machines
X *
X * synopsis
X *
X *   branch = mkbranch( first, second );
X *
X *     branch - a machine which matches either first's pattern or second's
X *     first, second - machines whose patterns are to be or'ed (the | operator)
X *
X * note that first and second are NEITHER destroyed by the operation.  Also,
X * the resulting machine CANNOT be used with any other "mk" operation except
X * more mkbranch's.  Compare with mkor()
X */
X
Xint mkbranch( first, second )
Xint first, second;
X
X    {
X    int eps;
X
X    if ( first == NO_TRANSITION )
X	return ( second );
X
X    else if ( second == NO_TRANSITION )
X	return ( first );
X
X    eps = mkstate( SYM_EPSILON );
X
X    mkxtion( eps, first );
X    mkxtion( eps, second );
X
X    return ( eps );
X    }
X
X
X/* mkclos - convert a machine into a closure
X *
X * synopsis
X *   new = mkclos( state );
X *
X *     new - a new state which matches the closure of "state"
X */
X
Xint mkclos( state )
Xint state;
X
X    {
X    return ( mkopt( mkposcl( state ) ) );
X    }
X
X
X/* mkopt - make a machine optional
X *
X * synopsis
X *
X *   new = mkopt( mach );
X *
X *     new  - a machine which optionally matches whatever mach matched
X *     mach - the machine to make optional
X *
X * notes:
X *     1. mach must be the last machine created
X *     2. mach is destroyed by the call
X */
X
Xint mkopt( mach )
Xint mach;
X
X    {
X    int eps;
X
X    if ( ! SUPER_FREE_EPSILON(finalst[mach]) )
X	{
X	eps = mkstate( SYM_EPSILON );
X	mach = link_machines( mach, eps );
X	}
X
X    /* can't skimp on the following if FREE_EPSILON(mach) is true because
X     * some state interior to "mach" might point back to the beginning
X     * for a closure
X     */
X    eps = mkstate( SYM_EPSILON );
X    mach = link_machines( eps, mach );
X
X    mkxtion( mach, finalst[mach] );
X
X    return ( mach );
X    }
X
X
X/* mkor - make a machine that matches either one of two machines
X *
X * synopsis
X *
X *   new = mkor( first, second );
X *
X *     new - a machine which matches either first's pattern or second's
X *     first, second - machines whose patterns are to be or'ed (the | operator)
X *
X * note that first and second are both destroyed by the operation
X * the code is rather convoluted because an attempt is made to minimize
X * the number of epsilon states needed
X */
X
Xint mkor( first, second )
Xint first, second;
X
X    {
X    int eps, orend;
X
X    if ( first == NIL )
X	return ( second );
X
X    else if ( second == NIL )
X	return ( first );
X
X    else
X	{
X	/* see comment in mkopt() about why we can't use the first state
X	 * of "first" or "second" if they satisfy "FREE_EPSILON"
X	 */
X	eps = mkstate( SYM_EPSILON );
X
X	first = link_machines( eps, first );
X
X	mkxtion( first, second );
X
X	if ( SUPER_FREE_EPSILON(finalst[first]) &&
X	     accptnum[finalst[first]] == NIL )
X	    {
X	    orend = finalst[first];
X	    mkxtion( finalst[second], orend );
X	    }
X
X	else if ( SUPER_FREE_EPSILON(finalst[second]) &&
X		  accptnum[finalst[second]] == NIL )
X	    {
X	    orend = finalst[second];
X	    mkxtion( finalst[first], orend );
X	    }
X
X	else
X	    {
X	    eps = mkstate( SYM_EPSILON );
X
X	    first = link_machines( first, eps );
X	    orend = finalst[first];
X
X	    mkxtion( finalst[second], orend );
X	    }
X	}
X
X    finalst[first] = orend;
X    return ( first );
X    }
X
X
X/* mkposcl - convert a machine into a positive closure
X *
X * synopsis
X *   new = mkposcl( state );
X *
X *    new - a machine matching the positive closure of "state"
X */
X
Xint mkposcl( state )
Xint state;
X
X    {
X    int eps;
X
X    if ( SUPER_FREE_EPSILON(finalst[state]) )
X	{
X	mkxtion( finalst[state], state );
X	return ( state );
X	}
X
X    else
X	{
X	eps = mkstate( SYM_EPSILON );
X	mkxtion( eps, state );
X	return ( link_machines( state, eps ) );
X	}
X    }
X
X
X/* mkrep - make a replicated machine
X *
X * synopsis
X *   new = mkrep( mach, lb, ub );
X *
X *    new - a machine that matches whatever "mach" matched from "lb"
X *          number of times to "ub" number of times
X *
X * note
X *   if "ub" is INFINITY then "new" matches "lb" or more occurrences of "mach"
X */
X
Xint mkrep( mach, lb, ub )
Xint mach, lb, ub;
X
X    {
X    int base, tail, copy, i;
X
X    base = copysingl( mach, lb - 1 );
X
X    if ( ub == INFINITY )
X	{
X	copy = dupmachine( mach );
X	mach = link_machines( mach, link_machines( base, mkclos( copy ) ) );
X	}
X
X    else
X	{
X	tail = mkstate( SYM_EPSILON );
X
X	for ( i = lb; i < ub; ++i )
X	    {
X	    copy = dupmachine( mach );
X	    tail = mkopt( link_machines( copy, tail ) );
X	    }
X
X	mach = link_machines( mach, link_machines( base, tail ) );
X	}
X
X    return ( mach );
X    }
X
X
X/* mkstate - create a state with a transition on a given symbol
X *
X * synopsis
X *
X *   state = mkstate( sym );
X *
X *     state - a new state matching sym
X *     sym   - the symbol the new state is to have an out-transition on
X *
X * note that this routine makes new states in ascending order through the
X * state array (and increments LASTNFA accordingly).  The routine DUPMACHINE
X * relies on machines being made in ascending order and that they are
X * CONTIGUOUS.  Change it and you will have to rewrite DUPMACHINE (kludge
X * that it admittedly is)
X */
X
Xint mkstate( sym )
Xint sym;
X
X    {
X    if ( ++lastnfa >= current_mns )
X	{
X	if ( (current_mns += MNS_INCREMENT) >= MAXIMUM_MNS )
X	    lerrif( "input rules are too complicated (>= %d NFA states)",
X		    current_mns );
X	
X	++num_reallocs;
X
X	transchar = reallocate_integer_array( transchar, current_mns );
X	trans1 = reallocate_integer_array( trans1, current_mns );
X	trans2 = reallocate_integer_array( trans2, current_mns );
X	accptnum = reallocate_integer_array( accptnum, current_mns );
X	firstst = reallocate_integer_array( firstst, current_mns );
X	finalst = reallocate_integer_array( finalst, current_mns );
X	lastst = reallocate_integer_array( lastst, current_mns );
X	}
X
X    transchar[lastnfa] = sym;
X    trans1[lastnfa] = NO_TRANSITION;
X    trans2[lastnfa] = NO_TRANSITION;
X    accptnum[lastnfa] = NIL;
X    firstst[lastnfa] = lastnfa;
X    finalst[lastnfa] = lastnfa;
X    lastst[lastnfa] = lastnfa;
X
X    /* fix up equivalence classes base on this transition.  Note that any
X     * character which has its own transition gets its own equivalence class.
X     * Thus only characters which are only in character classes have a chance
X     * at being in the same equivalence class.  E.g. "a|b" puts 'a' and 'b'
X     * into two different equivalence classes.  "[ab]" puts them in the same
X     * equivalence class (barring other differences elsewhere in the input).
X     */
X
X    if ( sym < 0 )
X	{
X	/* we don't have to update the equivalence classes since that was
X	 * already done when the ccl was created for the first time
X	 */
X	}
X
X    else if ( sym == SYM_EPSILON )
X	++numeps;
X
X    else
X	{
X	if ( useecs )
X	    mkechar( sym, nextecm, ecgroup );
X	}
X
X    return ( lastnfa );
X    }
X
X
X/* mkxtion - make a transition from one state to another
X *
X * synopsis
X *
X *   mkxtion( statefrom, stateto );
X *
X *     statefrom - the state from which the transition is to be made
X *     stateto   - the state to which the transition is to be made
X */
X
Xmkxtion( statefrom, stateto )
Xint statefrom, stateto;
X
X    {
X    if ( trans1[statefrom] == NO_TRANSITION )
X	trans1[statefrom] = stateto;
X
X    else if ( (transchar[statefrom] != SYM_EPSILON) ||
X	      (trans2[statefrom] != NO_TRANSITION) )
X	flexfatal( "found too many transitions in mkxtion()" );
X
X    else
X	{ /* second out-transition for an epsilon state */
X	++eps2;
X	trans2[statefrom] = stateto;
X	}
X    }
SHAR_EOF
if test 13633 -ne "`wc -c < 'nfa.c'`"
then
	echo shar: error transmitting "'nfa.c'" '(should have been 13633 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'parse.y'" '(8970 characters)'
if test -f 'parse.y'
then
	echo shar: will not over-write existing file "'parse.y'"
else
sed 's/^X//' << \SHAR_EOF > 'parse.y'
X/* parse.y - parser for flex input */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X%token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL
X
X%{
X#include "flexdef.h"
X
Xint pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen;
Xint trlcontxt, xcluflg, cclsorted, varlength;
Xchar clower();
X
Xstatic int madeany = false;  /* whether we've made the '.' character class */
X
X%}
X
X%%
Xgoal            :  initlex sect1 sect1end sect2
X		;
X
Xinitlex         :
X			{
X			/* initialize for processing rules */
X
X			/* create default DFA start condition */
X			scinstal( "INITIAL", false );
X			}
X		;
X			
Xsect1		:  sect1 startconddecl WHITESPACE namelist1 '\n'
X		|
X		|  error '\n'
X			{ synerr( "unknown error processing section 1" ); }
X		;
X
Xsect1end	:  SECTEND
X		;
X
Xstartconddecl   :  SCDECL
X			{
X			/* these productions are separate from the s1object
X			 * rule because the semantics must be done before
X			 * we parse the remainder of an s1object
X			 */
X
X			xcluflg = false;
X			}
X		
X		|  XSCDECL
X			{ xcluflg = true; }
X		;
X
Xnamelist1	:  namelist1 WHITESPACE NAME
X			{ scinstal( nmstr, xcluflg ); }
X
X		|  NAME
X			{ scinstal( nmstr, xcluflg ); }
X
X		|  error
X                        { synerr( "bad start condition list" ); }
X		;
X
Xsect2           :  sect2 initforrule flexrule '\n'
X		|
X		;
X
Xinitforrule     :
X			{
X			/* initialize for a parse of one rule */
X			trlcontxt = varlength = false;
X			trailcnt = headcnt = rulelen = 0;
X			}
X		;
X
Xflexrule        :  scon '^' re eol 
X                        {
X			pat = link_machines( $3, $4 );
X			add_accept( pat, headcnt, trailcnt );
X
X			for ( i = 1; i <= actvp; ++i )
X			    scbol[actvsc[i]] = mkbranch( scbol[actvsc[i]], pat );
X			}
X
X		|  scon re eol 
X                        {
X			pat = link_machines( $2, $3 );
X			add_accept( pat, headcnt, trailcnt );
X
X			for ( i = 1; i <= actvp; ++i )
X			    scset[actvsc[i]] = mkbranch( scset[actvsc[i]], pat );
X			}
X
X                |  '^' re eol 
X			{
X			pat = link_machines( $2, $3 );
X			add_accept( pat, headcnt, trailcnt );
X
X			/* add to all non-exclusive start conditions,
X			 * including the default (0) start condition
X			 */
X
X			for ( i = 1; i <= lastsc; ++i )
X			    if ( ! scxclu[i] )
X				scbol[i] = mkbranch( scbol[i], pat );
X			}
X
X                |  re eol 
X			{
X			pat = link_machines( $1, $2 );
X			add_accept( pat, headcnt, trailcnt );
X
X			for ( i = 1; i <= lastsc; ++i )
X			    if ( ! scxclu[i] )
X				scset[i] = mkbranch( scset[i], pat );
X			}
X
X                |  error
X			{ synerr( "unrecognized rule" ); }
X		;
X
Xscon            :  '<' namelist2 '>'
X		;
X
Xnamelist2       :  namelist2 ',' NAME
X                        {
X			if ( (scnum = sclookup( nmstr )) == 0 )
X			    synerr( "undeclared start condition" );
X
X			else
X			    actvsc[++actvp] = scnum;
X			}
X
X		|  NAME
X			{
X			if ( (scnum = sclookup( nmstr )) == 0 )
X			    synerr( "undeclared start condition" );
X			else
X			    actvsc[actvp = 1] = scnum;
X			}
X
X		|  error
X			{ synerr( "bad start condition list" ); }
X		;
X
Xeol             :  '$'
X                        {
X			if ( trlcontxt )
X			    {
X			    synerr( "trailing context used twice" );
X			    $$ = mkstate( SYM_EPSILON );
X			    }
X			else
X			    {
X			    trlcontxt = true;
X
X			    if ( ! varlength )
X				headcnt = rulelen;
X
X			    ++rulelen;
X			    trailcnt = 1;
X
X			    eps = mkstate( SYM_EPSILON );
X			    $$ = link_machines( eps, mkstate( '\n' ) );
X			    }
X			}
X
X		|
X		        {
X		        $$ = mkstate( SYM_EPSILON );
X
X			if ( trlcontxt )
X			    {
X			    if ( varlength && headcnt == 0 )
X				/* both head and trail are variable-length */
X				synerr( "illegal trailing context" );
X
X			    else
X				trailcnt = rulelen;
X			    }
X		        }
X		;
X
Xre              :  re '|' series
X                        {
X			varlength = true;
X
X			$$ = mkor( $1, $3 );
X			}
X
X		|  re2 series
X			{ $$ = link_machines( $1, $2 ); }
X
X		|  series
X			{ $$ = $1; }
X		;
X
X
Xre2		:  re '/'
X			{
X			/* this rule is separate from the others for "re" so
X			 * that the reduction will occur before the trailing
X			 * series is parsed
X			 */
X
X			if ( trlcontxt )
X			    synerr( "trailing context used twice" );
X			else
X			    trlcontxt = true;
X
X			if ( varlength )
X			    /* the trailing context had better be fixed-length */
X			    varlength = false;
X			else
X			    headcnt = rulelen;
X
X			rulelen = 0;
X			$$ = $1;
X			}
X		;
X
Xseries          :  series singleton
X                        {
X			/* this is where concatenation of adjacent patterns
X			 * gets done
X			 */
X			$$ = link_machines( $1, $2 );
X			}
X
X		|  singleton
X			{ $$ = $1; }
X		;
X
Xsingleton       :  singleton '*'
X                        {
X			varlength = true;
X
X			$$ = mkclos( $1 );
X			}
X			
X		|  singleton '+'
X			{
X			varlength = true;
X
X			$$ = mkposcl( $1 );
X			}
X
X		|  singleton '?'
X			{
X			varlength = true;
X
X			$$ = mkopt( $1 );
X			}
X
X		|  singleton '{' NUMBER ',' NUMBER '}'
X			{
X			varlength = true;
X
X			if ( $3 > $5 || $3 <= 0 )
X			    {
X			    synerr( "bad iteration values" );
X			    $$ = $1;
X			    }
X			else
X			    $$ = mkrep( $1, $3, $5 );
X			}
X				
X		|  singleton '{' NUMBER ',' '}'
X			{
X			varlength = true;
X
X			if ( $3 <= 0 )
X			    {
X			    synerr( "iteration value must be positive" );
X			    $$ = $1;
X			    }
X
X			else
X			    $$ = mkrep( $1, $3, INFINITY );
X			}
X
X		|  singleton '{' NUMBER '}'
X			{
X			/* the singleton could be something like "(foo)",
X			 * in which case we have no idea what its length
X			 * is, so we punt here.
X			 */
X			varlength = true;
X
X			if ( $3 <= 0 )
X			    {
X			    synerr( "iteration value must be positive" );
X			    $$ = $1;
X			    }
X
X			else
X			    $$ = link_machines( $1, copysingl( $1, $3 - 1 ) );
X			}
X
X		|  '.'
X			{
X			if ( ! madeany )
X			    {
X			    /* create the '.' character class */
X			    anyccl = cclinit();
X			    ccladd( anyccl, '\n' );
X			    cclnegate( anyccl );
X
X			    if ( useecs )
X				mkeccl( ccltbl + cclmap[anyccl],
X					ccllen[anyccl], nextecm,
X					ecgroup, CSIZE );
X			    
X			    madeany = true;
X			    }
X
X			++rulelen;
X
X			$$ = mkstate( -anyccl );
X			}
X
X		|  fullccl
X			{
X			if ( ! cclsorted )
X			    /* sort characters for fast searching.  We use a
X			     * shell sort since this list could be large.
X			     */
X			    cshell( ccltbl + cclmap[$1], ccllen[$1] );
X
X			if ( useecs )
X			    mkeccl( ccltbl + cclmap[$1], ccllen[$1],
X				    nextecm, ecgroup, CSIZE );
X				     
X			++rulelen;
X
X			$$ = mkstate( -$1 );
X			}
X
X		|  PREVCCL
X			{
X			++rulelen;
X
X			$$ = mkstate( -$1 );
X			}
X
X		|  '"' string '"'
X			{ $$ = $2; }
X
X		|  '(' re ')'
X			{ $$ = $2; }
X
X		|  CHAR
X			{
X			++rulelen;
X
X			if ( $1 == '\0' )
X			    synerr( "null in rule" );
X
X			if ( caseins && $1 >= 'A' && $1 <= 'Z' )
X			    $1 = clower( $1 );
X
X			$$ = mkstate( $1 );
X			}
X		;
X
Xfullccl		:  '[' ccl ']'
X			{ $$ = $2; }
X
X		|  '[' '^' ccl ']'
X			{
X			/* *Sigh* - to be compatible Unix lex, negated ccls
X			 * match newlines
X			 */
X#ifdef NOTDEF
X			ccladd( $3, '\n' ); /* negated ccls don't match '\n' */
X			cclsorted = false; /* because we added the newline */
X#endif
X			cclnegate( $3 );
X			$$ = $3;
X			}
X		;
X
Xccl             :  ccl CHAR '-' CHAR
X                        {
X			if ( $2 > $4 )
X			    synerr( "negative range in character class" );
X
X			else
X			    {
X			    if ( caseins )
X				{
X				if ( $2 >= 'A' && $2 <= 'Z' )
X				    $2 = clower( $2 );
X				if ( $4 >= 'A' && $4 <= 'Z' )
X				    $4 = clower( $4 );
X				}
X
X			    for ( i = $2; i <= $4; ++i )
X			        ccladd( $1, i );
X
X			    /* keep track if this ccl is staying in alphabetical
X			     * order
X			     */
X			    cclsorted = cclsorted && ($2 > lastchar);
X			    lastchar = $4;
X			    }
X			
X			$$ = $1;
X			}
X
X		|  ccl CHAR
X		        {
X			if ( caseins )
X			    if ( $2 >= 'A' && $2 <= 'Z' )
X				$2 = clower( $2 );
X
X			ccladd( $1, $2 );
X			cclsorted = cclsorted && ($2 > lastchar);
X			lastchar = $2;
X			$$ = $1;
X			}
X
X		|
X			{
X			cclsorted = true;
X			lastchar = 0;
X			$$ = cclinit();
X			}
X		;
X
Xstring		:  string CHAR
X                        {
X			if ( caseins )
X			    if ( $2 >= 'A' && $2 <= 'Z' )
X				$2 = clower( $2 );
X
X			++rulelen;
X
X			$$ = link_machines( $1, mkstate( $2 ) );
X			}
X
X		|
X			{ $$ = mkstate( SYM_EPSILON ); }
X		;
X
X%%
X
X/* synerr - report a syntax error
X *
X * synopsis
X *    char str[];
X *    synerr( str );
X */
X
Xsynerr( str )
Xchar str[];
X
X    {
X    syntaxerror = true;
X#ifdef MPW
X	fprintf( stderr, "File %s ;Line %d # Syntax error: %s\n",infilename,linenum, str );
X#else
X    fprintf( stderr, "Syntax error at line %d:  %s\n", linenum, str );
X#endif
X    }
X
X
X/* yyerror - eat up an error message from the parser
X *
X * synopsis
X *    char msg[];
X *    yyerror( msg );
X */
X
Xyyerror( msg )
Xchar msg[];
X
X    {
X    }
SHAR_EOF
if test 8970 -ne "`wc -c < 'parse.y'`"
then
	echo shar: error transmitting "'parse.y'" '(should have been 8970 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'scan.l'" '(9222 characters)'
if test -f 'scan.l'
then
	echo shar: will not over-write existing file "'scan.l'"
else
sed 's/^X//' << \SHAR_EOF > 'scan.l'
X/* scan.l - scanner for flex input */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X%{
X#include "flexdef.h"
X#include "parse.h"
X
X#define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
X#define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
X
X#undef YY_DECL
X#define YY_DECL \
X	int flexscan()
X
X#define RETURNCHAR \
X	yylval = yytext[0] & BYTEMASK; \
X	return ( CHAR );
X
X#define RETURNNAME \
X	(void) strcpy( nmstr, yytext ); \
X	return ( NAME );
X
X#define PUT_BACK_STRING(str, start) \
X	for ( i = strlen( str ) - 1; i >= start; --i ) \
X	    unput(str[i])
X%}
X
X%x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
X%x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT C_COMMENT_2 ACTION_COMMENT
X%x ACTION_STRING PERCENT_BRACE_ACTION
X
XWS		[ \t]+
X
XOPTWS		[ \t]*
X
XNAME		[a-z_][a-z_0-9]*
X
XSCNAME		{NAME}
X
XESCSEQ		\\([^^\n]|"^".|0[0-9]{1,3})
X
X%%
X    static int bracelevel, didadef;
X    int i, cclval;
X    char nmdef[MAXLINE], myesc();
X
X^{WS}.*\n		++linenum; ECHO; /* indented code */
X^#.*\n			++linenum; ECHO; /* treat as a comment */
X^"/*"			ECHO; BEGIN(C_COMMENT);
X^"%s"(tart)?		return ( SCDECL );
X^"%x"			return ( XSCDECL );
X^"%{".*\n		++linenum; line_directive_out( stdout ); BEGIN(CODEBLOCK);
X{WS}			return ( WHITESPACE );
X
X^"%%".*			{
X			sectnum = 2;
X			line_directive_out( stdout );
X			BEGIN(SECT2PROLOG);
X			return ( SECTEND );
X			}
X
X^"%"[^sx{%].*\n		{
X			fprintf( stderr,
X			     "old-style lex command at line %d ignored:\n\t%s",
X				 linenum, yytext );
X			++linenum;
X			}
X
X^{NAME}			{
X			(void) strcpy( nmstr, yytext );
X			didadef = false;
X			BEGIN(PICKUPDEF);
X			}
X
X{SCNAME}		RETURNNAME;
X^{OPTWS}\n		++linenum; /* allows blank lines in section 1 */
X\n			++linenum; return ( '\n' );
X.			synerr( "illegal character" ); BEGIN(RECOVER);
X
X
X<C_COMMENT>"*/"		ECHO; BEGIN(0);
X<C_COMMENT>"*/".*\n	++linenum; ECHO; BEGIN(0);
X<C_COMMENT>[^*\n]+	ECHO;
X<C_COMMENT>"*"		ECHO;
X<C_COMMENT>\n		++linenum; ECHO;
X
X<CODEBLOCK>^"%}".*\n	++linenum; BEGIN(0);
X<CODEBLOCK>.*\n		++linenum; ECHO;
X
X<PICKUPDEF>{WS}		/* separates name and definition */
X
X<PICKUPDEF>[^ \t\n].*	{
X			(void) strcpy( nmdef, yytext );
X
X			for ( i = strlen( nmdef ) - 1;
X			      i >= 0 &&
X			      nmdef[i] == ' ' || nmdef[i] == '\t';
X			      --i )
X			    ;
X
X			nmdef[i + 1] = '\0';
X
X                        ndinstal( nmstr, nmdef );
X			didadef = true;
X			}
X
X<PICKUPDEF>\n		{
X			if ( ! didadef )
X			    synerr( "incomplete name definition" );
X			BEGIN(0);
X			++linenum;
X			}
X
X<RECOVER>.*\n		++linenum; BEGIN(0); RETURNNAME;
X
X
X<SECT2PROLOG>.*\n/[^ \t\n]	{
X			++linenum;
X			ACTION_ECHO;
X			MARK_END_OF_PROLOG;
X			BEGIN(SECT2);
X			}
X
X<SECT2PROLOG>.*\n	++linenum; ACTION_ECHO;
X
X<SECT2>^{OPTWS}\n	++linenum; /* allow blank lines in section 2 */
X
X	/* this horrible mess of a rule matches indented lines which
X	 * do not contain "/*".  We need to make the distinction because
X	 * otherwise this rule will be taken instead of the rule which
X	 * matches the beginning of comments like this one
X	 */
X<SECT2>^{WS}([^/\n]|"/"[^*\n])*("/"?)\n	{
X			synerr( "indented code found outside of action" );
X			++linenum;
X			}
X
X<SECT2>"<"		BEGIN(SC); return ( '<' );
X<SECT2>^"^"		return ( '^' );
X<SECT2>\"		BEGIN(QUOTE); return ( '"' );
X<SECT2>"{"/[0-9]		BEGIN(NUM); return ( '{' );
X<SECT2>"{"[^0-9\n][^}\n]*	BEGIN(BRACEERROR);
X<SECT2>"$"/[ \t\n]	return ( '$' );
X
X<SECT2>{WS}"%{"		{
X			bracelevel = 1;
X			BEGIN(PERCENT_BRACE_ACTION);
X			return ( '\n' );
X			}
X<SECT2>{WS}"|".*\n	++linenum; return ( '\n' );
X
X<SECT2>^{OPTWS}"/*"	ACTION_ECHO; BEGIN(C_COMMENT_2);
X
X<SECT2>{WS}		{ /* needs to be separate from following rule due to
X			   * bug with trailing context
X			   */
X			bracelevel = 0;
X			BEGIN(ACTION);
X			return ( '\n' );
X			}
X
X<SECT2>{OPTWS}/\n	{
X			bracelevel = 0;
X			BEGIN(ACTION);
X			return ( '\n' );
X			}
X
X<SECT2>^{OPTWS}\n	++linenum; return ( '\n' );
X
X<SECT2>^"%%".*		{
X			/* guarantee that the SECT3 rule will have something
X			 * to match
X			 */
X			yyless(1);
X			sectnum = 3;
X			BEGIN(SECT3);
X			return ( EOF ); /* to stop the parser */
X			}
X
X<SECT2>"["([^\\\]\n]|{ESCSEQ})+"]"	{
X			(void) strcpy( nmstr, yytext );
X
X			/* check to see if we've already encountered this ccl */
X			if ( (cclval = ccllookup( nmstr )) )
X			    {
X			    yylval = cclval;
X			    ++cclreuse;
X			    return ( PREVCCL );
X			    }
X			else
X			    {
X			    /* we fudge a bit.  We know that this ccl will
X			     * soon be numbered as lastccl + 1 by cclinit
X			     */
X			    cclinstal( nmstr, lastccl + 1 );
X
X			    /* push back everything but the leading bracket
X			     * so the ccl can be rescanned
X			     */
X			    PUT_BACK_STRING(nmstr, 1);
X
X			    BEGIN(FIRSTCCL);
X			    return ( '[' );
X			    }
X			}
X
X<SECT2>"{"{NAME}"}"	{
X			register char *nmdefptr;
X			char *ndlookup();
X
X			(void) strcpy( nmstr, yytext );
X			nmstr[yyleng - 1] = '\0';  /* chop trailing brace */
X
X			/* lookup from "nmstr + 1" to chop leading brace */
X			if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
X			    synerr( "undefined {name}" );
X
X			else
X			    { /* push back name surrounded by ()'s */
X			    unput(')');
X			    PUT_BACK_STRING(nmdefptr, 0);
X			    unput('(');
X			    }
X			}
X
X<SECT2>[/|*+?.()]	return ( yytext[0] );
X<SECT2>.		RETURNCHAR;
X<SECT2>\n		++linenum; return ( '\n' );
X
X
X<SC>","			return ( ',' );
X<SC>">"			BEGIN(SECT2); return ( '>' );
X<SC>">"/"^"		BEGIN(CARETISBOL); return ( '>' );
X<SC>{SCNAME}		RETURNNAME;
X<SC>.			synerr( "bad start condition name" );
X
X<CARETISBOL>"^"		BEGIN(SECT2); return ( '^' );
X
X
X<QUOTE>[^"\n]		RETURNCHAR;
X<QUOTE>\"		BEGIN(SECT2); return ( '"' );
X
X<QUOTE>\n		{
X			synerr( "missing quote" );
X			BEGIN(SECT2);
X			++linenum;
X			return ( '"' );
X			}
X
X
X<FIRSTCCL>"^"/[^-\n]	BEGIN(CCL); return ( '^' );
X<FIRSTCCL>"^"/-		return ( '^' );
X<FIRSTCCL>-		BEGIN(CCL); yylval = '-'; return ( CHAR );
X<FIRSTCCL>.		BEGIN(CCL); RETURNCHAR;
X
X<CCL>-/[^\]\n]		return ( '-' );
X<CCL>[^\]\n]		RETURNCHAR;
X<CCL>"]"			BEGIN(SECT2); return ( ']' );
X
X
X<NUM>[0-9]+		{
X			yylval = myctoi( yytext );
X			return ( NUMBER );
X			}
X
X<NUM>","			return ( ',' );
X<NUM>"}"			BEGIN(SECT2); return ( '}' );
X
X<NUM>.			{
X			synerr( "bad character inside {}'s" );
X			BEGIN(SECT2);
X			return ( '}' );
X			}
X
X<NUM>\n			{
X			synerr( "missing }" );
X			BEGIN(SECT2);
X			++linenum;
X			return ( '}' );
X			}
X
X
X<BRACEERROR>"}"		synerr( "bad name in {}'s" ); BEGIN(SECT2);
X<BRACEERROR>\n		synerr( "missing }" ); ++linenum; BEGIN(SECT2);
X
X
X<PERCENT_BRACE_ACTION>{OPTWS}"%}".*	bracelevel = 0;
X<PERCENT_BRACE_ACTION>.*		ACTION_ECHO;
X<PERCENT_BRACE_ACTION>\n		{
X			++linenum;
X			ACTION_ECHO;
X			if ( bracelevel == 0 )
X			    {
X			    fputs( "\tYY_BREAK\n", temp_action_file );
X			    BEGIN(SECT2);
X			    }
X			}
X
X<ACTION>"{"		ACTION_ECHO; ++bracelevel;
X<ACTION>"}"		ACTION_ECHO; --bracelevel;
X<ACTION>[^{}"'/\n]+	ACTION_ECHO;
X<ACTION>"/*"		ACTION_ECHO; BEGIN(ACTION_COMMENT);
X<ACTION>"'"([^'\\\n]|\\.)*"'"	ACTION_ECHO; /* character constant */
X<ACTION>\"		ACTION_ECHO; BEGIN(ACTION_STRING);
X<ACTION>\n		{
X			++linenum;
X			ACTION_ECHO;
X			if ( bracelevel == 0 )
X			    {
X			    fputs( "\tYY_BREAK\n", temp_action_file );
X			    BEGIN(SECT2);
X			    }
X			}
X<ACTION>.		ACTION_ECHO;
X
X<ACTION_COMMENT>"*/"	ACTION_ECHO; BEGIN(ACTION);
X<ACTION_COMMENT>[^*\n]+	ACTION_ECHO;
X<ACTION_COMMENT>"*"	ACTION_ECHO;
X<ACTION_COMMENT>\n	++linenum; ACTION_ECHO;
X<ACTION_COMMENT>.	ACTION_ECHO;
X
X<C_COMMENT_2>"*/"	ACTION_ECHO; BEGIN(SECT2);
X<C_COMMENT_2>"*/".*\n	++linenum; ACTION_ECHO; BEGIN(SECT2);
X<C_COMMENT_2>[^*\n]+	ACTION_ECHO;
X<C_COMMENT_2>"*"	ACTION_ECHO;
X<C_COMMENT_2>\n		++linenum; ACTION_ECHO;
X
X<ACTION_STRING>[^"\\\n]+	ACTION_ECHO;
X<ACTION_STRING>\\.	ACTION_ECHO;
X<ACTION_STRING>\n	++linenum; ACTION_ECHO;
X<ACTION_STRING>\"	ACTION_ECHO; BEGIN(ACTION);
X<ACTION_STRING>.	ACTION_ECHO;
X
X
X<SECT2,QUOTE,CCL>{ESCSEQ}	{
X			yylval = myesc( yytext ) & BYTEMASK;
X			return ( CHAR );
X			}
X
X<FIRSTCCL>{ESCSEQ}	{
X			yylval = myesc( yytext ) & BYTEMASK;
X			BEGIN(CCL);
X			return ( CHAR );
X			}
X
X
X<SECT3>.|\n		{
X			register int numchars;
X
X			/* black magic - we know the names of a flex scanner's
X			 * internal variables.  We cap the input buffer with
X			 * an end-of-string and dump it to the output.
X			 */
X			YY_DO_BEFORE_SCAN; /* recover from setting up yytext */
X
X#ifdef FLEX_FAST_SKEL
X			fputs( yy_c_buf_p + 1, stdout );
X#else
X			yy_ch_buf[yy_e_buf_p + 1] = '\0';
X
X			/* ignore the first character; it's the second '%'
X			 * put back by the yyless(1) above
X			 */
X			fputs( yy_ch_buf + yy_c_buf_p + 1, stdout );
X#endif
X
X			/* if we don't do this, the data written by write()
X			 * can get overwritten when stdout is finally flushed
X			 */
X			(void) fflush( stdout );
X
X			while ( (numchars = read( fileno(yyin), yy_ch_buf,
X						  YY_BUF_MAX )) > 0 )
X			    (void) write( fileno(stdout), yy_ch_buf, numchars );
X	
X			if ( numchars < 0 )
X			    flexerror( "fatal read error in section 3" );
X
X			return ( EOF );
X			}
X%%
SHAR_EOF
if test 9222 -ne "`wc -c < 'scan.l'`"
then
	echo shar: error transmitting "'scan.l'" '(should have been 9222 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 4 ---

earleh@eleazar.dartmouth.edu (Earle R. Horton) (07/02/88)

[Flex for the Mac - part 5 of 7]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	flex/scan.c.dist
# This archive created: Wed Jun 29 07:03:25 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'scan.c.dist'" '(38884 characters)'
if test -f 'scan.c.dist'
then
	echo shar: will not over-write existing file "'scan.c.dist'"
else
sed 's/^X//' << \SHAR_EOF > 'scan.c.dist'
X#define YY_DEFAULT_ACTION YY_FATAL_ERROR( "flex scanner jammed" );
X#define FLEX_USE_ECS
X#define FLEX_USE_MECS
X/* A lexical scanner generated by flex */
X
X#include "flexskeldef.h"
X
X# line 1 "scan.l"
X#define INITIAL 0
X/* scan.l - scanner for flex input */
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X# line 16 "scan.l"
X#include "flexdef.h"
X#include "parse.h"
X
X#define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
X#define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
X
X#undef YY_DECL
X#define YY_DECL \
X	int flexscan()
X
X#define RETURNCHAR \
X	yylval = yytext[0] & BYTEMASK; \
X	return ( CHAR );
X
X#define RETURNNAME \
X	(void) strcpy( nmstr, yytext ); \
X	return ( NAME );
X
X#define PUT_BACK_STRING(str, start) \
X	for ( i = strlen( str ) - 1; i >= start; --i ) \
X	    unput(str[i])
X#define SECT2 2
X#define SECT2PROLOG 4
X#define SECT3 6
X#define CODEBLOCK 8
X#define PICKUPDEF 10
X#define SC 12
X#define CARETISBOL 14
X#define NUM 16
X#define QUOTE 18
X#define FIRSTCCL 20
X#define CCL 22
X#define ACTION 24
X#define RECOVER 26
X#define BRACEERROR 28
X#define C_COMMENT 30
X#define C_COMMENT_2 32
X#define ACTION_COMMENT 34
X#define ACTION_STRING 36
X#define PERCENT_BRACE_ACTION 38
X# line 53 "scan.l"
X#define YY_JAM 226
X#define YY_JAM_BASE 800
X#define YY_TEMPLATE 227
Xstatic char l[227] =
X    {   0,
X       -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
X       -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
X       -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
X       -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
X       14,    7,   13,   11,    7,   12,   14,   14,   14,   10,
X       46,   39,   40,   32,   46,   45,   30,   46,   46,   46,
X       39,   28,   46,   45,   31,    0,   27,   99,    0,   21,
X        0,   23,   22,   24,   52,   48,   49,   51,   53,   67,
X       68,   65,   64,   66,   54,   56,   55,   54,   60,   59,
X       60,   60,   62,   62,   62,   63,   76,   80,   79,   81,
X
X       81,   74,   75,    0,   25,   70,   69,   17,   19,   18,
X       89,   91,   90,   83,   85,   84,   92,   94,   95,   96,
X       72,   72,   73,   72,    7,   11,    0,    7,    1,    0,
X        2,    0,    8,    4,    5,    0,    3,   10,   39,   40,
X        0,    0,   35,    0,    0,   97,   97,    0,   34,   33,
X       34,    0,   39,   28,    0,    0,    0,   42,   38,   26,
X        0,   23,   50,   51,   64,   98,   98,    0,   57,   58,
X       61,   76,    0,   78,    0,   77,   15,   87,   83,   82,
X       92,   93,   71,    1,    0,    9,    8,    0,    0,    6,
X       36,    0,   37,   43,    0,    0,   97,   34,   34,   44,
X
X       29,    0,   36,    0,   29,    0,   42,    0,   20,   98,
X        0,   16,    0,   88,   71,    0,    0,   97,   98,    0,
X        0,   97,   98,    4,    0,    0
X    } ;
X/*
X * Two things to watch out for here.  Size of character set, and
X * which character is the newline.  For this reason, and because
X * I want to supply a copy of scan.c.dist which works for all
X * systems, "make test" will produce output which you will have
X * to interpret yourself.
X */
X#if MPW
X/* Initial table for eight-bit chars, '\n' = 13. */
Xstatic char e[256] =
X    {   0,
X        1,    1,    1,    1,    1,    1,    1,    1,    2,    1,
X        1,    1,    3,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    2,    1,    4,    5,    6,    7,    1,    8,    9,
X        9,   10,    9,   11,   12,    9,   13,   14,   15,   15,
X       15,   15,   15,   15,   15,   15,   15,    1,    1,   16,
X        1,   17,    9,    1,   23,   22,   22,   22,   22,   22,
X       22,   22,   22,   22,   22,   22,   22,   22,   22,   22,
X       22,   24,   25,   26,   22,   22,   22,   27,   22,   22,
X       18,   19,   20,   21,   22,    1,   23,   22,   22,   22,
X
X       22,   22,   22,   22,   22,   22,   22,   22,   22,   22,
X       22,   22,   22,   24,   25,   26,   22,   22,   22,   27,
X       22,   22,   28,   29,   30,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1
X    } ;
X#else
X/* Initial table for seven-bit chars, '\n' = 10. */
Xstatic char e[128] =
X    {   0,
X        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
X        1,    2,    1,    4,    5,    6,    7,    1,    8,    9,
X        9,   10,    9,   11,   12,    9,   13,   14,   15,   15,
X       15,   15,   15,   15,   15,   15,   15,    1,    1,   16,
X        1,   17,    9,    1,   23,   22,   22,   22,   22,   22,
X       22,   22,   22,   22,   22,   22,   22,   22,   22,   22,
X       22,   24,   25,   26,   22,   22,   22,   27,   22,   22,
X       18,   19,   20,   21,   22,    1,   23,   22,   22,   22,
X
X       22,   22,   22,   22,   22,   22,   22,   22,   22,   22,
X       22,   22,   22,   24,   25,   26,   22,   22,   22,   27,
X       22,   22,   28,   29,   30,    1,    1
X    } ;
X#endif
X
Xstatic char m[31] =
X    {   0,
X        1,    2,    3,    4,    1,    1,    1,    5,    1,    6,
X        1,    1,    5,    7,    7,    1,    1,    1,    8,    9,
X        1,    7,    7,    7,    7,    7,    7,    5,    1,   10
X    } ;
X
Xstatic short int b[276] =
X    {   0,
X        0,   26,   52,   80,  286,  285,    0,    0,  284,    1,
X        3,    7,   99,  116,  265,  264,  141,  169,   11,   13,
X        0,   22,   25,   47,  197,  225,  281,  280,    8,   10,
X       32,   54,   66,   69,   75,   85,   88,   99,  110,  112,
X      800,  280,  800,    0,   44,  800,  277,  104,  269,    0,
X      800,  144,  800,  800,   71,  800,  800,  259,   83,  242,
X      268,  800,  270,  266,  800,  271,    0,  800,  270,  800,
X       33,    0,  270,  800,  800,  800,  242,    0,  800,  800,
X      800,  800,   91,  800,  800,  800,  800,  114,  800,  800,
X      116,  250,  800,    0,  136,  800,    0,  800,  800,  126,
X
X      251,  800,  800,  257,  800,  800,  800,  150,  800,  246,
X      151,  800,  245,    0,  800,  241,    0,  800,  800,    0,
X      249,  156,  800,  145,  249,    0,  247,  162,  800,  246,
X      800,  245,    0,  219,  800,  234,  800,    0,  167,  800,
X      206,  229,  800,  147,  165,  800,  162,    0,    0,  800,
X      284,  165,  313,  800,  178,  179,  184,    0,  800,  800,
X      218,    0,  800,    0,  178,  800,  180,    0,  800,  800,
X      800,    0,  190,  800,    0,  800,  216,  187,    0,  800,
X        0,  800,    0,  800,  185,  800,    0,  139,  146,  800,
X      800,  133,  800,  800,  188,  100,  197,    0,    0,  800,
X
X      800,  210,  201,  213,  800,  212,    0,   97,  800,  203,
X       91,  800,   74,  800,    0,   51,  216,  209,  225,   34,
X      227,  800,  800,  800,  224,  800,  342,  352,  362,  372,
X      382,  392,  402,  412,  422,  432,  442,  452,  462,  472,
X      482,  492,  502,  512,   13,  522,  532,  542,   11,  552,
X      562,  572,  582,  592,  602,    0,  612,  622,  632,  642,
X      651,  661,  671,  681,  691,  701,  711,  721,  731,  740,
X      750,  760,  770,  780,  790
X    } ;
X
Xstatic short int d[276] =
X    {   0,
X      227,  227,  228,  228,  229,  229,  230,  230,  231,  231,
X      232,  232,  233,  233,  226,  226,  234,  234,  235,  235,
X      236,  236,  237,  237,  238,  238,  239,  239,  226,  226,
X      240,  240,  241,  241,  242,  242,  243,  243,  244,  244,
X      226,  226,  226,  245,  246,  226,  247,  248,  226,  249,
X      226,  226,  226,  226,  226,  226,  226,  250,  251,  252,
X      253,  226,  226,  226,  226,  229,  254,  226,  231,  226,
X      231,  255,  226,  226,  226,  226,  226,  256,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  251,  226,  226,
X      257,  258,  226,  259,  251,  226,  260,  226,  226,  261,
X
X      226,  226,  226,  239,  226,  226,  226,  240,  226,  226,
X      241,  226,  226,  262,  226,  226,  263,  226,  226,  264,
X      244,  244,  226,  244,  226,  245,  246,  246,  226,  247,
X      226,  265,  266,  226,  226,  267,  226,  249,  226,  226,
X      226,  268,  226,  250,  250,  226,  226,  251,  269,  226,
X      269,  253,  253,  226,  253,  253,  270,  271,  226,  226,
X      272,  255,  226,  256,  226,  226,  226,  257,  226,  226,
X      226,  260,  261,  226,  261,  226,  273,  274,  262,  226,
X      263,  226,  275,  226,  265,  226,  266,  226,  267,  226,
X      226,  268,  226,  226,  250,  250,  226,  269,  151,  226,
X
X      226,  253,  253,  270,  226,  270,  271,  272,  226,  226,
X      273,  226,  274,  226,  275,  226,  250,  226,  226,  226,
X      250,  226,  226,  226,  250,-32767,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  226,  226,  226,  226
X    } ;
X
Xstatic short int n[831] =
X    {   0,
X      226,   42,   43,   70,   73,   74,  164,   71,   73,   74,
X      106,   90,  106,   86,   87,   86,   87,  138,   91,  126,
X       92,   44,   44,   44,   44,   44,   44,   45,   46,   88,
X       47,   88,   48,   90,  109,   70,   94,  107,   49,  107,
X       91,  110,   92,   95,   96,  128,  129,   50,   50,   50,
X       50,   50,   50,   52,   53,   54,  109,   55,   94,  224,
X       56,   56,  161,  110,   56,   95,   96,   57,  112,   58,
X       59,  112,  143,  143,  220,  113,  214,  115,  113,   60,
X       56,   61,   62,   54,  116,   55,   63,  115,   56,   56,
X      118,  119,   64,  212,  116,   57,  147,   58,   59,  209,
X
X       65,  118,  119,  148,  165,  165,  120,   60,   56,   76,
X      133,  122,  123,  122,  123,   77,  124,  120,  124,  144,
X       78,   78,   78,   78,   78,   78,   76,  147,  134,  167,
X      135,  136,   77,  174,  148,  193,  168,   78,   78,   78,
X       78,   78,   78,   81,  175,  139,  140,  226,  190,  147,
X      141,   82,  226,  226,   83,   83,  148,  122,  226,  226,
X      226,  216,  124,  128,  129,  145,  194,  201,  139,  140,
X       84,   81,  142,  141,  183,  197,  197,  202,  195,   82,
X      201,  201,   83,   83,  144,  196,  205,  186,  159,  214,
X      202,  165,  165,  210,  210,  142,  206,  174,   84,   98,
X
X       99,  217,  217,  201,  100,  203,  145,  194,  175,  101,
X      218,  218,  201,  202,  205,  205,  219,  219,  212,  226,
X      209,  192,  222,  222,  102,  206,  103,   98,   99,  221,
X      221,  193,  100,  191,  145,  194,  190,  101,  223,  223,
X      225,  225,  145,  194,  188,  145,  194,  186,  131,  184,
X      125,  226,  102,  180,  103,  150,  150,  178,  177,  105,
X      176,  170,  163,  151,  151,  151,  151,  151,  151,  153,
X      154,   73,   70,   67,  155,  159,  158,  145,  137,  131,
X      156,  125,  105,  105,   79,   79,   70,   67,   67,  226,
X      226,  226,  226,  226,  226,  226,  157,  199,  199,  226,
X
X      226,  226,  226,  226,  226,  199,  199,  199,  199,  199,
X      199,  226,  226,  200,  153,  154,  226,  226,  226,  155,
X      226,  226,  226,  226,  226,  156,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  157,   41,   41,   41,   41,   41,   41,   41,   41,
X       41,   41,   51,   51,   51,   51,   51,   51,   51,   51,
X       51,   51,   66,   66,   66,   66,   66,   66,   66,   66,
X       66,   66,   68,   68,   68,   68,   68,   68,   68,   68,
X       68,   68,   69,   69,   69,   69,   69,   69,   69,   69,
X       69,   69,   72,   72,   72,   72,   72,   72,   72,   72,
X
X       72,   72,   75,   75,  226,   75,   75,   75,   75,   75,
X       75,   75,   80,   80,   80,   80,   80,   80,   80,   80,
X       80,   80,   85,   85,   85,   85,   85,   85,   85,   85,
X       85,   85,   89,   89,  226,   89,   89,   89,   89,   89,
X       89,   89,   93,   93,  226,   93,   93,   93,   93,   93,
X       93,   93,   97,   97,   97,   97,   97,   97,   97,   97,
X       97,   97,  104,  104,  104,  104,  104,  104,  104,  104,
X      104,  104,  108,  108,  108,  108,  108,  108,  108,  108,
X      108,  108,  111,  111,  111,  111,  111,  111,  111,  111,
X      111,  111,  114,  114,  114,  114,  114,  114,  114,  114,
X
X      114,  114,  117,  117,  117,  117,  117,  117,  117,  117,
X      117,  117,  121,  121,  121,  121,  121,  121,  121,  121,
X      121,  121,  127,  127,  127,  127,  127,  127,  127,  127,
X      127,  127,  130,  130,  130,  130,  130,  130,  130,  130,
X      130,  130,  132,  132,  132,  132,  132,  132,  132,  132,
X      132,  132,  144,  144,  226,  144,  144,  144,  144,  144,
X      226,  144,  146,  146,  226,  146,  146,  146,  146,  146,
X      146,  146,  149,  149,  226,  149,  149,  149,  149,  149,
X      149,  149,  152,  152,  152,  152,  152,  152,  152,  152,
X      152,  152,  160,  226,  226,  160,  160,  160,  160,  160,
X
X      160,  160,  162,  162,  226,  162,  162,  162,  162,  162,
X      162,  162,  166,  166,  226,  166,  166,  166,  166,  166,
X      166,  166,  169,  169,  226,  169,  169,  169,  169,  169,
X      169,  169,  171,  171,  226,  171,  171,  171,  171,  171,
X      226,  171,  172,  172,  226,  226,  226,  172,  172,  172,
X      172,  173,  173,  226,  173,  173,  173,  173,  173,  173,
X      173,  179,  179,  226,  179,  179,  226,  179,  179,  179,
X      179,  181,  181,  226,  226,  181,  181,  181,  226,  181,
X      181,  182,  182,  226,  182,  182,  182,  182,  182,  182,
X      182,  185,  185,  185,  185,  185,  185,  185,  185,  185,
X
X      185,  187,  187,  226,  187,  187,  187,  187,  187,  187,
X      187,  189,  189,  189,  189,  189,  189,  189,  189,  189,
X      189,  192,  192,  192,  192,  192,  192,  192,  192,  192,
X      192,  198,  198,  226,  198,  198,  198,  198,  198,  198,
X      204,  204,  204,  204,  204,  204,  204,  204,  204,  204,
X      207,  207,  226,  207,  207,  207,  207,  207,  207,  207,
X      208,  208,  208,  208,  208,  208,  208,  208,  208,  208,
X      211,  211,  211,  211,  211,  211,  211,  211,  211,  211,
X      213,  213,  213,  213,  213,  213,  213,  213,  213,  213,
X      215,  215,  226,  215,  215,  215,  215,  215,  215,  215,
X
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226
X    } ;
X
Xstatic short int c[831] =
X    {   0,
X        0,    1,    1,   10,   11,   11,  256,   10,   12,   12,
X       29,   21,   30,   19,   19,   20,   20,  249,   21,  245,
X       21,    1,    1,    1,    1,    1,    1,    2,    2,   19,
X        2,   20,    2,   22,   31,   71,   23,   29,    2,   30,
X       22,   31,   22,   23,   23,   45,   45,    2,    2,    2,
X        2,    2,    2,    3,    3,    3,   32,    3,   24,  220,
X        3,    3,   71,   32,    3,   24,   24,    3,   33,    3,
X        3,   34,   55,   55,  216,   33,  213,   35,   34,    3,
X        3,    4,    4,    4,   35,    4,    4,   36,    4,    4,
X       37,   37,    4,  211,   36,    4,   59,    4,    4,  208,
X
X        4,   38,   38,   59,   83,   83,   37,    4,    4,   13,
X       48,   39,   39,   40,   40,   13,   39,   38,   40,  196,
X       13,   13,   13,   13,   13,   13,   14,   88,   48,   91,
X       48,   48,   14,  100,   88,  192,   91,   14,   14,   14,
X       14,   14,   14,   17,  100,   52,   52,  124,  189,   95,
X       52,   17,  108,  111,   17,   17,   95,  122,  122,  108,
X      111,  188,  122,  128,  128,  144,  144,  152,  139,  139,
X       17,   18,   52,  139,  124,  147,  147,  152,  145,   18,
X      155,  156,   18,   18,  145,  145,  157,  185,  156,  178,
X      155,  165,  165,  167,  167,  139,  157,  173,   18,   25,
X
X       25,  195,  195,  203,   25,  155,  195,  195,  173,   25,
X      197,  197,  202,  203,  206,  204,  210,  210,  177,  202,
X      161,  206,  218,  218,   25,  204,   25,   26,   26,  217,
X      217,  142,   26,  141,  217,  217,  136,   26,  219,  219,
X      221,  221,  225,  225,  134,  221,  221,  132,  130,  127,
X      125,  121,   26,  116,   26,   60,   60,  113,  110,  104,
X      101,   92,   77,   60,   60,   60,   60,   60,   60,   61,
X       61,   73,   69,   66,   61,   64,   63,   58,   49,   47,
X       61,   42,   28,   27,   16,   15,    9,    6,    5,    0,
X        0,    0,    0,    0,    0,    0,   61,  151,  151,    0,
X
X        0,    0,    0,    0,    0,  151,  151,  151,  151,  151,
X      151,    0,    0,  151,  153,  153,    0,    0,    0,  153,
X        0,    0,    0,    0,    0,  153,    0,    0,    0,    0,
X        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
X        0,  153,  227,  227,  227,  227,  227,  227,  227,  227,
X      227,  227,  228,  228,  228,  228,  228,  228,  228,  228,
X      228,  228,  229,  229,  229,  229,  229,  229,  229,  229,
X      229,  229,  230,  230,  230,  230,  230,  230,  230,  230,
X      230,  230,  231,  231,  231,  231,  231,  231,  231,  231,
X      231,  231,  232,  232,  232,  232,  232,  232,  232,  232,
X
X      232,  232,  233,  233,    0,  233,  233,  233,  233,  233,
X      233,  233,  234,  234,  234,  234,  234,  234,  234,  234,
X      234,  234,  235,  235,  235,  235,  235,  235,  235,  235,
X      235,  235,  236,  236,    0,  236,  236,  236,  236,  236,
X      236,  236,  237,  237,    0,  237,  237,  237,  237,  237,
X      237,  237,  238,  238,  238,  238,  238,  238,  238,  238,
X      238,  238,  239,  239,  239,  239,  239,  239,  239,  239,
X      239,  239,  240,  240,  240,  240,  240,  240,  240,  240,
X      240,  240,  241,  241,  241,  241,  241,  241,  241,  241,
X      241,  241,  242,  242,  242,  242,  242,  242,  242,  242,
X
X      242,  242,  243,  243,  243,  243,  243,  243,  243,  243,
X      243,  243,  244,  244,  244,  244,  244,  244,  244,  244,
X      244,  244,  246,  246,  246,  246,  246,  246,  246,  246,
X      246,  246,  247,  247,  247,  247,  247,  247,  247,  247,
X      247,  247,  248,  248,  248,  248,  248,  248,  248,  248,
X      248,  248,  250,  250,    0,  250,  250,  250,  250,  250,
X        0,  250,  251,  251,    0,  251,  251,  251,  251,  251,
X      251,  251,  252,  252,    0,  252,  252,  252,  252,  252,
X      252,  252,  253,  253,  253,  253,  253,  253,  253,  253,
X      253,  253,  254,    0,    0,  254,  254,  254,  254,  254,
X
X      254,  254,  255,  255,    0,  255,  255,  255,  255,  255,
X      255,  255,  257,  257,    0,  257,  257,  257,  257,  257,
X      257,  257,  258,  258,    0,  258,  258,  258,  258,  258,
X      258,  258,  259,  259,    0,  259,  259,  259,  259,  259,
X        0,  259,  260,  260,    0,    0,    0,  260,  260,  260,
X      260,  261,  261,    0,  261,  261,  261,  261,  261,  261,
X      261,  262,  262,    0,  262,  262,    0,  262,  262,  262,
X      262,  263,  263,    0,    0,  263,  263,  263,    0,  263,
X      263,  264,  264,    0,  264,  264,  264,  264,  264,  264,
X      264,  265,  265,  265,  265,  265,  265,  265,  265,  265,
X
X      265,  266,  266,    0,  266,  266,  266,  266,  266,  266,
X      266,  267,  267,  267,  267,  267,  267,  267,  267,  267,
X      267,  268,  268,  268,  268,  268,  268,  268,  268,  268,
X      268,  269,  269,    0,  269,  269,  269,  269,  269,  269,
X      270,  270,  270,  270,  270,  270,  270,  270,  270,  270,
X      271,  271,    0,  271,  271,  271,  271,  271,  271,  271,
X      272,  272,  272,  272,  272,  272,  272,  272,  272,  272,
X      273,  273,  273,  273,  273,  273,  273,  273,  273,  273,
X      274,  274,  274,  274,  274,  274,  274,  274,  274,  274,
X      275,  275,    0,  275,  275,  275,  275,  275,  275,  275,
X
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
X      226,  226,  226,  226,  226,  226,  226,  226,  226,  226
X    } ;
X
X
X/* these declarations have to come after the section 1 code or lint gets
X * confused about whether the variables are used
X */
XFILE *yyin = stdin, *yyout = stdout;
X
X/* these variables are all declared out here so that section 3 code can
X * manipulate them
X */
Xstatic int yy_start, yy_b_buf_p, yy_c_buf_p, yy_e_buf_p;
Xstatic int yy_saw_eof, yy_init = 1;
X
X/* yy_ch_buf has to be 1 character longer than YY_BUF_SIZE, since when
X * setting up yytext we can try to put a '\0' just past the end of the
X * matched text
X */
X#ifdef MALLOC_BUFFERS
Xstatic char *yy_ch_buf = 0L;
Xstatic int *yy_st_buf = 0L;
X#else
Xstatic char yy_ch_buf[YY_BUF_SIZE + 1];
Xstatic int yy_st_buf[YY_BUF_SIZE];
X#endif
Xstatic char yy_hold_char;
Xchar *yytext;
Xstatic int yyleng;
X
XYY_DECL
X    {
X    int yy_n_chars, yy_lp, yy_iii, yy_buf_pos, yy_act;
X
X
X    static int bracelevel, didadef;
X    int i, cclval;
X    char nmdef[MAXLINE], myesc();
X
X
X#ifdef MALLOC_BUFFERS
X	if(yy_ch_buf == 0L){
X		yy_ch_buf = (char *)malloc(YY_BUF_SIZE + 1);
X		yy_st_buf = (int *)malloc(YY_BUF_SIZE * sizeof(int));
X		if(yy_ch_buf == 0L || yy_st_buf == 0L){
X			fprintf( stderr, "Out of memory\n");
X			exit(-1);
X		}
X	}
X#endif
X    if ( yy_init )
X	{
X	YY_INIT;
X	yy_start = 1;
X	yy_init = 0;
X	}
X
X    goto get_next_token;
X
Xdo_action:
X    for ( ; ; )
X	{
X	YY_DO_BEFORE_ACTION
X
X#ifdef FLEX_DEBUG
X	fprintf( stderr, "--accepting rule #%d\n", yy_act );
X#endif
X	switch ( yy_act )
X	    {
Xcase 1:
X# line 58 "scan.l"
X++linenum; ECHO; /* indented code */
X	YY_BREAK
Xcase 2:
X# line 59 "scan.l"
X++linenum; ECHO; /* treat as a comment */
X	YY_BREAK
Xcase 3:
X# line 60 "scan.l"
XECHO; BEGIN(C_COMMENT);
X	YY_BREAK
Xcase 4:
X# line 61 "scan.l"
Xreturn ( SCDECL );
X	YY_BREAK
Xcase 5:
X# line 62 "scan.l"
Xreturn ( XSCDECL );
X	YY_BREAK
Xcase 6:
X# line 63 "scan.l"
X++linenum; line_directive_out( stdout ); BEGIN(CODEBLOCK);
X	YY_BREAK
Xcase 7:
X# line 64 "scan.l"
Xreturn ( WHITESPACE );
X	YY_BREAK
Xcase 8:
X# line 66 "scan.l"
X{
X			sectnum = 2;
X			line_directive_out( stdout );
X			BEGIN(SECT2PROLOG);
X			return ( SECTEND );
X			}
X	YY_BREAK
Xcase 9:
X# line 73 "scan.l"
X{
X			fprintf( stderr,
X			     "old-style lex command at line %d ignored:\n\t%s",
X				 linenum, yytext );
X			++linenum;
X			}
X	YY_BREAK
Xcase 10:
X# line 80 "scan.l"
X{
X			(void) strcpy( nmstr, yytext );
X			didadef = false;
X			BEGIN(PICKUPDEF);
X			}
X	YY_BREAK
Xcase 11:
X# line 86 "scan.l"
XRETURNNAME;
X	YY_BREAK
Xcase 12:
X# line 87 "scan.l"
X++linenum; /* allows blank lines in section 1 */
X	YY_BREAK
Xcase 13:
X# line 88 "scan.l"
X++linenum; return ( '\n' );
X	YY_BREAK
Xcase 14:
X# line 89 "scan.l"
Xsynerr( "illegal character" ); BEGIN(RECOVER);
X	YY_BREAK
Xcase 15:
X# line 92 "scan.l"
XECHO; BEGIN(0);
X	YY_BREAK
Xcase 16:
X# line 93 "scan.l"
X++linenum; ECHO; BEGIN(0);
X	YY_BREAK
Xcase 17:
X# line 94 "scan.l"
XECHO;
X	YY_BREAK
Xcase 18:
X# line 95 "scan.l"
XECHO;
X	YY_BREAK
Xcase 19:
X# line 96 "scan.l"
X++linenum; ECHO;
X	YY_BREAK
Xcase 20:
X# line 98 "scan.l"
X++linenum; BEGIN(0);
X	YY_BREAK
Xcase 21:
X# line 99 "scan.l"
X++linenum; ECHO;
X	YY_BREAK
Xcase 22:
X# line 101 "scan.l"
X/* separates name and definition */
X	YY_BREAK
Xcase 23:
X# line 103 "scan.l"
X{
X			(void) strcpy( nmdef, yytext );
X
X			for ( i = strlen( nmdef ) - 1;
X			      i >= 0 &&
X			      nmdef[i] == ' ' || nmdef[i] == '\t';
X			      --i )
X			    ;
X
X			nmdef[i + 1] = '\0';
X
X                        ndinstal( nmstr, nmdef );
X			didadef = true;
X			}
X	YY_BREAK
Xcase 24:
X# line 118 "scan.l"
X{
X			if ( ! didadef )
X			    synerr( "incomplete name definition" );
X			BEGIN(0);
X			++linenum;
X			}
X	YY_BREAK
Xcase 25:
X# line 125 "scan.l"
X++linenum; BEGIN(0); RETURNNAME;
X	YY_BREAK
Xcase 26:
XYY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
Xyy_c_buf_p -= 1;
XYY_DO_BEFORE_ACTION; /* set up yytext again */
X# line 128 "scan.l"
X{
X			++linenum;
X			ACTION_ECHO;
X			MARK_END_OF_PROLOG;
X			BEGIN(SECT2);
X			}
X	YY_BREAK
Xcase 27:
X# line 135 "scan.l"
X++linenum; ACTION_ECHO;
X	YY_BREAK
Xcase 28:
X# line 137 "scan.l"
X++linenum; /* allow blank lines in section 2 */
X	YY_BREAK
X	/* this horrible mess of a rule matches indented lines which
X	 * do not contain "/*".  We need to make the distinction because
X	 * otherwise this rule will be taken instead of the rule which
X	 * matches the beginning of comments like this one
X	 */
Xcase 29:
X# line 144 "scan.l"
X{
X			synerr( "indented code found outside of action" );
X			++linenum;
X			}
X	YY_BREAK
Xcase 30:
X# line 149 "scan.l"
XBEGIN(SC); return ( '<' );
X	YY_BREAK
Xcase 31:
X# line 150 "scan.l"
Xreturn ( '^' );
X	YY_BREAK
Xcase 32:
X# line 151 "scan.l"
XBEGIN(QUOTE); return ( '"' );
X	YY_BREAK
Xcase 33:
XYY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
Xyy_c_buf_p = yy_b_buf_p;
XYY_DO_BEFORE_ACTION; /* set up yytext again */
X# line 152 "scan.l"
XBEGIN(NUM); return ( '{' );
X	YY_BREAK
Xcase 34:
X# line 153 "scan.l"
XBEGIN(BRACEERROR);
X	YY_BREAK
Xcase 35:
XYY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
Xyy_c_buf_p = yy_b_buf_p;
XYY_DO_BEFORE_ACTION; /* set up yytext again */
X# line 154 "scan.l"
Xreturn ( '$' );
X	YY_BREAK
Xcase 36:
X# line 156 "scan.l"
X{
X			bracelevel = 1;
X			BEGIN(PERCENT_BRACE_ACTION);
X			return ( '\n' );
X			}
X	YY_BREAK
Xcase 37:
X# line 161 "scan.l"
X++linenum; return ( '\n' );
X	YY_BREAK
Xcase 38:
X# line 163 "scan.l"
XACTION_ECHO; BEGIN(C_COMMENT_2);
X	YY_BREAK
Xcase 39:
X# line 165 "scan.l"
X{ /* needs to be separate from following rule due to
X			   * bug with trailing context
X			   */
X			bracelevel = 0;
X			BEGIN(ACTION);
X			return ( '\n' );
X			}
X	YY_BREAK
Xcase 40:
XYY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
Xyy_c_buf_p -= 1;
XYY_DO_BEFORE_ACTION; /* set up yytext again */
X# line 173 "scan.l"
X{
X			bracelevel = 0;
X			BEGIN(ACTION);
X			return ( '\n' );
X			}
X	YY_BREAK
Xcase 41:
X# line 179 "scan.l"
X++linenum; return ( '\n' );
X	YY_BREAK
Xcase 42:
X# line 181 "scan.l"
X{
X			/* guarantee that the SECT3 rule will have something
X			 * to match
X			 */
X			yyless(1);
X			sectnum = 3;
X			BEGIN(SECT3);
X			return ( EOF ); /* to stop the parser */
X			}
X	YY_BREAK
Xcase 43:
X# line 191 "scan.l"
X{
X			(void) strcpy( nmstr, yytext );
X
X			/* check to see if we've already encountered this ccl */
X			if ( (cclval = ccllookup( nmstr )) )
X			    {
X			    yylval = cclval;
X			    ++cclreuse;
X			    return ( PREVCCL );
X			    }
X			else
X			    {
X			    /* we fudge a bit.  We know that this ccl will
X			     * soon be numbered as lastccl + 1 by cclinit
X			     */
X			    cclinstal( nmstr, lastccl + 1 );
X
X			    /* push back everything but the leading bracket
X			     * so the ccl can be rescanned
X			     */
X			    PUT_BACK_STRING(nmstr, 1);
X
X			    BEGIN(FIRSTCCL);
X			    return ( '[' );
X			    }
X			}
X	YY_BREAK
Xcase 44:
X# line 218 "scan.l"
X{
X			register char *nmdefptr;
X			char *ndlookup();
X
X			(void) strcpy( nmstr, yytext );
X			nmstr[yyleng - 1] = '\0';  /* chop trailing brace */
X
X			/* lookup from "nmstr + 1" to chop leading brace */
X			if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
X			    synerr( "undefined {name}" );
X
X			else
X			    { /* push back name surrounded by ()'s */
X			    unput(')');
X			    PUT_BACK_STRING(nmdefptr, 0);
X			    unput('(');
X			    }
X			}
X	YY_BREAK
Xcase 45:
X# line 237 "scan.l"
Xreturn ( yytext[0] );
X	YY_BREAK
Xcase 46:
X# line 238 "scan.l"
XRETURNCHAR;
X	YY_BREAK
Xcase 47:
X# line 239 "scan.l"
X++linenum; return ( '\n' );
X	YY_BREAK
Xcase 48:
X# line 242 "scan.l"
Xreturn ( ',' );
X	YY_BREAK
Xcase 49:
X# line 243 "scan.l"
XBEGIN(SECT2); return ( '>' );
X	YY_BREAK
Xcase 50:
XYY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
Xyy_c_buf_p = yy_b_buf_p;
XYY_DO_BEFORE_ACTION; /* set up yytext again */
X# line 244 "scan.l"
XBEGIN(CARETISBOL); return ( '>' );
X	YY_BREAK
Xcase 51:
X# line 245 "scan.l"
XRETURNNAME;
X	YY_BREAK
Xcase 52:
X# line 246 "scan.l"
Xsynerr( "bad start condition name" );
X	YY_BREAK
Xcase 53:
X# line 248 "scan.l"
XBEGIN(SECT2); return ( '^' );
X	YY_BREAK
Xcase 54:
X# line 251 "scan.l"
XRETURNCHAR;
X	YY_BREAK
Xcase 55:
X# line 252 "scan.l"
XBEGIN(SECT2); return ( '"' );
X	YY_BREAK
Xcase 56:
X# line 254 "scan.l"
X{
X			synerr( "missing quote" );
X			BEGIN(SECT2);
X			++linenum;
X			return ( '"' );
X			}
X	YY_BREAK
Xcase 57:
XYY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
Xyy_c_buf_p = yy_b_buf_p;
XYY_DO_BEFORE_ACTION; /* set up yytext again */
X# line 262 "scan.l"
XBEGIN(CCL); return ( '^' );
X	YY_BREAK
Xcase 58:
XYY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
Xyy_c_buf_p = yy_b_buf_p;
XYY_DO_BEFORE_ACTION; /* set up yytext again */
X# line 263 "scan.l"
Xreturn ( '^' );
X	YY_BREAK
Xcase 59:
X# line 264 "scan.l"
XBEGIN(CCL); yylval = '-'; return ( CHAR );
X	YY_BREAK
Xcase 60:
X# line 265 "scan.l"
XBEGIN
(CCL); RETURNCHAR;
X	YY_BREAK
Xcase 61:
XYY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
Xyy_c_buf_p = yy_b_buf_p;
XYY_DO_BEFORE_ACTION; /* set up yytext again */
X# line 267 "scan.l"
Xreturn ( '-' );
X	YY_BREAK
Xcase 62:
X# line 268 "scan.l"
XRETURNCHAR;
X	YY_BREAK
Xcase 63:
X# line 269 "scan.l"
XBEGIN(SECT2); return ( ']' );
X	YY_BREAK
Xcase 64:
X# line 272 "scan.l"
X{
X			yylval = myctoi( yytext );
X			return ( NUMBER );
X			}
X	YY_BREAK
Xcase 65:
X# line 277 "scan.l"
Xreturn ( ',' );
X	YY_BREAK
Xcase 66:
X# line 278 "scan.l"
XBEGIN(SECT2); return ( '}' );
X	YY_BREAK
Xcase 67:
X# line 280 "scan.l"
X{
X			synerr( "bad character inside {}'s" );
X			BEGIN(SECT2);
X			return ( '}' );
X			}
X	YY_BREAK
Xcase 68:
X# line 286 "scan.l"
X{
X			synerr( "missing }" );
X			BEGIN(SECT2);
X			++linenum;
X			return ( '}' );
X			}
X	YY_BREAK
Xcase 69:
X# line 294 "scan.l"
Xsynerr( "bad name in {}'s" ); BEGIN(SECT2);
X	YY_BREAK
Xcase 70:
X# line 295 "scan.l"
Xsynerr( "missing }" ); ++linenum; BEGIN(SECT2);
X	YY_BREAK
Xcase 71:
X# line 298 "scan.l"
Xbracelevel = 0;
X	YY_BREAK
Xcase 72:
X# line 299 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 73:
X# line 300 "scan.l"
X{
X			++linenum;
X			ACTION_ECHO;
X			if ( bracelevel == 0 )
X			    {
X			    fputs( "\tYY_BREAK\n", temp_action_file );
X			    BEGIN(SECT2);
X			    }
X			}
X	YY_BREAK
Xcase 74:
X# line 310 "scan.l"
XACTION_ECHO; ++bracelevel;
X	YY_BREAK
Xcase 75:
X# line 311 "scan.l"
XACTION_ECHO; --bracelevel;
X	YY_BREAK
Xcase 76:
X# line 312 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 77:
X# line 313 "scan.l"
XACTION_ECHO; BEGIN(ACTION_COMMENT);
X	YY_BREAK
Xcase 78:
X# line 314 "scan.l"
XACTION_ECHO; /* character constant */
X	YY_BREAK
Xcase 79:
X# line 315 "scan.l"
XACTION_ECHO; BEGIN(ACTION_STRING);
X	YY_BREAK
Xcase 80:
X# line 316 "scan.l"
X{
X			++linenum;
X			ACTION_ECHO;
X			if ( bracelevel == 0 )
X			    {
X			    fputs( "\tYY_BREAK\n", temp_action_file );
X			    BEGIN(SECT2);
X			    }
X			}
X	YY_BREAK
Xcase 81:
X# line 325 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 82:
X# line 327 "scan.l"
XACTION_ECHO; BEGIN(ACTION);
X	YY_BREAK
Xcase 83:
X# line 328 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 84:
X# line 329 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 85:
X# line 330 "scan.l"
X++linenum; ACTION_ECHO;
X	YY_BREAK
Xcase 86:
X# line 331 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 87:
X# line 333 "scan.l"
XACTION_ECHO; BEGIN(SECT2);
X	YY_BREAK
Xcase 88:
X# line 334 "scan.l"
X++linenum; ACTION_ECHO; BEGIN(SECT2);
X	YY_BREAK
Xcase 89:
X# line 335 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 90:
X# line 336 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 91:
X# line 337 "scan.l"
X++linenum; ACTION_ECHO;
X	YY_BREAK
Xcase 92:
X# line 339 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 93:
X# line 340 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 94:
X# line 341 "scan.l"
X++linenum; ACTION_ECHO;
X	YY_BREAK
Xcase 95:
X# line 342 "scan.l"
XACTION_ECHO; BEGIN(ACTION);
X	YY_BREAK
Xcase 96:
X# line 343 "scan.l"
XACTION_ECHO;
X	YY_BREAK
Xcase 97:
X# line 346 "scan.l"
X{
X			yylval = myesc( yytext ) & BYTEMASK;
X			return ( CHAR );
X			}
X	YY_BREAK
Xcase 98:
X# line 351 "scan.l"
X{
X			yylval = myesc( yytext ) & BYTEMASK;
X			BEGIN(CCL);
X			return ( CHAR );
X			}
X	YY_BREAK
Xcase 99:
X# line 358 "scan.l"
X{
X			register int numchars;
X
X			/* black magic - we know the names of a flex scanner's
X			 * internal variables.  We cap the input buffer with
X			 * an end-of-string and dump it to the output.
X			 */
X			YY_DO_BEFORE_SCAN; /* recover from setting up yytext */
X
X#ifdef FLEX_FAST_SKEL
X			fputs( yy_c_buf_p + 1, stdout );
X#else
X			yy_ch_buf[yy_e_buf_p + 1] = '\0';
X
X			/* ignore the first character; it's the second '%'
X			 * put back by the yyless(1) above
X			 */
X			fputs( yy_ch_buf + yy_c_buf_p + 1, stdout );
X#endif
X
X			/* if we don't do this, the data written by write()
X			 * can get overwritten when stdout is finally flushed
X			 */
X			(void) fflush( stdout );
X
X			while ( (numchars = read( fileno(yyin), yy_ch_buf,
X						  YY_BUF_MAX )) > 0 )
X			    (void) write( fileno(stdout), yy_ch_buf, numchars );
X	
X			if ( numchars < 0 )
X			    flexerror( "fatal read error in section 3" );
X
X			return ( EOF );
X			}
X	YY_BREAK
X
Xcase YY_NEW_FILE:
Xbreak; /* begin reading from new file */
X
Xcase YY_DO_DEFAULT:
XYY_DEFAULT_ACTION;
Xbreak;
X
Xcase YY_END_TOK:
Xreturn ( YY_END_TOK );
X
Xdefault:
XYY_FATAL_ERROR( "fatal flex scanner internal error" );
X	    }
X
Xget_next_token:
X	{
X	register int yy_curst;
X	register char yy_sym;
X
X	YY_DO_BEFORE_SCAN
X
X	/* set up to begin running DFA */
X
X	yy_curst = yy_start;
X
X	if ( yy_ch_buf[yy_c_buf_p] == '\n' )
X	    ++yy_curst;
X
X	/* yy_b_buf_p points to the position in yy_ch_buf
X	 * of the start of the current run.
X	 */
X
X	yy_b_buf_p = yy_c_buf_p + 1;
X
X	do /* until the machine jams */
X	    {
X	    if ( yy_c_buf_p == yy_e_buf_p )
X		{ /* need more input */
X		if ( yy_e_buf_p >= YY_BUF_LIM )
X		    { /* not enough room to do another read */
X		    /* see if we can make some room for more chars */
X
X		    yy_n_chars = yy_e_buf_p - yy_b_buf_p;
X
X		    if ( yy_n_chars >= 0 )
X			/* shift down buffer to make room */
X			for ( yy_iii = 0; yy_iii <= yy_n_chars; ++yy_iii )
X			    {
X			    yy_buf_pos = yy_b_buf_p + yy_iii;
X			    yy_ch_buf[yy_iii] = yy_ch_buf[yy_buf_pos];
X			    yy_st_buf[yy_iii] = yy_st_buf[yy_buf_pos];
X			    }
X
X		    yy_b_buf_p = 0;
X		    yy_e_buf_p = yy_n_chars;
X
X		    if ( yy_e_buf_p >= YY_BUF_LIM )
X			YY_FATAL_ERROR( "flex input buffer overflowed" );
X
X		    yy_c_buf_p = yy_e_buf_p;
X		    }
X
X		else if ( yy_saw_eof )
X		    {
Xsaweof:		    if ( yy_b_buf_p > yy_e_buf_p )
X			{
X			if ( yywrap() )
X			    {
X			    yy_act = YY_END_TOK;
X			    goto do_action;
X			    }
X			
X			else
X			    {
X			    YY_INIT;
X			    yy_act = YY_NEW_FILE;
X			    goto do_action;
X			    }
X			}
X
X		    else /* do a jam to eat up more input */
X			{
X#ifndef FLEX_INTERACTIVE_SCANNER
X			/* we're going to decrement yy_c_buf_p upon doing
X			 * the jam.  In this case, that's wrong, since
X			 * it points to the last non-jam character.  So
X			 * we increment it now to counter the decrement.
X			 */
X			++yy_c_buf_p;
X#endif
X			break;
X			}
X		    }
X
X		YY_INPUT( (yy_ch_buf + yy_c_buf_p + 1), yy_n_chars,
X			  YY_MAX_LINE );
X
X		if ( yy_n_chars == YY_NULL )
X		    {
X		    if ( yy_saw_eof )
X	YY_FATAL_ERROR( "flex scanner saw EOF twice - shouldn't happen" );
X		    yy_saw_eof = 1;
X		    goto saweof;
X		    }
X
X		yy_e_buf_p += yy_n_chars;
X		}
X
X	    ++yy_c_buf_p;
X
X#ifdef FLEX_USE_ECS
X	    yy_sym = e[(yy_ch_buf[yy_c_buf_p] & BYTEMASK)];
X#else
X	    yy_sym = yy_ch_buf[yy_c_buf_p];
X#endif
X
X#ifdef FLEX_FULL_TABLE
X	    yy_curst = n[yy_curst][yy_sym];
X
X#else /* get next state from compressed table */
X
X	    while ( c[b[yy_curst] + yy_sym] != yy_curst )
X		{
X		yy_curst = d[yy_curst];
X
X#ifdef FLEX_USE_MECS
X		/* we've arrange it so that templates are never chained
X		 * to one another.  This means we can afford make a
X		 * very simple test to see if we need to convert to
X		 * yy_sym's meta-equivalence class without worrying
X		 * about erroneously looking up the meta-equivalence
X		 * class twice
X		 */
X
X		if ( yy_curst >= YY_TEMPLATE )
X		    yy_sym = m[yy_sym];
X#endif
X		}
X
X	    yy_curst = n[b[yy_curst] + yy_sym];
X
X#endif
X
X	    yy_st_buf[yy_c_buf_p] = yy_curst;
X
X	    }
X#ifdef FLEX_INTERACTIVE_SCANNER
X	while ( b[yy_curst] != YY_JAM_BASE );
X#else
X	while ( yy_curst != YY_JAM );
X	--yy_c_buf_p; /* put back character we jammed on */
X
X#endif
X
X	if ( yy_c_buf_p >= yy_b_buf_p )
X	    { /* we matched some text */
X	    yy_curst = yy_st_buf[yy_c_buf_p];
X	    yy_lp = l[yy_curst];
X
X#ifdef FLEX_REJECT_ENABLED
Xfind_rule: /* we branch to this label when doing a REJECT */
X#endif
X
X	    for ( ; ; ) /* until we find what rule we matched */
X		{
X#ifdef FLEX_REJECT_ENABLED
X		if ( yy_lp && yy_lp < l[yy_curst + 1] )
X		    {
X		    yy_act = a[yy_lp];
X		    goto do_action; /* "continue 2" */
X		    }
X#else
X		if ( yy_lp )
X		    {
X		    yy_act = yy_lp;
X		    goto do_action; /* "continue 2" */
X		    }
X#endif
X
X		if ( --yy_c_buf_p < yy_b_buf_p )
X		    break;
X
X		yy_curst = yy_st_buf[yy_c_buf_p];
X		yy_lp = l[yy_curst];
X		}
X	    }
X
X	/* if we got this far, then we didn't find any accepting
X	 * states
X	 */
X
X	/* so that the default applies to the first char read */
X	++yy_c_buf_p;
X
X	yy_act = YY_DO_DEFAULT;
X	}
X	}
X
X    /*NOTREACHED*/
X    }
X
X
Xstatic int unput( c )
Xchar c;
X
X    {
X    YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
X
X    if ( yy_c_buf_p == 0 )
X	{
X	register int i;
X	register int yy_buf_pos = YY_BUF_MAX;
X
X	for ( i = yy_e_buf_p; i >= yy_c_buf_p; --i )
X	    {
X	    yy_ch_buf[yy_buf_pos] = yy_ch_buf[i];
X	    yy_st_buf[yy_buf_pos] = yy_st_buf[i];
X	    --yy_buf_pos;
X	    }
X
X	yy_c_buf_p = YY_BUF_MAX - yy_e_buf_p;
X	yy_e_buf_p = YY_BUF_MAX;
X	}
X
X    if ( yy_c_buf_p <= 0 )
X	YY_FATAL_ERROR( "flex scanner push-back overflow" );
X
X    if ( yy_c_buf_p >= yy_b_buf_p && yy_ch_buf[yy_c_buf_p] == '\n' )
X	yy_ch_buf[yy_c_buf_p - 1] = '\n';
X
X    yy_ch_buf[yy_c_buf_p--] = c;
X
X    YY_DO_BEFORE_ACTION; /* set up yytext again */
X    }
X
X
Xstatic int input()
X
X    {
X    int c;
X
X    YY_DO_BEFORE_SCAN
X
X    if ( yy_c_buf_p == yy_e_buf_p )
X	{ /* need more input */
X	int yy_n_chars;
X
X	/* we can throw away the entire current buffer */
X	if ( yy_saw_eof )
X	    {
X	    if ( yywrap() )
X		return ( EOF );
X
X	    YY_INIT;
X	    }
X
X	yy_b_buf_p = 0;
X	YY_INPUT( yy_ch_buf, yy_n_chars, YY_MAX_LINE );
X
X	if ( yy_n_chars == YY_NULL )
X	    {
X	    yy_saw_eof = 1;
X
X	    if ( yywrap() )
X		return ( EOF );
X
X	    YY_INIT;
X
X	    return ( input() );
X	    }
X
X	yy_c_buf_p = -1;
X	yy_e_buf_p = yy_n_chars - 1;
X	}
X
X    c = yy_ch_buf[++yy_c_buf_p];
X
X    YY_DO_BEFORE_ACTION;
X
X    return ( c & BYTEMASK);
X    }
X# line 392 "scan.l"
X
SHAR_EOF
if test 38884 -ne "`wc -c < 'scan.c.dist'`"
then
	echo shar: error transmitting "'scan.c.dist'" '(should have been 38884 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 5 ---

earleh@eleazar.dartmouth.edu (Earle R. Horton) (07/02/88)

[Flex for the Mac - part 6 of 7]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	flex/sym.c
#	flex/tblcmp.c
# This archive created: Wed Jun 29 07:03:28 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'sym.c'" '(6202 characters)'
if test -f 'sym.c'
then
	echo shar: will not over-write existing file "'sym.c'"
else
sed 's/^X//' << \SHAR_EOF > 'sym.c'
X/* sym - symbol table routines */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include "flexdef.h"
X/*
X * MPW C 2.0.2 does not like variables named "entry".
X */
X#ifdef MPW
X#define entry entry_by_another_name
X#endif
X
Xstruct hash_entry *ndtbl[NAME_TABLE_HASH_SIZE];
Xstruct hash_entry *sctbl[START_COND_HASH_SIZE];
Xstruct hash_entry *ccltab[CCL_HASH_SIZE];
X
Xstruct hash_entry *findsym();
X
X
X/* addsym - add symbol and definitions to symbol table
X *
X * synopsis
X *    char sym[], *str_def;
X *    int int_def;
X *    hash_table table;
X *    int table_size;
X *    0 / -1 = addsym( sym, def, int_def, table, table_size );
X *
X * -1 is returned if the symbol already exists, and the change not made.
X */
X
Xint addsym( sym, str_def, int_def, table, table_size )
Xregister char sym[];
Xchar *str_def;
Xint int_def;
Xhash_table table;
Xint table_size;
X
X    {
X    int hash_val = hashfunct( sym, table_size );
X    register struct hash_entry *entry = table[hash_val];
X    register struct hash_entry *new_entry;
X    register struct hash_entry *successor;
X    char *malloc();
X
X    while ( entry )
X	{
X	if ( ! strcmp( sym, entry->name ) )
X	    { /* entry already exists */
X	    return ( -1 );
X	    }
X	
X	entry = entry->next;
X	}
X
X    /* create new entry */
X    new_entry = (struct hash_entry *) malloc( sizeof( struct hash_entry ) );
X
X    if ( new_entry == NULL )
X	flexfatal( "symbol table memory allocation failed" );
X
X    if ( (successor = table[hash_val]) )
X	{
X	new_entry->next = successor;
X	successor->prev = new_entry;
X	}
X    else
X	new_entry->next = NULL;
X
X    new_entry->prev = NULL;
X    new_entry->name = sym;
X    new_entry->str_val = str_def;
X    new_entry->int_val = int_def;
X
X    table[hash_val] = new_entry;
X
X    return ( 0 );
X    }
X
X
X/* cclinstal - save the text of a character class
X *
X * synopsis
X *    char ccltxt[];
X *    int cclnum;
X *    cclinstal( ccltxt, cclnum );
X */
X
Xcclinstal( ccltxt, cclnum )
Xchar ccltxt[];
Xint cclnum;
X
X    {
X    /* we don't bother checking the return status because we are not called
X     * unless the symbol is new
X     */
X    char *copy_string();
X
X    (void) addsym( copy_string( ccltxt ), (char *) 0, cclnum,
X		   ccltab, CCL_HASH_SIZE );
X    }
X
X
X/* ccllookup - lookup the number associated with character class text
X *
X * synopsis
X *    char ccltxt[];
X *    int ccllookup, cclval;
X *    cclval/0 = ccllookup( ccltxt );
X */
X
Xint ccllookup( ccltxt )
Xchar ccltxt[];
X
X    {
X    return ( findsym( ccltxt, ccltab, CCL_HASH_SIZE )->int_val );
X    }
X
X
X/* findsym - find symbol in symbol table
X *
X * synopsis
X *    char sym[];
X *    hash_table table;
X *    int table_size;
X *    struct hash_entry *entry, *findsym();
X *    entry = findsym( sym, table, table_size );
X */
X
Xstruct hash_entry *findsym( sym, table, table_size )
Xregister char sym[];
Xhash_table table;
Xint table_size;
X
X    {
X    register struct hash_entry *entry = table[hashfunct( sym, table_size )];
X    static struct hash_entry empty_entry =
X	{
X	(struct hash_entry *) 0, (struct hash_entry *) 0, NULL, NULL, 0,
X	} ;
X
X    while ( entry )
X	{
X	if ( ! strcmp( sym, entry->name ) )
X	    return ( entry );
X	entry = entry->next;
X	}
X
X    return ( &empty_entry );
X    }
X
X    
X/* hashfunct - compute the hash value for "str" and hash size "hash_size"
X *
X * synopsis
X *    char str[];
X *    int hash_size, hash_val;
X *    hash_val = hashfunct( str, hash_size );
X */
X
Xint hashfunct( str, hash_size )
Xregister char str[];
Xint hash_size;
X
X    {
X    register int hashval;
X    register int locstr;
X
X    hashval = 0;
X    locstr = 0;
X
X    while ( str[locstr] )
X	hashval = ((hashval << 1) + str[locstr++]) % hash_size;
X
X    return ( hashval );
X    }
X
X
X/* ndinstal - install a name definition
X *
X * synopsis
X *    char nd[], def[];
X *    ndinstal( nd, def );
X */
X
Xndinstal( nd, def )
Xchar nd[], def[];
X
X    {
X    char *copy_string();
X
X    if ( addsym( copy_string( nd ), copy_string( def ), 0,
X		 ndtbl, NAME_TABLE_HASH_SIZE ) )
X	synerr( "name defined twice" );
X    }
X
X
X/* ndlookup - lookup a name definition
X *
X * synopsis
X *    char nd[], *def;
X *    char *ndlookup();
X *    def/NULL = ndlookup( nd );
X */
X
Xchar *ndlookup( nd )
Xchar nd[];
X
X    {
X    return ( findsym( nd, ndtbl, NAME_TABLE_HASH_SIZE )->str_val );
X    }
X
X
X/* scinstal - make a start condition
X *
X * synopsis
X *    char str[];
X *    int xcluflg;
X *    scinstal( str, xcluflg );
X *
X * NOTE
X *    the start condition is Exclusive if xcluflg is true
X */
X
Xscinstal( str, xcluflg )
Xchar str[];
Xint xcluflg;
X
X    {
X    char *copy_string();
X
X    /* bit of a hack.  We know how the default start-condition is
X     * declared, and don't put out a define for it, because it
X     * would come out as "#define 0 1"
X     */
X    /* actually, this is no longer the case.  The default start-condition
X     * is now called "INITIAL".  But we keep the following for the sake
X     * of future robustness.
X     */
X
X    if ( strcmp( str, "0" ) )
X	printf( "#define %s %d\n", str, lastsc * 2 );
X
X    if ( ++lastsc >= current_max_scs )
X	{
X	current_max_scs += MAX_SCS_INCREMENT;
X
X	++num_reallocs;
X
X	scset = reallocate_integer_array( scset, current_max_scs );
X	scbol = reallocate_integer_array( scbol, current_max_scs );
X	scxclu = reallocate_integer_array( scxclu, current_max_scs );
X	actvsc = reallocate_integer_array( actvsc, current_max_scs );
X	}
X
X    if ( addsym( copy_string( str ), (char *) 0, lastsc,
X	 sctbl, START_COND_HASH_SIZE ) )
X	lerrsf( "start condition %s declared twice", str );
X
X    scset[lastsc] = mkstate( SYM_EPSILON );
X    scbol[lastsc] = mkstate( SYM_EPSILON );
X    scxclu[lastsc] = xcluflg;
X    }
X
X
X/* sclookup - lookup the number associated with a start condition
X *
X * synopsis
X *    char str[], scnum;
X *    int sclookup;
X *    scnum/0 = sclookup( str );
X */
X
Xint sclookup( str )
Xchar str[];
X
X    {
X    return ( findsym( str, sctbl, START_COND_HASH_SIZE )->int_val );
X    }
SHAR_EOF
if test 6202 -ne "`wc -c < 'sym.c'`"
then
	echo shar: error transmitting "'sym.c'" '(should have been 6202 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'tblcmp.c'" '(39351 characters)'
if test -f 'tblcmp.c'
then
	echo shar: will not over-write existing file "'tblcmp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'tblcmp.c'
X/* tblcmp - table compression routines */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include "flexdef.h"
X
X/* bldtbl - build table entries for dfa state
X *
X * synopsis
X *   int state[numecs], statenum, totaltrans, comstate, comfreq;
X *   bldtbl( state, statenum, totaltrans, comstate, comfreq );
X *
X * State is the statenum'th dfa state.  It is indexed by equivalence class and
X * gives the number of the state to enter for a given equivalence class.
X * totaltrans is the total number of transitions out of the state.  Comstate
X * is that state which is the destination of the most transitions out of State.
X * Comfreq is how many transitions there are out of State to Comstate.
X *
X * A note on terminology:
X *    "protos" are transition tables which have a high probability of
X * either being redundant (a state processed later will have an identical
X * transition table) or nearly redundant (a state processed later will have
X * many of the same out-transitions).  A "most recently used" queue of
X * protos is kept around with the hope that most states will find a proto
X * which is similar enough to be usable, and therefore compacting the
X * output tables.
X *    "templates" are a special type of proto.  If a transition table is
X * homogeneous or nearly homogeneous (all transitions go to the same
X * destination) then the odds are good that future states will also go
X * to the same destination state on basically the same character set.
X * These homogeneous states are so common when dealing with large rule
X * sets that they merit special attention.  If the transition table were
X * simply made into a proto, then (typically) each subsequent, similar
X * state will differ from the proto for two out-transitions.  One of these
X * out-transitions will be that character on which the proto does not go
X * to the common destination, and one will be that character on which the
X * state does not go to the common destination.  Templates, on the other
X * hand, go to the common state on EVERY transition character, and therefore
X * cost only one difference.
X */
X
Xbldtbl( state, statenum, totaltrans, comstate, comfreq )
Xint state[], statenum, totaltrans, comstate, comfreq;
X
X    {
X    int extptr, extrct[2][CSIZE + 1];
X    int mindiff, minprot, i, d;
X    int checkcom;
X
X    /* If extptr is 0 then the first array of extrct holds the result of the
X     * "best difference" to date, which is those transitions which occur in
X     * "state" but not in the proto which, to date, has the fewest differences
X     * between itself and "state".  If extptr is 1 then the second array of
X     * extrct hold the best difference.  The two arrays are toggled
X     * between so that the best difference to date can be kept around and
X     * also a difference just created by checking against a candidate "best"
X     * proto.
X     */
X
X    extptr = 0;
X
X    /* if the state has too few out-transitions, don't bother trying to
X     * compact its tables
X     */
X
X    if ( (totaltrans * 100) < (numecs * PROTO_SIZE_PERCENTAGE) )
X	mkentry( state, numecs, statenum, JAMSTATE, totaltrans );
X
X    else
X	{
X	/* checkcom is true if we should only check "state" against
X	 * protos which have the same "comstate" value
X	 */
X
X	checkcom = comfreq * 100 > totaltrans * CHECK_COM_PERCENTAGE;
X
X	minprot = firstprot;
X	mindiff = totaltrans;
X
X	if ( checkcom )
X	    {
X	    /* find first proto which has the same "comstate" */
X	    for ( i = firstprot; i != NIL; i = protnext[i] )
X		if ( protcomst[i] == comstate )
X		    {
X		    minprot = i;
X		    mindiff = tbldiff( state, minprot, extrct[extptr] );
X		    break;
X		    }
X	    }
X
X	else
X	    {
X	    /* since we've decided that the most common destination out
X	     * of "state" does not occur with a high enough frequency,
X	     * we set the "comstate" to zero, assuring that if this state
X	     * is entered into the proto list, it will not be considered
X	     * a template.
X	     */
X	    comstate = 0;
X
X	    if ( firstprot != NIL )
X		{
X		minprot = firstprot;
X		mindiff = tbldiff( state, minprot, extrct[extptr] );
X		}
X	    }
X
X	/* we now have the first interesting proto in "minprot".  If
X	 * it matches within the tolerances set for the first proto,
X	 * we don't want to bother scanning the rest of the proto list
X	 * to see if we have any other reasonable matches.
X	 */
X
X	if ( mindiff * 100 > totaltrans * FIRST_MATCH_DIFF_PERCENTAGE )
X	    { /* not a good enough match.  Scan the rest of the protos */
X	    for ( i = minprot; i != NIL; i = protnext[i] )
X		{
X		d = tbldiff( state, i, extrct[1 - extptr] );
X		if ( d < mindiff )
X		    {
X		    extptr = 1 - extptr;
X		    mindiff = d;
X		    minprot = i;
X		    }
X		}
X	    }
X
X	/* check if the proto we've decided on as our best bet is close
X	 * enough to the state we want to match to be usable
X	 */
X
X	if ( mindiff * 100 > totaltrans * ACCEPTABLE_DIFF_PERCENTAGE )
X	    {
X	    /* no good.  If the state is homogeneous enough, we make a
X	     * template out of it.  Otherwise, we make a proto.
X	     */
X
X	    if ( comfreq * 100 >= totaltrans * TEMPLATE_SAME_PERCENTAGE )
X		mktemplate( state, statenum, comstate );
X
X	    else
X		{
X		mkprot( state, statenum, comstate );
X		mkentry( state, numecs, statenum, JAMSTATE, totaltrans );
X		}
X	    }
X
X	else
X	    { /* use the proto */
X	    mkentry( extrct[extptr], numecs, statenum,
X		     prottbl[minprot], mindiff );
X
X	    /* if this state was sufficiently different from the proto
X	     * we built it from, make it, too, a proto
X	     */
X
X	    if ( mindiff * 100 >= totaltrans * NEW_PROTO_DIFF_PERCENTAGE )
X		mkprot( state, statenum, comstate );
X
X	    /* since mkprot added a new proto to the proto queue, it's possible
X	     * that "minprot" is no longer on the proto queue (if it happened
X	     * to have been the last entry, it would have been bumped off).
X	     * If it's not there, then the new proto took its physical place
X	     * (though logically the new proto is at the beginning of the
X	     * queue), so in that case the following call will do nothing.
X	     */
X
X	    mv2front( minprot );
X	    }
X	}
X    }
X
X
X/* cmptmps - compress template table entries
X *
X * synopsis
X *    cmptmps();
X *
X *  template tables are compressed by using the 'template equivalence
X *  classes', which are collections of transition character equivalence
X *  classes which always appear together in templates - really meta-equivalence
X *  classes.  until this point, the tables for templates have been stored
X *  up at the top end of the nxt array; they will now be compressed and have
X *  table entries made for them.
X */
X
Xcmptmps()
X
X    {
X    int tmpstorage[CSIZE + 1];
X    register int *tmp = tmpstorage, i, j;
X    int totaltrans, trans;
X
X    peakpairs = numtemps * numecs + tblend;
X
X    if ( usemecs )
X	{
X	/* create equivalence classes base on data gathered on template
X	 * transitions
X	 */
X
X	nummecs = cre8ecs( tecfwd, tecbck, numecs );
X	}
X    
X    else
X	nummecs = numecs;
X
X    if ( lastdfa + numtemps + 1 >= current_max_dfas )
X	increase_max_dfas();
X
X    /* loop through each template */
X
X    for ( i = 1; i <= numtemps; ++i )
X	{
X	totaltrans = 0;	/* number of non-jam transitions out of this template */
X
X	for ( j = 1; j <= numecs; ++j )
X	    {
X	    trans = tnxt[numecs * i + j];
X
X	    if ( usemecs )
X		{
X		/* the absolute value of tecbck is the meta-equivalence class
X		 * of a given equivalence class, as set up by cre8ecs
X		 */
X		if ( tecbck[j] > 0 )
X		    {
X		    tmp[tecbck[j]] = trans;
X
X		    if ( trans > 0 )
X			++totaltrans;
X		    }
X		}
X
X	    else
X		{
X		tmp[j] = trans;
X
X		if ( trans > 0 )
X		    ++totaltrans;
X		}
X	    }
X
X	/* it is assumed (in a rather subtle way) in the skeleton that
X	 * if we're using meta-equivalence classes, the def[] entry for
X	 * all templates is the jam template, i.e., templates never default
X	 * to other non-jam table entries (e.g., another template)
X	 */
X
X	/* leave room for the jam-state after the last real state */
X	mkentry( tmp, nummecs, lastdfa + i + 1, JAMSTATE, totaltrans );
X	}
X    }
X
X
X
X/* expand_nxt_chk - expand the next check arrays */
X
Xexpand_nxt_chk()
X
X    {
X    register int old_max = current_max_xpairs;
X
X    current_max_xpairs += MAX_XPAIRS_INCREMENT;
X
X    ++num_reallocs;
X
X    nxt = reallocate_integer_array( nxt, current_max_xpairs );
X    chk = reallocate_integer_array( chk, current_max_xpairs );
X
X    bzero( (char *) (chk + old_max),
X	   MAX_XPAIRS_INCREMENT * sizeof( int ) / sizeof( char ) );
X    }
X
X
X/* find_table_space - finds a space in the table for a state to be placed
X *
X * synopsis
X *     int *state, numtrans, block_start;
X *     int find_table_space();
X *
X *     block_start = find_table_space( state, numtrans );
X *
X * State is the state to be added to the full speed transition table.
X * Numtrans is the number of out-transitions for the state.
X *
X * find_table_space() returns the position of the start of the first block (in
X * chk) able to accommodate the state
X *
X * In determining if a state will or will not fit, find_table_space() must take
X * into account the fact that an end-of-buffer state will be added at [0],
X * and an action number will be added in [-1].
X */
X
Xint find_table_space( state, numtrans )
Xint *state, numtrans;
X    
X    {
X    /* firstfree is the position of the first possible occurrence of two
X     * consecutive unused records in the chk and nxt arrays
X     */
X    register int i;
X    register int *state_ptr, *chk_ptr;
X    register int *ptr_to_last_entry_in_state;
X
X    /* if there are too many out-transitions, put the state at the end of
X     * nxt and chk
X     */
X    if ( numtrans > MAX_XTIONS_FOR_FULL_INTERIOR_FIT )
X	{
X	/* if table is empty, return the first available spot in chk/nxt,
X	 * which should be 1
X	 */
X	if ( tblend < 2 )
X	    return ( 1 );
X
X	i = tblend - numecs;	/* start searching for table space near the
X				 * end of chk/nxt arrays
X				 */
X	}
X
X    else
X	i = firstfree;		/* start searching for table space from the
X				 * beginning (skipping only the elements
X				 * which will definitely not hold the new
X				 * state)
X				 */
X
X    while ( 1 )		/* loops until a space is found */
X	{
X	if ( i + numecs > current_max_xpairs )
X	    expand_nxt_chk();
X
X	/* loops until space for end-of-buffer and action number are found */
X	while ( 1 )
X	    {
X	    if ( chk[i - 1] == 0 )	/* check for action number space */
X		{
X		if ( chk[i] == 0 )	/* check for end-of-buffer space */
X		    break;
X
X		else
X		    i += 2;	/* since i != 0, there is no use checking to
X				 * see if (++i) - 1 == 0, because that's the
X				 * same as i == 0, so we skip a space
X				 */
X		}
X
X	    else
X		++i;
X
X	    if ( i + numecs > current_max_xpairs )
X		expand_nxt_chk();
X	    }
X
X	/* if we started search from the beginning, store the new firstfree for
X	 * the next call of find_table_space()
X	 */
X	if ( numtrans <= MAX_XTIONS_FOR_FULL_INTERIOR_FIT )
X	    firstfree = i + 1;
X
X	/* check to see if all elements in chk (and therefore nxt) that are
X	 * needed for the new state have not yet been taken
X	 */
X
X	state_ptr = &state[1];
X	ptr_to_last_entry_in_state = &chk[i + numecs + 1];
X
X	for ( chk_ptr = &chk[i + 1]; chk_ptr != ptr_to_last_entry_in_state;
X	      ++chk_ptr )
X	    if ( *(state_ptr++) != 0 && *chk_ptr != 0 )
X		break;
X
X	if ( chk_ptr == ptr_to_last_entry_in_state )
X	    return ( i );
X
X	else
X	    ++i;
X	}
X    }
X
X
X/* genctbl - generates full speed compressed transition table
X *
X * synopsis
X *     genctbl();
X */
X
Xgenctbl()
X
X    {
X    register int i;
X
X    /* table of verify for transition and offset to next state */
X    printf( "static struct yy_trans_info yy_transition[%d] =\n",
X	    tblend + numecs + 1 );
X    printf( "    {\n" );
X    
X    /* We want the transition to be represented as the offset to the
X     * next state, not the actual state number, which is what it currently is.
X     * The offset is base[nxt[i]] - base[chk[i]].  That's just the
X     * difference between the starting points of the two involved states
X     * (to - from).
X     *
X     * first, though, we need to find some way to put in our end-of-buffer
X     * flags and states.  We do this by making a state with absolutely no
X     * transitions.  We put it at the end of the table.
X     */
X    /* at this point, we're guaranteed that there's enough room in nxt[]
X     * and chk[] to hold tblend + numecs entries.  We need just two slots.
X     * One for the action and one for the end-of-buffer transition.  We
X     * now *assume* that we're guaranteed the only character we'll try to
X     * index this nxt/chk pair with is EOB, i.e., 0, so we don't have to
X     * make sure there's room for jam entries for other characters.
X     */
X
X    base[lastdfa + 1] = tblend + 2;
X    nxt[tblend + 1] = END_OF_BUFFER_ACTION;
X    chk[tblend + 1] = numecs + 1;
X    chk[tblend + 2] = 1; /* anything but EOB */
X    nxt[tblend + 2] = 0; /* so that "make test" won't show arb. differences */
X
X    /* make sure every state has a end-of-buffer transition and an action # */
X    for ( i = 0; i <= lastdfa; ++i )
X	{
X	chk[base[i]] = EOB_POSITION;
X	chk[base[i] - 1] = ACTION_POSITION;
X	nxt[base[i] - 1] = dfaacc[i].dfaacc_state;	/* action number */
X	}
X
X    for ( i = 0; i <= lastsc * 2; ++i )
X	nxt[base[i] - 1] = DEFAULT_ACTION;
X
X    dataline = 0;
X    datapos = 0;
X
X    for ( i = 0; i <= tblend; ++i )
X	{
X	if ( chk[i] == EOB_POSITION )
X	    transition_struct_out( 0, base[lastdfa + 1] - i );
X
X	else if ( chk[i] == ACTION_POSITION )
X	    transition_struct_out( 0, nxt[i] );
X
X	else if ( chk[i] > numecs || chk[i] == 0 )
X	    transition_struct_out( 0, 0 );		/* unused slot */
X
X	else	/* verify, transition */
X	    transition_struct_out( chk[i], base[nxt[i]] - (i - chk[i]) );
X	}
X
X
X    /* here's the final, end-of-buffer state */
X    transition_struct_out( chk[tblend + 1], nxt[tblend + 1] );
X    transition_struct_out( chk[tblend + 2], nxt[tblend + 2] );
X
X    printf( "    };\n" );
X    printf( "\n" );
X
X    /* table of pointers to start states */
X    printf( "static struct yy_trans_info *yy_state_ptr[%d] =\n",
X	lastsc * 2 + 1 );
X    printf( "    {\n" );
X
X    for ( i = 0; i <= lastsc * 2; ++i )
X	printf( "    &yy_transition[%d],\n", base[i] );
X
X    printf( "    };\n" );
X
X    if ( useecs )
X	genecs();
X    }
X
X
X/* gentabs - generate data statements for the transition tables
X *
X * synopsis
X *    gentabs();
X */
X
Xgentabs()
X
X    {
X    int i, j, k, *accset, nacc, *acc_array;
X    char clower();
X
X    /* *everything* is done in terms of arrays starting at 1, so provide
X     * a null entry for the zero element of all FTL arrays
X     */
X    static char ftl_long_decl[] = "static long int %c[%d] =\n    {   0,\n";
X    static char ftl_short_decl[] = "static short int %c[%d] =\n    {   0,\n";
X    static char ftl_char_decl[] = "static char %c[%d] =\n    {   0,\n";
X
X    acc_array = allocate_integer_array( current_max_dfas );
X    nummt = 0;
X
X    if ( fulltbl )
X	jambase = lastdfa + 1;	/* home of "jam" pseudo-state */
X
X    printf( "#define YY_JAM %d\n", jamstate );
X    printf( "#define YY_JAM_BASE %d\n", jambase );
X
X    if ( usemecs )
X	printf( "#define YY_TEMPLATE %d\n", lastdfa + 2 );
X
X    if ( reject )
X	{
X	/* write out accepting list and pointer list
X	 * first we generate the ACCEPT array.  In the process, we compute
X	 * the indices that will go into the ALIST array, and save the
X	 * indices in the dfaacc array
X	 */
X
X	printf( accnum > 127 ? ftl_short_decl : ftl_char_decl,
X		ACCEPT, max( numas, 1 ) + 1 );
X
X	j = 1;	/* index into ACCEPT array */
X
X	for ( i = 1; i <= lastdfa; ++i )
X	    {
X	    acc_array[i] = j;
X
X	    if ( accsiz[i] != 0 )
X		{
X		accset = dfaacc[i].dfaacc_set;
X		nacc = accsiz[i];
X
X		if ( trace )
X		    fprintf( stderr, "state # %d accepts: ", i );
X
X		for ( k = 1; k <= nacc; ++k )
X		    {
X		    ++j;
X		    mkdata( accset[k] );
X
X		    if ( trace )
X			{
X			fprintf( stderr, "[%d]", accset[k] );
X
X			if ( k < nacc )
X			    fputs( ", ", stderr );
X			else
X			    putc( '\n', stderr );
X			}
X		    }
X		}
X	    }
X
X	/* add accepting number for the "jam" state */
X	acc_array[i] = j;
X
X	dataend();
X	}
X    
X    else
X	{
X	for ( i = 1; i <= lastdfa; ++i )
X	    acc_array[i] = dfaacc[i].dfaacc_state;
X	
X	acc_array[i] = 0; /* add (null) accepting number for jam state */
X	}
X
X    /* spit out ALIST array.  If we're doing "reject", it'll be pointers
X     * into the ACCEPT array.  Otherwise it's actual accepting numbers.
X     * In either case, we just dump the numbers.
X     */
X
X    /* "lastdfa + 2" is the size of ALIST; includes room for FTL arrays
X     * beginning at 0 and for "jam" state
X     */
X    k = lastdfa + 2;
X
X    if ( reject )
X	/* we put a "cap" on the table associating lists of accepting
X	 * numbers with state numbers.  This is needed because we tell
X	 * where the end of an accepting list is by looking at where
X	 * the list for the next state starts.
X	 */
X	++k;
X
X    printf( ((reject && numas > 126) || accnum > 127) ?
X	    ftl_short_decl : ftl_char_decl, ALIST, k );
X
X    /* set up default actions */
X    for ( i = 1; i <= lastsc * 2; ++i )
X	acc_array[i] = DEFAULT_ACTION;
X
X    acc_array[end_of_buffer_state] = END_OF_BUFFER_ACTION;
X
X    for ( i = 1; i <= lastdfa; ++i )
X	{
X	mkdata( acc_array[i] );
X
X	if ( ! reject && trace && acc_array[i] )
X	    fprintf( stderr, "state # %d accepts: [%d]\n", i, acc_array[i] );
X	}
X
X    /* add entry for "jam" state */
X    mkdata( acc_array[i] );
X
X    if ( reject )
X	/* add "cap" for the list */
X	mkdata( acc_array[i] );
X
X    dataend();
X
X    if ( useecs )
X	genecs();
X
X    if ( usemecs )
X	{
X	/* write out meta-equivalence classes (used to index templates with) */
X
X	if ( trace )
X	    fputs( "\n\nMeta-Equivalence Classes:\n", stderr );
X
X	printf( ftl_char_decl, MATCHARRAY, numecs + 1 );
X
X	for ( i = 1; i <= numecs; ++i )
X	    {
X	    if ( trace )
X		fprintf( stderr, "%d = %d\n", i, abs( tecbck[i] ) );
X
X	    mkdata( abs( tecbck[i] ) );
X	    }
X
X	dataend();
X	}
X
X    if ( ! fulltbl )
X	{
X	int total_states = lastdfa + numtemps;
X
X	printf( tblend > MAX_SHORT ? ftl_long_decl : ftl_short_decl,
X		BASEARRAY, total_states + 1 );
X
X	for ( i = 1; i <= lastdfa; ++i )
X	    {
X	    register int d = def[i];
X
X	    if ( base[i] == JAMSTATE )
X		base[i] = jambase;
X
X	    if ( d == JAMSTATE )
X		def[i] = jamstate;
X
X	    else if ( d < 0 )
X		{
X		/* template reference */
X		++tmpuses;
X		def[i] = lastdfa - d + 1;
X		}
X
X	    mkdata( base[i] );
X	    }
X
X	/* generate jam state's base index */
X	mkdata( base[i] );
X
X	for ( ++i /* skip jam state */; i <= total_states; ++i )
X	    {
X	    mkdata( base[i] );
X	    def[i] = jamstate;
X	    }
X
X	dataend();
X
X	printf( tblend > MAX_SHORT ? ftl_long_decl : ftl_short_decl,
X		DEFARRAY, total_states + 1 );
X
X	for ( i = 1; i <= total_states; ++i )
X	    mkdata( def[i] );
X
X	dataend();
X
X	printf( lastdfa > MAX_SHORT ? ftl_long_decl : ftl_short_decl,
X		NEXTARRAY, tblend + 1 );
X
X	for ( i = 1; i <= tblend; ++i )
X	    {
X	    if ( nxt[i] == 0 || chk[i] == 0 )
X		nxt[i] = jamstate;	/* new state is the JAM state */
X
X	    mkdata( nxt[i] );
X	    }
X
X	dataend();
X
X	printf( lastdfa > MAX_SHORT ? ftl_long_decl : ftl_short_decl,
X		CHECKARRAY, tblend + 1 );
X
X	for ( i = 1; i <= tblend; ++i )
X	    {
X	    if ( chk[i] == 0 )
X		++nummt;
X
X	    mkdata( chk[i] );
X	    }
X
X	dataend();
X	}
X    }
X
X
X/* generate equivalence-class tables */
X
Xgenecs()
X
X    {
X    register int i, j;
X    static char ftl_char_decl[] = "static char %c[%d] =\n    {   0,\n";
X    int numrows;
X
X    printf( ftl_char_decl, ECARRAY, CSIZE + 1 );
X
X    for ( i = 1; i <= CSIZE; ++i )
X	{
X	if ( caseins && (i >= 'A') && (i <= 'Z') )
X	    ecgroup[i] = ecgroup[clower( i )];
X
X	ecgroup[i] = abs( ecgroup[i] );
X	mkdata( ecgroup[i] );
X	}
X
X    dataend();
X
X    if ( trace )
X	{
X	fputs( "\n\nEquivalence Classes:\n\n", stderr );
X
X	numrows = (CSIZE + 1) / 8;
X
X	for ( j = 1; j <= numrows; ++j )
X	    {
X	    for ( i = j; i <= CSIZE; i = i + numrows )
X		{
X		if ( i >= 1 && i <= 31 )
X		    fprintf( stderr, "^%c = %-2d",
X			     'A' + i - 1, ecgroup[i] );
X
X		else if ( i >= 32 && i <= 126 )
X		    fprintf( stderr, " %c = %-2d", i, ecgroup[i] );
X
X		else if ( i == 127 )
X		    fprintf( stderr, "^@ = %-2d", ecgroup[i] );
X
X		else
X		    fprintf( stderr, "\nSomething Weird: %d = %d\n", i,
X			     ecgroup[i] );
X
X		putc( '\t', stderr );
X		}
X
X	    putc( '\n', stderr );
X	    }
X	}
X    }
X
X
X/* inittbl - initialize transition tables
X *
X * synopsis
X *   inittbl();
X *
X * Initializes "firstfree" to be one beyond the end of the table.  Initializes
X * all "chk" entries to be zero.  Note that templates are built in their
X * own tbase/tdef tables.  They are shifted down to be contiguous
X * with the non-template entries during table generation.
X */
Xinittbl()
X
X    {
X    register int i;
X
X    bzero( (char *) chk, current_max_xpairs * sizeof( int ) / sizeof( char ) );
X
X    tblend = 0;
X    firstfree = tblend + 1;
X    numtemps = 0;
X
X    if ( usemecs )
X	{
X	/* set up doubly-linked meta-equivalence classes
X	 * these are sets of equivalence classes which all have identical
X	 * transitions out of TEMPLATES
X	 */
X
X	tecbck[1] = NIL;
X
X	for ( i = 2; i <= numecs; ++i )
X	    {
X	    tecbck[i] = i - 1;
X	    tecfwd[i - 1] = i;
X	    }
X
X	tecfwd[numecs] = NIL;
X	}
X    }
X
X
X/* make_tables - generate transition tables
X *
X * synopsis
X *     make_tables();
X *
X * Generates transition tables and finishes generating output file
X */
X
Xmake_tables()
X
X    {
X    if ( fullspd )
X	{ /* need to define YY_TRANS_OFFSET_TYPE as a size large
X	   * enough to hold the biggest offset
X	   */
X	int total_table_size = tblend + numecs + 1;
X
X	printf( "#define YY_TRANS_OFFSET_TYPE %s\n",
X		total_table_size > MAX_SHORT ? "long" : "short" );
X	}
X    
X    if ( fullspd || fulltbl )
X	skelout();
X
X    /* compute the tables and copy them to output file */
X    if ( fullspd )
X	genctbl();
X
X    else
X	gentabs();
X
X    skelout();
X
X    (void) fclose( temp_action_file );
X    temp_action_file = fopen( action_file_name, "r" );
X
X    /* copy prolog from action_file to output file */
X    action_out();
X
X    skelout();
X
X    /* copy actions from action_file to output file */
X    action_out();
X
X    skelout();
X
X    /* copy remainder of input to output */
X
X    line_directive_out( stdout );
X    (void) flexscan(); /* copy remainder of input to output */
X    }
X
X
X/* mkdeftbl - make the default, "jam" table entries
X *
X * synopsis
X *   mkdeftbl();
X */
X
Xmkdeftbl()
X
X    {
X    int i;
X
X    jamstate = lastdfa + 1;
X
X    if ( tblend + numecs > current_max_xpairs )
X	expand_nxt_chk();
X
X    for ( i = 1; i <= numecs; ++i )
X	{
X	nxt[tblend + i] = 0;
X	chk[tblend + i] = jamstate;
X	}
X
X    jambase = tblend;
X
X    base[jamstate] = jambase;
X
X    /* should generate a run-time array bounds check if
X     * ever used as a default
X     */
X    def[jamstate] = BAD_SUBSCRIPT;
X
X    tblend += numecs;
X    ++numtemps;
X    }
X
X
X/* mkentry - create base/def and nxt/chk entries for transition array
X *
X * synopsis
X *   int state[numchars + 1], numchars, statenum, deflink, totaltrans;
X *   mkentry( state, numchars, statenum, deflink, totaltrans );
X *
X * "state" is a transition array "numchars" characters in size, "statenum"
X * is the offset to be used into the base/def tables, and "deflink" is the
X * entry to put in the "def" table entry.  If "deflink" is equal to
X * "JAMSTATE", then no attempt will be made to fit zero entries of "state"
X * (i.e., jam entries) into the table.  It is assumed that by linking to
X * "JAMSTATE" they will be taken care of.  In any case, entries in "state"
X * marking transitions to "SAME_TRANS" are treated as though they will be
X * taken care of by whereever "deflink" points.  "totaltrans" is the total
X * number of transitions out of the state.  If it is below a certain threshold,
X * the tables are searched for an interior spot that will accommodate the
X * state array.
X */
X
Xmkentry( state, numchars, statenum, deflink, totaltrans )
Xregister int *state;
Xint numchars, statenum, deflink, totaltrans;
X
X    {
X    register int minec, maxec, i, baseaddr;
X    int tblbase, tbllast;
X
X    if ( totaltrans == 0 )
X	{ /* there are no out-transitions */
X	if ( deflink == JAMSTATE )
X	    base[statenum] = JAMSTATE;
X	else
X	    base[statenum] = 0;
X
X	def[statenum] = deflink;
X	return;
X	}
X
X    for ( minec = 1; minec <= numchars; ++minec )
X	{
X	if ( state[minec] != SAME_TRANS )
X	    if ( state[minec] != 0 || deflink != JAMSTATE )
X		break;
X	}
X
X    if ( totaltrans == 1 )
X	{
X	/* there's only one out-transition.  Save it for later to fill
X	 * in holes in the tables.
X	 */
X	stack1( statenum, minec, state[minec], deflink );
X	return;
X	}
X
X    for ( maxec = numchars; maxec > 0; --maxec )
X	{
X	if ( state[maxec] != SAME_TRANS )
X	    if ( state[maxec] != 0 || deflink != JAMSTATE )
X		break;
X	}
X
X    /* Whether we try to fit the state table in the middle of the table
X     * entries we have already generated, or if we just take the state
X     * table at the end of the nxt/chk tables, we must make sure that we
X     * have a valid base address (i.e., non-negative).  Note that not only are
X     * negative base addresses dangerous at run-time (because indexing the
X     * next array with one and a low-valued character might generate an
X     * array-out-of-bounds error message), but at compile-time negative
X     * base addresses denote TEMPLATES.
X     */
X
X    /* find the first transition of state that we need to worry about. */
X    if ( totaltrans * 100 <= numchars * INTERIOR_FIT_PERCENTAGE )
X	{ /* attempt to squeeze it into the middle of the tabls */
X	baseaddr = firstfree;
X
X	while ( baseaddr < minec )
X	    {
X	    /* using baseaddr would result in a negative base address below
X	     * find the next free slot
X	     */
X	    for ( ++baseaddr; chk[baseaddr] != 0; ++baseaddr )
X		;
X	    }
X
X	if ( baseaddr + maxec - minec >= current_max_xpairs )
X	    expand_nxt_chk();
X
X	for ( i = minec; i <= maxec; ++i )
X	    if ( state[i] != SAME_TRANS )
X		if ( state[i] != 0 || deflink != JAMSTATE )
X		    if ( chk[baseaddr + i - minec] != 0 )
X			{ /* baseaddr unsuitable - find another */
X			for ( ++baseaddr;
X			      baseaddr < current_max_xpairs &&
X			      chk[baseaddr] != 0;
X			      ++baseaddr )
X			    ;
X
X			if ( baseaddr + maxec - minec >= current_max_xpairs )
X			    expand_nxt_chk();
X
X			/* reset the loop counter so we'll start all
X			 * over again next time it's incremented
X			 */
X
X			i = minec - 1;
X			}
X	}
X
X    else
X	{
X	/* ensure that the base address we eventually generate is
X	 * non-negative
X	 */
X	baseaddr = max( tblend + 1, minec );
X	}
X
X    tblbase = baseaddr - minec;
X    tbllast = tblbase + maxec;
X
X    if ( tbllast >= current_max_xpairs )
X	expand_nxt_chk();
X
X    base[statenum] = tblbase;
X    def[statenum] = deflink;
X
X    for ( i = minec; i <= maxec; ++i )
X	if ( state[i] != SAME_TRANS )
X	    if ( state[i] != 0 || deflink != JAMSTATE )
X		{
X		nxt[tblbase + i] = state[i];
X		chk[tblbase + i] = statenum;
X		}
X
X    if ( baseaddr == firstfree )
X	/* find next free slot in tables */
X	for ( ++firstfree; chk[firstfree] != 0; ++firstfree )
X	    ;
X
X    tblend = max( tblend, tbllast );
X    }
X
X
X/* mk1tbl - create table entries for a state (or state fragment) which
X *            has only one out-transition
X *
X * synopsis
X *   int state, sym, onenxt, onedef;
X *   mk1tbl( state, sym, onenxt, onedef );
X */
X
Xmk1tbl( state, sym, onenxt, onedef )
Xint state, sym, onenxt, onedef;
X
X    {
X    if ( firstfree < sym )
X	firstfree = sym;
X
X    while ( chk[firstfree] != 0 )
X	if ( ++firstfree >= current_max_xpairs )
X	    expand_nxt_chk();
X
X    base[state] = firstfree - sym;
X    def[state] = onedef;
X    chk[firstfree] = state;
X    nxt[firstfree] = onenxt;
X
X    if ( firstfree > tblend )
X	{
X	tblend = firstfree++;
X
X	if ( firstfree >= current_max_xpairs )
X	    expand_nxt_chk();
X	}
X    }
X
X
X/* mkprot - create new proto entry
X *
X * synopsis
X *   int state[], statenum, comstate;
X *   mkprot( state, statenum, comstate );
X */
X
Xmkprot( state, statenum, comstate )
Xint state[], statenum, comstate;
X
X    {
X    int i, slot, tblbase;
X
X    if ( ++numprots >= MSP || numecs * numprots >= PROT_SAVE_SIZE )
X	{
X	/* gotta make room for the new proto by dropping last entry in
X	 * the queue
X	 */
X	slot = lastprot;
X	lastprot = protprev[lastprot];
X	protnext[lastprot] = NIL;
X	}
X
X    else
X	slot = numprots;
X
X    protnext[slot] = firstprot;
X
X    if ( firstprot != NIL )
X	protprev[firstprot] = slot;
X
X    firstprot = slot;
X    prottbl[slot] = statenum;
X    protcomst[slot] = comstate;
X
X    /* copy state into save area so it can be compared with rapidly */
X    tblbase = numecs * (slot - 1);
X
X    for ( i = 1; i <= numecs; ++i )
X	protsave[tblbase + i] = state[i];
X    }
X
X
X/* mktemplate - create a template entry based on a state, and connect the state
X *              to it
X *
X * synopsis
X *   int state[], statenum, comstate, totaltrans;
X *   mktemplate( state, statenum, comstate, totaltrans );
X */
X
Xmktemplate( state, statenum, comstate )
Xint state[], statenum, comstate;
X
X    {
X    int i, numdiff, tmpbase, tmp[CSIZE + 1];
X    char transset[CSIZE + 1];
X    int tsptr;
X
X    ++numtemps;
X
X    tsptr = 0;
X
X    /* calculate where we will temporarily store the transition table
X     * of the template in the tnxt[] array.  The final transition table
X     * gets created by cmptmps()
X     */
X
X    tmpbase = numtemps * numecs;
X
X    if ( tmpbase + numecs >= current_max_template_xpairs )
X	{
X	current_max_template_xpairs += MAX_TEMPLATE_XPAIRS_INCREMENT;
X
X	++num_reallocs;
X
X	tnxt = reallocate_integer_array( tnxt, current_max_template_xpairs );
X	}
X
X    for ( i = 1; i <= numecs; ++i )
X	if ( state[i] == 0 )
X	    tnxt[tmpbase + i] = 0;
X	else
X	    {
X	    transset[tsptr++] = i;
X	    tnxt[tmpbase + i] = comstate;
X	    }
X
X    if ( usemecs )
X	mkeccl( transset, tsptr, tecfwd, tecbck, numecs );
X
X    mkprot( tnxt + tmpbase, -numtemps, comstate );
X
X    /* we rely on the fact that mkprot adds things to the beginning
X     * of the proto queue
X     */
X
X    numdiff = tbldiff( state, firstprot, tmp );
X    mkentry( tmp, numecs, statenum, -numtemps, numdiff );
X    }
X
X
X/* mv2front - move proto queue element to front of queue
X *
X * synopsis
X *   int qelm;
X *   mv2front( qelm );
X */
X
Xmv2front( qelm )
Xint qelm;
X
X    {
X    if ( firstprot != qelm )
X	{
X	if ( qelm == lastprot )
X	    lastprot = protprev[lastprot];
X
X	protnext[protprev[qelm]] = protnext[qelm];
X
X	if ( protnext[qelm] != NIL )
X	    protprev[protnext[qelm]] = protprev[qelm];
X
X	protprev[qelm] = NIL;
X	protnext[qelm] = firstprot;
X	protprev[firstprot] = qelm;
X	firstprot = qelm;
X	}
X    }
X
X
X/* ntod - convert an ndfa to a dfa
X *
X * synopsis
X *    ntod();
X *
X *  creates the dfa corresponding to the ndfa we've constructed.  the
X *  dfa starts out in state #1.
X */
Xntod()
X
X    {
X    int *accset, ds, nacc, newds;
X    int duplist[CSIZE + 1], sym, hashval, numstates, dsize;
X    int targfreq[CSIZE + 1], targstate[CSIZE + 1], state[CSIZE + 1];
X    int *nset, *dset;
X    int targptr, totaltrans, i, comstate, comfreq, targ;
X    int *epsclosure(), snstods(), symlist[CSIZE + 1];
X
X    /* this is so find_table_space(...) will know where to start looking in
X     * chk/nxt for unused records for space to put in the state
X     */
X    if ( fullspd )
X	firstfree = 0;
X
X    accset = allocate_integer_array( accnum + 1 );
X    nset = allocate_integer_array( current_max_dfa_size );
X
X    todo_head = todo_next = 0;
X
X#define ADD_QUEUE_ELEMENT(element) \
X	if ( ++element >= current_max_dfas ) \
X	    { /* check for queue overflowing */ \
X	    if ( todo_head == 0 ) \
X		increase_max_dfas(); \
X	    else \
X		element = 0; \
X	    }
X
X#define NEXT_QUEUE_ELEMENT(element) ((element + 1) % (current_max_dfas + 1))
X
X    for ( i = 0; i <= CSIZE; ++i )
X	{
X	duplist[i] = NIL;
X	symlist[i] = false;
X	}
X
X    for ( i = 0; i <= accnum; ++i )
X	accset[i] = NIL;
X
X    if ( trace )
X	{
X	dumpnfa( scset[1] );
X	fputs( "\n\nDFA Dump:\n\n", stderr );
X	}
X
X    inittbl();
X
X    if ( fullspd )
X	{
X	for ( i = 0; i <= numecs; ++i )
X	    state[i] = 0;
X	place_state( state, 0, 0 );
X	}
X
X    if ( fulltbl )
X	{
X	/* declare it "short" because it's a real long-shot that that
X	 * won't be large enough
X	 */
X	printf( "static short int %c[][%d] =\n    {\n", NEXTARRAY,
X		numecs + 1 ); /* '}' so vi doesn't get too confused */
X
X	/* generate 0 entries for state #0 */
X	for ( i = 0; i <= numecs; ++i )
X	    mk2data( 0 );
X
X	/* force ',' and dataflush() next call to mk2data */
X	datapos = NUMDATAITEMS;
X
X	/* force extra blank line next dataflush() */
X	dataline = NUMDATALINES;
X	}
X
X    /* create the first states */
X
X    for ( i = 1; i <= lastsc * 2; ++i )
X	{
X	numstates = 1;
X
X	/* for each start condition, make one state for the case when
X	 * we're at the beginning of the line (the '%' operator) and
X	 * one for the case when we're not
X	 */
X	if ( i % 2 == 1 )
X	    nset[numstates] = scset[(i / 2) + 1];
X	else
X	    nset[numstates] = mkbranch( scbol[i / 2], scset[i / 2] );
X
X	nset = epsclosure( nset, &numstates, accset, &nacc, &hashval );
X
X	if ( snstods( nset, numstates, accset, nacc, hashval, &ds ) )
X	    {
X	    numas = numas + nacc;
X	    totnst = totnst + numstates;
X
X	    todo[todo_next] = ds;
X	    ADD_QUEUE_ELEMENT(todo_next);
X	    }
X	}
X
X    if ( fulltbl )
X	{
X	if ( ! snstods( nset, 0, accset, 0, 0, &end_of_buffer_state ) )
X	    flexfatal( "could not create unique end-of-buffer state" );
X
X	numas += 1;
X
X	todo[todo_next] = end_of_buffer_state;
X	ADD_QUEUE_ELEMENT(todo_next);
X	}
X
X    while ( todo_head != todo_next )
X	{
X	targptr = 0;
X	totaltrans = 0;
X
X	for ( i = 1; i <= numecs; ++i )
X	    state[i] = 0;
X
X	ds = todo[todo_head];
X	todo_head = NEXT_QUEUE_ELEMENT(todo_head);
X
X	dset = dss[ds];
X	dsize = dfasiz[ds];
X
X	if ( trace )
X	    fprintf( stderr, "state # %d:\n", ds );
X
X	sympartition( dset, dsize, symlist, duplist );
X
X	for ( sym = 1; sym <= numecs; ++sym )
X	    {
X	    if ( symlist[sym] )
X		{
X		symlist[sym] = 0;
X
X		if ( duplist[sym] == NIL )
X		    { /* symbol has unique out-transitions */
X		    numstates = symfollowset( dset, dsize, sym, nset );
X		    nset = epsclosure( nset, &numstates, accset,
X				       &nacc, &hashval );
X
X		    if ( snstods( nset, numstates, accset,
X				  nacc, hashval, &newds ) )
X			{
X			totnst = totnst + numstates;
X			todo[todo_next] = newds;
X			ADD_QUEUE_ELEMENT(todo_next);
X			numas = numas + nacc;
X			}
X
X		    state[sym] = newds;
X
X		    if ( trace )
X			fprintf( stderr, "\t%d\t%d\n", sym, newds );
X
X		    targfreq[++targptr] = 1;
X		    targstate[targptr] = newds;
X		    ++numuniq;
X		    }
X
X		else
X		    {
X		    /* sym's equivalence class has the same transitions
X		     * as duplist(sym)'s equivalence class
X		     */
X		    targ = state[duplist[sym]];
X		    state[sym] = targ;
X
X		    if ( trace )
X			fprintf( stderr, "\t%d\t%d\n", sym, targ );
X
X		    /* update frequency count for destination state */
X
X		    i = 0;
X		    while ( targstate[++i] != targ )
X			;
X
X		    ++targfreq[i];
X		    ++numdup;
X		    }
X
X		++totaltrans;
X		duplist[sym] = NIL;
X		}
X	    }
X
X	numsnpairs = numsnpairs + totaltrans;
X
X	if ( caseins && ! useecs )
X	    {
X	    register int j;
X
X	    for ( i = 'A', j = 'a'; i <= 'Z'; ++i, ++j )
X		state[i] = state[j];
X	    }
X
X	if ( fulltbl )
X	    {
X	    /* supply array's 0-element */
X	    if ( ds == end_of_buffer_state )
X		mk2data( 0 );
X	    else
X		mk2data( end_of_buffer_state );
X
X	    for ( i = 1; i <= numecs; ++i )
X		mk2data( state[i] );
X
X	    /* force ',' and dataflush() next call to mk2data */
X	    datapos = NUMDATAITEMS;
X
X	    /* force extra blank line next dataflush() */
X	    dataline = NUMDATALINES;
X	    }
X
X        else if ( fullspd )
X	    place_state( state, ds, totaltrans );
X
X	else
X	    {
X	    /* determine which destination state is the most common, and
X	     * how many transitions to it there are
X	     */
X
X	    comfreq = 0;
X	    comstate = 0;
X
X	    for ( i = 1; i <= targptr; ++i )
X		if ( targfreq[i] > comfreq )
X		    {
X		    comfreq = targfreq[i];
X		    comstate = targstate[i];
X		    }
X
X	    bldtbl( state, ds, totaltrans, comstate, comfreq );
X	    }
X	}
X
X    if ( fulltbl )
X	dataend();
X
X    else
X	{
X	cmptmps();  /* create compressed template entries */
X
X	/* create tables for all the states with only one out-transition */
X	while ( onesp > 0 )
X	    {
X	    mk1tbl( onestate[onesp], onesym[onesp], onenext[onesp],
X		    onedef[onesp] );
X	    --onesp;
X	    }
X
X	mkdeftbl();
X	}
X    
X    }
X
X
X/* place_state - place a state into full speed transition table
X *
X * synopsis
X *     int *state, statenum, transnum;
X *     place_state( state, statenum, transnum );
X *
X * State is the statenum'th state.  It is indexed by equivalence class and
X * gives the number of the state to enter for a given equivalence class.
X * Transnum is the number of out-transitions for the state.
X */
X
Xplace_state( state, statenum, transnum )
Xint *state, statenum, transnum;
X
X    {
X    register int i;
X    register int *state_ptr;
X    int position = find_table_space( state, transnum );
X
X    /* base is the table of start positions */
X    base[statenum] = position;
X
X    /* put in action number marker; this non-zero number makes sure that
X     * find_table_space() knows that this position in chk/nxt is taken
X     * and should not be used for another accepting number in another state
X     */
X    chk[position - 1] = 1;
X
X    /* put in end-of-buffer marker; this is for the same purposes as above */
X    chk[position] = 1;
X
X    /* place the state into chk and nxt */
X    state_ptr = &state[1];
X
X    for ( i = 1; i <= numecs; ++i, ++state_ptr )
X	if ( *state_ptr != 0 )
X	    {
X	    chk[position + i] = i;
X	    nxt[position + i] = *state_ptr;
X	    }
X
X    if ( position + numecs > tblend )
X	tblend = position + numecs;
X    }
X
X
X/* stack1 - save states with only one out-transition to be processed later
X *
X * synopsis
X *   int statenum, sym, nextstate, deflink;
X *   stack1( statenum, sym, nextstate, deflink );
X *
X * if there's room for another state one the "one-transition" stack, the
X * state is pushed onto it, to be processed later by mk1tbl.  If there's
X * no room, we process the sucker right now.
X */
X
Xstack1( statenum, sym, nextstate, deflink )
Xint statenum, sym, nextstate, deflink;
X
X    {
X    if ( onesp >= ONE_STACK_SIZE )
X	mk1tbl( statenum, sym, nextstate, deflink );
X
X    else
X	{
X	++onesp;
X	onestate[onesp] = statenum;
X	onesym[onesp] = sym;
X	onenext[onesp] = nextstate;
X	onedef[onesp] = deflink;
X	}
X    }
X
X
X/* tbldiff - compute differences between two state tables
X *
X * synopsis
X *   int state[], pr, ext[];
X *   int tbldiff, numdifferences;
X *   numdifferences = tbldiff( state, pr, ext )
X *
X * "state" is the state array which is to be extracted from the pr'th
X * proto.  "pr" is both the number of the proto we are extracting from
X * and an index into the save area where we can find the proto's complete
X * state table.  Each entry in "state" which differs from the corresponding
X * entry of "pr" will appear in "ext".
X * Entries which are the same in both "state" and "pr" will be marked
X * as transitions to "SAME_TRANS" in "ext".  The total number of differences
X * between "state" and "pr" is returned as function value.  Note that this
X * number is "numecs" minus the number of "SAME_TRANS" entries in "ext".
X */
X
Xint tbldiff( state, pr, ext )
Xint state[], pr, ext[];
X
X    {
X    register int i, *sp = state, *ep = ext, *protp;
X    register int numdiff = 0;
X
X    protp = &protsave[numecs * (pr - 1)];
X
X    for ( i = numecs; i > 0; --i )
X	{
X	if ( *++protp == *++sp )
X	    *++ep = SAME_TRANS;
X	else
X	    {
X	    *++ep = *sp;
X	    ++numdiff;
X	    }
X	}
X
X    return ( numdiff );
X    }
SHAR_EOF
if test 39351 -ne "`wc -c < 'tblcmp.c'`"
then
	echo shar: error transmitting "'tblcmp.c'" '(should have been 39351 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 6 ---

earleh@eleazar.dartmouth.edu (Earle R. Horton) (07/03/88)

[Flex for the Mac - part 7 of 7]

---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	flex/yylex.c
#	flex/fastskeldef.h
#	flex/flexdef.h
#	flex/flexskelcom.h
#	flex/flexskeldef.h
# This archive created: Wed Jun 29 07:03:31 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'yylex.c'" '(3554 characters)'
if test -f 'yylex.c'
then
	echo shar: will not over-write existing file "'yylex.c'"
else
sed 's/^X//' << \SHAR_EOF > 'yylex.c'
X/* yylex - scanner front-end for flex */
X
X#include "flexdef.h"
X#include "parse.h"
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X/* yylex - scan for a regular expression token
X *
X * synopsis
X *
X *   token = yylex();
X *
X *     token - return token found
X */
X
Xint yylex()
X
X    {
X    int toktype;
X    static int beglin = false;
X
X    if ( eofseen )
X	toktype = EOF;
X    else
X	toktype = flexscan();
X
X    if ( toktype == EOF )
X	{
X	eofseen = 1;
X
X	if ( sectnum == 1 )
X	    {
X	    synerr( "unexpected EOF" );
X	    sectnum = 2;
X	    toktype = SECTEND;
X	    }
X
X	else if ( sectnum == 2 )
X	    {
X	    sectnum = 3;
X	    toktype = SECTEND;
X	    }
X
X	else
X	    toktype = 0;
X	}
X
X    if ( trace )
X	{
X	if ( beglin )
X	    {
X	    fprintf( stderr, "%d\t", accnum + 1 );
X	    beglin = 0;
X	    }
X
X	switch ( toktype )
X	    {
X	    case '<':
X	    case '>':
X	    case '^':
X	    case '$':
X	    case '"':
X	    case '[':
X	    case ']':
X	    case '{':
X	    case '}':
X	    case '|':
X	    case '(':
X	    case ')':
X	    case '-':
X	    case '/':
X	    case '\\':
X	    case '?':
X	    case '.':
X	    case '*':
X	    case '+':
X	    case ',':
X		(void) putc( toktype, stderr );
X		break;
X
X	    case '\n':
X		(void) putc( '\n', stderr );
X
X		if ( sectnum == 2 )
X		    beglin = 1;
X
X		break;
X
X	    case SCDECL:
X		fputs( "%s", stderr );
X		break;
X
X	    case XSCDECL:
X		fputs( "%x", stderr );
X		break;
X
X	    case WHITESPACE:
X		(void) putc( ' ', stderr );
X		break;
X
X	    case SECTEND:
X		fputs( "%%\n", stderr );
X
X		/* we set beglin to be true so we'll start
X		 * writing out numbers as we echo rules.  flexscan() has
X		 * already assigned sectnum
X		 */
X
X		if ( sectnum == 2 )
X		    beglin = 1;
X
X		break;
X
X	    case NAME:
X		fprintf( stderr, "'%s'", nmstr );
X		break;
X
X	    case CHAR:
X		switch ( yylval )
X		    {
X		    case '<':
X		    case '>':
X		    case '^':
X		    case '$':
X		    case '"':
X		    case '[':
X		    case ']':
X		    case '{':
X		    case '}':
X		    case '|':
X		    case '(':
X		    case ')':
X		    case '-':
X		    case '/':
X		    case '\\':
X		    case '?':
X		    case '.':
X		    case '*':
X		    case '+':
X		    case ',':
X			fprintf( stderr, "\\%c", yylval );
X			break;
X
X		    case 1:
X		    case 2:
X		    case 3:
X		    case 4:
X		    case 5:
X		    case 6:
X		    case 7:
X		    case 8:
X		    case 9:
X		    case 10:
X		    case 11:
X		    case 12:
X		    case 13:
X		    case 14:
X		    case 15:
X		    case 16:
X		    case 17:
X		    case 18:
X		    case 19:
X		    case 20:
X		    case 21:
X		    case 22:
X		    case 23:
X		    case 24:
X		    case 25:
X		    case 26:
X		    case 27:
X		    case 28:
X		    case 29:
X		    case 30:
X		    case 31:
X			fprintf( stderr, "^%c", 'A' + yylval - 1 );
X			break;
X
X		    case 127:
X			(void) putc( '^', stderr );
X			(void) putc( '@', stderr );
X			break;
X
X		    default:
X			(void) putc( yylval, stderr );
X			break;
X		    }
X			
X		break;
X
X	    case NUMBER:
X		fprintf( stderr, "%d", yylval );
X		break;
X
X	    case PREVCCL:
X		fprintf( stderr, "[%d]", yylval );
X		break;
X
X	    case 0:
X		fprintf( stderr, "End Marker" );
X		break;
X
X	    default:
X		fprintf( stderr, "*Something Weird* - tok: %d val: %d\n",
X			 toktype, yylval );
X		break;
X	    }
X	}
X	    
X    return ( toktype );
X    }
SHAR_EOF
if test 3554 -ne "`wc -c < 'yylex.c'`"
then
	echo shar: error transmitting "'yylex.c'" '(should have been 3554 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'fastskeldef.h'" '(2842 characters)'
if test -f 'fastskeldef.h'
then
	echo shar: will not over-write existing file "'fastskeldef.h'"
else
sed 's/^X//' << \SHAR_EOF > 'fastskeldef.h'
X/*  macro definitions for fast/full-table  C/FTL programs generated by flex */
X
X#include "flexskelcom.h"
X
X#define YY_END_OF_BUFFER_CHAR 0
X
X/* action number for "not an accepting state; back-track (not implemented)" */
X#define YY_BACK_TRACK 0
X
X/* action number for end-of-buffer was seen */
X#define YY_END_OF_BUFFER -3
X
X/* reinitializes everything except the current start condition.  The last
X * input character is set to a newline so an initial beginning-of-line
X * rule will match
X */
X#define YY_FAST_INIT \
X	{ \
X	yytext = yy_c_buf_p = &yy_ch_buf[1]; \
X	yyleng = 0; \
X	yy_hold_char = *yy_c_buf_p; \
X	}
X
X/* done before the next pattern has been matched action
X * change both of these if you change them at all!
X */
X#define YY_DO_BEFORE_SCAN \
X	*yy_c_buf_p = yy_hold_char
X#define YY_DO_BEFORE_RESTART \
X	yy_hold_char = *yy_c_buf_p
X
X/* done after the current pattern has been matched and before the
X * corresponding action
X */
X#define YY_DO_BEFORE_ACTION \
X	yytext = yy_b_buf_p; \
X	yyleng = YY_LENG; \
X	yy_hold_char = *yy_c_buf_p; \
X	*yy_c_buf_p = '\0'
X
X/* returns the length of the matched text */
X#define YY_LENG (yy_c_buf_p - yy_b_buf_p)
X
X#ifdef FLEX_FULL_TABLE
X#define YY_CS_TYPE int
X#else
X#define YY_CS_TYPE struct yy_trans_info *
X#endif
X
X/* find starting state */
X#ifdef FLEX_FULL_TABLE
X#    define YY_FIND_START_STATE( x ) \
X	    x = yy_start; \
X	    if ( yy_b_buf_p[-1] == '\n' ) \
X		++x
X#else
X#    define YY_FIND_START_STATE( x ) \
X	    x = yy_state_ptr[yy_start]; \
X	    if ( yy_b_buf_p[-1] == '\n' ) \
X		x = yy_state_ptr[yy_start + 1]
X#endif
X
X# ifdef FLEX_USE_ECS
X#     define yy_eq(x) e[x]
X# else
X#     define yy_eq(x) x
X# endif
X
X/* get next jam state from packed table */
X#ifdef FLEX_FULL_TABLE
X#    define YY_FIND_NEXT_MATCH \
X	    { \
X	    register int yy_state_info; \
X	    while ( (yy_state_info = n[yy_current_state][yy_eq(*yy_c_buf_p)] ) != YY_JAM ) \
X		{ \
X		yy_current_state = yy_state_info; \
X		YY_BACKTRACKING_ACTION \
X		yy_c_buf_p++; \
X		} \
X	    }
X#else
X#    define YY_FIND_NEXT_MATCH \
X	    for ( yy_c = yy_eq(*yy_c_buf_p); \
X		  (yy_trans_info = &yy_current_state[yy_c])->v == yy_c; \
X		  yy_c = yy_eq(*++yy_c_buf_p) ) \
X		{ \
X		yy_current_state += yy_trans_info->n; \
X		YY_BACKTRACKING_ACTION \
X		}
X#endif
X
X#ifdef FLEX_FULL_TABLE
X#    define YY_FIND_ACTION( x ) x = l[yy_current_state]
X#else
X#    define YY_FIND_ACTION( x ) x = yy_current_state[-1].n
X#endif
X
X
X#ifdef FLEX_FULL_TABLE
X#    define YY_GET_NEXT_STATE yy_cur_state = n[yy_cur_state][*(yy_temp_char_ptr++)]
X#else
X#    define YY_GET_NEXT_STATE yy_cur_state += yy_cur_state[*(yy_temp_char_ptr++)].n
X#endif
X
X#define EOB_ACT_RESTART_SCAN 2
X#define EOB_ACT_END_OF_FILE 3
X#define EOB_ACT_LAST_MATCH 4
X
X#ifdef FLEX_FULL_TABLE
X#define YY_DECLARE_YY_CS_PARAM int *yy_current_state
X#else
X#define YY_DECLARE_YY_CS_PARAM struct yy_trans_info *yy_current_state
X#endif
SHAR_EOF
if test 2842 -ne "`wc -c < 'fastskeldef.h'`"
then
	echo shar: error transmitting "'fastskeldef.h'" '(should have been 2842 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'flexdef.h'" '(17911 characters)'
if test -f 'flexdef.h'
then
	echo shar: will not over-write existing file "'flexdef.h'"
else
sed 's/^X//' << \SHAR_EOF > 'flexdef.h'
X/*
X *  Definitions for flex.
X *
X * modification history
X * --------------------
X * 02b kg, vp   30sep87  .added definitions for fast scanner; misc. cleanup
X * 02a vp       27jun86  .translated into C/FTL
X */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include <stdio.h>
X
X#ifdef MPW
X#include <string.h>
X#else
X#ifdef SV
X#include <string.h>
X#define bzero(s, n) memset((char *)(s), '\000', (unsigned)(n))
X#else
X#include <strings.h>
X#endif
X#endif
X
X/* Critical where characters are signed. */
X#ifndef BYTEMASK
X#define BYTEMASK	0xFF
X#endif
X
X
Xchar *sprintf(); /* keep lint happy */
X
X
X/* maximum line length we'll have to deal with */
X#define MAXLINE BUFSIZ
X
X/* maximum size of file name */
X#define FILENAMESIZE 1024
X
X#define min(x,y) (x < y ? x : y)
X#define max(x,y) (x > y ? x : y)
X
X#define true 1
X#define false 0
X
X
X#ifndef DEFAULT_SKELETON_FILE
X#define DEFAULT_SKELETON_FILE "flex.skel"
X#endif
X
X#ifndef FAST_SKELETON_FILE
X#define FAST_SKELETON_FILE "flex.fastskel"
X#endif
X
X/* special nxt[] action number for the "at the end of the input buffer" state */
X/* note: -1 is already taken by YY_NEW_FILE */
X#define END_OF_BUFFER_ACTION -3
X/* action number for default action for fast scanners */
X#define DEFAULT_ACTION -2
X
X/* special chk[] values marking the slots taking by end-of-buffer and action
X * numbers
X */
X#define EOB_POSITION -1
X#define ACTION_POSITION -2
X
X/* number of data items per line for -f output */
X#define NUMDATAITEMS 10
X
X/* number of lines of data in -f output before inserting a blank line for
X * readability.
X */
X#define NUMDATALINES 10
X
X/* transition_struct_out() definitions */
X#define TRANS_STRUCT_PRINT_LENGTH 15
X
X/* returns true if an nfa state has an epsilon out-transition slot
X * that can be used.  This definition is currently not used.
X */
X#define FREE_EPSILON(state) \
X	(transchar[state] == SYM_EPSILON && \
X	 trans2[state] == NO_TRANSITION && \
X	 finalst[state] != state)
X
X/* returns true if an nfa state has an epsilon out-transition character
X * and both slots are free
X */
X#define SUPER_FREE_EPSILON(state) \
X	(transchar[state] == SYM_EPSILON && \
X	 trans1[state] == NO_TRANSITION) \
X
X/* maximum number of NFA states that can comprise a DFA state.  It's real
X * big because if there's a lot of rules, the initial state will have a
X * huge epsilon closure.
X */
X#define INITIAL_MAX_DFA_SIZE 750
X#define MAX_DFA_SIZE_INCREMENT 750
X
X/* array names to be used in generated machine.  They're short because
X * we write out one data statement (which names the array) for each element
X * in the array.
X */
X
X#define ALIST 'l'	/* points to list of rules accepted for a state */
X#define ACCEPT 'a'	/* list of rules accepted for a state */
X#define ECARRAY 'e'	/* maps input characters to equivalence classes */
X#define MATCHARRAY 'm'	/* maps equivalence classes to meta-equivalence classes */
X#define BASEARRAY 'b'	/* "base" array */
X#define DEFARRAY 'd'	/* "default" array */
X#define NEXTARRAY 'n'	/* "next" array */
X#define CHECKARRAY 'c'	/* "check" array */
X
X/* NIL must be 0.  If not, its special meaning when making equivalence classes
X * (it marks the representative of a given e.c.) will be unidentifiable
X */
X#define NIL 0
X
X#define JAM -1	/* to mark a missing DFA transition */
X#define NO_TRANSITION NIL
X#define UNIQUE -1	/* marks a symbol as an e.c. representative */
X#define INFINITY -1	/* for x{5,} constructions */
X
X/* size of input alphabet - should be size of ASCII set */
X#ifdef MPW
X#define CSIZE 255
X#else
X#define CSIZE 127
X#endif
X
X#define INITIAL_MAXCCLS 100	/* max number of unique character classes */
X#define MAXCCLS_INCREMENT 100
X
X/* size of table holding members of character classes */
X#define INITIAL_MAX_CCL_TBL_SIZE 500
X#define MAX_CCL_TBL_SIZE_INCREMENT 250
X
X#define INITIAL_MNS 2000	/* default maximum number of nfa states */
X#define MNS_INCREMENT 1000	/* amount to bump above by if it's not enough */
X
X#define INITIAL_MAX_DFAS 1000	/* default maximum number of dfa states */
X#define MAX_DFAS_INCREMENT 1000
X
X#define JAMSTATE -32766	/* marks a reference to the state that always jams */
X
X/* enough so that if it's subtracted from an NFA state number, the result
X * is guaranteed to be negative
X */
X#define MARKER_DIFFERENCE 32000
X#define MAXIMUM_MNS 31999
X
X/* maximum number of nxt/chk pairs for non-templates */
X#define INITIAL_MAX_XPAIRS 2000
X#define MAX_XPAIRS_INCREMENT 2000
X
X/* maximum number of nxt/chk pairs needed for templates */
X#define INITIAL_MAX_TEMPLATE_XPAIRS 2500
X#define MAX_TEMPLATE_XPAIRS_INCREMENT 2500
X
X#define SYM_EPSILON 0	/* to mark transitions on the symbol epsilon */
X
X#define INITIAL_MAX_SCS 40	/* maximum number of start conditions */
X#define MAX_SCS_INCREMENT 40	/* amount to bump by if it's not enough */
X
X#define ONE_STACK_SIZE 500	/* stack of states with only one out-transition */
X#define SAME_TRANS -1	/* transition is the same as "default" entry for state */
X
X/* the following percentages are used to tune table compression:
X
X * the percentage the number of out-transitions a state must be of the
X * number of equivalence classes in order to be considered for table
X * compaction by using protos
X */
X#define PROTO_SIZE_PERCENTAGE 15
X
X/* the percentage the number of homogeneous out-transitions of a state
X * must be of the number of total out-transitions of the state in order
X * that the state's transition table is first compared with a potential 
X * template of the most common out-transition instead of with the first
X * proto in the proto queue
X */
X#define CHECK_COM_PERCENTAGE 50
X
X/* the percentage the number of differences between a state's transition
X * table and the proto it was first compared with must be of the total
X * number of out-transitions of the state in order to keep the first
X * proto as a good match and not search any further
X */
X#define FIRST_MATCH_DIFF_PERCENTAGE 10
X
X/* the percentage the number of differences between a state's transition
X * table and the most similar proto must be of the state's total number
X * of out-transitions to use the proto as an acceptable close match
X */
X#define ACCEPTABLE_DIFF_PERCENTAGE 50
X
X/* the percentage the number of homogeneous out-transitions of a state
X * must be of the number of total out-transitions of the state in order
X * to consider making a template from the state
X */
X#define TEMPLATE_SAME_PERCENTAGE 60
X
X/* the percentage the number of differences between a state's transition
X * table and the most similar proto must be of the state's total number
X * of out-transitions to create a new proto from the state
X */
X#define NEW_PROTO_DIFF_PERCENTAGE 20
X
X/* the percentage the total number of out-transitions of a state must be
X * of the number of equivalence classes in order to consider trying to
X * fit the transition table into "holes" inside the nxt/chk table.
X */
X#define INTERIOR_FIT_PERCENTAGE 15
X
X/* size of region set aside to cache the complete transition table of
X * protos on the proto queue to enable quick comparisons
X */
X#define PROT_SAVE_SIZE 2000
X
X#define MSP 50	/* maximum number of saved protos (protos on the proto queue) */
X
X/* maximum number of out-transitions a state can have that we'll rummage
X * around through the interior of the internal fast table looking for a
X * spot for it
X */
X#define MAX_XTIONS_FOR_FULL_INTERIOR_FIT 4
X
X/* number that, if used to subscript an array, has a good chance of producing
X * an error; should be small enough to fit into a short
X */
X#define BAD_SUBSCRIPT -32767
X
X/* absolute value of largest number that can be stored in a short, with a
X * bit of slop thrown in for general paranoia.
X */
X#define MAX_SHORT 32766
X
X
X/* Declarations for global variables. */
X
X/* variables for symbol tables:
X * sctbl - start-condition symbol table
X * ndtbl - name-definition symbol table
X * ccltab - character class text symbol table
X */
X
Xstruct hash_entry
X    {
X    struct hash_entry *prev, *next;
X    unsigned char *name;
X    unsigned char *str_val;
X    int int_val;
X    } ;
X
Xtypedef struct hash_entry *hash_table[];
X
X#define NAME_TABLE_HASH_SIZE 101
X#define START_COND_HASH_SIZE 101
X#define CCL_HASH_SIZE 101
X
Xextern struct hash_entry *ndtbl[NAME_TABLE_HASH_SIZE]; 
Xextern struct hash_entry *sctbl[START_COND_HASH_SIZE];
Xextern struct hash_entry *ccltab[CCL_HASH_SIZE];
X
X
X/* variables for flags:
X * printstats - if true (-v), dump statistics
X * syntaxerror - true if a syntax error has been found
X * eofseen - true if we've seen an eof in the input file
X * ddebug - if true (-d), make a "debug" scanner
X * trace - if true (-T), trace processing
X * spprdflt - if true (-s), suppress the default rule
X * interactive - if true (-I), generate an interactive scanner
X * caseins - if true (-i), generate a case-insensitive scanner
X * useecs - if true (-ce flag), use equivalence classes
X * fulltbl - if true (-cf flag), don't compress the DFA state table
X * usemecs - if true (-cm flag), use meta-equivalence classes
X * reject - if true (-r flag), generate tables for REJECT macro
X * fullspd - if true (-F flag), use Jacobson method of table representation
X * gen_line_dirs - if true (i.e., no -L flag), generate #line directives
X */
X
Xextern int printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
Xextern int interactive, caseins, useecs, fulltbl, usemecs, reject;
Xextern int fullspd, gen_line_dirs;
X
X
X/* variables used in the flex input routines:
X * datapos - characters on current output line
X * dataline - number of contiguous lines of data in current data
X *    statement.  Used to generate readable -f output
X * skelfile - fd of the skeleton file
X * yyin - input file
X * temp_action_file - temporary file to hold actions
X * action_file_name - name of the temporary file
X * infilename - name of input file
X * linenum - current input line number
X */
X
Xextern int datapos, dataline, linenum;
Xextern FILE *skelfile, *yyin, *temp_action_file;
Xextern char *infilename;
Xextern char *action_file_name;
X
X
X/* variables for stack of states having only one out-transition:
X * onestate - state number
X * onesym - transition symbol
X * onenext - target state
X * onedef - default base entry
X * onesp - stack pointer
X */
X
X#ifdef MALLOC_BUFFERS
Xextern int *onestate,*onesym,*onenext,*onedef,onesp;
X#else
Xextern int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
Xextern int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
X#endif
X
X
X/* variables for nfa machine data:
X * current_mns - current maximum on number of NFA states
X * accnum - number of the last accepting state
X * firstst - physically the first state of a fragment
X * lastst - last physical state of fragment
X * finalst - last logical state of fragment
X * transchar - transition character
X * trans1 - transition state
X * trans2 - 2nd transition state for epsilons
X * accptnum - accepting number
X * lastnfa - last nfa state number created
X */
X
Xextern int current_mns;
Xextern int accnum, *firstst, *lastst, *finalst, *transchar;
Xextern int *trans1, *trans2, *accptnum, lastnfa;
X
X
X/* variables for protos:
X * numtemps - number of templates created
X * numprots - number of protos created
X * protprev - backlink to a more-recently used proto
X * protnext - forward link to a less-recently used proto
X * prottbl - base/def table entry for proto
X * protcomst - common state of proto
X * firstprot - number of the most recently used proto
X * lastprot - number of the least recently used proto
X * protsave contains the entire state array for protos
X */
X#ifdef MALLOC_BUFFERS
Xextern int numtemps, numprots, *protprev, *protnext, *prottbl;
Xextern int *protcomst, firstprot, lastprot,
X#else
Xextern int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
Xextern int protcomst[MSP], firstprot, lastprot,
X#endif
X#ifdef MALLOC_BUFFERS
X	*protsave;
X#else
X	protsave[PROT_SAVE_SIZE];
X#endif
X
X
X/* variables for managing equivalence classes:
X * numecs - number of equivalence classes
X * nextecm - forward link of Equivalence Class members
X * ecgroup - class number or backward link of EC members
X * nummecs - number of meta-equivalence classes (used to compress
X *   templates)
X * tecfwd - forward link of meta-equivalence classes members
X * tecbck - backward link of MEC's
X */
X#ifdef MALLOC_BUFFERS
Xextern int numecs, *nextecm, *ecgroup, nummecs;
Xextern int *tecfwd, *tecbck;
X#else
Xextern int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs;
Xextern int tecfwd[CSIZE + 1], tecbck[CSIZE + 1];
X#endif
X
X
X/* variables for start conditions:
X * lastsc - last start condition created
X * current_max_scs - current limit on number of start conditions
X * scset - set of rules active in start condition
X * scbol - set of rules active only at the beginning of line in a s.c.
X * scxclu - true if start condition is exclusive
X * actvsc - stack of active start conditions for the current rule
X */
X
Xextern int lastsc, current_max_scs, *scset, *scbol, *scxclu, *actvsc;
X
X
X/* variables for dfa machine data:
X * current_max_dfa_size - current maximum number of NFA states in DFA
X * current_max_xpairs - current maximum number of non-template xtion pairs
X * current_max_template_xpairs - current maximum number of template pairs
X * current_max_dfas - current maximum number DFA states
X * lastdfa - last dfa state number created
X * nxt - state to enter upon reading character
X * chk - check value to see if "nxt" applies
X * tnxt - internal nxt table for templates
X * base - offset into "nxt" for given state
X * def - where to go if "chk" disallows "nxt" entry
X * tblend - last "nxt/chk" table entry being used
X * firstfree - first empty entry in "nxt/chk" table
X * dss - nfa state set for each dfa
X * dfasiz - size of nfa state set for each dfa
X * dfaacc - accepting set for each dfa state (or accepting number, if
X *    -r is not given)
X * accsiz - size of accepting set for each dfa state
X * dhash - dfa state hash value
X * todo - queue of DFAs still to be processed
X * todo_head - head of todo queue
X * todo_next - next available entry on todo queue
X * numas - number of DFA accepting states created; note that this
X *    is not necessarily the same value as accnum, which is the analogous
X *    value for the NFA
X * numsnpairs - number of state/nextstate transition pairs
X * jambase - position in base/def where the default jam table starts
X * jamstate - state number corresponding to "jam" state
X * end_of_buffer_state - end-of-buffer dfa state number
X */
X
Xextern int current_max_dfa_size, current_max_xpairs;
Xextern int current_max_template_xpairs, current_max_dfas;
Xextern int lastdfa, lasttemp, *nxt, *chk, *tnxt;
Xextern int *base, *def, tblend, firstfree, **dss, *dfasiz;
Xextern union dfaacc_union
X    {
X    int *dfaacc_set;
X    int dfaacc_state;
X    } *dfaacc;
Xextern int *accsiz, *dhash, *todo, todo_head, todo_next, numas;
Xextern int numsnpairs, jambase, jamstate;
Xextern int end_of_buffer_state;
X
X/* variables for ccl information:
X * lastccl - ccl index of the last created ccl
X * current_maxccls - current limit on the maximum number of unique ccl's
X * cclmap - maps a ccl index to its set pointer
X * ccllen - gives the length of a ccl
X * cclng - true for a given ccl if the ccl is negated
X * cclreuse - counts how many times a ccl is re-used
X * current_max_ccl_tbl_size - current limit on number of characters needed
X *	to represent the unique ccl's
X * ccltbl - holds the characters in each ccl - indexed by cclmap
X */
X
Xextern int lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
Xextern int current_max_ccl_tbl_size;
Xextern char *ccltbl;
X
X
X/* variables for miscellaneous information:
X * starttime - real-time when we started
X * endtime - real-time when we ended
X * nmstr - last NAME scanned by the scanner
X * sectnum - section number currently being parsed
X * nummt - number of empty nxt/chk table entries
X * hshcol - number of hash collisions detected by snstods
X * dfaeql - number of times a newly created dfa was equal to an old one
X * numeps - number of epsilon NFA states created
X * eps2 - number of epsilon states which have 2 out-transitions
X * num_reallocs - number of times it was necessary to realloc() a group
X *		  of arrays
X * tmpuses - number of DFA states that chain to templates
X * totnst - total number of NFA states used to make DFA states
X * peakpairs - peak number of transition pairs we had to store internally
X * numuniq - number of unique transitions
X * numdup - number of duplicate transitions
X * hshsave - number of hash collisions saved by checking number of states
X */
X
Xextern char *starttime, *endtime, nmstr[MAXLINE];
Xextern int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
Xextern int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
X
Xchar *allocate_array(), *reallocate_array();
X
X#define allocate_integer_array(size) \
X	(int *) allocate_array( size, sizeof( int ) )
X
X#define reallocate_integer_array(array,size) \
X	(int *) reallocate_array( (char *) array, size, sizeof( int ) )
X
X#define allocate_integer_pointer_array(size) \
X	(int **) allocate_array( size, sizeof( int * ) )
X
X#define allocate_dfaacc_union(size) \
X	(union dfaacc_union *) \
X		allocate_array( size, sizeof( union dfaacc_union ) )
X
X#define reallocate_integer_pointer_array(array,size) \
X	(int **) reallocate_array( (char *) array, size, sizeof( int * ) )
X
X#define reallocate_dfaacc_union(array, size) \
X	(union dfaacc_union *)  reallocate_array( (char *) array, size, sizeof( union dfaacc_union ) )
X
X#define allocate_character_array(size) allocate_array( size, sizeof( char ) )
X
X#define reallocate_character_array(array,size) \
X	reallocate_array( array, size, sizeof( char ) )
X
X
X/* used to communicate between scanner and parser.  The type should really
X * be YYSTYPE, but we can't easily get our hands on it.
X */
Xextern int yylval;
SHAR_EOF
if test 17911 -ne "`wc -c < 'flexdef.h'`"
then
	echo shar: error transmitting "'flexdef.h'" '(should have been 17911 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'flexskelcom.h'" '(2466 characters)'
if test -f 'flexskelcom.h'
then
	echo shar: will not over-write existing file "'flexskelcom.h'"
else
sed 's/^X//' << \SHAR_EOF > 'flexskelcom.h'
X/* common macro definitions for C/FTL programs generated by flex */
X
X/* Critical where characters are signed. */
X#define BYTEMASK	0xFF
X
X/* returned upon end-of-file */
X#define YY_END_TOK 0
X
X/* action number for an "end-of-file was seen and yywrap indicated that we
X * should continue processing"
X */
X#define YY_NEW_FILE -1
X
X/* action number for "the default action should be done" */
X#define YY_DO_DEFAULT -2
X
X#ifndef BUFSIZ
X#include <stdio.h>
X#endif
X
X#define YY_BUF_SIZE (BUFSIZ * 2) /* size of input buffer */
X
X/* number of characters one rule can match.  One less than YY_BUF_SIZE to make
X * sure we never access beyond the end of an array
X */
X#define YY_BUF_MAX (YY_BUF_SIZE - 1)
X
X/* we will never use more than the first YY_BUF_LIM + YY_MAX_LINE positions
X * of the input buffer
X */
X#ifndef YY_MAX_LINE
X#define YY_MAX_LINE BUFSIZ
X#endif
X
X#define YY_BUF_LIM (YY_BUF_MAX - YY_MAX_LINE)
X
X/* copy whatever the last rule matched to the standard output */
X
X#define ECHO fputs( yytext, yyout )
X
X/* gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
X * is returned in "result".
X */
X#define YY_INPUT(buf,result,max_size) \
X	if ( (result = read( fileno(yyin), buf, max_size )) < 0 ) \
X	    YY_FATAL_ERROR( "read() in flex scanner failed" );
X#define YY_NULL 0
X
X/* macro used to output a character */
X#define YY_OUTPUT(c) putc( c, yyout );
X
X/* report a fatal error */
X#define YY_FATAL_ERROR(msg) \
X	{ \
X	fputs( msg, stderr ); \
X	putc( '\n', stderr ); \
X	exit( 1 ); \
X	}
X
X/* returns the first character of the matched text */
X#define YY_FIRST_CHAR yy_ch_buf[yy_b_buf_p]
X
X/* default yywrap function - always treat EOF as an EOF */
X#define yywrap() 1
X
X/* enter a start condition.  This macro really ought to take a parameter,
X * but we do it the disgusting crufty way that old Unix-lex does it
X */
X#define BEGIN yy_start = 1 +
X
X/* callable from YY_INPUT to set things up so that '%' will match.  Proper
X * usage is "YY_SET_BOL(array,pos)"
X */
X#define YY_SET_BOL(array,pos) array[pos - 1] = '\n';
X
X/* default declaration of generated scanner - a define so the user can
X * easily add parameters
X */
X#define YY_DECL int yylex()
X
X/* return all but the first 'n' matched characters back to the input stream */
X#define yyless(n) \
X	{ \
X	YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */ \
X	yy_c_buf_p = yy_b_buf_p + n - 1; \
X	YY_DO_BEFORE_ACTION; /* set up yytext again */ \
X	}
X
X/* code executed at the end of each rule */
X#define YY_BREAK break;
SHAR_EOF
if test 2466 -ne "`wc -c < 'flexskelcom.h'`"
then
	echo shar: error transmitting "'flexskelcom.h'" '(should have been 2466 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'flexskeldef.h'" '(1197 characters)'
if test -f 'flexskeldef.h'
then
	echo shar: will not over-write existing file "'flexskeldef.h'"
else
sed 's/^X//' << \SHAR_EOF > 'flexskeldef.h'
X/* macro definitions for compressed-table C/FTL programs generated by flex */
X
X#include "flexskelcom.h"
X
X/* reinitializes everything except the current start condition.  The last
X * input character is set to a newline so an initial beginning-of-line
X * rule will match
X */
X#define YY_INIT \
X	{ \
X	yyleng = yy_c_buf_p = yy_e_buf_p = 0; \
X	yy_hold_char = yy_ch_buf[yy_c_buf_p] = '\n'; \
X	yytext = &yy_ch_buf[yy_c_buf_p]; \
X	yy_saw_eof = 0; \
X	}
X
X/* returns the length of the matched text */
X#define YY_LENG (yy_c_buf_p - yy_b_buf_p + 1)
X
X/* done before the next pattern has been matched action */
X#define YY_DO_BEFORE_SCAN \
X	yytext[yyleng] = yy_hold_char;
X
X/* done after the current pattern has been matched and before the corresponding action */
X#define YY_DO_BEFORE_ACTION \
X	yytext = &yy_ch_buf[yy_b_buf_p]; \
X	yyleng = YY_LENG; \
X	yy_hold_char = yytext[yyleng]; \
X	yytext[yyleng] = '\0';
X
X/* find the next rule matched */
X#ifdef FLEX_REJECT_ENABLED
X#define REJECT \
X        { \
X	YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */ \
X        ++yy_lp; \
X        goto find_rule; \
X        }
X#else
X#define REJECT YY_FATAL_ERROR( "REJECT used and scanner was not generated using -r" )
X#endif
SHAR_EOF
if test 1197 -ne "`wc -c < 'flexskeldef.h'`"
then
	echo shar: error transmitting "'flexskeldef.h'" '(should have been 1197 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 7 ---