/* 
   Copyright 1994-2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
*/
#include        <stdio.h>
#include 				<string.h>
#include        "lists.h"
#include        "expr.h"
#include        "c.h"
#include        "errors.h"

extern int typequal ;
extern int skm_closepa[],skm_declbegin[] ;
extern LIST *instantiated_inlines ;
extern int prm_cplusplus ;
extern ENODE *thisenode ;
extern char *cpp_funcname_tab[];
extern int lastst;
extern int skm_declcomma[];
extern int skm_declclosepa[];
extern int stdaddrsize;       
extern ENODE *block_rundown ;
extern SYM *declclass;
extern char lastid[];
extern TYP stdmatch;
extern TABLE lsyms;
extern SYM undef;
extern int global_flag;
extern long nextlabel;
int classhead;
int vtabhead;
static TABLE vmptab;
static TYP             voidtype = { bt_void, 0, 0 ,-1, -1, 4};

void defclassini(void)
{
   vtabhead = stdaddrsize*2;
	classhead = stdaddrsize;
	vmptab.head = 0;
}
SYM *copysym(SYM *sp)
{
	SYM *rv = xalloc(sizeof(SYM));
	*rv = *sp;
   rv->next = 0 ;
	return rv;
}
#ifdef CPLUSPLUS
static int copydata(SYM *sym, SYM *from, int mode)
{
   int size = sym->value.classdata.size ;
	
	TABLE *dest = &sym->tp->lst;

	if (from) {
		SYM *head=from->tp->lst.head;
		while (head) {
         SYM *sp ;
         if (head->storage_class == sc_friendlist) {
            TABLE *t ;
            SYM *sp1 ;
            if (!(sp = basesearch(head->name,dest,FALSE))) {
               sp = copysym(head) ;
               sp->tp = cponetype(sp->tp) ;
               sp->tp->sp = sp ;
               sp->tp->lst.head = sp->tp->lst.tail = 0 ;
            }
            t = &sp->tp->lst ;
            sp1 = head->tp->lst.head ;
            while (sp1) {
               SYM*sp2 = copysym(sp1) ;
               if (!t->head)
                  t->head = t->tail = sp2 ;
               else
                  t->tail = t->tail->next = sp2 ;
               sp1 = sp1->next ;
            }
            if (!dest->head)
               dest->head = dest->tail = sp;
            else 
               dest->tail = dest->tail->next = sp;
            head = head ->next ;
            continue ;
         }
         sp = copysym(head);
         if (!sp->mainsym)
            sp->mainsym = head ;
         sp->next = 0 ;
         sp->parentclass = sym ;
         sp->value.classdata.cppflags |= PF_INHERITED ;
         if (sp->value.classdata.cppflags & PF_VIRTUAL) 
            sp->value.classdata.cppflags |= PF_NODEF;
         if (sp->value.classdata.cppflags & PF_PRIVATE)
            sp->value.classdata.cppflags |= PF_UNREACHABLE;

         if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc)
            sp->value.classdata.vtaboffs+= size ;
         else if (sp->tp->type == bt_defunc) {
            SYM *head2 = dest->head;
            SYM *head3 = sp->tp->lst.head ;
            int retagged = 0 ;
            while (head2) {
               if (!strcmp(head2->name,sp->name) && head2->tp->type == bt_defunc) {
                  sp = head2 ;
                  retagged = TRUE ;
                  break ;
               }
               head2 = head2->next ;
            }
            if (!retagged) {
               sp->tp = cponetype(sp->tp) ;
               sp->tp->sp = sp ;
               sp->tp->lst.head = sp->tp->lst.tail = 0 ;
            }
            head2 = head3 ;
            while (head2) {
               if (!(head2->value.classdata.cppflags & (PF_CONSTRUCTOR | PF_DESTRUCTOR))) {
                  SYM *s = copysym(head2) ;
                  s->value.classdata.cppflags |= PF_INHERITED ;
                  if (!s->mainsym)
                     s->mainsym = head2 ;
                  s->value.classdata.vtaboffs+= size ;
                  if (sp->tp->lst.head)
                     sp->tp->lst.tail = sp->tp->lst.tail->next = s ;
                  else
                     sp->tp->lst.head = sp->tp->lst.tail = s ;
                  s->next = 0 ;
               }
               head2 = head2 -> next ;
            }
            if (retagged || sp->tp->lst.head == 0) {
               head = head->next ;
               continue ;
            }
         } else
            sp->value.i += size ;

         if (mode == BM_PRIVATE) {
            sp->value.classdata.cppflags &= ~(PF_PUBLIC | PF_PROTECTED);
            sp->value.classdata.cppflags |= PF_PRIVATE;
         }
         else {
            if (mode == BM_PROTECTED &&
                     sp->value.classdata.cppflags & PF_PUBLIC) {
               sp->value.classdata.cppflags &= ~PF_PUBLIC; 
               sp->value.classdata.cppflags |= PF_PROTECTED;
            }
         }
         if (!dest->head)
            dest->head = dest->tail = sp;
         else 
            dest->tail = dest->tail->next = sp;
			head = head->next;
		}
	}
  return size ; 
}
int loadclassdata(SYM *sp, SYM *spc, int mode) 
{
  CLASSLIST *l = spc->value.classdata.baseclass, *lo=sp->value.classdata.baseclass, **lp=&lo ;
  int rv = copydata(sp,spc,mode);
  while (*lp)
      lp = & (*lp)->link ;
  while (l) {
      LIST *vlst=0, **vlstp=&vlst, *slst ;
      *lp = xalloc(sizeof(CLASSLIST)) ;
      (*lp)->data = l->data ;
      (*lp)->offset = l->offset + rv ;
      (*lp)->vtabsize = l->vtabsize ;
      (*lp)->isvtab = l->isvtab ;
      (*lp)->vtaboffs = 0 ;
      slst = l->vtablist ;
      /* copy the list of vtab funcs */
      while (slst) {
         *vlstp = xalloc(sizeof(LIST)) ;
         (*vlstp)->data = slst->data ;
         vlstp = &(*vlstp)->link ;
         slst = slst->link ;
      }
      (*lp)->vtablist = vlst ;
      lp = &(*lp)->link ;
      l = l->link ;
  }
  sp->value.classdata.baseclass = lo ;
  sp->value.classdata.size = rv + spc->value.classdata.size ;
  return rv + spc->value.classdata.size;
}
static char *findname(char *buf)
{
   char *buf1 = buf ;
  while (TRUE) {
    buf1 = strchr(buf1+1,'$');
    if (!buf1)
      return FALSE;

    if (*(buf1 - 1) != '@') {
      while (*(buf1-1) != '@' && buf1 != buf)
        buf1--;
      return buf1;
    }
  }
}
static int vtabmatch(SYM *candidate, SYM *current)
{
  char *cbuf = candidate->name;
  char *ubuf = current->name;
  if (!exactype(candidate->tp, current->tp))
    return FALSE ;
  cbuf = findname(cbuf);
  ubuf = findname(ubuf);
  if (!cbuf || !ubuf)
    return FALSE;
  return (!strcmp(cbuf,ubuf));
}
void addvtabentry(SYM *cl, SYM *sp)
{
   CLASSLIST *l = cl->value.classdata.baseclass ;
   LIST **lst  ;
   while (l) { 
      if (l->isvtab) {
         LIST *lst = l->vtablist;
         while (lst) {
            SYM *sp1 = lst->data;
            if (vtabmatch(sp,sp1)) {
               sp->value.classdata.vtabindex = sp1->value.classdata.vtabindex;
               sp->value.classdata.vtaboffs = sp1->value.classdata.vtaboffs;
               lst->data = sp;
               return ;
            }
            lst = lst->link;
         }
      }
      l = l->link ;
   }
   /* get here if no entry matched */
   l = cl->value.classdata.baseclass ;
   while (l) {
      if (l->isvtab)
         break ;
      l = l->link ;
   }
   if (!l) {
      l = cl->value.classdata.baseclass ;
      l->isvtab = TRUE ;
   }
   lst = &l->vtablist ;
   while (*lst)
      lst = &(*lst)->link ;
   *lst = xalloc(sizeof(LIST)) ;
   (*lst)->link = 0;
   (*lst)->data = sp;
   sp->value.classdata.vtabindex = l->vtabsize;
   sp->value.classdata.vtaboffs = l->offset ;
   l->vtabsize +=stdaddrsize;
}
void classerrs(SYM *sp)
{
	SYM *head = sp->tp->lst.head;
   int hasref = FALSE ;
	while (head) {
      if (head->tp->type == bt_ref && !(sp->value.classdata.cppflags & PF_HASCONS)) {
         if (!(head->value.classdata.cppflags & PF_INHERITED))
            genclass2error(ERR_REFNOCONS,head->parentclass->name,head->name);
      }
		head->parentclass = sp;
		head = head->next;
	}
}
ENODE *conscall(ENODE *tcnode, SYM *sp, ENODE* ep)
{
   ENODE *pnode,*rnode ;
   pnode = makenode(en_napccon,sp,0) ;
	sp->extflag = TRUE ;
   if (!ep)
      ep = makenode(en_void,0,0) ;
   pnode = makenode(en_void,pnode,ep);
   rnode = makeintnode(en_icon,sp->tp->btp->size);
   if (sp->pascaldefn)
      pnode = makenode(en_pfcall,rnode,pnode);
   else
      if (sp->isstdcall)
         pnode = makenode(en_sfcall,rnode,pnode);
      else
         pnode = makenode(en_fcall,rnode,pnode);
   pnode = makenode(en_thiscall, tcnode, pnode);
   return pnode ;
}
void setthunkflags( SYM *sp_in, int state)
{
   CLASSLIST *l=sp_in->value.classdata.enclosedclass ;
   while (l) {
      setthunkflags(l->data->tp->sp,state) ;
      l = l->link ;
   }
   l = sp_in->value.classdata.baseclass ;
   while (l) {
      if (!state)
         l->data->value.classdata.cppflags &= ~PF_TEMPCONSALREADY ;
      else
         l->data->value.classdata.cppflags |= PF_TEMPCONSALREADY ;
      l = l->link ;
   }
}
/* things are placed in the constructor expression in backwards order */
void thunkVtabs(SNODE *snp3, SYM *sp_in, int ofs, int checkaccess)
{
            CLASSLIST *l ;
            ENODE *thisn = thisenode ;
            ENODE *ts = makenode(en_nacon,sp_in->value.classdata.baseclass->vtabsp, 0) ;
            ENODE *exp1, *exp2, *exps ;
            thisn = makenode(en_l_ref,thisn,0);
            /* enclosed classes last */
            l = sp_in->value.classdata.enclosedclass ;
            while (l) {
               thunkVtabs(snp3,l->data->tp->sp, l->offset,TRUE) ;
               l = l->link ;
            }
            /* current constructor */
            l = sp_in->value.classdata.baseclass ;
            exps = 0 ;
            while (l) {          
               if (l->isvtab && !(l->data->value.classdata.cppflags & PF_TEMPCONSALREADY)) {
                  if (checkaccess) {
                     SYM *sp1 = search(cpp_funcname_tab[CI_CONSTRUCTOR],l->data->tp->lst.head);
                     if (sp1) {
                        sp1 = funcovermatch(sp1,&voidtype,FALSE) ;
                        if (sp1)
                           isaccessible(sp1) ;
                     } else // should never get here
                        gensymerror(ERR_NOFUNCMATCH,fullcppmangle(sp_in,cpp_funcname_tab[CI_CONSTRUCTOR],&voidtype)) ; 
                  }
                  exp1 = makenode(en_addstruc,ts,makeintnode(en_icon,l->vtaboffs)) ;
                  exp2 = makenode(en_addstruc,thisn,makeintnode(en_icon,(l->offset+ofs))) ;
                  exp2 = makenode(en_l_ref,exp2,0);
                  exp2 = makenode(en_assign,exp2,exp1) ;
                  if (!exps)
                     exps = exp2 ;
                  else 
                     exps = makenode(en_void,(void *)exps,(void *)exp2) ;
               }
               l = l->link ;
            }
            if (exps)
               if (!snp3->exp)
                  snp3->exp = exps ;
               else
                  snp3->exp = makenode(en_void,(void *)exps,(void *)snp3->exp) ;
            /* previous constructors */
            l = sp_in->value.classdata.baseclass->link ;
            exps = 0 ;
            while (l) {
               SYM *sp1 = search(cpp_funcname_tab[CI_CONSTRUCTOR],l->data->tp->lst.head);
               if (sp1) {
                  sp1 = funcovermatch(sp1,&voidtype,FALSE) ;
                  if (!sp1)
                     gensymerror(ERR_NOFUNCMATCH,fullcppmangle(sp_in,cpp_funcname_tab[CI_CONSTRUCTOR],&voidtype)) ; 
                  else {
                     if (!(l->data->value.classdata.cppflags & PF_TEMPCONSALREADY)) {
                        isaccessible(sp1) ;
                        if (sp1->value.classdata.cppflags & PF_INLINE) {
                           ts = makenode(en_nacon,l->data->value.classdata.baseclass->vtabsp, 0) ;
                           exp2 = makenode(en_addstruc,thisn,makeintnode(en_icon,(l->offset+ofs))) ;
                           exp2 = makenode(en_l_ref,exp2,0);
                           exp2 = makenode(en_assign,exp2,ts) ;
                        } else {
                           exp2 = makenode(en_addstruc,thisn,makeintnode(en_icon,(l->offset+ofs))) ;
                           exp2 = conscall(exp2,sp1,0) ;
                           setthunkflags(l->data->tp->sp,TRUE) ;
                        }
                        if (!exps)
                           exps = exp2 ;
                        else 
                           exps = makenode(en_void,(void *)exps,(void *)exp2) ;
                     }
                  }
               } else // should never get here
                  gensymerror(ERR_NOFUNCMATCH,fullcppmangle(sp_in,cpp_funcname_tab[CI_CONSTRUCTOR],&voidtype)) ; 
               
               l = l->link ;
            }
            if (exps)
               if (!snp3->exp)
                  snp3->exp = exps ;
               else
                  snp3->exp = makenode(en_void,(void *)exps,(void *)snp3->exp) ;
}
/* things are placed in the constructor expression in backwards order */
void thunkConstructors(SNODE *snp3, SYM *sp_in, int ofs, int checkaccess)
{
            CLASSLIST *l ;
            ENODE *thisn = thisenode ;
            ENODE *ts = makenode(en_nacon,sp_in->value.classdata.baseclass->vtabsp, 0) ;
            ENODE *exp1, *exp2, *exps ;
            SYM *spt = sp_in->tp->lst.head ;
            thisn = makenode(en_l_ref,thisn,0);
            while (spt) {
               if (!(spt->value.classdata.cppflags & PF_INHERITED)) {
                  if (spt->value.classdata.consbuild) {
                     exp1 = spt->value.classdata.consbuild ;
                     if (spt->tp->type == bt_struct || spt->tp->type == bt_union || spt->tp->type == bt_class) {
                        setthunkflags(spt->tp->sp,TRUE) ;
                     } else {
                        if (spt->tp->type == bt_ref) {
                           spt->value.classdata.cppflags |= PF_TEMPCONSREFALREADY ;
                           if (!lvalue(exp1))
                              generror(ERR_REFLVALUE,0,0) ;
                           else
                              exp1 = exp1->v.p[0] ;
                        }
                        exp2 = makenode(en_addstruc,(void *)thisn,(void *)makeintnode(en_icon,spt->value.i));
                        exp2 = makenode(en_l_ref,(void *)exp2,0) ;
                        exp1 = makenode(en_assign,(void *)exp2, (void *)exp1) ;
                     }
                     if (!snp3->exp)
                        snp3->exp = exp1 ;
                     else
                        snp3->exp = makenode(en_void,(void *)snp3->exp,(void *)exp1) ;
                     spt->value.classdata.consbuild = 0 ;
                  } else if (spt->tp->type == bt_struct || spt->tp->type == bt_union  || spt->tp->type == bt_class) {
                     thunkVtabs(snp3,spt->tp->sp,spt->value.i,TRUE) ;
                  }
               }
               spt = spt->next ;
            }
            /* current constructor */
            l = sp_in->value.classdata.baseclass ;
            exps = 0 ;
            while (l) {          
               if (l->isvtab && !(l->data->value.classdata.cppflags & PF_TEMPCONSALREADY)) {
                  if (checkaccess) {
                     SYM *sp1 = search(cpp_funcname_tab[CI_CONSTRUCTOR],l->data->tp->lst.head);
                     if (sp1) {
                        sp1 = funcovermatch(sp1,&voidtype,FALSE) ;
                        if (sp1)
                           isaccessible(sp1) ;
                     } else // should never get here
                        gensymerror(ERR_NOFUNCMATCH,fullcppmangle(sp_in,cpp_funcname_tab[CI_CONSTRUCTOR],&voidtype)) ; 
                  }
                  exp1 = makenode(en_addstruc,ts,makeintnode(en_icon,l->vtaboffs)) ;
                  exp2 = makenode(en_addstruc,thisn,makeintnode(en_icon,(l->offset+ofs))) ;
                  exp2 = makenode(en_l_ref,exp2,0);
                  exp2 = makenode(en_assign,exp2,exp1) ;
                  if (!exps)
                     exps = exp2 ;
                  else 
                     exps = makenode(en_void,(void *)exps,(void *)exp2) ;
               }
               l = l->link ;
            }
            if (exps)
               if (!snp3->exp)
                  snp3->exp = exps ;
               else
                  snp3->exp = makenode(en_void,(void *)exps,(void *)snp3->exp) ;
            /* previous constructors */
            l = sp_in->value.classdata.baseclass->link ;
            exps = 0 ;
            while (l) {
               SYM *sp1 = search(cpp_funcname_tab[CI_CONSTRUCTOR],l->data->tp->lst.head);
               if (sp1) {
                  sp1 = funcovermatch(sp1,&voidtype,FALSE) ;
                  if (!sp1)
                     gensymerror(ERR_NOFUNCMATCH,fullcppmangle(sp_in,cpp_funcname_tab[CI_CONSTRUCTOR],&voidtype)) ; 
                  else {
                     if (!(l->data->value.classdata.cppflags & PF_TEMPCONSALREADY)) {
                        isaccessible(sp1) ;
                        if (l->data->value.classdata.consbuild) {
                           exp2 = l->data->value.classdata.consbuild ;
                           l->data->value.classdata.consbuild = 0 ;
                           setthunkflags(l->data->tp->sp,TRUE) ;
                        } else if (sp1->value.classdata.cppflags & PF_INLINE) {
                           ts = makenode(en_nacon,l->data->value.classdata.baseclass->vtabsp, 0) ;
                           exp2 = makenode(en_addstruc,thisn,makeintnode(en_icon,(l->offset+ofs))) ;
                           exp2 = makenode(en_l_ref,exp2,0);
                           exp2 = makenode(en_assign,exp2,ts) ;
                        } else {
                           exp2 = makenode(en_addstruc,thisn,makeintnode(en_icon,(l->offset+ofs))) ;
                           exp2 = conscall(exp2,sp1,0) ;
                           setthunkflags(l->data->tp->sp,TRUE) ;
                        }
                        if (!exps)
                           exps = exp2 ;
                        else 
                           exps = makenode(en_void,(void *)exps,(void *)exp2) ;
                     }
                  }
               } else // should never get here
                  gensymerror(ERR_NOFUNCMATCH,fullcppmangle(sp_in,cpp_funcname_tab[CI_CONSTRUCTOR],&voidtype)) ; 
               
               l = l->link ;
            }
            if (exps)
               if (!snp3->exp)
                  snp3->exp = exps ;
               else
                  snp3->exp = makenode(en_void,(void *)exps,(void *)snp3->exp) ;
}
void thunkDestructors(SNODE *snp3, SYM *sp_in, int ofs, int checkaccess, int skipself)
{
            CLASSLIST *l ;
            ENODE *thisn = thisenode ;
            ENODE *ts = makenode(en_nacon,sp_in->value.classdata.baseclass->vtabsp, 0) ;
            ENODE *exp1, *exp2 ;
            thisn = makenode(en_l_ref,thisn,0);
            l = sp_in->value.classdata.baseclass ;
            if (skipself)
               l = l->link ;
            while (l) {
               SYM *sp1 = search(cpp_funcname_tab[CI_DESTRUCTOR],l->data->tp->lst.head);
               if (sp1) {
                  sp1 = funcovermatch(sp1,&voidtype,FALSE) ;
                  if (sp1 && !(sp1->value.classdata.cppflags & PF_DUMDEST)) {
                     if (!(l->data->value.classdata.cppflags & PF_TEMPCONSALREADY)) {
                        isaccessible(sp1) ;
                        exp2 = makenode(en_addstruc,thisn,makeintnode(en_icon,(l->offset+ofs))) ;
                        exp2 = conscall(exp2,sp1,0) ;
                        if (!snp3->exp)
                           snp3->exp = exp2 ;
                        else 
                           snp3->exp = makenode(en_void,(void *)exp2,(void *)snp3->exp) ;
                        setthunkflags(l->data->tp->sp,TRUE) ;
                     }
                  }
               } 
               
               l = l->link ;
            }
            l = sp_in->value.classdata.enclosedclass ;
            while (l) {
               thunkDestructors(snp3,l->data->tp->sp, l->offset,TRUE,FALSE) ;
               l = l->link ;
            }
}
void CreateBaseConstructor(SYM *sp_in)
{
      SYM *sp = search(cpp_funcname_tab[CI_CONSTRUCTOR], &sp_in->tp->lst);
      TYP vtyp ;
      vtyp.type = bt_func ;
      vtyp.lst.head = vtyp.lst.tail = -1 ;
      if (!sp) {
         SNODE *snp3 ;
         sp = xalloc(sizeof(SYM)) ;
         sp->name = litlate(fullcppmangle(sp_in,cpp_funcname_tab[CI_CONSTRUCTOR],&vtyp)) ;
         sp->tp = maketype(bt_func,0) ;
         sp->tp->sp = sp ;
         sp->tp->btp = copytype(&voidtype,0) ;
         sp->tp->lst.head = -1 ;
         sp->value.classdata.cppflags = PF_INLINE | PF_CONSTRUCTOR | PF_MEMBER | PF_PUBLIC;
         sp->parentclass = sp_in ;
         snp3 = xalloc(sizeof(SNODE)) ;
         snp3->stype = st_expr ;
         snp3->exp = 0 ;
         setthunkflags(sp_in,FALSE) ;
         thunkVtabs(snp3,sp_in,0,FALSE) ;
         sp->value.classdata.inlinefunc = xalloc(sizeof(INLINEFUNC));
         sp->value.classdata.inlinefunc->stmt = snp3;
         sp->value.classdata.inlinefunc->syms.head = sp->value.classdata.inlinefunc->syms.tail = 0;
         funcrefinsert(cpp_funcname_tab[CI_CONSTRUCTOR],sp,&sp_in->tp->lst,sp_in);
      }
      sp = search(cpp_funcname_tab[CI_DESTRUCTOR], &sp_in->tp->lst);
      if (!sp) {
         SNODE *snp3 ;
         snp3 = xalloc(sizeof(SNODE)) ;
         snp3->stype = st_expr ;
         snp3->exp = 0 ;
         setthunkflags(sp_in,FALSE) ;
         thunkDestructors(snp3,sp_in,0,FALSE,FALSE) ;
         if (snp3->exp) {
            sp = xalloc(sizeof(SYM)) ;
            sp->name = litlate(fullcppmangle(sp_in,cpp_funcname_tab[CI_DESTRUCTOR],&vtyp)) ;
            sp->tp = maketype(bt_func,0) ;
            sp->tp->sp = sp ;
            sp->tp->btp = copytype(&voidtype,0) ;
            sp->tp->lst.head = -1 ;
            sp->value.classdata.cppflags = PF_INLINE | PF_DESTRUCTOR | PF_MEMBER | PF_PUBLIC | PF_DUMDEST;
            sp->parentclass = sp_in ;
            sp->value.classdata.inlinefunc = xalloc(sizeof(INLINEFUNC));
            sp->value.classdata.inlinefunc->stmt = snp3;
            sp->value.classdata.inlinefunc->syms.head = sp->value.classdata.inlinefunc->syms.tail = 0;
            funcrefinsert(cpp_funcname_tab[CI_DESTRUCTOR],sp,&sp_in->tp->lst,sp_in);
         }
      }
}
void classbaseasn(SYM *sp)
/*
 *      handles a list of constructor base assignment operators
 */
{
            CLASSLIST *ls = 0 ;
				while (TRUE) {
					if (lastst != id) {
						generror(ERR_IDEXPECT,0,0);
                  basicskim(skm_declbegin);
                  return ;
					} else {
                  int discard = FALSE ;
                  SYM *sp1 = search(lastid,&sp->tp->lst) ;
                  if (sp1) {
                     if (sp1->value.classdata.cppflags &PF_INHERITED) {
                        discard = TRUE ;
                        doubleerr(ERR_NOTUNAMBIGUOUSBASE,lastid,sp->name) ;
                     }
                  } else {
                     CLASSLIST *l = sp->value.classdata.baseclass->link ;
                     while (l) {
                        if (!strcmp(l->data->name,lastid))
                           break ;
                        l = l->link ;
                     }
                     if (!l || !l->isvtab) {
                        discard = TRUE ;
                        doubleerr(ERR_NOTUNAMBIGUOUSBASE,lastid,sp->name) ;
                     } else {
                        sp1 = l->data->tp->sp ;
                        ls = l ;
                     }
                        
                  }
                  getsym() ;
                  if (needpunc(openpa,skm_closepa)) {
                     ENODE *expr ;
                     TYP *tp ;
                     if (!discard) {
                        typequal = 0 ;
                        if (sp1->value.classdata.consbuild)
                           gensymerror(ERR_MEMBERREINIT,sp1->name) ;
                        if (sp1->tp->type == bt_class || sp1->tp->type == bt_struct || sp1->tp->type == bt_union) {
                           ENODE *qnode ;
                           TYP *tp1 = gatherparms(&qnode,FALSE) ;
                           if (ls) 
                              expr = do_constructor(sp,tp1,sp1->tp,qnode,1,ls->offset) ;                              
                           else
                              expr = do_constructor(sp,tp1,sp1->tp,qnode,1,sp1->value.i) ;                              
                           sp1->value.classdata.consbuild = expr ;
                        } else {
                           tp = exprnc(&expr) ;
                           if (!exactype(sp1->tp,tp))
                              genmismatcherror(tp,sp1->tp) ;
                           else if (sp1->value.classdata.cppflags & PF_STATIC)
                              gensymerror(ERR_NOINITSTATICMEMBER,sp1->name) ;
                           else
                              sp1->value.classdata.consbuild = expr ;
                           needpunc(closepa,0) ;
                        }
                     } else {
                        tp = expression(&expr,0) ;
                        needpunc(closepa,0) ;
                     }
                  }
					}
					if (lastst != comma)
						break;
               getsym() ;
				}
}
void setRefFlags(SYM *sp)
{
   sp = sp->tp->lst.head ;
   while (sp) {
      if (sp->tp->type == bt_ref)
         sp->value.classdata.cppflags &= ~PF_TEMPCONSREFALREADY ;
      sp = sp->next ;
   }
}
void RefErrs(SYM *sp)
{
   sp = sp->tp->lst.head ;
   while (sp) {
      if (sp->tp->type == bt_ref)
         if (!(sp->value.classdata.cppflags & (PF_TEMPCONSREFALREADY | PF_INHERITED)))
            gensymerror(ERR_CONSNOREFINIT,sp->name);
            
      sp = sp->next ;
   }
}
void gen_vtab(SYM *sp)
{
	SYM *head;
   LIST *lst;
   CLASSLIST *l ;
   int first = TRUE,size = 0 ;
   l = sp->value.classdata.baseclass ;
   while (l) {
      if (l->isvtab) {
         if (first) {
            gen_virtual(sp->value.classdata.baseclass->vtabsp);
            genlong(0); /* space for exception handling */ 
            first = FALSE ;
            size += stdaddrsize ;
         }
         genlong(0) ; /* Space for who knows what... */
         size += stdaddrsize ;
         l->vtaboffs = size ;
         lst = l->vtablist ;
         while (lst) {
            SYM *sp = lst->data ;
            sp->extflag = TRUE ;
            genpcref(sp,0);
            size += stdaddrsize ;
            lst = lst->link ;
         }
      }
      l = l->link ;  
   }
   if (!first)
      gen_endvirtual(sp->value.classdata.baseclass->vtabsp);
}
#endif
