amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (08/20/90)
Submitted-by: loftus@wpllabs.uucp (William P Loftus) Posting-number: Volume 90, Issue 230 Archive-name: unix/flex-2.3/part03 #!/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 <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 13)." # Contents: flex.skel main.c nfa.c # Wrapped by tadguy@abcfd20 on Sun Aug 19 18:41:42 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'flex.skel' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'flex.skel'\" else echo shar: Extracting \"'flex.skel'\" \(19618 characters\) sed "s/^X//" >'flex.skel' <<'END_OF_FILE' X/* A lexical scanner generated by flex */ X X/* scanner skeleton version: X * $Header: WPL:Generators/flex-2.3/RCS/flex.skel,v 1.2 90/07/15 01:17:26 loftus Exp $ X */ X X#define FLEX_SCANNER X X#include <stdio.h> X X#ifdef __STDC__ X X#ifndef DONT_HAVE_STDLIB_H X#include <stdlib.h> X#else Xvoid *malloc( unsigned ); Xvoid free( void* ); X#endif X X#define YY_USE_PROTOS X#define YY_USE_CONST X#endif X X X/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ X#ifdef c_plusplus X#ifndef __cplusplus X#define __cplusplus X#endif X#endif X X X#ifdef __cplusplus X X#ifndef __STDC__ X#include <stdlib.h> X#endif X X#include <osfcn.h> X X/* use prototypes in function declarations */ X#define YY_USE_PROTOS X X/* the "const" storage-class-modifier is valid */ X#define YY_USE_CONST X X#endif X X X#ifdef __TURBOC__ X#define YY_USE_CONST X#endif X X X#ifndef YY_USE_CONST X#define const X#endif X X X#ifdef YY_USE_PROTOS X#define YY_PROTO(proto) proto X#else X#define YY_PROTO(proto) () X/* there's no standard place to get these definitions */ Xchar *malloc(); Xint free(); Xint read(); X#endif X X X/* amount of stuff to slurp up with each read */ X#ifndef YY_READ_BUF_SIZE X#define YY_READ_BUF_SIZE 8192 X#endif X X/* returned upon end-of-file */ X#define YY_END_TOK 0 X X/* copy whatever the last rule matched to the standard output */ X X/* cast to (char *) is because for 8-bit chars, yytext is (unsigned char *) */ X/* this used to be an fputs(), but since the string might contain NUL's, X * we now use fwrite() X */ X#define ECHO (void) fwrite( (char *) yytext, yyleng, 1, 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), (char *) buf, max_size )) < 0 ) \ X YY_FATAL_ERROR( "read() in flex scanner failed" ); X#define YY_NULL 0 X X/* no semi-colon after return; correct usage is to write "yyterminate();" - X * we don't want an extra ';' after the "return" because that will cause X * some compilers to complain about unreachable statements. X */ X#define yyterminate() return ( YY_NULL ) X X/* report a fatal error */ X X/* The funky do-while is used to turn this macro definition into X * a single C statement (which needs a semi-colon terminator). X * This avoids problems with code like: X * X * if ( something_happens ) X * YY_FATAL_ERROR( "oops, the something happened" ); X * else X * everything_okay(); X * X * Prior to using the do-while the compiler would get upset at the X * "else" because it interpreted the "if" statement as being all X * done when it reached the ';' after the YY_FATAL_ERROR() call. X */ X X#define YY_FATAL_ERROR(msg) \ X do \ X { \ X (void) fputs( msg, stderr ); \ X (void) putc( '\n', stderr ); \ X exit( 1 ); \ X } \ X while ( 0 ) 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 forced on us by the ()-less X * definition of BEGIN X */ X#define BEGIN yy_start = 1 + 2 * X X/* action number for EOF rule of a given start state */ X#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) X X/* special action meaning "start processing a new file" */ X#define YY_NEW_FILE \ X do \ X { \ X yy_init_buffer( yy_current_buffer, yyin ); \ X yy_load_buffer_state(); \ X } \ X while ( 0 ) X X/* default declaration of generated scanner - a define so the user can X * easily add parameters X */ X#define YY_DECL int yylex YY_PROTO(( void )) X X/* code executed at the end of each rule */ X#define YY_BREAK break; X X#define YY_END_OF_BUFFER_CHAR 0 X X#ifndef YY_BUF_SIZE X#define YY_BUF_SIZE (YY_READ_BUF_SIZE * 2) /* size of default input buffer */ X#endif X Xtypedef struct yy_buffer_state *YY_BUFFER_STATE; X X%% section 1 definitions go here X X/* done after the current pattern has been matched and before the X * corresponding action - sets up yytext X */ X#define YY_DO_BEFORE_ACTION \ X yytext = yy_bp; \ X%% code to fiddle yytext and yyleng for yymore() goes here X yy_hold_char = *yy_cp; \ X *yy_cp = '\0'; \ X yy_c_buf_p = yy_cp; X X#define EOB_ACT_CONTINUE_SCAN 0 X#define EOB_ACT_END_OF_FILE 1 X#define EOB_ACT_LAST_MATCH 2 X X/* return all but the first 'n' matched characters back to the input stream */ X#define yyless(n) \ X do \ X { \ X /* undo effects of setting up yytext */ \ X *yy_cp = yy_hold_char; \ X yy_c_buf_p = yy_cp = yy_bp + n; \ X YY_DO_BEFORE_ACTION; /* set up yytext again */ \ X } \ X while ( 0 ) X X#define unput(c) yyunput( c, yytext ) X X Xstruct yy_buffer_state X { X FILE *yy_input_file; X X YY_CHAR *yy_ch_buf; /* input buffer */ X YY_CHAR *yy_buf_pos; /* current position in input buffer */ X X /* size of input buffer in bytes, not including room for EOB characters*/ X int yy_buf_size; X X /* number of characters read into yy_ch_buf, not including EOB characters */ X int yy_n_chars; X X int yy_eof_status; /* whether we've seen an EOF on this buffer */ X#define EOF_NOT_SEEN 0 X /* "pending" happens when the EOF has been seen but there's still X * some text process X */ X#define EOF_PENDING 1 X#define EOF_DONE 2 X }; X Xstatic YY_BUFFER_STATE yy_current_buffer; X X/* we provide macros for accessing buffer states in case in the X * future we want to put the buffer states in a more general X * "scanner state" X */ X#define YY_CURRENT_BUFFER yy_current_buffer X X X/* yy_hold_char holds the character lost when yytext is formed */ Xstatic YY_CHAR yy_hold_char; X Xstatic int yy_n_chars; /* number of characters read into yy_ch_buf */ X X X X#ifndef YY_USER_ACTION X#define YY_USER_ACTION X#endif X X#ifndef YY_USER_INIT X#define YY_USER_INIT X#endif X Xextern YY_CHAR *yytext; Xextern int yyleng; Xextern FILE *yyin, *yyout; X XYY_CHAR *yytext; Xint yyleng; X XFILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; X X%% data tables for the DFA go here X X/* these variables are all declared out here so that section 3 code can X * manipulate them X */ X/* points to current character in buffer */ Xstatic YY_CHAR *yy_c_buf_p = (YY_CHAR *) 0; Xstatic int yy_init = 1; /* whether we need to initialize */ Xstatic int yy_start = 0; /* start state number */ X X/* flag which is used to allow yywrap()'s to do buffer switches X * instead of setting up a fresh yyin. A bit of a hack ... X */ Xstatic int yy_did_buffer_switch_on_eof; X Xstatic yy_state_type yy_get_previous_state YY_PROTO(( void )); Xstatic yy_state_type yy_try_NUL_trans YY_PROTO(( register yy_state_type current_state )); Xstatic int yy_get_next_buffer YY_PROTO(( void )); Xstatic void yyunput YY_PROTO(( YY_CHAR c, register YY_CHAR *buf_ptr )); Xvoid yyrestart YY_PROTO(( FILE *input_file )); Xvoid yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); Xvoid yy_load_buffer_state YY_PROTO(( void )); XYY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); Xvoid yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); Xvoid yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); X X#define yy_new_buffer yy_create_buffer X X#ifdef __cplusplus Xstatic int yyinput YY_PROTO(( void )); X#else Xstatic int input YY_PROTO(( void )); X#endif X XYY_DECL X { X register yy_state_type yy_current_state; X register YY_CHAR *yy_cp, *yy_bp; X register int yy_act; X X%% user's declarations go here X X if ( yy_init ) X { X YY_USER_INIT; X X if ( ! yy_start ) X yy_start = 1; /* first start state */ X X if ( ! yyin ) X yyin = stdin; X X if ( ! yyout ) X yyout = stdout; X X if ( yy_current_buffer ) X yy_init_buffer( yy_current_buffer, yyin ); X else X yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); X X yy_load_buffer_state(); X X yy_init = 0; X } X X while ( 1 ) /* loops until end-of-file is reached */ X { X%% yymore()-related code goes here X yy_cp = yy_c_buf_p; X X /* support of yytext */ X *yy_cp = yy_hold_char; X X /* yy_bp points to the position in yy_ch_buf of the start of the X * current run. X */ X yy_bp = yy_cp; X X%% code to set up and find next match goes here X Xyy_find_action: X%% code to find the action number goes here X X YY_DO_BEFORE_ACTION; X YY_USER_ACTION; X Xdo_action: /* this label is used only to access EOF actions */ X X%% debug code goes here X X switch ( yy_act ) X { X%% actions go here X X case YY_END_OF_BUFFER: X { X /* amount of text matched not including the EOB char */ X int yy_amount_of_matched_text = yy_cp - yytext - 1; X X /* undo the effects of YY_DO_BEFORE_ACTION */ X *yy_cp = yy_hold_char; X X /* note that here we test for yy_c_buf_p "<=" to the position X * of the first EOB in the buffer, since yy_c_buf_p will X * already have been incremented past the NUL character X * (since all states make transitions on EOB to the end- X * of-buffer state). Contrast this with the test in yyinput(). X */ X if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) X /* this was really a NUL */ X { X yy_state_type yy_next_state; X X yy_c_buf_p = yytext + yy_amount_of_matched_text; X X yy_current_state = yy_get_previous_state(); X X /* okay, we're now positioned to make the X * NUL transition. We couldn't have X * yy_get_previous_state() go ahead and do it X * for us because it doesn't know how to deal X * with the possibility of jamming (and we X * don't want to build jamming into it because X * then it will run more slowly) X */ X X yy_next_state = yy_try_NUL_trans( yy_current_state ); X X yy_bp = yytext + YY_MORE_ADJ; X X if ( yy_next_state ) X { X /* consume the NUL */ X yy_cp = ++yy_c_buf_p; X yy_current_state = yy_next_state; X goto yy_match; X } X X else X { X%% code to do backtracking for compressed tables and set up yy_cp goes here X goto yy_find_action; X } X } X X else switch ( yy_get_next_buffer() ) X { X case EOB_ACT_END_OF_FILE: X { X yy_did_buffer_switch_on_eof = 0; X X if ( yywrap() ) X { X /* note: because we've taken care in X * yy_get_next_buffer() to have set up yytext, X * we can now set up yy_c_buf_p so that if some X * total hoser (like flex itself) wants X * to call the scanner after we return the X * YY_NULL, it'll still work - another YY_NULL X * will get returned. X */ X yy_c_buf_p = yytext + YY_MORE_ADJ; X X yy_act = YY_STATE_EOF((yy_start - 1) / 2); X goto do_action; X } X X else X { X if ( ! yy_did_buffer_switch_on_eof ) X YY_NEW_FILE; X } X } X break; X X case EOB_ACT_CONTINUE_SCAN: X yy_c_buf_p = yytext + yy_amount_of_matched_text; X X yy_current_state = yy_get_previous_state(); X X yy_cp = yy_c_buf_p; X yy_bp = yytext + YY_MORE_ADJ; X goto yy_match; X X case EOB_ACT_LAST_MATCH: X yy_c_buf_p = X &yy_current_buffer->yy_ch_buf[yy_n_chars]; X X yy_current_state = yy_get_previous_state(); X X yy_cp = yy_c_buf_p; X yy_bp = yytext + YY_MORE_ADJ; X goto yy_find_action; X } X break; X } X X default: X#ifdef FLEX_DEBUG X printf( "action # %d\n", yy_act ); X#endif X YY_FATAL_ERROR( X "fatal flex scanner internal error--no action found" ); X } X } X } X X X/* yy_get_next_buffer - try to read in a new buffer X * X * synopsis X * int yy_get_next_buffer(); X * X * returns a code representing an action X * EOB_ACT_LAST_MATCH - X * EOB_ACT_CONTINUE_SCAN - continue scanning from current position X * EOB_ACT_END_OF_FILE - end of file X */ X Xstatic int yy_get_next_buffer() X X { X register YY_CHAR *dest = yy_current_buffer->yy_ch_buf; X register YY_CHAR *source = yytext - 1; /* copy prev. char, too */ X register int number_to_move, i; X int ret_val; X X if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) X YY_FATAL_ERROR( X "fatal flex scanner internal error--end of buffer missed" ); X X /* try to read more data */ X X /* first move last chars to start of buffer */ X number_to_move = yy_c_buf_p - yytext; X X for ( i = 0; i < number_to_move; ++i ) X *(dest++) = *(source++); X X if ( yy_current_buffer->yy_eof_status != EOF_NOT_SEEN ) X /* don't do the read, it's not guaranteed to return an EOF, X * just force an EOF X */ X yy_n_chars = 0; X X else X { X int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; X X if ( num_to_read > YY_READ_BUF_SIZE ) X num_to_read = YY_READ_BUF_SIZE; X X else if ( num_to_read <= 0 ) X YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); X X /* read in more data */ X YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), X yy_n_chars, num_to_read ); X } X X if ( yy_n_chars == 0 ) X { X if ( number_to_move == 1 ) X { X ret_val = EOB_ACT_END_OF_FILE; X yy_current_buffer->yy_eof_status = EOF_DONE; X } X X else X { X ret_val = EOB_ACT_LAST_MATCH; X yy_current_buffer->yy_eof_status = EOF_PENDING; X } X } X X else X ret_val = EOB_ACT_CONTINUE_SCAN; X X yy_n_chars += number_to_move; X yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; X yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; X X /* yytext begins at the second character in yy_ch_buf; the first X * character is the one which preceded it before reading in the latest X * buffer; it needs to be kept around in case it's a newline, so X * yy_get_previous_state() will have with '^' rules active X */ X X yytext = &yy_current_buffer->yy_ch_buf[1]; X X return ( ret_val ); X } X X X/* yy_get_previous_state - get the state just before the EOB char was reached X * X * synopsis X * yy_state_type yy_get_previous_state(); X */ X Xstatic yy_state_type yy_get_previous_state() X X { X register yy_state_type yy_current_state; X register YY_CHAR *yy_cp; X X%% code to get the start state into yy_current_state goes here X X for ( yy_cp = yytext + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) X { X%% code to find the next state goes here X } X X return ( yy_current_state ); X } X X X/* yy_try_NUL_trans - try to make a transition on the NUL character X * X * synopsis X * next_state = yy_try_NUL_trans( current_state ); X */ X X#ifdef YY_USE_PROTOS Xstatic yy_state_type yy_try_NUL_trans( register yy_state_type yy_current_state ) X#else Xstatic yy_state_type yy_try_NUL_trans( yy_current_state ) Xregister yy_state_type yy_current_state; X#endif X X { X register int yy_is_jam; X%% code to find the next state, and perhaps do backtracking, goes here X X return ( yy_is_jam ? 0 : yy_current_state ); X } X X X#ifdef YY_USE_PROTOS Xstatic void yyunput( YY_CHAR c, register YY_CHAR *yy_bp ) X#else Xstatic void yyunput( c, yy_bp ) XYY_CHAR c; Xregister YY_CHAR *yy_bp; X#endif X X { X register YY_CHAR *yy_cp = yy_c_buf_p; X X /* undo effects of setting up yytext */ X *yy_cp = yy_hold_char; X X if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) X { /* need to shift things up to make room */ X register int number_to_move = yy_n_chars + 2; /* +2 for EOB chars */ X register YY_CHAR *dest = X &yy_current_buffer->yy_ch_buf[yy_current_buffer->yy_buf_size + 2]; X register YY_CHAR *source = X &yy_current_buffer->yy_ch_buf[number_to_move]; X X while ( source > yy_current_buffer->yy_ch_buf ) X *--dest = *--source; X X yy_cp += dest - source; X yy_bp += dest - source; X yy_n_chars = yy_current_buffer->yy_buf_size; X X if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) X YY_FATAL_ERROR( "flex scanner push-back overflow" ); X } X X if ( yy_cp > yy_bp && yy_cp[-1] == '\n' ) X yy_cp[-2] = '\n'; X X *--yy_cp = c; X X /* note: the formal parameter *must* be called "yy_bp" for this X * macro to now work correctly X */ X YY_DO_BEFORE_ACTION; /* set up yytext again */ X } X X X#ifdef __cplusplus Xstatic int yyinput() X#else Xstatic int input() X#endif X X { X int c; X YY_CHAR *yy_cp = yy_c_buf_p; X X *yy_cp = yy_hold_char; X X if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) X { X /* yy_c_buf_p now points to the character we want to return. X * If this occurs *before* the EOB characters, then it's a X * valid NUL; if not, then we've hit the end of the buffer. X */ X if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) X /* this was really a NUL */ X *yy_c_buf_p = '\0'; X X else X { /* need more input */ X yytext = yy_c_buf_p; X ++yy_c_buf_p; X X switch ( yy_get_next_buffer() ) X { X case EOB_ACT_END_OF_FILE: X { X if ( yywrap() ) X { X yy_c_buf_p = yytext + YY_MORE_ADJ; X return ( EOF ); X } X X YY_NEW_FILE; X X#ifdef __cplusplus X return ( yyinput() ); X#else X return ( input() ); X#endif X } X break; X X case EOB_ACT_CONTINUE_SCAN: X yy_c_buf_p = yytext + YY_MORE_ADJ; X break; X X case EOB_ACT_LAST_MATCH: X#ifdef __cplusplus X YY_FATAL_ERROR( "unexpected last match in yyinput()" ); X#else X YY_FATAL_ERROR( "unexpected last match in input()" ); X#endif X } X } X } X X c = *yy_c_buf_p; X yy_hold_char = *++yy_c_buf_p; X X return ( c ); X } X X X#ifdef YY_USE_PROTOS Xvoid yyrestart( FILE *input_file ) X#else Xvoid yyrestart( input_file ) XFILE *input_file; X#endif X X { X yy_init_buffer( yy_current_buffer, input_file ); X yy_load_buffer_state(); X } X X X#ifdef YY_USE_PROTOS Xvoid yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) X#else Xvoid yy_switch_to_buffer( new_buffer ) XYY_BUFFER_STATE new_buffer; X#endif X X { X if ( yy_current_buffer == new_buffer ) X return; X X if ( yy_current_buffer ) X { X /* flush out information for old buffer */ X *yy_c_buf_p = yy_hold_char; X yy_current_buffer->yy_buf_pos = yy_c_buf_p; X yy_current_buffer->yy_n_chars = yy_n_chars; X } X X yy_current_buffer = new_buffer; X yy_load_buffer_state(); X X /* we don't actually know whether we did this switch during X * EOF (yywrap()) processing, but the only time this flag X * is looked at is after yywrap() is called, so it's safe X * to go ahead and always set it. X */ X yy_did_buffer_switch_on_eof = 1; X } X X X#ifdef YY_USE_PROTOS Xvoid yy_load_buffer_state( void ) X#else Xvoid yy_load_buffer_state() X#endif X X { X yy_n_chars = yy_current_buffer->yy_n_chars; X yytext = yy_c_buf_p = yy_current_buffer->yy_buf_pos; X yyin = yy_current_buffer->yy_input_file; X yy_hold_char = *yy_c_buf_p; X } X X X#ifdef YY_USE_PROTOS XYY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) X#else XYY_BUFFER_STATE yy_create_buffer( file, size ) XFILE *file; Xint size; X#endif X X { X YY_BUFFER_STATE b; X X b = (YY_BUFFER_STATE) malloc( sizeof( struct yy_buffer_state ) ); X X if ( ! b ) X YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); X X b->yy_buf_size = size; X X /* yy_ch_buf has to be 2 characters longer than the size given because X * we need to put in 2 end-of-buffer characters. X */ X b->yy_ch_buf = (YY_CHAR *) malloc( (unsigned) (b->yy_buf_size + 2) ); X X if ( ! b->yy_ch_buf ) X YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); X X yy_init_buffer( b, file ); X X return ( b ); X } X X X#ifdef YY_USE_PROTOS Xvoid yy_delete_buffer( YY_BUFFER_STATE b ) X#else Xvoid yy_delete_buffer( b ) XYY_BUFFER_STATE b; X#endif X X { X if ( b == yy_current_buffer ) X yy_current_buffer = (YY_BUFFER_STATE) 0; X X free( (char *) b->yy_ch_buf ); X free( (char *) b ); X } X X X#ifdef YY_USE_PROTOS Xvoid yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) X#else Xvoid yy_init_buffer( b, file ) XYY_BUFFER_STATE b; XFILE *file; X#endif X X { X b->yy_input_file = file; X X /* we put in the '\n' and start reading from [1] so that an X * initial match-at-newline will be true. X */ X X b->yy_ch_buf[0] = '\n'; X b->yy_n_chars = 1; X X /* we always need two end-of-buffer characters. The first causes X * a transition to the end-of-buffer state. The second causes X * a jam in that state. X */ X b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; X b->yy_ch_buf[2] = YY_END_OF_BUFFER_CHAR; X X b->yy_buf_pos = &b->yy_ch_buf[1]; X X b->yy_eof_status = EOF_NOT_SEEN; X } END_OF_FILE if test 19618 -ne `wc -c <'flex.skel'`; then echo shar: \"'flex.skel'\" unpacked with wrong size! fi # end of 'flex.skel' fi if test -f 'main.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'main.c'\" else echo shar: Extracting \"'main.c'\" \(20291 characters\) sed "s/^X//" >'main.c' <<'END_OF_FILE' X/* flex - tool to generate fast lexical analyzers */ 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 Xchar copyright[] = X"@(#) Copyright (c) 1990 The Regents of the University of California.\n\ X All rights reserved.\n"; X#endif /* not lint */ X X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: WPL:Generators/flex-2.3/RCS/main.c,v 1.2 90/07/15 01:17:37 loftus Exp $ (LBL)"; X#endif X X X#include "flexdef.h" X Xstatic char flex_version[] = "2.3"; X X X/* declare functions that have forward references */ X Xvoid flexinit PROTO((int, char**)); Xvoid readin PROTO(()); Xvoid set_up_initial_allocations PROTO(()); X X X/* these globals are all defined and commented in flexdef.h */ Xint printstats, syntaxerror, eofseen, ddebug, trace, spprdflt; Xint interactive, caseins, useecs, fulltbl, usemecs; Xint fullspd, gen_line_dirs, performance_report, backtrack_report, csize; Xint yymore_used, reject, real_reject, continued_action; Xint yymore_really_used, reject_really_used; Xint datapos, dataline, linenum; XFILE *skelfile = NULL; Xchar *infilename = NULL; Xint onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE]; Xint onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp; Xint current_mns, num_rules, current_max_rules, lastnfa; Xint *firstst, *lastst, *finalst, *transchar, *trans1, *trans2; Xint *accptnum, *assoc_rule, *state_type, *rule_type, *rule_linenum; Xint current_state_type; Xint variable_trailing_context_rules; Xint numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP]; Xint protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE]; Xint numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1]; Xint tecbck[CSIZE + 1]; Xint *xlation = (int *) 0; Xint num_xlations; Xint lastsc, current_max_scs, *scset, *scbol, *scxclu, *sceof, *actvsc; Xchar **scname; Xint current_max_dfa_size, current_max_xpairs; Xint current_max_template_xpairs, current_max_dfas; Xint lastdfa, *nxt, *chk, *tnxt; Xint *base, *def, *nultrans, NUL_ec, tblend, firstfree, **dss, *dfasiz; Xunion dfaacc_union *dfaacc; Xint *accsiz, *dhash, numas; Xint numsnpairs, jambase, jamstate; Xint lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse; Xint current_max_ccl_tbl_size; XChar *ccltbl; Xchar *starttime, *endtime, nmstr[MAXLINE]; Xint sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs; Xint tmpuses, totnst, peakpairs, numuniq, numdup, hshsave; Xint num_backtracking, bol_needed; XFILE *temp_action_file; XFILE *backtrack_file; Xint end_of_buffer_state; Xchar *action_file_name = NULL; Xchar **input_files; Xint num_input_files; Xchar *program_name; X X#ifndef SHORT_FILE_NAMES Xstatic char *outfile = "lex.yy.c"; X#else Xstatic char *outfile = "lexyy.c"; X#endif Xstatic int outfile_created = 0; Xstatic int use_stdout; Xstatic char *skelname = NULL; X X#ifdef AMIGA Xchar * XTmpFileName(template) Xchar *template; X{ X static char Template[256]; X static unsigned short Idx; X X sprintf(Template, "%s-%08lx.TMP", template, (long)FindTask(NULL) + Idx++); X return(Template); X} X#endif X X Xint main( argc, argv ) Xint argc; Xchar **argv; X X { X flexinit( argc, argv ); X X readin(); X X if ( syntaxerror ) X flexend( 1 ); X X if ( yymore_really_used == REALLY_USED ) X yymore_used = true; X else if ( yymore_really_used == REALLY_NOT_USED ) X yymore_used = false; X X if ( reject_really_used == REALLY_USED ) X reject = true; X else if ( reject_really_used == REALLY_NOT_USED ) X reject = false; X X if ( performance_report ) X { X if ( interactive ) X fprintf( stderr, X "-I (interactive) entails a minor performance penalty\n" ); X X if ( yymore_used ) X fprintf( stderr, "yymore() entails a minor performance penalty\n" ); X X if ( reject ) X fprintf( stderr, "REJECT entails a large performance penalty\n" ); X X if ( variable_trailing_context_rules ) X fprintf( stderr, X"Variable trailing context rules entail a large performance penalty\n" ); X } X X if ( reject ) X real_reject = true; X X if ( variable_trailing_context_rules ) X reject = true; X X if ( (fulltbl || fullspd) && reject ) X { X if ( real_reject ) X flexerror( "REJECT cannot be used with -f or -F" ); X else X flexerror( X "variable trailing context rules cannot be used with -f or -F" ); X } X X ntod(); X X /* generate the C state transition tables from the DFA */ X make_tables(); X X /* note, flexend does not return. It exits with its argument as status. */ X X flexend( 0 ); X X /*NOTREACHED*/ X } X X X/* flexend - terminate flex X * X * synopsis X * int status; X * flexend( status ); X * X * status is exit status. X * X * note X * This routine does not return. X */ X Xvoid flexend( status ) Xint status; X X { X int tblsiz; X char *flex_gettime(); X X if ( skelfile != NULL ) X { X if ( ferror( skelfile ) ) X flexfatal( "error occurred when writing skeleton file" ); X X else if ( fclose( skelfile ) ) X flexfatal( "error occurred when closing skeleton file" ); X } X X if ( temp_action_file ) X { X if ( ferror( temp_action_file ) ) X flexfatal( "error occurred when writing temporary action file" ); X X else if ( fclose( temp_action_file ) ) X flexfatal( "error occurred when closing temporary action file" ); X X else if ( unlink( action_file_name ) ) X flexfatal( "error occurred when deleting temporary action file" ); X } X X if ( status != 0 && outfile_created ) X { X if ( ferror( stdout ) ) X flexfatal( "error occurred when writing output file" ); X X else if ( fclose( stdout ) ) X flexfatal( "error occurred when closing output file" ); X X else if ( unlink( outfile ) ) X flexfatal( "error occurred when deleting output file" ); X } X X if ( backtrack_report && backtrack_file ) X { X if ( num_backtracking == 0 ) X fprintf( backtrack_file, "No backtracking.\n" ); X else if ( fullspd || fulltbl ) X fprintf( backtrack_file, X "%d backtracking (non-accepting) states.\n", X num_backtracking ); X else X fprintf( backtrack_file, "Compressed tables always backtrack.\n" ); X X if ( ferror( backtrack_file ) ) X flexfatal( "error occurred when writing backtracking file" ); X X else if ( fclose( backtrack_file ) ) X flexfatal( "error occurred when closing backtracking file" ); X } X X if ( printstats ) X { X endtime = flex_gettime(); X X fprintf( stderr, "%s version %s usage statistics:\n", program_name, X flex_version ); X fprintf( stderr, " started at %s, finished at %s\n", X starttime, endtime ); X X fprintf( stderr, " scanner options: -" ); X X if ( backtrack_report ) X putc( 'b', stderr ); X if ( ddebug ) X putc( 'd', stderr ); X if ( interactive ) X putc( 'I', stderr ); X if ( caseins ) X putc( 'i', stderr ); X if ( ! gen_line_dirs ) X putc( 'L', stderr ); X if ( performance_report ) X putc( 'p', stderr ); X if ( spprdflt ) X putc( 's', stderr ); X if ( use_stdout ) X putc( 't', stderr ); X if ( trace ) X putc( 'T', stderr ); X if ( printstats ) X putc( 'v', stderr ); /* always true! */ X if ( csize == 256 ) X putc( '8', stderr ); X X fprintf( stderr, " -C" ); X X if ( fulltbl ) X putc( 'f', stderr ); X if ( fullspd ) X putc( 'F', stderr ); X if ( useecs ) X putc( 'e', stderr ); X if ( usemecs ) X putc( 'm', stderr ); X X if ( strcmp( skelname, DEFAULT_SKELETON_FILE ) ) X fprintf( stderr, " -S%s", skelname ); X X putc( '\n', stderr ); X X fprintf( stderr, " %d/%d NFA states\n", lastnfa, current_mns ); X fprintf( stderr, " %d/%d DFA states (%d words)\n", lastdfa, X current_max_dfas, totnst ); X fprintf( stderr, X " %d rules\n", num_rules - 1 /* - 1 for def. rule */ ); X X if ( num_backtracking == 0 ) X fprintf( stderr, " No backtracking\n" ); X else if ( fullspd || fulltbl ) X fprintf( stderr, " %d backtracking (non-accepting) states\n", X num_backtracking ); X else X fprintf( stderr, " compressed tables always backtrack\n" ); X X if ( bol_needed ) X fprintf( stderr, " Beginning-of-line patterns used\n" ); X X fprintf( stderr, " %d/%d start conditions\n", lastsc, X current_max_scs ); X fprintf( stderr, " %d epsilon states, %d double epsilon states\n", X numeps, eps2 ); X X if ( lastccl == 0 ) X fprintf( stderr, " no character classes\n" ); X else X fprintf( stderr, X " %d/%d character classes needed %d/%d words of storage, %d reused\n", X lastccl, current_maxccls, X cclmap[lastccl] + ccllen[lastccl], X current_max_ccl_tbl_size, cclreuse ); X X fprintf( stderr, " %d state/nextstate pairs created\n", numsnpairs ); X fprintf( stderr, " %d/%d unique/duplicate transitions\n", X numuniq, numdup ); X X if ( fulltbl ) X { X tblsiz = lastdfa * numecs; X fprintf( stderr, " %d table entries\n", tblsiz ); X } X X else X { X tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend; X X fprintf( stderr, " %d/%d base-def entries created\n", X lastdfa + numtemps, current_max_dfas ); X fprintf( stderr, " %d/%d (peak %d) nxt-chk entries created\n", X tblend, current_max_xpairs, peakpairs ); X fprintf( stderr, X " %d/%d (peak %d) template nxt-chk entries created\n", X numtemps * nummecs, current_max_template_xpairs, X numtemps * numecs ); X fprintf( stderr, " %d empty table entries\n", nummt ); X fprintf( stderr, " %d protos created\n", numprots ); X fprintf( stderr, " %d templates created, %d uses\n", X numtemps, tmpuses ); X } X X if ( useecs ) X { X tblsiz = tblsiz + csize; X fprintf( stderr, " %d/%d equivalence classes created\n", X numecs, csize ); X } X X if ( usemecs ) X { X tblsiz = tblsiz + numecs; X fprintf( stderr, " %d/%d meta-equivalence classes created\n", X nummecs, csize ); X } X X fprintf( stderr, " %d (%d saved) hash collisions, %d DFAs equal\n", X hshcol, hshsave, dfaeql ); X fprintf( stderr, " %d sets of reallocations needed\n", num_reallocs ); X fprintf( stderr, " %d total table entries needed\n", tblsiz ); X } X X#ifndef VMS X exit( status ); X#else X exit( status + 1 ); X#endif X } X X X/* flexinit - initialize flex X * X * synopsis X * int argc; X * char **argv; X * flexinit( argc, argv ); X */ X Xvoid flexinit( argc, argv ) Xint argc; Xchar **argv; X X { X int i, sawcmpflag; X char *arg, *flex_gettime(), *mktemp(); X X printstats = syntaxerror = trace = spprdflt = interactive = caseins = false; X backtrack_report = performance_report = ddebug = fulltbl = fullspd = false; X yymore_used = continued_action = reject = false; X yymore_really_used = reject_really_used = false; X gen_line_dirs = usemecs = useecs = true; X X sawcmpflag = false; X use_stdout = false; X X csize = DEFAULT_CSIZE; X X program_name = argv[0]; X X /* read flags */ X for ( --argc, ++argv; argc ; --argc, ++argv ) X { X if ( argv[0][0] != '-' || argv[0][1] == '\0' ) X break; X X arg = argv[0]; X X for ( i = 1; arg[i] != '\0'; ++i ) X switch ( arg[i] ) X { X case 'b': X backtrack_report = true; X break; X X case 'c': X fprintf( stderr, X "%s: Assuming use of deprecated -c flag is really intended to be -C\n", X program_name ); X X /* fall through */ X X case 'C': X if ( i != 1 ) X flexerror( "-C flag must be given separately" ); X X if ( ! sawcmpflag ) X { X useecs = false; X usemecs = false; X fulltbl = false; X sawcmpflag = true; X } X X for ( ++i; arg[i] != '\0'; ++i ) X switch ( arg[i] ) X { X case 'e': X useecs = true; X break; X X case 'F': X fullspd = true; X break; X X case 'f': X fulltbl = true; X break; X X case 'm': X usemecs = true; X break; X X default: X lerrif( "unknown -C option '%c'", X (int) arg[i] ); X break; X } X X goto get_next_arg; X X case 'd': X ddebug = true; X break; X X case 'f': X useecs = usemecs = false; X fulltbl = true; X break; X X case 'F': X useecs = usemecs = false; X fullspd = true; X break; X X case 'I': X interactive = true; X break; X X case 'i': X caseins = true; X break; X X case 'L': X gen_line_dirs = false; X break; X X case 'n': X /* stupid do-nothing deprecated option */ X break; X X case 'p': X performance_report = true; X break; X X case 'S': X if ( i != 1 ) X flexerror( "-S flag must be given separately" ); X X skelname = arg + i + 1; X goto get_next_arg; X X case 's': X spprdflt = true; X break; X X case 't': X use_stdout = true; X break; X X case 'T': X trace = true; X break; X X case 'v': X printstats = true; X break; X X case '8': X csize = CSIZE; X break; X X default: X lerrif( "unknown flag '%c'", (int) arg[i] ); X break; X } X Xget_next_arg: /* used by -C and -S flags in lieu of a "continue 2" control */ X ; X } X X if ( (fulltbl || fullspd) && usemecs ) X flexerror( "full table and -Cm don't make sense together" ); X X if ( (fulltbl || fullspd) && interactive ) X flexerror( "full table and -I are (currently) incompatible" ); X X if ( fulltbl && fullspd ) X flexerror( "full table and -F are mutually exclusive" ); X X if ( ! skelname ) X { X static char skeleton_name_storage[400]; X X skelname = skeleton_name_storage; X (void) strcpy( skelname, DEFAULT_SKELETON_FILE ); X } X X if ( ! use_stdout ) X { X FILE *prev_stdout = freopen( outfile, "w", stdout ); X X if ( prev_stdout == NULL ) X lerrsf( "could not create %s", outfile ); X X outfile_created = 1; X } X X num_input_files = argc; X input_files = argv; X set_input_file( num_input_files > 0 ? input_files[0] : NULL ); X X if ( backtrack_report ) X { X#ifndef SHORT_FILE_NAMES X backtrack_file = fopen( "lex.backtrack", "w" ); X#else X backtrack_file = fopen( "lex.bck", "w" ); X#endif X X if ( backtrack_file == NULL ) X flexerror( "could not create lex.backtrack" ); X } X X else X backtrack_file = NULL; X X X lastccl = 0; X lastsc = 0; X X /* initialize the statistics */ X starttime = flex_gettime(); X X if ( (skelfile = fopen( skelname, "r" )) == NULL ) X lerrsf( "can't open skeleton file %s", skelname ); X X#ifdef SYS_V X action_file_name = tmpnam( NULL ); X#endif X X if ( action_file_name == NULL ) X { X static char temp_action_file_name[32]; X X#ifdef AMIGA X (void) strcpy( temp_action_file_name, TmpFileName("t:flex") ); X#else X#ifndef SHORT_FILE_NAMES X (void) strcpy( temp_action_file_name, "/tmp/flexXXXXXX" ); X#else X (void) strcpy( temp_action_file_name, "flexXXXXXX.tmp" ); X#endif X (void) mktemp( temp_action_file_name ); X#endif X X action_file_name = temp_action_file_name; X } X X if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL ) X lerrsf( "can't open temporary action file %s", action_file_name ); X X lastdfa = lastnfa = num_rules = numas = numsnpairs = tmpuses = 0; X numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0; X numuniq = numdup = hshsave = eofseen = datapos = dataline = 0; X num_backtracking = onesp = numprots = 0; X variable_trailing_context_rules = bol_needed = false; X X linenum = sectnum = 1; X firstprot = NIL; X X /* used in mkprot() so that the first proto goes in slot 1 X * of the proto queue X */ X lastprot = 1; X X if ( useecs ) X { /* set up doubly-linked equivalence classes */ X /* We loop all the way up to csize, since ecgroup[csize] is the X * position used for NUL characters X */ X ecgroup[1] = NIL; X X for ( i = 2; i <= csize; ++i ) X { X ecgroup[i] = i - 1; X nextecm[i - 1] = i; X } X X nextecm[csize] = NIL; X } X X else X { /* put everything in its own equivalence class */ X for ( i = 1; i <= csize; ++i ) X { X ecgroup[i] = i; X nextecm[i] = BAD_SUBSCRIPT; /* to catch errors */ X } X } X X set_up_initial_allocations(); X } X X X/* readin - read in the rules section of the input file(s) X * X * synopsis X * readin(); X */ X Xvoid readin() X X { X skelout(); X X if ( ddebug ) X puts( "#define FLEX_DEBUG" ); X X if ( csize == 256 ) X puts( "#define YY_CHAR unsigned char" ); X else X puts( "#define YY_CHAR char" ); X X line_directive_out( stdout ); X X if ( yyparse() ) X { X pinpoint_message( "fatal parse error" ); X flexend( 1 ); X } X X if ( xlation ) X { X numecs = ecs_from_xlation( ecgroup ); X useecs = true; X } X X else if ( useecs ) X numecs = cre8ecs( nextecm, ecgroup, csize ); X X else X numecs = csize; X X /* now map the equivalence class for NUL to its expected place */ X ecgroup[0] = ecgroup[csize]; X NUL_ec = abs( ecgroup[0] ); X X if ( useecs ) X ccl2ecl(); X } X X X X/* set_up_initial_allocations - allocate memory for internal tables */ X Xvoid set_up_initial_allocations() X X { X current_mns = INITIAL_MNS; X firstst = allocate_integer_array( current_mns ); X lastst = allocate_integer_array( current_mns ); X finalst = allocate_integer_array( current_mns ); X transchar = allocate_integer_array( current_mns ); X trans1 = allocate_integer_array( current_mns ); X trans2 = allocate_integer_array( current_mns ); X accptnum = allocate_integer_array( current_mns ); X assoc_rule = allocate_integer_array( current_mns ); X state_type = allocate_integer_array( current_mns ); X X current_max_rules = INITIAL_MAX_RULES; X rule_type = allocate_integer_array( current_max_rules ); X rule_linenum = allocate_integer_array( current_max_rules ); X X current_max_scs = INITIAL_MAX_SCS; X scset = allocate_integer_array( current_max_scs ); X scbol = allocate_integer_array( current_max_scs ); X scxclu = allocate_integer_array( current_max_scs ); X sceof = allocate_integer_array( current_max_scs ); X scname = allocate_char_ptr_array( current_max_scs ); X actvsc = allocate_integer_array( current_max_scs ); X X current_maxccls = INITIAL_MAX_CCLS; X cclmap = allocate_integer_array( current_maxccls ); X ccllen = allocate_integer_array( current_maxccls ); X cclng = allocate_integer_array( current_maxccls ); X X current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE; X ccltbl = allocate_character_array( current_max_ccl_tbl_size ); X X current_max_dfa_size = INITIAL_MAX_DFA_SIZE; X X current_max_xpairs = INITIAL_MAX_XPAIRS; X nxt = allocate_integer_array( current_max_xpairs ); X chk = allocate_integer_array( current_max_xpairs ); X X current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS; X tnxt = allocate_integer_array( current_max_template_xpairs ); X X current_max_dfas = INITIAL_MAX_DFAS; X base = allocate_integer_array( current_max_dfas ); X def = allocate_integer_array( current_max_dfas ); X dfasiz = allocate_integer_array( current_max_dfas ); X accsiz = allocate_integer_array( current_max_dfas ); X dhash = allocate_integer_array( current_max_dfas ); X dss = allocate_int_ptr_array( current_max_dfas ); X dfaacc = allocate_dfaacc_union( current_max_dfas ); X X nultrans = (int *) 0; X } END_OF_FILE if test 20291 -ne `wc -c <'main.c'`; then echo shar: \"'main.c'\" unpacked with wrong size! fi # end of 'main.c' fi if test -f 'nfa.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'nfa.c'\" else echo shar: Extracting \"'nfa.c'\" \(17603 characters\) sed "s/^X//" >'nfa.c' <<'END_OF_FILE' X/* nfa - NFA construction 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/nfa.c,v 2.6 90/06/27 23:48:29 vern Exp $ (LBL)"; X#endif X X#include "flexdef.h" X X X/* declare functions that have forward references */ X Xint dupmachine PROTO((int)); Xvoid mkxtion PROTO((int, int)); X X X/* add_accept - add an accepting state to a machine X * X * synopsis X * X * add_accept( mach, accepting_number ); X * X * accepting_number becomes mach's accepting number. X */ X Xvoid add_accept( mach, accepting_number ) Xint mach, accepting_number; X X { X /* hang the accepting number off an epsilon state. if it is associated X * with a state that has a non-epsilon out-transition, then the state X * will accept BEFORE it makes that transition, i.e., one character X * too soon X */ X X if ( transchar[finalst[mach]] == SYM_EPSILON ) X accptnum[finalst[mach]] = accepting_number; X X else X { X int astate = mkstate( SYM_EPSILON ); X accptnum[astate] = accepting_number; X mach = link_machines( mach, astate ); X } X } X X X/* copysingl - make a given number of copies of a singleton machine X * X * synopsis X * X * newsng = copysingl( singl, num ); X * X * newsng - a new singleton composed of num copies of singl X * singl - a singleton machine X * num - the number of copies of singl to be present in newsng X */ X Xint copysingl( singl, num ) Xint singl, num; X X { X int copy, i; X X copy = mkstate( SYM_EPSILON ); X X for ( i = 1; i <= num; ++i ) X copy = link_machines( copy, dupmachine( singl ) ); X X return ( copy ); X } X X X/* dumpnfa - debugging routine to write out an nfa X * X * synopsis X * int state1; X * dumpnfa( state1 ); X */ X Xvoid dumpnfa( state1 ) Xint state1; X X { X int sym, tsp1, tsp2, anum, ns; X X fprintf( stderr, "\n\n********** beginning dump of nfa with start state %d\n", X state1 ); X X /* we probably should loop starting at firstst[state1] and going to X * lastst[state1], but they're not maintained properly when we "or" X * all of the rules together. So we use our knowledge that the machine X * starts at state 1 and ends at lastnfa. X */ X X /* for ( ns = firstst[state1]; ns <= lastst[state1]; ++ns ) */ X for ( ns = 1; ns <= lastnfa; ++ns ) X { X fprintf( stderr, "state # %4d\t", ns ); X X sym = transchar[ns]; X tsp1 = trans1[ns]; X tsp2 = trans2[ns]; X anum = accptnum[ns]; X X fprintf( stderr, "%3d: %4d, %4d", sym, tsp1, tsp2 ); X X if ( anum != NIL ) X fprintf( stderr, " [%d]", anum ); X X fprintf( stderr, "\n" ); X } X X fprintf( stderr, "********** end of dump\n" ); X } X X X/* dupmachine - make a duplicate of a given machine X * X * synopsis X * X * copy = dupmachine( mach ); X * X * copy - holds duplicate of mach X * mach - machine to be duplicated X * X * note that the copy of mach is NOT an exact duplicate; rather, all the X * transition states values are adjusted so that the copy is self-contained, X * as the original should have been. X * X * also note that the original MUST be contiguous, with its low and high X * states accessible by the arrays firstst and lastst X */ X Xint dupmachine( mach ) Xint mach; X X { X int i, init, state_offset; X int state = 0; X int last = lastst[mach]; X X for ( i = firstst[mach]; i <= last; ++i ) X { X state = mkstate( transchar[i] ); X X if ( trans1[i] != NO_TRANSITION ) X { X mkxtion( finalst[state], trans1[i] + state - i ); X X if ( transchar[i] == SYM_EPSILON && trans2[i] != NO_TRANSITION ) X mkxtion( finalst[state], trans2[i] + state - i ); X } X X accptnum[state] = accptnum[i]; X } X X if ( state == 0 ) X flexfatal( "empty machine in dupmachine()" ); X X state_offset = state - i + 1; X X init = mach + state_offset; X firstst[init] = firstst[mach] + state_offset; X finalst[init] = finalst[mach] + state_offset; X lastst[init] = lastst[mach] + state_offset; X X return ( init ); X } X X X/* finish_rule - finish up the processing for a rule X * X * synopsis X * X * finish_rule( mach, variable_trail_rule, headcnt, trailcnt ); X * X * An accepting number is added to the given machine. If variable_trail_rule X * is true then the rule has trailing context and both the head and trail X * are variable size. Otherwise if headcnt or trailcnt is non-zero then X * the machine recognizes a pattern with trailing context and headcnt is X * the number of characters in the matched part of the pattern, or zero X * if the matched part has variable length. trailcnt is the number of X * trailing context characters in the pattern, or zero if the trailing X * context has variable length. X */ X Xvoid finish_rule( mach, variable_trail_rule, headcnt, trailcnt ) Xint mach, variable_trail_rule, headcnt, trailcnt; X X { X add_accept( mach, num_rules ); X X /* we did this in new_rule(), but it often gets the wrong X * number because we do it before we start parsing the current rule X */ X rule_linenum[num_rules] = linenum; X X /* if this is a continued action, then the line-number has X * already been updated, giving us the wrong number X */ X if ( continued_action ) X --rule_linenum[num_rules]; X X fprintf( temp_action_file, "case %d:\n", num_rules ); X X if ( variable_trail_rule ) X { X rule_type[num_rules] = RULE_VARIABLE; X X if ( performance_report ) X fprintf( stderr, "Variable trailing context rule at line %d\n", X rule_linenum[num_rules] ); X X variable_trailing_context_rules = true; X } X X else X { X rule_type[num_rules] = RULE_NORMAL; X X if ( headcnt > 0 || trailcnt > 0 ) X { X /* do trailing context magic to not match the trailing characters */ X char *scanner_cp = "yy_c_buf_p = yy_cp"; X char *scanner_bp = "yy_bp"; X X fprintf( temp_action_file, X "*yy_cp = yy_hold_char; /* undo effects of setting up yytext */\n" ); X X if ( headcnt > 0 ) X fprintf( temp_action_file, "%s = %s + %d;\n", X scanner_cp, scanner_bp, headcnt ); X X else X fprintf( temp_action_file, X "%s -= %d;\n", scanner_cp, trailcnt ); X X fprintf( temp_action_file, X "YY_DO_BEFORE_ACTION; /* set up yytext again */\n" ); X } X } X X line_directive_out( temp_action_file ); X } X X X/* link_machines - connect two machines together X * X * synopsis X * X * new = link_machines( first, last ); X * X * new - a machine constructed by connecting first to last X * first - the machine whose successor is to be last X * last - the machine whose predecessor is to be first X * X * note: this routine concatenates the machine first with the machine X * last to produce a machine new which will pattern-match first first X * and then last, and will fail if either of the sub-patterns fails. X * FIRST is set to new by the operation. last is unmolested. X */ X Xint link_machines( first, last ) Xint first, last; X X { X if ( first == NIL ) X return ( last ); X X else if ( last == NIL ) X return ( first ); X X else X { X mkxtion( finalst[first], last ); X finalst[first] = finalst[last]; X lastst[first] = max( lastst[first], lastst[last] ); X firstst[first] = min( firstst[first], firstst[last] ); X X return ( first ); X } X } X X X/* mark_beginning_as_normal - mark each "beginning" state in a machine X * as being a "normal" (i.e., not trailing context- X * associated) states X * X * synopsis X * X * mark_beginning_as_normal( mach ) X * X * mach - machine to mark X * X * The "beginning" states are the epsilon closure of the first state X */ X Xvoid mark_beginning_as_normal( mach ) Xregister int mach; X X { X switch ( state_type[mach] ) X { X case STATE_NORMAL: X /* oh, we've already visited here */ X return; X X case STATE_TRAILING_CONTEXT: X state_type[mach] = STATE_NORMAL; X X if ( transchar[mach] == SYM_EPSILON ) X { X if ( trans1[mach] != NO_TRANSITION ) X mark_beginning_as_normal( trans1[mach] ); X X if ( trans2[mach] != NO_TRANSITION ) X mark_beginning_as_normal( trans2[mach] ); X } X break; X X default: X flexerror( "bad state type in mark_beginning_as_normal()" ); X break; X } X } X X X/* mkbranch - make a machine that branches to two machines X * X * synopsis X * X * branch = mkbranch( first, second ); X * X * branch - a machine which matches either first's pattern or second's X * first, second - machines whose patterns are to be or'ed (the | operator) X * X * note that first and second are NEITHER destroyed by the operation. Also, X * the resulting machine CANNOT be used with any other "mk" operation except X * more mkbranch's. Compare with mkor() X */ X Xint mkbranch( first, second ) Xint first, second; X X { X int eps; X X if ( first == NO_TRANSITION ) X return ( second ); X X else if ( second == NO_TRANSITION ) X return ( first ); X X eps = mkstate( SYM_EPSILON ); X X mkxtion( eps, first ); X mkxtion( eps, second ); X X return ( eps ); X } X X X/* mkclos - convert a machine into a closure X * X * synopsis X * new = mkclos( state ); X * X * new - a new state which matches the closure of "state" X */ X Xint mkclos( state ) Xint state; X X { X return ( mkopt( mkposcl( state ) ) ); X } X X X/* mkopt - make a machine optional X * X * synopsis X * X * new = mkopt( mach ); X * X * new - a machine which optionally matches whatever mach matched X * mach - the machine to make optional X * X * notes: X * 1. mach must be the last machine created X * 2. mach is destroyed by the call X */ X Xint mkopt( mach ) Xint mach; X X { X int eps; X X if ( ! SUPER_FREE_EPSILON(finalst[mach]) ) X { X eps = mkstate( SYM_EPSILON ); X mach = link_machines( mach, eps ); X } X X /* can't skimp on the following if FREE_EPSILON(mach) is true because X * some state interior to "mach" might point back to the beginning X * for a closure X */ X eps = mkstate( SYM_EPSILON ); X mach = link_machines( eps, mach ); X X mkxtion( mach, finalst[mach] ); X X return ( mach ); X } X X X/* mkor - make a machine that matches either one of two machines X * X * synopsis X * X * new = mkor( first, second ); X * X * new - a machine which matches either first's pattern or second's X * first, second - machines whose patterns are to be or'ed (the | operator) X * X * note that first and second are both destroyed by the operation X * the code is rather convoluted because an attempt is made to minimize X * the number of epsilon states needed X */ X Xint mkor( first, second ) Xint first, second; X X { X int eps, orend; X X if ( first == NIL ) X return ( second ); X X else if ( second == NIL ) X return ( first ); X X else X { X /* see comment in mkopt() about why we can't use the first state X * of "first" or "second" if they satisfy "FREE_EPSILON" X */ X eps = mkstate( SYM_EPSILON ); X X first = link_machines( eps, first ); X X mkxtion( first, second ); X X if ( SUPER_FREE_EPSILON(finalst[first]) && X accptnum[finalst[first]] == NIL ) X { X orend = finalst[first]; X mkxtion( finalst[second], orend ); X } X X else if ( SUPER_FREE_EPSILON(finalst[second]) && X accptnum[finalst[second]] == NIL ) X { X orend = finalst[second]; X mkxtion( finalst[first], orend ); X } X X else X { X eps = mkstate( SYM_EPSILON ); X X first = link_machines( first, eps ); X orend = finalst[first]; X X mkxtion( finalst[second], orend ); X } X } X X finalst[first] = orend; X return ( first ); X } X X X/* mkposcl - convert a machine into a positive closure X * X * synopsis X * new = mkposcl( state ); X * X * new - a machine matching the positive closure of "state" X */ X Xint mkposcl( state ) Xint state; X X { X int eps; X X if ( SUPER_FREE_EPSILON(finalst[state]) ) X { X mkxtion( finalst[state], state ); X return ( state ); X } X X else X { X eps = mkstate( SYM_EPSILON ); X mkxtion( eps, state ); X return ( link_machines( state, eps ) ); X } X } X X X/* mkrep - make a replicated machine X * X * synopsis X * new = mkrep( mach, lb, ub ); X * X * new - a machine that matches whatever "mach" matched from "lb" X * number of times to "ub" number of times X * X * note X * if "ub" is INFINITY then "new" matches "lb" or more occurrences of "mach" X */ X Xint mkrep( mach, lb, ub ) Xint mach, lb, ub; X X { X int base_mach, tail, copy, i; X X base_mach = copysingl( mach, lb - 1 ); X X if ( ub == INFINITY ) X { X copy = dupmachine( mach ); X mach = link_machines( mach, X link_machines( base_mach, mkclos( copy ) ) ); X } X X else X { X tail = mkstate( SYM_EPSILON ); X X for ( i = lb; i < ub; ++i ) X { X copy = dupmachine( mach ); X tail = mkopt( link_machines( copy, tail ) ); X } X X mach = link_machines( mach, link_machines( base_mach, tail ) ); X } X X return ( mach ); X } X X X/* mkstate - create a state with a transition on a given symbol X * X * synopsis X * X * state = mkstate( sym ); X * X * state - a new state matching sym X * sym - the symbol the new state is to have an out-transition on X * X * note that this routine makes new states in ascending order through the X * state array (and increments LASTNFA accordingly). The routine DUPMACHINE X * relies on machines being made in ascending order and that they are X * CONTIGUOUS. Change it and you will have to rewrite DUPMACHINE (kludge X * that it admittedly is) X */ X Xint mkstate( sym ) Xint sym; X X { X if ( ++lastnfa >= current_mns ) X { X if ( (current_mns += MNS_INCREMENT) >= MAXIMUM_MNS ) X lerrif( "input rules are too complicated (>= %d NFA states)", X current_mns ); X X ++num_reallocs; X X firstst = reallocate_integer_array( firstst, current_mns ); X lastst = reallocate_integer_array( lastst, current_mns ); X finalst = reallocate_integer_array( finalst, current_mns ); X transchar = reallocate_integer_array( transchar, current_mns ); X trans1 = reallocate_integer_array( trans1, current_mns ); X trans2 = reallocate_integer_array( trans2, current_mns ); X accptnum = reallocate_integer_array( accptnum, current_mns ); X assoc_rule = reallocate_integer_array( assoc_rule, current_mns ); X state_type = reallocate_integer_array( state_type, current_mns ); X } X X firstst[lastnfa] = lastnfa; X finalst[lastnfa] = lastnfa; X lastst[lastnfa] = lastnfa; X transchar[lastnfa] = sym; X trans1[lastnfa] = NO_TRANSITION; X trans2[lastnfa] = NO_TRANSITION; X accptnum[lastnfa] = NIL; X assoc_rule[lastnfa] = num_rules; X state_type[lastnfa] = current_state_type; X X /* fix up equivalence classes base on this transition. Note that any X * character which has its own transition gets its own equivalence class. X * Thus only characters which are only in character classes have a chance X * at being in the same equivalence class. E.g. "a|b" puts 'a' and 'b' X * into two different equivalence classes. "[ab]" puts them in the same X * equivalence class (barring other differences elsewhere in the input). X */ X X if ( sym < 0 ) X { X /* we don't have to update the equivalence classes since that was X * already done when the ccl was created for the first time X */ X } X X else if ( sym == SYM_EPSILON ) X ++numeps; X X else X { X if ( useecs ) X /* map NUL's to csize */ X mkechar( sym ? sym : csize, nextecm, ecgroup ); X } X X return ( lastnfa ); X } X X X/* mkxtion - make a transition from one state to another X * X * synopsis X * X * mkxtion( statefrom, stateto ); X * X * statefrom - the state from which the transition is to be made X * stateto - the state to which the transition is to be made X */ X Xvoid mkxtion( statefrom, stateto ) Xint statefrom, stateto; X X { X if ( trans1[statefrom] == NO_TRANSITION ) X trans1[statefrom] = stateto; X X else if ( (transchar[statefrom] != SYM_EPSILON) || X (trans2[statefrom] != NO_TRANSITION) ) X flexfatal( "found too many transitions in mkxtion()" ); X X else X { /* second out-transition for an epsilon state */ X ++eps2; X trans2[statefrom] = stateto; X } X } X X/* new_rule - initialize for a new rule X * X * synopsis X * X * new_rule(); X * X * the global num_rules is incremented and the any corresponding dynamic X * arrays (such as rule_type[]) are grown as needed. X */ X Xvoid new_rule() X X { X if ( ++num_rules >= current_max_rules ) X { X ++num_reallocs; X current_max_rules += MAX_RULES_INCREMENT; X rule_type = reallocate_integer_array( rule_type, current_max_rules ); X rule_linenum = X reallocate_integer_array( rule_linenum, current_max_rules ); X } X X if ( num_rules > MAX_RULE ) X lerrif( "too many rules (> %d)!", MAX_RULE ); X X rule_linenum[num_rules] = linenum; X } END_OF_FILE if test 17603 -ne `wc -c <'nfa.c'`; then echo shar: \"'nfa.c'\" unpacked with wrong size! fi # end of 'nfa.c' fi echo shar: End of archive 3 \(of 13\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 13 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>. Mail comments to the moderator at <amiga-request@uunet.uu.net>. Post requests for sources, and general discussion to comp.sys.amiga.