Subject: v14i079: Flex, a lex replacement, Part01/05 Newsgroups: comp.sources.unix Sender: sources Approved: rsalz@uunet.UU.NET Submitted-by: Vern Paxson Posting-number: Volume 14, Issue 79 Archive-name: flex/part01 This is the initial release of flex, a replacement for the lex(1) tool. As the copyright indicates, this distribution can be freely redistributed. Yes, there are some niggling lex features which are not available which seem like they'd be easy to add. They're not, or if they are then the straight-forward implementation of them would slow down the scanner. Unfortunately I am unable to do any further work on flex other than bug fixes, so if there's something you've just gotta have, you'd better be willing to dive into the code. I'll be happy to give (fairly high-level) advice on how to proceed. Flex runs on Sun and 4.3 Unix. For a System V machine, add the #define "SV". Not guaranteed to do the full job, but a step in the right direction. Work is being done on an MS-DOS port. For more details on the installation, see the README. Please send problems and feedback to: vern@lbl-{csam,rtsg}.arpa or ucbvax!lbl-csam.arpa!vern Vern Paxson Real Time Systems Group Bldg. 46A Lawrence Berkeley Laboratory 1 Cyclotron Rd. Berkeley, CA 94720 (415) 486-6411 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'Changes' <<'END_OF_FILE' Changes 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 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 END_OF_FILE if test 861 -ne `wc -c <'Changes'`; then echo shar: \"'Changes'\" unpacked with wrong size! fi # end of 'Changes' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(858 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X Changes 1 X MANIFEST 1 This shipping list X Makefile 1 X README 1 X Timings 1 X ccl.c 1 X dfa.c 2 X ecs.c 1 X fastskeldef.h 1 X flex.1 3 X flex.fastskel 2 X flex.skel 1 X flexdef.h 3 X flexskelcom.h 1 X flexskeldef.h 1 X main.c 2 X misc.c 2 X nfa.c 3 X parse.y 1 X scan.c.dist 4 X scan.l 2 X sym.c 1 X tblcmp.c 5 X yylex.c 1 END_OF_FILE if test 858 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(1264 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# make file for "flex" tool X X# the first time around use "make first_flex" X SKELETON_FILE = \"/usr/local/lib/flex.skel\" XF_SKELETON_FILE = \"/usr/local/lib/flex.fastskel\" SKELFLAGS = -DDEFAULT_SKELETON_FILE=$(SKELETON_FILE) \ X -DFAST_SKELETON_FILE=$(F_SKELETON_FILE) CFLAGS = -O LDFLAGS = 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 flex : $(FLEXOBJS) X cc $(CFLAGS) -o flex $(LDFLAGS) $(FLEXOBJS) X first_flex: X cp scan.c.dist scan.c X make $(MFLAGS) flex X parse.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 scan.c : scan.l X $(FLEX) $(FLEX_FLAGS) scan.l >scan.c X scan.o : scan.c parse.h X main.o : main.c X cc $(CFLAGS) -c $(SKELFLAGS) main.c X flex.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 clean : X rm -f core errs flex *.o parse.c *.lint parse.h X test : X $(FLEX) $(FLEX_FLAGS) scan.l | diff scan.c - END_OF_FILE if test 1264 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(3402 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' This is the initial release of flex, a replacement for the lex(1) tool. As the copyright indicates, this distribution can be freely redistributed. X Some 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 The 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 The files are packaged as a compressed shell archive, which in turn contains seven shell archives. Create a directory where you want flex to 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 to extract them. X] X Either move {flexskelcom.h,flexskeldef.h,fastskeldef.h} into /usr/include or edit {flex.skel,flex.fastskel,flexskeldef.h,fastskeldef.h,scan.c.dist} and wire in the full pathname of where you are going to keep the include files. X Decide where you want to keep {flex.skel,flex.fastskel} (suggestion: X/usr/local/lib) and move it there. Edit "Makefile" and change the definitions of SKELETON_FILE and F_SKELETON_FILE to reflect the full pathnames of {flex.skel,flex.fastskel}. X To make flex for the first time, use: X X make first_flex X which uses a pre-generated copy of the scanner whose source is in flex. X Assuming it builds successfully, you can test it using X X make test X The "diff" should not show any differences. X If you're feeling adventurous, rebuild scan.c using various combinations of FLEX_FLAGS, each time trying "make test" when you're done. To rebuild it, do X X rm scan.c X make FLEX_FLAGS="..." X where "..." is one of: X X -ist -c X -ist -ce X -ist -cm X -ist -cfe X -ist -cFe X and testing using: X X make FLEX_FLAGS="..." test X X XFormat the manual entry using X X nroff -man flex.1 X X Please 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 END_OF_FILE if test 3402 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'Timings' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Timings'\" else echo shar: Extracting \"'Timings'\" \(857 characters\) sed "s/^X//" >'Timings' <<'END_OF_FILE' flex vs. lex timings for a C tokenizer which includes keywords: X Generation 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 Scanner object file sizes: X X lex 41.0K bytes X flex 9.4K X flex -cfe 49.6K X flex -cf 126.5K X Running 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 The timings were made on a Sun 3/60. All times are user + system CPU time, and don't include hashing of identifiers. X Summary: 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. END_OF_FILE if test 857 -ne `wc -c <'Timings'`; then echo shar: \"'Timings'\" unpacked with wrong size! fi # end of 'Timings' fi if test -f 'ccl.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ccl.c'\" else echo shar: Extracting \"'ccl.c'\" \(2257 characters\) sed "s/^X//" >'ccl.c' <<'END_OF_FILE' 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 ccladd( cclp, ch ) int cclp; char 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 int 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 cclnegate( cclp ) int cclp; X X { X cclng[cclp] = 1; X } END_OF_FILE if test 2257 -ne `wc -c <'ccl.c'`; then echo shar: \"'ccl.c'\" unpacked with wrong size! fi # end of 'ccl.c' 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'\" \(4546 characters\) sed "s/^X//" >'ecs.c' <<'END_OF_FILE' 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 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 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 int cre8ecs( fwd, bck, num ) int 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 mkeccl( ccls, lenccl, fwd, bck, llsiz ) char ccls[]; int lenccl, fwd[], bck[], llsiz; X X { X int cclp, oldec, newec; X int cclm, i, j; 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 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 && ccls[j] <= i; ++j ) X if ( ccls[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 ccls[j] = -i; /* set flag so we don't reprocess */ 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; next_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; ccls[cclp] < 0 && cclp < lenccl; ++cclp ) X { X /* reset "doesn't need processing" flag */ X ccls[cclp] = -ccls[cclp]; 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 mkechar( tch, fwd, bck ) int 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 4546 -ne `wc -c <'ecs.c'`; then echo shar: \"'ecs.c'\" unpacked with wrong size! fi # end of 'ecs.c' fi if test -f 'fastskeldef.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fastskeldef.h'\" else echo shar: Extracting \"'fastskeldef.h'\" \(2842 characters\) sed "s/^X//" >'fastskeldef.h' <<'END_OF_FILE' 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 END_OF_FILE if test 2842 -ne `wc -c <'fastskeldef.h'`; then echo shar: \"'fastskeldef.h'\" unpacked with wrong size! fi # end of 'fastskeldef.h' fi if test -f 'flex.skel' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'flex.skel'\" else echo shar: Extracting \"'flex.skel'\" \(6545 characters\) sed "s/^X//" >'flex.skel' <<'END_OF_FILE' 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 */ static int yy_start, yy_b_buf_p, yy_c_buf_p, yy_e_buf_p; static 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 */ static char yy_ch_buf[YY_BUF_SIZE + 1]; static int yy_st_buf[YY_BUF_SIZE]; static char yy_hold_char; char *yytext; static int yyleng; X YY_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 if ( yy_init ) X { X YY_INIT; X yy_start = 1; X yy_init = 0; X } X X goto get_next_token; X do_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 case YY_NEW_FILE: break; /* begin reading from new file */ X case YY_DO_DEFAULT: YY_DEFAULT_ACTION; break; X case YY_END_TOK: return ( YY_END_TOK ); X default: YY_FATAL_ERROR( "fatal flex scanner internal error" ); X } X get_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 { saweof: 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]]; 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 find_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 static int unput( c ) char 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 static 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 ); X } END_OF_FILE if test 6545 -ne `wc -c <'flex.skel'`; then echo shar: \"'flex.skel'\" unpacked with wrong size! fi # end of 'flex.skel' fi if test -f 'flexskelcom.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'flexskelcom.h'\" else echo shar: Extracting \"'flexskelcom.h'\" \(2400 characters\) sed "s/^X//" >'flexskelcom.h' <<'END_OF_FILE' X/* common macro definitions for C/FTL programs generated by flex */ X 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 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; END_OF_FILE if test 2400 -ne `wc -c <'flexskelcom.h'`; then echo shar: \"'flexskelcom.h'\" unpacked with wrong size! fi # end of 'flexskelcom.h' fi if test -f 'flexskeldef.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'flexskeldef.h'\" else echo shar: Extracting \"'flexskeldef.h'\" \(1197 characters\) sed "s/^X//" >'flexskeldef.h' <<'END_OF_FILE' 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 END_OF_FILE if test 1197 -ne `wc -c <'flexskeldef.h'`; then echo shar: \"'flexskeldef.h'\" unpacked with wrong size! fi # end of 'flexskeldef.h' 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'\" \(8861 characters\) sed "s/^X//" >'parse.y' <<'END_OF_FILE' 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 int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen; int trlcontxt, xcluflg, cclsorted, varlength; char clower(); X static int madeany = false; /* whether we've made the '.' character class */ X X%} X X%% goal : initlex sect1 sect1end sect2 X ; X initlex : X { X /* initialize for processing rules */ X X /* create default DFA start condition */ X scinstal( "INITIAL", false ); X } X ; X sect1 : sect1 startconddecl WHITESPACE namelist1 '\n' X | X | error '\n' X { synerr( "unknown error processing section 1" ); } X ; X sect1end : SECTEND X ; X startconddecl : 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 namelist1 : 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 sect2 : sect2 initforrule flexrule '\n' X | X ; X initforrule : X { X /* initialize for a parse of one rule */ X trlcontxt = varlength = false; X trailcnt = headcnt = rulelen = 0; X } X ; X flexrule : 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 scon : '<' namelist2 '>' X ; X namelist2 : 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 eol : '$' 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 re : 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 re2 : 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 series : 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 singleton : 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 fullccl : '[' 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 ccl : 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 string : 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 synerr( str ) char str[]; X X { X syntaxerror = true; X fprintf( stderr, "Syntax error at line %d: %s\n", linenum, str ); X } X X X/* yyerror - eat up an error message from the parser X * X * synopsis X * char msg[]; X * yyerror( msg ); X */ X yyerror( msg ) char msg[]; X X { X } END_OF_FILE if test 8861 -ne `wc -c <'parse.y'`; then echo shar: \"'parse.y'\" unpacked with wrong size! fi # end of 'parse.y' fi if test -f 'sym.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sym.c'\" else echo shar: Extracting \"'sym.c'\" \(6087 characters\) sed "s/^X//" >'sym.c' <<'END_OF_FILE' 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 struct hash_entry *ndtbl[NAME_TABLE_HASH_SIZE]; struct hash_entry *sctbl[START_COND_HASH_SIZE]; struct hash_entry *ccltab[CCL_HASH_SIZE]; X struct 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 int addsym( sym, str_def, int_def, table, table_size ) register char sym[]; char *str_def; int int_def; hash_table table; int 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 cclinstal( ccltxt, cclnum ) char ccltxt[]; int 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 int ccllookup( ccltxt ) char 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 struct hash_entry *findsym( sym, table, table_size ) register char sym[]; hash_table table; int 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 int hashfunct( str, hash_size ) register char str[]; int 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 ndinstal( nd, def ) char 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 char *ndlookup( nd ) char 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 scinstal( str, xcluflg ) char str[]; int 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 int sclookup( str ) char str[]; X X { X return ( findsym( str, sctbl, START_COND_HASH_SIZE )->int_val ); X } END_OF_FILE if test 6087 -ne `wc -c <'sym.c'`; then echo shar: \"'sym.c'\" unpacked with wrong size! fi # end of 'sym.c' fi if test -f 'yylex.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'yylex.c'\" else echo shar: Extracting \"'yylex.c'\" \(3554 characters\) sed "s/^X//" >'yylex.c' <<'END_OF_FILE' 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 int 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 } END_OF_FILE if test 3554 -ne `wc -c <'yylex.c'`; then echo shar: \"'yylex.c'\" unpacked with wrong size! fi # end of 'yylex.c' fi echo shar: End of archive 1 \(of 5\). cp /dev/null ark1isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0