📄 symbol.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
*/
/* Handles symbol tables
*/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "ccerr.h"
#include "lists.h"
#define ROTR(x,bits) (((x << (32 - bits)) | (x >> bits)) & 0xffff)
#define ROTL(x,bits) (((x << bits) | (x >> (32 - bits))) & 0xffff)
extern TABLE *funcparmtable;
extern int inarrayindexparsing;
extern int templateLookup;
extern char *infile;
extern TABLE oldlsym, oldltag;
extern int prm_cplusplus, prm_cmangle;
extern SYM *declclass, *typequal, *currentfunc;
extern struct template *currentTemplate;
extern int global_flag;
extern char lastid[];
extern int lastst;
extern TABLE *baseasnsymtbl;
extern int skm_declcomma[];
extern int funcnesting;
extern int structlevel;
extern SYM *parm_namespaces[20][100];
extern int parm_ns_counts[20];
extern int parm_ns_level;
extern int parsing_params;
HASHREC **defhash = 0;
NAMESPACE *thisnamespace;
HASHREC **gsyms; /*everywhere else this is a table so I don't have to typecast
*/
HASHREC **templateFuncs; // ditto
HASHREC **tagtable;
TABLE lsyms, defsyms, ltags;
LIST **global_using_list, **global_tag_using_list;
LIST *local_using_list, *local_tag_using_list;
LIST *openns_list;
int nonslookup;
int unique_namespace_num;
static SYM *nssym1, *nssym2;
static SYM *lastsearchsym;
static TABLE *lastsearchtable;
static char lastsearchname[256];
char searchname[256];
void symini(void)
{
lsyms.head = lsyms.tail = defsyms.head = defsyms.tail = 0;
ltags.head = ltags.tail = 0;
if (!defhash)
{
gsyms = (HASHREC **)malloc(HASHTABLESIZE *sizeof(HASHREC*));
templateFuncs = (HASHREC **)malloc(HASHTABLESIZE *sizeof(HASHREC*));
defhash = (HASHREC **)malloc(HASHTABLESIZE *sizeof(HASHREC*));
tagtable = (HASHREC **)malloc(HASHTABLESIZE *sizeof(HASHREC*));
global_using_list = (LIST **)malloc((HASHTABLESIZE + 1) *sizeof(LIST*));
global_tag_using_list = (LIST **)malloc((HASHTABLESIZE + 1) *sizeof
(LIST*));
} memset(defhash, 0, HASHTABLESIZE *sizeof(HASHREC*));
memset(tagtable, 0, HASHTABLESIZE *sizeof(HASHREC*));
memset(gsyms, 0, HASHTABLESIZE *sizeof(HASHREC*));
memset(templateFuncs, 0, HASHTABLESIZE *sizeof(HASHREC*));
memset(global_using_list, 0, (HASHTABLESIZE + 1) *sizeof(LIST*));
memset(global_tag_using_list, 0, (HASHTABLESIZE + 1) *sizeof(LIST*));
thisnamespace = 0;
local_using_list = 0;
local_tag_using_list = 0;
srand(time(0));
unique_namespace_num = rand() % 2000;
nonslookup = FALSE;
lastsearchname[0] = 0;
lastsearchtable = 0;
}
/* Sym tab hash function */
static unsigned int ComputeHash(char *string, int size)
{
unsigned i;
char *s = string;
for (i = 0; *string; string++)
i = i * 128+i * 2+i + *string;
// printf("%d: %u %d: %s\n",i %size,i,size,s) ;
return (i % size);
#ifdef XXXXX
unsigned int len = strlen(string), rv;
char *pe = len + string;
unsigned char blank = ' ';
rv = len | blank;
while (len--)
{
unsigned char cback = (unsigned char)(*--pe) | blank;
rv = ROTL(rv, 2) ^ cback;
}
return (rv % size);
#endif
}
/* Add a hash item to the table */
HASHREC *AddHash(HASHREC *item, HASHREC **table, int size)
{
int index = ComputeHash(item->key, size);
HASHREC **p;
item->link = 0;
if (*(p = &table[index]))
{
HASHREC *q = *p, *r = *p;
while (q)
{
r = q;
if (!strcmp(r->key, item->key))
return (r);
q = q->link;
}
r->link = item;
}
else
*p = item;
return (0);
}
/*
* Find something in the hash table
*/
HASHREC **LookupHash(char *key, HASHREC **table, int size)
{
int index = ComputeHash(key, size);
HASHREC **p;
if (*(p = &table[index]))
{
HASHREC *q = *p;
while (q)
{
if (!strcmp(q->key, key))
return (p);
p = *p;
q = q->link;
}
}
return (0);
}
//-------------------------------------------------------------------------
void pushusing(SYM *sp, int tag)
{
LIST **l, *m = xalloc(sizeof(LIST)), *li;
if (openns_list)
if (tag)
l = ((SYM*)openns_list->data)->value.classdata.parentns
->tag_using_list;
else
l = ((SYM*)openns_list->data)->value.classdata.parentns->using_list;
else if (!funcnesting && !structlevel)
if (tag)
l = global_tag_using_list;
else
l = global_using_list;
else
if (tag)
l = &local_tag_using_list;
else
l = &local_using_list;
if (l != &local_using_list && l != &local_tag_using_list)
{
if (sp->storage_class == sc_namespace)
l = &l[HASHTABLESIZE];
else
{
int index = ComputeHash(sp->name, HASHTABLESIZE);
l = &l[index];
}
}
li = *l;
while (li)
{
if (li->data == sp)
break;
li = li->link;
}
if (!li)
{
m->data = sp;
m->link = *l;
*l = m;
}
}
//-------------------------------------------------------------------------
void aliasnamespace(char *name)
{
char buf[256];
strcpy(buf, name);
getsym();
if (lastst == id)
{
SYM *s;
SYM *typesp;
if ((typesp = typesearch(lastid)) && typesp->storage_class ==
sc_namespace)
{
getsym();
typesp = parsetype(typesp, TRUE);
}
if (typesp->storage_class == sc_namespace)
{
s = makesym(sc_namespace);
s->name = litlate(buf);
s->tp = maketype(bt_int, 4);
s->value.classdata.parentns = typesp->value.classdata.parentns;
insert(s, gsyms);
}
else
generror(ERR_NAMESPACEEXP, 0, 0);
}
else
generror(ERR_IDEXPECT, 0, 0);
}
//-------------------------------------------------------------------------
void switchtonamespace(char *name)
{
NAMESPACE *q;
char buf[256];
int anon = 0;
SYM *s;
if (name == 0)
{
int i = 0;
name = infile;
buf[i++] = '_';
buf[i++] = 'n';
buf[i++] = 's';
while (*name)
{
if (isalnum(name))
buf[i++] = *name++;
else
buf[i++] = '_', name++;
sprintf(buf + i, "%d%d_", unique_namespace_num++, rand() % 1000);
}
anon = 1;
}
else
strcpy(buf, name);
if (!openns_list)
s = basesearch(buf, gsyms, 0);
else
s = namespace_search(buf, ((SYM*)openns_list->data)
->value.classdata.parentns, 0);
if (!s)
{
NAMESPACE *ns;
global_flag++;
s = makesym(sc_namespace);
s->name = litlate(buf);
s->tp = maketype(bt_int, 4);
ns = s->value.classdata.parentns = xalloc(sizeof(NAMESPACE));
ns->table = (HASHREC **)xalloc(HASHTABLESIZE *sizeof(HASHREC*));
ns->tagtable = (HASHREC **)xalloc(HASHTABLESIZE *sizeof(HASHREC*));
ns->using_list = (LIST **)xalloc((HASHTABLESIZE + 1) *sizeof(LIST*));
ns->tag_using_list = (LIST **)xalloc((HASHTABLESIZE + 1) *sizeof(LIST*))
;
ns->sp = s;
ns->anonymous = anon;
ns->guardian = FALSE;
ns->next = thisnamespace;
insert(s, gsyms);
global_flag--;
}
else if (s->storage_class != sc_namespace)
{
generror(ERR_NAMESPACEEXP, 0, 0);
s = 0;
}
if (s)
{
LIST *l = xalloc(sizeof(LIST));
l->link = openns_list;
l->data = s;
thisnamespace = s->value.classdata.parentns;
if (anon)
{
pushusing(s, 0);
pushusing(s, 1);
}
openns_list = l;
}
}
//-------------------------------------------------------------------------
void switchfromnamespace(void)
{
if (openns_list)
{
thisnamespace = openns_list = openns_list->link;
}
else
thisnamespace = 0;
// safety
}
//-------------------------------------------------------------------------
void inject_namespace(int ns)
{
SYM *sp = search(lastid, gsyms), *sp1;
if (!sp)
{
gensymerror(ERR_UNDEFINED, lastid);
return ;
}
getsym();
if (sp->storage_class == sc_namespace && lastst == classsel)
{
do
{
getsym();
if (lastst != id)
{
generror(ERR_IDEXPECT, 0, 0);
return ;
}
sp1 = namespace_search(lastid, sp->value.classdata.parentns, 0);
if (!sp1)
sp1 = namespace_search(lastid, sp->value.classdata.parentns, 1);
if (!sp1)
{
gensymerror(ERR_UNDEFINED, lastid);
return ;
}
sp = sp1;
getsym();
}
while (sp->storage_class == sc_namespace && lastst == classsel);
}
if (ns)
{
if (sp->storage_class != sc_namespace)
generror(ERR_NAMESPACEEXP, 0, 0);
pushusing(sp, 0);
pushusing(sp, 1);
}
else
{
if (sp->storage_class == sc_namespace)
gensymerror(ERR_ILLEGALNAMESPACEUSE, lastid);
pushusing(sp, sp->intagtable);
}
}
//-------------------------------------------------------------------------
SYM *namespace_search(char *name, NAMESPACE *data, int tags)
{
SYM **p;
if (tags)
p = ((SYM **)LookupHash(name, data->tagtable, HASHTABLESIZE));
else
p = ((SYM **)LookupHash(name, data->table, HASHTABLESIZE));
if (p)
{
p = *p;
}
return (SYM*)p;
}
//-------------------------------------------------------------------------
static SYM *namespace_search_full(char *name, LIST **l, TABLE *table)
{
LIST *list, *list2 = 0;
if (l != &local_using_list && l != &local_tag_using_list)
{
int index = ComputeHash(name, HASHTABLESIZE);
list2 = l[HASHTABLESIZE];
l = &l[index];
}
list = *l;
if (!list)
{
list = list2;
list2 = 0;
}
while (list)
{
SYM *sp = list->data;
SYM *main = 0, *temp = 0;
if (sp->storage_class == sc_namespace)
{
if (!sp->value.classdata.parentns->guardian)
{
sp->value.classdata.parentns->guardian++;
main = namespace_search(name, sp->value.classdata.parentns,
table == tagtable);
temp = namespace_search_full(name, table == tagtable ? sp
->value.classdata.parentns->tag_using_list: sp
->value.classdata.parentns->using_list, table);
sp->value.classdata.parentns->guardian--;
}
}
else if (!strcmp(name, sp->name))
main = sp;
if (main)
{
if (nssym1)
{
if (!nssym2 &nssym1 != main)
{
nssym2 = main;
return nssym1;
}
}
else
nssym1 = main;
}
if (temp)
{
if (nssym1)
{
if (!nssym2 && nssym1 != temp)
{
nssym2 = temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -