// Copyright (C) 1989-1997 by Symantec
// Copyright (C) 2000-2009 by Digital Mars
// All Rights Reserved
// http://www.digitalmars.com
// Written by Walter Bright
/*
 * This source file is made available for personal use
 * only. The license is in /dmd/src/dmd/backendlicense.txt
 * or /dm/src/dmd/backendlicense.txt
 * For any other uses, please contact Digital Mars.
 */

/* Definitions only used by the parser			*/

//#pragma once
#ifndef PARSER_H
#define PARSER_H 1

#if SCPP
#ifndef SCOPE_H
#include	"scope.h"
#endif
#endif

#ifndef __TYPE_H
#include	"type.h"
#endif

#if TX86
extern linkage_t linkage;	/* current linkage that is in effect	*/
extern int linkage_spec;	/* !=0 if active linkage specification	*/

#if MEMMODELS == 1
extern tym_t functypetab[LINK_MAXDIM];
#define FUNC_TYPE(l,m) functypetab[l]
#else
extern tym_t functypetab[LINK_MAXDIM][MEMMODELS];
#define FUNC_TYPE(l,m) functypetab[l][m]
#endif

extern mangle_t funcmangletab[LINK_MAXDIM];
extern mangle_t varmangletab[LINK_MAXDIM];

#else
#include	"TGparser.h"
#endif

#ifndef EL_H
#include	"el.h"
#endif

/* Type matches	*/
#define TMATCHnomatch	0	/* no match				*/
#define TMATCHellipsis	0x01	/* match using ellipsis			*/
#define TMATCHuserdef	0x09	/* match using user-defined conversions	*/
#define TMATCHboolean	0x0E	// conversion of pointer or pointer-to-member to boolean
#define TMATCHstandard	0xFA	/* match with standard conversions	*/
#define TMATCHpromotions 0xFC	/* match using promotions		*/
#define TMATCHexact	0xFF	/* exact type match			*/

typedef unsigned char match_t;

#if SCPP
struct Match
{
    match_t m;
    match_t m2;		// for user defined conversion, this is the second
			// sequence match level (the second sequence is the
			// one on the result of the user defined conversion)
    Symbol *s;		// user defined conversion function or constructor
    int ref;		// !=0 if reference binding
    tym_t toplevelcv;

    Match()
    {	m = 0;
	m2 = 0;
	s = NULL;
	ref = 0;
	toplevelcv = 0;
    }

    static int cmp(Match& m1, Match& m2);
};
#endif

/***************************
 * Type of destructor call
 */

#define DTORfree	1	// it is destructor's responsibility to
				//   free the pointer
#define DTORvecdel	2	// delete array syntax
#define DTORmostderived	4	// destructor is invoked for most-derived
				//  instance, not for a base class
#define DTORvector	8	// destructor has been invoked for an
				//   array of instances of known size
#define DTORvirtual	0x10	// use virtual destructor, if any
#define DTORnoeh	0x20	// do not append eh stuff
#define DTORnoaccess	0x40	// do not perform access check

/***************************
 * Macros.
 */
#if TARGET_POWERPC
#pragma ZTC align 4
#elif !TX86
#pragma ZTC align 1
#endif

struct MACRO
{
#ifdef DEBUG
    unsigned short	id;
#define IDmacro 0x614D
#define macro_debug(m) assert((m)->id == IDmacro)
#else
#define macro_debug(m)
#endif

    char *Mtext;		// replacement text
    list_t Marglist;		// list of arguments (as char*'s)
    macro_t *ML,*MR;
#if TX86
    macro_t *Mnext;		// next macro in threaded list (all macros
				// are on one list or another)
#endif
    unsigned char Mflags;
#define	Mdefined	1	// if macro is defined
#define Mfixeddef	2	// if can't be re/un defined
#define Minuse		4	// if macro is currently being expanded
#define Mellipsis	0x8	// if arglist had trailing ...
#define Mnoparen	0x10	// if macro has no parentheses
#define Mkeyword	0x20	// this is a C/C++ keyword
#define Mconcat		0x40	// if macro uses concat operator
#define Mnotexp 	0x80	// if macro should be expanded
    unsigned char Mval;		// if Mkeyword, this is the TKval
#if TX86    
    char Mid[1];		// macro identifier
#else
    str4 Mid[];			/* macro identifier as a 4 byte string */
#endif
};

#if !TX86
#pragma ZTC align
#endif

/**********************
 * Flags for #include files.
 */

#define FQcwd		1	// search current working directory
#define FQpath		2	// search INCLUDE path
#define FQsystem	4	// this is a system include
#if TX86
#define FQtop		8	// top level file, already open
#define FQqual		0x10	// filename is already qualified
#endif
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
#define FQnext		0x20	// search starts after directory
#endif				// of last included file

/***************************************************************************
 * Which block is active is maintained by the BLKLST, which is a backwardly
 * linked list of which blocks are active.
 */

struct BLKLST
{
    /* unsigned because of the chars with the 8th bit set	*/
    unsigned char  *BLtextp;	/* current position in text buffer	*/
    unsigned char  *BLtext;	/* start of text buffer			*/
    struct BLKLST  *BLprev;	/* enclosing blklst			*/
    unsigned char   BLflags;	/* input block list flags		*/
#	define BLspace	 0x01	/* we've put out an extra space		*/
#	define BLexpanded 0x40	// already macro expanded; don't do it again
#if IMPLIED_PRAGMA_ONCE
#	define BLnew	 0x02	/* start of new file 			*/
#	define BLfndif	 0x04	/* found initial #ifdef at start	*/
#	define BLckendif 0x08	/* check if looking for EOF after #endif */
#	define BLckonce  (BLnew|BLfndif|BLckendif)
			 	/* check if file only included once	*/
#	define BLclear	 0xf1	/* to clear implied pragma once flags	*/
#endif
#if PRAGMA_ONCE
#	define BLponce	 0x10	/* pragma - only include this file once	*/
#endif
#if TARGET_MAC
#	define BFpdef	 0x20	/* pre-compilation definition block 	*/
#endif
    char	BLtyp;		/* type of block (BLxxxx)		*/
#	define BLstr	2	/* string				*/
#	define BLfile	3	/* a #include file			*/
#	define BLarg	4	/* macro argument			*/
#	define BLrtext	5	// random text

    list_t	BLaargs;	/* actual arguments			*/
    list_t	BLeargs;	/* actual arguments			*/
    int		BLnargs;	/* number of dummy args			*/
    int		BLtextmax;	/* size of text buffer			*/
#if INDIVFILEIO
    unsigned char *BLbuf;	// BLfile: file buffer
    unsigned char *BLbufp;	// BLfile: next position in file buffer
#else
    FILE	*BLstream;	/* BLfile				*/
#endif
    Srcpos	BLsrcpos;	/* BLfile, position in that file	*/
#if SOURCE_OFFSETS
    long 	BLfoffset;	/* BLfile, offset into file		*/
    short 	BLcurcnt;	/* BLfile, current count from offset	*/
    short 	BLlincnt;	/* BLfile, start of cur line from offset*/
#endif
    TARGET_structBLKLST

    void print();
};

struct BlklstSave
{
    blklst *BSbl;
    unsigned char *BSbtextp;
    unsigned char BSxc;
};

#if IMPLIED_PRAGMA_ONCE
extern int TokenCnt;
#endif

#if TX86
/* Get filename for BLfile block	*/
#define blklst_filename(b)	(srcpos_name((b)->BLsrcpos))
#endif

/* Different types of special values that can occur in the character stream */
#define PRE_ARG	0xFF	// the next char following is a parameter number
			// If next char is PRE_ARG, then PRE_ARG is the char
#define PRE_BRK 0xFE	// token separator
#define PRE_STR 0xFA	// If immediately following PRE_ARG, then the
			// parameter is to be 'stringized'
#define PRE_EXP	0xFC	// following identifier may not be expanded as a macro
#define PRE_CAT 0xFB	// concatenate tokens
#define PRE_EOB 0	// end of block
#define PRE_EOF 0	// end of file
#define PRE_SPACE  0xFD	// token separator

#define PRE_ARGMAX 0xFB	// maximum number of arguments to a macro

#if 1
#define EGCHAR()						\
	((((xc = *btextp) != PRE_EOB && xc != PRE_ARG)	\
	?   (btextp++,(config.flags2 & CFG2expand && (explist(xc),1)),1) \
	:   egchar2()						\
	),xc)
#else
#define EGCHAR() egchar()
#endif

/**********************************
 * Function return value methods.
 */

#define RET_REGS	1	/* returned in registers		*/
#define RET_STACK	2	/* returned on stack			*/
#define RET_STATIC	4	/* returned in static memory location	*/
#define RET_NDPREG	8	/* returned in floating point register	*/
#define RET_PSTACK	2	// returned on stack (DOS pascal style)

/* from blklst.c */
CEXTERN	blklst *bl;
CEXTERN	unsigned char *btextp;
extern int blklst_deferfree;
extern char *eline;
extern int elinmax;		/* # of chars in buffer eline[]		*/
extern int elini;		/* index into eline[]			*/
extern int elinnum;		/* expanded line number			*/
CEXTERN int expflag;		/* != 0 means not expanding list file	*/
blklst *blklst_getfileblock(void);
void putback(int);
#if PRAGMA_ONCE
extern blklst *Once;
void *once_dehydrate(void);
void once_hydrate(blklst *);
#endif

unsigned char *macro_replacement_text(macro_t *m, list_t args);
unsigned char *macro_rescan(macro_t *m, unsigned char *text);
unsigned char *macro_expand(unsigned char *text);

CEXTERN void explist(HINT);
void expstring(char *);
void expinsert(int);
void expbackup(void);
void wrtexp(FILE *);
CEXTERN UHINT egchar2(void);
CEXTERN UHINT egchar(void);

void insblk(unsigned char *text,int typ,list_t aargs,int nargs,macro_t *m);
void insblk2(unsigned char *text,int typ);

#if TARGET_MAC || __GNUC__
unsigned getreallinnum();
CEXTERN void getcharnum(void);
#endif

Srcpos getlinnum(void);
unsigned blklst_linnum(void);
void blklst_term();

/* adl.c */
symbol *adl_lookup(char *id, symbol *so, list_t arglist);

/* exp.c */

/* exp2.c */
extern elem *typechk(elem *,type *),
	*exp2_cast(elem *,type *),
	*cast(elem *,type *),
	*doarray(elem *),
	*doarrow(elem *),
	*xfunccall(elem *efunc,elem *ethis,list_t pvirtbase,list_t arglist),
	*exp2_gethidden(elem *e),
	*dodotstar(elem *, elem *),
	*reftostar(elem *),
	*reftostart(elem *,type *),
	*exp2_copytotemp(elem *),
	*dofunc(elem *),
	*builtinFunc(elem *),
	*arraytoptr(elem *),
	*convertchk(elem *),
	*lptrtooffset(elem *),
	*dodot(elem *,type *,bool bColcol),
	*minscale(elem *);
elem *exp2_addr(elem *);
void getarglist(list_t *);
elem *exp2_ptrvbaseclass(elem *ethis,Classsym *stag,Classsym *sbase);
int t1isbaseoft2(type *,type *);
int c1isbaseofc2(elem **,symbol *,symbol *);
int c1dominatesc2(symbol *stag, symbol *c1, symbol *c2);
int exp2_retmethod(type *);
type *exp2_hiddentype(type *);
int typematch(type *,type *,int);
int typecompat(type *,type *);
int t1isSameOrSubsett2(type *,type *);
void handleaccess(elem *);
void chkarithmetic(elem *);
void chkintegral(elem *);
void scale(elem *);
void impcnv(elem *);
void exp2_ptrtocomtype(elem *);
int  exp2_ptrconv(type *,type *);
void getinc(elem *);
int paramlstmatch(param_t *,param_t *);
int template_paramlstmatch(type *, type *);

/* from file.c */
extern char ext_obj[];
extern char ext_i[];
extern char ext_dep[];
extern char ext_lst[];
extern char ext_hpp[];
extern char ext_c[];
extern char ext_cpp[];
extern char ext_sym[];
extern char ext_tdb[];
#if HTOD
extern char ext_dmodule[];
extern int includenest;
#endif

int file_qualify(char **pfilename,int flag);
void afopen(char *,blklst *,int);
FILE *file_openwrite(const char *name,const char *mode);
void file_iofiles(void);
int readln(void);
void wrtpos(FILE *);
void wrtlst(FILE *);

/* from func.c */
void func_nest(symbol *);
void func_body(symbol *);
elem *addlinnum(elem *);
void func_conddtors(elem **pe, SYMIDX sistart, SYMIDX siend);
void func_expadddtors(elem **,SYMIDX,SYMIDX,bool,bool);
void paramtypadj(type **);
void func_noreturnvalue(void);
elem *func_expr_dtor(int keepresult);
elem *func_expr();

/* getcmd.c */
extern unsigned long netspawn_flags;
void getcmd(int,char *[]);
void getcmd_term(void);

/* init.c */
void datadef(symbol *);
dt_t **dtnbytes(dt_t **,targ_size_t,const char *);
dt_t **dtnzeros(dt_t **pdtend,targ_size_t size);
dt_t **dtxoff(dt_t **pdtend,symbol *s,targ_size_t offset,tym_t ty);
dt_t **dtcoff(dt_t **pdtend,targ_size_t offset);
void dtsymsize(symbol *);
void init_common(symbol *);
symbol *init_typeinfo_data(type *ptype);
symbol *init_typeinfo(type *ptype);
elem *init_constructor(symbol *,type *,list_t,targ_size_t,int,symbol *);
void init_vtbl(symbol *,symlist_t,Classsym *,Classsym *);
void init_vbtbl(symbol *,baseclass_t *,Classsym *,targ_size_t);
void init_sym(symbol *, elem *);

/* inline.c */
void inline_do(symbol *sfunc);
bool inline_possible(symbol *sfunc);

/* msc.c */
void list_hydrate(list_t *plist, void (*hydptr)(void *));
void list_dehydrate(list_t *plist, void (*dehydptr)(void *));
void list_hydrate_d(list_t *plist);
void list_dehydrate_d(list_t *plist);

// nspace.c
void namespace_definition();
void using_declaration();
symbol *nspace_search(const char *id,Nspacesym *sn);
symbol *nspace_searchmember(const char *id,Nspacesym *sn);
symbol *nspace_qualify(Nspacesym *sn);
symbol *nspace_getqual(int);
void nspace_add(void *snv,symbol *s);
void nspace_addfuncalias(Funcsym *s,Funcsym *s2);
symbol *using_member_declaration(Classsym *stag);
void scope_push_nspace(Nspacesym *sn);
void nspace_checkEnclosing(symbol *s);
int nspace_isSame(symbol *s1, symbol *s2);

#if TARGET_MAC
/* TGnwc.c */
void ext_init(void);
void ext_term(void);
void nwc_chkmain(symbol *,enum SC);
#endif

/* nwc.c */
void thunk_hydrate(struct Thunk **);
void thunk_dehydrate(struct Thunk **);
void nwc_defaultparams(param_t *,param_t *);
void nwc_musthaveinit(param_t *);
void nwc_addstatic(symbol *);
void output_func(void);
void queue_func(symbol *);
void savesymtab(func_t *f);
void nwc_mustwrite(symbol *);
void ext_def(int);
type *declar_abstract(type *);
type *new_declarator(type *);
type *ptr_operator(type *);
type *declar_fix(type *,char *);
void fixdeclar(type *);
type *declar(type *,char *,int);
int type_specifier(type **);
int declaration_specifier(type **ptyp_spec, enum SC *pclass, unsigned long *pclassm);
symbol *id_expression();
elem *declaration(int flag);
int funcdecl(symbol *,enum SC,int,Declar *);
symbol *symdecl(char *,type *,enum SC,param_t *);
void nwc_typematch(type *,type *,symbol *);
int isexpression(void);
void nwc_setlinkage(char *,long,mangle_t);
tym_t nwc_declspec();

/* struct.c */
type *stunspec(enum_TK tk, Symbol *s, Symbol *stempsym, param_t *template_argument_list);
Classsym * n2_definestruct(char *struct_tag,unsigned flags,tym_t ptrtype,
	symbol *stempsym,param_t *template_argument_list,int nestdecl);
void n2_classfriends(Classsym *stag);
int n2_isstruct(symbol * __ss *ps);
void n2_addfunctoclass(Classsym *,Funcsym *,int flags);
void n2_chkexist(Classsym *stag, char *name);
void n2_addmember(Classsym *stag,symbol *smember);
symbol *n2_searchmember(Classsym *,const char *);
symbol *struct_searchmember(const char *,Classsym *);
void n2_instantiate_memfunc(symbol *s);
type *n2_adjfunctype(type *t);
int n2_anypure(list_t);
void n2_genvtbl(Classsym *stag, enum SC sc , int);
void n2_genvbtbl(Classsym *stag, enum SC sc , int);
void n2_creatector(type *tclass);
/*void n2_createdtor(type *tclass);*/
symbol *n2_createprimdtor(Classsym *stag);
symbol *n2_createpriminv(Classsym *stag);
symbol *n2_createscaldeldtor(Classsym *stag);
symbol *n2_vecctor(Classsym *stag);
symbol *n2_veccpct(Classsym *stag);
symbol *n2_vecdtor(Classsym *stag, elem *enelems);
symbol *n2_delete(Classsym *stag,symbol *sfunc,unsigned nelems);
void n2_createopeq(Classsym *stag, int flag);
void n2_lookforcopyctor(Classsym *stag);
int n2_iscopyctor(symbol *scpct);
void n2_createcopyctor(Classsym *stag, int flag);
char *n2_genident (void);
symbol *nwc_genthunk(symbol *s, targ_size_t d, int i, targ_size_t d2);
type *enumspec(void);
int type_covariant(type *t1, type *t2);

/* ph.c */
extern char *ph_directory;		/* directory to read PH files from	*/
#if MARS
void ph_init();
#else
void ph_init(void *, unsigned reservesize);
#endif
void ph_term(void);
void ph_comdef(symbol *);
void ph_testautowrite(void);
void ph_autowrite(void);
void ph_write(const char *,int);
void ph_auto(void);
int ph_read(char *filename);
int ph_autoread(char *filename);
void *ph_malloc(size_t nbytes);
void *ph_calloc(size_t nbytes);
void ph_free(void *p);
#if TX86
void *ph_realloc(void *p , size_t nbytes);
#else
void *ph_realloc(void *p , size_t nbytes,unsigned short uFlag);
#endif
void ph_add_global_symdef(symbol *s, unsigned sctype);

#if H_STYLE & H_OFFSET
#define dohydrate	ph_hdradjust
#define isdehydrated(p)	(ph_hdrbaseaddress <= (p) && (p) < ph_hdrmaxaddress)
#define ph_hydrate(p)	((isdehydrated(*(void **)(p)) && (*(char **)(p) -= ph_hdradjust)),*(void **)(p))
#define ph_dehydrate(p)	((void)(p))
extern void *ph_hdrbaseaddress;
extern void *ph_hdrmaxaddress;
extern int   ph_hdradjust;
#elif H_STYLE & H_BIT0
#define dohydrate	1
#define isdehydrated(p)	((int)(p) & 1)
extern int ph_hdradjust;
#define ph_hydrate(p)	((isdehydrated(*(void **)(p)) && (*(char **)(p) -= ph_hdradjust)),*(void **)(p))
#define ph_dehydrate(p)	((*(long *)(p)) && (*(long *)(p) |= 1))
#elif H_STYLE & H_COMPLEX
#define dohydrate	1
#define isdehydrated(p)	((int)(p) & 1)
void *ph_hydrate(void *pp);
void *ph_dehydrate(void *pp);
#elif H_STYLE & H_NONE
#define dohydrate	0
#define isdehydrated(p)	0
#define ph_hydrate(p)	(*(void **)(p))
#define ph_dehydrate(p)	((void)(p))
#else
#error "H_STYLE set wrong"
#endif

/* pragma.c */
#if PRAGMA_PARAM
extern short pragma_param_cnt;
#endif
int __near pragma_search(char *id);
macro_t *__near macfind(void);
void __near listident(void);
char *filename_stringize(char *name);
unsigned char *macro_predefined(macro_t *m);
int macprocess(macro_t *m, list_t *pargs, BlklstSave *blsave);
void pragma_include(char *filename,int flag);
void pragma_init(void);
void pragma_term(void);
macro_t *defmac(const char *name , const char *text);
void definedmac();
macro_t *fixeddefmac(const char *name , const char *text);
macro_t *defkwd(const char *name , enum_TK val);
void macro_freelist(macro_t *m);
int pragma_defined(void);
void macro_print(macro_t *m);
void macrotext_print(char *p);

void pragma_hydrate_macdefs(macro_t **pmb,int flag);
void pragma_dehydrate_macdefs(macro_t **pm);

void *pragma_dehydrate(void);
void pragma_hydrate(macro_t **pmactabroot);

// rtti.c
Classsym *rtti_typeinfo();
elem *rtti_cast(enum_TK,elem *,type *);
elem *rtti_typeid(type *,elem *);

/* symbol.c */
char *symbol_ident(symbol *s);
symbol *symbol_search(const char *);
void symbol_tree_hydrate(symbol **ps);
void symbol_tree_dehydrate(symbol **ps);
symbol *symbol_hydrate(symbol **ps);
void symbol_dehydrate(symbol **ps);

inline Classsym *Classsym_hydrate(Classsym **ps)
{
    return (Classsym *) symbol_hydrate((symbol **)ps);
}

inline void Classsym_dehydrate(Classsym **ps)
{
    symbol_dehydrate((symbol **)ps);
}

void symbol_symdefs_dehydrate(symbol **ps);
void symbol_symdefs_hydrate(symbol **ps,symbol **parent,int flag);
void symboltable_hydrate(symbol *s, symbol **parent);
void symboltable_clean(symbol *s);
void symboltable_balance(symbol **ps);
symbol *symbol_membersearch(const char *id);
void symbol_gendebuginfo(void);

/* template.c */
#if TEMPLATE_ACCESS
extern enum SC template_access;
int template_getcmd(char,char *);
#else
int template_getcmd(char *);
#endif
void template_declaration(Classsym *stag, unsigned access_specifier);
void template_instantiate(void);
type *template_expand_type(symbol *s);
Classsym *template_expand(symbol *s, int flag);
void template_instantiate_forward(Classsym *stag);
param_t *template_gargs(symbol *s);
param_t *template_gargs2(symbol *s);
void template_createsymtab(param_t *pt , param_t *p);
void template_deletesymtab(void);
symbol *template_createsym(const char *id, type *t, symbol **proot);
char *template_mangle(symbol *s , param_t *arglist);
symbol *template_matchfunc(symbol *stemp, param_t *pl, int, match_t, param_t *ptal, symbol *stagfriend = NULL);
symbol *template_matchfunctempl(symbol *sfunc, param_t *ptali, type *tf, symbol *stagfriend = NULL, int flags = 1);
int template_match_expanded_type(type *ptyTemplate, param_t *ptpl, param_t *ptal, type *ptyActual, 
	type *ptyFormal );
int template_classname(char *vident, Classsym *stag);
void template_free_ptal(param_t *ptal);
#if TARGET_MAC
bool template_match_expanded_type(type *ptyTemplate, param_t *ptal, type *ptyActual, 
	type *ptyFormal );
#endif
int template_function_leastAsSpecialized(symbol *f1, symbol *f2, param_t *ptal);
#if SCPP
Match template_matchtype(type *tp,type *te,elem *ee,param_t *ptpl, param_t *ptal, int flags);
Match template_deduce_ptal(type *tthis, symbol *sfunc, param_t *ptali,
	Match *ma, int flags, param_t *pl, param_t **pptal);
#endif
void template_function_verify(symbol *sfunc, list_t arglist, param_t *ptali, int matchStage);
int template_arglst_match(param_t *p1, param_t *p2);
type * template_tyident(type *t,param_t *ptal,param_t *ptpl, int flag);

void tmf_free(TMF *tmf);
void tmf_hydrate(TMF **ptmf);
void tmf_dehydrate(TMF **ptmf);

void tme_free(TME *tme);
void tme_hydrate(TME **ptme);
void tme_dehydrate(TME **ptme);

void tmne_free(TMNE *tmne);
void tmne_hydrate(TMNE **ptmne);
void tmne_dehydrate(TMNE **ptmne);

void tmnf_free(TMNF *tmnf);
void tmnf_hydrate(TMNF **ptmnf);
void tmnf_dehydrate(TMNF **ptmnf);

extern symlist_t template_ftlist;	// list of template function symbols
extern symbol *template_class_list;
extern symbol **template_class_list_p;
#if PUBLIC_EXT
extern short template_expansion;
#endif

// from htod.c
#if HTOD
void htod_init(const char *name);
void htod_term();
void htod_include(const char *p, int flag);
void htod_include_pop();
void htod_writeline();
void htod_define(macro_t *m);
void htod_decl(symbol *s);
#endif

// from token.c
extern char *Arg;

/* tytostr.c	*/
char *type_tostring(Outbuffer *,type *);
char *param_tostring(Outbuffer *,type *);
char *arglist_tostring(Outbuffer *,list_t el);
char *ptpl_tostring(Outbuffer *, param_t *ptpl);
char *el_tostring(Outbuffer *, elem *e);

extern list_t pathlist;			// include paths
extern list_t headers;			// pre-include files
#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
extern list_t pathsyslist;		// include path for .h file overrides
#endif

extern int structalign;			/* alignment for members of structures	*/
extern char dbcs;
extern int colnumber;			/* current column number		*/
CEXTERN	HINT xc;		/* character last read			*/
extern targ_size_t	dsout;		/* # of bytes actually output to data	*/
					/* segment, used to pad for alignment	*/
extern char *fdepname;
extern FILE *fdep;
extern char *flstname,*fsymname,*fphreadname,*ftdbname;
extern FILE *flst;
#if HTOD
extern char *fdmodulename;
extern FILE *fdmodule;
#endif
#if SPP
extern FILE *fout;
#endif

CEXTERN	unsigned idhash;	// hash value of identifier
extern tym_t pointertype;	// default data pointer type
extern int level;		// declaration level
				// -2: base class list
				// -1: class body
				// 0: top level
				// 1: function parameter declarations
				// 2: function local declarations
				// 3+: compound statement decls
#if !TX86
extern symbol *symlinkage;		/* symbol linkage table			*/
#endif
extern param_t *paramlst;		/* function parameter list		*/

#endif /* PARSER_H */
