/*
*         OpenPBS (Portable Batch System) v2.3 Software License
* 
* Copyright (c) 1999-2000 Veridian Information Solutions, Inc.
* All rights reserved.
* 
* ---------------------------------------------------------------------------
* For a license to use or redistribute the OpenPBS software under conditions
* other than those described below, or to purchase support for this software,
* please contact Veridian Systems, PBS Products Department ("Licensor") at:
* 
*    www.OpenPBS.org  +1 650 967-4675                  sales@OpenPBS.org
*                        877 902-4PBS (US toll-free)
* ---------------------------------------------------------------------------
* 
* This license covers use of the OpenPBS v2.3 software (the "Software") at
* your site or location, and, for certain users, redistribution of the
* Software to other sites and locations.  Use and redistribution of
* OpenPBS v2.3 in source and binary forms, with or without modification,
* are permitted provided that all of the following conditions are met.
* After December 31, 2001, only conditions 3-6 must be met:
* 
* 1. Commercial and/or non-commercial use of the Software is permitted
*    provided a current software registration is on file at www.OpenPBS.org.
*    If use of this software contributes to a publication, product, or
*    service, proper attribution must be given; see www.OpenPBS.org/credit.html
* 
* 2. Redistribution in any form is only permitted for non-commercial,
*    non-profit purposes.  There can be no charge for the Software or any
*    software incorporating the Software.  Further, there can be no
*    expectation of revenue generated as a consequence of redistributing
*    the Software.
* 
* 3. Any Redistribution of source code must retain the above copyright notice
*    and the acknowledgment contained in paragraph 6, this list of conditions
*    and the disclaimer contained in paragraph 7.
* 
* 4. Any Redistribution in binary form must reproduce the above copyright
*    notice and the acknowledgment contained in paragraph 6, this list of
*    conditions and the disclaimer contained in paragraph 7 in the
*    documentation and/or other materials provided with the distribution.
* 
* 5. Redistributions in any form must be accompanied by information on how to
*    obtain complete source code for the OpenPBS software and any
*    modifications and/or additions to the OpenPBS software.  The source code
*    must either be included in the distribution or be available for no more
*    than the cost of distribution plus a nominal fee, and all modifications
*    and additions to the Software must be freely redistributable by any party
*    (including Licensor) without restriction.
* 
* 6. All advertising materials mentioning features or use of the Software must
*    display the following acknowledgment:
* 
*     "This product includes software developed by NASA Ames Research Center,
*     Lawrence Livermore National Laboratory, and Veridian Information 
*     Solutions, Inc.
*     Visit www.OpenPBS.org for OpenPBS software support,
*     products, and information."
* 
* 7. DISCLAIMER OF WARRANTY
* 
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT
* ARE EXPRESSLY DISCLAIMED.
* 
* IN NO EVENT SHALL VERIDIAN CORPORATION, ITS AFFILIATED COMPANIES, OR THE
* U.S. GOVERNMENT OR ANY OF ITS AGENCIES BE LIABLE FOR ANY DIRECT OR INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* 
* This license will be governed by the laws of the Commonwealth of Virginia,
* without reference to its choice of law rules.
*/
/*************************************************************
*      myname           Parser.b
*      created          7/2/1996
*      updated          12/20/1996
*      works            12/20/1996
*
*      designed			rrs/1996
*************************************************************/

/***********************************************************
*
*	               OPERATION OVERVIEW
*
* The Bison will generate a Parser that parses input
* in NASL language.
* The Scanner which resides in the other files is generated by Flex
* from the source file Lexer.fl.
*
************************************************************/

/***********************************************************
* 					SOFTWARE ENGINEERING METHODS
* The Compiler was designed as a collection of entities
* which communicate across well defined intefaces similar
* objects in C++.
* This approach allows independence in design, 
* implementation, and testing.
* each "object" in addition contains support routines for 
* self-diagnosis.
***********************************************************/
/* Libraries, Types, tokens, precedences */

%{
#include <stdio.h>
#include <setjmp.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "Parser.h"
#include "Semantic.h"
#include "CodeGen.h"
#include "af.h"

Np np;
extern int linenum;
extern char linebuf[];
extern jmp_buf begin;
extern int sizeStrcmp();
extern int sizeRangeStrcmp();
extern int strToInt();
extern double strToFloat();
int    intval;
int    intval2;
int    inLoop = 0;
int    inSwitch = 0;
char   bufstr[10];
char   bufstr2[300];
%}

%union
{
	struct MYTOK mytok;
}

/* tokens */
/*main*/
%token MAIN

/*data types simple*/
%token VOID
%token INT
%token FLOAT
%token DAYOFWEEK
%token DATETIME
%token STRING
%token FUN
%token SIZE

/*data types complex*/
%token SERVER
%token QUE
%token JOB
%token CNODE

/*data types qualifiers*/
%token SET
%token RANGE


/*constants*/
%token INTCONST
%token FLOATCONST
%token DAYOFWEEKCONST
%token STRINGCONST
%token SIZECONST
%token SERVERCONST
%token JOBCONST
%token QUECONST
%token CNODECONST
%token SETSERVERCONST
%token SETJOBCONST
%token SETQUECONST
%token SETCNODECONST

/*instruction keywords*/
%token WHILE
%token IF
%token ELSE
%token RETURN
%token PRINT
%token FOR
%token FOREACH
%token IN
%token SWITCH
%token CASE
%token BREAK
%token CONTINUE 
%token EXIT

/*compare etc*/
%token EQ
%token NEQ
%token LT
%token LE
%token GT
%token GE
%token MIN
%token MAX

/*logical*/
%token AND
%token OR

/*misc*/
%token '('
%token ')'
%token ';'
%token ':'
%token '|'
%token ','
%token '{'
%token '}'
%token '@'
%token POSTOP
%token DEFAULT


/*ident*/
%token IDENT


/*
 * Types of symbols
 */

/*types*/
/*main*/
%type <mytok> MAIN

/*data types simple*/
%type <mytok> VOID
%type <mytok> INT
%type <mytok> FLOAT
%type <mytok> DAYOFWEEK
%type <mytok> DATETIME
%type <mytok> STRING
%type <mytok> FUN
%type <mytok> SIZE


/*data types complex*/
%type <mytok> SERVER
%type <mytok> QUE
%type <mytok> JOB
%type <mytok> CNODE


/*data types qualifiers*/
%type <mytok> SET
%type <mytok> RANGE

/*constants*/
%type <mytok> INTCONST
%type <mytok> FLOATCONST
%type <mytok> DAYOFWEEKCONST
%type <mytok> STRINGCONST
%type <mytok> SIZECONST
%type <mytok> SERVERCONST
%type <mytok> JOBCONST
%type <mytok> QUECONST
%type <mytok> CNODECONST
%type <mytok> SETSERVERCONST
%type <mytok> SETJOBCONST
%type <mytok> SETQUECONST
%type <mytok> SETCNODECONST

/*instruction keywords*/
%type <mytok> WHILE
%type <mytok> IF
%type <mytok> ELSE
%type <mytok> RETURN
%type <mytok> PRINT
%type <mytok> FOR
%type <mytok> FOREACH
%type <mytok> IN
%type <mytok> SWITCH
%type <mytok> CASE
%type <mytok> BREAK
%type <mytok> CONTINUE
%type <mytok> EXIT



/*compare etc*/
%type <mytok> EQ
%type <mytok> NEQ
%type <mytok> LT
%type <mytok> LE
%type <mytok> GT
%type <mytok> GE
%type <mytok> MIN
%type <mytok> MAX


/*logical*/
%type <mytok> AND
%type <mytok> OR


/*vars*/
%type <mytok> var

/*ident*/
%type <mytok> IDENT

/*
misc
*/
%type <mytok> '{'
%type <mytok> '}'
%type <mytok> '('
%type <mytok> ')'
%type <mytok> ';'
%type <mytok> ':'
%type <mytok> '|'
%type <mytok> '@'
%type <mytok> ','
%type <mytok> POSTOP
%type <mytok> DEFAULT

%type <mytok> expr
%type <mytok> exprTerms
%type <mytok> consts
%type <mytok> intConst
%type <mytok> floatConst
%type <mytok> dataTypes
%type <mytok> dataTypesSimple
%type <mytok> dataTypesComplex
%type <mytok> dataTypesSet
%type <mytok> dataTypesRange
%type <mytok> funCall
%type <mytok> dayofweekConst
%type <mytok> datetimeConst
%type <mytok> stringConst
%type <mytok> sizeConst
%type <mytok> serverConst
%type <mytok> queConst
%type <mytok> jobConst
%type <mytok> cnodeConst
%type <mytok> setServerConst
%type <mytok> setQueConst
%type <mytok> setJobConst
%type <mytok> setCnodeConst
%type <mytok> cprOp
%type <mytok> constRange
%type <mytok> intConstRange
%type <mytok> floatConstRange
%type <mytok> dayofweekConstRange
%type <mytok> datetimeConstRange
%type <mytok> sizeConstRange
%type <mytok> arg
%type <mytok> lb
%type <mytok> rb
%type <mytok> comma
%type <mytok> colon
%type <mytok> pipe
%type <mytok> at


/* precedences */
%right '='
%left OR
%left AND
%left EQ NEQ
%left LT LE GT GE
%left '+' '-'
%left '*' '/' '%'
%right NOT POSTOP UPLUS UMINUS /* unary - */


%%
/* Rules */


prog:   	defs1 globAssign { CodeGenBuffSave("}");
				   CodeGenBuffSave("\n");
				   CodeGenBuffEmit();
				 }	mainProg {
							ParserCondPrint("prog"); 
							ParserCondPrint("\n***WHOLE PROGRAM PARSED OK***\n");

									}
		;

defs1:		/* lambda */		{
							ParserCondPrint("defs1");
							ParserCondPrint("\n***DEFS1 PARSED OK***\n");

						}
		| defs1 defFun		{
							ParserCondPrint("defs1");
						}
		| defs1 def		{
							ParserCondPrint("defs1");

						}
		;

globAssign:	/* lambda */		{
							ParserCondPrint("globAssign");

							CodeGenBuffSave("void sched_init()");
							CodeGenBuffSave("\n");
							CodeGenBuffSave("{");
							CodeGenBuffSave("\n");
						}
		| globAssign statAssign

mainProg:   	progHead blockWithDefs {
							ParserCondPrint("mainProg"); 
							ParserPutDF(1);
							ParserCondPrint("\n***MAIN PROGRAM PARSED OK***\n");
							ParserPutDF(0);
				

									}
		;


progHead:   	MAIN {
					ParserVarScopeIncr();
					CodeGenBuffSave("void sched_main");
					} lb rb {
							ParserCondPrint("progHead");

							$1.type = VOIDTYPE;
							np = NodeNew( (char *) $1.lexeme, $1.type, $1.line, ParserLevelGet(), YES);
							/*
							NodePrint(np);
							*/
							SymTabInsertFront(np);
							ParserCurrFunPtrPut(np);
									}
		;

blockWithDefs:  lcb defs 		{
							ParserCondPrint("blockWithDefs");
							
			} stats rcb	{
							ParserCondPrint("blockWithDefs");
								}
		;

block:		lcb stats rcb	{

							ParserCondPrint("block");
								}
		;


defs:	/*lambda*/		{
							ParserCondPrint("defs");

						}
		| defs def		{
							ParserCondPrint("defs");

						}
		;


def:	defSimple	{
								ParserCondPrint("def"); 

					}

		| defComplex	{
								ParserCondPrint("def"); 

					}


		| defSet	{
								ParserCondPrint("def"); 

					}

		| defRange	{
								ParserCondPrint("def"); 

					}
		;

/*all data types */

dataTypes:	dataTypesSimple	{
								ParserCondPrint("dataTypes"); 

					}

		| dataTypesComplex	{
								ParserCondPrint("dataTypes"); 

					}

		| dataTypesSet	{
								ParserCondPrint("dataTypes"); 

					}

		| dataTypesRange	{
								ParserCondPrint("dataTypes"); 

					}
		;

/*this will be done more elgantly; -- see statPrint*/
/*data types simple*/
dataTypesSimple:	INT 	{ 
								ParserCondPrint("dataTypesSimple"); 

								$$.type = INTTYPE; /*semantic type*/
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("int ");

					}

			
		|	VOID {
								ParserCondPrint("dataTypesSimple"); 
								$$.type = VOIDTYPE;	
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("void ");

					}

		|	FLOAT 	{ 
								ParserCondPrint("dataTypesSimple"); 
								$$.type = FLOATTYPE;	/*semantic type*/
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("double ");

					}


		|	DAYOFWEEK 	{ 
								ParserCondPrint("dataTypesSimple"); 
								$$.type = DAYOFWEEKTYPE;	/*semantic type*/
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("Dayofweek ");

					}


		|	DATETIME 	{ 
								ParserCondPrint("dataTypesSimple"); 
								$$.type = DATETIMETYPE;	/*semantic type*/
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("DateTime ");

					}


		|	STRING 	{ 
								ParserCondPrint("dataTypesSimple"); 
								$$.type = STRINGTYPE;	/*semantic type*/
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("char *");

					}
		|	SIZE 	{
								ParserCondPrint("dataTypesSimple"); 
								$$.type = SIZETYPE;	/*semantic type*/
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("Size ");

					}
		;


/*def data types simple*/
defSimple:	dataTypesSimple IDENT { 			$2.type = $1.type;
								if( $1.type == VOIDTYPE )
									SemanticErr(27);

								CodeGenBuffSave((char *)$2.lexeme);
								if( $2.type == STRINGTYPE ) {
									CodeGenBuffSave(" = NULLSTR");
								}


								} sc	{
								ParserCondPrint("defSimple"); 
								if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
									SemanticErr(7);	
								}
								np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
								/*
								NodePrint(np);
								*/
								SymTabInsertFront(np);

							}
		;


/*data types Complex*/
dataTypesComplex:	SERVER {
								ParserCondPrint("dataTypesComplex"); 
								$$.type = SERVERTYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("Server *");
					}

		|	QUE 	{ 
								ParserCondPrint("dataTypesComplex"); 
								$$.type = QUETYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("Que *");
					}

		|	JOB 	{ 
								ParserCondPrint("dataTypesComplex"); 
								$$.type = JOBTYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("Job *");
					}


		|	CNODE 	{ 
								ParserCondPrint("dataTypesComplex"); 
								$$.type = CNODETYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("CNode *");
					}

		;


/*def data types Complex*/
defComplex:	dataTypesComplex IDENT { 			$2.type = $1.type;
								CodeGenBuffSave((char *)$2.lexeme);
								switch($2.type) {
								  case SERVERTYPE:	
									CodeGenBuffSave(" = NOSERVER");
									break;
								  case QUETYPE:	
									CodeGenBuffSave(" = NOQUE");
									break;
								  case JOBTYPE:	
									CodeGenBuffSave(" = NOJOB");
									break;
								  case CNODETYPE:
									CodeGenBuffSave(" = NOCNODE");
									break;
								}
								} sc	{
								ParserCondPrint("defComplex"); 

								if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
									SemanticErr(7);	
								}

								np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
								/*
								NodePrint(np);
								*/
								SymTabInsertFront(np);
							}
		;



dataTypesSet:	SET SERVER {
								ParserCondPrint("dataTypesSet"); 
								$$.type = SERVERSETTYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("SetServer *");
					}

		|	SET QUE 	{ 
								ParserCondPrint("dataTypesSet"); 
								$$.type = QUESETTYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("SetQue *");
					}

		|	SET JOB 	{ 
								ParserCondPrint("dataTypesSet"); 
								$$.type = JOBSETTYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("struct SetJobElement *");
					}


		|	SET CNODE 	{ 
								ParserCondPrint("dataTypesSet"); 
								$$.type = CNODESETTYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("SetCNode *");
					}

		;


/*def data types Set*/
defSet:	dataTypesSet IDENT { $2.type = $1.type;
								CodeGenBuffSave((char *)$2.lexeme);
								switch($2.type) {
								  case SERVERSETTYPE:
									CodeGenBuffSave(" = EMPTYSETSERVER");
									break;
								  case QUESETTYPE:
									CodeGenBuffSave(" = EMPTYSETQUE");
									break;
								  case JOBSETTYPE:
									CodeGenBuffSave(" = EMPTYSETJOB");
									break;
								  case CNODESETTYPE:
									CodeGenBuffSave(" = EMPTYSETCNODE");
									break;
								}
					} sc	{
								ParserCondPrint("defSet"); 

								if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
									SemanticErr(7);	
								}

								np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
								/*
								NodePrint(np);
								*/
								SymTabInsertFront(np);
							}
		;


/*data types Range*/
dataTypesRange:	RANGE INT {
								ParserCondPrint("dataTypesRange"); 
								$$.type = INTRANGETYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("IntRange ");
					}

		|	RANGE FLOAT {
								ParserCondPrint("dataTypesRange"); 
								$$.type = FLOATRANGETYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("FloatRange ");
					}


		|	RANGE DAYOFWEEK {
								ParserCondPrint("dataTypesRange"); 
								$$.type = DAYOFWEEKRANGETYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("DayofweekRange ");
					}


		|	RANGE DATETIME {
								ParserCondPrint("dataTypesRange"); 
								$$.type = DATETIMERANGETYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("DateTimeRange ");
					}

		|	RANGE SIZE {
								ParserCondPrint("dataTypesRange"); 
								$$.type = SIZERANGETYPE;
								if( ParserLevelGet() == 0 )
									CodeGenBuffSave("static ");
								CodeGenBuffSave("SizeRange ");
					}
		;



/*def data types Range*/
defRange:	dataTypesRange IDENT { $2.type = $1.type;
								CodeGenBuffSave((char *)$2.lexeme);
						} sc	{
								ParserCondPrint("defRange"); 

								if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
									SemanticErr(7);	
								}

								np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
								/*
								NodePrint(np);
								*/
								SymTabInsertFront(np);
							}
		;


/*statements*/
stats:	/*lambda */		{

								ParserCondPrint("stats");
						}

		|	stats stat	{
								ParserCondPrint("stats");

						}
		;


stat:		statNop 	{ 
								ParserCondPrint("stat");
						}


		|	statExpression	{ 
			
								ParserCondPrint("stat");
		
						}

		|	statAssign	{ 
			
								ParserCondPrint("stat");
		
						}

		|	statPrint	{ 
								ParserCondPrint("stat");
						}

		|	statWhile	{
								ParserCondPrint("stat");
						}

		|	statContinue	{
								ParserCondPrint("stat");
						}

		|	statExit	{
								ParserCondPrint("stat");
						}

		|	statIf		{ 
								ParserCondPrint("stat");
						}


		|	statReturn		{ 
								ParserCondPrint("stat");
						}


		|	statFor		{ 
								ParserCondPrint("stat");
						}


		|	statForeach		{ 
								ParserCondPrint("stat");
						}


		|	statSwitch		{ 
								ParserCondPrint("stat");
						}


		|	statBreak		{ 
								ParserCondPrint("stat");
						}

		|	block		{ 
								ParserCondPrint("stat");
						}
		;


statNop:	sc			{
							/*NOT Much*/
								ParserCondPrint("statNop");
								SemanticStatNopCk();
						}
		;


statAssign: var eqs expr 		{
								if( $1.type == STRINGTYPE ) {
									CodeGenBuffSaveStrAssign();	
								}
					} sc {
								/*will have Sematic check case for each type*/
								ParserCondPrint("statAssign");

								SemanticStatAssignCk($1, $3);

								if( $1.type == STRINGTYPE && \
								    NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(),
											      (char *)$1.lexeme ) != NULL )
									SemanticErr(30);
							
								if( $1.type == STRINGTYPE ) {
									if( SymTabFindNodeByLexemeInLevel( (char *)$1.lexeme,
												  		0 ) == NULL ) {
										CodeGenBuffSave("varstrModScope(");
										CodeGenBuffSave((char *)$1.lexeme);
										CodeGenBuffSave(", ");
										sprintf(bufstr, "%d", ParserVarScopeGet());
										CodeGenBuffSave(bufstr);
										CodeGenBuffSave(");");
										CodeGenBuffSave("\n");
									}
									CodeGenBuffSave("varstrFreeByScope(-1);");
									CodeGenBuffSave("\n");
									CodeGenBuffEmit();
								} else if ( $1.type == QUETYPE ) {
									CodeGenBuffSave("mallocTableSafeModScope(");
									CodeGenBuffSave((char *)$1.lexeme);
									CodeGenBuffSave(", ");
									if( SymTabFindNodeByLexemeInLevel( (char *)$1.lexeme,
														0 )  != NULL ) {
										CodeGenBuffSave("0");
									} else {
										sprintf(bufstr, "%d", ParserVarScopeGet());
										CodeGenBuffSave(bufstr);
									}
									CodeGenBuffSave(");");
									CodeGenBuffSave("\n");

									CodeGenBuffSave("mallocTableFreeByScope(-1, QueFree);");
									CodeGenBuffSave("\n");
									CodeGenBuffEmit();
								}
					 }
			;


statExpression:	expr sc	{
							ParserCondPrint("statExpression");
							if( $1.type == STRINGTYPE ) {
								CodeGenBuffSave("varstrFreeByScope(-1);");
								CodeGenBuffSave("\n");
							} else if( $1.type == QUETYPE ) {
								CodeGenBuffSave("mallocTableFreeByScope(-1, QueFree);");
								CodeGenBuffSave("\n");
							}

						}
		;



		/*
		 * CodeGen will produce print stat based
		 * the type of var.
		 * See outline for CodeGenPrintVar() in CodeGen.fun.
		 * OK: all simple, Job, Que, Node
		 * OK: range of simples
		 * Not: Setof X
		 */
statPrint:	PRINT {
		} statPrintTail	{
							ParserCondPrint("statPrint");
								CodeGenBuffSave("printf(\"\\n\");");
								CodeGenBuffSave("\n");
								CodeGenBuffEmit();

								}
		;

statPrintTail:	lb var rb { 
							ParserCondPrint("statPrintTail");
							SemanticStatPrintTailCk($2);
							CodeGenStatPrintTail($2);
							}
							sc 
							{
							ParserCondPrint("statPrintTail");


								}
				|	lb consts rb {
							ParserCondPrint("statPrintTail");
							SemanticStatPrintTailCk($2);
							CodeGenStatPrintTail($2);
							}
							sc
							{
							ParserCondPrint("statPrintTail");

								}
				;


		/*make it block */
		/*block -> { stat } anyway */
		/*Ok: INT, Float */
		/*Semantic check*/
statWhile:	statWhileHead block	{
							ParserCondPrint("statWhile");
							inLoop--;
									
									}
		;


statWhileHead:	WHILE { 
						CodeGenBuffSave("while");
						inLoop++;
	} lb expr rb {
							ParserCondPrint("statWhileHead");
							SemanticStatWhileHeadCk($4);
									
									}
		;


		/*make it block */
		/*block -> { stat } anyway */
		/*Ok: INT, Float */
		/*Semantic check*/
statIf:	statIfHead block 	{
							ParserCondPrint("statIf");

								}
	| statIfHead block ELSE {
							CodeGenBuffSave("else");

		} block		{
							ParserCondPrint("statIf");

								}
		;


statIfHead:	IF { 
					CodeGenBuffSave("if");
	} lb expr rb {
							ParserCondPrint("statIfHead");
							SemanticStatIfHeadCk($4);
									
									}
		;



		/*Ok: all simple */
		/*OK: Node, Que, Job*/
		/*Semantic check*/
statReturn:  RETURN {
					CodeGenBuffSave("return");
		} statReturnTail {
					ParserCondPrint("statReturn");
					}

				;	

		/*Ok: INT, Float */
		/*Semantic check*/
statReturnTail:	lb var rb { 		ParserCondPrint("statReturnTail");
					SemanticStatReturnTailCk($2);
					if( $2.type == STRINGTYPE && \
					    NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$2.lexeme ) == NULL ) {
						if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, 0 ) == NULL ) {
							CodeGenBuffSaveBefore("varstrModScope(", "return", CodeGenLastDef("return"));
							CodeGenBuffSaveAfter((char *)$2.lexeme, "varstrModScope(", 
											CodeGenLastDef("varstrModScope("));
							CodeGenBuffSaveAfter("\n", (char *)$2.lexeme, 
											CodeGenLastDef((char *)$2.lexeme));
							CodeGenBuffSaveAfter(", -1);", (char *)$2.lexeme, 
											CodeGenLastDef((char *)$2.lexeme));
						}


					} else if( $2.type == QUETYPE ) {
						if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, 0 ) == NULL ) {
							CodeGenBuffSaveBefore("mallocTableSafeModScope(", "return", CodeGenLastDef("return"));
							CodeGenBuffSaveAfter((char *)$2.lexeme, "mallocTableSafeModScope(", 
											CodeGenLastDef("mallocTableSafeModScope("));
							CodeGenBuffSaveAfter("\n", (char *)$2.lexeme,
											CodeGenLastDef((char *)$2.lexeme));
							CodeGenBuffSaveAfter(", -1);", (char *)$2.lexeme, 
											CodeGenLastDef((char *)$2.lexeme));
						}

					}
					/* level 1 is where all local variables are declared */
					if( SymTabFindAnyNodeInLevelOfType( 1, STRINGTYPE ) != NULL ) {
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSaveBefore("varstrFreeByScope(", "return",
											CodeGenLastDef("return"));
						CodeGenBuffSaveAfter(bufstr, "varstrFreeByScope(",
											CodeGenLastDef("varstrFreeByScope("));
						CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr));
					}

					if( SymTabFindAnyNodeInLevelOfType( 1, QUETYPE ) != NULL ) {
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSaveBefore("mallocTableFreeByScope(", "return",
											CodeGenLastDef("return"));
						CodeGenBuffSaveAfter(bufstr, "mallocTableFreeByScope(",
										   CodeGenLastDef("mallocTableFreeByScope("));
						CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(", QueFree", bufstr, CodeGenLastDef(bufstr));
					}	
						

			  } ';' {
					ParserCondPrint("statReturnTail");
					CodeGenBuffSave(";");
					CodeGenBuffSave("\n");

							}	

			|	lb consts rb {
					ParserCondPrint("statReturnTail");
					/* Let's allow a constant string value return
					if($2.type == STRINGTYPE)
						SemanticErr(29);
					*/
					SemanticStatReturnTailCk($2);
					if( SymTabFindAnyNodeInLevelOfType( 1, STRINGTYPE ) != NULL ) {
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSaveBefore("varstrFreeByScope(", "return", CodeGenLastDef("return"));
						CodeGenBuffSaveAfter(bufstr, "varstrFreeByScope(",
										CodeGenLastDef("varstrFreeByScope("));
						CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr));
					}

					if( SymTabFindAnyNodeInLevelOfType( 1, QUETYPE ) != NULL ) {
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSaveBefore("mallocTableFreeByScope(", "return", CodeGenLastDef("return"));
						CodeGenBuffSaveAfter(bufstr, "mallocTableFreeByScope(",
										CodeGenLastDef("mallocTableFreeByScope("));
						CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(", QueFree", bufstr, CodeGenLastDef(bufstr));
					}

				} ';' {
					ParserCondPrint("statReturnTail");
					CodeGenBuffSave(";");
					CodeGenBuffSave("\n");
				}
			|	'(' ')' {
					ParserCondPrint("statReturnTail");
					if( (np = ParserCurrFunPtrGet()) == NULL )
                                		SemanticErr(2);

                        		if( NodeGetType(np) != VOIDTYPE )
                                		SemanticErr(11);

					if( SymTabFindAnyNodeInLevelOfType( 1, STRINGTYPE ) != NULL ) {
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSaveBefore("varstrFreeByScope(", "return", CodeGenLastDef("return"));
						CodeGenBuffSaveAfter(bufstr, "varstrFreeByScope(",
										CodeGenLastDef("varstrFreeByScope("));
						CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr));
					}

					if( SymTabFindAnyNodeInLevelOfType( 1, QUETYPE ) != NULL ) {
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSaveBefore("mallocTableFreeByScope(", "return", CodeGenLastDef("return"));
						CodeGenBuffSaveAfter(bufstr, "mallocTableFreeByScope(",
										CodeGenLastDef("mallocTableFreeByScope("));
						CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(", QueFree", bufstr, CodeGenLastDef(bufstr));
					}


				} ';' {
					ParserCondPrint("statReturnTail");
					CodeGenBuffSave(";");
					CodeGenBuffSave("\n");
				}

		;


		/*make it block */
		/*block -> { stat } anyway */
		/*Ok: INT, Float */
		/*Semantic check*/
statFor:	statForHead  block {
					ParserCondPrint("statFor");
					inLoop--;

							}	
		;


statForHead:	FOR {
						CodeGenBuffSave("for");
						inLoop++;
				} lb statForAssign ';'	{
						ParserCondPrint("statForHead");
						CodeGenBuffSave("; ");
				
				} var cprOp expr ';'	{
						ParserCondPrint("statForHead");
						CodeGenBuffSave("; ");
				} statForAssign rb {
							ParserCondPrint("statForHead");
							SemanticStatForHeadCk($7, $9);
									
				}
		;

statForAssign:  var eqs expr 	{
					ParserCondPrint("statForAssign");
					SemanticStatForAssignCk($1, $3);
				}
		|	var POSTOP	{
					ParserCondPrint("statForAssign");
					SemanticStatForPostAssignCk($1);
					CodeGenBuffSave((char *)$2.lexeme);
				}
		;

cprOp:	LE {
					ParserCondPrint("cprOp");

					CodeGenBuffSave(" <= ");

							}	
		|	LT {
					ParserCondPrint("cprOp");

					CodeGenBuffSave(" < ");

							}	
		|	GE {
					ParserCondPrint("cprOp");

					CodeGenBuffSave( " >= ");

							}	
		|	GT {
					ParserCondPrint("cprOp");

					CodeGenBuffSave(" > ");

							}	
		|	EQ {
					ParserCondPrint("cprOp");

					CodeGenBuffSave(" == ");

							}	
		|	NEQ {
					ParserCondPrint("cprOp");

					CodeGenBuffSave(" != ");

							}	
		;


		/*make it block */
		/*block -> { stat } anyway */
		/*
		 * OK:q,j,n,cpu in JOBSET, QUESET, NODESET, CPUSET.
		 * OK: int, float, dayofweek, date, time in RANGE of X.
		 */
statForeach:	statForeachHead block {
					ParserCondPrint("statForeach");
					inLoop--;

							}	
		;


statForeachHead:	FOREACH { 
					inLoop++;
		} lb var IN var rb {
					ParserCondPrint("statForeachHead");
					SemanticStatForeachHeadCk($4, $6);
					CodeGenBuffSaveForeach($4, $6);

							}
		;


			/*semantic check*/
			/*
			 * allow var int, float, dayofwekk, date, time.
			 * Range int, float, dayofweek, date, time
			 *
			 */
statSwitch:	caseSwitchHead '{' { ParserLevelIncr(); } caseList defCase '}' {
					SymTabDeleteLevel(ParserLevelGet());
					ParserLevelDecr();
					ParserCondPrint("statSwitch");
					inSwitch--;
					/* delete remaining switch if any */
					CodeGenBuffDelete("switch", CodeGenLastDef("switch"));


				}
		;


			/*semantic check*/
			/*
			 * allow var int, float, dayofwekk, date, time.
			 * Range int, float, dayofweek, date, time
			 *
			 */
caseSwitchHead:	SWITCH lb var rb {
					inSwitch++;
					ParserCondPrint("caseSwitchHead");
					if( $3.type == VOIDTYPE )
						SemanticErr(1);
					ParserCurrSwitchVarPut($3);
					CodeGenBuffClear();
					CodeGenBuffSave("switch");
							}	
		;


