Subject: v19i056: Flex, a fast LEX replacement, Part02/07 Newsgroups: comp.sources.unix Sender: sources Approved: rsalz@uunet.UU.NET Submitted-by: Vern Paxson Posting-number: Volume 19, Issue 56 Archive-name: flex2/part02 #! /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 'flex/flex.skel' <<'END_OF_FILE' X/* A lexical scanner generated by flex */ X X/* scanner skeleton version: X * $Header: flex.skel,v 2.0 89/06/20 15:49:46 vern Locked $ X */ X X#include X X#define FLEX_SCANNER 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#ifndef YY_BUF_SIZE X#define YY_BUF_SIZE (YY_READ_BUF_SIZE * 2) /* size of input buffer */ 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#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#define yyterminate() return ( YY_NULL ) 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/* 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 goto new_file X X/* default declaration of generated scanner - a define so the user can X * easily add parameters X */ X#ifdef __STDC__ X#define YY_DECL int yylex( void ) X#else X#define YY_DECL int yylex() X#endif 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/* 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 yy_hold_char = *yy_cp; \ X *yy_cp = '\0'; \ X yy_c_buf_p = yy_cp; X X/* returns the length of the matched text */ X#define yyleng (yy_cp - yy_bp) X X#define EOB_ACT_RESTART_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 { \ X *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \ X yy_c_buf_p = yy_cp = yy_bp + n; \ X YY_DO_BEFORE_ACTION; /* set up yytext again */ \ X } X X#define unput(c) yyunput( c, yy_bp ) X X#define YY_USER_ACTION X XFILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; Xchar *yytext; X X#ifndef __STDC__ X#define const X#endif X X%% section 1 code and the 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 */ Xstatic char *yy_c_buf_p; /* points to current character in buffer */ Xstatic int yy_init = 1; /* whether we need to initialize */ Xstatic int yy_start = 0; /* start state number */ X X/* true when we've seen an EOF for the current input file */ Xstatic int yy_eof_has_been_seen; X Xstatic int yy_n_chars; /* number of characters read into yy_ch_buf */ X X/* yy_ch_buf has to be 2 characters longer than YY_BUF_SIZE because we need X * to put in 2 end-of-buffer characters (this is explained where it is X * done) at the end of yy_ch_buf X */ Xstatic char yy_ch_buf[YY_BUF_SIZE + 2]; X X/* yy_hold_char holds the character lost when yytext is formed */ Xstatic char yy_hold_char; X Xstatic yy_state_type yy_last_accepting_state; Xstatic char *yy_last_accepting_cpos; X X#ifdef __STDC__ Xstatic yy_state_type yy_get_previous_state( void ); Xstatic int yy_get_next_buffer( void ); Xstatic void yyunput( int c, char *buf_ptr ); Xstatic int input( void ); Xstatic void yyrestart( FILE *input_file ); X#else Xstatic yy_state_type yy_get_previous_state(); Xstatic int yy_get_next_buffer(); Xstatic void yyunput(); Xstatic int input(); Xstatic void yyrestart(); X#endif X XYY_DECL X { X register yy_state_type yy_current_state; X register char *yy_cp, *yy_bp; X register int yy_act; X X%% user's declarations go here X X if ( yy_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 Xnew_file: X /* this is where we enter upon encountering an end-of-file and X * yywrap() indicating that we should continue processing X */ X X /* we put in the '\n' and start reading from [1] so that an X * initial match-at-newline will be true. X */ X X yy_ch_buf[0] = '\n'; X yy_n_chars = 1; X X /* we always need two end-of-buffer characters. The first causes X * a transition to the end-of-buffer state. The second causes X * a jam in that state. X */ X yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; X yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; X X yy_eof_has_been_seen = 0; X X yytext = yy_c_buf_p = &yy_ch_buf[1]; X yy_hold_char = *yy_c_buf_p; X yy_init = 0; X } X X while ( 1 ) /* loops until end-of-file is reached */ X { 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%% yymore()-related code goes here X X%% code to set up and find next match goes here X X /* bogus while loop to let YY_BACK_TRACK, EOB_ACT_LAST_MATCH, X * and EOF actions branch here without introducing an optimizer- X * daunting goto X */ X while ( 1 ) X { X%% code to find the action number goes here X X YY_DO_BEFORE_ACTION; X YY_USER_ACTION; X X#ifdef FLEX_DEBUG X fprintf( stderr, "--accepting rule #%d (\"%s\")\n", X yy_act, yytext ); X#endif X Xdo_action: /* this label is used only to access EOF actions */ X switch ( yy_act ) X { X%% actions go here X X case YY_END_OF_BUFFER: X /* undo the effects of YY_DO_BEFORE_ACTION */ X *yy_cp = yy_hold_char; X X yytext = yy_bp; X X switch ( yy_get_next_buffer() ) X { X case EOB_ACT_END_OF_FILE: X { X if ( yywrap() ) X { X /* note: because we've taken care in X * yy_get_next_buffer() to have set up 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; X X yy_act = YY_STATE_EOF((yy_start - 1) / 2); X goto do_action; X } X X else X YY_NEW_FILE; X } X break; X X case EOB_ACT_RESTART_SCAN: X yy_c_buf_p = yytext; X yy_hold_char = *yy_c_buf_p; X break; X X case EOB_ACT_LAST_MATCH: X yy_c_buf_p = &yy_ch_buf[yy_n_chars]; X X yy_current_state = yy_get_previous_state(); X X yy_cp = yy_c_buf_p; X yy_bp = yytext; X continue; /* go to "YY_DO_BEFORE_ACTION" */ X } X break; X X default: X printf( "action # %d\n", yy_act ); X YY_FATAL_ERROR( "fatal flex scanner internal error" ); X } X X break; /* exit bogus while loop */ X } X } X } X X X/* yy_get_next_buffer - try to read in new buffer X * X * synopsis X * int yy_get_next_buffer(); X * X * returns a code representing an action X * EOB_ACT_LAST_MATCH - X * EOB_ACT_RESTART_SCAN - restart the scanner X * EOB_ACT_END_OF_FILE - end of file X */ X Xstatic int yy_get_next_buffer() X X { X register char *dest = yy_ch_buf; X register 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_ch_buf[yy_n_chars + 1] ) X { X YY_FATAL_ERROR( "NULL in input" ); X /*NOTREACHED*/ X } 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_eof_has_been_seen ) X /* don't do the read, it's not guaranteed to return an EOF, X * just force an EOF X */ X yy_n_chars = 0; X X else X { X int num_to_read = 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 /* read in more data */ X YY_INPUT( (&yy_ch_buf[number_to_move]), yy_n_chars, num_to_read ); X } X X if ( yy_n_chars == 0 ) X { X if ( number_to_move == 1 ) X ret_val = EOB_ACT_END_OF_FILE; X else X ret_val = EOB_ACT_LAST_MATCH; X X yy_eof_has_been_seen = 1; X } X X else X ret_val = EOB_ACT_RESTART_SCAN; X X yy_n_chars += number_to_move; X yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; X yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; X X /* yytext begins at the second character in X * yy_ch_buf; the first character is the one which X * preceded it before reading in the latest buffer; X * it needs to be kept around in case it's a X * newline, so yy_get_previous_state() will have X * with '^' rules active X */ X X yytext = &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 char *yy_cp; X X%% code to get the start state into yy_current_state goes here X X for ( yy_cp = yytext; 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#ifdef __STDC__ Xstatic void yyunput( int c, register char *yy_bp ) X#else Xstatic void yyunput( c, yy_bp ) Xint c; Xregister char *yy_bp; X#endif X X { X register char *yy_cp = yy_c_buf_p; X X *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ X X if ( yy_cp < yy_ch_buf + 2 ) X { /* need to shift things up to make room */ X register int number_to_move = yy_n_chars + 2; /* +2 for EOB chars */ X register char *dest = &yy_ch_buf[YY_BUF_SIZE + 2]; X register char *source = &yy_ch_buf[number_to_move]; X X while ( source > yy_ch_buf ) X *--dest = *--source; X X yy_cp += dest - source; X yy_bp += dest - source; X X if ( yy_cp < 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 YY_DO_BEFORE_ACTION; /* set up yytext again */ X } X X Xstatic int input() X X { X int c; X 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 { /* need more input */ X yytext = yy_c_buf_p; X ++yy_c_buf_p; X X switch ( yy_get_next_buffer() ) X { X /* this code, unfortunately, is somewhat redundant with X * that above X */ X case EOB_ACT_END_OF_FILE: X { X if ( yywrap() ) X { X yy_c_buf_p = yytext; X return ( EOF ); X } X X yy_ch_buf[0] = '\n'; X yy_n_chars = 1; X yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; X yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; X yy_eof_has_been_seen = 0; X yytext = yy_c_buf_p = &yy_ch_buf[1]; X yy_hold_char = *yy_c_buf_p; X X return ( input() ); X } X break; X X case EOB_ACT_RESTART_SCAN: X yy_c_buf_p = yytext; X break; X X case EOB_ACT_LAST_MATCH: X YY_FATAL_ERROR( "unexpected last match in input()" ); X } X } X X c = *yy_c_buf_p; X yy_hold_char = *++yy_c_buf_p; X X return ( c ); X } X X X#ifdef __STDC__ Xstatic void yyrestart( FILE *input_file ) X#else Xstatic void yyrestart( input_file ) XFILE *input_file; X#endif X X { X if ( yyin != stdin ) X fclose( yyin ); X X yyin = input_file; X yy_init = 1; X } END_OF_FILE if test 11297 -ne `wc -c <'flex/flex.skel'`; then echo shar: \"'flex/flex.skel'\" unpacked with wrong size! fi # end of 'flex/flex.skel' fi if test -f 'flex/misc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'flex/misc.c'\" else echo shar: Extracting \"'flex/misc.c'\" \(12468 characters\) sed "s/^X//" >'flex/misc.c' <<'END_OF_FILE' X/* misc - miscellaneous flex routines */ X X/* X * Copyright (c) 1989 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 to X * contract no. DE-AC03-76SF00098 between the United States Department of X * Energy and the University of California. X * X * Redistribution and use in source and binary forms are permitted X * provided that the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley. The name of the X * University may not be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#ifndef lint X Xstatic char copyright[] = X "@(#) Copyright (c) 1989 The Regents of the University of California.\n"; Xstatic char CR_continuation[] = "@(#) All rights reserved.\n"; X Xstatic char rcsid[] = X "@(#) $Header: misc.c,v 2.0 89/06/20 15:50:00 vern Locked $ (LBL)"; X X#endif X X#include X#include "flexdef.h" X Xchar *malloc(), *realloc(); X X X/* action_out - write the actions from the temporary file to lex.yy.c X * X * synopsis X * action_out(); X * X * Copies the action file up to %% (or end-of-file) to lex.yy.c X */ X Xaction_out() X X { X char buf[MAXLINE]; X X while ( fgets( buf, MAXLINE, temp_action_file ) != NULL ) X if ( buf[0] == '%' && buf[1] == '%' ) X break; X else X fputs( buf, stdout ); X } X X X/* allocate_array - allocate memory for an integer array of the given size */ X Xchar *allocate_array( size, element_size ) Xint size, element_size; X X { X register char *mem; X X /* on 16-bit int machines (e.g., 80286) we might be trying to X * allocate more than a signed int can hold, and that won't X * work. Cheap test: X */ X if ( element_size * size <= 0 ) X flexfatal( "request for < 1 byte in allocate_array()" ); X X mem = malloc( (unsigned) (element_size * size) ); X X if ( mem == NULL ) X flexfatal( "memory allocation failed in allocate_array()" ); X X return ( mem ); X } X X X/* all_lower - true if a string is all lower-case X * X * synopsis: X * char *str; X * int all_lower(); X * true/false = all_lower( str ); X */ X Xint all_lower( str ) Xregister char *str; X X { X while ( *str ) X { X if ( ! islower( *str ) ) X return ( 0 ); X ++str; X } X X return ( 1 ); X } X X X/* all_upper - true if a string is all upper-case X * X * synopsis: X * char *str; X * int all_upper(); X * true/false = all_upper( str ); X */ X Xint all_upper( str ) Xregister char *str; X X { X while ( *str ) X { X if ( ! isupper( *str ) ) X return ( 0 ); X ++str; X } X X return ( 1 ); X } X X X/* bubble - bubble sort an integer array in increasing order X * X * synopsis X * int v[n], n; X * bubble( v, n ); X * X * description X * sorts the first n elements of array v and replaces them in X * increasing order. X * X * passed X * v - the array to be sorted X * n - the number of elements of 'v' to be sorted */ X Xbubble( v, n ) Xint v[], n; X X { X register int i, j, k; X X for ( i = n; i > 1; --i ) X for ( j = 1; j < i; ++j ) X if ( v[j] > v[j + 1] ) /* compare */ X { X k = v[j]; /* exchange */ X v[j] = v[j + 1]; X v[j + 1] = k; X } X } X X X/* clower - replace upper-case letter to lower-case X * X * synopsis: X * char clower(), c; X * c = clower( c ); X */ X Xchar clower( c ) Xregister char c; X X { X return ( isupper(c) ? tolower(c) : c ); X } X X X/* copy_string - returns a dynamically allocated copy of a string X * X * synopsis X * char *str, *copy, *copy_string(); X * copy = copy_string( str ); X */ X Xchar *copy_string( str ) Xregister char *str; X X { X register char *c; X char *copy; X X /* find length */ X for ( c = str; *c; ++c ) X ; X X copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) ); X X if ( copy == NULL ) X flexfatal( "dynamic memory failure in copy_string()" ); X X for ( c = copy; (*c++ = *str++); ) X ; X X return ( copy ); X } X X X/* cshell - shell sort a character array in increasing order X * X * synopsis X * X * char v[n]; X * int n; X * cshell( v, n ); X * X * description X * does a shell sort of the first n elements of array v. X * X * passed X * v - array to be sorted X * n - number of elements of v to be sorted X */ Xcshell( v, n ) Xchar v[]; Xint n; X X { X int gap, i, j, jg; X char k; X X for ( gap = n / 2; gap > 0; gap = gap / 2 ) X for ( i = gap; i < n; ++i ) X for ( j = i - gap; j >= 0; j = j - gap ) X { X jg = j + gap; X X if ( v[j] <= v[jg] ) X break; X X k = v[j]; X v[j] = v[jg]; X v[jg] = k; X } X } X X X/* dataend - finish up a block of data declarations X * X * synopsis X * dataend(); X */ Xdataend() X X { X if ( datapos > 0 ) X dataflush(); X X /* add terminator for initialization */ X puts( " } ;\n" ); X X dataline = 0; X } X X X X/* dataflush - flush generated data statements X * X * synopsis X * dataflush(); X */ Xdataflush() X X { X putchar( '\n' ); X X if ( ++dataline >= NUMDATALINES ) X { X /* put out a blank line so that the table is grouped into X * large blocks that enable the user to find elements easily X */ X putchar( '\n' ); X dataline = 0; X } X X /* reset the number of characters written on the current line */ X datapos = 0; X } X X/* flex_gettime - return current time X * X * synopsis X * char *flex_gettime(), *time_str; X * time_str = flex_gettime(); X * X * note X * the routine name has the "flex_" prefix because of name clashes X * with Turbo-C X */ X X/* include sys/types.h to use time_t and make lint happy */ X X#ifndef MS_DOS X#ifndef VMS X#include X#else X#include X#endif X#endif X X#ifdef MS_DOS X#include Xtypedef long time_t; X#endif X Xchar *flex_gettime() X X { X time_t t, time(); X char *result, *ctime(), *copy_string(); X X t = time( (long *) 0 ); X X result = copy_string( ctime( &t ) ); X X /* get rid of trailing newline */ X result[24] = '\0'; X X return ( result ); X } X X X/* lerrif - report an error message formatted with one integer argument X * X * synopsis X * char msg[]; X * int arg; X * lerrif( msg, arg ); X */ X Xlerrif( msg, arg ) Xchar msg[]; Xint arg; X X { X char errmsg[MAXLINE]; X (void) sprintf( errmsg, msg, arg ); X flexerror( errmsg ); X } X X X/* lerrsf - report an error message formatted with one string argument X * X * synopsis X * char msg[], arg[]; X * lerrsf( msg, arg ); X */ X Xlerrsf( msg, arg ) Xchar msg[], arg[]; X X { X char errmsg[MAXLINE]; X X (void) sprintf( errmsg, msg, arg ); X flexerror( errmsg ); X } X X X/* flexerror - report an error message and terminate X * X * synopsis X * char msg[]; X * flexerror( msg ); X */ X Xflexerror( msg ) Xchar msg[]; X X { X fprintf( stderr, "flex: %s\n", msg ); X X flexend( 1 ); X } X X X/* flexfatal - report a fatal error message and terminate X * X * synopsis X * char msg[]; X * flexfatal( msg ); X */ X Xflexfatal( msg ) Xchar msg[]; X X { X fprintf( stderr, "flex: fatal internal error %s\n", msg ); X flexend( 1 ); X } X X X/* line_directive_out - spit out a "# line" statement */ X Xline_directive_out( output_file_name ) XFILE *output_file_name; X X { X if ( infilename && gen_line_dirs ) X fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename ); X } X X X/* mk2data - generate a data statement for a two-dimensional array X * X * synopsis X * int value; X * mk2data( value ); X * X * generates a data statement initializing the current 2-D array to "value" X */ Xmk2data( value ) Xint value; X X { X if ( datapos >= NUMDATAITEMS ) X { X putchar( ',' ); X dataflush(); X } X X if ( datapos == 0 ) X /* indent */ X fputs( " ", stdout ); X X else X putchar( ',' ); X X ++datapos; X X printf( "%5d", value ); X } X X X/* mkdata - generate a data statement X * X * synopsis X * int value; X * mkdata( value ); X * X * generates a data statement initializing the current array element to X * "value" X */ Xmkdata( value ) Xint value; X X { X if ( datapos >= NUMDATAITEMS ) X { X putchar( ',' ); X dataflush(); X } X X if ( datapos == 0 ) X /* indent */ X fputs( " ", stdout ); X X else X putchar( ',' ); X X ++datapos; X X printf( "%5d", value ); X } X X X/* myctoi - return the integer represented by a string of digits X * X * synopsis X * char array[]; X * int val, myctoi(); X * val = myctoi( array ); X * X */ X Xint myctoi( array ) Xchar array[]; X X { X int val = 0; X X (void) sscanf( array, "%d", &val ); X X return ( val ); X } X X X/* myesc - return character corresponding to escape sequence X * X * synopsis X * char array[], c, myesc(); X * c = myesc( array ); X * X */ X Xchar myesc( array ) Xchar array[]; X X { X switch ( array[1] ) X { X case 'a': return ( '\a' ); X case 'b': return ( '\b' ); X case 'f': return ( '\f' ); X case 'n': return ( '\n' ); X case 'r': return ( '\r' ); X case 't': return ( '\t' ); X case 'v': return ( '\v' ); X X case '0': 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 { /* \ */ X char c, esc_char; X register int sptr = 1; X X while ( isdigit(array[sptr]) ) X /* don't increment inside loop control because if X * isdigit() is a macro it will expand it to two X * increments ... X */ X ++sptr; X X c = array[sptr]; X array[sptr] = '\0'; X X esc_char = otoi( array + 1 ); X array[sptr] = c; X X if ( esc_char == '\0' ) X { X synerr( "escape sequence for null not allowed" ); X return ( 1 ); X } X X return ( esc_char ); X } X X default: X return ( array[1] ); X } X } X X X/* otoi - convert an octal digit string to an integer value X * X * synopsis: X * int val, otoi(); X * char str[]; X * val = otoi( str ); X */ X Xint otoi( str ) Xchar str[]; X X { X int result; X X (void) sscanf( str, "%o", &result ); X X return ( result ); X } X X X/* readable_form - return the the human-readable form of a character X * X * synopsis: X * int c; X * char *readable_form(); X * = readable_form( c ); X * X * The returned string is in static storage. X */ X Xchar *readable_form( c ) Xregister int c; X X { X static char rform[10]; X X if ( (c >= 0 && c < 32) || c == 127 ) X { X switch ( c ) X { X case '\n': return ( "\\n" ); X case '\t': return ( "\\t" ); X case '\f': return ( "\\f" ); X case '\r': return ( "\\r" ); X case '\b': return ( "\\b" ); X X default: X sprintf( rform, "\\%.3o", c ); X return ( rform ); X } X } X X else if ( c == ' ' ) X return ( "' '" ); X X else X { X rform[0] = c; X rform[1] = '\0'; X X return ( rform ); X } X } X X X/* reallocate_array - increase the size of a dynamic array */ X Xchar *reallocate_array( array, size, element_size ) Xchar *array; Xint size, element_size; X X { X register char *new_array; X X /* same worry as in allocate_array(): */ X if ( size * element_size <= 0 ) X flexfatal( "attempt to increase array size by less than 1 byte" ); X X new_array = realloc( array, (unsigned) (size * element_size )); X X if ( new_array == NULL ) X flexfatal( "attempt to increase array size failed" ); X X return ( new_array ); X } X X X/* skelout - write out one section of the skeleton file X * X * synopsis X * skelout(); X * X * DESCRIPTION X * Copies from skelfile to stdout until a line beginning with "%%" or X * EOF is found. X */ Xskelout() X X { X char buf[MAXLINE]; X X while ( fgets( buf, MAXLINE, skelfile ) != NULL ) X if ( buf[0] == '%' && buf[1] == '%' ) X break; X else X fputs( buf, stdout ); X } X X X/* transition_struct_out - output a yy_trans_info structure X * X * synopsis X * int element_v, element_n; X * transition_struct_out( element_v, element_n ); X * X * outputs the yy_trans_info structure with the two elements, element_v and X * element_n. Formats the output with spaces and carriage returns. X */ X Xtransition_struct_out( element_v, element_n ) Xint element_v, element_n; X X { X printf( "%7d, %5d,", element_v, element_n ); X X datapos += TRANS_STRUCT_PRINT_LENGTH; X X if ( datapos >= 75 ) X { X putchar( '\n' ); X X if ( ++dataline % 10 == 0 ) X putchar( '\n' ); X X datapos = 0; X } X } END_OF_FILE if test 12468 -ne `wc -c <'flex/misc.c'`; then echo shar: \"'flex/misc.c'\" unpacked with wrong size! fi # end of 'flex/misc.c' fi if test -f 'flex/parse.y' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'flex/parse.y'\" else echo shar: Extracting \"'flex/parse.y'\" \(13366 characters\) sed "s/^X//" >'flex/parse.y' <<'END_OF_FILE' X/* parse.y - parser for flex input */ X X/* X * Copyright (c) 1989 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 to X * contract no. DE-AC03-76SF00098 between the United States Department of X * Energy and the University of California. X * X * Redistribution and use in source and binary forms are permitted X * provided that the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley. The name of the X * University may not be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X%token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL EOF_OP X X%{ X X#include "flexdef.h" X X#ifndef lint X Xstatic char copyright[] = X "@(#) Copyright (c) 1989 The Regents of the University of California.\n"; Xstatic char CR_continuation[] = "@(#) All rights reserved.\n"; X Xstatic char rcsid[] = X "@(#) $Header: parse.y,v 2.1 89/06/20 17:23:54 vern Exp $ (LBL)"; X X#endif X Xint pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen; Xint trlcontxt, xcluflg, cclsorted, varlength, variable_trail_rule; Xchar clower(); X Xstatic int madeany = false; /* whether we've made the '.' character class */ Xint previous_continued_action; /* whether the previous rule's action was '|' */ X X%} X X%% Xgoal : initlex sect1 sect1end sect2 initforrule X { /* add default rule */ X int def_rule; X X pat = cclinit(); X cclnegate( pat ); X X def_rule = mkstate( -pat ); X X finish_rule( def_rule, false, 0, 0 ); X X for ( i = 1; i <= lastsc; ++i ) X scset[i] = mkbranch( scset[i], def_rule ); X X if ( spprdflt ) X fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )", X temp_action_file ); X else X fputs( "ECHO", temp_action_file ); X X fputs( ";\n\tYY_BREAK\n", temp_action_file ); X } X ; X Xinitlex : X { X /* initialize for processing rules */ X X /* create default DFA start condition */ X scinstal( "INITIAL", false ); X } X ; X Xsect1 : sect1 startconddecl WHITESPACE namelist1 '\n' X | X | error '\n' X { synerr( "unknown error processing section 1" ); } X ; X Xsect1end : SECTEND X ; X Xstartconddecl : SCDECL X { X /* these productions are separate from the s1object X * rule because the semantics must be done before X * we parse the remainder of an s1object X */ X X xcluflg = false; X } X X | XSCDECL X { xcluflg = true; } X ; X Xnamelist1 : namelist1 WHITESPACE NAME X { scinstal( nmstr, xcluflg ); } X X | NAME X { scinstal( nmstr, xcluflg ); } X X | error X { synerr( "bad start condition list" ); } X ; X Xsect2 : sect2 initforrule flexrule '\n' X | X ; X Xinitforrule : X { X /* initialize for a parse of one rule */ X trlcontxt = variable_trail_rule = varlength = false; X trailcnt = headcnt = rulelen = 0; X current_state_type = STATE_NORMAL; X previous_continued_action = continued_action; X new_rule(); X } X ; X Xflexrule : scon '^' re eol X { X pat = link_machines( $3, $4 ); X finish_rule( pat, variable_trail_rule, X headcnt, trailcnt ); X X for ( i = 1; i <= actvp; ++i ) X scbol[actvsc[i]] = X mkbranch( scbol[actvsc[i]], pat ); X X if ( ! bol_needed ) X { X bol_needed = true; X X if ( performance_report ) X fprintf( stderr, X "'^' operator results in sub-optimal performance\n" ); X } X } X X | scon re eol X { X pat = link_machines( $2, $3 ); X finish_rule( pat, variable_trail_rule, X headcnt, trailcnt ); X X for ( i = 1; i <= actvp; ++i ) X scset[actvsc[i]] = X mkbranch( scset[actvsc[i]], pat ); X } X X | '^' re eol X { X pat = link_machines( $2, $3 ); X finish_rule( pat, variable_trail_rule, X headcnt, trailcnt ); X X /* add to all non-exclusive start conditions, X * including the default (0) start condition X */ X X for ( i = 1; i <= lastsc; ++i ) X if ( ! scxclu[i] ) X scbol[i] = mkbranch( scbol[i], pat ); X X if ( ! bol_needed ) X { X bol_needed = true; X X if ( performance_report ) X fprintf( stderr, X "'^' operator results in sub-optimal performance\n" ); X } X } X X | re eol X { X pat = link_machines( $1, $2 ); X finish_rule( pat, variable_trail_rule, X headcnt, trailcnt ); X X for ( i = 1; i <= lastsc; ++i ) X if ( ! scxclu[i] ) X scset[i] = mkbranch( scset[i], pat ); X } X X | scon EOF_OP X { build_eof_action(); } X X | EOF_OP X { X /* this EOF applies only to the INITIAL start cond. */ X actvsc[actvp = 1] = 1; X build_eof_action(); X } X X | error X { synerr( "unrecognized rule" ); } X ; X Xscon : '<' namelist2 '>' X ; X Xnamelist2 : namelist2 ',' NAME X { X if ( (scnum = sclookup( nmstr )) == 0 ) X lerrsf( "undeclared start condition %s", nmstr ); X X else X actvsc[++actvp] = scnum; X } X X | NAME X { X if ( (scnum = sclookup( nmstr )) == 0 ) X lerrsf( "undeclared start condition %s", nmstr ); X else X actvsc[actvp = 1] = scnum; X } X X | error X { synerr( "bad start condition list" ); } X ; X Xeol : '$' X { X if ( trlcontxt ) X { X synerr( "trailing context used twice" ); X $$ = mkstate( SYM_EPSILON ); X } X else X { X trlcontxt = true; X X if ( ! varlength ) X headcnt = rulelen; X X ++rulelen; X trailcnt = 1; X X eps = mkstate( SYM_EPSILON ); X $$ = link_machines( eps, mkstate( '\n' ) ); X } X } X X | X { X $$ = mkstate( SYM_EPSILON ); X X if ( trlcontxt ) X { X if ( varlength && headcnt == 0 ) X /* both head and trail are variable-length */ X variable_trail_rule = true; X else X trailcnt = rulelen; X } X } X ; X Xre : re '|' series X { X varlength = true; X X $$ = mkor( $1, $3 ); X } X X | re2 series X { X if ( transchar[lastst[$2]] != SYM_EPSILON ) X /* provide final transition \now/ so it X * will be marked as a trailing context X * state X */ X $2 = link_machines( $2, mkstate( SYM_EPSILON ) ); X X mark_beginning_as_normal( $2 ); X current_state_type = STATE_NORMAL; X X if ( previous_continued_action ) X { X /* we need to treat this as variable trailing X * context so that the backup does not happen X * in the action but before the action switch X * statement. If the backup happens in the X * action, then the rules "falling into" this X * one's action will *also* do the backup, X * erroneously. X */ X if ( ! varlength || headcnt != 0 ) X { X fprintf( stderr, X "flex: warning - trailing context rule at line %d made variable because\n", X linenum ); X fprintf( stderr, X " of preceding '|' action\n" ); X } X X /* mark as variable */ X varlength = true; X headcnt = 0; X } X X if ( varlength && headcnt == 0 ) X { /* variable trailing context rule */ X /* mark the first part of the rule as the accepting X * "head" part of a trailing context rule X */ X /* by the way, we didn't do this at the beginning X * of this production because back then X * current_state_type was set up for a trail X * rule, and add_accept() can create a new X * state ... X */ X add_accept( $1, num_rules | YY_TRAILING_HEAD_MASK ); X } X X $$ = link_machines( $1, $2 ); X } X X | series X { $$ = $1; } X ; X X Xre2 : re '/' X { X /* this rule is separate from the others for "re" so X * that the reduction will occur before the trailing X * series is parsed X */ X X if ( trlcontxt ) X synerr( "trailing context used twice" ); X else X trlcontxt = true; X X if ( varlength ) X /* we hope the trailing context is fixed-length */ X varlength = false; X else X headcnt = rulelen; X X rulelen = 0; X X current_state_type = STATE_TRAILING_CONTEXT; X $$ = $1; X } X ; X Xseries : series singleton X { X /* this is where concatenation of adjacent patterns X * gets done X */ X $$ = link_machines( $1, $2 ); X } X X | singleton X { $$ = $1; } X ; X Xsingleton : singleton '*' X { X varlength = true; X X $$ = mkclos( $1 ); X } X X | singleton '+' X { X varlength = true; X X $$ = mkposcl( $1 ); X } X X | singleton '?' X { X varlength = true; X X $$ = mkopt( $1 ); X } X X | singleton '{' NUMBER ',' NUMBER '}' X { X varlength = true; X X if ( $3 > $5 || $3 < 0 ) X { X synerr( "bad iteration values" ); X $$ = $1; X } X else X { X if ( $3 == 0 ) X $$ = mkopt( mkrep( $1, $3, $5 ) ); X else X $$ = mkrep( $1, $3, $5 ); X } X } X X | singleton '{' NUMBER ',' '}' X { X varlength = true; X X if ( $3 <= 0 ) X { X synerr( "iteration value must be positive" ); X $$ = $1; X } X X else X $$ = mkrep( $1, $3, INFINITY ); X } X X | singleton '{' NUMBER '}' X { X /* the singleton could be something like "(foo)", X * in which case we have no idea what its length X * is, so we punt here. X */ X varlength = true; X X if ( $3 <= 0 ) X { X synerr( "iteration value must be positive" ); X $$ = $1; X } X X else X $$ = link_machines( $1, copysingl( $1, $3 - 1 ) ); X } X X | '.' X { X if ( ! madeany ) X { X /* create the '.' character class */ X anyccl = cclinit(); X ccladd( anyccl, '\n' ); X cclnegate( anyccl ); X X if ( useecs ) X mkeccl( ccltbl + cclmap[anyccl], X ccllen[anyccl], nextecm, X ecgroup, CSIZE ); X X madeany = true; X } X X ++rulelen; X X $$ = mkstate( -anyccl ); X } X X | fullccl X { X if ( ! cclsorted ) X /* sort characters for fast searching. We use a X * shell sort since this list could be large. X */ X cshell( ccltbl + cclmap[$1], ccllen[$1] ); X X if ( useecs ) X mkeccl( ccltbl + cclmap[$1], ccllen[$1], X nextecm, ecgroup, CSIZE ); X X ++rulelen; X X $$ = mkstate( -$1 ); X } X X | PREVCCL X { X ++rulelen; X X $$ = mkstate( -$1 ); X } X X | '"' string '"' X { $$ = $2; } X X | '(' re ')' X { $$ = $2; } X X | CHAR X { X ++rulelen; X X if ( $1 == '\0' ) X synerr( "null in rule" ); X X if ( caseins && $1 >= 'A' && $1 <= 'Z' ) X $1 = clower( $1 ); X X $$ = mkstate( $1 ); X } X ; X Xfullccl : '[' ccl ']' X { $$ = $2; } X X | '[' '^' ccl ']' X { X /* *Sigh* - to be compatible Unix lex, negated ccls X * match newlines X */ X#ifdef NOTDEF X ccladd( $3, '\n' ); /* negated ccls don't match '\n' */ X cclsorted = false; /* because we added the newline */ X#endif X cclnegate( $3 ); X $$ = $3; X } X ; X Xccl : ccl CHAR '-' CHAR X { X if ( $2 > $4 ) X synerr( "negative range in character class" ); X X else X { X if ( caseins ) X { X if ( $2 >= 'A' && $2 <= 'Z' ) X $2 = clower( $2 ); X if ( $4 >= 'A' && $4 <= 'Z' ) X $4 = clower( $4 ); X } X X for ( i = $2; i <= $4; ++i ) X ccladd( $1, i ); X X /* keep track if this ccl is staying in alphabetical X * order X */ X cclsorted = cclsorted && ($2 > lastchar); X lastchar = $4; X } X X $$ = $1; X } X X | ccl CHAR X { X if ( caseins ) X if ( $2 >= 'A' && $2 <= 'Z' ) X $2 = clower( $2 ); X X ccladd( $1, $2 ); X cclsorted = cclsorted && ($2 > lastchar); X lastchar = $2; X $$ = $1; X } X X | X { X cclsorted = true; X lastchar = 0; X $$ = cclinit(); X } X ; X Xstring : string CHAR X { X if ( caseins ) X if ( $2 >= 'A' && $2 <= 'Z' ) X $2 = clower( $2 ); X X ++rulelen; X X $$ = link_machines( $1, mkstate( $2 ) ); X } X X | X { $$ = mkstate( SYM_EPSILON ); } X ; X X%% X X X/* build_eof_action - build the "<>" action for the active start X * conditions X */ X Xbuild_eof_action() X X { X register int i; X X for ( i = 1; i <= actvp; ++i ) X { X if ( sceof[actvsc[i]] ) X lerrsf( "multiple <> rules for start condition %s", X scname[actvsc[i]] ); X X else X { X sceof[actvsc[i]] = true; X fprintf( temp_action_file, "case YY_STATE_EOF(%s):\n", X scname[actvsc[i]] ); X } X } X X line_directive_out( temp_action_file ); X } X X X/* synerr - report a syntax error X * X * synopsis X * char str[]; X * synerr( str ); X */ X Xsynerr( str ) Xchar 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 Xyyerror( msg ) Xchar msg[]; X X { X } END_OF_FILE if test 13366 -ne `wc -c <'flex/parse.y'`; then echo shar: \"'flex/parse.y'\" unpacked with wrong size! fi # end of 'flex/parse.y' fi echo shar: End of archive 2 \(of 7\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 6 7 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 7 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