Subject: v23i045: Flex, a fast lex replacement, Part09/10 Newsgroups: comp.sources.unix Approved: rsalz@uunet.UU.NET X-Checksum-Snefru: 03a4a332 d2dd5468 7ad02658 144eaae4 Submitted-by: Vern Paxson Posting-number: Volume 23, Issue 45 Archive-name: flex2.3/part09 #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: Changes MISC/MSDOS.notes MISC/Turbo-C.notes ecs.c parse.y # Wrapped by rsalz@litchi.bbn.com on Wed Oct 10 13:24:05 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive 9 (of 10)."' if test -f 'Changes' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Changes'\" else echo shar: Extracting \"'Changes'\" \(12334 characters\) sed "s/^X//" >'Changes' <<'END_OF_FILE' XChanges between 2.3 Patch #6 (29Aug90) and 2.3 Patch #5: X X - Fixed a serious bug in yymore() which basically made it X completely broken. Thanks goes to Jean Christophe of X the Nethack development team for finding the problem X and passing along the fix. X X XChanges between 2.3 Patch #5 (16Aug90) and 2.3 Patch #4: X X - An up-to-date version of initscan.c so "make test" will X work after applying the previous patches X X XChanges between 2.3 Patch #4 (14Aug90) and 2.3 Patch #3: X X - Fixed bug in hexadecimal escapes which allowed only digits, X not letters, in escapes X - Fixed bug in previous "Changes" file! X X XChanges between 2.3 Patch #3 (03Aug90) and 2.3 Patch #2: X X - Correction to patch #2 for gcc compilation; thanks goes to X Paul Eggert for catching this. X X XChanges between 2.3 Patch #2 (02Aug90) and original 2.3 release: X X - Fixed (hopefully) headaches involving declaring malloc() X and free() for gcc, which defines __STDC__ but (often) doesn't X come with the standard include files such as . X Reordered #ifdef maze in the scanner skeleton in the hope of X getting the declarations right for cfront and g++, too. X X - Note that this patch supercedes patch #1 for release 2.3, X which was never announced but was available briefly for X anonymous ftp. X X XChanges between 2.3 (full) release of 28Jun90 and 2.2 (alpha) release: X X User-visible: X X - A lone <> rule (that is, one which is not qualified with X a list of start conditions) now specifies the EOF action for X *all* start conditions which haven't already had <> actions X given. To specify an end-of-file action for just the initial X state, use <>. X X - -d debug output is now contigent on the global yy_flex_debug X being set to a non-zero value, which it is by default. X X - A new macro, YY_USER_INIT, is provided for the user to specify X initialization action to be taken on the first call to the X scanner. This action is done before the scanner does its X own initialization. X X - yy_new_buffer() has been added as an alias for yy_create_buffer() X X - Comments beginning with '#' and extending to the end of the line X now work, but have been deprecated (in anticipation of making X flex recognize #line directives). X X - The funky restrictions on when semi-colons could follow the X YY_NEW_FILE and yyless macros have been removed. They now X behave identically to functions. X X - A bug in the sample redefinition of YY_INPUT in the documentation X has been corrected. X X - A bug in the sample simple tokener in the documentation has X been corrected. X X - The documentation on the incompatibilities between flex and X lex has been reordered so that the discussion of yylineno X and input() come first, as it's anticipated that these will X be the most common source of headaches. X X X Things which didn't used to be documented but now are: X X - flex interprets "^foo|bar" differently from lex. flex interprets X it as "match either a 'foo' or a 'bar', providing it comes at the X beginning of a line", whereas lex interprets it as "match either X a 'foo' at the beginning of a line, or a 'bar' anywhere". X X - flex initializes the global "yyin" on the first call to the X scanner, while lex initializes it at compile-time. X X - yy_switch_to_buffer() can be used in the yywrap() macro/routine. X X - flex scanners do not use stdio for their input, and hence when X writing an interactive scanner one must explictly call fflush() X after writing out a prompt. X X - flex scanner can be made reentrant (after a fashion) by using X "yyrestart( yyin );". This is useful for interactive scanners X which have interrupt handlers that long-jump out of the scanner. X X - a defense of why yylineno is not supported is included, along X with a suggestion on how to convert scanners which rely on it. X X X Other changes: X X - Prototypes and proper declarations of void routines have X been added to the flex source code, courtesy of Kevin B. Kenny. X X - Routines dealing with memory allocation now use void* pointers X instead of char* - see Makefile for porting implications. X X - Error-checking is now done when flex closes a file. X X - Various lint tweaks were added to reduce the number of gripes. X X - Makefile has been further parameterized to aid in porting. X X - Support for SCO Unix added. X X - Flex now sports the latest & greatest UC copyright notice X (which is only slightly different from the previous one). X X - A note has been added to flexdoc.1 mentioning work in progress X on modifying flex to generate straight C code rather than a X table-driven automaton, with an email address of whom to contact X if you are working along similar lines. X X XChanges between 2.2 Patch #3 (30Mar90) and 2.2 Patch #2: X X - fixed bug which caused -I scanners to bomb X X XChanges between 2.2 Patch #2 (27Mar90) and 2.2 Patch #1: X X - fixed bug writing past end of input buffer in yyunput() X - fixed bug detecting NUL's at the end of a buffer X X XChanges between 2.2 Patch #1 (23Mar90) and 2.2 (alpha) release: X X - Makefile fixes: definition of MAKE variable for systems X which don't have it; installation of flexdoc.1 along with X flex.1; fixed two bugs which could cause "bigtest" to fail. X X - flex.skel fix for compiling with g++. X X - README and flexdoc.1 no longer list an out-of-date BITNET address X for contacting me. X X - minor typos and formatting changes to flex.1 and flexdoc.1. X X XChanges between 2.2 (alpha) release of March '90 and previous release: X X User-visible: X X - Full user documentation now available. X X - Support for 8-bit scanners. X X - Scanners now accept NUL's. X X - A facility has been added for dealing with multiple X input buffers. X X - Two manual entries now. One which fully describes flex X (rather than just its differences from lex), and the X other for quick(er) reference. X X - A number of changes to bring flex closer into compliance X with the latest POSIX lex draft: X X %t support X flex now accepts multiple input files and concatenates X them together to form its input X previous -c (compress) flag renamed -C X do-nothing -c and -n flags added X Any indented code or code within %{}'s in section 2 is X now copied to the output X X - yyleng is now a bona fide global integer. X X - -d debug information now gives the line number of the X matched rule instead of which number rule it was from X the beginning of the file. X X - -v output now includes a summary of the flags used to generate X the scanner. X X - unput() and yyrestart() are now globally callable. X X - yyrestart() no longer closes the previous value of yyin. X X - C++ support; generated scanners can be compiled with C++ compiler. X X - Primitive -lfl library added, containing default main() X which calls yylex(). A number of routines currently living X in the scanner skeleton will probably migrate to here X in the future (in particular, yywrap() will probably cease X to be a macro and instead be a function in the -lfl library). X X - Hexadecimal (\x) escape sequences added. X X - Support for MS-DOS, VMS, and Turbo-C integrated. X X - The %used/%unused operators have been deprecated. They X may go away soon. X X X Other changes: X X - Makefile enhanced for easier testing and installation. X - The parser has been tweaked to detect some erroneous X constructions which previously were missed. X - Scanner input buffer overflow is now detected. X - Bugs with missing "const" declarations fixed. X - Out-of-date Minix/Atari patches provided. X - Scanners no longer require printf() unless FLEX_DEBUG is being used. X - A subtle input() bug has been fixed. X - Line numbers for "continued action" rules (those following X the special '|' action) are now correct. X - unput() bug fixed; had been causing problems porting flex to VMS. X - yymore() handling rewritten to fix bug with interaction X between yymore() and trailing context. X - EOF in actions now generates an error message. X - Bug involving -CFe and generating equivalence classes fixed. X - Bug which made -CF be treated as -Cf fixed. X - Support for SysV tmpnam() added. X - Unused #define's for scanner no longer generated. X - Error messages which are associated with a particular input X line are now all identified with their input line in standard X format. X - % directives which are valid to lex but not to flex are X now ignored instead of generating warnings. X - -DSYS_V flag can now also be specified -DUSG for System V X compilation. X X XChanges between 2.1 beta-test release of June '89 and previous release: X X User-visible: X X - -p flag generates a performance report to stderr. The report X consists of comments regarding features of the scanner rules X which result in slower scanners. X X - -b flag generates backtracking information to lex.backtrack. X This is a list of scanner states which require backtracking X and the characters on which they do so. By adding rules X one can remove backtracking states. If all backtracking states X are eliminated, the generated scanner will run faster. X Backtracking is not yet documented in the manual entry. X X - Variable trailing context now works, i.e., one can have X rules like "(foo)*/[ \t]*bletch". Some trailing context X patterns still cannot be properly matched and generate X error messages. These are patterns where the ending of the X first part of the rule matches the beginning of the second X part, such as "zx*/xy*", where the 'x*' matches the 'x' at X the beginning of the trailing context. Lex won't get these X patterns right either. X X - Faster scanners. X X - End-of-file rules. The special rule "<>" indicates X actions which are to be taken when an end-of-file is X encountered and yywrap() returns non-zero (i.e., indicates X no further files to process). See manual entry for example. X X - The -r (reject used) flag is gone. flex now scans the input X for occurrences of the string "REJECT" to determine if the X action is needed. It tries to be intelligent about this but X can be fooled. One can force the presence or absence of X REJECT by adding a line in the first section of the form X "%used REJECT" or "%unused REJECT". X X - yymore() has been implemented. Similarly to REJECT, flex X detects the use of yymore(), which can be overridden using X "%used" or "%unused". X X - Patterns like "x{0,3}" now work (i.e., with lower-limit == 0). X X - Removed '\^x' for ctrl-x misfeature. X X - Added '\a' and '\v' escape sequences. X X - \ now works for octal escape sequences; previously X \0 was required. X X - Better error reporting; line numbers are associated with rules. X X - yyleng is a macro; it cannot be accessed outside of the X scanner source file. X X - yytext and yyleng should not be modified within a flex action. X X - Generated scanners #define the name FLEX_SCANNER. X X - Rules are internally separated by YY_BREAK in lex.yy.c rather X than break, to allow redefinition. X X - The macro YY_USER_ACTION can be redefined to provide an action X which is always executed prior to the matched rule's action. X X - yyrestart() is a new action which can be used to restart X the scanner after it has seen an end-of-file (a "real" one, X that is, one for which yywrap() returned non-zero). It takes X a FILE* argument indicating a new file to scan and sets X things up so that a subsequent call to yylex() will start X scanning that file. X X - Internal scanner names all preceded by "yy_" X X - lex.yy.c is deleted if errors are encountered during processing. X X - Comments may be put in the first section of the input by preceding X them with '#'. X X X X Other changes: X X - Some portability-related bugs fixed, in particular for machines X with unsigned characters or sizeof( int* ) != sizeof( int ). X Also, tweaks for VMS and Microsoft C (MS-DOS), and identifiers all X trimmed to be 31 or fewer characters. Shortened file names X for dinosaur OS's. Checks for allocating > 64K memory X on 16 bit'ers. Amiga tweaks. Compiles using gcc on a Sun-3. X - Compressed and fast scanner skeletons merged. X - Skeleton header files done away with. X - Generated scanner uses prototypes and "const" for __STDC__. X - -DSV flag is now -DSYS_V for System V compilation. X - Removed all references to FTL language. X - Software now covered by BSD Copyright. X - flex will replace lex in subsequent BSD releases. END_OF_FILE if test 12334 -ne `wc -c <'Changes'`; then echo shar: \"'Changes'\" unpacked with wrong size! fi # end of 'Changes' fi if test -f 'MISC/MSDOS.notes' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MISC/MSDOS.notes'\" else echo shar: Extracting \"'MISC/MSDOS.notes'\" \(5328 characters\) sed "s/^X//" >'MISC/MSDOS.notes' <<'END_OF_FILE' X$Header:$ X XNotes on Porting flex to MS-DOS X------------------------------- X X[These notes were last revised 30Dec89 for flex release 2.2.] X XPrevious releases of flex have been successfully built using Microsoft C and Xthe following options: /AL, /stack:10000, -LARGE, -Ml, -Mt128, -DSYS_V X XOther folks report that the following work for MSC 5.1 under DOS and OS/2: X X CFLAGS=-ALu -F 8000 -Gt16000 -Ox -DMS_DOS -DSYS_V -D__RUNTIME_YYMAXDEPTH X LINKFLAGS=/E /FAR /PAC /NOI X XWhere you may want to adjust -F up in order to increase available stack Xsize (though it may not be necessary) and you may want to increase -Gt Xto some number that puts just enought of the big data items in their own Xdata segments. (The default for -Gt is items of 32k. This is too high for Xflex.) __RUNTIME_YYMAXDEPTH is useful if you have a parse.c that's Xbeen generated by a yacc that understands how to do this; otherwise, it's a Xno-op. X XJeffrey R. Jones (jjones@angate.att.com) writes [this has been edited -vp]: X X.... The port was accomplished with: X X AT&T 6312 WGS (12 Mhz AT class machine) X Microsoft C compiler Version 5.0 X 'make' utility from Aztec-C package (subset of unix-make) X XThe re-done makefile is included .... Do what you wish with it. X X X[note that this Makefile is now slightly out of date and has not been X tested with flex 2.2] X X# This makefile is used to port the flex 2.1 build to a PC. The compiler is X# Microsoft-C Version 5.0 while the 'make' utility came with Aztec-C, which X# is VERY compatible with Unix's make. There are a few things that Aztec-C's X# 'make' can't do that unix does so I have made a few minor changes. X# At the least you can manually compile each file and then link. X# The linker and library utilities are alos Microsoft's. X# X# Additionally, after building with the large model, the flex.map reveals that X# code-size is less than 64K, therefore, in favor of a little more execution X# efficiency, I built with the compact model. I've used the default compiler X# optimization (no /O switches). X# X# The linker must be told to increase the run-time stack space. The default X# stack space is 2048. Flexing scan.l with the default stack-space results in X# a run-time stack overflow, hence the stack was increase to 4096. X# X# NOTE: I have MKS-Toolkit's yacc and was able to use it with virtually no X# modifications to anything. If you don't have yacc for a PC, you can try X# yaccing on a unix system and downloading the resulting files to the PC. X# X# Jeffrey R. Jones X# jjones@angate!att.com X X X# make file for "flex" tool X X# @(#) $Header: Makefile,v 2.3 89/06/20 17:27:12 vern Exp $ (LBL) X X# Porting considerations: X# X# For System V Unix machines, add -DSYS_V to CFLAGS. X# For Vax/VMS, add -DSYS_V to CFLAGS. X# For MS-DOS, add "-DMS_DOS -DSYS_V" to CFLAGS. Create \tmp if not present. X# You will also want to rename flex.skel to something with a three X# character extension, change SKELETON_FILE below appropriately, X# For Amiga, add "-DAMIGA -DSYS_V" to CFLAGS. X X X# the first time around use "make first_flex" X X XYACC=yacc XSKELETON_DIR = c:/usr/contrib/lib XSKELETON_FILE = flex.ske XSKELFLAGS = -DDEFAULT_SKELETON_FILE=\"$(SKELETON_DIR)/$(SKELETON_FILE)\" XCFLAGS = -c -AC -DMS_DOS -DSYS_V XLDFLAGS = /noi /cp:1 /stack:4096 X X#this null definition prevents a returned error code XMFLAGS = X XFLEX_FLAGS = XFLEX = flex XCC = cl X X# redefine Aztec make's built-in rule X.c.obj: X $(CC) $(CFLAGS) $*.c X X# break obj-list into two because of 128 character command-line limit of X# Microsoft's link and lib utilities. XFLEXOBJS1 = ccl.obj dfa.obj ecs.obj gen.obj main.obj misc.obj nfa.obj parse.obj XFLEXOBJS2 = scan.obj sym.obj tblcmp.obj yylex.obj X XFLEX_C_SOURCES = \ X ccl.c \ X dfa.c \ X ecs.c \ X gen.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 X# lib is used to get around the 128 character command-line limit of 'link'. Xflex.exe : $(FLEXOBJS1) $(FLEXOBJS2) X lib tmplib $(FLEXOBJS1); X link $(LDFLAGS) $(FLEXOBJS2),$*.exe,,tmplib; X rm -f tmplib.lib X X# the second 'make flex.exe' causes scan.l to be RE-flexed. The resulting X# scan.c is different from initscan.c in that \r\n are added instead of X# just \n. Since \r\n is DOS language and this is targetted for PCs, and X# since I don't know what would happen for all cases in DOS-land, I went X# ahead and did it. Xfirst_flex: X cp initscan.c scan.c X make $(MFLAGS) flex.exe X rm -f scan.c X make flex.exe X Xparse.obj: parse.c parse.h X Xparse.h parse.c : parse.y X $(YACC) -d parse.y X @mv ytab.c parse.c X @mv ytab.h parse.h X Xscan.c : scan.l X $(FLEX) -ist $(FLEX_FLAGS) scan.l > scan.c X Xscan.obj : scan.c parse.h X Xmain.obj : main.c X $(CC) $(CFLAGS) $(SKELFLAGS) main.c X X################### X#don't have, or need, anything else except maybe the 'test' rule. X# X# don't have nroff X#flex.man : flex.1 X# nroff -man flex.1 >flex.man X# X# don't have lint X#lint : $(FLEX_C_SOURCES) X# lint $(FLEX_C_SOURCES) > flex.lint X# X#distrib : X# mv scan.c initscan.c X# chmod 444 initscan.c X# $(MAKE) $(MFLAGS) clean X# X#clean : X# rm -f core errs flex *.o parse.c *.lint parse.h flex.man tags X# X#tags : X# ctags $(FLEX_C_SOURCES) X# X#vms : flex.man X# $(MAKE) $(MFLAGS) distrib X# X# break this up into multiple lines...Aztec 'make' limitation Xtest : X $(FLEX) -ist $(FLEX_FLAGS) scan.l > scan.tst X diff scan.c scan.tst X rm -f scan.tst END_OF_FILE if test 5328 -ne `wc -c <'MISC/MSDOS.notes'`; then echo shar: \"'MISC/MSDOS.notes'\" unpacked with wrong size! fi # end of 'MISC/MSDOS.notes' fi if test -f 'MISC/Turbo-C.notes' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MISC/Turbo-C.notes'\" else echo shar: Extracting \"'MISC/Turbo-C.notes'\" \(6089 characters\) sed "s/^X//" >'MISC/Turbo-C.notes' <<'END_OF_FILE' X(Message inbox:25) XDate: Tue, 29 Aug 89 18:57:48 pst XFrom: few@quad1.quad.com (Frank Whaley) XSubject: Re: flex 2.1 for Turbo C XTo: vern@cs.cornell.edu X X> Sorry it's taken me so long to get back to you - I've been out of touch X> for about the last month. X XI didn't expect to hear from you soon -- hope your journey was nice. X X> I'd like to have your 'adjustments' for Turbo C, so if you still have X> them lying conveniently around, please mail them to me. Thanks. X XAfter a little more fiddling, the changes are relatively small. Probably Xthe largest problem is that Turbo C does not yet claim to adhere to the Xdraft standard, so even though they support many "modern" constructs, they Xstill are not __STDC__. Thus the diffs from flex.skl (note the name): X X 62c62 X < #if defined(__STDC__) || defined(__TURBOC__) X --- X > #ifdef __STDC__ X 104c104 X < #if !(defined(__STDC__) || defined(__TURBOC__)) X --- X > #ifndef __STDC__ X 134c134 X < #if defined(__STDC__) || defined(__TURBOC__) X --- X > #ifdef __STDC__ X 390c390 X < #if defined(__STDC__) || defined(__TURBOC__) X --- X > #ifdef __STDC__ X 482c482 X < #if defined(__STDC__) || defined(__TURBOC__) X --- X > #ifdef __STDC__ X Xand initscan.c: X X 63c63 X < #if defined(__STDC__) || defined(__TURBOC__) X --- X > #ifdef __STDC__ X 105c105 X < #if !(defined(__STDC__) || defined(__TURBOC__)) X --- X > #ifndef __STDC__ X 677c677 X < #if defined(__STDC__) || defined(__TURBOC__) X --- X > #ifdef __STDC__ X 1658c1658 X < #if defined(__STDC__) || defined(__TURBOC__) X --- X > #ifdef __STDC__ X 1750c1750 X < #if defined(__STDC__) || defined(__TURBOC__) X --- X > #ifdef __STDC__ X Xare pretty simple. BTW, simply adding -D__STDC__=1 to CFLAGS works, but X__STDC__ is used in many Turbo C header files, and can confuse things. XIt would also mean that all flex-generated code must be compiled with Xthat flag. X Xflexdef.h also had one small problem: X X 44,46c44 X < #ifndef MS_DOS X < char *memset(); /* should be declared in string.h */ X < #endif X --- X > char *memset(); X Xas the Turbo C definiton of memset() is: X void *memset(void *s, int c, size_t n); X XThe 128-byte command line limit of MS-DOS prevents us from using tcc to Xlink the objects together, so I provide a tlink script, flex.lnk: X----- X\turboc\lib\c0l+ Xccl+ Xdfa+ Xecs+ Xgen+ Xmain+ Xmisc+ Xnfa+ Xparse+ Xscan+ Xsym+ Xtblcmp+ Xyylex Xflex.exe X X\turboc\lib\cl X----- X XThe blank line is required. X XThe makefile needed a lot of hacking, so here it is in its entirety. XI don't think it is completely finished, but I'll be happy to work on Xit more if you'd like. Some of the changes are specific to my environment X(my yacc outputs ytab.c and ytab.h) and most MS-DOS people won't have Xcp, mv and rm. Some people like separate makefiles for different Xsystems, but we like one makefile with obscene parameterization. X XI should note that all of my experiments with FLEX_FLAGS=-{c,f,F,e} Xhave failed, mostly due to scan.c becoming too large to be a single Xmodule. Damn toy operating system. X----- X# make file for "flex" tool X X# @(#) $Header: Makefile,v 2.3 89/06/20 17:27:12 vern Exp $ (LBL) X X# Porting considerations: X# X# For BSD machines: X# CFLAGS = X# LDFLAGS = -s X# LINK = $(CC) $(CFLAGS) -o flex $(LDFLAGS) $(FLEXOBJS) X# SKELETON_DIR = . X# SKELETON_FILE = flex.skel X# SKELFLAGS = -DDEFAULT_SKELETON_FILE=\"$(SKELETON_DIR)/$(SKELETON_FILE)\" X# O = o X# YTAB = y.tab X# FLEX = ./flex X# X# For System V Unix or Vax/VMS machines, merely add: X# CFLAGS = -DSYS_V X# X# For MS-DOS, Turbo C: XCC = tcc XCFLAGS = -DSYS_V -DMS_DOS -O -G -Z -ml -v XLINK = tlink @flex.lnk/c/x/v XSKELETON_DIR = . XSKELETON_FILE = flex.skl XSKELFLAGS = -DDEFAULT_SKELETON_FILE="$(SKELETON_DIR)/$(SKELETON_FILE)" XO = obj XEXE = .exe XYTAB = ytab XFLEX = flex X X# X# the first time around use "make first_flex" X# X XFLEX_FLAGS = X XFLEXOBJS = \ X ccl.$O \ X dfa.$O \ X ecs.$O \ X gen.$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 gen.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$(EXE): $(FLEXOBJS) X $(LINK) X Xfirst_flex: X cp initscan.c scan.c X $(MAKE) flex$(EXE) X Xparse.h parse.c: parse.y X $(YACC) -d parse.y X @mv $(YTAB).c parse.c X @mv $(YTAB).h parse.h X Xscan.c: scan.l X $(FLEX) -ist $(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.man: flex.1 X nroff -man flex.1 >flex.man X Xlint: $(FLEX_C_SOURCES) X lint $(FLEX_C_SOURCES) > flex.lint X Xdistrib: X mv scan.c initscan.c X chmod 444 initscan.c X $(MAKE) clean X Xclean: X rm -f core errs flex *.$O parse.c *.lint parse.h flex.man tags X Xtags: X ctags $(FLEX_C_SOURCES) X Xvms: flex.man X $(MAKE) distrib X Xtest: X $(FLEX) -ist $(FLEX_FLAGS) scan.l | diff scan.c - X----- X XBTW, thanks for a great tool. X XFrank Whaley XSenior Development Engineer XQuadratron Systems Incorporated Xfew@quad1.quad.com Xuunet!ccicpg!quad1!few X(Message inbox:8) XDate: Thu, 31 Aug 89 14:57:36 pst XFrom: few@quad1.quad.com (Frank Whaley) XSubject: Re: flex 2.1 for Turbo C XTo: vern@cs.cornell.edu X X> Thanks for the diffs and Makefile. I'll endeavor to integrate them X> into the next release. X XOne terribly important thing I forgot -- Turbo C (and most MS-DOS C Xcompilers) provide only a 4K default stack. Not having thoroughly Xtested flex, I can't say that this is enough. The makefile I provided Xto you builds a version without stack checking code. I would suggest Xadding "-N" to CFLAGS, which will include some simple stack overflow Xchecking code. You may wish to include the following lines to main.c: X X #ifdef __TURBOC__ X unsigned _stklen = 16384; /* some reasonably large number */ X #endif X XIn addition, the flags in the makefile build a version with symbols Xfor Turbo Debugger (like -g). You may wan't to leave these flags off X(remove "-v" from CFLAGS and "/v" from LINK) or you may wish to provide Xan "install" target like so: X X BINDIR = {/usr/local/bin | c:\bin} X STRIP = {strip | tdstrip} X X install: flex$(EXE) X $(CP) flex$(EXE) $(BINDIR) X $(STRIP) $(BINDIR)/flex$(EXE) X XRegards, X few X Xfew@quad1.quad.com Xuunet!ccicpg!quad1!few X END_OF_FILE if test 6089 -ne `wc -c <'MISC/Turbo-C.notes'`; then echo shar: \"'MISC/Turbo-C.notes'\" unpacked with wrong size! fi # end of 'MISC/Turbo-C.notes' fi if test -f 'ecs.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ecs.c'\" else echo shar: Extracting \"'ecs.c'\" \(8758 characters\) sed "s/^X//" >'ecs.c' <<'END_OF_FILE' X/* ecs - equivalence class routines */ X X/*- X * Copyright (c) 1990 The Regents of the University of California. X * All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Vern Paxson. X * X * The United States Government has rights in this work pursuant X * to contract no. DE-AC03-76SF00098 between the United States X * Department of Energy and the University of California. X * X * Redistribution and use in source and binary forms are permitted provided X * that: (1) source distributions retain this entire copyright notice and X * comment, and (2) distributions including binaries display the following X * acknowledgement: ``This product includes software developed by the X * University of California, Berkeley and its contributors'' in the X * documentation or other materials provided with the distribution and in X * all advertising materials mentioning features or use of this software. X * Neither the name of the University nor the names of its contributors may X * be used to endorse or promote products derived from this software without X * specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: /usr/fsys/odin/a/vern/flex/RCS/ecs.c,v 2.5 90/06/27 23:48:17 vern Exp $ (LBL)"; X#endif X X#include "flexdef.h" X X/* ccl2ecl - convert character classes to set of equivalence classes X * X * synopsis X * ccl2ecl(); X */ X Xvoid ccl2ecl() 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]; X cclmec = ecgroup[ich]; X X if ( xlation && cclmec < 0 ) X { X /* special hack--if we're doing %t tables then it's X * possible that no representative of this character's X * equivalence class is in the ccl. So waiting till X * we see the representative would be disastrous. Instead, X * we add this character's equivalence class anyway, if it's X * not already present. X */ X int j; X X /* this loop makes this whole process n^2; but we don't X * really care about %t performance anyway X */ X for ( j = 0; j < newlen; ++j ) X if ( ccltbl[cclp + j] == -cclmec ) X break; X X if ( j >= newlen ) X { /* no representative yet, add this one in */ X ccltbl[cclp + newlen] = -cclmec; X ++newlen; X } X } X X else 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 * 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 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/* ecs_from_xlation - associate equivalence class numbers using %t table X * X * synopsis X * numecs = ecs_from_xlation( ecmap ); X * X * Upon return, ecmap will map each character code to its equivalence X * class. The mapping will be positive if the character is the representative X * of its class, negative otherwise. X * X * Returns the number of equivalence classes used. X */ X Xint ecs_from_xlation( ecmap ) Xint ecmap[]; X X { X int i; X int nul_is_alone = false; X int did_default_xlation_class = false; X X if ( xlation[0] != 0 ) X { X /* if NUL shares its translation with other characters, choose one X * of the other characters as the representative for the equivalence X * class. This allows a cheap test later to see whether we can X * do away with NUL's equivalence class. X */ X for ( i = 1; i < csize; ++i ) X if ( xlation[i] == -xlation[0] ) X { X xlation[i] = xlation[0]; X ecmap[0] = -xlation[0]; X break; X } X X if ( i >= csize ) X /* didn't find a companion character--remember this fact */ X nul_is_alone = true; X } X X for ( i = 1; i < csize; ++i ) X if ( xlation[i] == 0 ) X { X if ( did_default_xlation_class ) X ecmap[i] = -num_xlations; X X else X { X /* make an equivalence class for those characters not X * specified in the %t table X */ X ++num_xlations; X ecmap[i] = num_xlations; X did_default_xlation_class = true; X } X } X X else X ecmap[i] = xlation[i]; X X if ( nul_is_alone ) X /* force NUL's equivalence class to be the last one */ X { X ++num_xlations; X ecmap[0] = num_xlations; X X /* there's actually a bug here: if someone is fanatic enough to X * put every character in its own translation class, then right X * now we just promoted NUL's equivalence class to be csize + 1; X * we can handle NUL's class number being == csize (by instead X * putting it in its own table), but we can't handle some *other* X * character having to be put in its own table, too. So in X * this case we bail out. X */ X if ( num_xlations > csize ) X flexfatal( "too many %t classes!" ); X } X X return num_xlations; 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, NUL_mapping; X * mkeccl( ccls, lenccl, fwd, bck, llsiz, NUL_mapping ); 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 * NUL_mapping is the value which NUL (0) should be mapped to. X */ X Xvoid mkeccl( ccls, lenccl, fwd, bck, llsiz, NUL_mapping ) XChar ccls[]; Xint lenccl, fwd[], bck[], llsiz, NUL_mapping; X X { X int cclp, oldec, newec; X int cclm, i, j; X static unsigned char cclflags[CSIZE]; /* initialized to all '\0' */ 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 = ccls[cclp]; X X if ( NUL_mapping && cclm == 0 ) X cclm = NUL_mapping; X 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; ++j ) X { X register int ccl_char; X X if ( NUL_mapping && ccls[j] == 0 ) X ccl_char = NUL_mapping; X else X ccl_char = ccls[j]; X X if ( ccl_char > i ) X break; X X if ( ccl_char == i && ! cclflags[j] ) 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 cclflags[j] = 1; /* set flag so we don't reprocess */ X X /* get next equivalence class member */ X /* continue 2 */ X goto next_pt; X } 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; cclflags[cclp] && cclp < lenccl; ++cclp ) X { X /* reset "doesn't need processing" flag */ X cclflags[cclp] = 0; X } X } 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 Xvoid mkechar( 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 } END_OF_FILE if test 8758 -ne `wc -c <'ecs.c'`; then echo shar: \"'ecs.c'\" unpacked with wrong size! fi # end of 'ecs.c' fi if test -f 'parse.y' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'parse.y'\" else echo shar: Extracting \"'parse.y'\" \(14498 characters\) sed "s/^X//" >'parse.y' <<'END_OF_FILE' X X/* parse.y - parser for flex input */ X X%token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL EOF_OP X X%{ X/*- X * Copyright (c) 1990 The Regents of the University of California. X * All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Vern Paxson. X * X * The United States Government has rights in this work pursuant X * to contract no. DE-AC03-76SF00098 between the United States X * Department of Energy and the University of California. X * X * Redistribution and use in source and binary forms are permitted provided X * that: (1) source distributions retain this entire copyright notice and X * comment, and (2) distributions including binaries display the following X * acknowledgement: ``This product includes software developed by the X * University of California, Berkeley and its contributors'' in the X * documentation or other materials provided with the distribution and in X * all advertising materials mentioning features or use of this software. X * Neither the name of the University nor the names of its contributors may X * be used to endorse or promote products derived from this software without X * specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: /usr/fsys/odin/a/vern/flex/RCS/parse.y,v 2.7 90/06/27 23:48:31 vern Exp $ (LBL)"; X#endif X X#include "flexdef.h" X Xint pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen; Xint trlcontxt, xcluflg, cclsorted, varlength, variable_trail_rule; XChar clower(); X Xstatic int madeany = false; /* whether we've made the '.' character class */ Xint previous_continued_action; /* whether the previous rule's action was '|' */ X X%} X X%% Xgoal : initlex sect1 sect1end sect2 initforrule X { /* add default rule */ X int def_rule; X X pat = cclinit(); X cclnegate( pat ); X X def_rule = mkstate( -pat ); X X finish_rule( def_rule, false, 0, 0 ); X X for ( i = 1; i <= lastsc; ++i ) X scset[i] = mkbranch( scset[i], def_rule ); X X if ( spprdflt ) X fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )", X temp_action_file ); X else X fputs( "ECHO", temp_action_file ); X X fputs( ";\n\tYY_BREAK\n", temp_action_file ); X } 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 = variable_trail_rule = varlength = false; X trailcnt = headcnt = rulelen = 0; X current_state_type = STATE_NORMAL; X previous_continued_action = continued_action; X new_rule(); X } X ; X Xflexrule : scon '^' rule X { X pat = $3; X finish_rule( pat, variable_trail_rule, X headcnt, trailcnt ); X X for ( i = 1; i <= actvp; ++i ) X scbol[actvsc[i]] = X mkbranch( scbol[actvsc[i]], pat ); X X if ( ! bol_needed ) X { X bol_needed = true; X X if ( performance_report ) X pinpoint_message( X "'^' operator results in sub-optimal performance" ); X } X } X X | scon rule X { X pat = $2; X finish_rule( pat, variable_trail_rule, X headcnt, trailcnt ); X X for ( i = 1; i <= actvp; ++i ) X scset[actvsc[i]] = X mkbranch( scset[actvsc[i]], pat ); X } X X | '^' rule X { X pat = $2; X finish_rule( pat, variable_trail_rule, X 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 if ( ! bol_needed ) X { X bol_needed = true; X X if ( performance_report ) X pinpoint_message( X "'^' operator results in sub-optimal performance" ); X } X } X X | rule X { X pat = $1; X finish_rule( pat, variable_trail_rule, X headcnt, trailcnt ); X X for ( i = 1; i <= lastsc; ++i ) X if ( ! scxclu[i] ) X scset[i] = mkbranch( scset[i], pat ); X } X X | scon EOF_OP X { build_eof_action(); } X X | EOF_OP X { X /* this EOF applies to all start conditions X * which don't already have EOF actions X */ X actvp = 0; X X for ( i = 1; i <= lastsc; ++i ) X if ( ! sceof[i] ) X actvsc[++actvp] = i; X X if ( actvp == 0 ) X pinpoint_message( X "warning - all start conditions already have <> rules" ); X X else X build_eof_action(); 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 format_pinpoint_message( X "undeclared start condition %s", nmstr ); X X else X actvsc[++actvp] = scnum; X } X X | NAME X { X if ( (scnum = sclookup( nmstr )) == 0 ) X format_pinpoint_message( X "undeclared start condition %s", nmstr ); X else X actvsc[actvp = 1] = scnum; X } X X | error X { synerr( "bad start condition list" ); } X ; X Xrule : re2 re X { X if ( transchar[lastst[$2]] != SYM_EPSILON ) X /* provide final transition \now/ so it X * will be marked as a trailing context X * state X */ X $2 = link_machines( $2, mkstate( SYM_EPSILON ) ); X X mark_beginning_as_normal( $2 ); X current_state_type = STATE_NORMAL; X X if ( previous_continued_action ) X { X /* we need to treat this as variable trailing X * context so that the backup does not happen X * in the action but before the action switch X * statement. If the backup happens in the X * action, then the rules "falling into" this X * one's action will *also* do the backup, X * erroneously. X */ X if ( ! varlength || headcnt != 0 ) X { X fprintf( stderr, X "%s: warning - trailing context rule at line %d made variable because\n", X program_name, linenum ); X fprintf( stderr, X " of preceding '|' action\n" ); X } X X /* mark as variable */ X varlength = true; X headcnt = 0; X } X X if ( varlength && headcnt == 0 ) X { /* variable trailing context rule */ X /* mark the first part of the rule as the accepting X * "head" part of a trailing context rule X */ X /* by the way, we didn't do this at the beginning X * of this production because back then X * current_state_type was set up for a trail X * rule, and add_accept() can create a new X * state ... X */ X add_accept( $1, num_rules | YY_TRAILING_HEAD_MASK ); X variable_trail_rule = true; X } X X else X trailcnt = rulelen; X X $$ = link_machines( $1, $2 ); X } X X | re2 re '$' X { synerr( "trailing context used twice" ); } X X | re '$' X { X if ( trlcontxt ) X { X synerr( "trailing context used twice" ); X $$ = mkstate( SYM_EPSILON ); X } X X else if ( previous_continued_action ) X { X /* see the comment in the rule for "re2 re" X * above X */ X if ( ! varlength || headcnt != 0 ) X { X fprintf( stderr, X "%s: warning - trailing context rule at line %d made variable because\n", X program_name, linenum ); X fprintf( stderr, X " of preceding '|' action\n" ); X } X X /* mark as variable */ X varlength = true; X headcnt = 0; X } 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( $1, X link_machines( eps, mkstate( '\n' ) ) ); X } X X | re X { X $$ = $1; X X if ( trlcontxt ) X { X if ( varlength && headcnt == 0 ) X /* both head and trail are variable-length */ X variable_trail_rule = true; X else X trailcnt = rulelen; X } X } X ; X X Xre : re '|' series X { X varlength = true; X $$ = mkor( $1, $3 ); X } X X | series X { $$ = $1; } X ; X X Xre2 : re '/' X { X /* this rule is written separately so X * 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 /* we hope the trailing context is fixed-length */ X varlength = false; X else X headcnt = rulelen; X X rulelen = 0; X X current_state_type = STATE_TRAILING_CONTEXT; 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 { X if ( $3 == 0 ) X $$ = mkopt( mkrep( $1, $3, $5 ) ); X else X $$ = mkrep( $1, $3, $5 ); X } 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, 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], true ); X X if ( useecs ) X mkeccl( ccltbl + cclmap[$1], ccllen[$1], X nextecm, ecgroup, csize, 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 ( 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 X/* build_eof_action - build the "<>" action for the active start X * conditions X */ X Xvoid build_eof_action() X X { X register int i; X X for ( i = 1; i <= actvp; ++i ) X { X if ( sceof[actvsc[i]] ) X format_pinpoint_message( X "multiple <> rules for start condition %s", X scname[actvsc[i]] ); X X else X { X sceof[actvsc[i]] = true; X fprintf( temp_action_file, "case YY_STATE_EOF(%s):\n", X scname[actvsc[i]] ); X } X } X X line_directive_out( temp_action_file ); X } X X X/* synerr - report a syntax error */ X Xvoid synerr( str ) Xchar str[]; X X { X syntaxerror = true; X pinpoint_message( str ); X } X X X/* format_pinpoint_message - write out a message formatted with one string, X * pinpointing its location X */ X Xvoid format_pinpoint_message( msg, arg ) Xchar msg[], arg[]; X X { X char errmsg[MAXLINE]; X X (void) sprintf( errmsg, msg, arg ); X pinpoint_message( errmsg ); X } X X X/* pinpoint_message - write out a message, pinpointing its location */ X Xvoid pinpoint_message( str ) Xchar str[]; X X { X fprintf( stderr, "\"%s\", line %d: %s\n", infilename, linenum, str ); X } X X X/* yyerror - eat up an error message from the parser; X * currently, messages are ignore X */ X Xvoid yyerror( msg ) Xchar msg[]; X X { X } END_OF_FILE if test 14498 -ne `wc -c <'parse.y'`; then echo shar: \"'parse.y'\" unpacked with wrong size! fi # end of 'parse.y' fi echo shar: End of archive 9 \(of 10\). cp /dev/null ark9isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 10 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still must unpack the following archives: echo " " ${MISSING} fi exit 0 exit 0 # Just in case...