📄 declass.c
字号:
/*
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.
This program is derived from the cc68k complier by
Matthew Brandt (mattb@walkingdog.net)
You may contact the author of this derivative 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 "ccerr.h"
#define VTABVALTHRESH (1024 * 1024)
extern ENODE *expr_runup[50];
extern ENODE *expr_rundown[50];
extern int expr_updowncount;
extern int prm_xcept;
extern int global_flag;
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 long nextlabel;
extern TYP stdvoidfunc;
extern SYM *currentfunc;
TABLE *baseasnsymtbl;
int classhead;
int vtabhead;
static TABLE vmptab;
static TYP functovoidtype =
{
bt_func, 0, 0, - 1, - 1, 4
};
static TYP vtyp;
void defclassini(void)
{
vtyp.type = bt_func;
vtyp.lst.head = vtyp.lst.tail = - 1;
vtyp.cflags = 0;
vtabhead = stdaddrsize * 3;
classhead = stdaddrsize;
vmptab.head = 0;
functovoidtype.lst.head = - 1;
functovoidtype.btp = maketype(bt_void, 0);
}
//-------------------------------------------------------------------------
void SetExtFlag(SYM *sp, int state)
{
sp->mainsym->extflag = state;
if (state && (sp->value.classdata.cppflags &PF_INLINE) && !(sp
->value.classdata.cppflags &PF_INSTANTIATED))
{
LIST *l;
global_flag++;
l = xalloc(sizeof(LIST));
global_flag--;
l->data = sp;
l->link = instantiated_inlines;
instantiated_inlines = l;
sp->value.classdata.cppflags |= PF_INSTANTIATED;
sp->value.classdata.cppflags &= ~PF_INLINE;
}
}
//-------------------------------------------------------------------------
SYM *copysym(SYM *sp)
{
SYM *rv = xalloc(sizeof(SYM));
*rv = *sp;
rv->next = 0;
return rv;
}
//-------------------------------------------------------------------------
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;
if (s->value.classdata.cppflags &PF_VIRTUAL)
s->tp = copytype(s->tp, 0);
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, int virtual)
{
CLASSLIST *l = spc->value.classdata.baseclass, *lo = sp
->value.classdata.baseclass, **lp = &lo;
CLASSLIST *x = lo->link;
int rv = copydata(sp, spc, mode);
int first = 2, primary = 1, firstrun;
int ofs = lo->vtabsize - 12;
while (*lp)
{
first--;
if (!first)
break;
lp = &(*lp)->link;
}
{
LIST **vlist = &lo->vtablist, *slst = l->vtablist;
int voffs = lo->vtabsize - 12;
int offs = sp->value.classdata.size;
while (*vlist)
vlist = *vlist;
if (!first)
{
*vlist = xalloc(sizeof(LIST));
(*vlist)->data = rv;
vlist = &(*vlist)->link;
*vlist = xalloc(sizeof(LIST));
(*vlist)->data = lo->vtabsize - 12+8;
vlist = &(*vlist)->link;
lo->vtabsize += 2 * stdaddrsize;
ofs += 2 * stdaddrsize;
voffs += 2 * stdaddrsize;
}
while (slst)
{
if ((int)slst->data < VTABVALTHRESH)
{
*vlist = xalloc(sizeof(LIST));
(*vlist)->data = (void*)((int)slst->data + offs);
vlist = &(*vlist)->link;
slst = slst->link;
*vlist = xalloc(sizeof(LIST));
(*vlist)->data = (void*)((int)slst->data + voffs);
vlist = &(*vlist)->link;
slst = slst->link;
}
else
{
*vlist = xalloc(sizeof(LIST));
(*vlist)->data = slst->data;
vlist = &(*vlist)->link;
slst = slst->link;
}
}
}
firstrun = first;
lp = &lo->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;
if (primary)
lo->vtabsize += l->vtabsize - vtabhead;
if (l->flags &CL_VTAB)
{
(*lp)->flags |= CL_VTAB;
lo->flags |= CL_VTAB;
}
(*lp)->vtaboffs = l->vtaboffs + ofs;
(*lp)->vtabsp = l->vtabsp;
if (primary)
(*lp)->flags |= CL_PRIMARY;
if (firstrun && l->offset + rv == 0)
(*lp)->flags |= CL_TOPCLASS;
if (l->mode == BM_PRIVATE || mode == BM_PRIVATE)
(*lp)->mode = BM_PRIVATE;
else if (l->mode == BM_PROTECTED || mode == BM_PROTECTED)
(*lp)->mode = BM_PROTECTED;
else
(*lp)->mode = BM_PUBLIC;
(*lp)->vtablist = vlst;
(*lp)->link = x;
lp = &(*lp)->link;
first = FALSE;
primary = FALSE;
l = l->link;
}
sp->value.classdata.size = rv + spc->value.classdata.size;
return sp->value.classdata.size;
}
int insertVirtualData(SYM *sp)
{
return 0 ;
}
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, FALSE))
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;
SetExtFlag(sp, TRUE);
if (sp->tp->type == bt_func)
sp->storage_class = sc_externalfunc;
if (l->flags &CL_VTAB)
{
LIST *lst = l->vtablist;
while (lst)
{
SYM *sp1 = lst->data;
if (sp1 > VTABVALTHRESH)
{
if (vtabmatch(sp, sp1))
{
CLASSLIST *l1 = l;
while (l1 && l1->data->mainsym != sp1->parentclass
->mainsym)
l1 = l1->link;
if (l1 && l1->offset)
{
SYM *sp2 = gen_vsn_virtual_thunk(sp, l1->offset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -