📄 symbol.c
字号:
/*
* C compiler
* ==========
*
* Copyright 1989, 1990, 1991 Christoph van Wuellen.
* Credits to Matthew Brandt.
* All commercial rights reserved.
*
* This compiler may be redistributed as long there is no
* commercial interest. The compiler must not be redistributed
* without its full sources. This notice must stay intact.
*
* History:
*
* 1989 starting an 68000 C compiler, starting with material
* originally by M. Brandt
* 1990 68000 C compiler further bug fixes
* started i386 port (December)
* 1991 i386 port finished (January)
* further corrections in the front end and in the 68000
* code generator.
* The next port will be a SPARC port
*/
/*****************************************************************************/
#include "chdr.h"
#include "expr.h"
#include "cglbdec.h"
#include "proto.h"
#include "outproto.h"
/********************************************************* Macro Definitions */
#define SMAXKEY ((unsigned)631)
/********************************************************** Type Definitions */
typedef unsigned int KEY; /* type for hash key */
/********************************************************** Static Variables */
static LEVEL scope_level = (LEVEL) 0;
static struct scopetbl scope;
static SYM *symbols[SMAXKEY];
static SYM *tags[SMAXKEY];
/*********************************************** Static Function Definitions */
static SYM *copy_sym P_ ((const SYM *));
static SYM *findsym P_ ((const CHAR *, SYM *const *));
static SYM *get_label P_ ((const CHAR *));
static SYM *global_search P_ ((SYM *));
static KEY skey P_ ((register const CHAR *));
static void addsym P_ ((SYM *, TABLE *));
static void append P_ ((SYM **, TABLE *, SYM **));
static void check_same P_ ((const SYM *, const SYM *));
static void deletesym P_ ((const SYM *, SYM **));
static void insertsym P_ ((SYM *, SYM **));
/*****************************************************************************/
static void check_same P2 (const SYM *, sp1, const SYM *, sp2)
{
if ((is_member (sp1) && !is_member (sp2)) || (!is_member (sp1) && is_member (sp2))) {
return;
}
#ifndef SYNTAX_CORRECT
if (!is_equal_type (typeof (sp1), typeof (sp2))) {
message (ERR_REDECL, nameof (sp1));
}
#endif /* SYNTAX_CORRECT */
}
SYM *mk_sym P3 (const CHAR *, name, STORAGE, storage, TYP *, tp)
{
SYM *sp;
sp = (SYM *) xalloc (sizeof (SYM));
set_nextsym (sp, NIL_SYM);
set_name (sp, name);
set_type (sp, tp);
sp->value.i = 0L;
set_storage (sp, storage);
sp->status = (STATUS) 0;
sp->function_specifier = fs_none;
#ifdef SEQUENCE
sp->sequence = (SEQNUM) 0;
#endif
return sp;
}
static SYM *copy_sym P1 (const SYM *, sp)
{
SYM *sp2;
sp2 = (SYM *) xalloc (sizeof (SYM));
*sp2 = *sp;
sp2->hnext = NIL_SYM;
set_nextsym (sp2, NIL_SYM);
return sp2;
}
static void addsym P2 (SYM *, sp, TABLE *, table)
{
assert (sp != NIL_SYM);
if (table->head == NIL_SYM) {
/* The table is empty so far... */
table->head = sp;
} else {
set_nextsym (table->tail, sp);
}
table->tail = sp;
set_nextsym (sp, NIL_SYM);
}
/* calculate the key for the hash function */
static KEY skey P1 (register const CHAR *, p)
{
register KEY sum;
for (sum = (KEY) 0; *p;) {
sum += (sum << 5) + (KEY) * p++;
}
return (sum % SMAXKEY);
}
/* insert a symbol into the specified hash table */
static void insertsym P2 (SYM *, sp, SYM **, hashtab)
{
KEY keyno = skey (nameof (sp));
sp->hnext = hashtab[keyno];
set_level (sp, scope_level);
hashtab[keyno] = sp;
}
/* insert a symbol into the specified hash table, at the reverse end */
static void rinsertsym P2 (SYM *, sp, SYM **, hashtab)
{
KEY keyno = skey (nameof (sp));
SYM **spp = &hashtab[keyno];
if (*spp) {
while ((*spp)->hnext) {
spp = &(*spp)->hnext;
}
(*spp)->hnext = sp;
} else {
hashtab[keyno] = sp;
}
}
/* find a symbol in the specified hash table */
static SYM *findsym P2 (const CHAR *, p, SYM *const *, hashtab)
{
register SYM *sp;
for (sp = hashtab[skey (p)]; sp; sp = sp->hnext) {
if (p == nameof (sp)) {
break;
}
}
return sp;
}
/* delete a symbol from the specified hash table */
static void deletesym P2 (const SYM *, sp, SYM **, hashtab)
{
SYM **hsp;
for (hsp = &hashtab[skey (nameof (sp))]; *hsp; hsp = &(*hsp)->hnext) {
if (*hsp == sp) {
*hsp = (*hsp)->hnext;
return;
}
}
}
/* returns true is the symbol is in the current scope, otherwise return false */
BOOL is_local_scope P1 (const SYM *, sp)
{
return (levelof (sp) >= scope_level);
}
/* searches the current scope/table for the specified symbol */
SYM *search P2 (const CHAR *, na, const TABLE *, table)
{
register SYM *sp;
for (sp = table->head; sp != NIL_SYM; sp = nextsym (sp)) {
if (nameof (sp) == na) {
break;
}
}
return sp;
}
/* looks to see if a symbol of this name can be found in the global scope */
static SYM *global_search P1 (SYM *, sp)
{
SYM *sp1;
for (sp1 = sp; sp1 != NIL_SYM; sp1 = sp1->hnext) {
if ((nameof (sp1) == nameof (sp)) && is_global_scope (sp1)) {
break;
}
}
return sp1;
}
static void append P3 (SYM **, ptr_sp, TABLE *, scope_tab, SYM **, hashtab)
{
SYM *sp1 = NIL_SYM;
SYM *sp = *ptr_sp;
if ((nameof (sp)[0] != (CHAR) 0) && (sp1 = findsym (nameof (sp), hashtab)) != NIL_SYM) {
if (is_extern (sp) && !is_local_scope (sp1) && !is_symbol_outscope (sp1)) {
/*ANSI 3.1.2.2
* If the declarator of an identifier for an object or a function
* contains the storage-class specifier extern, the identifier
* has the same linkage as any visible declaration of the
* identifier with file scope. If there is no visible declaration
* with file scope, the identifier has external linkage.
*/
sp1 = global_search (sp1);
if (sp1 != NIL_SYM) {
check_same (sp, sp1);
set_type (sp, typeof (sp1));
set_storage (sp, storageof (sp1));
sp->value = sp1->value;
sp->status |= sp1->status;
if (is_static (sp1)) {
symbol_output (sp);
}
}
}
}
if (sp1 != NIL_SYM) {
if (is_local_scope (sp1)) {
if (scope_level == GLOBAL_SCOPE) {
sp1->status &= (STATUS) ~((unsigned) SYM_OUTSCOPE);
}
check_same (sp, sp1);
set_type (sp1, composite_type (typeof (sp1), typeof (sp)));
if (is_func (typeof (sp))) {
sp1->status |= sp->status;
if (is_global (sp)) {
typeof (sp1)->state &= (STATE) (~(unsigned) STATE_ANSI);
if (is_ansi (typeof (sp))) {
set_ansi (typeof (sp1));
}
}
}
/*
* The new storage class depends on the old and on the new one.
*/
if (storageof (sp) == storageof (sp1)) {
#ifndef SYNTAX_CORRECT
switch (storageof (sp)) {
case sc_const:
case sc_auto:
message (ERR_REDECL, nameof (sp));
break;
case sc_typedef:
if (is_equal_type (typeof (sp), typeof (sp1))) {
message (WARN_REDECL, nameof (sp));
} else {
message (ERR_REDECL, nameof (sp));
}
break;
#ifdef FACIST
case sc_external:
message (WARN_DUPDECL, nameof (sp));
break;
#endif /* FACIST */
default:
break;
}
#endif /* SYNTAX_CORRECT */
if (!is_symbol_outscope (sp1)) {
*ptr_sp = sp1; /* caller uses old entry */
return;
}
}
switch (storageof (sp)) {
case sc_const:
case sc_typedef:
#ifndef SYNTAX_CORRECT
message (ERR_REDECL, nameof (sp));
#endif /* SYNTAX_CORRECT */
*ptr_sp = sp1; /* caller uses old entry */
return;
case sc_external:
if (scope_level == GLOBAL_SCOPE) {
sp1->status &= (STATUS) ~((unsigned) SYM_OUTSCOPE);
}
if (!is_symbol_outscope (sp1)) {
*ptr_sp = sp1; /* caller uses old entry */
return;
}
break;
case sc_global:
#ifndef SYNTAX_CORRECT
switch (storageof (sp1)) {
case sc_typedef:
case sc_const:
message (ERR_REDECL, nameof (sp));
return;
case sc_static:
if ((lang_option == LANG_KANDR) || !is_func (typeof (sp))) {
message (ERR_REDECL, nameof (sp));
} else if (is_func (typeof (sp))) {
message (WARN_GLOBAL, nameof (sp));
}
break;
default:
break;
}
#endif /* SYNTAX_CORRECT */
set_storage (sp1, sc_global);
*ptr_sp = sp1; /* caller uses old entry */
return;
case sc_static:
#ifndef SYNTAX_CORRECT
switch (storageof (sp1)) {
case sc_typedef:
case sc_const:
case sc_global:
message (ERR_REDECL, nameof (sp));
return;
case sc_external:
if (is_object_type (typeof (sp))) {
message (ERR_LINKAGE, nameof (sp));
} else {
message (WARN_EXTERN, nameof (sp));
}
break;
default:
break;
}
#endif /* SYNTAX_CORRECT */
set_storage (sp1, sc_static);
*ptr_sp = sp1; /* caller uses old entry */
return;
default:
#ifndef SYNTAX_CORRECT
if (is_typedef (sp1)) {
message (ERR_REDECL, nameof (sp));
}
#endif /* SYNTAX_CORRECT */
*ptr_sp = sp1; /* caller uses old entry */
return;
}
#ifndef SYNTAX_CORRECT
} else {
if (!is_member (sp)) {
switch (storageof (sp1)) {
case sc_external:
case sc_static:
if (!is_extern (sp) && !is_static (sp)) {
message (WARN_HIDE, nameof (sp));
}
break;
case sc_global:
if (!is_global (sp)) {
if (!is_function_type (typeof (sp))) {
message (WARN_HIDE, nameof (sp));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -