/* @(#)request.l	1.7	2/10/93 */
/*******************************************************************************

This code was written and designed by 
Andrew Gene HALL of I.N. Services Pty. Ltd., Scarborough WA, Australia,
for the 
University of Western Australia, Crawley WA, Australia.

*******************************************************************************/
/* Lex Definitions for the sb Request Language */

%{

/* Global Definitions */
#include <ctype.h>

#ifdef FLEX_SCANNER
/* problem with GNUC redefining size_t etc */
/* these definitions are pinched directly from /usr/include/string.h */
extern char *	strcat(/* char *s1, const char *s2 */);
extern char *   strncat(/* char *s1, const char *s2, size_t n */);
extern char *	strchr(/* const char *s, int c */);
#ifndef	_POSIX_SOURCE
extern char *	strdup(/* char *s1 */);
#endif
extern size_t	strlen(/* const char *s */);
#else
#include <string.h>
#endif

/* Local Definitions */

#define fileno(p) ((p)->_file) /* CHANGE 11/3 */

/* redefine yywrap */
#ifdef yywrap
#undef yywrap
#endif
#define yywrap	request_wrap
#define yy_init_buffer		request_init_buffer
#define yyin			request_in
#define yy_switch_to_buffer	request_switch_to_buffer
#define yyout			request_out
#define yy_delete_buffer	request_delete_buffer
#define yy_create_buffer	request_create_buffer
#define yyrestart		request_restart
#define yy_load_buffer_state	request_load_buffer_state

extern int	yywrap();

/* redefine yylex */
#ifdef yylex
#undef yylex
#endif
#define yylex request_scanner

extern char * 	tmp_string;
%}

a		[aA]
b		[bB]
c		[cC]
d		[dD]
e		[eE]
f		[fF]
g		[gG]
i		[iI]
k		[kK]
l		[lL]
m		[mM]
n		[nN]
o		[oO]
p		[pP]
r		[rR]
s		[sS]
t		[tT]
u		[uU]
v		[vV]
w		[wW]
x		[xX]
Dollar		\$
Assume_True_	{a}{s}{s}{u}{m}{e}_{t}{r}{u}{e}_
Data_		{d}{a}{t}{a}_
Endif_		{e}{n}{d}{i}{f}_
Endscope_	{e}{n}{d}{s}{c}{o}{p}{e}_
Else_		{e}{l}{s}{e}_
Global_		{g}{l}{o}{b}{a}{l}_
If_		{i}{f}_
Reg_Exp_	{r}{e}{g}_{e}{x}{p}_
Save_		{s}{a}{v}{e}_
Scope_Data_Item_	{s}{c}{o}{p}{e}_{d}{a}{t}{a}_{i}{t}{e}{m}_
Scope_Loop_Packet_	{s}{c}{o}{p}{e}_{l}{o}{o}{p}_{p}{a}{c}{k}{e}{t}_
Scope_Loop_Structure_	{s}{c}{o}{p}{e}_{l}{o}{o}{p}_{s}{t}{r}{u}{c}{t}{u}{r}{e}_
Scope_Save_Frame_	{s}{c}{o}{p}{e}_{s}{a}{v}{e}_{f}{r}{a}{m}{e}_
Scope_Data_Block_	{s}{c}{o}{p}{e}_{d}{a}{t}{a}_{b}{l}{o}{c}{k}_
Scope_File_		{s}{c}{o}{p}{e}_{f}{i}{l}{e}_
Unknown_	{u}{n}{k}{n}{o}{w}{n}_
Union		[/|]
Intersection	&
Complement	!
Equal_Strings	~=
Not_Equal_Strings	~!=
Sub_String		\?=
Not_Sub_String		\?!=
ASCII_Less		\~\<
ASCII_Less_Or_Equal	\~\<\=
ASCII_Greater		\~\>
ASCII_Greater_Or_Equal	\~\>\=
Real_Equal		=
Real_Not_Equal		!=
Real_Less		\<
Real_Less_Or_Equal	\<\=
Real_Greater		>
Real_Greater_Or_Equal	>=
Open_Round_Bracket	\(
Close_Round_Bracket	\)
Open_Curley_Bracket	{
Close_Curley_Bracket	}
Char		[^\n]
Blank		[\n \t]
NonBlank	[^\n \t]
NonDQuote	[^\n"]
NonSQuote	[^\n']
NotUnderscore	[^\n \t_]
Space	        [\t ]
Spaces          [\t ]*
Start_RE	\/
End_RE		\/
Comment		#.*
EndOfLine	{Spaces}({Comment})?\n

%START RE RE_Delim
%a 4000
%o 6000

/* Lex Rules fo a STAR File */
%%
{Data_}{NonBlank}+	|
{Global_}		|
{Save_}{NonBlank}+	|
_{NonBlank}+		{
			DEBUG_MSG("REQUEST_STRING"); 
			DEBUG_MSG(yytext);
			/* save input */
			request_string = strdup( yytext );
			/* return token */
			last_request_token = yytext;
			return( REQUEST_STRING );
                        }

{Assume_True_}		{
			DEBUG_MSG("ASSUME_TRUE_"); 
			last_request_token = yytext;
			return( ASSUME_TRUE_ );
			}

{Endif_}		{
			DEBUG_MSG("ENDIF_"); 
			last_request_token = yytext;
			return( ENDIF_ );
			}

{Unknown_}		{
			DEBUG_MSG("UNKNOWN_"); 
			last_request_token = yytext;
			return( UNKNOWN_ );
			}

{Else_}			{
			DEBUG_MSG("ELSE_"); 
			last_request_token = yytext;
			return( ELSE_ );
			}

{If_}			{
			DEBUG_MSG("IF_"); 
			last_request_token = yytext;
			return( IF_ );
			}

{Reg_Exp_}		{
			DEBUG_MSG("REG_EXP_"); 
			BEGIN RE_Delim;
			last_request_token = yytext;
			return( REG_EXP_ );
			}

{Scope_Data_Item_}	{
			DEBUG_MSG("SCOPE_DATA_ITEM_");
			last_request_token = yytext;
			return( SCOPE_DATA_ITEM_ );
			}

{Scope_Loop_Packet_}	{
			DEBUG_MSG("SCOPE_LOOP_PACKET_");
			last_request_token = yytext;
			return( SCOPE_LOOP_PACKET_ );
			}

{Scope_Loop_Structure_}	{
			DEBUG_MSG("SCOPE_LOOP_STRUCTURE_");
			last_request_token = yytext;
			return( SCOPE_LOOP_STRUCTURE_ );
			}

{Scope_Save_Frame_}	{
			DEBUG_MSG("SCOPE_SAVE_FRAME_");
			last_request_token = yytext;
			return( SCOPE_SAVE_FRAME_ );
			}

{Scope_Data_Block_}	{
			DEBUG_MSG("SCOPE_DATA_BLOCK_");
			last_request_token = yytext;
			return( SCOPE_DATA_BLOCK_ );
			}

{Scope_File_}		{
			DEBUG_MSG("SCOPE_FILE_");
			last_request_token = yytext;
			return( SCOPE_FILE_ );
			}

{Endscope_}		{
			DEBUG_MSG("ENDSCOPE_");
			last_request_token = yytext;
			return( ENDSCOPE_ );
			}


<RE_Delim>{Start_RE}	{
			BEGIN RE;
			}

<RE_Delim>{End_RE}	{
			BEGIN 0;
			}

<RE>{NonBlank}+		{
			/* a regular experession */
			DEBUG_MSG("REQUEST_STRING"); 
			DEBUG_MSG(yytext);
			/* save input */
			request_string = strdup( yytext );
			/* return token */
			last_request_token = yytext;
			return( REQUEST_STRING );
			}

{Union}			{
			DEBUG_MSG("UNION_");
			last_request_token = yytext;
			return( UNION_ );
			}

{Intersection}		{
			DEBUG_MSG("INTERSECTION_");
			last_request_token = yytext;
			return( INTERSECTION_ );
			}

{Complement}		{
			DEBUG_MSG("COMPLEMENT_");
			last_request_token = yytext;
			return( COMPLEMENT_ );
			}

{Equal_Strings}		{
			DEBUG_MSG("EQUAL_STRINGS_");
			last_request_token = yytext;
			return( EQUAL_STRINGS_ );
			}

{Not_Equal_Strings}	{
			DEBUG_MSG("NOT_EQUAL_STRINGS_");
			last_request_token = yytext;
			return( NOT_EQUAL_STRINGS_ );
			}

{Sub_String}		{
			DEBUG_MSG("SUB_STRING_");
			last_request_token = yytext;
			return( SUB_STRING_ );
			}

{Not_Sub_String}	{
			DEBUG_MSG("NOT_SUB_STRING_");
			last_request_token = yytext;
			return( NOT_SUB_STRING_ );
			}

{ASCII_Less}		{
			DEBUG_MSG("ASCII_LESS_");
			last_request_token = yytext;
			return( ASCII_LESS_ );
			}

{ASCII_Less_Or_Equal}	{
			DEBUG_MSG("ASCII_LESS_OR_EQUAL_");
			last_request_token = yytext;
			return( ASCII_LESS_OR_EQUAL_ );
			}

{ASCII_Greater}		{
			DEBUG_MSG("ASCII_GREATER_");
			last_request_token = yytext;
			return( ASCII_GREATER_ );
			}

{ASCII_Greater_Or_Equal}	{
			DEBUG_MSG("ASCII_GREATER_OR_EQUAL_");
			last_request_token = yytext;
			return( ASCII_GREATER_OR_EQUAL_ );
			}

{Real_Equal}	{
			DEBUG_MSG("REAL_EQUAL_");
			last_request_token = yytext;
			return( REAL_EQUAL_ );
			}

{Real_Not_Equal}	{
			DEBUG_MSG("REAL_NOT_EQUAL_");
			last_request_token = yytext;
			return( REAL_NOT_EQUAL_ );
			}

{Real_Less}	{
			DEBUG_MSG("REAL_LESS_");
			last_request_token = yytext;
			return( REAL_LESS_ );
			}

{Real_Less_Or_Equal}	{
			DEBUG_MSG("REAL_LESS_OR_EQUAL_");
			last_request_token = yytext;
			return( REAL_LESS_OR_EQUAL_ );
			}

{Real_Greater}	{
			DEBUG_MSG("REAL_GREATER_");
			last_request_token = yytext;
			return( REAL_GREATER_ );
			}

{Real_Greater_Or_Equal}	{
			DEBUG_MSG("REAL_GREATER_OR_EQUAL_");
			last_request_token = yytext;
			return( REAL_GREATER_OR_EQUAL_ );
			}

{Open_Round_Bracket}	{
			DEBUG_MSG("OPEN_ROUND_BRACKET");
			last_request_token = yytext;
			return( OPEN_ROUND_BRACKET );
			}

{Close_Round_Bracket}	{
			DEBUG_MSG("CLOSE_ROUND_BRACKET");
			last_request_token = yytext;
			return( CLOSE_ROUND_BRACKET );
			}

\'.*\'{Blank}		{
			/* get the longest '.....'blank in the current line */

			char *p;

			p = yytext;
			/* step over first quote */
			p++;
			/* scan to '?
			 * (? == null) or (? == space) => end of string, stop
			 */
			DEBUG_MSG("searching for \' in");
			DEBUG_MSG(p);
			while ( p = strchr( p, '\''))
			   if (isspace( *(++p))) {
			      /* (? == space) => push back rest of the input,
			       *                 S_Q_T_S */
                              /* this is to avoid side effects in the macro */
                              int	i = yyleng - strlen(p);
			      yyless( i ); 
                              p = &yytext[yyleng];
                           }
			   else /* keep searching */
			      DEBUG_MSG(p);
                        if( current_di = (Data_Item *)malloc(sizeof(Data_Item)))
                        {
                           current_di->tag = SINGLE_QUOTED_TEXT_STRING_DI;
			   /* build a new string without the bounding quotes */
                           if( tmp_string = (char *)malloc((strlen(yytext) -2 +1) * sizeof(char)) ) {
                             tmp_string[0] = '\0';
                             tmp_string = strncat( tmp_string, yytext + 1, strlen(yytext +1) -1);
                           } else
                             ERROR_MSG("star_scanner: Out of memory.");
			   DEBUG_MSG("star_scanner: SINGLE_QUOTED_TEXT_STRING =");
			   DEBUG_MSG( tmp_string );
			   current_di->value = tmp_string;
                           tmp_string = NULL;
                        } else
                            ERROR_MSG("star_scanner: Out of memory.");
			last_request_token = yytext;
                        return( SINGLE_QUOTED_TEXT_STRING );
                        }

\".*\"{Blank}		{
			/* get the longest "....."blank in the current line */

			char *p;

			p = yytext;
			/* step over first quote */
			p++;
			/* scan to '?
			 * (? == null) or (? == space) => end of string, stop
			 */
			DEBUG_MSG("searching for \" in");
			DEBUG_MSG(p);
			while ( p = strchr( p, '\"'))
			   if (isspace( *(++p))) {
			      /* (? == space) => push back rest of the input,
			       *                 S_Q_T_S */
                              /* this is to avoid side effects in the macro */
                              int	i = yyleng - strlen(p);
			      yyless( i ); 
                              p = &yytext[yyleng];
                           }
			   else /* keep searching */
			      DEBUG_MSG(p);
                        if( current_di = (Data_Item *)malloc(sizeof(Data_Item)))
                        {
                           current_di->tag = DOUBLE_QUOTED_TEXT_STRING_DI;
			   /* build a new string without the bounding quotes */
                           if( tmp_string = (char *)malloc((strlen(yytext) -2 +1) * sizeof(char)) ) {
                             tmp_string[0] = '\0';
                             tmp_string = strncat( tmp_string, yytext + 1, strlen(yytext +1) -1);
                           } else
                             ERROR_MSG("star_scanner: Out of memory.");
			   DEBUG_MSG("star_scanner: DOUBLE_QUOTED_TEXT_STRING_DI =");
			   DEBUG_MSG( tmp_string );
			   current_di->value = tmp_string;
                           tmp_string = NULL;
                        } else
                            ERROR_MSG("star_scanner: Out of memory.");
			last_request_token = yytext;
                        return( DOUBLE_QUOTED_TEXT_STRING );
                        }

{NotUnderscore}{NonBlank}* {
			DEBUG_MSG("NON_QUOTED_TEXT_STRING");
			DEBUG_MSG(yytext);
                        /* save input */
                        if( current_di = (Data_Item *)malloc(sizeof(Data_Item)))
                        {
                           current_di->tag = NON_QUOTED_TEXT_STRING_DI;
			   current_di->value = strdup( yytext );
                        } else
                            ERROR_MSG("star_scanner: Out of memory.");
                        /* return token */
			last_request_token = yytext;
                        return( NON_QUOTED_TEXT_STRING );
			}

{EndOfLine}		{
			DEBUG_MSG("REST_OF_LINE");
			DEBUG_MSG(yytext);
                        /* increment the line count */
                        request_line_count++;
                        /* simply consume the padding */
			}

{Spaces}		{
			DEBUG_MSG("PADDING");
                        DEBUG_MSG(yytext);
                        /* simply consume the padding */
                        }

.			{
			ERROR_MSG("Unexpected Character");
                        ERROR_MSG(yytext);
			}
%%
/* redefine yywrap */
extern int	ARGc;
extern char	**ARGv;
int
yywrap( void )
{
FILE	*fp;

   DEBUG_MSG("yywrap - looking for more input.");
   if( ARGc ) {
      /* attempt to open the next file */
      if( yyin = fopen(*ARGv, "r") ) {
         /* input file opened successfully */
         INFORM_MSG("Input from:");
         INFORM_MSG(*ARGv);
         /* move pointers along */
         ARGc--; ARGv++;
         /* reset the line count */
         request_line_count = 1;
         /* return the flag to proceed */
         return(0);
         }
      else {
         /* error in opening the file */
         ERROR_MSG("Cannot open file for input:");
         ERROR_MSG(*ARGv);
         return(-1);
      }
   } else {
      /* no arguments left */
      INFORM_MSG("End of input.");
      return( 1 );
   }
} /* yywrap */
