/*
** Most of the semantic routines are found here.
*/
#include <sys/types.h>
#include <stdio.h>
#include "ansi.h"
#include "host.h"
#include "files.h"
#include "hash.h"
#include "il.h"
#include "type_util.h"
#include "nodeop.h"
#include "stab.h"
#include "allocate.h"
#include "gen.h"
#include "ada_name.h"
#ifndef CCPROTO
#include "anonymous.h"
#endif
#include "config.h"
/* Import from scanner */
extern file_pos_t yypos;
extern int auto_package;
#undef NULL
#define NULL 0L
#undef N_BUILTINS
#define N_BUILTINS 5
static symbol_t builtins[N_BUILTINS];
static typeinfo_t builtin_types[N_BUILTINS];
static void dump_type _ANSI_PROTO_((typeinfo_t*));
static void dump_pos _ANSI_PROTO_((void));
void
not_implemented(file, line)
char *file;
int line;
{
fatal(file_name(yypos), line_number(yypos),
"This has not yet been implemented [%s:%d]", file, line);
}
/*
* These are the builtin/intrinsic types
*/
void
type_init()
{
int i;
symbol_t *sym;
typeinfo_t *typ;
/* int must be 0 */
sym = &builtins[0];
sym->gened = 1;
sym->intrinsic = 1;
sym->sym_type = &builtin_types[0];
sym->sym_kind = type_symbol;
sym->sym_ident = new_node(_Ident, "int");
#ifndef CCPROTO
sym->sym_ada_name = TYPE_NAMEOF_SIGNED_INT;
#endif
sym->sym_type->type_kind = int_type;
sym->sym_type->_sizeof = SIZEOF_INT;
sym->sym_type->_alignof = ALIGNOF_INT;
sym->sym_type->type_base = sym;
/*store_sym(sym);*/
/* void must be 1 */
sym = &builtins[1];
sym->gened = 1;
sym->intrinsic = 1;
sym->sym_type = &builtin_types[1];
sym->sym_kind = type_symbol;
sym->sym_ident = new_node(_Ident, "void");
#ifndef CCPROTO
sym->sym_ada_name = TYPE_NAMEOF_VOID;
#endif
sym->sym_type->type_kind = void_type;
sym->sym_type->_sizeof = SIZEOF_INT;
sym->sym_type->_alignof = ALIGNOF_INT;
sym->sym_type->type_base = sym;
/*store_sym(sym);*/
/* char must be 2 */
sym = &builtins[2];
sym->gened = 1;
sym->intrinsic = 1;
sym->sym_type = &builtin_types[2];
sym->sym_kind = type_symbol;
sym->sym_ident = new_node(_Ident, "char");
sym->sym_type->type_kind = int_type;
sym->sym_type->_sizeof = SIZEOF_CHAR;
sym->sym_type->_alignof = ALIGNOF_CHAR;
sym->sym_type->type_base = sym;
#ifdef CHARS_ARE_UNSIGNED
# ifndef CCPROTO
sym->sym_ada_name = TYPE_NAMEOF_UNSIGNED_CHAR;
# endif
sym->sym_type->_unsigned = 1;
#else
sym->sym_type->_signed = 1;
# ifndef CCPROTO
sym->sym_ada_name = TYPE_NAMEOF_SIGNED_CHAR;
# endif
#endif
/*store_sym(sym);*/
/* float must be 3 */
sym = &builtins[3];
sym->intrinsic = 1;
sym->gened = 1;
sym->sym_type = &builtin_types[3];
sym->sym_kind = type_symbol;
sym->sym_ident = new_node(_Ident, "float");
#ifndef CCPROTO
sym->sym_ada_name = TYPE_NAMEOF_FLOAT;
#endif
sym->sym_type->type_kind = float_type;
sym->sym_type->_sizeof = SIZEOF_FLOAT;
sym->sym_type->_alignof = ALIGNOF_FLOAT;
sym->sym_type->type_base = sym;
/*store_sym(sym);*/
/* double must be 4 */
sym = &builtins[4];
sym->intrinsic = 1;
sym->gened = 1;
sym->sym_type = &builtin_types[4];
sym->sym_kind = type_symbol;
sym->sym_ident = new_node(_Ident, "double");
#ifndef CCPROTO
sym->sym_ada_name = TYPE_NAMEOF_DOUBLE;
#endif
sym->sym_type->type_kind = float_type;
sym->sym_type->_sizeof = SIZEOF_DOUBLE;
sym->sym_type->_alignof = ALIGNOF_DOUBLE;
sym->sym_type->type_base = sym;
/*store_sym(sym);*/
for (i = 0; i < N_BUILTINS; i++) {
typ = &builtin_types[i];
typ->_builtin = 1;
set_hash_for_type(&builtin_types[i]);
}
#ifndef CCPROTO
init_anonymous_types();
#endif
}
symbol_t*
copy_sym(sym)
symbol_t *sym;
{
symbol_t *d;
d = new_sym();
d->sym_type = copy_type(sym->sym_type);
return d;
}
typeinfo_t*
typeof_int(is_unsigned)
{
typeinfo_t *typ;
typ = copy_type(&builtin_types[0]);
if (is_unsigned) typ->_unsigned = 1;
return typ;
}
static symbol_t*
int_basetype()
{
return &builtins[0];
}
typeinfo_t*
typeof_void()
{
return copy_type(&builtin_types[1]);
}
typeinfo_t*
typeof_char()
{
return copy_type(&builtin_types[2]);
}
typeinfo_t*
typeof_float()
{
return copy_type(&builtin_types[3]);
}
typeinfo_t*
typeof_double()
{
return copy_type(&builtin_types[4]);
}
static typeinfo_t*
typeof_enum()
{
typeinfo_t *typ;
typ = new_type(enum_type);
typ->_sizeof = SIZEOF_ENUM; /* See host.h */
typ->_alignof = ALIGNOF_ENUM;
set_hash_for_type(typ);
return typ;
}
static typeinfo_t*
typeof_rec(is_union)
int is_union;
{
return new_type(is_union ? union_of : struct_of);
}
decl_class_t
decl_class(typ)
typeinfo_t *typ;
{
if (typ == NULL) {
return int_decl;
}
switch (typ->type_kind) {
case field_type:
return field_decl;
case pointer_to:
return pointer_decl;
case array_of:
return array_decl;
case struct_of:
case union_of:
return struct_decl;
case int_type:
return int_decl;
case float_type:
return fp_decl;
case void_type:
return int_decl;
case function_type:
return func_decl;
case enum_type:
return enum_decl;
default:
fatal(__FILE__,__LINE__,"Unexpected type kind %d",
typ->type_kind);
return int_decl;
}
}
static symbol_t*
sym_decl(typ, n, uniq)
typeinfo_t *typ;
node_t *n;
int uniq; /* symbol name must be uniq */
{
symbol_t *sym;
assert(typ != NULL);
assert(n != NULL);
assert(n->node_kind == _Ident);
assert(n->node.id.name != NULL);
sym = new_sym();
sym->sym_def = n->node_def;
sym->sym_ident = n;
#ifndef CCPROTO
sym->sym_ada_name
= ada_name(sym->sym_ident->node.id.name,
uniq ? FILE_ORD(sym->sym_def) : -1);
#endif
sym->sym_type = copy_type(typ);
return sym;
}
symbol_t*
concat_symbols(s1,s2)
symbol_t *s1, *s2;
{
symbol_t *s;
if (s1 == NULL) return s2;
if (s2 == NULL) return s1;
for (s = s1; s->sym_parse_list; s = s->sym_parse_list);
s->sym_parse_list = s2;
return s1;
}
#ifndef CCPROTO
/*
* OK. The following looks really crappy. Since C lets you
* generate array types and pointer types without any formal
* declaration, we'll need to traverse all types seen in the
* C source and generate similar Ada types. For example, if
* foo(int*) is seen we'll need to generate type a_int_t is
* access c.signed_int automatically. OK wise guy, do you
* have a better idea?
*/
static void gen_tag_types _ANSI_PROTO_((symbol_t*));
static void
all_types_gened(typ)
typeinfo_t *typ;
{
symbol_t *basetype;
if (typ) {
all_types_gened(typ->type_next);
if (! typ->_builtin) {
switch (typ->type_kind) {
case pointer_to:
case array_of:
case struct_of:
case union_of:
case enum_type:
break;
case field_type:
case void_type:
case int_type:
case float_type:
case function_type:
return;
case typemodifier:
default:
assert(0);
}
basetype = typ->type_base;
if (basetype == NULL) {
basetype = get_anonymous_type(typ);
assert(basetype != NULL);
}
if (! basetype->gened) {
basetype->gened = 1;
gen_tag_types(basetype->sym_tags);
gen_ada_type(basetype);
}
}
}
}
static void
gen_tag_types(tags)
symbol_t *tags;
{
for (; tags; tags = tags->sym_parse_list) {
all_types_gened(tags->sym_type);
}
}
#endif
static typeinfo_t*
grok_array_type(typ, elem)
typeinfo_t *typ;
node_t *elem;
{
host_int_t nelem = -1;
typeinfo_t *array_type;
unsigned long bsize;
assert(typ != NULL);
if (elem != NULL) {
reduce_node(elem);
if (elem->node_kind == _Int_Number) {
nelem = elem->node.ival;
if (nelem < 0) {
warning(NODE_FNAME(elem), NODE_FLINE(elem),
"Array length %d is not supported (see %s:%d)",
nelem, __FILE__, __LINE__);
nelem = -1;
}
free_node(elem);
}
else {
nelem = -1;
/*
* Hell! Probably reduce_node() in nodeop.c isn't
* doing the right thing. Or it could be in cpp_eval
*/
warning(NODE_FNAME(elem), NODE_FLINE(elem),
"Failed reducing array index to a constant integer value (see %s:%d)",
__FILE__, __LINE__);
}
}
array_type = add_array_type(typ, nelem);
all_types_gened(array_type);
return array_type;
#if 0
array_type = new_type(array_of);
array_type->type_info.array_elements = nelem;
array_type->type_next = typ;
array_type->_typedef = typ->_typedef;
switch (nelem) {
case -1:
array_type->_sizeof = SIZEOF_ADDRESS;
array_type->_alignof = ALIGNOF_ADDRESS;
break;
case 0:
array_type->_sizeof = 0;
array_type->_alignof = 0;
break;
default:
array_type->_alignof = type_alignof(typ);
bsize = alignto(type_sizeof(typ), array_type->_alignof);
array_type->_sizeof = bsize * nelem;
break;
}
set_hash_for_type(array_type);
return array_type;
#endif
}
typeinfo_t*
typeof_typemod(adj)
int adj;
{
typeinfo_t *typ;
typ = new_type(typemodifier);
switch (adj) {
case TYPEMOD_SHORT:
typ->_short = 1;
break;
case TYPEMOD_LONG:
typ->_long = 1;
break;
case TYPEMOD_SIGNED:
typ->_signed = 1;
typ->_unsigned = 0;
break;
case TYPEMOD_UNSIGNED:
typ->_unsigned = 1;
typ->_signed = 0;
break;
case TYPEMOD_CONST:
typ->_constant = 1;
break;
case TYPEMOD_VOLATILE:
typ->_volatile = 1;
break;
case TYPEMOD_TYPEDEF:
typ->_typedef = 1;
break;
case TYPEMOD_EXTERN:
typ->_extern = 1;
break;
case TYPEMOD_STATIC:
typ->_static = 1;
break;
case TYPEMOD_AUTO:
typ->_auto = 1;
break;
case TYPEMOD_REGISTER:
typ->_register = 1;
break;
default:
assert(0);
break;
}
return typ;
}
static void
combine_typespec(tmod)
typeinfo_t *tmod;
{
typeinfo_t *typ;
assert(tmod != NULL);
assert(tmod->type_kind == typemodifier);
assert(tmod->type_next != NULL);
typ = tmod->type_next;
if (typ->_volatile) tmod->_volatile = 1;
if (typ->_constant) tmod->_constant = 1;
if (typ->_extern) tmod->_extern = 1;
if (typ->_static) tmod->_static = 1;
if (typ->_auto) tmod->_auto = 1;
if (typ->_register) tmod->_register = 1;
if (typ->_typedef) tmod->_typedef = 1;
if (tmod->_signed) {
tmod->_unsigned = 0;
}
else if (tmod->_unsigned) {
tmod->_signed = 0;
}
else if (typ->_unsigned) {
tmod->_unsigned = 1;
tmod->_signed = 0;
}
else if (typ->_signed) {
tmod->_unsigned = 0;
tmod->_signed = 1;
}
if (tmod->_short == 0) {
if (typ->_short) tmod->_short = 1;
if (typ->_long_long)tmod->_long_long = 1;
if (typ->_long) {
if (tmod->_long) {
tmod->_long_long = 1;
}
else {
tmod->_long = 1;
}
}
}
tmod->type_kind = typ->type_kind;
tmod->type_info = typ->type_info;
tmod->_sizeof = typ->_sizeof;
tmod->_alignof = typ->_alignof;
tmod->type_base = typ->type_base;
tmod->type_next = typ->type_next;
set_hash_for_type(tmod);
deallocate(typ);
}
typeinfo_t*
typeof_typespec(tlist)
typeinfo_t *tlist;
{
typeinfo_t *prev = NULL;
typeinfo_t *result = tlist;
top:
assert(tlist != NULL);
switch (tlist->type_kind) {
case typemodifier:
if (tlist->type_next == NULL) {
/*
* If type is not specified it's assumed to be an int.
* ie. short foo; == short int foo;
*/
result = tlist;
result->type_kind = int_type;
result->type_base = int_basetype();
if (result->_short) {
result->_sizeof = SIZEOF_SHORT;
result->_alignof = ALIGNOF_SHORT;
}
#ifdef SIZEOF_LONG_LONG
else if (result->_long_long) {
result->_sizeof = SIZEOF_LONG_LONG;
result->_alignof = ALIGNOF_LONG_LONG;
result->_short = 0;
result->_long = 0;
set_hash_for_type(result);
}
#endif
else if (result->_long) {
result->_sizeof = SIZEOF_LONG;
result->_alignof = ALIGNOF_LONG;
}
else {
result->_sizeof = SIZEOF_INT;
result->_alignof = ALIGNOF_INT;
}
set_hash_for_type(result);
}
else {
combine_typespec(tlist);
goto top;
}
break;
case void_type:
case int_type:
case float_type:
case struct_of:
case union_of:
case enum_type:
assert(tlist->type_next == NULL);
break;
case array_of:
case pointer_to:
case function_type:
break;
default:
assert(0);
break;
}
return result;
}
typeinfo_t*
typeof_specifier(sym)
symbol_t *sym;
{
typeinfo_t *typ;
assert(sym != NULL);
assert(sym->sym_type != NULL);
typ = copy_type(sym->sym_type);
typ->type_base = sym;
return typ;
}
static symbol_t*
KnR_formals(params)
node_t *params;
{
symbol_t *p1, *p2;
if (params == NULL) return NULL;
switch (params->node_kind) {
case _List:
p1 = KnR_formals(params->node.binary.l);
p2 = KnR_formals(params->node.binary.r);
free_node(params);
p1 = concat_symbols(p1, p2);
break;
case _Ident:
p1 = sym_decl(typeof_int(0), params, 0);
break;
default:
assert(0);
break;
}
return p1;
}
static symbol_t*
grok_formals(params)
node_t *params;
{
symbol_t *p;
if (params == NULL) return NULL;
if (params->node_kind == _Sym) { /* Ansi function decl */
p = params->node.sym;
free_node(params);
return p;
}
return KnR_formals(params);
}
static void
grok_subp(subp)
symbol_t *subp;
{
symbol_t *param, *prev;
prev = NULL;
param = subp->sym_tags;
for (; param && param->sym_parse_list; param = param->sym_parse_list) {
prev = param;
}
if (param != NULL && param->var_params) {
subp->var_params = 1;
if (prev) {
prev->sym_parse_list = NULL;
} else {
subp->sym_tags = NULL;
}
}
}
static typeinfo_t*
add_field(typ, width)
typeinfo_t *typ;
node_t *width;
{
typeinfo_t *ftype;
assert(typ != NULL);
assert(width != NULL);
reduce_node(width);
if (width->node_kind != _Int_Number || width->node.ival < 1 || width->node.ival > 31) {
warning(NODE_FNAME(width), NODE_FLINE(width),
"Bit filed width not handled properly (see %s:%d)",
__FILE__, __LINE__);
return typ;
}
ftype = new_type(field_type);
ftype->type_next = typ;
ftype->_sizeof = width->node.ival;
free_node(width);
set_hash_for_type(ftype);
return ftype;
}
static symbol_t*
grok_decl_list(tspec, vlist, uniq)
typeinfo_t *tspec;
node_t *vlist;
int uniq; /* Generate uniq Ada idenifer name */
{
symbol_t *d1, *d2;
assert(tspec != NULL);
assert(vlist != NULL);
switch (vlist->node_kind) {
case _List:
d1 = grok_decl_list(tspec, vlist->node.binary.l, uniq);
d2 = grok_decl_list(tspec, vlist->node.binary.r, uniq);
free_node(vlist);
return concat_symbols(d1, d2);
case _Ident:
assert(vlist->node.id.name != NULL);
d1 = sym_decl(tspec, vlist, uniq);
return d1;
case _Assign:
d1 = grok_decl_list(tspec, vlist->node.binary.l, uniq);
d1->sym_value.initializer = vlist->node.binary.r;
d1->has_initializer = 1;
free_node(vlist);
return d1;
case _Bit_Field:
tspec = add_field(tspec, vlist->node.binary.r);
if (vlist->node.binary.l == NULL) {
d1 = new_sym();
d1->sym_type = copy_type(tspec);
}
else {
d1 = grok_decl_list(tspec, vlist->node.binary.l, 0);
}
free_node(vlist);
return d1;
case _Array_Index:
if (vlist->node.binary.l == NULL) {
d1 = new_sym();
d1->sym_type = tspec;
}
else {
d1 = grok_decl_list(tspec, vlist->node.binary.l, uniq);
}
d1->sym_type = grok_array_type(d1->sym_type, vlist->node.binary.r);
return d1;
case _Indirect:
tspec = add_pointer_type(tspec);
if (vlist->node.unary == NULL) {
d1 = new_sym();
d1->sym_type = tspec;
return d1;
}
return grok_decl_list(tspec, vlist->node.unary, uniq);
case _Func_Call:
tspec = add_function_type(tspec);
d1 = grok_decl_list(tspec, vlist->node.binary.l, uniq);
if (d1->sym_tags == NULL) {
d1->sym_tags = grok_formals(vlist->node.binary.r);
grok_subp(d1);
}
tspec->type_info.subp_params = d1->sym_tags;
return d1;
default:
fatal(file_name(yypos), line_number(yypos),
"Unhandled node kind %d [%s:%d]",
vlist->node_kind, __FILE__, __LINE__);
break;
}
return NULL;
}
static void
check_type_base(sym)
symbol_t *sym;
{
typeinfo_t *typ;
assert(sym != NULL);
typ = sym->sym_type;
assert(typ != NULL);
switch (decl_class(typ)) {
case pointer_decl:
case array_decl:
typ->type_base = sym;
break;
default:
assert(typ->type_base != NULL);
break;
}
}
static symbol_t*
set_symbol_kind(vlist)
symbol_t *vlist;
{
symbol_t *s;
typeinfo_t *typ;
assert(vlist != NULL);
for (s = vlist; s; s = s->sym_parse_list) {
typ = s->sym_type;
if (typ->_typedef) {
s->sym_kind = type_symbol;
if (is_array(typ)) {
typ->type_base = s;
}
}
else if (typ->type_kind == function_type) {
s->sym_kind = func_symbol;
}
else {
s->sym_kind = var_symbol;
}
}
return vlist;
}
static void
dump_pos()
{
fprintf(stderr, "%s:%d\n", file_name(yypos), line_number(yypos));
fflush(stderr);
}
/*
* Useful routine for debugging if your debugger lets
* you invoke it directly. If using verdix debugger
* you can say: p debug_type(typ)
* buy vads :-)
*/
static void
dump_type(typ)
typeinfo_t *typ;
{
symbol_t *basetype;
for (; typ; typ = typ->type_next) {
if (typ->_static) fputs("static/", stderr);
if (typ->_typedef) fputs("typedef/", stderr);
if (typ->_short) fputs("short/", stderr);
if (typ->_long) fputs("long/", stderr);
if (typ->_long_long) fputs("long_long/", stderr);
if (typ->_signed) fputs("signed/", stderr);
if (typ->_unsigned) fputs("unsigned/", stderr);
switch (typ->type_kind) {
case pointer_to:
fputs("pointer_to", stderr);
break;
case array_of:
fputs("array_of", stderr);
break;
case struct_of:
fputs("struct_of", stderr);
break;
case union_of:
fputs("union_of", stderr);
break;
case field_type:
fputs("field_type", stderr);
break;
case int_type:
fputs("int_type", stderr);
break;
case float_type:
fputs("float_type", stderr);
break;
case void_type:
fputs("void_type", stderr);
break;
case function_type:
fputs("function_type", stderr);
break;
case enum_type:
fputs("enum_type", stderr);
break;
case typemodifier:
fputs("typemodifier", stderr);
break;
default:
fputs("default", stderr);
break;
}
fputc('[',stderr);
basetype = typ->type_base;
if (basetype != NULL) {
assert(basetype->sym_ident != NULL);
assert(basetype->sym_ident->node_kind == _Ident);
assert(basetype->sym_ident->node.id.name != NULL);
fputs(basetype->sym_ident->node.id.name, stderr);
}
fputs("] ",stderr);
}
fputc('\n',stderr);
}
static int
decl_defined(sym)
symbol_t *sym;
{
symbol_t *dup;
assert(sym->sym_ident != NULL);
assert(sym->sym_ident->node_kind == _Ident);
assert(sym->sym_ident->node.id.name != NULL);
dup = find_sym(sym->sym_ident->node.id.name);
if (dup == NULL) {
store_sym(sym);
return 0;
}
if (sym->sym_kind != dup->sym_kind) {
return 0;
}
return equal_types(sym->sym_type, dup->sym_type);
}
static void find_units();
static void
get_basetype_unit_list(ord, sym)
symbol_t *sym;
{
symbol_t *tags;
for (tags = sym->sym_tags; tags; tags = tags->sym_parse_list) {
find_units(ord, tags->sym_type);
}
if (sym->sym_type->type_base != sym) {
find_units(ord, sym->sym_type);
}
}
static void
find_units(ord, typ)
int ord;
typeinfo_t *typ;
{
#ifndef CCPROTO
typeinfo_t *t;
symbol_t *basetype;
int unit_ord;
for (t = typ; t; t = t->type_next) {
if (! t->_builtin) {
basetype = t->type_base;
if (basetype != NULL && !basetype->intrinsic && basetype->traversal_unit != ord) {
basetype->traversal_unit = ord;
get_basetype_unit_list(ord, basetype);
unit_ord = FILE_ORD(basetype->sym_def);
if (unit_ord != ord) {
unit_dependency(ord, unit_ord);
}
}
}
}
#endif
}
/*
* Determine which Ada package need to be with'd
* for the types of this symbol
*/
static void
get_unit_list(sym)
symbol_t *sym;
{
symbol_t *tags;
int unit_ord;
if (!auto_package) return;
for (tags = sym->sym_tags; tags; tags = tags->sym_parse_list) {
unit_ord = FILE_ORD(tags->sym_def);
find_units(unit_ord, tags->sym_type);
}
unit_ord = FILE_ORD(sym->sym_def);
find_units(unit_ord, sym->sym_type);
}
static void
grok_decl(sym)
symbol_t *sym;
{
typeinfo_t *typ, *ntyp;
assert(sym != NULL);
typ = sym->sym_type;
assert(typ != NULL);
assert(sym->sym_parse_list == NULL);
if (typ->_typedef) {
if (typ->type_kind == union_of || typ->type_kind == struct_of) {
assert(typ->type_base != NULL);
if (typ->type_base != sym) {
sym->sym_tags = typ->type_base->sym_tags;
}
}
else if (is_access(typ)) {
ntyp = typ->type_next;
assert(ntyp != NULL);
all_types_gened(ntyp);
typ->type_base = sym;
}
}
#ifndef CCPROTO
all_types_gened(typ);
gen_tag_types(sym->sym_tags);
get_unit_list(sym);
#endif
switch (sym->sym_kind) {
case type_symbol:
store_sym(sym);
if (! sym->gened) {
sym->gened = 1;
gen_ada_type(sym);
}
break;
case func_symbol:
#ifndef CCPROTO
if (! is_static_function(typ)) {
#endif
if (! decl_defined(sym)) {
if (! sym->gened) {
sym->gened = 1;
gen_ada_func(sym);
}
}
#ifndef CCPROTO
}
#endif
break;
case var_symbol:
if (! typ->_static) {
if (! decl_defined(sym)) {
if (! sym->gened) {
sym->gened = 1;
gen_ada_var(sym);
}
}
}
break;
case enum_literal:
default:
fatal(__FILE__,__LINE__,"Unhandled symbol kind %d",
sym->sym_kind);
break;
}
}
void
grok_declarations(list)
symbol_t *list;
{
symbol_t *next;
for (; list; list = next) {
next = list->sym_parse_list;
list->sym_parse_list = NULL;
grok_decl(list);
}
}
static void
grok_enum_lits(tags, typ)
symbol_t *tags;
typeinfo_t *typ;
{
symbol_t *sym;
int ord = 0;
for (sym = tags; sym; sym = sym->sym_parse_list) {
assert(sym->sym_type == NULL);
sym->sym_type = typ;
if (sym->sym_value.intval == 0xBAD) {
sym->sym_value.intval = ord++;
}
else {
ord = sym->sym_value.intval + 1;
}
}
}
static symbol_t*
gen_enum_sym(id)
node_t *id;
{
symbol_t *sym;
char enum_name[2048];
assert(id != NULL);
assert(id->node_kind == _Ident);
enum_name[0] = ENUM_PREFIX;
strcpy(&enum_name[1], id->node.id.name);
id->node.id.name = new_string(enum_name);
sym = new_sym();
sym->sym_type = typeof_enum();
sym->sym_kind = type_symbol;
sym->sym_ident = id;
#ifndef CCPROTO
sym->sym_ada_name = ada_name(enum_name, FILE_ORD(sym->sym_def));
#endif
sym->sym_def = id->node_def;
return sym;
}
static void
add_tags(decls, tags)
symbol_t *decls, *tags;
{
symbol_t *sym;
for (sym = decls; sym; sym = sym->sym_parse_list) {
assert(sym->sym_tags == NULL);
sym->sym_tags = tags;
}
}
static void
grok_sizeof_struct(styp, fields)
typeinfo_t *styp;
symbol_t *fields;
{
symbol_t *sym;
typeinfo_t *typ, *ftype;
int min = 0;
int aggsize = 0;
int bitsize = 0;
int width, tmp;
for (sym = fields; sym; sym = sym->sym_parse_list) {
typ = sym->sym_type;
assert(typ != NULL);
if (typ->type_kind == field_type) {
width = typ->_sizeof;
ftype = typ->type_next; assert(ftype != NULL);
if (ftype->_sizeof > min) {
min = ftype->_sizeof;
}
align_field:
tmp = alignto(aggsize, ftype->_alignof);
if (tmp != aggsize) {
aggsize = tmp;
bitsize = 0;
}
tmp = bitsize + width;
if (tmp > ftype->_sizeof * BITS_PER_BYTE) {
aggsize += (bitsize + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
bitsize = 0;
goto align_field;
}
sym->bitoffset = aggsize * BITS_PER_BYTE + bitsize;
typ->_alignof = bitsize;
bitsize += width;
}
else {
if (bitsize != 0) {
aggsize += (bitsize + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
bitsize = 0;
}
aggsize = alignto(aggsize, typ->_alignof);
sym->bitoffset = aggsize * BITS_PER_BYTE;
aggsize += typ->_sizeof;
}
}
if (bitsize != 0) {
aggsize += (bitsize + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
}
if (aggsize < min) {
aggsize = min;
}
styp->_sizeof = aggsize;
set_hash_for_type(styp);
}
static void
grok_sizeof_union(utyp, fields)
typeinfo_t *utyp;
symbol_t *fields;
{
symbol_t *sym;
typeinfo_t *typ;
int aggsize = 0;
for (sym = fields; sym; sym = sym->sym_parse_list) {
typ = sym->sym_type;
assert(typ != NULL);
assert(typ->type_kind != field_type);
if (typ->_sizeof > aggsize) {
aggsize = typ->_sizeof;
}
}
utyp->_sizeof = aggsize;
set_hash_for_type(utyp);
}
static void
grok_alignof_record(rtyp, fields)
typeinfo_t *rtyp;
symbol_t *fields;
{
symbol_t *sym;
typeinfo_t *typ;
int max = 0;
for (sym = fields; sym; sym = sym->sym_parse_list) {
typ = sym->sym_type;
assert(typ != NULL);
if (typ->type_kind == field_type) {
typ = typ->type_next;
assert(typ != NULL);
}
if (typ->_alignof > max) {
max = typ->_alignof;
}
}
rtyp->_alignof = max;
set_hash_for_type(rtyp);
}
static void
grok_type(typ)
typeinfo_t *typ;
{
if (typ == NULL) return;
switch (decl_class(typ)) {
case pointer_decl:
typ->_sizeof = SIZEOF_ADDRESS;
typ->_alignof = ALIGNOF_ADDRESS;
if (is_function_pointer(typ)) {
grok_type(typ->type_next->type_next);
} else {
grok_type(typ->type_next);
}
set_hash_for_type(typ);
break;
case int_decl:
#ifdef SIZEOF_LONG_LONG
if (typ->_long_long) {
typ->_sizeof = SIZEOF_LONG_LONG;
typ->_alignof = ALIGNOF_LONG_LONG;
typ->_short = 0;
typ->_long = 0;
set_hash_for_type(typ);
return;
}
#endif
if (typ->_long) {
typ->_sizeof = SIZEOF_LONG;
typ->_alignof = ALIGNOF_LONG;
typ->_short = 0;
typ->_long_long = 0;
set_hash_for_type(typ);
return;
}
if (typ->_short) {
typ->_sizeof = SIZEOF_SHORT;
typ->_alignof = ALIGNOF_SHORT;
typ->_long_long = 0;
set_hash_for_type(typ);
return;
}
break;
case fp_decl:
#ifdef SIZEOF_LONG_DOUBLE
if (typ->_long) {
if (typ->_sizeof == SIZEOF_DOUBLE&&typ->_alignof == ALIGNOF_DOUBLE){
typ->_sizeof = SIZEOF_LONG_DOUBLE;
typ->_alignof = ALIGNOF_LONG_DOUBLE;
set_hash_for_type(typ);
return;
}
}
#endif
break;
case func_decl:
assert(0);
break;
case enum_decl:
typ->_sizeof = SIZEOF_INT;
typ->_alignof = ALIGNOF_INT;
set_hash_for_type(typ);
break;
case array_decl:
case struct_decl:
set_hash_for_type(typ);
break;
default:
assert(0);
break;
}
}
static symbol_t*
gen_rec_sym(id, typ)
node_t *id;
typeinfo_t *typ;
{
symbol_t *sym;
char rec_name[2048];
assert(id != NULL);
assert(id->node_kind == _Ident);
rec_name[0] = (typ->type_kind == struct_of) ? STRUCT_PREFIX : UNION_PREFIX;
strcpy(&rec_name[1], id->node.id.name);
id->node.id.name = new_string(rec_name);
sym = new_sym();
sym->sym_type = typ;
sym->sym_kind = type_symbol;
sym->sym_ident = id;
#ifndef CCPROTO
sym->sym_ada_name = ada_name(rec_name, FILE_ORD(sym->sym_def));
#endif
sym->sym_def = id->node_def;
typ->type_base = sym;
return sym;
}
symbol_t*
grok_enumerator(id, val)
node_t *id, *val;
{
symbol_t *sym;
assert(id != NULL);
assert(id->node_kind == _Ident);
assert(id->node.id.name != NULL);
sym = new_sym();
sym->sym_ident = id;
#ifndef CCPROTO
sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def));
#endif
if (val == NULL) {
sym->sym_value.intval = 0xBAD;
}
else {
reduce_node(val);
if (val->node_kind == _Int_Number) {
sym->sym_value.intval = val->node.ival;
}
else {
warning(NODE_FNAME(val), NODE_FLINE(val),
"Enum literal value ignored");
sym->sym_value.intval = 0xBAD;
}
}
store_sym(sym);
return sym;
}
static char*
gen_type_name(prefix)
int prefix;
{
char name[256];
#ifdef CCPROTO
name[0] = prefix;
name[1] = 0;
#else
sprintf(name, "%c%s%d%s", prefix, OTHER_TYPE_PREFIX,
next_anonymous_ord(), TYPE_POSTFIX);
#endif
return new_string(name);
}
static char*
add_prefix(name, prefix, buf, len)
char *name, *buf;
int prefix, len;
{
char *result;
int nlen;
assert(name != NULL);
nlen = strlen(name) + 2;
if (buf == NULL || nlen > len) {
result = (char*) malloc(strlen(name)+2);
}
else {
result = buf;
}
assert(result != NULL);
result[0] = prefix;
strcpy(&result[1], name);
return result;
}
symbol_t*
anonymous_enum(literals)
symbol_t *literals;
{
symbol_t *sym;
assert(literals != NULL);
sym = new_sym();
sym->sym_type = typeof_enum();
sym->sym_type->type_base = sym;
sym->sym_kind = type_symbol;
sym->sym_ident = new_node(_Ident, gen_type_name(ENUM_PREFIX));
#ifndef CCPROTO
sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def));
#endif
sym->_created_name = 1;
grok_enum_lits(literals, sym->sym_type);
add_tags(sym, literals);
return sym;
}
symbol_t*
named_enum(id, literals)
node_t *id;
symbol_t *literals;
{
symbol_t *sym;
char buf[1024];
assert(id != NULL);
assert(literals != NULL);
assert(id->node_kind == _Ident);
buf[0] = ENUM_PREFIX;
strcpy(&buf[1], id->node.id.name);
sym = find_sym(buf);
if (sym == NULL) {
sym = new_sym();
sym->sym_type = typeof_enum();
sym->sym_type->type_base = sym;
sym->sym_ident = new_node(_Ident, new_string(buf));
#ifndef CCPROTO
sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def));
#endif
sym->sym_kind = type_symbol;
store_sym(sym);
}
else {
sym->_created_by_reference = 0;
}
sym->sym_def = id->node_def;
grok_enum_lits(literals, sym->sym_type);
add_tags(sym, literals);
return sym;
}
symbol_t*
enum_reference(id)
node_t *id;
{
char buf[256];
char *name;
symbol_t *sym;
assert(id != NULL);
assert(id->node_kind == _Ident);
name = add_prefix(id->node.id.name, ENUM_PREFIX, buf, sizeof(buf));
sym = find_sym(name);
if (sym == NULL || !is_typedef(sym)) {
sym = new_sym();
sym->sym_type = typeof_enum();
sym->sym_type->type_base = sym;
sym->sym_kind = type_symbol;
if (name != buf) {
id->node.id.name = name;
}
else {
id->node.id.name = new_string(name);
}
sym->sym_ident = id;
#ifndef CCPROTO
sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def));
#endif
sym->_created_by_reference = 1;
store_sym(sym);
}
else {
if (name != buf) {
free(name);
}
}
return sym;
}
static char*
anonymous_rec_name(is_union)
int is_union;
{
return gen_type_name(is_union ? UNION_PREFIX : STRUCT_PREFIX);
}
static symbol_t*
delete_unamed_fields(tags)
symbol_t *tags;
{
symbol_t *head = NULL;
symbol_t *last = NULL;
if (tags == NULL) return NULL;
for (; tags; tags = tags->sym_parse_list) {
if (tags->sym_ident == NULL) {
if (head != NULL) {
last->sym_parse_list = tags->sym_parse_list;
}
}
else {
if (head == NULL) {
head = tags;
}
else {
last->sym_parse_list = tags;
}
last = tags;
}
}
return head;
}
symbol_t*
anonymous_rec(is_union, tags)
int is_union;
symbol_t *tags;
{
symbol_t *sym;
typeinfo_t *rtyp;
assert(tags != NULL);
rtyp = typeof_rec(is_union);
sym = new_sym();
sym->sym_type = rtyp;
sym->sym_kind = type_symbol;
sym->sym_ident = new_node(_Ident, anonymous_rec_name(is_union));
#ifndef CCPROTO
sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def));
#endif
sym->sym_tags = tags;
rtyp->type_base = sym;
if (is_union) {
grok_sizeof_union(rtyp, tags);
}
else {
grok_sizeof_struct(rtyp, tags);
tags = delete_unamed_fields(tags);
sym->sym_tags = tags;
}
grok_alignof_record(rtyp, tags);
return sym;
}
symbol_t*
named_rec(is_union, id, tags)
int is_union;
node_t *id;
symbol_t *tags;
{
symbol_t *sym;
typeinfo_t *rtyp;
char buf[1024];
assert(id != NULL);
assert(id->node_kind == _Ident);
assert(tags != NULL);
buf[0] = is_union ? UNION_PREFIX : STRUCT_PREFIX;
strcpy(&buf[1], id->node.id.name);
sym = find_sym(buf);
if (sym == NULL) {
rtyp = typeof_rec(is_union);
sym = gen_rec_sym(id, rtyp);
store_sym(sym);
}
else {
sym->_created_by_reference = 0;
rtyp = sym->sym_type;
}
sym->sym_tags = tags;
if (is_union) {
grok_sizeof_union(rtyp, tags);
}
else {
grok_sizeof_struct(rtyp, tags);
tags = delete_unamed_fields(tags);
sym->sym_tags = tags;
}
grok_alignof_record(rtyp, tags);
return sym;
}
symbol_t*
rec_reference(is_union, id)
int is_union;
node_t *id;
{
symbol_t *sym;
typeinfo_t *rtyp;
char buf[1024];
assert(id != NULL);
assert(id->node_kind == _Ident);
buf[0] = is_union ? UNION_PREFIX : STRUCT_PREFIX;
strcpy(&buf[1], id->node.id.name);
sym = find_sym(buf);
if (sym == NULL) {
rtyp = typeof_rec(is_union);
sym = gen_rec_sym(id, rtyp);
sym->_created_by_reference = 1;
store_sym(sym);
}
return sym;
}
static int
no_typemods(typ)
typeinfo_t *typ;
{
for (; typ; typ = typ->type_next) {
if (typ->type_kind == typemodifier) {
return 0;
}
}
return 1;
}
symbol_t*
novar_declaration(tlist)
typeinfo_t *tlist;
{
symbol_t *result = NULL;
assert(tlist != NULL);
tlist = typeof_typespec(tlist);
assert(no_typemods(tlist));
switch (decl_class(tlist)) {
case int_decl:
return NULL;
case enum_decl:
case struct_decl:
assert(tlist->type_base != NULL);
return tlist->type_base;
case pointer_decl:
case fp_decl:
case func_decl:
case array_decl:
break;
default:
assert(0);
break;
}
assert(0);
return result;
}
symbol_t*
var_declaration(tlist, vlist)
typeinfo_t *tlist;
node_t *vlist;
{
symbol_t *decl_list;
assert(tlist != NULL);
assert(vlist != NULL);
tlist = typeof_typespec(tlist);
assert(no_typemods(tlist));
grok_type(tlist);
decl_list = grok_decl_list(tlist, vlist, 1);
return set_symbol_kind(decl_list);
}
symbol_t*
function_spec(tlist, f)
typeinfo_t *tlist;
node_t *f;
{
symbol_t *fdecl;
assert(f != NULL);
if (tlist == NULL) {
tlist = typeof_int(0);
}
else {
tlist = typeof_typespec(tlist);
}
assert(no_typemods(tlist));
grok_type(tlist);
fdecl = grok_decl_list(tlist, f, 1);
assert(fdecl != NULL);
fdecl->sym_kind = func_symbol;
return fdecl;
}
static void
set_field_names(tags)
symbol_t *tags;
{
#ifndef CCPROTO
for (; tags; tags = tags->sym_parse_list) {
if (tags->sym_ada_name == NULL) {
if (tags->sym_ident != NULL) {
tags->sym_ada_name = ada_name(tags->sym_ident->node.id.name, FILE_ORD(tags->sym_def));
}
}
}
#endif
}
symbol_t*
field_declaration(tlist, vlist)
typeinfo_t *tlist;
node_t *vlist;
{
symbol_t *decl_list;
assert(tlist != NULL);
assert(vlist != NULL);
tlist = typeof_typespec(tlist);
assert(no_typemods(tlist));
grok_type(tlist);
decl_list = grok_decl_list(tlist, vlist, 0);
set_field_names(decl_list);
#ifndef CCPROTO
gen_tag_types(decl_list);
#endif
return set_symbol_kind(decl_list);
}
void
typed_external_decl(syms)
symbol_t *syms;
{
symbol_t *next;
for (; syms; syms = next) {
next = syms->sym_parse_list;
syms->sym_parse_list = NULL;
grok_decl(syms);
}
}
static char*
next_param_name()
{
char buf[48];
sprintf(buf, "p%d", next_param());
return new_string(buf);
}
symbol_t*
noname_simple_param(typ)
typeinfo_t *typ;
{
symbol_t *sym;
char *name;
assert(typ != NULL);
name = next_param_name();
typ = typeof_typespec(typ);
assert(no_typemods(typ));
grok_type(typ);
sym = new_sym();
sym->sym_ident = new_node(_Ident, name);
#ifndef CCPROTO
sym->sym_ada_name = name;
#endif
sym->sym_type = typ;
sym->sym_kind = param_symbol;
return sym;
}
symbol_t*
noname_abstract_param(typ, adecl)
typeinfo_t *typ;
node_t *adecl;
{
symbol_t *sym;
char *name;
assert(typ != NULL);
assert(adecl != NULL);
name = next_param_name();
typ = typeof_typespec(typ);
assert(no_typemods(typ));
grok_type(typ);
sym = grok_decl_list(typ, adecl, 0);
sym->sym_ident = new_node(_Ident,name);
#ifndef CCPROTO
sym->sym_ada_name = name;
#endif
sym->sym_kind = param_symbol;
return sym;
}
symbol_t*
named_abstract_param(typ, adecl)
typeinfo_t *typ;
node_t *adecl;
{
symbol_t *sym;
assert(typ != NULL);
assert(adecl != NULL);
next_param();
typ = typeof_typespec(typ);
assert(no_typemods(typ));
grok_type(typ);
sym = grok_decl_list(typ, adecl, 0);
sym->sym_kind = param_symbol;
return sym;
}
typeinfo_t*
noname_type(typ, adecl)
typeinfo_t *typ;
node_t *adecl;
{
symbol_t *sym;
assert(typ != NULL);
assert(adecl != NULL);
typ = typeof_typespec(typ);
assert(no_typemods(typ));
grok_type(typ);
sym = grok_decl_list(typ, adecl, 0);
return sym->sym_type;
}
static void
KnR_tag_type(p, params)
symbol_t *p, *params;
{
for (; params; params = params->sym_parse_list) {
if (!strcmp(p->sym_ident->node.id.name, params->sym_ident->node.id.name)) {
p->sym_type = params->sym_type;
return;
}
}
}
void
KnR_params(func, params)
symbol_t *func, *params;
{
symbol_t *tags;
assert(func != NULL);
assert(params != NULL);
for (tags = func->sym_tags; tags; tags = tags->sym_parse_list) {
KnR_tag_type(tags, params);
}
}
void
function_def(f)
symbol_t *f;
{
symbol_t *dup;
assert(f != NULL);
#ifndef CCPROTO
if (is_static_function(f->sym_type)) {
return;
}
#endif
assert(f->sym_ident != NULL);
assert(f->sym_ident->node_kind == _Ident);
assert(f->sym_ident->node.id.name != NULL);
dup = find_sym(f->sym_ident->node.id.name);
if (dup == NULL) {
grok_decl(f);
return;
}
if (dup->sym_tags == NULL && f->sym_tags != NULL) {
/* Must be K&R crap */
dup->sym_tags = f->sym_tags;
#ifndef CCPROTO
gen_tag_types(dup->sym_tags);
#endif
}
}
symbol_t*
elipsis_arg()
{
static symbol_t varg;
varg.var_params = 1;
return &varg;
}
syntax highlighted by Code2HTML, v. 0.9.1