%{
     extern long int LineNo;
%}

%%

<<EOF>>                               return (ENDOFFILE);

"("([^\)\\]([\\]")")?)*")"[ \t]*      return (TEXT);

"run"                                 return (RUN);

"\%"[^\n]*                            return (MISC);

[^\n]                                 return (MISC);
[\n]             {
     ++Line_No;
     return (MISC);
}

%%

#define MaxFiles 5

typedef struct {
     char title[512];
     FILE *file;            /* the latest file opened */
     long int Line_No;
     YY_BUFFER_STATE flex;  /* the parent of the current file */
} FARRAY;

int TopFile = 1;
FARRAY FileArray[MaxFiles] = {
     { "stdin", stdin, 1L }
};

BOOLEAN ReadFromScript(char *f)
{
     FILE *ftmp;
     YY_BUFFER_STATE fyytmp;

     /* open new file */
     if (!(ftmp = fopen(f,"r"))) {
	  yyerror("cannot open desired file");
	  return (FALSE);
     }

     /* make a flex buffer for it */
     if (!(fyytmp = yy_create_buffer(ftmp,YY_BUF_SIZE))) {
	  yyerror("cannot make a FLEXible buffer, sorry");
	  fclose(ftmp);
	  return (FALSE);
     }

     /* store old buffer */
     if (TopFile < MaxFiles) {
	  FileArray[TopFile].Line_No = Line_No;
	  FileArray[TopFile].file = ftmp;
	  strcpy(FileArray[TopFile].title,f);
	  FileArray[TopFile++].flex = YY_CURRENT_BUFFER;
     } else {
	  yyerror("nested too many buffers deep");
	  fclose(ftmp);
	  yy_delete_buffer(fyytmp);
	  return (FALSE);
     }

     /* switch to new buffer */
     yy_switch_to_buffer(fyytmp);
     Line_No = 1;

     return (TRUE);
}

BOOLEAN ReturnToParentScript()
{
     FILE *ftmp;
     YY_BUFFER_STATE now;

     if (TopFile <= 1)
	  return (FALSE);

     ftmp = FileArray[--TopFile].file;
     now = YY_CURRENT_BUFFER;

     /* select parent */
     yy_switch_to_buffer(FileArray[TopFile].flex);
     Line_No = FileArray[TopFile].Line_No;

     /* free old stuff */
     fclose(ftmp);
     yy_delete_buffer(now);

     return (TRUE);
}

void yyerror(char *x)
{
     fprintf(stderr,"ERROR: `%s' line %ld; %s\n"
	     ,FileArray[TopFile-1].title,Line_No,x);
}
