/* @(#)star.l	1.10	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 a STAR File */

%{

/* 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 */);
extern int      strcmp(/* const char *s1, const char *s2 */);
#ifndef	_POSIX_SOURCE
extern char *	strdup(/* char *s1 */);
#endif
extern size_t	strlen(/* const char *s */);
#else
#include <malloc.h>
#include <string.h>
#endif

/* Local Definitions */

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

/* redefine yywrap */
#ifdef yywrap
#undef yywrap
#endif
#define yywrap			star_wrap
#define yy_init_buffer		star_init_buffer
#define yyin			star_in
#define yy_switch_to_buffer	star_switch_to_buffer
#define yyout			star_out
#define yy_delete_buffer	star_delete_buffer
#define yy_create_buffer	star_create_buffer
#define yyrestart		star_restart
#define yy_load_buffer_state	star_load_buffer_state
extern int	yywrap();

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

extern char * 	tmp_string;
%}

a		[aA]
b		[bB]
d		[dD]
e		[eE]
g		[gG]
l		[lL]
o		[oO]
p		[pP]
s		[sS]
t		[tT]
v		[vV]
Dollar		\$
Data_		{d}{a}{t}{a}_
Loop_		{l}{o}{o}{p}_
Global_		{g}{l}{o}{b}{a}{l}_
Stop_		{s}{t}{o}{p}_
Save_		{s}{a}{v}{e}_
Char		[^\n]
Blank		[\n \t]
NonBlank	[^\n \t]
NonDQuote	[^\n"]
NonSQuote	[^\n']
NotUnderscore	[^\n \t_]
Space	        [\t ]
Spaces          [\t ]*
Comment		#.*
EndOfLine	{Spaces}({Comment})?\n

%START Alltext 
%a 4000
%o 6000

/* Lex Rules fo a STAR File */
%%
<Alltext>{Char}*\n	{
			/* check for ; in first column */
			if (yytext[0] == ';') {
			  /* reset to the initial state */
			  BEGIN 0;
			  /* return everything but the ';' to input */
			  yyless(1);
			  /* return the token */
                          DEBUG_MSG("end of SEMI_COLON_BOUNDED_TEXT_STRING");
                          DEBUG_MSG(yytext);
                          /* save input */
                          if( current_di = (Data_Item *)malloc(sizeof(Data_Item))) {
                             current_di->tag = SEMI_COLON_BOUNDED_TEXT_STRING_DI;
			     current_di->value = tmp_string;
                          } else
                              ERROR_MSG("star_scanner: Out of memory.");
			  last_star_token = tmp_string;
                          return( SEMI_COLON_BOUNDED_TEXT_STRING );
			} else {
			  /* save each line of text */
                          DEBUG_MSG("LINE_OF_TEXT");
                          DEBUG_MSG(yytext);
			  /* increment the line count */
			  star_line_count++;
                          /* expand the string for the new input */
                          if( tmp_string = (char *) realloc( tmp_string, (strlen(tmp_string) + strlen(yytext) +1) * sizeof( char ) )) /* CHANGE 9/3 */
                            /* add the input onto the end */
                            tmp_string = strcat( tmp_string, yytext );
                          else
                            ERROR_MSG("star_scanner: Out of memory.");
			  }
			}

^;{Char}*		{
			/* return everything but the ';' to input */
			yyless(1);
                     	DEBUG_MSG("start of SEMI_COLON_BOUNDED_TEXT_STRING");
                        DEBUG_MSG(yytext);
                        /* create the empty basis for the contiguous string */
                        if( tmp_string = (char *)malloc(sizeof(char)) )
                           tmp_string[0] = '\0';
                        else
                           ERROR_MSG("star_scanner: Out of memory.");
                        /* set the scanner for consuming all incoming text */
			BEGIN Alltext;
			}

{Spaces}{Loop_}	{
			DEBUG_MSG("LOOP_");
                        DEBUG_MSG(yytext);
			/* save input */
			/* return token */
			last_star_token = yytext;
			return( LOOP_ );
			}

{Spaces}{Stop_}	{
/* does NOt handle blankline being equivalent to stop_ */
			DEBUG_MSG("STOP_");
                        DEBUG_MSG(yytext);
			/* save input */
			/* return token */
			last_star_token = yytext;
			return( STOP_ );
			}

{Spaces}{Data_}{NonBlank}+	{
			DEBUG_MSG("DATA_HEADING");
                        DEBUG_MSG(yytext);
			/* save input */
			if( next_DH ) current_DH = strdup( next_DH );
			next_DH = strdup( yytext );
			/* return token */
			last_star_token = yytext;
			return( DATA_HEADING );
                        }

{Spaces}{Global_}	{
			DEBUG_MSG("GLOBAL_HEADING"); 
			DEBUG_MSG(yytext);
			/* save input */
			if( next_GH ) current_GH = strdup(next_GH);
			next_GH = strdup( yytext );
			/* return token */
			last_star_token = yytext;
			return( GLOBAL_HEADING );
                        }

{Spaces}{Save_}{NonBlank}+	{
			DEBUG_MSG("SAVE_HEADING");
                        DEBUG_MSG(yytext);
			/* save input */
			current_SH = strdup( yytext );
			last_star_token = yytext;
			return( SAVE_HEADING );
                        }

{Spaces}{Save_}	{
			DEBUG_MSG("SAVE_END");
                        DEBUG_MSG(yytext);
			/* return token */
			last_star_token = yytext;
			return( SAVE_END );
                        }

{Spaces}		{
			DEBUG_MSG("PADDING");
                        DEBUG_MSG(yytext);
                     	/* continue with scanning */
                        }

^{EndOfLine}		|
{EndOfLine}		{
			DEBUG_MSG("REST_OF_LINE");
			DEBUG_MSG(yytext);
			/* increment the line count */
			star_line_count++;
                     	/* continue with scanning */
                        /* save input */
                        /* return token */
			/* don't return this token,
			 * This is an attempt to improve the robustness of the 
			 * parser.
                        return( REST_OF_LINE );
			 */
                        }

_{NonBlank}+           {
			DEBUG_MSG("DATA_NAME");
			DEBUG_MSG(yytext);
                        /* save input */
			current_DN = strdup( yytext );
                        /* return token */
			last_star_token = yytext;
                        return( DATA_NAME );
                        }

\'.*\'{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_star_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_star_token = yytext;
                        return( DOUBLE_QUOTED_TEXT_STRING );
                        }

{Dollar}{NonBlank}+	{
			DEBUG_MSG("FRAME_CODE");
			DEBUG_MSG(yytext);
                        /* save input */
                        if( current_di = (Data_Item *)malloc(sizeof(Data_Item)))
                        {
                           current_di->tag = FRAME_CODE_DI;
			   current_di->value = strdup( yytext );
                        } else
                            ERROR_MSG("star_scanner: Out of memory.");
                        /* return token */
			last_star_token = yytext;
                        return( FRAME_CODE );
			}

{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_star_token = yytext;
                        return( NON_QUOTED_TEXT_STRING );
			}

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

   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 */
         star_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 */

char * 	tmp_string = NULL;
