/* parse.h */
#ifndef PARSE_H
#define PARSE_H

/*
	Process all input text.
	At this level, only static declarations, defines,
	includes, and function definitions are legal.
*/
void parse();

/*	>>>>>> start of cc2 <<<<<<<<	*/
/*	Get required array size		*/
/* invoked when declared variable is followed by "[" */
/*	this routine makes subscript the absolute */
/*	size of the array. */
/** doesn't eval expression, nor multi-dimensions. **/
int mk_subscript();

/*	Begin a function		*/
/* Called from "parse" this routine tries to make a function */
/*	out of what follows.	*/
/** is_identifier() gets & validates identifier **/
void newfunc();

/*	Declare argument types		*/
/* called from "newfunc" this routine adds an entry in the */
/*	local symbol table for each named argument */

/* top tells how the max arg stack size was found while
   scanning arguments.  From this, we can calculate the
   the actual stack offset and stuff it back into the
   local symbol table.
*/
/* t = cchar or cint, top = max arg stack */
void getarg(int t, int top);

/*	Statement parser		*/
/* called whenever syntax requires	*/
/*	a statement. 			 */
/*  this routine performs that statement */
/*  and returns a number telling which one */
int statement();

/*	Semicolon enforcer	*/
/* called whenever syntax requires a semicolon */
void ns();

/*	Compound statement	*/
/* allow any number of statements to fall between "{}" */
void compound();

/*	"if" statement	*/
void doif();

/*	"do" statement "while" (expr)	*/
void dodo();

void addwhile(int ptr[]);

void delwhile();

int* readwhile();

/*** Additional Statement Support Routines ***/
/*****

findwhile ()
{
	int	*ptr;

	for (ptr = wsptr; ptr != ws;) {
		ptr = ptr - WSSIZ;
		if (ptr[WSTYP] != WSSWITCH)
			return (ptr);
	}
	error ("no active do/for/while");
	return (0);
}

readswitch ()
{
	int	*ptr;

	if (ptr = readwhile ())
		if (ptr[WSTYP] == WSSWITCH)
			return (ptr);
	return (0);
}

addcase (val)
int	val;
{
	int	lab;

	if (swstp == SWSTSZ)
		error ("too many case labels");
	else {
		swstcase[swstp] = val;
		swstlab[swstp++] = lab = getlabel ();
		printlabel (lab);
		col ();
		nl ();
	}
}

/*						*/
/*	"while" (expr) statement	*/
/*						*/

void dowhile();

/*
 *	"for" statement
 */
/*****
dofor ()
{
	int	ws[7],
		*pws;

	ws[WSSYM] = autoptr;
	ws[WSSP] = Csp;
	ws[WSTYP] = WSFOR;
	ws[WSTEST] = getlabel ();
	ws[WSINCR] = getlabel ();
	ws[WSBODY] = getlabel ();
	ws[WSEXIT] = getlabel ();
	addwhile (ws);
	pws = readwhile ();
	needbrack ("(");

	if (match (";") == 0) {
		expression (YES);
		ns ();
	}
	gnlabel (pws[WSTEST]);

	if (match (";") == 0) {
		expression (YES);
		testjump (pws[WSBODY], TRUE);
		jump (pws[WSEXIT]);
		ns ();
	} else
		pws[WSTEST] = pws[WSBODY];
	gnlabel (pws[WSINCR]);

	if (match (")") == 0) {
		expression (YES);
		needbrack (")");
		jump (pws[WSTEST]);
	} else
		pws[WSINCR] = pws[WSTEST];
	gnlabel (pws[WSBODY]);
	statement (NO);
	jump (pws[WSINCR]);
	gnlabel (pws[WSEXIT]);
	locptr = pws[WSSYM];
	stkp = modstk (pws[WSSP]);
	delwhile ();
}
*****/

/*
 *	"switch" statement
 */
/*****
doswitch ()
{
	int	ws[7];
	int	*ptr;

	ws[WSSYM] = locptr;
	ws[WSSP] = stkp;
	ws[WSTYP] = WSSWITCH;
	ws[WSCASEP] = swstp;
	ws[WSTAB] = getlabel ();
	ws[WSDEF] = ws[WSEXIT] = getlabel ();
	addwhile (ws);
	immed ();
	printlabel (ws[WSTAB]);
	nl ();
	gpush ();
	needbrack ("(");
	expression (YES);
	needbrack (")");
	stkp = stkp + intsize(); **'?case' will adjust the stack **
	gjcase ();
	statement (NO);
	ptr = readswitch ();
	jump (ptr[WSEXIT]);
	dumpsw (ptr);
	gnlabel (ptr[WSEXIT]);
	locptr = ptr[WSSYM];
	stkp = modstk (ptr[WSSP]);
	swstp = ptr[WSCASEP];
	delwhile ();
}
*****/
/*
 *	"case" label
 */
/*****
docase ()
{
	int	val;

	val = 0;
	if (readswitch ()) {
	
		if (number (&val) == 0)
		
			if (pstr (&val) == 0)
				error ("bad case label");
		addcase (val);
	
		if (match (":") == 0)
			error ("missing colon");
	} else
		error ("no active switch");
}
*****/
/*
 *	"default" label
 */
/*****
dodefault ()
{
	int	*ptr,
		lab;

	if (ptr = readswitch ()) {
		ptr[WSDEF] = lab = getlabel ();
		gnlabel (lab);
	
		if (match (":") == 0)
			error ("missing colon");
	} else
		error ("no active switch");
}
*****/

/*	"return" statement	*/
void doreturn();

/*	"break" statement		*/
void dobreak();

/*	"continue" statement	*/
void docont();

/*	"asm" pseudo-statement	*/
/* enters mode where assembly language statement are */
/*	passed intact through parser	*/
void doasm();

/*	Perform a function call	*/
/*  called from heir11, this routine will either call	*/
/*	the named function, or if the supplied ptr is		*/
/*	zero, will call the contents of Primary Register	*/
void callfunction(char* ptr);

void junk();

int endst();

void illname();

void multidef(char* sname);

void needbrack(char* str);

void needlval();

/** -= Scope =- match sname to static's, secondly **/
char* findstatic(char* sname);

/** -= Scope =- match sname to auto's, firstly **/
/** - on match, return ptr to sname in auto's table - **/
char* findauto(char* sname);

/* catch previously defined symbol and return its ptr, symbptr, which is
** its address in the static symbol table.  If not previously defined,
** define it now.
*/
char* addstatic(char* sname, char id, char typ, int value);

char* addauto(char* sname, char id, char typ, int value);

/* Test if next input string is legal symbol name */
/** A legal identifier is a chr, perhaps followed by alphanumerics **/
/** is_identifier, token input, ck lexeme in line buffer, returns T..F **/
/** sname[k] limit?? **/
/** ex. sname[NAMESIZE]; **/
/** was symname() -> tok_in() -> is_identifier **/
int is_identifier(char* sname);

/* Return next avail internal label number */
int getlabel();

#endif /* PARSE_H */