/*
* Functions to generate anonymous Ada types
*/
#include <sys/types.h>
#include "ansi.h"
#include "host.h"
#include "files.h"
#include "hash.h"
#include "il.h"
#include "nodeop.h"
#include "allocate.h"
#include "types.h"
#include "stab.h"
#include "ada_name.h"
#include "anonymous.h"
#include "config.h"
#include "type_util.h"
extern int auto_package;
extern file_pos_t yypos;
#undef TYPE_HASH_MAX
#define TYPE_HASH_MAX 256 /* Anonymous type hash table size */
#undef NULL
#define NULL 0
static typeinfo_t *anonymous_types[TYPE_HASH_MAX];
static int anonymous_ord[MAX_UNIQ_FNAMES];
symbol_t *anonymous_function_pointer;
/*
* Use ordinal for anonymous type names
*/
int
next_anonymous_ord()
{
int file_ord;
if (auto_package) {
file_ord = FILE_ORD(yypos);
assert(file_ord < num_files());
return anonymous_ord[file_ord]++;
}
return anonymous_ord[0]++;
}
/*
* don't generate names ending in _t_t
*/
static int
ends_in(str,postfix)
char *str, *postfix;
{
for (; *str; str++) {
if (*str == *postfix && strcmp(str+1,postfix+1) == 0) {
return 1;
}
}
return 0;
}
/*
* look for type to Anonymous type hash table
*/
static typeinfo_t*
find_anonymous_type(typ)
typeinfo_t *typ;
{
typeinfo_t *t;
assert(typ != NULL);
assert(typ->type_hash != 0);
t = anonymous_types[typ->type_hash & (TYPE_HASH_MAX-1)];
for (; t; t = t->type_anonymous_list) {
if (equal_types(t, typ)) {
return t;
}
}
return NULL;
}
/*
* add type to Anonymous type hash table
*/
static void
store_anonymous_type(typ)
typeinfo_t *typ;
{
int index;
index = typ->type_hash & (TYPE_HASH_MAX-1);
assert(typ->type_anonymous_list == NULL);
typ->type_anonymous_list = anonymous_types[index];
anonymous_types[index] = typ;
}
static symbol_t*
add_anonymous_builtin(typ, c_name, ada_name)
typeinfo_t *typ;
char *c_name, *ada_name;
{
symbol_t *basetype;
typ->_anonymous = 1;
basetype = new_sym();
basetype->intrinsic = 1;
typ->type_base = basetype;
store_anonymous_type(typ);
basetype->sym_kind = type_symbol;
basetype->sym_type = typ;
basetype->sym_ident = new_node(_Ident, c_name);
basetype->sym_ada_name = ada_name;
basetype->gened = 1;
return basetype;
}
static typeinfo_t*
create_type(typ, n, mod1, mod2, mod3)
typeinfo_t *typ;
int n;
int mod1, mod2, mod3;
{
switch (n) {
case 3: typ = concat_types(typ, typeof_typemod(mod3));
case 2: typ = concat_types(typ, typeof_typemod(mod2));
case 1: typ = concat_types(typ, typeof_typemod(mod1));
}
return typeof_typespec(typ);
}
static typeinfo_t*
typeof_long_long(want_unsigned)
int want_unsigned;
{
typeinfo_t *typ;
typ = (want_unsigned) ? typeof_typemod(TYPEMOD_UNSIGNED) : NULL;
return create_type(typ, 2, TYPEMOD_LONG, TYPEMOD_LONG, 0);
}
static typeinfo_t*
typeof_long(want_unsigned)
int want_unsigned;
{
typeinfo_t *typ;
typ = (want_unsigned) ? typeof_typemod(TYPEMOD_UNSIGNED) : NULL;
return create_type(typ, 1, TYPEMOD_LONG, 0, 0);
}
static typeinfo_t*
typeof_short(want_unsigned)
int want_unsigned;
{
typeinfo_t *typ;
typ = (want_unsigned) ? typeof_typemod(TYPEMOD_UNSIGNED) : NULL;
return create_type(typ, 1, TYPEMOD_SHORT, 0, 0);
}
/*
* Define some builtin/intrinsic anonymous types
*/
void
init_anonymous_types()
{
static int initialized = 0;
if (initialized) return;
initialized = 1;
/* Builin: signed char* */
add_anonymous_builtin(add_pointer_type(set_signed_type(typeof_char())),
"%% builin *signed char %%",
TYPE_NAMEOF_CHAR_POINTER);
/* Builin: unsigned char* */
add_anonymous_builtin(add_pointer_type(set_unsigned_type(typeof_char())),
"%% builin *unsigned char %%",
TYPE_NAMEOF_UCHAR_POINTER);
/* Builin: void* */
add_anonymous_builtin(add_pointer_type(typeof_void()),
"%% builin *void %%",
TYPE_NAMEOF_VOID_POINTER);
/* Builin: int (*)() */
anonymous_function_pointer =
add_anonymous_builtin(add_function_type(typeof_int(0)),
"%% int (*)() %%",
TYPE_NAMEOF_FUNCTION_POINTER);
#ifdef SIZEOF_LONG_LONG
add_anonymous_builtin(add_pointer_type(typeof_long_long(0)),
"%% long long int * %%",
TYPE_NAMEOF_SIGNED_LONG_LONG_POINTER);
add_anonymous_builtin(add_pointer_type(typeof_long_long(1)),
"%% unsigned long long int * %%",
TYPE_NAMEOF_UNSIGNED_LONG_LONG_POINTER);
#endif
/* builtin: long int* */
add_anonymous_builtin(add_pointer_type(typeof_long(0)),
"%% long int * %%",
TYPE_NAMEOF_SIGNED_LONG_POINTER);
/* builtin: unsigned long int* */
add_anonymous_builtin(add_pointer_type(typeof_long(1)),
"%% long unsigned int * %%",
TYPE_NAMEOF_UNSIGNED_LONG_POINTER);
/* builtin: int* */
add_anonymous_builtin(add_pointer_type(typeof_int(0)),
"%% int * %%",
TYPE_NAMEOF_SIGNED_INT_POINTER);
/* builtin: int* */
add_anonymous_builtin(add_pointer_type(typeof_int(1)),
"%% unsigned int * %%",
TYPE_NAMEOF_UNSIGNED_INT_POINTER);
/* builtin: short* */
add_anonymous_builtin(add_pointer_type(typeof_short(0)),
"%% short int * %%",
TYPE_NAMEOF_SIGNED_SHORT_POINTER);
/* builtin: unsigned short* */
add_anonymous_builtin(add_pointer_type(typeof_short(1)),
"%% short unsigned int * %%",
TYPE_NAMEOF_UNSIGNED_SHORT_POINTER);
/* builtin: float* */
add_anonymous_builtin(add_pointer_type(typeof_float()),
"%% int * %%",
TYPE_NAMEOF_FLOAT_POINTER);
/* builtin: double* */
add_anonymous_builtin(add_pointer_type(typeof_double()),
"%% int * %%",
TYPE_NAMEOF_DOUBLE_POINTER);
/* builtin: string */
add_anonymous_builtin(add_array_type(set_signed_type(typeof_char()), 1),
"%% builin char[] %%",
TYPE_NAMEOF_STRING);
/* builtin: ustring */
add_anonymous_builtin(add_array_type(set_unsigned_type(typeof_char()), 1),
"%% builin char[] %%",
TYPE_NAMEOF_USTRING);
}
/*
* Given "vector_of_c.signed_int" produce "vector_of_c_signed_int"
*/
rm_selectors(s)
char *s;
{
for (; *s; s++) {
if (*s == '.') *s = '_';
}
}
static int
is_matrix(typ)
typeinfo_t *typ;
{
int count;
if (! is_array(typ)) return 0;
count = 1;
for (typ = typ->type_next; is_array(typ); typ = typ->type_next) {
count++;
}
/* if even number of indices then assume matrix */
return (count & 1) == 0;
}
static void
force_ada_name(sym)
symbol_t *sym;
{
if (sym->sym_ada_name == NULL) {
assert(sym->sym_ident != NULL);
assert(sym->sym_ident->node_kind == _Ident);
assert(sym->sym_ident->node.id.name != NULL);
sym->sym_ada_name =
ada_name(sym->sym_ident->node.id.name,
FILE_ORD(sym->sym_def));
}
}
/*
* Here we go. We may need to generate an anonymous type
* for the input type. An example is when "struct foo *a;" is
* encountered we'll need to gen "type a_sruct_foo_t is ...".
*/
symbol_t*
get_anonymous_type(typ)
typeinfo_t *typ;
{
typeinfo_t *anonymous_type;
symbol_t *basetype;
ident_case_t icase;
char buf[1024];
assert(typ != NULL);
if (typ->type_next != NULL && typ->type_next->type_base == NULL) {
if (is_function_pointer(typ)) {
typ->type_base = anonymous_function_pointer;
return typ->type_base;
}
}
assert(typ->type_next == NULL || typ->type_next->type_base != NULL);
assert(typ->type_hash != 0);
assert(typ->type_anonymous_list == NULL);
anonymous_type = find_anonymous_type(typ);
if (anonymous_type != NULL) {
basetype = anonymous_type->type_base;
assert(basetype != NULL);
typ->type_base = basetype;
return basetype;
}
if (is_access(typ)) {
typeinfo_t *ptype;
ptype = typ->type_next;
assert(ptype != NULL);
basetype = ptype->type_base;
assert(basetype != NULL);
assert(basetype->gened);
force_ada_name(basetype);
strcpy(buf, ACCESS_TYPE_PREFIX);
if (ptype->_unsigned != basetype->sym_type->_unsigned) {
if (ptype->_unsigned) {
strcat(buf, "unsigned_");
} else {
strcat(buf, "signed_");
}
}
strcat(buf, basetype->sym_ada_name);
icase = id_case(basetype->sym_ada_name);
} else if (is_array(typ)) {
typeinfo_t *elem_typ;
char *prefix = VECTOR_TYPE_PREFIX;
elem_typ = typ->type_next;
assert(elem_typ != NULL);
if (is_array(elem_typ) && !is_matrix(elem_typ)) { /* matrix */
prefix = MATRIX_TYPE_PREFIX;
elem_typ = elem_typ->type_next;
assert(elem_typ != NULL);
}
basetype = elem_typ->type_base;
assert(basetype != NULL);
assert(basetype->gened);
force_ada_name(basetype);
sprintf(buf, "%s%s", prefix, basetype->sym_ada_name);
icase = id_case(basetype->sym_ada_name);
} else {
sprintf(buf, "%s%d", OTHER_TYPE_PREFIX,
next_anonymous_ord());
icase = Lower;
}
rm_selectors(buf);
if (! ends_in(basetype->sym_ada_name, TYPE_POSTFIX)) {
strcat(buf, TYPE_POSTFIX);
}
id_format(buf, icase);
basetype = new_sym();
typ->type_base = basetype;
typ = copy_type(typ);
typ->_anonymous = 1;
store_anonymous_type(typ);
basetype->sym_kind = type_symbol;
basetype->sym_type = typ;
basetype->sym_def = yypos;
basetype->sym_ident = new_node(_Ident, new_string(buf));
basetype->sym_ada_name =
ada_name(basetype->sym_ident->node.id.name, FILE_ORD(yypos));
return basetype;
}
syntax highlighted by Code2HTML, v. 0.9.1