/* ----------------------------------------------------------------
 *   FILE
 *	flexdep.c
 *	
 *   DESCRIPTION
 *	dependencies of the lexical scanner: here flex
 *
 *   NOTES
 *	yytext: char *yytext
 *	flex reads input via the YY_INPUT macro
 *	input() can be used to read one character from flex' input
 *	    stream, but is declared static.
 *	unput(c) is a MACRO to push back data, which calls the static
 *	    function yyunput(c, yytext).
 *	flex defines the constant FLEX_SCANNER
 *
 *	(C) 1993, 1994 Kai Petzke, wpp@marie.physik.tu-berlin.de
 *
 *   IDENTIFICATION
 *	???
 * ----------------------------------------------------------------
 */

#include <stdio.h>
#include "utils/log.h"
#include "dep.h"
#include <stdlib.h>


static void NewInput ARGS((void));
static char *CurScan ARGS((void));

/*
 * Default error handler for syntax errors.
 */
void
yyerror(message)
char    message[];
{
    elog(WARN, "parser: %s at or near \"%s\"\n", message, yytext);
}

/*
 *	Scanner error handler.
 */
void
serror(str)
char str[];
{
	elog(WARN, "*** scanner error: %s\n", str);
}


void
init_io()
{
    parser_cleanup();
    NewInput();
    Ch = NULL;
}


/*
 * Switch to new input (discard the read buffer)
 */
static void
NewInput()
{
    if(yy_current_buffer)
	YY_NEW_FILE;
}


int
scan_input()
{
    return input();
}


void
scan_unput(c)
char c;
{
    unput(c);
}


#if 0
/*
 * Get a character out of flex's buffer
 */
char
DoInput()
{
    char *yy_cp = yy_c_buf_p;
    char *yy_bp = yytext;

    /* undo effects of setting up yytext */
    *yy_cp = yy_hold_char;
    if ( yy_c_buf_p >= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
	switch ( yy_get_next_buffer() ) {
	    case EOB_ACT_CONTINUE_SCAN:
		break;

	    case EOB_ACT_LAST_MATCH:
	    case EOB_ACT_END_OF_FILE:
		return -1;
	}

    yy_cp++;
    yy_c_buf_p = yy_cp;
    YY_DO_BEFORE_ACTION; /* set up yytext again */ \

    return yy_cp[-1];
}
#endif


/*
 * This function determines the current position of the lexical scanning
 * relative to TheString.
 */
static char *
CurScan()
{
    return (InputFrag ? InputFrag : Ch) +
	   (yy_c_buf_p - &yy_current_buffer->yy_ch_buf[yy_n_chars]);
}


#if 0
/*
 * Put a character back into flex's buffer
 */
void DoUnput(char c)
{
    yyunput(c, yytext);
}
#endif


/*
 * Delete the input buffer.
 */
void
parser_cleanup()
{
    if(yy_current_buffer)
	yy_delete_buffer(yy_current_buffer);
    yy_init = 1;
}


/**********************************************************************
  SkipToFromList

  - employ lookahead to see if there is indeed a from_list
  ahead of us.  If so, skip to it and continue processing

 **********************************************************************/
  
static char *target_list_place;
  

void
SkipForwardToFromList()
{
        LispValue next_token;
        char *temp = CurScan();
  
	/*
	 * kai: Don't deliver a from clause, if the scanner hasn't passed beyond
	 *      the last from clause yet.
	 */
	if(temp < InputFrag)
	    return;

        while ((int)(next_token=(LispValue)yylex()) > 0 &&
	     (next_token != (LispValue) FROM &&
		/*
		 * Stop at the beginning of any statement that can have 
		 * a "from" clause (i.e., all optimizable statements --
		 * "execute" doesn't really exist).
		 */
		next_token != (LispValue) APPEND &&
		next_token != (LispValue) DELETE &&
		next_token != (LispValue) REPLACE &&
		next_token != (LispValue) RETRIEVE))
	     ; /* empty while */

        if (next_token == (LispValue) FROM ) {
                Ch = CurScan() - 4;
                FragLen = Ch - temp;
                target_list_place = temp;
        } else {
		Ch = temp;
        }

	NewInput();
}


LispValue
SkipBackToTlist()
{
	extern LispValue yychar;

	/* need to put the token after the target_list back first */
	Ch = CurScan();
	switch ((int) yychar) {
	/*
	 * by examination of gram.y, these seem to be the only clauses
	 * that can follow the "from_clause" non-terminal.  at least,
	 * someone else thought so.
	 */
	case WHERE:
	case SORT:
	/*
	 * these can also follow "from_clause" if we have multiple 
	 * queries, with some empty "from_clause"s.. 
	 */
	case APPEND:
	case DELETE:
	case REPLACE:
	case RETRIEVE:
		Ch -= yyleng;
		break;
	}

	InputFrag = target_list_place;
	NewInput();

	return(LispNil);
}


#include "tmp/acl.h"

void
dep_aclparse(aip, modechg)
        AclItem *aip;
	unsigned *modechg;
{
	Ch = aclparse(CurScan(), aip, modechg);
	NewInput();
}
