/*ident	"@(#)cls4:src/cfront.h	1.6" */
/*******************************************************************************
 
C++ source for the C++ Language System, Release 3.0.  This product
is a new release of the original cfront developed in the computer
science research center of AT&T Bell Laboratories.

Copyright (c) 1991 AT&T and UNIX System Laboratories, Inc.
Copyright (c) 1984, 1989, 1990 AT&T.  All Rights Reserved.

THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System
Laboratories, Inc.  The copyright notice above does not evidence
any actual or intended publication of such source code.

*	Here are all the class definitions for cfront, and most of the externs
*******************************************************************************/

#ifndef _CFRONT_H
#define _CFRONT_H

#include "token.h"
#include "typedef.h"

#ifndef GRAM
extern char* prog_name;		// compiler name and version
extern int inline_restr;	// inline expansion restrictions 
#endif

extern TOK	tlex();
extern Pname	syn();

extern void	ext(int);

extern char* 	make_name(TOK);
extern char* 	make_nested_name(char*,Pclass); 
extern void 	make_dummy();
extern Pname	dummy_fct;
extern Pname    really_dominate(Pname, Pname, bit);
extern int      exact1(Pname, Ptype);
extern int      exact2(Pname, Ptype);
extern int      exact3(Pname, Ptype);
extern char*	strdup(const char*);

extern int friend_check(Pclass start,Pclass stop, Pfct f);

struct loc		// a source file location
{
	int	file;	// index into file_name[], or zero
	int	line;
#ifndef GRAM
	void	put(FILE*);
	void	putline();
#endif
};

extern Loc curloc;
extern int curr_file;
extern char* curr_filename();
extern char* src_file_name;
extern loc noloc; // dummy null location
extern bit binary_val;
extern bit stmtno;
extern Ptable tmp_tbl;
extern Ptable bound_expr_tbl;

struct ea {	// fudge portable printf-like formatting for error()
	union {
		const void* p;
		long i;
	};

	ea(const void* pp); 
	ea(long ii)   { i = ii; }
	ea() {}
};

extern ea* ea0;

int error(const char*);
int error(const char*, const ea&, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
int error(int, const char*);
int error(int, const char*, const ea&, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
int error(loc*, const char*, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
int error(int, loc*, const char*, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
extern char emode;

extern int error_count;
extern int vtbl_opt;
extern int debug_opt;
extern int warning_opt;
extern int ansi_opt;
extern int pt_opt;
extern int perf_opt;
extern int dtpt_opt;
extern int se_opt;
extern int strict_opt;
extern FILE* out_file;
extern FILE* in_file;
extern FILE* debug_file;
extern FILE* pt_file;
extern FILE* dtpt_file;
extern char scan_started;

extern int bl_level;

//SYM Tables replacing the ktbl
extern Pktab Gtbl;	//SYM global parsing table
extern Pktab Ctbl;	//SYM current parsing table
	//SYM Ctbl is also set during dcl for accurate TNAME lookup.
	//SYM This is ok since parsing and dcl are disjoint operations.
extern Pname k_find_name( char*, Pktab, TOK );
extern Pname k_find_member( char*, Pclass, TOK );
extern Pname insert_type( Pname, Pktab, TOK );
extern Pname insert_name( Pname, Pktab );

extern Ptable gtbl;		// global names
extern Ptable ptbl;		
extern char* oper_name(TOK);
extern char* name_oper(char *);
extern int is_probably_temp(char*);
extern Pname def_name;
extern Pname pdef_name;
extern Pclass ccl;
extern Pbase defa_type;
extern Pbase moe_type;
extern Pbase mptr_type;

#ifndef GRAM
extern Pstmt Cstmt;		// current statement, or 0
extern Pname Cdcl;		// name currently being declared, or 0

extern int largest_int;
#endif

extern Pbase any_type;
extern Pbase int_type;
extern Pbase char_type;
extern Pbase short_type;
extern Pbase long_type;
extern Pbase uint_type;
extern Pbase float_type;
extern Pbase double_type;
extern Pbase ldouble_type;
extern Pbase void_type;

#ifndef GRAM
extern Pbase uchar_type;
extern Pbase ushort_type;
extern Pbase ulong_type;
extern Ptype Pchar_type;
extern Ptype Pint_type;
extern Ptype Pvptr_type;
extern Ptype Pfctvec_type;
extern Ptype Pvoid_type;
extern Pbase zero_type;
extern Ptype size_t_type;

extern int byte_offset;
extern int bit_offset;
extern int max_align;
extern int const_save;
extern int const_ptr;
extern int cm_const_save;
extern bit const_problem;
#endif

extern Pexpr dummy;	/* the empty expression */
extern Pexpr zero;
extern Pexpr one;
extern Pname sta_name;	/* qualifier for unary :: */

#define DEL(p) if (p && (p->permanent==0)) p->del()
#define PERM(p) p->permanent=1
#define UNPERM(p) p->permanent=0

struct node {
	TOK	base;
	bit	permanent;
        bit     baseclass; // base classes have NAME in their base ...
#ifdef DBG
	bit	displayed;	// avoid infinite recursion in display functions
	bit	allocated;	// set when not on free list
	long	id;
#endif
};
#ifdef DBG
extern long node_id;
extern int Adebug;
#define DBID() { node::id = ++::node_id; node::allocated=1; displayed=0; \
	if(Adebug>=1)fprintf(stderr,"\n*** allocated %d base %d\n",id,base); }
#else
#define DBID() /**/
#endif

struct table : node {
/*	a table is a node only to give it a "base" for debugging */
	bit	init_stat;	/* ==0 if block(s) of table not simplified,
				   ==1 if simplified but had no initializers,
				   ==2 if simplified and had initializers.
				*/
	TOK	t_realbase; // is this part of a ktable?
	short	size;
	short	hashsize;
	short	free_slot;	/* next free slot in entries */
	Pname*	entries;
	short*	hashtbl;
	Pstmt	real_block;	/* the last block the user wrote,
				   not one of the ones cfront created
				*/
	Ptable	next;		/* table for enclosing scope */
	Pname	t_name;		/* name of the table */

	static Ptable table_free;
	void* operator new(size_t);
	void operator delete(void*,size_t);

	table(short, Ptable, Pname);
	~table();

	Pname	look(char*, TOK);
	Pname	insert(Pname, TOK);
	inline Pname	insert_copy(Pname, TOK);
	void	reinit();
#ifndef GRAM
	void	grow(int);
	void	set_name(Pname n)	{ t_name = n; };
	int	max()			{ return free_slot-1; };
	void	dcl_print(TOK,TOK);
#endif
	// return a pointer to the i'th entry, or 0 if it does not exist
	Pname get_mem(int i) { return (i<=0 || free_slot<=i) ? 0 : entries[i]; }
	void	del();
	char* whatami();
#ifdef DBG 
	void dump( int verbose = 1 );
#endif 
};
#define NEXT_NAME(tbl,n,i) (n = (n->n_tbl_list ? n->n_tbl_list : tbl->get_mem(++i)))
struct ktable : public node { //SYM parsing table
/*	a ktable is a node only to give it a "base" for debugging */
	union {
	Ptable k_t; // hash table
	Pname  k_n; // list of names for tiny tables such as arg lists
	};
	short k_size;   // if k_tiny, number of names in small table
	bit k_tiny;     // set when table is small (not hash table)
	TOK k_id;       // ARG CLASS BLOCK TEMPLATE 0

	Pktab	k_next; // table for enclosing scope 
	Pname   k_name; // name of table
	ktable(int, Pktab, Pname);
	~ktable();
	static Pktab table_free;
	void* operator new(size_t);
	void operator delete(void*,size_t);

	Pname	look(char*, TOK);
	Pname	insert(Pname, TOK);
	Pname	find_cn(char*); // find name of this class table
	void	expand(int);// expand tiny table to hash table
	void	hoist();    // hoist names in this table to enclosing table
	Pname get_mem(int);
	void	del();
	char* whereami(); // return name or description of table
};

#ifndef GRAM
extern bit Nold;
extern bit vec_const, fct_const;
#endif

//SYM -- tn stuff removed

// local class
extern Plist local_class; //SYM -- preserve for use in del.c
extern char *make_local_name(Ptype, Pname);

// nested type
extern Pname curr_fct; 

extern Pname start_cl(TOK, Pname, Pbcl);
extern void end_cl();
extern Pbase end_enum(Pname, nlist*);

/************ types : basic types, aggregates, declarators ************/

#ifndef GRAM
extern bit new_type;
extern Pname cl_obj_vec;
extern Pname eobj;
#endif


#define DEFINED 01	/* definition fed through ?::dcl() */
#define SIMPLIFIED 02	/* in ?::simpl() */
#define DEF_SEEN 04	/* definition seen, but not processed */
#define REF_SEEN 010	/* reference seen (classdef) */
			/*   used for class members in norm.c */
#define IN_ERROR 020
#define TNAME_SEEN 040  /* used in typedef TNAME name */

enum Templ_type { VANILLA, FCT_TEMPLATE, CL_TEMPLATE, BOUND_TEMPLATE,
                	INSTANTIATED, UNINSTANTIATED };

struct type : node {
	bit	defined;	/* flags DEF_SEEN, DEFINED, SIMPLIFIED, IN_ERROR
					not used systematically yet */
	bit	lex_level;
	Templ_type templ_base;  // CL_TEMPLATE(specialization) or BOUND_TEMPLATE
	Pclass  in_class; 	// nested type
	Pname	in_fct;
	char	*nested_sig;
	char    *local_sig;
	bit	b_const;
	bit	ansi_const;	// turns off constness when print ansi C

	char	*signature(char*,int=0);
	Ptype	tlist;
	bit	check(Ptype, TOK, bit=0);
	Ptype	mkconst();

	// encapsulate casts
	Pclass classtype(); 
	inline Penum enumtype(); 
	inline Ptype bname_type();
	inline Pname bname();
        inline bit is_templ_instance();

	Ptype	skiptypedefs();			// skip over typedef's
	Ptype	skiptypedefs(bit &isconst);	// same, but `OR' b_const's in isconst
#ifndef GRAM
	void	print();
	void	dcl_print(Pname);
	void	base_print();

	Pptr	is_ref();
	Pptr	is_ptr();
	Pptr	is_ptr_or_ref();
	bit	is_unsigned();
	void	dcl(Ptable);
	int	tsizeof(int = 0);
	bit	tconst();
	bit	is_const_object();
	TOK	set_const(bit);
	int	align();
	TOK	kind(TOK,TOK,bit=1);
	TOK	integral(TOK oo)	{ return kind(oo,'I'); };
	TOK	numeric(TOK oo)		{ return kind(oo,'N'); };
	TOK	num_ptr(TOK oo)		{ return kind(oo,'P'); };
	bit	vec_type();
	Ptype	deref();
	inline	Pptr addrof();
	inline	bit is_or_pts_to(TOK);
	Pfct	memptr();
#endif
	Pname	is_cl_obj();	/* sets cl_obj_vec */
	void	del();
};

struct enumdef : type {	/* ENUM */
	bit	e_body;
	short	no_of_enumerators;
	unsigned char e_strlen;	// strlen(string) or strlen(local_sig)
	char*	string;		// name of enum
	Pname	mem;
	Pbase	e_type;		// type representing the enum
		enumdef(Pname n)	{ base=ENUM; mem=n; };
#ifndef GRAM
	void	print();
	void	dcl_print(Pname);
	void	dcl(Pname, Ptable);
	void	simpl();
#endif
};

struct velem {
	Pname	n;
	int	offset;
};

struct virt : node {
	Pvirt	next;
	int     n_init;
	velem*	virt_init;	// vector of vtbl initializers (zero-terminated)
	Pclass	vclass;		// for class vclass
	char*	string;
	bit	is_vbase;	// vtable for virtual base
	bit	printed;
 	virt(Pclass cl, velem* v, char* s, bit flag, int ni) {base = XVIRT; vclass=cl; virt_init=v; string=s; is_vbase=flag; next=0; n_init = ni;}
};

enum { C_VPTR=1, C_XREF=2, C_ASS=4, C_VBASE=8, C_REFM=16 };

typedef class cons *Pcons;
typedef class basic_template *Ptempl_base;

struct classdef : type {	/* CLASS */
        Templ_type  class_base; /* recognize template classes */
	bit	c_body;		/* print definition only once */
	TOK	csu;		/* CLASS, STRUCT, UNION, or ANON */
	bit	obj_align;
	bit	c_xref;
		// 1 set:	has vptr(s) 
		// 2 set:	X(X&) exists
		// 4 set:	operator=(X&) exists
		// 8 set:	has vbaseptr(s)
		// 16 set:	has reference data member(s)
		
	short	virt_count;	// number of virtual functions
				// starting at max base class virt_count in
	bit	virt_merge;	// set when no virtual functions, but
				// need to merge virtual base classes
	bit	has_vvtab;	// set if class has vtable from virtual base
	unsigned char c_strlen;	// strlen(string) or strlen(local_sig)
	Pbcl	baselist;	// list of base classes
	char*	string;		/* name of class */
	Pname	c_abstract;	// abstract class: don't instantiate: virt func name 
	Pname	mem_list;
	Ptable	memtbl;
	Pktab	k_tbl; //SYM parsing table
	Ptable	c_context;
	int	obj_size;
	int	real_size;	/* obj_size - alignment waste */
 	Pcons	templ_friends;  /* list of template friends: template <class T> friend ... */
	Plist	friend_list;
	Pname	pubdef;
	Ptype	this_type;
	Pvirt	virt_list;	// vtbl initializers
	Pname	c_ctor;		// constuctor: possibly overloaded
	Pname	c_dtor;		// destructor
	Pname	c_itor;		/* constructor X(X&) */
	Pname	c_vtor;		/* x::x() ctor for vec_new */
	Pname	conv;		/* operator T() chain */
	struct toknode *c_funqf, *c_funqr; // token Q for parsing function defs after class def

	classdef(TOK);
	~classdef();
	TOK	is_simple()	{ return (csu==CLASS)?0:csu; };
#ifndef GRAM
	void	print();
	void	dcl_print(Pname);
	void	simpl();

	void	print_members();
	void	dcl(Pname, Ptable);
	void	make_vec_ctor(Pname);

//	bit	has_friend(Pname);
	bit	has_friend(Pclass);
	bit	has_friend(Pfct);

	bit	has_base(Pclass cl,int level=0);
	bit	baseof(Pname);
	bit	baseof(Pclass);
	Pclass	is_base(char*,int level=0);

	Pname	has_oper(TOK);
	Pname	has_ctor()	{ return c_ctor; }
	Pname	has_dtor()	{ return c_dtor; }
	Pname	has_itor()	{ return c_itor; }
	Pname	has_vtor()	{ return c_vtor; }
	Pname	has_ictor();
	Pname	make_itor(int);

	Pexpr	find_name(char*, Pclass, int=0);
	int	do_virtuals(Pvirt, char*, int, bit);
	int	all_virt(Pclass, char*, int, bit);
	void	add_vtbl(velem*, char*, bit, int);
	void	print_all_vtbls(Pclass);
	void	print_vtbl(Pvirt);
	void	really_print(Pvirt);
	int	check_dup(Pclass, TOK);
	int	has_allocated_base(Pclass,bit=0);
	char 	*has_allocated_base(char*);
	int	get_offset(char*,bit=0);
	Pbcl	get_base(char*);
	Pexpr	get_vptr_exp(char*);
	Pexpr	find_in_base(char*, Pclass, int);
        void    modify_inst_names(char *s); // Adjust ctor names for instantiation
        bit     parametrized_class();
        bit 	same_class(Pclass p,int=0);
	bit	has_const_mem();
#endif
};

#ifndef GRAM

class clist {
	Pclass cl;
	clist* next;
public:
	clist(Pclass c, clist* n) { cl=c; next=n; }
	int onlist(Pclass);
	void clear();
};
	
extern clist * vcllist;

struct vl {
	struct vl* next;
	Pvirt vt;
	classdef* cl;

	vl(classdef* c, Pvirt v, struct vl* n)
		{ cl = c; vt = v; next = n; }
};

extern vl* vlist;

extern int nin;
extern int Noffset;
extern TOK Nvis;
extern TOK Nvirt;
extern Pexpr Nptr;
extern Pbcl Nvbc_alloc;
extern char *Nalloc_base;
extern Pexpr rptr(Ptype,Pexpr,int);
extern Pexpr vbase_args(Pfct, Pname);
extern Pexpr cdvec(Pname,Pexpr,Pclass,Pname,int,Pexpr,Pexpr=0);
extern Pexpr mk_zero_init(Ptype,Pname,Pname);

extern Pexpr find_name(Pname, Pclass, Ptable, int, Pname);
extern Pname find_virtual(Pclass,Pname);
extern Pname vfct(Pclass, char*);
extern int Vcheckerror;
extern int ignore_const;	

extern int mex;
extern Pclass mec;
extern Pclass tcl;
extern int processing_sizeof; // suppresscertain referencing errors for args to sizeof 
#endif

struct basetype : type
	/*	ZTYPE CHAR SHORT INT LONG FLOAT DOUBLE
		FIELD EOBJ COBJ TYPE ANY
	*/
	/*	used for gathering all the attributes
		for a list of declarators

		ZTYPE is the (generic) type of ZERO
		ANY is the generic type of an undeclared name
	*/
{
	bit	b_unsigned;
	bit	b_signed;
	bit	b_volatile;
	bit	b_typedef;
	bit	b_inline;
	bit	b_virtual;
	bit	b_short;
	bit	b_long;
	bit	b_bits;		/* number of bits in field */
	bit	b_offset;	// bit offset of field
	TOK	b_sto;		/* AUTO STATIC EXTERN REGISTER 0 */
	Pname	b_name;		/* name of non-basic type */
	Ptable	b_table;	/* memtbl for b_name, or 0 */
	Pname	b_xname;	/* extra name */
	union {
	Ptype	b_fieldtype;
	char*	b_linkage;
	};

	basetype(TOK, Pname);

	Pbase	type_adj(TOK);
	Pbase	base_adj(Pbase);
	Pbase	name_adj(Pname);
	Pname   aggr();
	Pbase	check(Pname);
#ifndef GRAM
	void	dcl_print();
 	Pbase	arit_conv(Pbase);
        bit     parametrized_class();
#endif
	int     discriminator(int); // union discriminator fcn 
};

enum Linkage { linkage_default, linkage_C, linkage_Cplusplus };
extern Linkage linkage;
void set_linkage(char*);

struct fct : type {		// FCT
	Templ_type fct_base;  	// recognize template function
	TOK	nargs;		// count of arguments
	TOK	nargs_known;	// 0 if unknown, 1 if known, or ELLIPSIS
	bit  	last_stmt;
	bit	f_vdef;		// 1 if this is the first virtual definition
				// of this function
	bit	f_inline;	// 1 if inline, 2 if being expanded, else 0
	bit	f_is_inline;	// because f_inline is set to 0
				//   before laying down static version of inline
	bit	f_const;	// one if member function that may be called for
				// a const object, else 0
	bit	f_static;	// 1 if static member function, else 0
	short	f_virtual;	// index in virtual table, or 0 meaning non-virtual
	short	f_imeasure;	// some measure of the size of an inline function
	Ptype	returns;
	Pname	argtype;
	Ptype	s_returns;
	Pname	f_this;
	Pclass	memof;		// member of class memof
	Pclass	def_context;	// defined in def_context (as for friends)
	Pblock	body;
	Pname	f_init;		// base and member initializers
	Pexpr	f_expr;		// body expanded into an expression
	Pexpr	last_expanded;
	Pname	nrv;		// named return value name
	Pname	f_result;	// extra second argument of type X&
	Pname	f_args;		// argument list including args added by cfront
	Linkage	f_linkage;
	char*	f_signature;	// character encoding of function type
	Plist local_class;	// list of local classes //SYM -- preserve for use in del.c
	static Pfct fct_free;
	void*	operator new(size_t);
	void	operator delete(void*,size_t);

	fct(Ptype, Pname, TOK);
	void	argdcl(Pname,Pname);
#ifndef GRAM
	Ptype	normalize(Ptype);
	void 	arg_print();
	void	dcl_print();
	void	dcl(Pname);
	Pexpr	base_init(Pclass, Pexpr, Ptable, int);
	Pexpr	mem_init(Pname, Pexpr, Ptable);
	void	init_bases(Pclass, Pexpr);
	bit	declared() { return nargs_known; };
	void	simpl();
	int	ctor_simpl(Pclass, Pexpr);
	Pstmt	dtor_simpl(Pclass, Pexpr);
	Pexpr	expand(Pname,Ptable,Pexpr);
	void	sign();
        int     is_templ() { return fct_base != VANILLA; }
#endif
	int     discriminator(int); // union discriminator fcn 
};

struct name_list : node {
	Pname	f;
	Plist	l;
        name_list(Pname ff, Plist ll);
};

#ifndef GRAM
enum gen_types { no_templ, some_templ, all_templ };

struct gen : type {		// OVERLOAD
	Plist	fct_list;
        gen_types holds_templ;    // does fct_list hold a template?

	gen() { base = OVERLOAD; }
	Pname	add(Pname);
	Pname  	find(Pfct, bit);
	Pname	match(Pname, Pfct, bit);
	Pname	exactMatch(Pexpr, int);
	Pname	oneArgMatch(Pexpr, int);
	Pname	multArgMatch(Pexpr, int);
        int     has_templ() { return holds_templ != no_templ; }
        int     pure_templ() { return holds_templ == all_templ; }
};
#endif

struct pvtyp : type {
	Ptype typ;
};

struct vec : pvtyp		// VEC
				// typ [ dim ]
{
	Pexpr	dim;
	int	size;	

	static Pvec vec_free;
	void*	operator new(size_t);
	void	operator delete(void*,size_t);

	vec(Ptype t, Pexpr e) { base=VEC; typ=t; dim=e; DBID(); }
#ifndef GRAM
	Ptype	normalize(Ptype);
#endif
};

struct ptr : pvtyp		// PTR, RPTR i.e. reference
{
	Pclass	memof;		// pointer to member of memof: memof::*
	Pname   ptname;		// template class: T::*, adjusted in type::dcl

	static Pptr ptr_free;
	void*	operator new(size_t);
	void	operator delete(void*,size_t);

	ptr(TOK b, Ptype t) { base=b; typ=t; DBID(); }
#ifndef GRAM
	Ptype	normalize(Ptype);
#endif
};

#ifndef GRAM
inline Pptr type::addrof() { return new ptr(PTR,this); }

inline bit
type::is_or_pts_to(TOK k)
{
	Ptype t = skiptypedefs();
	if (t->base == PTR) t = Pptr(t)->typ->skiptypedefs();
	return (t->base == k) ? 1 : 0;
}
#endif


/****************************** constants ********************************/

		/* STRING ZERO ICON FCON CCON ID */
		/* IVAL FVAL LVAL */

/***************************** expressions ********************************/

#ifndef GRAM
extern Pexpr next_elem();
extern void new_list(Pexpr);
extern void list_check(Pname, Ptype, Pexpr, Ptable=0);
extern Pexpr ref_init(Pptr,Pexpr,Ptable);
extern Pexpr class_init(Pexpr,Ptype,Pexpr,Ptable);
extern Pexpr check_cond(Pexpr, TOK, Ptable);
extern Pexpr ptof(Pfct,Pexpr,Ptable);
extern void dosimpl(Pexpr, Pname);
extern int ref_initializer;
extern int ntok;

extern void ptbl_init(int);
extern void ptbl_add_pair(char*,char*);
extern char *ptbl_lookup(char*);
extern char *st_name(char*);
#endif

struct expr : node	/* PLUS, MINUS, etc. */
	/* IMPORTANT:	all expressions are of sizeof(expr) */
	/*	DEREF		=>	*e1 (e2==0) OR e1[e2]
		UMINUS		=>	-e2
		INCR (e1==0)	=>	++e2
		INCR (e2==0)	=>	e1++
		CM		=>	e1 , e2
		ILIST		=>	LC e1 RC   (an initializer list)
		a Pexpr may denote a name
	*/
{
	union {
		Ptype	tp;
		char 	*string4;
	};
	union {
		Pexpr	e1;
		long	i1;
		char*	string;
	};
	union {
		Pexpr	e2;
		int	i2;
		char*	string2;
		Pexpr	n_initializer;
		Ptype	tpdef;  // local and nested typedef info
	};
	union {			/* used by the derived classes */
		Ptype	tp2;    
		Pname	fct_name; // of a call expr
		Pname	pt_name;  // T(); grammar: tp2 = $<pn>1->tp: oops...
		Pexpr	cond;
		Pexpr	mem;
		Ptype	as_type;
		Ptable	n_table;
		Pin	il;
		Pname	query_this; 
	};

	static Pexpr expr_free;
	void* operator new(size_t);
	void operator delete(void*,size_t);
	expr(TOK, Pexpr, Pexpr);
	void	del();
#ifndef GRAM
	void	print();
        Pexpr   typ0(Ptable);
	Pexpr	typ(Ptable);
	long	eval();
	unsigned long ueval(long,long);
	int	lval(TOK);
	Ptype	call_fct(Ptable);
	Pexpr	address();
	Pexpr	contents();
	void	simpl();
	Pexpr	expand();
	bit	not_simple();
	bit	is_const_obj();
	Pexpr	oper_overload(Ptable);
	Pexpr	docast(Ptable);
	Pexpr	dovalue(Ptable);
	Pexpr	donew(Ptable);
	void	simpl_new();
	void	simpl_delete();
#endif
	int     discriminator(int); // union discriminator fcn 
};

struct texpr : expr {		// G_CAST, CAST NEW VALUE (also ICALL)
	texpr(TOK bb, Ptype tt, Pexpr ee) : expr (bb,ee,0) { tp2=tt; }
};

struct cast : expr {		// G_CAST
	cast(Ptype tt, Pexpr ee) : expr (G_CAST,ee,0) { tp=tp2=tt; }
};

struct ival : expr {		// IVAL
	ival(long ii) : expr (IVAL,0,0) { i1 = ii;}
};

struct call : expr {		// CALL
	call(Pexpr aa, Pexpr bb) : expr (CALL,aa,bb) { }
#ifndef GRAM
	void	simpl();
	Pexpr	expand(Ptable);
#endif
};

struct qexpr : expr {		// QUEST	cond ? e1 : e2
	qexpr(Pexpr ee, Pexpr ee1, Pexpr ee2) : expr (QUEST,ee1,ee2) { cond=ee; }
};

struct ref : expr {		// REF DOT	e1->mem OR e1.mem
	ref(TOK ba, Pexpr a, Pexpr b) : expr (ba,a,0) { mem=b; }
};

struct mdot : expr {		// MDOT		a.b
	mdot(char* a, Pexpr b) : expr (MDOT,0,0) { string2=a; mem=b; }
};

struct text_expr : expr	{	// TEXT (vtbl_name)
	text_expr(char* a, char* b) : expr (TEXT,0,0)
	{ string=a; string2=b; }
};
extern char* vtbl_name(char*,char*);
/************************* names (are expressions) ****************************/

struct basecl : node {	// NAME		=> base class
			// VIRTUAL	=> virtual base class
	TOK	ppp;		// private / public / protected
	bit	allocated;	// allocated virtual base
        bit     promoted;       // non-explicit, promoted virtual base
	Pclass	bclass;
	Pexpr	init;		// base class initializers for ctors
	int	ptr_offset;	// pointer's relative position in derived class
	int	obj_offset;	// object's relative position in derived class
	Pname*	virt_init;	// vector of vtbl table initializers
	basecl*	next;

        basecl(Pclass cl, basecl* n) { baseclass=1; bclass=cl; next=n; promoted=0; init=0;}
};

enum template_formal_types { 
	template_type_formal =1 , template_expr_formal,
        template_actual_arg_dummy // used during the parse
};

extern TOK ppbase;

struct name : expr {	// NAME TNAME DTOR and the lexical keywords
	TOK	n_oper;		// name of operator or 0
	TOK	n_sto;		// EXTERN STATIC AUTO REGISTER ENUM 0
	TOK	n_stclass;	// STATIC AUTO REGISTER 0
	TOK	n_scope;	// EXTERN STATIC FCT ARG PUBLIC 0 
	TOK	n_key;	/* for names in table: class */
	bit	n_evaluated;	// 0 or n_val holds the value
	bit	n_xref;		// argument of type X(X&)
	unsigned char	lex_level;
	TOK	n_protect;	// PROTECTED (<=>n_scope==0) or 0
	bit	n_dcl_printed;	// 1: declaration printed
				// 2: definition printed
				// 0: declaration not printed

        // if this is set it implies that n_template_arg == template_type_formal
	char    n_template_arg; // One of template_formal_types for template arguments
	bit 	n_template_fct; // non-class template function
        bit     n_redefined ;   // set only for PT function names && classes 
				// where an explict definition was provided.
        bit     n_pt_class_arg; // nonmember template function signature
                                // contains class x<t> formal : permit conversions
	short	n_addr_taken;
	short	n_used;
	short	n_assigned_to;
	Loc where;
	int	n_offset;	// byte offset in frame or struct
	char*	n_anon;	// 0, or anon union object name 
	union {//SYM ???
	Pname	n_list;   // next name in arg or other list 
	Pname	n_hidden; //SYM type name hidden by this name in parse table
	Pname	n_dtag;   // base==DTOR -- name after ~ or 0 for basic type dtor
	};
	Pname	n_tbl_list;
	char    *n_gen_fct_name; // used to be punned with n_tbl_list.
        char    *n_template_arg_string ; // the mangled string name
	Pktab	n_ktable;//SYM parsing table in which name is entered
	union {
	/* 
	 * n_qualifier: name of containing class
	 * n_realscope: for labels (always entered in function table) 
         *		the table for the actual scope in which label occurred.
	 * syn_class: lex table only
	 */
		Pname	n_qualifier;	
                Ptable  n_realscope;    
		int     syn_class; 
        };

	/* n_val: the value of n_initializer */
	long	n_val;		
	/* for inlines, the number of the argument when base == ANAME */
	int argno;
	static Pname name_free;
	void* operator new(size_t);
	void operator delete(void*,size_t);
	name(char* =0);

	Pname	normalize(Pbase, Pblock, bit);
	Pname	tdef();
	Pname	tname(TOK);
	void	hide();
#ifndef GRAM
	Pname	dcl(Ptable,TOK);
	int	no_of_names();
	void	use()		{ n_used++; };
	void	assign();
	void	take_addr();
	void	check_oper(Pname);
	void	simpl();
	void	print(bit fullprint=0);
	void	dcl_print(TOK);
	void	field_align();
	Pname	dofct(Ptable,TOK);
	inline	Pfct get_fct();
        bit     is_template_fct() { return n_template_fct; }
	bit	inst_body();
	bit	finst_body();
	bit	dinst_body();
#endif
        // this works only for function templates which require type formals
        bit     is_template_arg() { return n_template_arg == template_type_formal; }
	void	del();
	inline Pfct fct_type();  
	int     discriminator(int); // union discriminator fcn 
};

extern int friend_in_class;
extern int in_class_dcl;

// from parser
extern int in_class_decl;
extern int parsing_class_members;
extern int in_mem_fct;
extern int in_arg_list;
extern Ptype in_typedef;
extern int	defer_check;	 // redefinition typedef check delay
extern int	declTag;	 // !1: inline, virtual mod permitted
extern Pname in_tag;
extern int DECL_TYPE;

/******************** statements *********************************/

struct stmt : node {	/* BREAK CONTINUE DEFAULT */
/*	IMPORTANT: all statement nodes have sizeof(stmt) */
	Pstmt	s;
	Pstmt	s_list;
	Loc	where;
	union {
		Pname	d; // goto/block -- destination
		Pexpr	e2; // for iteration
		Pstmt	has_default; // switch statement default
		int	case_value; 
		Ptype	ret_tp; // pair
	};
	union {
		Pexpr	e;
		bit	own_tbl;
		Pstmt	s2;
	};
	Ptable	memtbl;
	Pktab	k_tbl; //SYM parsing table
	union {
		Pstmt	for_init;
		Pstmt	else_stmt;
		Pstmt	case_list;
		Loc	where2; // location of } at end of block
				// in DO loops, location of conditional
	};

	static Pstmt stmt_free;
	void* operator new(size_t);
	void operator delete(void*,size_t);
	stmt(TOK, loc, Pstmt);
	void	del();
#ifndef GRAM
	void	print();
	void	dcl();
        void    dcl1(Pstmt&);
	void	reached();
	Pstmt	simpl();
	Pstmt	expand();
	Pstmt	copy();
	// PAIR and BLOCK pun on `e': if (s->e) not safe
	bit	has_expr() { return (base != BLOCK && base != PAIR)?e!=0:0; }
#endif
	int     discriminator(int); // union discriminator fcn 
};

#ifndef GRAM
extern char* Neval;
extern Ptable scope;
extern Ptable expand_tbl;
extern Pname expand_fn;
#endif

struct estmt : stmt	/* SM WHILE DO SWITCH RETURN CASE */
	/*	SM (e!=0)	=>	e;
		in particular assignments and function calls
		SM (e==0)	=>	;	(the null statement)
		CASE		=>	case e : s ;
		SM_PARAM        => e is the template_statement_tree_formal name
	*/
{
	estmt(TOK t, loc ll, Pexpr ee, Pstmt ss) : stmt (t,ll,ss) { e=ee;}
};

struct ifstmt : stmt	/* IF */
	// else_stmt==0 =>	if (e) s
	// else_stmt!=0 =>	if (e) s else else_stmt
{
	ifstmt(loc ll, Pexpr ee, Pstmt ss1, Pstmt ss2)
		: stmt (IF,ll,ss1) { e=ee; else_stmt=ss2; };
};

struct lstmt : stmt	/* LABEL GOTO */
	/*
		d : s
		goto d
	*/
{
	lstmt(TOK bb, loc ll, Pname nn, Pstmt ss) : stmt (bb,ll,ss) { d=nn; }
};

struct forstmt : stmt {	// FOR
	forstmt(loc ll, Pstmt fss, Pexpr ee1, Pexpr ee2, Pstmt ss)
		: stmt (FOR,ll,ss) { for_init=fss; e=ee1; e2=ee2; }
};

struct block : stmt {	// BLOCK	{ d s }
	block(loc ll, Pname nn, Pstmt ss, loc rr = noloc ) : stmt (BLOCK,ll,ss)
		{ d=nn; where2=rr; }
#ifndef GRAM
	void	dcl(Ptable);
	Pstmt	simpl();
#endif
};

struct handler : stmt {	// not implemented -- currently set to BLOCK
	handler( Pstmt tt, Pstmt hh ) : stmt (BLOCK,tt?tt->where:curloc,tt)
		{ d=0; s->s_list=hh; where2=curloc; }
};

#ifndef GRAM
struct pair : public stmt {	// PAIR
	pair(loc ll, Pstmt a, Pstmt b) : stmt (PAIR,ll,a) { s2 = b; }
};
#endif

struct nlist {
	Pname	head;
	Pname	tail;
		nlist(Pname);
	void	add(Pname n)	{ tail->n_list = n; tail = n; };
	void	add_list(Pname);
};

extern Pname name_unlist(nlist*);

struct slist {
	Pstmt	head;
	Pstmt	tail;
		slist(Pstmt s)	{ /*Nl++;*/ head = tail = s; };
	void	add(Pstmt s)	{ tail->s_list = s; tail = s; };
};

extern Pstmt stmt_unlist(slist*);

struct elist {
	Pexpr	head;
	Pexpr	tail;
		elist(Pexpr e)	{ /*Nl++;*/ head = tail = e; };
	void	add(Pexpr e)	{ tail->e2 = e; tail = e; };
};

extern Pexpr expr_unlist(elist*);

#ifndef GRAM 
extern class dcl_context * cc;

#define MAXCONT	100
extern dcl_context ccvec[/* plan 9 MAXCONT */];

struct dcl_context {
	Pname	c_this;	/* current fct's "this" */
	Ptype	tot;	/* type of "this" or 0 */
	Pname	not;	/* name of "this"'s class or 0 */
	Pclass	cot;	/* the definition of "this"'s class */
	Ptable	ftbl;	/* current fct's symbol table */
	Pname	nof;	/* current fct's name */

	void	stack()		{
					cc++;
					cc >= &ccvec[MAXCONT] ?
					    error('i', "ccvec buffer overflow")
					    :
					    0;
					*cc = *(cc-1);
				};
	void	unstack()	{ cc--; };
};

#endif 

extern void yyerror(const char*);


#ifndef GRAM
extern char* line_format;

extern Plist stat_mem_list;
extern Plist isf_list;
extern Pstmt st_ilist;
extern Pstmt st_dlist;
extern Ptable sti_tbl;
extern Ptable std_tbl;
extern int need_sti( Pexpr e, Ptable tbl = 0, bit is_static_ok = 0 ); 
Pexpr try_to_coerce(Ptype, Pexpr, char*, Ptable);
extern bit can_coerce(Ptype, Ptype);
extern Ptype np_promote(TOK, TOK, TOK, Ptype, Ptype, TOK, bit=1);
extern bit enum_promote;
extern int suppress_error;
extern void delete_local();

extern int over_call(Pname, Pexpr);
extern Pname overFound;
extern Pname Nover;
extern Pname Ncoerce;
extern Nover_coerce;
struct ia : node {
	Pname	local;	// local variable for argument
	Pexpr	arg;	// actual arguments for call
	Ptype	tp;	// type of formal argument
        ia() { base = XIA; };
};

struct iline : node {
	Pname	fct_name;	/* fct called */
	Pin	i_next;
	Ptable	i_table;
	int	i_slots;	// no of arg slots pointer to by i_args
	ia*	i_args;
        iline() { base = XILINE; };
};

struct con_dtor {
    Pname tn;
    Pexpr condition;
    con_dtor *next;
    con_dtor(Pname n, Pexpr e)
        : tn(n), condition(e), next(0) {}
};

extern con_dtor *pdlist;
extern Pexpr curr_expr;
extern Pin curr_icall;
#define FUDGE111 11111
#define VTOK 22222
#define ITOR 77

extern Pstmt curr_loop;
extern Pblock curr_block;
extern Pstmt curr_switch;
extern loc last_line;  // last #line + number of '\n's output since
extern int last_ll;    // 0 or line of current stmt/dcl being printed
extern FILE* out_file; // output file descriptor
extern bit Cast;
extern bit TCast;
extern bit simpl_friend; // are we simplifying a friend function
extern bit in_return; // are we calling ref_init with a RETURN
extern loc no_where;

extern no_of_undcl;
extern no_of_badcall;
extern Pname undcl, badcall;

extern long str_to_long(const char*);
extern int c_strlen(const char* s);
#endif

#ifndef GRAM
extern Pname vec_new_fct;
extern Pname new_fct;
extern Pname del_fct;
extern Pname vec_del_fct;

extern int Nstd; // standard coercion used (derived* =>base* or int=>long or ...)

extern int stcount;	// number of names generated using make_name()

Pexpr replace_temp(Pexpr,Pexpr);
void make_res(Pfct);

extern int Pchecked;
Pexpr ptr_init(Pptr,Pexpr,Ptable);
Pexpr call_ctor(Ptable, Pexpr p, Pexpr ctor, Pexpr args, int d = REF, Pexpr vb_args = 0);
Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg = 0, int d = DOT, Pexpr vb_args = 0);
void check_visibility(Pname, Pname, Pclass, Ptable, Pname);

int make_assignment(Pname);

extern Pname make_tmp(char, Ptype, Ptable);
Pexpr init_tmp(Pname, Pexpr, Ptable);
extern Pname Ntmp;
extern Pname Ntmp_refd;
extern Pname Ntmp_flag;
extern Pexpr Ntmp_dtor;

extern int is_unique_base(Pclass, char*, int, int = 0);
extern Pexpr rptr(Ptype, Pexpr, int);

extern int read_align(char*);
extern void new_init();

extern void Eprint(Pexpr);
extern Pexpr cast_cptr(Pclass ccl, Pexpr ee, Ptable tbl, int real_cast);
extern Pexpr mptr_assign(Pexpr,Pexpr);
extern Pclass Mptr;

#endif

extern bit fake_sizeof;	// suppress error message for ``int v[];''

extern TOK lalex();

// encapsulate casts
inline Pname type::bname() { return Pbase(this)->b_name; }
inline Ptype type::bname_type() { return Pbase(this)->b_name->tp; }
//move to typ.c because 2.0 bug
/*
inline Pclass type::classtype() { 
    return (base==COBJ)?Pclass(Pbase(this)->b_name->tp)
	: (error('i',"T::classtype(): %k cobjX",base),0); 
}
*/

inline Penum type::enumtype() { 
    return (base==EOBJ)?Penum(Pbase(this)->b_name->tp)
	: (error('i',"T::enumtype(): %k eobjX",base),0); 
}

inline Pfct name::fct_type() { 
    return (tp->base==FCT) ? Pfct(tp)
	: (error('i',"N::fct_type():%n is %k notF",this,tp->base),0); 
}

inline bit type::is_templ_instance() {
        Templ_type t = (base==FCT)
                ? Pfct(this)->fct_base
                : (base==CLASS)
                ? Pclass(this)->class_base : (Templ_type)0;
        return (t==INSTANTIATED || t==UNINSTANTIATED);
}

#ifndef GRAM
inline Pfct name::get_fct() { 
    return (tp->base==FCT) ? Pfct(tp)
	: Pfct(Pgen(tp)->fct_list->f->tp);
}

inline Pname
table::insert_copy(Pname n, TOK k)
{
	Pname nn = new name; *nn = *n;
	nn->n_table = 0; nn->n_tbl_list = 0;
	return insert(nn,k);
}
#endif

#ifdef DBG
extern "C" {
extern void display_expr( Pexpr, char* = 0, int = 0 );
extern void display_stmt( Pstmt, char* = 0, int = 0 );
extern void display_type( Ptype );
extern void display_namelist( Plist, char* = 0, int = 0 );
#ifndef GRAM
extern void display_context( dcl_context*, char* = "", int = 0 );
#endif
extern void process_debug_flags( char* );
}
#define DB(a) if(scan_started){a;}
extern int Adebug; // allocation (ctor/del) debugging
extern int Bdebug; // table.c debugging
extern char* Bdebarg; // arg for B flag
extern int Ddebug; // dcl debugging
extern int Edebug; // expr debugging
extern int Kdebug; // parsing table debugging
extern int Ldebug; // lex/lalex debugging
extern int Mdebug; // trace function matching
extern int Ndebug; // norm debugging
extern int Pdebug; // print debugging
extern int Rdebug; // run() debugging
extern int Sdebug; // simpl debugging
extern int Tdebug; // typ debugging
#define Ydebug yydebug
extern int Ydebug; // yacc debugging

#else

#define DB(a) /**/

#endif

#endif
/* end */