caseList:	/*lambda*/	{
					ParserCondPrint("caseList");

						}

	|	caseList caseElement	{
					ParserCondPrint("caseList");

						}
	;

defCase:	/* lambda */		{
					ParserCondPrint("defCase");
						}
	|	DEFAULT ':' 		{
					ParserCondPrint("defCase");
					intval = CodeGenLastDef("switch");
					if( intval == 0 )
						CodeGenBuffSave("else");
					else {
						CodeGenBuffDelete("switch", intval);
						CodeGenBuffSave("if(1)");
					}	
			} 	block	{
					ParserCondPrint("defCase");
						}
	;

		/*
		 * need two types of elt.
		 * FirstCaseElt & NextCaseElt to include "else" in front.
		 *
		 * Alternate need typicalElt (has trailing else), and lastElt (no else).
		 */
		/*make it block */
		/*block -> { stat } anyway */
caseElement:	caseElementHead block 	{
					ParserCondPrint("caseElement");

							}	
		;

		/*
		 * need two types of elt.
		 * FirstCaseElt & NextCaseElt to include "else" in front.
		 *
		 * Alternate need typicalElt (has trailing else), and lastElt (no else).
		 */
		/*make it block */
		/*block -> { stat } anyway */
caseElementHead:	CASE intConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");
					
					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());


						}

		|	CASE floatConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());

							}	

		|	CASE dayofweekConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());

							}	

		|	CASE datetimeConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);
					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());

							}	
		|	CASE sizeConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeAndTypeInLevel( (char *)$2.lexeme, ParserLevelGet(), SIZETYPE, sizeStrcmp ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());
							}	

		|	CASE stringConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());

							}

		|	CASE serverConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());

							}
		|	CASE queConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());

							}
		|	CASE jobConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());

							}
		|	CASE cnodeConst ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseTypeCk($2);

					if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitch(ParserCurrSwitchVarGet());

							}
		|	CASE IN constRange ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseInTypeCk($3);

					if( $3.type == SIZERANGETYPE ) {
						if( SymTabFindNodeByLexemeAndTypeInLevel( (char *)$3.lexeme, ParserLevelGet(), SIZERANGETYPE, sizeRangeStrcmp ) != NULL ) {
							SemanticErr(12);
						}
					} else {
						if( SymTabFindNodeByLexemeInLevel( (char *)$3.lexeme, ParserLevelGet() ) != NULL ) {
							SemanticErr(12);	
						}
					}
					np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);
					CodeGenBuffSaveSwitchIn(ParserCurrSwitchVarGet(), $3);

							}	

		/*
		 * Use semantics cases distinguish betw Set & Range.
		 * To have seperate rule for Set & Range creates red/red conf.
		 */


		/*
		 * We **only** have var IN RANGE. (the only var permitted).
		 * Use Semantics to check Range type.
		 * Maybe, const Range also.
		 */
		|	CASE IN var ':' {
					ParserCondPrint("caseElementHead");
					ParserCondPrint(":");

					SemanticCaseInTypeCk($3);

					if( SymTabFindNodeByLexemeInLevel( (char *)$3.lexeme, ParserLevelGet() ) != NULL ) {
						SemanticErr(12);	
					}
					np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/
					SymTabInsertFront(np);

					SemanticCaseInVarCk($3);
					CodeGenBuffSaveSwitchIn(ParserCurrSwitchVarGet(), $3);

							}	
		;


		/*break*/
statBreak:	BREAK ';'	{
					ParserCondPrint("statBreak");
					if( !inLoop )
						SemanticErr(14); 

					CodeGenBuffSave((char *)$1.lexeme);
					CodeGenBuffSave(";");
					CodeGenBuffSave("\n");
					CodeGenBuffEmit();
						
						}
		;

statContinue:	CONTINUE ';'	{
					ParserCondPrint("statContinue");
					if( !inLoop )
						SemanticErr(15); 

					CodeGenBuffSave((char *)$1.lexeme);
					CodeGenBuffSave(";");
					CodeGenBuffSave("\n");
					CodeGenBuffEmit();
						}
		;

statExit:	EXIT lb intConst rb ';'	{
					ParserCondPrint("statExit");

					CodeGenBuffSaveBefore("exit", "(", CodeGenLastDef("("));
					CodeGenBuffSave(";");
					CodeGenBuffSave("\n");

					if( SymTabFindAnyNodeInLevelOfType( 1, STRINGTYPE ) != NULL ) {
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSaveBefore("varstrFreeByScope(", "exit", CodeGenLastDef("exit"));
						CodeGenBuffSaveAfter(bufstr, "varstrFreeByScope(",
									CodeGenLastDef("varstrFreeByScope("));
						CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr));
					}

					if( SymTabFindAnyNodeInLevelOfType( 1, QUETYPE ) != NULL ) {
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSaveBefore("mallocTableFreeByScope(", "exit", CodeGenLastDef("exit"));
						CodeGenBuffSaveAfter(bufstr, "mallocTableFreeByScope(",
										CodeGenLastDef("mallocTableFreeByScope("));
						CodeGenBuffSaveAfter("\n", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(");", bufstr, CodeGenLastDef(bufstr));
						CodeGenBuffSaveAfter(", QueFree", bufstr, CodeGenLastDef(bufstr));
					}

						}
		;

		/*param lists*/
		/*can be almost any type, int, Range of int, ptrToFun, etc */
		/* Not Set. Use global Set var if needed. */
		/* Semantics analyser check valid args */
params:	/*lambda*/		{
					ParserCondPrint("params");
					CodeGenBuffDelete("static ", CodeGenLastDef("static "));
						}

		|	paramDeclare moreParams	{
					ParserCondPrint("params");
					CodeGenBuffDelete("static ", CodeGenLastDef("static "));

						}
		;


		/* Prototype definition*/
		/* This is serves fun prototype and also fun definition.*/
		/* They are handled different */
		/* All funs must have fun prototype.*/
		/* NASL funs will be defined in NASL prog.*/
		/* Some funs will be defined in the support.*/
		/*
		 * Ok: Simple, Complex, Range, funCall
		 * Ok: Cpr types: LE, MAX, etc
		 * Not: Set of x.
		 */
		/*problem how to specify argument that is a ptr fun */
		/*need fun type*/
		/*but all (almost) funs are different type -- leave that to
		semantic analyser*/
		/* Check params of use vs declare at first level of fun.
		 For now fun as param, verify sematics only ret type. */

		/*param declare pair*/	
paramDeclare:	dataTypes IDENT	{ 
					ParserCondPrint("paramDeclare");
					/*not here PPT($1) */
					$2.type = $1.type;


					if( NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$2.lexeme ) != NULL ) {
						SemanticErr(10);
					}
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					/*
					NodePrint(np);
					*/

					NodePutLevel(np, 1);
					/* prototyping: needed to check funCall against definition */
					SymTabParamLink(ParserCurrFunPtrGet(), np);
					/* create another node for semantic checking of undefined variables or redeclarations */
					np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), NO);
					NodePutLevel(np, 1);
					SymTabInsertFront(np);

					NodeParamCntIncr(ParserCurrFunPtrGet());
					CodeGenBuffSave((char *)$2.lexeme);

							}

			|	FUN	 dataTypesSimple IDENT	{ 
					ParserCondPrint("paramDeclare");
					$3.type = $2.type;

					if( NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$3.lexeme ) != NULL ) {
						SemanticErr(10);	
					}
					np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES);
					/*
					NodePrint(np);
					*/

					NodePutLevel(np, 1);
					/* prototyping: needed to check funCall against definition */
					SymTabParamLink(ParserCurrFunPtrGet(), np);
					/* create another node for semantic checking of undefined variables or redeclarations */
					np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES);
					NodePutLevel(np, 1);
					SymTabInsertFront(np);

					NodeParamCntIncr(ParserCurrFunPtrGet());
					CodeGenBuffSave("(*");
					CodeGenBuffSave((char *)$3.lexeme);
					CodeGenBuffSave(")()");

							}

			|	FUN	 dataTypesComplex IDENT	{ 
					ParserCondPrint("paramDeclare");
					$3.type = $2.type;

					if( NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$3.lexeme ) != NULL ) {
						SemanticErr(10);	
					}
					np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES);
					/*
					NodePrint(np);
					*/

					NodePutLevel(np, 1);
					/* prototyping: needed to check funCall against definition */
					SymTabParamLink(ParserCurrFunPtrGet(), np);
					/* create another node for semantic checking of undefined variables or redeclarations */
					np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES);
					NodePutLevel(np, 1);
					SymTabInsertFront(np);

					NodeParamCntIncr(ParserCurrFunPtrGet());
					CodeGenBuffSave("(*");
					CodeGenBuffSave((char *)$3.lexeme);
					CodeGenBuffSave(")()");

							}

			|	FUN	 dataTypesSet IDENT	{ 
					ParserCondPrint("paramDeclare");
					$3.type = $2.type;


					if( NodeFunDescrFindByLexeme( ParserCurrFunPtrGet(), (char *)$3.lexeme ) != NULL ) {
						SemanticErr(10);	
					}
					np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES);
					/*
					NodePrint(np);
					*/

					NodePutLevel(np, 1);
					/* prototyping: needed to check funCall against definition */
					SymTabParamLink(ParserCurrFunPtrGet(), np);
					/* create another node for semantic checking of undefined variables or redeclarations */
					np = NodeNew( (char *) $3.lexeme, $3.type, $3.line, ParserLevelGet(), YES);
					NodePutLevel(np, 1);
					SymTabInsertFront(np);

					NodeParamCntIncr(ParserCurrFunPtrGet());
					CodeGenBuffSave("(*");
					CodeGenBuffSave((char *)$3.lexeme);
					CodeGenBuffSave(")()");

							}
			;


moreParams:	/*lambda*/		{
					ParserCondPrint("moreParams");
					CodeGenBuffDelete("static ", CodeGenLastDef("static "));

							}

			| comma {
					ParserCondPrint(",");
			} paramDeclare moreParams	{
								ParserCondPrint("moreParams");
								CodeGenBuffDelete("static ", CodeGenLastDef("static "));

							}
			;


			/*Semantic must check ADT validity of op on type*/
			/* In general, verify binary arith
			 * both operands of int or float.
			 */
			/*arithmetic*/
expr:		expr '+' { 				ParserCondPrint("+");
			   				if( $1.type == SIZETYPE )
								CodeGenBuffSaveSpecOper("sizeAdd( ");
			   				else if( $1.type == STRINGTYPE )
								CodeGenBuffSaveSpecOper("strCat( ");
							else
			        				CodeGenBuffSave(" + ");
						} expr	{

							ParserCondPrint("expr");
							SemanticStatPlusExprCk($1, $4);

							if( $1.type == FLOATTYPE || $4.type == FLOATTYPE )
								$$.type = FLOATTYPE;
							else
								$$.type = $1.type;

							if( $1.type == SIZETYPE || $1.type == STRINGTYPE )
								CodeGenBuffSave(" )");
							}

		|	expr '-' { 			ParserCondPrint("-");
			   				if( $1.type == SIZETYPE )
								CodeGenBuffSaveSpecOper("sizeSub( ");
							else
								CodeGenBuffSave(" - ");

						} expr	{
							ParserCondPrint("expr");
							SemanticStatMinusExprCk($1, $4);

							if( $1.type == FLOATTYPE || $4.type == FLOATTYPE )
								$$.type = FLOATTYPE;
							else
								$$.type = $1.type;

							if( $1.type == SIZETYPE )
								CodeGenBuffSave(" )");
							}

		|	expr '*' { 			ParserCondPrint("*");
			   				if( $1.type == SIZETYPE )
								CodeGenBuffSaveSpecOper("sizeMul( ");
							else
								CodeGenBuffSave(" * ");

						} expr	{
							ParserCondPrint("expr");
							SemanticStatMultDivExprCk($1, $4);
							
							if( $1.type == FLOATTYPE || $4.type == FLOATTYPE )
								$$.type = FLOATTYPE;
							else
								$$.type = $1.type;

							if( $1.type == SIZETYPE )
								CodeGenBuffSave(" )");
							}

		|	expr '/' { 			ParserCondPrint("/");
			   				if( $1.type == SIZETYPE )
								CodeGenBuffSaveSpecOper("sizeDiv( ");
							else
								CodeGenBuffSave(" / ");
						} expr	{
							ParserCondPrint("expr");
							SemanticStatMultDivExprCk($1, $4);
							
							if( $1.type == FLOATTYPE || $4.type == FLOATTYPE )
								$$.type = FLOATTYPE;
							else
								$$.type = $1.type;

							if( $1.type == SIZETYPE )
								CodeGenBuffSave(" )");
							}

		|	expr '%' { 			ParserCondPrint("%");
							CodeGenBuffSave(" % ");
						} expr	{ $$.type = $1.type;
							ParserCondPrint("expr");
							SemanticStatModulusExprCk($1, $4);
							}

			/* For UMINUS and UPLUS, put an enclosing '()' during CodeGen (i.e. -5 should be written as (-5) */ 
			/*			another trick is to start with a space...'-6' should be ' -6' */
			/*			this is needed to disambiguate. Some C compiler will accept 6+ +3, */
			/*			6+(+3) but not 6++3 */ 
		|	'-' { 				ParserCondPrint("-");
							CodeGenBuffSave("-");
						} expr %prec UMINUS	{ $$.type = $3.type;
							ParserCondPrint("expr");
							SemanticStatUnaryExprCk($3);

							if( $3.type == SIZETYPE ) {
								CodeGenBuffSaveAfter("sizeUminus(", "-", CodeGenLastDef("-"));
								CodeGenBuffSave(")");
								CodeGenBuffDelete("-", CodeGenLastDef("-"));
							}
							}

			/* a UPLUS is needed to balance UMINUS and to resolve i=i+1 */
		|	'+' { 				ParserCondPrint("+");
							CodeGenBuffSave("+");
						} expr %prec UPLUS	{ $$.type = $3.type;
							ParserCondPrint("expr");
							SemanticStatUnaryExprCk($3);

							if( $3.type == SIZETYPE )
								CodeGenBuffDelete("+", CodeGenLastDef("+"));
							}

			/*compares*/
			/* simple operands int, float, strings.
			 * complex types, Job j, if (j == NULL).
			 */
		|	expr EQ { 			ParserCondPrint("EQ");
							switch($1.type) {
							  case DATETIMETYPE:
								CodeGenBuffSaveSpecOper("datetimecmp( ");
								break;
							  case STRINGTYPE:
								CodeGenBuffSaveSpecOper("STRCMP( ");
								CodeGenBuffSave(" ==, ");
								break;
							  case SIZETYPE:
								CodeGenBuffSaveSpecOper("sizecmp( ");
								break;
							  default: 
								CodeGenBuffSave(" == ");
							}
						} expr	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatCompExprCk($1, $4);
							
							if( $1.type == DATETIMETYPE || \
							    $1.type == SIZETYPE ) {
								CodeGenBuffSave(" )");
								CodeGenBuffSave(" == 0");
							} else if( $1.type == STRINGTYPE ) {
								CodeGenBuffSave(" )");
							}
						}

		|	expr NEQ { 			ParserCondPrint("NEQ");
							switch($1.type) {
							  case DATETIMETYPE:
								CodeGenBuffSaveSpecOper("datetimecmp( ");
								break;
							  case STRINGTYPE:
								CodeGenBuffSaveSpecOper("STRCMP( ");
								CodeGenBuffSave(" !=, ");
								break;
							  case SIZETYPE:
								CodeGenBuffSaveSpecOper("sizecmp( ");
								break;
							  default: 
								CodeGenBuffSave(" != ");
							}
						} expr	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatCompExprCk($1, $4);
							if( $1.type == DATETIMETYPE || \
							    $1.type == SIZETYPE ) {
								CodeGenBuffSave(" )");
								CodeGenBuffSave(" != 0");
							} else if( $1.type == STRINGTYPE ) {
								CodeGenBuffSave(" )");
							}
						}

		|	expr LT { 			ParserCondPrint("LT");
							switch($1.type) {
							  case DATETIMETYPE:
								CodeGenBuffSaveSpecOper("datetimecmp( ");
								break;
							  case STRINGTYPE:
								CodeGenBuffSaveSpecOper("STRCMP( ");
								CodeGenBuffSave(" <, ");
								break;
							  case SIZETYPE:
								CodeGenBuffSaveSpecOper("sizecmp( ");
								break;
							  default: 
								CodeGenBuffSave(" < ");
							}
						} expr	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatCompExprCk($1, $4);
							if( $1.type == DATETIMETYPE || \
							    $1.type == SIZETYPE ) {
								CodeGenBuffSave(" )");
								CodeGenBuffSave(" < 0");
							} else if( $1.type == STRINGTYPE ) {
								CodeGenBuffSave(" )");
							}
						}
							

		|	expr LE { 			ParserCondPrint("LE");
							switch($1.type) {
							  case DATETIMETYPE:
								CodeGenBuffSaveSpecOper("datetimecmp( ");
								break;
							  case STRINGTYPE:
								CodeGenBuffSaveSpecOper("STRCMP( ");
								CodeGenBuffSave(" <=, ");
								break;
							  case SIZETYPE:
								CodeGenBuffSaveSpecOper("sizecmp( ");
								break;
							  default: 
								CodeGenBuffSave(" <= ");
							}
						} expr	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatCompExprCk($1, $4);
							if( $1.type == DATETIMETYPE || \
							    $1.type == SIZETYPE ) {
								CodeGenBuffSave(" )");
								CodeGenBuffSave(" <= 0");
							} else if( $1.type == STRINGTYPE ) {
								CodeGenBuffSave(" )");
							}
							
						}

		|	expr GT { 			ParserCondPrint("GT");
							switch($1.type) {
							  case DATETIMETYPE:
								CodeGenBuffSaveSpecOper("datetimecmp( ");
								break;
							  case STRINGTYPE:
								CodeGenBuffSaveSpecOper("STRCMP( ");
								CodeGenBuffSave(" >, ");
								break;
							  case SIZETYPE:
								CodeGenBuffSaveSpecOper("sizecmp( ");
								break;
							  default: 
								CodeGenBuffSave(" > ");
							}
						} expr	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatCompExprCk($1, $4);
							if( $1.type == DATETIMETYPE || \
							    $1.type == SIZETYPE ) {
								CodeGenBuffSave(" )");
								CodeGenBuffSave(" > 0");
							} else if( $1.type == STRINGTYPE ) {
								CodeGenBuffSave(" )");
							}
							
						}


		|	expr GE { 			ParserCondPrint("GE");
							switch($1.type) {
							  case DATETIMETYPE:
								CodeGenBuffSaveSpecOper("datetimecmp( ");
								break;
							  case STRINGTYPE:
								CodeGenBuffSaveSpecOper("STRCMP( ");
								CodeGenBuffSave(" >=, ");
								break;
							  case SIZETYPE:
								CodeGenBuffSaveSpecOper("sizecmp( ");
								break;
							  default: 
								CodeGenBuffSave(" >= ");
							}
						} expr	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatCompExprCk($1, $4);
							if( $1.type == DATETIMETYPE   || \
							    $1.type == SIZETYPE ) {
								CodeGenBuffSave(" )");
								CodeGenBuffSave(" >= 0");
							} else if( $1.type == STRINGTYPE ) {
								CodeGenBuffSave(" )");
							}
							
						}

		|	expr AND { ParserCondPrint("AND"); CodeGenBuffSave(" && "); } expr	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatAndOrExprCk($1, $4);
							
							}

		|	expr OR { ParserCondPrint("OR"); CodeGenBuffSave(" || "); } expr	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatAndOrExprCk($1, $4);
							
							}

		|	'!' { ParserCondPrint("!"); CodeGenBuffSave("!"); } expr %prec NOT	{ $$.type = INTTYPE;
							ParserCondPrint("expr");
							SemanticStatNotExprCk($3);
							
							}

		|	var POSTOP { ParserCondPrint("POSTOP");
				     CodeGenBuffSave((char *)$2.lexeme);
				     $$.type = $1.type;
				     ParserCondPrint("expr");
				     SemanticStatPostOpExprCk($1);
							}
		|   	lb expr rb	{ $$.type = $2.type;
							ParserCondPrint("expr");

							}
		|	exprTerms	{ $$.type = $1.type;
							ParserCondPrint("expr");
							/* no need to xfer type -- auto --confired*/
							
							}
		;



exprTerms: 		consts		{ $$.type = $1.type;
							ParserCondPrint("expr");
							/* no need to xfer type -- auto --confired*/
							
							}
		|	funCall		{ $$.type = $1.type; 
							/*for this purpose, use fun ret type */
							/*Do not use the type FUNTYPE */
							ParserCondPrint("expr");
							
							}
					
		|	var		{  /*lokk up var in ST, then get type*/
							/*leave the Semantic checking to R1 var->ID*/
							/*assume the R1 found ID in ST and also
							xferred type to var*/
							$$.type = $1.type;
							ParserCondPrint("expr");
							
							}
		;

consts:	intConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							/* no need for type xfer; type etc transferred auto*/
							/*$$.type = $1.type;*/
							
							}
					

		|	floatConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}

		|	dayofweekConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}
					
		|	datetimeConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}


		|	stringConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}
		|	sizeConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}

		|	constRange		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}
		|	serverConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}

		|	queConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}

		|	jobConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}
		|	cnodeConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}
		|	setServerConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}

		|	setQueConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}

		|	setJobConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}
		|	setCnodeConst		{
							ParserCondPrint("consts");
							$$.type = $1.type;
							
							}
		;




constRange:	intConstRange		{
							ParserCondPrint("constRange");
							$$.type = $1.type;
							strcpy($$.lexeme, $1.lexeme);
							
							}


		|	floatConstRange		{
							ParserCondPrint("constRange");
							$$.type = $1.type;
							strcpy($$.lexeme, $1.lexeme);
							
							}


		|	dayofweekConstRange		{
							ParserCondPrint("constRange");
							$$.type = $1.type;
							strcpy($$.lexeme, $1.lexeme);
							
							}

		|	datetimeConstRange		{
							ParserCondPrint("constRange");
							$$.type = $1.type;
							strcpy($$.lexeme, $1.lexeme);
							
							}

		|	sizeConstRange		{
							ParserCondPrint("constRange");
							$$.type = $1.type;
							strcpy($$.lexeme, $1.lexeme);
							
							}
		;



intConst:	INTCONST	{ 
							ParserCondPrint("intConst"); 
							$1.type = INTTYPE;	/*semantic type*/
							$$.type = INTTYPE;	/*semantic type*/

							if( strcmp($1.lexeme, "SUCCESS") == 0 		|| \
							    strcmp($1.lexeme, "FAIL") == 0    		|| \
							    strcmp($1.lexeme, "SERVER_ACTIVE") == 0    	|| \
							    strcmp($1.lexeme, "SERVER_IDLE") == 0    	|| \
							    strcmp($1.lexeme, "SERVER_SCHED") == 0    	|| \
							    strcmp($1.lexeme, "SERVER_TERM") == 0    	|| \
							    strcmp($1.lexeme, "SERVER_TERMDELAY") == 0  || \
							    strcmp($1.lexeme, "QTYPE_E") == 0    	|| \
							    strcmp($1.lexeme, "QTYPE_R") == 0    	|| \
							    strcmp($1.lexeme, "SCHED_DISABLED") == 0    || \
							    strcmp($1.lexeme, "SCHED_ENABLED") == 0    	|| \
							    strcmp($1.lexeme, "FALSE") == 0    		|| \
							    strcmp($1.lexeme, "TRUE") == 0		|| \
							    strcmp($1.lexeme, "TRANSIT") == 0		|| \
							    strcmp($1.lexeme, "QUEUED") == 0		|| \
							    strcmp($1.lexeme, "HELD") == 0		|| \
							    strcmp($1.lexeme, "WAITING") == 0		|| \
							    strcmp($1.lexeme, "RUNNING") == 0		|| \
							    strcmp($1.lexeme, "EXITING") == 0		|| \
							    strcmp($1.lexeme, "CNODE_OFFLINE") == 0	|| \
							    strcmp($1.lexeme, "CNODE_DOWN") == 0	|| \
							    strcmp($1.lexeme, "CNODE_FREE") == 0	|| \
							    strcmp($1.lexeme, "CNODE_RESERVE") == 0 	|| \
							    strcmp($1.lexeme, "CNODE_INUSE_EXCLUSIVE") == 0 	|| \
							    strcmp($1.lexeme, "CNODE_INUSE_SHARED") == 0 	|| \
							    strcmp($1.lexeme, "CNODE_TIMESHARED") == 0 		|| \
							    strcmp($1.lexeme, "CNODE_CLUSTER") == 0 		|| \
							    strcmp($1.lexeme, "CNODE_UNKNOWN") == 0 		|| \
							    strcmp($1.lexeme, "SYNCRUN") == 0 	  	  || \
							    strcmp($1.lexeme, "ASYNCRUN") == 0 	  	  || \
							    strcmp($1.lexeme, "DELETE") == 0 	  	  || \
							    strcmp($1.lexeme, "RERUN") == 0 	  	  || \
							    strcmp($1.lexeme, "HOLD") == 0 	  	  || \
							    strcmp($1.lexeme, "RELEASE") == 0 	  	  || \
							    strcmp($1.lexeme, "SIGNAL") == 0 	  	  || \
							    strcmp($1.lexeme, "MODIFYATTR") == 0 	  || \
							    strcmp($1.lexeme, "MODIFYRES") == 0 	  || \
							    strcmp($1.lexeme, "OP_EQ") == 0 		  || \
							    strcmp($1.lexeme, "OP_NEQ") == 0 		  || \
							    strcmp($1.lexeme, "OP_LT") == 0 		  || \
							    strcmp($1.lexeme, "OP_LE") == 0 		  || \
							    strcmp($1.lexeme, "OP_GE") == 0 		  || \
							    strcmp($1.lexeme, "OP_GT") == 0 		  || \
							    strcmp($1.lexeme, "ASC") == 0 		  || \
							    strcmp($1.lexeme, "DESC") == 0 		  || \
							    strcmp($1.lexeme, "OP_MAX") == 0 		  || \
							    strcmp($1.lexeme, "OP_MIN") == 0 )
								strcpy($$.lexeme, $1.lexeme);
							else
								sprintf( (char *)$$.lexeme, "%d", strToInt((char *)$1.lexeme));

							CodeGenBuffSave((char *)$$.lexeme);
						}
		;


floatConst:	FLOATCONST	{
							ParserCondPrint("floatConst"); 
							$1.type = FLOATTYPE;	/*semantic type*/
							$$.type = FLOATTYPE;	/*semantic type*/

							sprintf( (char *)$$.lexeme, "%f", strToFloat( (char *)$1.lexeme));
							/*her we need type xfer, becuase default
							doesnot happen becuase we doing $1.type = x*
							in the line above*/
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;


dayofweekConst:	DAYOFWEEKCONST	{ 
							ParserCondPrint("dayofweekConst"); 
							$1.type = DAYOFWEEKTYPE;
							$$.type = DAYOFWEEKTYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

datetimeConst:	lb intConst pipe intConst pipe intConst rb { 
							ParserCondPrint("datetimeConst"); 
							$2.type = DATETIMETYPE;
							$$.type = DATETIMETYPE;
							sprintf( (char *)$$.lexeme, "%s%s%s%s%s%s%s", $1.lexeme, $2.lexeme,
								$3.lexeme, $4.lexeme, $5.lexeme, $6.lexeme, $7.lexeme);
							SemanticDateConstCk($2, $4, $6);

							CodeGenBuffSaveBefore("strToDateTime(\"", "(", CodeGenLastDef("("));
							CodeGenBuffSave("\")");
						}
		| lb intConst colon intConst colon intConst rb {
                                                        ParserCondPrint("datetimeConst");
                                                        $2.type = DATETIMETYPE;
                                                        $$.type = DATETIMETYPE;
                                                        sprintf( (char *)$$.lexeme, "%s%s%s%s%s%s%s", $1.lexeme, $2.lexeme,
                                                                $3.lexeme, $4.lexeme, $5.lexeme, $6.lexeme, $7.lexeme);
                                                        SemanticTimeConstCk($2, $4, $6);
                                                        CodeGenBuffSaveBefore("strToDateTime(\"", "(", CodeGenLastDef("("));
                                                        CodeGenBuffSave("\")");
						}
		| lb intConst pipe intConst pipe intConst at intConst colon intConst colon intConst rb {
                                                        ParserCondPrint("datetimeConst");
                                                        $2.type = DATETIMETYPE;
                                                        $$.type = DATETIMETYPE;
                                                        sprintf( (char *)$$.lexeme, "%s%s%s%s%s%s%s%s%s%s%s%s%s", $1.lexeme, $2.lexeme,
                                                                $3.lexeme, $4.lexeme, $5.lexeme, $6.lexeme, $7.lexeme, $8.lexeme,
								$9.lexeme, $10.lexeme, $11.lexeme, $12.lexeme, $13.lexeme);
                                                        SemanticDateConstCk($2, $4, $6);
                                                        SemanticTimeConstCk($8, $10, $12);
                                                        CodeGenBuffSaveBefore("strToDateTime(\"", "(", CodeGenLastDef("("));
                                                        CodeGenBuffSave("\")");
						}
		; 	

stringConst:	STRINGCONST	{ 
							ParserCondPrint("stringConst"); 
							$1.type = STRINGTYPE;
							$$.type = STRINGTYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

sizeConst:	SIZECONST	{ 
							ParserCondPrint("sizeConst"); 
							$1.type = SIZETYPE;
							$$.type = SIZETYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave("strToSize(\"");
							CodeGenBuffSave((char *)$$.lexeme);
							CodeGenBuffSave("\")");
						}
		;


serverConst:	SERVERCONST	{
							ParserCondPrint("serverConst"); 
							$1.type = SERVERTYPE;
							$$.type = SERVERTYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

jobConst:	JOBCONST	{
							ParserCondPrint("jobConst"); 
							$1.type = JOBTYPE;
							$$.type = JOBTYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

queConst:	QUECONST	{
							ParserCondPrint("queConst"); 
							$1.type = QUETYPE;
							$$.type = QUETYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

cnodeConst:	CNODECONST	{
							ParserCondPrint("cnodeConst"); 
							$1.type = CNODETYPE;
							$$.type = CNODETYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}

setServerConst:	SETSERVERCONST	{
							ParserCondPrint("setServerConst"); 
							$1.type = SERVERSETTYPE;
							$$.type = SERVERSETTYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

setJobConst:	SETJOBCONST	{
							ParserCondPrint("setJobConst"); 
							$1.type = JOBSETTYPE;
							$$.type = JOBSETTYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

setQueConst:	SETQUECONST	{
							ParserCondPrint("setQueConst"); 
							$1.type = QUESETTYPE;
							$$.type = QUESETTYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

setCnodeConst:	SETCNODECONST	{
							ParserCondPrint("setCnodeConst"); 
							$1.type = CNODESETTYPE;
							$$.type = CNODESETTYPE;
							strcpy($$.lexeme, $1.lexeme);
							CodeGenBuffSave((char *)$$.lexeme);
						}
		;

intConstRange:	lb intConst comma intConst rb	{ 
							ParserCondPrint("intConstRange"); 
							$2.type = INTRANGETYPE;
							$$.type = INTRANGETYPE;
							sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme,
								$3.lexeme, $4.lexeme, $5.lexeme);

							SemanticIntConstRangeCk($2, $4);
							CodeGenBuffSaveBefore("toIntRange", "(", CodeGenLastDef("("));
						}
		;



floatConstRange:	lb floatConst comma floatConst rb	{ 
							ParserCondPrint("floatConstRange"); 
							$2.type = FLOATRANGETYPE;
							$$.type = FLOATRANGETYPE;
							sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme,
								$3.lexeme, $4.lexeme, $5.lexeme);

							SemanticFloatConstRangeCk($2, $4);
							CodeGenBuffSaveBefore("toFloatRange", "(", CodeGenLastDef("("));
						}
		;



dayofweekConstRange:	lb dayofweekConst comma dayofweekConst rb	{ 
							ParserCondPrint("dayofweekConstRange"); 
							$2.type = DAYOFWEEKRANGETYPE;
							$$.type = DAYOFWEEKRANGETYPE;
							sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme,
								$3.lexeme, $4.lexeme, $5.lexeme);

							SemanticDayofweekConstRangeCk($2, $4);
							CodeGenBuffSaveBefore("toDayofweekRange", "(", CodeGenLastDef("("));
						}
		;

datetimeConstRange:	lb datetimeConst comma datetimeConst rb	{
							ParserCondPrint("datetimeConstRange"); 
							$2.type = DATETIMERANGETYPE;
							$$.type = DATETIMERANGETYPE;
							sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme,
								$3.lexeme, $4.lexeme, $5.lexeme);

							SemanticDateTimeConstRangeCk($2, $4);
							/* following resolves conflict when there are inner "("s */
							/* the last token should be the ) */
							intval = NodeGetLineDef(CodeGenBuffGetLast());
							/* find the ( that pairs with the last ) */
							CodeGenBuffSaveBefore("toDateTimeRange", "(", intval);
						}
		;

sizeConstRange:	lb sizeConst comma sizeConst rb	{ 
							ParserCondPrint("datetimeConstRange"); 
							$2.type = SIZERANGETYPE;
							$$.type = SIZERANGETYPE;
							sprintf( (char *)$$.lexeme, "%s%s%s%s%s", $1.lexeme, $2.lexeme,
								$3.lexeme, $4.lexeme, $5.lexeme);

							SemanticSizeConstRangeCk($2, $4);
							/* following resolves conflict when there are inner "("s */
							intval = NodeGetLineDef(CodeGenBuffGetLast());
							CodeGenBuffSaveBefore("toSizeRange", "(", intval);
						}
		;

/*funcall stuff*/
		/*no end semic, funCall is expr, and exprStat adds ';' */

		/*
		 * Args types:
		 * Ok: Simple, Complex, Range, funCall
		 * Ok: Cpr type: LE, MAX, etc
		 * Not: Set of x.
		 */
funCall:	IDENT { /*get type etc by lookup in SymTab */
					/*
					 * Let $$ to return type -- not FUNtype.
					 * Get it from SymTab.
					 * This is needed for expr semantic anal.
					 */
					/* Check if func is in the symbol table */
					if( (np=(Np)SymTabFindNodeByLexemeInProg((char *)$1.lexeme)) == NULL ) {
						SemanticErr(8);
					} else {
						ParserCurrFunParamPtrPut((Np)np);
					}
					if( NodeGetFunFlag(np) == YES )	{ /* if not internally defined */
						strcpy(bufstr2, "basl_");
						strcat(bufstr2, $1.lexeme);
						CodeGenBuffSaveFun((char *)bufstr2);	/* save as is */
					} else {
						CodeGenBuffSaveFun((char *)$1.lexeme);	/* save as is */
					}
					} lb args rb  {
					ParserCondPrint("funCall");
					/*link args*/
					/*do not insert IDENT in SymTab-- already is*/
					if( (np=(Np)SymTabFindNodeByLexemeInProg((char *)$1.lexeme)) == NULL ) {
						SemanticErr(8);
					} else {
						$$.type = NodeGetType(np);
					}
					if( CodeGenLastDef("QueJobFind") != 0 )  {
						CodeGenBuffSaveQueJobFind();
					} else if( CodeGenLastDef("QueFilter") != 0 ) {
						CodeGenBuffSaveQueFilter();
					} else if( CodeGenLastDef("Sort") != 0 ) {
						if( ParserCurrFunParamPtrGet() != NULL )
							SemanticErr(18);
						CodeGenBuffSaveSort();
					} else if( ParserCurrFunParamPtrGet() != NULL ) {
							SemanticErr(18);
					}
							}
		;


args:		/*lambda*/		{  /*get type etc from var who gets it from SymTab */
							ParserCondPrint("args"); 
						}

			| arg argList		{ 
							ParserCondPrint("args"); 
							/*link 1st arg to funname -- need funname*/
							/* 
							 * Need two ptrs (globals) to arg & param. 
							 * Follow chain and cpr types.
							 */
						}

		;


argList:		/*lambda*/		{ 
							ParserCondPrint("argList"); 
						}

			| comma arg argList		{ 
							ParserCondPrint("argList"); 
						}

		;


		/*
		 * Args types:
		 * Ok: Simple, Complex, Range, funCall
		 * Ok: CprType: LE, MAX, etc
		 * Not: Set of x.
		 */
arg:	var {		 
						ParserCondPrint("arg"); 
						$$.type = $1.type;
						if( SemanticParamVarCk($1) == GENERICTYPE ) {
							if( CodeGenLastDef("QueJobFind") != 0 || \
							    CodeGenLastDef("QueFilter")  != 0 ) {
							     if ((np=SymTabFindNodeByLexemeInProg((char *) $1.lexeme)) == NULL)
										    SemanticErr(6);

							     /* QueJobFind and QueFilter's function parameter must accept only */
							     /* 1 type that is of JOBTYPE */
							     if( (NodeGetFunFlag(np) != NO ) \
									&& \
								 	(np->funDescr.paramCnt != 1 || \
									   	NodeGetType(np->funDescr.paramPtr) != JOBTYPE) )
									   SemanticErr(28);
							     np = NodeNew( (char *)"", $1.type, $1.line, -2, NodeGetFunFlag(np));
							     SymTabInsertFront(np);
							} else if ( CodeGenLastDef("Sort")  != 0 ) {
							     if ((np=SymTabFindNodeByLexemeInProg((char *) $1.lexeme)) == NULL)
										    SemanticErr(6);
							     /* a key function argument must only accept one argument */
							     if( NodeGetFunFlag(np) != NO ) {
								if( NodeGetParamCnt(np) != 1 )
									   SemanticErr(38);
							      	SymTabInsertFront( NodeNew( (char *)"", NodeGetType(np->funDescr.paramPtr),
									    		  NodeGetLineDef(np->funDescr.paramPtr), -2,
									    		  NodeGetFunFlag(np->funDescr.paramPtr)) );
							     }	

							     np = NodeNew( (char *)"", $1.type, $1.line, -2, NodeGetFunFlag(np));
							     SymTabInsertFront(np);
							} else {
							     /* Level -2 is for temporary/special processing - checking type */
							     np = NodeNew( (char *)"", $1.type, $1.line, -2, NO);
							     SymTabInsertFront(np);
							}
						}
					}
		| consts		{
						ParserCondPrint("arg"); 
						$$.type = $1.type;
						if( SemanticParamConstsCk($1) == GENERICTYPE ) {

							/* Level -2 is for temporary/special processing - checking type */
							np = NodeNew( (char *)"", $1.type, $1.line, -2, NO);
							SymTabInsertFront(np);
						}
					}
		;


/*var stuff*/
/*
 * Var types: typeSimple, complex, Range, fun, set
 * Yes Set. myQs = {"q1", "q2"}; (v2)
 */
var:		IDENT		{ 
							/*get $1.type by lookup of IDENT in SymTab*/
							/*right now $1.t unknown until lookup*/

							ParserCondPrint("var"); 
							
							SemanticVarDefCk($1);
							/*if all is weel continue else have sem err */

							np = SymTabFindNodeByLexemeInProg((char *) $1.lexeme);

							if (np == NULL) 
								ParserErr(3); /*should not happen
											since Sem checked this*/

							$1.type = NodeGetType(np);
							$$.type = $1.type;
							strcpy($$.lexeme, $1.lexeme);

							/*do not insert IDENT in SymTab-- already is*/
							switch( NodeGetFunFlag(np) ) {
							  case 	YES_INT:
							  case  NO:
									CodeGenBuffSave((char *)$$.lexeme);
									break;
							  case 	YES:
									CodeGenBuffSave("basl_");
									CodeGenBuffSave((char *)$$.lexeme);
							}
						}
		;


/*brackets, eqs, etc to order*/
lcb:		'{' {

				ParserCondPrint("lcb");
				/*
				SymTabPrint();
				*/
				CodeGenBuffSave("\n");
				CodeGenBuffSave("{");
				ParserLevelIncr();
				CodeGenBuffSave("\n");
				CodeGenBuffSave("\n");
				if( inSwitch )
					CodeGenBuffSwitchEmit();
				else
					CodeGenBuffEmit();

								}
		;


rcb:		'}' {

				ParserCondPrint("rcb");
				if( SymTabFindAnyNodeInLevelOfType( ParserLevelGet(), STRINGTYPE ) != NULL ) {
					intval = CodeGenLastDef("return") || CodeGenLastDef("exit");
					if( intval == 0 ) {	/* no previous return/exit statement */
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSave("varstrFreeByScope(");
						CodeGenBuffSave(bufstr);
						CodeGenBuffSave(");");
						CodeGenBuffSave("\n");
					}
				}
				if( SymTabFindAnyNodeInLevelOfType( ParserLevelGet(), QUETYPE ) != NULL ) {
					intval = CodeGenLastDef("return") || CodeGenLastDef("exit");
					if( intval == 0 ) {	/* no previous return/exit statement */
						sprintf(bufstr, "%d", ParserVarScopeGet());
						CodeGenBuffSave("mallocTableFreeByScope(");
						CodeGenBuffSave(bufstr);
						CodeGenBuffSave(", QueFree");
						CodeGenBuffSave(");");
						CodeGenBuffSave("\n");
					}
				}


				/*later must delete levels
				SymTabDeleteLevel(ParserLevelGet());
				*/
				/*
				SymTabPrint();
				*/
				SymTabDeleteLevel(ParserLevelGet());
				/*
				SymTabPrint();
				*/
				ParserLevelDecr();
				CodeGenBuffSave("}");

				CodeGenBuffSave("\n");
				if( inSwitch )
					CodeGenBuffSwitchEmit();
				else
					CodeGenBuffEmit();
								}
		;

lb:		'(' {
				strcpy($$.lexeme, $1.lexeme);

				ParserCondPrint("lb");
				CodeGenBuffSave("(");
								}
		;


rb:		')' {

				strcpy($$.lexeme, $1.lexeme);
				ParserCondPrint("rb");
				CodeGenBuffSave(")");
								}
		;


comma:		',' {
				ParserCondPrint("comma");
				strcpy($$.lexeme, $1.lexeme);
				CodeGenBuffSave(", ");
								}
		;

colon:		':' {
				ParserCondPrint("colon");
				strcpy($$.lexeme, $1.lexeme);
				CodeGenBuffSave(":");
								}
		;

pipe:		'|' {
				ParserCondPrint("pipe");
				strcpy($$.lexeme, $1.lexeme);
				CodeGenBuffSave("|");
								}
		;

at:		'@' {
				ParserCondPrint("at");
				strcpy($$.lexeme, $1.lexeme);
				CodeGenBuffSave("@");
								}
		;
	
eqs:	'=' 	{
							ParserCondPrint("eqs");
							CodeGenBuffSave(" = ");

						}

		;


sc:		';' 	{
							ParserCondPrint("sc");
							CodeGenBuffSave(";");
							CodeGenBuffSave("\n");
							CodeGenBuffEmit();

						}
		;


defFun: funHead blockWithDefs {
							ParserCondPrint("defFun");
						}
		;



/*def data types Fun*/
/*can have args int, float, day, Range of Int, prt to functs (funname) */
/*so make params all type, let Semantic analyser check validity*/
/*return type only simple or complex, no set, range */
/*
 * Set type of ID in token to ret type of fun for semantic anal.
 *
 * In STE set funFlag=YES.
 * 
 * Define glob currFunPtr = SymTabFind($2.lex) to do sem checks.
 * Use it to cpr proto vs deffun.
 * Use it tp cpr proto vs funCall.
 *
 */

funHead:	dataTypesSimple IDENT { $2.type = $1.type;

								if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
									SemanticErr(7);	
								}
								np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), YES);
								/*
								NodePrint(np);
								*/
								SymTabInsertFront(np);

								ParserCurrFunPtrPut(np);
								/*
								NodePrint(np);
								*/

								CodeGenBuffSave("basl_");
								CodeGenBuffSave((char *)$2.lexeme);
								ParserVarScopeIncr();

								} lb params rb	{
								ParserCondPrint("funHead"); 
								/*
								SymTabPrint();
								*/


							}
		|	dataTypesComplex IDENT { $2.type = $1.type;

								if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
									SemanticErr(7);	
								}
								np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), YES);
								/*
								NodePrint(np);
								*/
								SymTabInsertFront(np);

								ParserCurrFunPtrPut(np);
								/*
								NodePrint(np);
								*/
								CodeGenBuffSave("basl_");
								CodeGenBuffSave((char *)$2.lexeme);
								ParserVarScopeIncr();

								} lb params rb	{
								ParserCondPrint("funHead"); 
								/*
								SymTabPrint();
								*/


							}
		|	dataTypesSet IDENT { $2.type = $1.type;

								if( SymTabFindNodeByLexemeInLevel( (char *)$2.lexeme, ParserLevelGet() ) != NULL ) {
									SemanticErr(7);	
								}
								np = NodeNew( (char *) $2.lexeme, $2.type, $2.line, ParserLevelGet(), YES);
								/*
								NodePrint(np);
								*/
								SymTabInsertFront(np);

								ParserCurrFunPtrPut(np);
								/*
								NodePrint(np);
								*/
								CodeGenBuffSave("basl_");
								CodeGenBuffSave((char *)$2.lexeme);
								ParserVarScopeIncr();

								} lb params rb	{
								ParserCondPrint("funHead"); 
								/*
								SymTabPrint();
								*/


							}
		;

%%

#include <pbs_config.h>   /* the master config generated by configure */

#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE 1
#endif  /* _POSIX_SOURCE */
/*
#include "Parser.h"
#include "y.tab.h"
extern int linenum;
extern char linebuf[];
#include <setjmp.h>
extern jmp_buf begin;
*/

static char ident[] = "@(#) $RCSfile$ $Revision$";
/* GLobal Variables */
FILE * ParserFpOut;

/* File Scope Variables */
static char * ParserErrors[] =
{
        "0 no such error msg",
        "1 ep = NULL",
        "2 lexem ptr = NULL",
        "3 np = NULL",
        "4 ParserFpOut = NULL",
        "5 str = NULL",
	"6 string to constant value conversion failed", 
        ""
};

static int ParserMaxErrors = 8;

static char *ParserName = "Parser";

static int ParserLevel = 0; /*nesting level*/
static int ParserVarScope = 0;	/* variable scope */

static struct Node * ParserCurrFunPtr;
static struct Node * ParserCurrFunParamPtr;
static struct Node * ParserProtoFunPtr;
static struct Node * ParserCallFunPtr;

static int ParserDF = 0;

static struct MYTOK ParserCurrSwitchVar;

/*must be here*/

/* remove for DOS */
void yyerror(ep)
char	*ep;
{
	if(ParserFpOut == NULL)
		ParserErr(4);

	fprintf(ParserFpOut, "%d: Error %s in this line:\n%s\n",
			     			linenum, ep, linebuf);
	exit(1);
}

/*
 * Work around this Bison
 */
int yywrap(void)
{
	return(1);
}

/*
 * error message and return for new input
 */
void execError(cp)
char	*cp;
{
	if(ParserFpOut == NULL)
		ParserErr(4);

   fprintf(ParserFpOut, "***rrs Parser run time error: ");

   fprintf(ParserFpOut, "%s near line %d\n", cp, linenum);

   ++linenum;
   longjmp(begin, 0); /* return for next expression */
}


/*
 * Redefined FPE handler
 */
void ParserFpeCatch(void)
{
	execError("***rrs Parser floating point error\n");
}


 
void ParserInit(void)
{
	ParserCondPrint("ParserInit");

/*	ParserDF = 1; */
	ParserLevel = 0;
	ParserVarScope = 0;
}
 
/*
 * Print Token in Bison
 */
void ParserPrintToken(lexem, lin, len, typ)
char *lexem;
int lin;
int len;
int typ;
{
	ParserCondPrint("ParserPrintToken");

	if(ParserFpOut == NULL)
		ParserErr(4);

	if(ParserDF == 1)
	{
	if(lexem == NULL)
		ParserErr(2);

	fprintf(ParserFpOut, "lexem=%s, lin=%d, len=%d, typ=%d\n", lexem, lin, len, typ);
	}
}

 
/*
 * Print Token in Bison
 */
void ParserPrintToken2(tok)
struct	MYTOK	tok;
{
	ParserCondPrint("ParserPrintToken2");

	if(ParserFpOut == NULL)
		ParserErr(4);

	if (ParserDF == 1)
	{

	fprintf(ParserFpOut, "lexem=%s, lin=%d, len=%d, typ=%d, varFlag=%d\n", tok.lexeme, tok.line, tok.len, tok.type, tok.varFlag);
	}
}

/*
use for copy mytok -> sym
*/
/*
void ParserTokenToNode(lexem, lin, len, typ)
char *lexem;
int lin;
int len;
int typ;
{

	ParserCondPrint("ParserTokenToNode");

	if(lexem == NULL)
		ParserErr(2);

	np = NodeNew

	strcpy((char *) yylval.mytok.lexeme, lexem);
	yylval.mytok.line = lin;
	yylval.mytok.len = len;
	yylval.mytok.type = typ;
}
*/

 
void ParserPutDF(df)
int	df;
{
	ParserCondPrint("ParserPutDF");

	ParserDF = df;
}
 
 
void ParserLevelIncr(void)
{
	ParserCondPrint("ParserLevelIncr");

	if(ParserFpOut == NULL)
		ParserErr(4);

	ParserLevel++;

	if( ParserDF == 1 )
		fprintf(ParserFpOut, "linenum=%d, level=%d\n", linenum,
							      ParserLevel);

}
 
 
void ParserLevelDecr(void)
{
	ParserCondPrint("ParserLevelDecr");

	if(ParserFpOut == NULL)
		ParserErr(4);

	ParserLevel--;

	if( ParserDF == 1 )
		fprintf(ParserFpOut, "linenum=%d, level=%d\n", linenum,
							      ParserLevel);

}
 
 
int ParserLevelGet(void)
{
	ParserCondPrint("ParserLevelGet");

	return(ParserLevel);
}

void ParserVarScopeIncr(void)
{
	ParserCondPrint("ParserVarScopeIncr");

	ParserVarScope++;
}
 
 
int ParserVarScopeGet(void)
{
	ParserCondPrint("ParserVarScopeGet");

	return(ParserVarScope);
}
 
void ParserCondPrint(str)
char	*str;
{
	if(ParserFpOut == NULL)
		ParserErr(4);

	if(str == NULL)
		ParserErr(5);

	if (ParserDF ==1)
	{
		fprintf(ParserFpOut, "%s\t", ParserName);
		fprintf(ParserFpOut, "%s\n", str);
	}
}


void ParserErr(e)
int	e;
{
	fprintf(ParserFpOut, "ParserErr\n");

	if(ParserFpOut == NULL)
		ParserErr(4);

	if (e >= ParserMaxErrors)
		e = 0;

	fprintf(ParserFpOut, "rs: %s\n", ParserErrors[e]);
	exit(1);
}



void ParserPrint(void)
{
	ParserCondPrint("ParserPrint");

	fprintf(ParserFpOut, "CurrFunPtr=%x, ProtoFunPtr=%x, CallFunPtr=%x\n",
	      ParserCurrFunPtr , ParserProtoFunPtr , ParserCallFunPtr);

}

void ParserCurrFunPtrPut(np)
Np	np;
{
	ParserCondPrint("ParserCurrFunPtrPut");

	ParserCurrFunPtr = np;
}



Np ParserCurrFunPtrGet(void)
{
	ParserCondPrint("ParserCurrFunPtrGet");

	return(ParserCurrFunPtr);
}

void ParserCurrFunParamPtrPut(np)
Np	np;
{
	ParserCondPrint("ParserCurrFunParamPtrPut");
	if( np == NULL )
		ParserErr(3);

	ParserCurrFunParamPtr = np->funDescr.paramPtr;
}

Np ParserCurrFunParamPtrGet(void)
{
	ParserCondPrint("ParserCurrFunParamPtrGet");
/*
	printf("CURRENT PARAM: \n");
	NodePrint(ParserCurrFunParamPtr);
	printf("CURRENT PARAM: \n\n");
*/
	return(ParserCurrFunParamPtr);
}

void ParserCurrSwitchVarPut(token)
struct  MYTOK token;
{
	ParserCondPrint("ParserCurrSwitchVarPut");

	ParserCurrSwitchVar = token;
}

struct MYTOK ParserCurrSwitchVarGet(void)
{
	ParserCondPrint("ParserCurrSwitchVarGet");
	return(ParserCurrSwitchVar);
}
