/* A lexical scanner generated by flex */

/* Scanner skeleton version:
 * $Header: /project16/CVS/skycat/astrotcl/cfitsio/eval_l.c,v 1.1.1.1 2009/03/31 14:11:53 cguirao Exp $
 */

#define FLEX_SCANNER
#define FF_FLEX_MAJOR_VERSION 2
#define FF_FLEX_MINOR_VERSION 5

#include <stdio.h>


/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
#ifdef c_plusplus
#ifndef __cplusplus
#define __cplusplus
#endif
#endif


#ifdef __cplusplus

#include <stdlib.h>
#include <unistd.h>

/* Use prototypes in function declarations. */
#define FF_USE_PROTOS

/* The "const" storage-class-modifier is valid. */
#define FF_USE_CONST

#else	/* ! __cplusplus */

#if __STDC__

#define FF_USE_PROTOS
#define FF_USE_CONST

#endif	/* __STDC__ */
#endif	/* ! __cplusplus */

#ifdef __TURBOC__
 #pragma warn -rch
 #pragma warn -use
#include <io.h>
#include <stdlib.h>
#define FF_USE_CONST
#define FF_USE_PROTOS
#endif

#ifdef FF_USE_CONST
#define ffconst const
#else
#define ffconst
#endif


#ifdef FF_USE_PROTOS
#define FF_PROTO(proto) proto
#else
#define FF_PROTO(proto) ()
#endif

/* Returned upon end-of-file. */
#define FF_NULL 0

/* Promotes a possibly negative, possibly signed char to an unsigned
 * integer for use as an array index.  If the signed char is negative,
 * we want to instead treat it as an 8-bit unsigned char, hence the
 * double cast.
 */
#define FF_SC_TO_UI(c) ((unsigned int) (unsigned char) c)

/* Enter a start condition.  This macro really ought to take a parameter,
 * but we do it the disgusting crufty way forced on us by the ()-less
 * definition of BEGIN.
 */
#define BEGIN ff_start = 1 + 2 *

/* Translate the current start state into a value that can be later handed
 * to BEGIN to return to the state.  The FFSTATE alias is for lex
 * compatibility.
 */
#define FF_START ((ff_start - 1) / 2)
#define FFSTATE FF_START

/* Action number for EOF rule of a given start state. */
#define FF_STATE_EOF(state) (FF_END_OF_BUFFER + state + 1)

/* Special action meaning "start processing a new file". */
#define FF_NEW_FILE ffrestart( ffin )

#define FF_END_OF_BUFFER_CHAR 0

/* Size of default input buffer. */
#define FF_BUF_SIZE 16384

typedef struct ff_buffer_state *FF_BUFFER_STATE;

extern int ffleng;
extern FILE *ffin, *ffout;

#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2

/* The funky do-while in the following #define is used to turn the definition
 * int a single C statement (which needs a semi-colon terminator).  This
 * avoids problems with code like:
 *
 * 	if ( condition_holds )
 *		ffless( 5 );
 *	else
 *		do_something_else();
 *
 * Prior to using the do-while the compiler would get upset at the
 * "else" because it interpreted the "if" statement as being all
 * done when it reached the ';' after the ffless() call.
 */

/* Return all but the first 'n' matched characters back to the input stream. */

#define ffless(n) \
	do \
		{ \
		/* Undo effects of setting up fftext. */ \
		*ff_cp = ff_hold_char; \
		FF_RESTORE_FF_MORE_OFFSET \
		ff_c_buf_p = ff_cp = ff_bp + n - FF_MORE_ADJ; \
		FF_DO_BEFORE_ACTION; /* set up fftext again */ \
		} \
	while ( 0 )

#define unput(c) ffunput( c, fftext_ptr )

/* The following is because we cannot portably get our hands on size_t
 * (without autoconf's help, which isn't available because we want
 * flex-generated scanners to compile on their own).
 */
typedef unsigned int ff_size_t;


struct ff_buffer_state
	{
	FILE *ff_input_file;

	char *ff_ch_buf;		/* input buffer */
	char *ff_buf_pos;		/* current position in input buffer */

	/* Size of input buffer in bytes, not including room for EOB
	 * characters.
	 */
	ff_size_t ff_buf_size;

	/* Number of characters read into ff_ch_buf, not including EOB
	 * characters.
	 */
	int ff_n_chars;

	/* Whether we "own" the buffer - i.e., we know we created it,
	 * and can realloc() it to grow it, and should free() it to
	 * delete it.
	 */
	int ff_is_our_buffer;

	/* Whether this is an "interactive" input source; if so, and
	 * if we're using stdio for input, then we want to use getc()
	 * instead of fread(), to make sure we stop fetching input after
	 * each newline.
	 */
	int ff_is_interactive;

	/* Whether we're considered to be at the beginning of a line.
	 * If so, '^' rules will be active on the next match, otherwise
	 * not.
	 */
	int ff_at_bol;

	/* Whether to try to fill the input buffer when we reach the
	 * end of it.
	 */
	int ff_fill_buffer;

	int ff_buffer_status;
#define FF_BUFFER_NEW 0
#define FF_BUFFER_NORMAL 1
	/* When an EOF's been seen but there's still some text to process
	 * then we mark the buffer as FF_EOF_PENDING, to indicate that we
	 * shouldn't try reading from the input source any more.  We might
	 * still have a bunch of tokens to match, though, because of
	 * possible backing-up.
	 *
	 * When we actually see the EOF, we change the status to "new"
	 * (via ffrestart()), so that the user can continue scanning by
	 * just pointing ffin at a new input file.
	 */
#define FF_BUFFER_EOF_PENDING 2
	};

static FF_BUFFER_STATE ff_current_buffer = 0;

/* We provide macros for accessing buffer states in case in the
 * future we want to put the buffer states in a more general
 * "scanner state".
 */
#define FF_CURRENT_BUFFER ff_current_buffer


/* ff_hold_char holds the character lost when fftext is formed. */
static char ff_hold_char;

static int ff_n_chars;		/* number of characters read into ff_ch_buf */


int ffleng;

/* Points to current character in buffer. */
static char *ff_c_buf_p = (char *) 0;
static int ff_init = 1;		/* whether we need to initialize */
static int ff_start = 0;	/* start state number */

/* Flag which is used to allow ffwrap()'s to do buffer switches
 * instead of setting up a fresh ffin.  A bit of a hack ...
 */
static int ff_did_buffer_switch_on_eof;

void ffrestart FF_PROTO(( FILE *input_file ));

void ff_switch_to_buffer FF_PROTO(( FF_BUFFER_STATE new_buffer ));
void ff_load_buffer_state FF_PROTO(( void ));
FF_BUFFER_STATE ff_create_buffer FF_PROTO(( FILE *file, int size ));
void ff_delete_buffer FF_PROTO(( FF_BUFFER_STATE b ));
void ff_init_buffer FF_PROTO(( FF_BUFFER_STATE b, FILE *file ));
void ff_flush_buffer FF_PROTO(( FF_BUFFER_STATE b ));
#define FF_FLUSH_BUFFER ff_flush_buffer( ff_current_buffer )

FF_BUFFER_STATE ff_scan_buffer FF_PROTO(( char *base, ff_size_t size ));
FF_BUFFER_STATE ff_scan_string FF_PROTO(( ffconst char *ff_str ));
FF_BUFFER_STATE ff_scan_bytes FF_PROTO(( ffconst char *bytes, int len ));

static void *ff_flex_alloc FF_PROTO(( ff_size_t ));
static void *ff_flex_realloc FF_PROTO(( void *, ff_size_t ));
static void ff_flex_free FF_PROTO(( void * ));

#define ff_new_buffer ff_create_buffer

#define ff_set_interactive(is_interactive) \
	{ \
	if ( ! ff_current_buffer ) \
		ff_current_buffer = ff_create_buffer( ffin, FF_BUF_SIZE ); \
	ff_current_buffer->ff_is_interactive = is_interactive; \
	}

#define ff_set_bol(at_bol) \
	{ \
	if ( ! ff_current_buffer ) \
		ff_current_buffer = ff_create_buffer( ffin, FF_BUF_SIZE ); \
	ff_current_buffer->ff_at_bol = at_bol; \
	}

#define FF_AT_BOL() (ff_current_buffer->ff_at_bol)

typedef unsigned char FF_CHAR;
FILE *ffin = (FILE *) 0, *ffout = (FILE *) 0;
typedef int ff_state_type;
extern char *fftext;
#define fftext_ptr fftext

static ff_state_type ff_get_previous_state FF_PROTO(( void ));
static ff_state_type ff_try_NUL_trans FF_PROTO(( ff_state_type current_state ));
static int ff_get_next_buffer FF_PROTO(( void ));
static void ff_fatal_error FF_PROTO(( ffconst char msg[] ));

/* Done after the current pattern has been matched and before the
 * corresponding action - sets up fftext.
 */
#define FF_DO_BEFORE_ACTION \
	fftext_ptr = ff_bp; \
	ffleng = (int) (ff_cp - ff_bp); \
	ff_hold_char = *ff_cp; \
	*ff_cp = '\0'; \
	ff_c_buf_p = ff_cp;

#define FF_NUM_RULES 26
#define FF_END_OF_BUFFER 27
static ffconst short int ff_accept[160] =
    {   0,
        0,    0,   27,   25,    1,   24,   15,   25,   25,   25,
       25,   25,   25,   25,    7,    5,   21,   25,   20,   10,
       10,   10,   10,    6,   10,   10,   10,   10,   10,   14,
       10,   10,   10,   10,   10,   10,   10,   25,    1,   19,
        0,    9,    0,    8,    0,   10,   17,    0,    0,    0,
        0,    0,    0,    0,   14,    0,    7,    0,    0,    0,
        0,    0,    0,    0,    0,    0,    0,    0,    0,    7,
        5,    0,   23,   18,   22,   10,   10,   10,    2,   10,
       10,   10,    4,   10,   10,   10,   10,    3,   10,   10,
       10,   10,   10,   10,   10,   10,   10,   10,   16,    0,

        8,    0,    0,    0,    0,    0,    0,    0,    0,    0,
        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
        0,    0,    0,    0,    0,    0,    0,    7,   11,   10,
       20,   21,   10,   10,   10,    0,    0,    0,    0,    0,
        0,    0,    0,    0,    0,   15,    0,    0,   12,    0,
        0,    0,    0,    0,    0,    0,   13,    0,    0
    } ;

static ffconst int ff_ec[256] =
    {   0,
        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    2,    4,    5,    6,    7,    1,    8,    9,   10,
       11,   12,   13,    1,   13,   14,    1,   15,   15,   16,
       16,   16,   16,   16,   16,   17,   17,    1,    1,   18,
       19,   20,    1,    1,   21,   22,   23,   24,   25,   26,
       27,   28,   29,   30,   30,   31,   30,   32,   33,   30,
       34,   35,   30,   36,   37,   30,   30,   38,   30,   30,
        1,    1,    1,   39,   40,    1,   41,   42,   23,   43,

       44,   45,   46,   28,   47,   30,   30,   48,   30,   49,
       50,   30,   51,   52,   30,   53,   54,   30,   30,   38,
       30,   30,    1,   55,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,

        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1
    } ;

static ffconst int ff_meta[56] =
    {   0,
        1,    1,    2,    1,    1,    1,    3,    1,    1,    1,
        1,    1,    1,    1,    4,    4,    4,    1,    1,    1,
        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
        4,    4,    4,    4,    4,    4,    4,    4,    1,    4,
        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
        4,    4,    4,    4,    1
    } ;

static ffconst short int ff_base[167] =
    {   0,
        0,    0,  367,  368,  364,  368,  346,  359,  356,  355,
      353,  351,   32,  347,   66,  103,  339,   44,  338,   25,
       52,  316,   26,  315,   34,  133,   48,   61,  125,  368,
        0,   29,   45,   60,   81,   82,   93,  299,  351,  368,
      347,  368,  344,  343,  342,  368,  368,  339,  314,  315,
      313,  294,  295,  293,  368,  121,  164,  307,  301,   70,
      117,   43,  296,  276,  271,   58,   86,   79,  269,  152,
      168,  181,  368,  368,  368,  151,  162,    0,  180,  189,
      190,  191,  309,  196,  199,  205,  204,  211,  214,  207,
      223,  224,  232,  238,  243,  245,  222,  246,  368,  311,

      310,  279,  282,  278,  259,  262,  258,  252,  286,  295,
      294,  293,  292,  291,  290,  267,  288,  258,  285,  284,
      278,  270,  268,  259,  218,  252,  264,  272,  368,  251,
      368,  368,  260,  280,  283,  236,  222,  230,  193,  184,
      212,  208,  202,  173,  156,  368,  133,  126,  368,  104,
       98,  119,  132,   80,   94,   92,  368,   78,  368,  323,
      325,  329,  333,   68,   67,  337
    } ;

static ffconst short int ff_def[167] =
    {   0,
      159,    1,  159,  159,  159,  159,  159,  160,  161,  162,
      159,  163,  159,  159,  159,  159,  159,  159,  159,  164,
      164,  164,  164,  164,  164,  164,  164,  164,  164,  159,
      165,  164,  164,  164,  164,  164,  164,  159,  159,  159,
      160,  159,  166,  161,  162,  159,  159,  163,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  164,  164,  165,  164,  164,
      164,  164,   26,  164,  164,  164,  164,  164,  164,  164,
      164,  164,  164,  164,  164,  164,  164,  164,  159,  166,

      166,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  164,
      159,  159,  164,  164,  164,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,    0,  159,
      159,  159,  159,  159,  159,  159
    } ;

static ffconst short int ff_nxt[424] =
    {   0,
        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
        4,   14,    4,   15,   16,   16,   16,   17,   18,   19,
       20,   21,   22,   22,   23,   24,   25,   26,   22,   22,
       27,   28,   29,   22,   22,   24,   22,   22,   30,   31,
       32,   21,   22,   33,   24,   34,   22,   35,   36,   37,
       22,   22,   24,   22,   38,   49,   77,   50,   81,   80,
       51,   73,   74,   75,   78,   78,   79,  115,   78,   82,
       78,   76,   84,   78,   52,  116,   53,   90,   54,   56,
       57,   57,   57,   85,   78,   86,   58,   78,  157,   79,
       59,   78,   60,   87,  111,   91,   61,   62,   63,   78,

       78,  120,  157,   92,  157,  112,   64,   88,   88,   65,
      121,   66,   93,   67,   68,   69,   70,   71,   71,   71,
       78,   78,  124,  158,   94,   96,   72,   72,  125,  122,
       88,   97,   78,   95,   56,  108,  108,  108,  123,   88,
       88,  113,  157,  156,   98,   72,   72,   83,   83,   83,
      155,  154,  114,   83,   83,   83,   83,   83,   83,   89,
      129,  153,   88,  152,   78,   56,   57,   57,   57,  146,
       83,  129,   78,   83,   83,   83,   83,   83,   57,   57,
       57,   70,   71,   71,   71,  130,   47,   72,   72,  129,
       78,   72,   72,  127,   79,  128,  128,  128,  129,  129,

      129,   78,   74,   75,  131,  129,   72,   72,  129,   73,
       72,   72,  132,  129,  129,  146,  129,   79,   40,   78,
      129,   47,  149,  129,  151,   88,   88,   99,   78,   78,
       78,  129,  129,  129,  150,   78,   74,   75,   78,  133,
      149,  129,  148,   78,   78,  131,   78,  129,   88,  134,
       78,   73,  129,   78,  129,  129,  132,  147,   40,   99,
      129,   78,   78,   78,   47,   99,  108,  108,  108,  129,
      145,   78,   40,  146,  135,   72,   72,   78,  128,  128,
      128,  132,   78,   73,   78,   78,  128,  128,  128,  129,
       78,  131,  129,   47,   72,   72,  146,   75,   74,   78,

      144,   99,  143,   40,  132,   73,  131,   75,   74,  142,
      141,  140,  139,  138,  137,  136,  101,  101,  129,   78,
      126,  119,   78,   41,  118,   41,   41,   44,   44,   45,
      117,   45,   45,   48,  110,   48,   48,  100,  109,  100,
      100,  107,  106,  105,  104,  103,  102,   42,   46,  159,
      101,   42,   39,   99,   78,   78,   75,   73,   55,   42,
       47,   46,   43,   42,   40,   39,  159,    3,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,

      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159
    } ;

static ffconst short int ff_chk[424] =
    {   0,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
        1,    1,    1,    1,    1,   13,   20,   13,   25,   23,
       13,   18,   18,   18,   20,   23,   21,   62,   32,   25,
      165,  164,   27,   25,   13,   62,   13,   32,   13,   15,
       15,   15,   15,   27,   33,   28,   15,   27,  158,   21,
       15,   21,   15,   28,   60,   33,   15,   15,   15,   34,

       28,   66,  156,   34,  155,   60,   15,   37,   37,   15,
       66,   15,   34,   15,   15,   15,   16,   16,   16,   16,
       35,   36,   68,  154,   35,   36,   16,   16,   68,   67,
       37,   36,   37,   35,   56,   56,   56,   56,   67,   29,
       29,   61,  153,  152,   37,   16,   16,   26,   26,   26,
      151,  150,   61,   26,   26,   26,   26,   26,   26,   29,
       76,  148,   29,  147,   29,   70,   70,   70,   70,  145,
       26,   77,   26,   26,   26,   26,   26,   26,   57,   57,
       57,   71,   71,   71,   71,   77,  144,   57,   57,   79,
       76,   71,   71,   72,   79,   72,   72,   72,   80,   81,

       82,   77,   80,   81,   82,   84,   57,   57,   85,   84,
       71,   71,   85,   87,   86,  143,   90,   79,   86,   79,
       88,  142,  141,   89,  140,   88,   88,   89,   80,   81,
       82,   97,   91,   92,  139,   84,   91,   92,   85,   87,
      138,   93,  137,   87,   86,   93,   90,   94,   88,   90,
       88,   94,   95,   89,   96,   98,   95,  136,   96,   98,
      130,   97,   91,   92,  130,  126,  108,  108,  108,  133,
      125,   93,  124,  133,   97,  108,  108,   94,  127,  127,
      127,  123,   95,  122,   96,   98,  128,  128,  128,  134,
      130,  121,  135,  134,  108,  108,  135,  120,  119,  133,

      118,  117,  116,  115,  114,  113,  112,  111,  110,  109,
      107,  106,  105,  104,  103,  102,  101,  100,   83,  134,
       69,   65,  135,  160,   64,  160,  160,  161,  161,  162,
       63,  162,  162,  163,   59,  163,  163,  166,   58,  166,
      166,   54,   53,   52,   51,   50,   49,   48,   45,   44,
       43,   41,   39,   38,   24,   22,   19,   17,   14,   12,
       11,   10,    9,    8,    7,    5,    3,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,

      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
      159,  159,  159
    } ;

static ff_state_type ff_last_accepting_state;
static char *ff_last_accepting_cpos;

/* The intent behind this definition is that it'll catch
 * any uses of REJECT which flex missed.
 */
#define REJECT reject_used_but_not_detected
#define ffmore() ffmore_used_but_not_detected
#define FF_MORE_ADJ 0
#define FF_RESTORE_FF_MORE_OFFSET
char *fftext;
#line 1 "eval.l"
#define INITIAL 0
#line 2 "eval.l"
/************************************************************************/
/*                                                                      */
/*                       CFITSIO Lexical Parser                         */
/*                                                                      */
/* This file is one of 3 files containing code which parses an          */
/* arithmetic expression and evaluates it in the context of an input    */
/* FITS file table extension.  The CFITSIO lexical parser is divided    */
/* into the following 3 parts/files: the CFITSIO "front-end",           */
/* eval_f.c, contains the interface between the user/CFITSIO and the    */
/* real core of the parser; the FLEX interpreter, eval_l.c, takes the   */
/* input string and parses it into tokens and identifies the FITS       */
/* information required to evaluate the expression (ie, keywords and    */
/* columns); and, the BISON grammar and evaluation routines, eval_y.c,  */
/* receives the FLEX output and determines and performs the actual      */
/* operations.  The files eval_l.c and eval_y.c are produced from       */
/* running flex and bison on the files eval.l and eval.y, respectively. */
/* (flex and bison are available from any GNU archive: see www.gnu.org) */
/*                                                                      */
/* The grammar rules, rather than evaluating the expression in situ,    */
/* builds a tree, or Nodal, structure mapping out the order of          */
/* operations and expression dependencies.  This "compilation" process  */
/* allows for much faster processing of multiple rows.  This technique  */
/* was developed by Uwe Lammers of the XMM Science Analysis System,     */
/* although the CFITSIO implementation is entirely code original.       */
/*                                                                      */
/*                                                                      */
/* Modification History:                                                */
/*                                                                      */
/*   Kent Blackburn      c1992  Original parser code developed for the  */
/*                              FTOOLS software package, in particular, */
/*                              the fselect task.                       */
/*   Kent Blackburn      c1995  BIT column support added                */
/*   Peter D Wilson   Feb 1998  Vector column support added             */
/*   Peter D Wilson   May 1998  Ported to CFITSIO library.  User        */
/*                              interface routines written, in essence  */
/*                              making fselect, fcalc, and maketime     */
/*                              capabilities available to all tools     */
/*                              via single function calls.              */
/*   Peter D Wilson   Jun 1998  Major rewrite of parser core, so as to  */
/*                              create a run-time evaluation tree,      */
/*                              inspired by the work of Uwe Lammers,    */
/*                              resulting in a speed increase of        */
/*                              10-100 times.                           */
/*   Peter D Wilson   Jul 1998  gtifilter(a,b,c,d) function added       */
/*   Peter D Wilson   Aug 1998  regfilter(a,b,c,d) function added       */
/*   Peter D Wilson   Jul 1999  Make parser fitsfile-independent,       */
/*                              allowing a purely vector-based usage    */
/*                                                                      */
/************************************************************************/

#include <math.h>
#include <string.h>
#include <ctype.h>
#ifdef sparc
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include "eval_defs.h"

ParseData gParse;     /* Global structure holding all parser information     */

/*****  Internal functions  *****/

       int ffGetVariable( char *varName, FFSTYPE *varVal );

static int find_variable( char *varName );
static int expr_read( char *buf, int nbytes );

/*****  Definitions  *****/

#define FF_NO_UNPUT   /*  Don't include FFUNPUT function  */
#define FF_NEVER_INTERACTIVE 1

#define MAXCHR 256
#define MAXBIT 128

#define OCT_0 "000"
#define OCT_1 "001"
#define OCT_2 "010"
#define OCT_3 "011"
#define OCT_4 "100"
#define OCT_5 "101"
#define OCT_6 "110"
#define OCT_7 "111"
#define OCT_X "xxx"

#define HEX_0 "0000"
#define HEX_1 "0001"
#define HEX_2 "0010"
#define HEX_3 "0011"
#define HEX_4 "0100"
#define HEX_5 "0101"
#define HEX_6 "0110"
#define HEX_7 "0111"
#define HEX_8 "1000"
#define HEX_9 "1001"
#define HEX_A "1010"
#define HEX_B "1011"
#define HEX_C "1100"
#define HEX_D "1101"
#define HEX_E "1110"
#define HEX_F "1111"
#define HEX_X "xxxx"

/* 
   MJT - 13 June 1996
   read from buffer instead of stdin
   (as per old ftools.skel)
*/
#undef FF_INPUT
#define FF_INPUT(buf,result,max_size) \
        if ( (result = expr_read( (char *) buf, max_size )) < 0 ) \
            FF_FATAL_ERROR( "read() in flex scanner failed" );


/* Macros after this point can all be overridden by user definitions in
 * section 1.
 */

#ifndef FF_SKIP_FFWRAP
#ifdef __cplusplus
extern "C" int ffwrap FF_PROTO(( void ));
#else
extern int ffwrap FF_PROTO(( void ));
#endif
#endif

#ifndef FF_NO_UNPUT
static void ffunput FF_PROTO(( int c, char *buf_ptr ));
#endif

#ifndef fftext_ptr
static void ff_flex_strncpy FF_PROTO(( char *, ffconst char *, int ));
#endif

#ifdef FF_NEED_STRLEN
static int ff_flex_strlen FF_PROTO(( ffconst char * ));
#endif

#ifndef FF_NO_INPUT
#ifdef __cplusplus
static int ffinput FF_PROTO(( void ));
#else
static int input FF_PROTO(( void ));
#endif
#endif

#if FF_STACK_USED
static int ff_start_stack_ptr = 0;
static int ff_start_stack_depth = 0;
static int *ff_start_stack = 0;
#ifndef FF_NO_PUSH_STATE
static void ff_push_state FF_PROTO(( int new_state ));
#endif
#ifndef FF_NO_POP_STATE
static void ff_pop_state FF_PROTO(( void ));
#endif
#ifndef FF_NO_TOP_STATE
static int ff_top_state FF_PROTO(( void ));
#endif

#else
#define FF_NO_PUSH_STATE 1
#define FF_NO_POP_STATE 1
#define FF_NO_TOP_STATE 1
#endif

#ifdef FF_MALLOC_DECL
FF_MALLOC_DECL
#else
#if __STDC__
#ifndef __cplusplus
#include <stdlib.h>
#endif
#else
/* Just try to get by without declaring the routines.  This will fail
 * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
 * or sizeof(void*) != sizeof(int).
 */
#endif
#endif

/* Amount of stuff to slurp up with each read. */
#ifndef FF_READ_BUF_SIZE
#define FF_READ_BUF_SIZE 8192
#endif

/* Copy whatever the last rule matched to the standard output. */

#ifndef ECHO
/* This used to be an fputs(), but since the string might contain NUL's,
 * we now use fwrite().
 */
#define ECHO (void) fwrite( fftext, ffleng, 1, ffout )
#endif

/* Gets input and stuffs it into "buf".  number of characters read, or FF_NULL,
 * is returned in "result".
 */
#ifndef FF_INPUT
#define FF_INPUT(buf,result,max_size) \
	if ( ff_current_buffer->ff_is_interactive ) \
		{ \
		int c = '*', n; \
		for ( n = 0; n < max_size && \
			     (c = getc( ffin )) != EOF && c != '\n'; ++n ) \
			buf[n] = (char) c; \
		if ( c == '\n' ) \
			buf[n++] = (char) c; \
		if ( c == EOF && ferror( ffin ) ) \
			FF_FATAL_ERROR( "input in flex scanner failed" ); \
		result = n; \
		} \
	else if ( ((result = fread( buf, 1, max_size, ffin )) == 0) \
		  && ferror( ffin ) ) \
		FF_FATAL_ERROR( "input in flex scanner failed" );
#endif

/* No semi-colon after return; correct usage is to write "ffterminate();" -
 * we don't want an extra ';' after the "return" because that will cause
 * some compilers to complain about unreachable statements.
 */
#ifndef ffterminate
#define ffterminate() return FF_NULL
#endif

/* Number of entries by which start-condition stack grows. */
#ifndef FF_START_STACK_INCR
#define FF_START_STACK_INCR 25
#endif

/* Report a fatal error. */
#ifndef FF_FATAL_ERROR
#define FF_FATAL_ERROR(msg) ff_fatal_error( msg )
#endif

/* Default declaration of generated scanner - a define so the user can
 * easily add parameters.
 */
#ifndef FF_DECL
#define FF_DECL int fflex FF_PROTO(( void ))
#endif

/* Code executed at the beginning of each rule, after fftext and ffleng
 * have been set up.
 */
#ifndef FF_USER_ACTION
#define FF_USER_ACTION
#endif

/* Code executed at the end of each rule. */
#ifndef FF_BREAK
#define FF_BREAK break;
#endif

#define FF_RULE_SETUP \
	FF_USER_ACTION

FF_DECL
	{
	register ff_state_type ff_current_state;
	register char *ff_cp, *ff_bp;
	register int ff_act;

#line 142 "eval.l"



	if ( ff_init )
		{
		ff_init = 0;

#ifdef FF_USER_INIT
		FF_USER_INIT;
#endif

		if ( ! ff_start )
			ff_start = 1;	/* first start state */

		if ( ! ffin )
			ffin = stdin;

		if ( ! ffout )
			ffout = stdout;

		if ( ! ff_current_buffer )
			ff_current_buffer =
				ff_create_buffer( ffin, FF_BUF_SIZE );

		ff_load_buffer_state();
		}

	while ( 1 )		/* loops until end-of-file is reached */
		{
		ff_cp = ff_c_buf_p;

		/* Support of fftext. */
		*ff_cp = ff_hold_char;

		/* ff_bp points to the position in ff_ch_buf of the start of
		 * the current run.
		 */
		ff_bp = ff_cp;

		ff_current_state = ff_start;
ff_match:
		do
			{
			register FF_CHAR ff_c = ff_ec[FF_SC_TO_UI(*ff_cp)];
			if ( ff_accept[ff_current_state] )
				{
				ff_last_accepting_state = ff_current_state;
				ff_last_accepting_cpos = ff_cp;
				}
			while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state )
				{
				ff_current_state = (int) ff_def[ff_current_state];
				if ( ff_current_state >= 160 )
					ff_c = ff_meta[(unsigned int) ff_c];
				}
			ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c];
			++ff_cp;
			}
		while ( ff_base[ff_current_state] != 368 );

ff_find_action:
		ff_act = ff_accept[ff_current_state];
		if ( ff_act == 0 )
			{ /* have to back up */
			ff_cp = ff_last_accepting_cpos;
			ff_current_state = ff_last_accepting_state;
			ff_act = ff_accept[ff_current_state];
			}

		FF_DO_BEFORE_ACTION;


do_action:	/* This label is used only to access EOF actions. */


		switch ( ff_act )
	{ /* beginning of action switch */
			case 0: /* must back up */
			/* undo the effects of FF_DO_BEFORE_ACTION */
			*ff_cp = ff_hold_char;
			ff_cp = ff_last_accepting_cpos;
			ff_current_state = ff_last_accepting_state;
			goto ff_find_action;

case 1:
FF_RULE_SETUP
#line 144 "eval.l"
;
	FF_BREAK
case 2:
FF_RULE_SETUP
#line 145 "eval.l"
{
                  int len;
                  len = strlen(fftext);
		  while (fftext[len] == ' ')
			len--;
                  len = len - 1;
		  strncpy(fflval.str,&fftext[1],len);
		  fflval.str[len] = '\0';
		  return( BITSTR );
		}
	FF_BREAK
case 3:
FF_RULE_SETUP
#line 155 "eval.l"
{
                  int len;
                  char tmpstring[256];
                  char bitstring[256];
                  len = strlen(fftext);
		  while (fftext[len] == ' ')
			len--;
                  len = len - 1;
		  strncpy(tmpstring,&fftext[1],len);
                  tmpstring[len] = '\0';
                  bitstring[0] = '\0';
		  len = 0;
                  while ( tmpstring[len] != '\0')
                       {
			switch ( tmpstring[len] )
			      {
			       case '0':
					strcat(bitstring,OCT_0);
					break;
			       case '1':
					strcat(bitstring,OCT_1);
					break;
			       case '2':
					strcat(bitstring,OCT_2);
					break;
			       case '3':
					strcat(bitstring,OCT_3);
					break;
			       case '4':
					strcat(bitstring,OCT_4);
					break;
			       case '5':
					strcat(bitstring,OCT_5);
					break;
			       case '6':
					strcat(bitstring,OCT_6);
					break;
			       case '7':
					strcat(bitstring,OCT_7);
					break;
			       case 'x':
			       case 'X':
					strcat(bitstring,OCT_X);
					break;
			      }
			len++;
                       }
                  strcpy( fflval.str, bitstring );
		  return( BITSTR );
		}
	FF_BREAK
case 4:
FF_RULE_SETUP
#line 205 "eval.l"
{
                  int len;
                  char tmpstring[256];
                  char bitstring[256];
                  len = strlen(fftext);
		  while (fftext[len] == ' ')
			len--;
                  len = len - 1;
		  strncpy(tmpstring,&fftext[1],len);
                  tmpstring[len] = '\0';
                  bitstring[0] = '\0';
		  len = 0;
                  while ( tmpstring[len] != '\0')
                       {
			switch ( tmpstring[len] )
			      {
			       case '0':
					strcat(bitstring,HEX_0);
					break;
			       case '1':
					strcat(bitstring,HEX_1);
					break;
			       case '2':
					strcat(bitstring,HEX_2);
					break;
			       case '3':
					strcat(bitstring,HEX_3);
					break;
			       case '4':
					strcat(bitstring,HEX_4);
					break;
			       case '5':
					strcat(bitstring,HEX_5);
					break;
			       case '6':
					strcat(bitstring,HEX_6);
					break;
			       case '7':
					strcat(bitstring,HEX_7);
					break;
			       case '8':
					strcat(bitstring,HEX_8);
					break;
			       case '9':
					strcat(bitstring,HEX_9);
					break;
			       case 'a':
			       case 'A':
					strcat(bitstring,HEX_A);
					break;
			       case 'b':
			       case 'B':
					strcat(bitstring,HEX_B);
					break;
			       case 'c':
			       case 'C':
					strcat(bitstring,HEX_C);
					break;
			       case 'd':
			       case 'D':
					strcat(bitstring,HEX_D);
					break;
			       case 'e':
			       case 'E':
					strcat(bitstring,HEX_E);
					break;
			       case 'f':
			       case 'F':
					strcat(bitstring,HEX_F);
					break;
			       case 'x':
			       case 'X':
					strcat(bitstring,HEX_X);
					break;
			      }
			len++;
                       }

                  strcpy( fflval.str, bitstring );
		  return( BITSTR );
		}
	FF_BREAK
case 5:
FF_RULE_SETUP
#line 286 "eval.l"
{
                  fflval.lng = atol(fftext);
		  return( LONG );
		}
	FF_BREAK
case 6:
FF_RULE_SETUP
#line 290 "eval.l"
{
                  if ((fftext[0] == 't') || (fftext[0] == 'T'))
		    fflval.log = 1;
		  else
		    fflval.log = 0;
		  return( BOOLEAN );
		}
	FF_BREAK
case 7:
FF_RULE_SETUP
#line 297 "eval.l"
{
                  fflval.dbl = atof(fftext);
		  return( DOUBLE );
		}
	FF_BREAK
case 8:
FF_RULE_SETUP
#line 301 "eval.l"
{
                  if(        !strcasecmp(fftext,"#PI") ) {
		     fflval.dbl = (double)(4) * atan((double)(1));
		     return( DOUBLE );
		  } else if( !strcasecmp(fftext,"#E") ) {
		     fflval.dbl = exp((double)(1));
		     return( DOUBLE );
		  } else if( !strcasecmp(fftext,"#DEG") ) {
		     fflval.dbl = ((double)4)*atan((double)1)/((double)180);
		     return( DOUBLE );
		  } else if( !strcasecmp(fftext,"#ROW") ) {
		     return( ROWREF );
		  } else if( !strcasecmp(fftext,"#NULL") ) {
		     return( NULLREF );
		  } else if( !strcasecmp(fftext,"#SNULL") ) {
		     return( SNULLREF );
		  } else {
                     int len; 
                     if (fftext[1] == '$') {
                        len = strlen(fftext) - 3;
                        fflval.str[0]     = '#';
                        strncpy(fflval.str+1,&fftext[2],len);
                        fflval.str[len+1] = '\0';
                        fftext = fflval.str;
		     }
                     return( (*gParse.getData)(fftext, &fflval) );
                  }
                }
	FF_BREAK
case 9:
FF_RULE_SETUP
#line 329 "eval.l"
{
                  int len;
                  len = strlen(fftext) - 2;
		  strncpy(fflval.str,&fftext[1],len);
		  fflval.str[len] = '\0';
		  return( STRING );
		}
	FF_BREAK
case 10:
FF_RULE_SETUP
#line 336 "eval.l"
{
		 int    len,type;

                 if (fftext[0] == '$') {
		    len = strlen(fftext) - 2;
		    strncpy(fflval.str,&fftext[1],len);
		    fflval.str[len] = '\0';
		    fftext = fflval.str;
		 } 
		 type = ffGetVariable(fftext, &fflval);
		 return( type );
		}
	FF_BREAK
case 11:
FF_RULE_SETUP
#line 348 "eval.l"
{
                  char *fname;
		  int len=0;
                  fname = &fflval.str[0];
		  while( (fname[len]=toupper(fftext[len])) ) len++;

                  if(      FSTRCMP(fname,"BOX(")==0 
                        || FSTRCMP(fname,"CIRCLE(")==0 
                        || FSTRCMP(fname,"ELLIPSE(")==0 
                        || FSTRCMP(fname,"NEAR(")==0 
                        || FSTRCMP(fname,"ISNULL(")==0 
                         )
                     /* Return type is always boolean  */
		     return( BFUNCTION );

                  else if( FSTRCMP(fname,"GTIFILTER(")==0 )
                     return( GTIFILTER );

                  else if( FSTRCMP(fname,"REGFILTER(")==0 )
                     return( REGFILTER );

                  else 
		     return( FUNCTION  );
		}
	FF_BREAK
case 12:
FF_RULE_SETUP
#line 372 "eval.l"
{ return( INTCAST ); }
	FF_BREAK
case 13:
FF_RULE_SETUP
#line 373 "eval.l"
{ return( FLTCAST ); }
	FF_BREAK
case 14:
FF_RULE_SETUP
#line 374 "eval.l"
{ return( POWER   ); }
	FF_BREAK
case 15:
FF_RULE_SETUP
#line 375 "eval.l"
{ return( NOT     ); }
	FF_BREAK
case 16:
FF_RULE_SETUP
#line 376 "eval.l"
{ return( OR      ); }
	FF_BREAK
case 17:
FF_RULE_SETUP
#line 377 "eval.l"
{ return( AND     ); }
	FF_BREAK
case 18:
FF_RULE_SETUP
#line 378 "eval.l"
{ return( EQ      ); }
	FF_BREAK
case 19:
FF_RULE_SETUP
#line 379 "eval.l"
{ return( NE      ); }
	FF_BREAK
case 20:
FF_RULE_SETUP
#line 380 "eval.l"
{ return( GT      ); }
	FF_BREAK
case 21:
FF_RULE_SETUP
#line 381 "eval.l"
{ return( LT      ); }
	FF_BREAK
case 22:
FF_RULE_SETUP
#line 382 "eval.l"
{ return( GTE     ); }
	FF_BREAK
case 23:
FF_RULE_SETUP
#line 383 "eval.l"
{ return( LTE     ); }
	FF_BREAK
case 24:
FF_RULE_SETUP
#line 384 "eval.l"
{ return( '\n'    ); }
	FF_BREAK
case 25:
FF_RULE_SETUP
#line 385 "eval.l"
{ return( fftext[0] ); }
	FF_BREAK
case 26:
FF_RULE_SETUP
#line 386 "eval.l"
ECHO;
	FF_BREAK
case FF_STATE_EOF(INITIAL):
	ffterminate();

	case FF_END_OF_BUFFER:
		{
		/* Amount of text matched not including the EOB char. */
		int ff_amount_of_matched_text = (int) (ff_cp - fftext_ptr) - 1;

		/* Undo the effects of FF_DO_BEFORE_ACTION. */
		*ff_cp = ff_hold_char;
		FF_RESTORE_FF_MORE_OFFSET

		if ( ff_current_buffer->ff_buffer_status == FF_BUFFER_NEW )
			{
			/* We're scanning a new file or input source.  It's
			 * possible that this happened because the user
			 * just pointed ffin at a new source and called
			 * fflex().  If so, then we have to assure
			 * consistency between ff_current_buffer and our
			 * globals.  Here is the right place to do so, because
			 * this is the first action (other than possibly a
			 * back-up) that will match for the new input source.
			 */
			ff_n_chars = ff_current_buffer->ff_n_chars;
			ff_current_buffer->ff_input_file = ffin;
			ff_current_buffer->ff_buffer_status = FF_BUFFER_NORMAL;
			}

		/* Note that here we test for ff_c_buf_p "<=" to the position
		 * of the first EOB in the buffer, since ff_c_buf_p will
		 * already have been incremented past the NUL character
		 * (since all states make transitions on EOB to the
		 * end-of-buffer state).  Contrast this with the test
		 * in input().
		 */
		if ( ff_c_buf_p <= &ff_current_buffer->ff_ch_buf[ff_n_chars] )
			{ /* This was really a NUL. */
			ff_state_type ff_next_state;

			ff_c_buf_p = fftext_ptr + ff_amount_of_matched_text;

			ff_current_state = ff_get_previous_state();

			/* Okay, we're now positioned to make the NUL
			 * transition.  We couldn't have
			 * ff_get_previous_state() go ahead and do it
			 * for us because it doesn't know how to deal
			 * with the possibility of jamming (and we don't
			 * want to build jamming into it because then it
			 * will run more slowly).
			 */

			ff_next_state = ff_try_NUL_trans( ff_current_state );

			ff_bp = fftext_ptr + FF_MORE_ADJ;

			if ( ff_next_state )
				{
				/* Consume the NUL. */
				ff_cp = ++ff_c_buf_p;
				ff_current_state = ff_next_state;
				goto ff_match;
				}

			else
				{
				ff_cp = ff_c_buf_p;
				goto ff_find_action;
				}
			}

		else switch ( ff_get_next_buffer() )
			{
			case EOB_ACT_END_OF_FILE:
				{
				ff_did_buffer_switch_on_eof = 0;

				if ( ffwrap() )
					{
					/* Note: because we've taken care in
					 * ff_get_next_buffer() to have set up
					 * fftext, we can now set up
					 * ff_c_buf_p so that if some total
					 * hoser (like flex itself) wants to
					 * call the scanner after we return the
					 * FF_NULL, it'll still work - another
					 * FF_NULL will get returned.
					 */
					ff_c_buf_p = fftext_ptr + FF_MORE_ADJ;

					ff_act = FF_STATE_EOF(FF_START);
					goto do_action;
					}

				else
					{
					if ( ! ff_did_buffer_switch_on_eof )
						FF_NEW_FILE;
					}
				break;
				}

			case EOB_ACT_CONTINUE_SCAN:
				ff_c_buf_p =
					fftext_ptr + ff_amount_of_matched_text;

				ff_current_state = ff_get_previous_state();

				ff_cp = ff_c_buf_p;
				ff_bp = fftext_ptr + FF_MORE_ADJ;
				goto ff_match;

			case EOB_ACT_LAST_MATCH:
				ff_c_buf_p =
				&ff_current_buffer->ff_ch_buf[ff_n_chars];

				ff_current_state = ff_get_previous_state();

				ff_cp = ff_c_buf_p;
				ff_bp = fftext_ptr + FF_MORE_ADJ;
				goto ff_find_action;
			}
		break;
		}

	default:
		FF_FATAL_ERROR(
			"fatal flex scanner internal error--no action found" );
	} /* end of action switch */
		} /* end of scanning one token */
	} /* end of fflex */


/* ff_get_next_buffer - try to read in a new buffer
 *
 * Returns a code representing an action:
 *	EOB_ACT_LAST_MATCH -
 *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
 *	EOB_ACT_END_OF_FILE - end of file
 */

static int ff_get_next_buffer()
	{
	register char *dest = ff_current_buffer->ff_ch_buf;
	register char *source = fftext_ptr;
	register int number_to_move, i;
	int ret_val;

	if ( ff_c_buf_p > &ff_current_buffer->ff_ch_buf[ff_n_chars + 1] )
		FF_FATAL_ERROR(
		"fatal flex scanner internal error--end of buffer missed" );

	if ( ff_current_buffer->ff_fill_buffer == 0 )
		{ /* Don't try to fill the buffer, so this is an EOF. */
		if ( ff_c_buf_p - fftext_ptr - FF_MORE_ADJ == 1 )
			{
			/* We matched a single character, the EOB, so
			 * treat this as a final EOF.
			 */
			return EOB_ACT_END_OF_FILE;
			}

		else
			{
			/* We matched some text prior to the EOB, first
			 * process it.
			 */
			return EOB_ACT_LAST_MATCH;
			}
		}

	/* Try to read more data. */

	/* First move last chars to start of buffer. */
	number_to_move = (int) (ff_c_buf_p - fftext_ptr) - 1;

	for ( i = 0; i < number_to_move; ++i )
		*(dest++) = *(source++);

	if ( ff_current_buffer->ff_buffer_status == FF_BUFFER_EOF_PENDING )
		/* don't do the read, it's not guaranteed to return an EOF,
		 * just force an EOF
		 */
		ff_current_buffer->ff_n_chars = ff_n_chars = 0;

	else
		{
		int num_to_read =
			ff_current_buffer->ff_buf_size - number_to_move - 1;

		while ( num_to_read <= 0 )
			{ /* Not enough room in the buffer - grow it. */
#ifdef FF_USES_REJECT
			FF_FATAL_ERROR(
"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
#else

			/* just a shorter name for the current buffer */
			FF_BUFFER_STATE b = ff_current_buffer;

			int ff_c_buf_p_offset =
				(int) (ff_c_buf_p - b->ff_ch_buf);

			if ( b->ff_is_our_buffer )
				{
				int new_size = b->ff_buf_size * 2;

				if ( new_size <= 0 )
					b->ff_buf_size += b->ff_buf_size / 8;
				else
					b->ff_buf_size *= 2;

				b->ff_ch_buf = (char *)
					/* Include room in for 2 EOB chars. */
					ff_flex_realloc( (void *) b->ff_ch_buf,
							 b->ff_buf_size + 2 );
				}
			else
				/* Can't grow it, we don't own it. */
				b->ff_ch_buf = 0;

			if ( ! b->ff_ch_buf )
				FF_FATAL_ERROR(
				"fatal error - scanner input buffer overflow" );

			ff_c_buf_p = &b->ff_ch_buf[ff_c_buf_p_offset];

			num_to_read = ff_current_buffer->ff_buf_size -
						number_to_move - 1;
#endif
			}

		if ( num_to_read > FF_READ_BUF_SIZE )
			num_to_read = FF_READ_BUF_SIZE;

		/* Read in more data. */
		FF_INPUT( (&ff_current_buffer->ff_ch_buf[number_to_move]),
			ff_n_chars, num_to_read );

		ff_current_buffer->ff_n_chars = ff_n_chars;
		}

	if ( ff_n_chars == 0 )
		{
		if ( number_to_move == FF_MORE_ADJ )
			{
			ret_val = EOB_ACT_END_OF_FILE;
			ffrestart( ffin );
			}

		else
			{
			ret_val = EOB_ACT_LAST_MATCH;
			ff_current_buffer->ff_buffer_status =
				FF_BUFFER_EOF_PENDING;
			}
		}

	else
		ret_val = EOB_ACT_CONTINUE_SCAN;

	ff_n_chars += number_to_move;
	ff_current_buffer->ff_ch_buf[ff_n_chars] = FF_END_OF_BUFFER_CHAR;
	ff_current_buffer->ff_ch_buf[ff_n_chars + 1] = FF_END_OF_BUFFER_CHAR;

	fftext_ptr = &ff_current_buffer->ff_ch_buf[0];

	return ret_val;
	}


/* ff_get_previous_state - get the state just before the EOB char was reached */

static ff_state_type ff_get_previous_state()
	{
	register ff_state_type ff_current_state;
	register char *ff_cp;

	ff_current_state = ff_start;

	for ( ff_cp = fftext_ptr + FF_MORE_ADJ; ff_cp < ff_c_buf_p; ++ff_cp )
		{
		register FF_CHAR ff_c = (*ff_cp ? ff_ec[FF_SC_TO_UI(*ff_cp)] : 1);
		if ( ff_accept[ff_current_state] )
			{
			ff_last_accepting_state = ff_current_state;
			ff_last_accepting_cpos = ff_cp;
			}
		while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state )
			{
			ff_current_state = (int) ff_def[ff_current_state];
			if ( ff_current_state >= 160 )
				ff_c = ff_meta[(unsigned int) ff_c];
			}
		ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c];
		}

	return ff_current_state;
	}


/* ff_try_NUL_trans - try to make a transition on the NUL character
 *
 * synopsis
 *	next_state = ff_try_NUL_trans( current_state );
 */

#ifdef FF_USE_PROTOS
static ff_state_type ff_try_NUL_trans( ff_state_type ff_current_state )
#else
static ff_state_type ff_try_NUL_trans( ff_current_state )
ff_state_type ff_current_state;
#endif
	{
	register int ff_is_jam;
	register char *ff_cp = ff_c_buf_p;

	register FF_CHAR ff_c = 1;
	if ( ff_accept[ff_current_state] )
		{
		ff_last_accepting_state = ff_current_state;
		ff_last_accepting_cpos = ff_cp;
		}
	while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state )
		{
		ff_current_state = (int) ff_def[ff_current_state];
		if ( ff_current_state >= 160 )
			ff_c = ff_meta[(unsigned int) ff_c];
		}
	ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c];
	ff_is_jam = (ff_current_state == 159);

	return ff_is_jam ? 0 : ff_current_state;
	}


#ifndef FF_NO_UNPUT
#ifdef FF_USE_PROTOS
static void ffunput( int c, register char *ff_bp )
#else
static void ffunput( c, ff_bp )
int c;
register char *ff_bp;
#endif
	{
	register char *ff_cp = ff_c_buf_p;

	/* undo effects of setting up fftext */
	*ff_cp = ff_hold_char;

	if ( ff_cp < ff_current_buffer->ff_ch_buf + 2 )
		{ /* need to shift things up to make room */
		/* +2 for EOB chars. */
		register int number_to_move = ff_n_chars + 2;
		register char *dest = &ff_current_buffer->ff_ch_buf[
					ff_current_buffer->ff_buf_size + 2];
		register char *source =
				&ff_current_buffer->ff_ch_buf[number_to_move];

		while ( source > ff_current_buffer->ff_ch_buf )
			*--dest = *--source;

		ff_cp += (int) (dest - source);
		ff_bp += (int) (dest - source);
		ff_current_buffer->ff_n_chars =
			ff_n_chars = ff_current_buffer->ff_buf_size;

		if ( ff_cp < ff_current_buffer->ff_ch_buf + 2 )
			FF_FATAL_ERROR( "flex scanner push-back overflow" );
		}

	*--ff_cp = (char) c;


	fftext_ptr = ff_bp;
	ff_hold_char = *ff_cp;
	ff_c_buf_p = ff_cp;
	}
#endif	/* ifndef FF_NO_UNPUT */


#ifdef __cplusplus
static int ffinput()
#else
static int input()
#endif
	{
	int c;

	*ff_c_buf_p = ff_hold_char;

	if ( *ff_c_buf_p == FF_END_OF_BUFFER_CHAR )
		{
		/* ff_c_buf_p now points to the character we want to return.
		 * If this occurs *before* the EOB characters, then it's a
		 * valid NUL; if not, then we've hit the end of the buffer.
		 */
		if ( ff_c_buf_p < &ff_current_buffer->ff_ch_buf[ff_n_chars] )
			/* This was really a NUL. */
			*ff_c_buf_p = '\0';

		else
			{ /* need more input */
			int offset = ff_c_buf_p - fftext_ptr;
			++ff_c_buf_p;

			switch ( ff_get_next_buffer() )
				{
				case EOB_ACT_LAST_MATCH:
					/* This happens because ff_g_n_b()
					 * sees that we've accumulated a
					 * token and flags that we need to
					 * try matching the token before
					 * proceeding.  But for input(),
					 * there's no matching to consider.
					 * So convert the EOB_ACT_LAST_MATCH
					 * to EOB_ACT_END_OF_FILE.
					 */

					/* Reset buffer status. */
					ffrestart( ffin );

					/* fall through */

				case EOB_ACT_END_OF_FILE:
					{
					if ( ffwrap() )
						return EOF;

					if ( ! ff_did_buffer_switch_on_eof )
						FF_NEW_FILE;
#ifdef __cplusplus
					return ffinput();
#else
					return input();
#endif
					}

				case EOB_ACT_CONTINUE_SCAN:
					ff_c_buf_p = fftext_ptr + offset;
					break;
				}
			}
		}

	c = *(unsigned char *) ff_c_buf_p;	/* cast for 8-bit char's */
	*ff_c_buf_p = '\0';	/* preserve fftext */
	ff_hold_char = *++ff_c_buf_p;


	return c;
	}


#ifdef FF_USE_PROTOS
void ffrestart( FILE *input_file )
#else
void ffrestart( input_file )
FILE *input_file;
#endif
	{
	if ( ! ff_current_buffer )
		ff_current_buffer = ff_create_buffer( ffin, FF_BUF_SIZE );

	ff_init_buffer( ff_current_buffer, input_file );
	ff_load_buffer_state();
	}


#ifdef FF_USE_PROTOS
void ff_switch_to_buffer( FF_BUFFER_STATE new_buffer )
#else
void ff_switch_to_buffer( new_buffer )
FF_BUFFER_STATE new_buffer;
#endif
	{
	if ( ff_current_buffer == new_buffer )
		return;

	if ( ff_current_buffer )
		{
		/* Flush out information for old buffer. */
		*ff_c_buf_p = ff_hold_char;
		ff_current_buffer->ff_buf_pos = ff_c_buf_p;
		ff_current_buffer->ff_n_chars = ff_n_chars;
		}

	ff_current_buffer = new_buffer;
	ff_load_buffer_state();

	/* We don't actually know whether we did this switch during
	 * EOF (ffwrap()) processing, but the only time this flag
	 * is looked at is after ffwrap() is called, so it's safe
	 * to go ahead and always set it.
	 */
	ff_did_buffer_switch_on_eof = 1;
	}


#ifdef FF_USE_PROTOS
void ff_load_buffer_state( void )
#else
void ff_load_buffer_state()
#endif
	{
	ff_n_chars = ff_current_buffer->ff_n_chars;
	fftext_ptr = ff_c_buf_p = ff_current_buffer->ff_buf_pos;
	ffin = ff_current_buffer->ff_input_file;
	ff_hold_char = *ff_c_buf_p;
	}


#ifdef FF_USE_PROTOS
FF_BUFFER_STATE ff_create_buffer( FILE *file, int size )
#else
FF_BUFFER_STATE ff_create_buffer( file, size )
FILE *file;
int size;
#endif
	{
	FF_BUFFER_STATE b;

	b = (FF_BUFFER_STATE) ff_flex_alloc( sizeof( struct ff_buffer_state ) );
	if ( ! b )
		FF_FATAL_ERROR( "out of dynamic memory in ff_create_buffer()" );

	b->ff_buf_size = size;

	/* ff_ch_buf has to be 2 characters longer than the size given because
	 * we need to put in 2 end-of-buffer characters.
	 */
	b->ff_ch_buf = (char *) ff_flex_alloc( b->ff_buf_size + 2 );
	if ( ! b->ff_ch_buf )
		FF_FATAL_ERROR( "out of dynamic memory in ff_create_buffer()" );

	b->ff_is_our_buffer = 1;

	ff_init_buffer( b, file );

	return b;
	}


#ifdef FF_USE_PROTOS
void ff_delete_buffer( FF_BUFFER_STATE b )
#else
void ff_delete_buffer( b )
FF_BUFFER_STATE b;
#endif
	{
	if ( ! b )
		return;

	if ( b == ff_current_buffer )
		ff_current_buffer = (FF_BUFFER_STATE) 0;

	if ( b->ff_is_our_buffer )
		ff_flex_free( (void *) b->ff_ch_buf );

	ff_flex_free( (void *) b );
	}


#ifndef FF_ALWAYS_INTERACTIVE
#ifndef FF_NEVER_INTERACTIVE
extern int isatty FF_PROTO(( int ));
#endif
#endif

#ifdef FF_USE_PROTOS
void ff_init_buffer( FF_BUFFER_STATE b, FILE *file )
#else
void ff_init_buffer( b, file )
FF_BUFFER_STATE b;
FILE *file;
#endif


	{
	ff_flush_buffer( b );

	b->ff_input_file = file;
	b->ff_fill_buffer = 1;

#if FF_ALWAYS_INTERACTIVE
	b->ff_is_interactive = 1;
#else
#if FF_NEVER_INTERACTIVE
	b->ff_is_interactive = 0;
#else
	b->ff_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
#endif
#endif
	}


#ifdef FF_USE_PROTOS
void ff_flush_buffer( FF_BUFFER_STATE b )
#else
void ff_flush_buffer( b )
FF_BUFFER_STATE b;
#endif

	{
	if ( ! b )
		return;

	b->ff_n_chars = 0;

	/* We always need two end-of-buffer characters.  The first causes
	 * a transition to the end-of-buffer state.  The second causes
	 * a jam in that state.
	 */
	b->ff_ch_buf[0] = FF_END_OF_BUFFER_CHAR;
	b->ff_ch_buf[1] = FF_END_OF_BUFFER_CHAR;

	b->ff_buf_pos = &b->ff_ch_buf[0];

	b->ff_at_bol = 1;
	b->ff_buffer_status = FF_BUFFER_NEW;

	if ( b == ff_current_buffer )
		ff_load_buffer_state();
	}


#ifndef FF_NO_SCAN_BUFFER
#ifdef FF_USE_PROTOS
FF_BUFFER_STATE ff_scan_buffer( char *base, ff_size_t size )
#else
FF_BUFFER_STATE ff_scan_buffer( base, size )
char *base;
ff_size_t size;
#endif
	{
	FF_BUFFER_STATE b;

	if ( size < 2 ||
	     base[size-2] != FF_END_OF_BUFFER_CHAR ||
	     base[size-1] != FF_END_OF_BUFFER_CHAR )
		/* They forgot to leave room for the EOB's. */
		return 0;

	b = (FF_BUFFER_STATE) ff_flex_alloc( sizeof( struct ff_buffer_state ) );
	if ( ! b )
		FF_FATAL_ERROR( "out of dynamic memory in ff_scan_buffer()" );

	b->ff_buf_size = size - 2;	/* "- 2" to take care of EOB's */
	b->ff_buf_pos = b->ff_ch_buf = base;
	b->ff_is_our_buffer = 0;
	b->ff_input_file = 0;
	b->ff_n_chars = b->ff_buf_size;
	b->ff_is_interactive = 0;
	b->ff_at_bol = 1;
	b->ff_fill_buffer = 0;
	b->ff_buffer_status = FF_BUFFER_NEW;

	ff_switch_to_buffer( b );

	return b;
	}
#endif


#ifndef FF_NO_SCAN_STRING
#ifdef FF_USE_PROTOS
FF_BUFFER_STATE ff_scan_string( ffconst char *ff_str )
#else
FF_BUFFER_STATE ff_scan_string( ff_str )
ffconst char *ff_str;
#endif
	{
	int len;
	for ( len = 0; ff_str[len]; ++len )
		;

	return ff_scan_bytes( ff_str, len );
	}
#endif


#ifndef FF_NO_SCAN_BYTES
#ifdef FF_USE_PROTOS
FF_BUFFER_STATE ff_scan_bytes( ffconst char *bytes, int len )
#else
FF_BUFFER_STATE ff_scan_bytes( bytes, len )
ffconst char *bytes;
int len;
#endif
	{
	FF_BUFFER_STATE b;
	char *buf;
	ff_size_t n;
	int i;

	/* Get memory for full buffer, including space for trailing EOB's. */
	n = len + 2;
	buf = (char *) ff_flex_alloc( n );
	if ( ! buf )
		FF_FATAL_ERROR( "out of dynamic memory in ff_scan_bytes()" );

	for ( i = 0; i < len; ++i )
		buf[i] = bytes[i];

	buf[len] = buf[len+1] = FF_END_OF_BUFFER_CHAR;

	b = ff_scan_buffer( buf, n );
	if ( ! b )
		FF_FATAL_ERROR( "bad buffer in ff_scan_bytes()" );

	/* It's okay to grow etc. this buffer, and we should throw it
	 * away when we're done.
	 */
	b->ff_is_our_buffer = 1;

	return b;
	}
#endif


#ifndef FF_NO_PUSH_STATE
#ifdef FF_USE_PROTOS
static void ff_push_state( int new_state )
#else
static void ff_push_state( new_state )
int new_state;
#endif
	{
	if ( ff_start_stack_ptr >= ff_start_stack_depth )
		{
		ff_size_t new_size;

		ff_start_stack_depth += FF_START_STACK_INCR;
		new_size = ff_start_stack_depth * sizeof( int );

		if ( ! ff_start_stack )
			ff_start_stack = (int *) ff_flex_alloc( new_size );

		else
			ff_start_stack = (int *) ff_flex_realloc(
					(void *) ff_start_stack, new_size );

		if ( ! ff_start_stack )
			FF_FATAL_ERROR(
			"out of memory expanding start-condition stack" );
		}

	ff_start_stack[ff_start_stack_ptr++] = FF_START;

	BEGIN(new_state);
	}
#endif


#ifndef FF_NO_POP_STATE
static void ff_pop_state()
	{
	if ( --ff_start_stack_ptr < 0 )
		FF_FATAL_ERROR( "start-condition stack underflow" );

	BEGIN(ff_start_stack[ff_start_stack_ptr]);
	}
#endif


#ifndef FF_NO_TOP_STATE
static int ff_top_state()
	{
	return ff_start_stack[ff_start_stack_ptr - 1];
	}
#endif

#ifndef FF_EXIT_FAILURE
#define FF_EXIT_FAILURE 2
#endif

#ifdef FF_USE_PROTOS
static void ff_fatal_error( ffconst char msg[] )
#else
static void ff_fatal_error( msg )
char msg[];
#endif
	{
	(void) fprintf( stderr, "%s\n", msg );
	exit( FF_EXIT_FAILURE );
	}



/* Redefine ffless() so it works in section 3 code. */

#undef ffless
#define ffless(n) \
	do \
		{ \
		/* Undo effects of setting up fftext. */ \
		fftext[ffleng] = ff_hold_char; \
		ff_c_buf_p = fftext + n; \
		ff_hold_char = *ff_c_buf_p; \
		*ff_c_buf_p = '\0'; \
		ffleng = n; \
		} \
	while ( 0 )


/* Internal utility routines. */

#ifndef fftext_ptr
#ifdef FF_USE_PROTOS
static void ff_flex_strncpy( char *s1, ffconst char *s2, int n )
#else
static void ff_flex_strncpy( s1, s2, n )
char *s1;
ffconst char *s2;
int n;
#endif
	{
	register int i;
	for ( i = 0; i < n; ++i )
		s1[i] = s2[i];
	}
#endif

#ifdef FF_NEED_STRLEN
#ifdef FF_USE_PROTOS
static int ff_flex_strlen( ffconst char *s )
#else
static int ff_flex_strlen( s )
ffconst char *s;
#endif
	{
	register int n;
	for ( n = 0; s[n]; ++n )
		;

	return n;
	}
#endif


#ifdef FF_USE_PROTOS
static void *ff_flex_alloc( ff_size_t size )
#else
static void *ff_flex_alloc( size )
ff_size_t size;
#endif
	{
	return (void *) malloc( size );
	}

#ifdef FF_USE_PROTOS
static void *ff_flex_realloc( void *ptr, ff_size_t size )
#else
static void *ff_flex_realloc( ptr, size )
void *ptr;
ff_size_t size;
#endif
	{
	/* The cast to (char *) in the following accommodates both
	 * implementations that use char* generic pointers, and those
	 * that use void* generic pointers.  It works with the latter
	 * because both ANSI C and C++ allow castless assignment from
	 * any pointer type to void*, and deal with argument conversions
	 * as though doing an assignment.
	 */
	return (void *) realloc( (char *) ptr, size );
	}

#ifdef FF_USE_PROTOS
static void ff_flex_free( void *ptr )
#else
static void ff_flex_free( ptr )
void *ptr;
#endif
	{
	free( ptr );
	}

#if FF_MAIN
int main()
	{
	fflex();
	return 0;
	}
#endif
#line 386 "eval.l"


int ffwrap()
{
  /* MJT -- 13 June 1996
     Supplied for compatibility with
     pre-2.5.1 versions of flex which
     do not recognize %option noffwrap 
  */
  return(1);
}

/* 
   expr_read is lifted from old ftools.skel. 
   Now we can use any version of flex with
   no .skel file necessary! MJT - 13 June 1996

   keep a memory of how many bytes have been
   read previously, so that an unlimited-sized
   buffer can be supported. PDW - 28 Feb 1998
*/

static int expr_read(char *buf, int nbytes)
{
 int n;
 
 n = 0;
 if( !gParse.is_eobuf ) {
     do {
        buf[n++] = gParse.expr[gParse.index++];
       } while ((n<nbytes)&&(gParse.expr[gParse.index] != '\0'));
     if( gParse.expr[gParse.index] == '\0' ) gParse.is_eobuf = 1;
 }
 buf[n] = '\0';
 return(n);
}

int ffGetVariable( char *varName, FFSTYPE *thelval )
{
   int varNum, type;
   char errMsg[MAXVARNAME+25];

   varNum = find_variable( varName );
   if( varNum<0 ) {
      if( gParse.getData ) {
	 type = (*gParse.getData)( varName, thelval );
      } else {
	 type = pERROR;
	 gParse.status = PARSE_SYNTAX_ERR;
	 strcpy (errMsg,"Unable to find data: ");
	 strncat(errMsg, varName, MAXVARNAME);
	 ffpmsg (errMsg);
      }
   } else {
      /*  Convert variable type into expression type  */
      switch( gParse.varData[ varNum ].type ) {
      case LONG:
      case DOUBLE:   type =  COLUMN;  break;
      case BOOLEAN:  type = BCOLUMN;  break;
      case STRING:   type = SCOLUMN;  break;
      case BITSTR:   type =  BITCOL;  break;
      default:
	 type = pERROR;
	 gParse.status = PARSE_SYNTAX_ERR;
	 strcpy (errMsg,"Bad datatype for data: ");
	 strncat(errMsg, varName, MAXVARNAME);
	 ffpmsg (errMsg);
	 break;
      }
      thelval->lng = varNum;
   }
   return( type );
}

static int find_variable(char *varName)
{
   int i;
 
   if( gParse.nCols )
      for( i=0; i<gParse.nCols; i++ ) {
         if( ! strncasecmp(gParse.varData[i].name,varName,MAXVARNAME) ) {
            return( i );
         }
      }
   return( -1 );
}

#if defined(vms) || defined(__vms) || defined(WIN32) || defined(__WIN32__) || defined(macintosh)

/* ================================================================== */
/* A hack for nonunix machines, which lack strcasecmp and strncasecmp */
/* ================================================================== */

int strcasecmp(const char *s1, const char *s2)
{
   char c1, c2;

   for (;;) {
      c1 = toupper( *s1 );
      c2 = toupper( *s2 );

      if (c1 < c2) return(-1);
      if (c1 > c2) return(1);
      if (c1 == 0) return(0);
      s1++;
      s2++;
   }
}

int strncasecmp(const char *s1, const char *s2, size_t n)
{
   char c1, c2;

   for (; n-- ;) {
      c1 = toupper( *s1 );
      c2 = toupper( *s2 );

      if (c1 < c2) return(-1);
      if (c1 > c2) return(1);
      if (c1 == 0) return(0);
      s1++;
      s2++;
   }
   return(0);
}

#endif
