⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 symbol.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
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 + -