#include <nidl.h>
#include <nametbl.h>
#include <errors.h>
#include <astp.h>
#include <nidlmsg.h>
static void ASTP_add_tag_binding (
parser_location_p location,
NAMETABLE_id_t name,
AST_type_n_t *type_node
);
static void ASTP_process_sp_type (
parser_location_p location,
AST_interface_n_t *interface_node_ptr,
AST_type_n_t *type_node_ptr
);
static AST_field_n_t *AST_field_node (
parser_location_p location,
NAMETABLE_id_t field_name
);
static void AST_find_self_reference (
parser_location_p location,
AST_interface_n_t *interface_node_ptr,
AST_type_p_n_t *active_type_chain,
AST_type_n_t *current_type_node_ptr
);
extern int error_count;
static void ASTP_add_tag_binding
(
parser_location_p location,
NAMETABLE_id_t name,
AST_type_n_t *type_node
)
{
if (!NAMETABLE_add_tag_binding (name, (char *)type_node))
{
char const *identifier;
char const *filename;
ASTP_node_t *binding;
NAMETABLE_id_to_string (name, &identifier);
binding = (ASTP_node_t *)NAMETABLE_lookup_binding(name);
if ((binding->fe_info != (fe_info_t *)NULL) &&
(binding->fe_info->source_line != 0) &&
(binding->fe_info->file != STRTAB_NULL_STR))
{
STRTAB_str_to_string(binding->fe_info->file, &filename);
log_error (location->lineno, NIDL_NAMEPREVDECLAT, identifier,
filename, binding->fe_info->source_line, NULL);
}
else
log_error (location->lineno, NIDL_NAMEALRDEC, identifier, NULL);
}
return;
}
ASTP_array_index_n_t *ASTP_array_index_node
(
parser_location_p location,
AST_constant_n_t *lower_bound,
ASTP_bound_t lower_bound_type,
AST_constant_n_t *upper_bound,
ASTP_bound_t upper_bound_type
)
{
ASTP_array_index_n_t *index_node_ptr;
index_node_ptr = NEW (ASTP_array_index_n_t);
index_node_ptr->lower_bound_type = lower_bound_type;
index_node_ptr->upper_bound_type = upper_bound_type;
if (lower_bound_type == ASTP_constant_bound)
{
index_node_ptr->lower_bound = lower_bound;
};
if (lower_bound_type == ASTP_default_bound)
{
index_node_ptr->lower_bound = zero_constant_p;
};
if (upper_bound_type == ASTP_constant_bound)
{
if (lower_bound_type == ASTP_default_bound)
{
index_node_ptr->upper_bound =
AST_clone_constant(location, upper_bound);
index_node_ptr->upper_bound->value.int_val--;
}
else
{
index_node_ptr->upper_bound = upper_bound;
}
};
return index_node_ptr;
}
AST_array_index_n_t *AST_array_index_node
(
parser_location_p location,
unsigned short array_size
)
{
unsigned short i;
AST_array_index_n_t *index_vector,
*index_node;
index_vector = NEW_VEC (AST_array_index_n_t, array_size);
for (i = 0, index_node = index_vector;
i<array_size;
i++, index_node++)
{
ASTP_set_fe_info (location, &index_node->fe_info, fe_array_index_n_k);
}
return index_vector;
}
AST_array_n_t *AST_array_node
(
parser_location_p location,
AST_type_n_t *element_type_ptr
)
{
AST_array_n_t *array_node_ptr;
array_node_ptr = NEW (AST_array_n_t);
array_node_ptr->element_type = element_type_ptr;
ASTP_set_fe_info(location, &array_node_ptr->fe_info, fe_array_n_k);
return array_node_ptr;
}
AST_field_attr_n_t *AST_field_attr_node
(
parser_location_p location
)
{
AST_field_attr_n_t *field_attr_node_ptr;
field_attr_node_ptr = NEW (AST_field_attr_n_t);
ASTP_set_fe_info(location, &field_attr_node_ptr->fe_info, fe_field_attr_n_k);
return field_attr_node_ptr;
}
AST_field_ref_n_t *AST_field_ref_node
(
parser_location_p location,
unsigned short dimension
)
{
unsigned short i;
AST_field_ref_n_t *field_ref_vector,
*field_ref_node;
field_ref_vector = NEW_VEC (AST_field_ref_n_t, dimension);
for (i = 0, field_ref_node = field_ref_vector;
i<dimension;
i++, field_ref_node++)
{
field_ref_node->valid = FALSE;
ASTP_set_fe_info(location, &field_ref_node->fe_info, fe_field_ref_n_k);
}
return field_ref_vector;
}
AST_type_n_t *AST_structure_node
(
parser_location_p location,
AST_field_n_t *field_list,
NAMETABLE_id_t identifier
)
{
AST_structure_n_t *structure_node_ptr;
AST_type_n_t *type_node_ptr;
AST_type_n_t *tag_type_node_ptr;
structure_node_ptr = NEW (AST_structure_n_t);
structure_node_ptr->fields = field_list;
structure_node_ptr->tag_name = identifier;
ASTP_set_fe_info(location, &structure_node_ptr->fe_info, fe_structure_n_k);
tag_type_node_ptr = NULL;
if (identifier != NAMETABLE_NIL_ID)
{
tag_type_node_ptr = (AST_type_n_t *) NAMETABLE_lookup_tag_binding(identifier);
if (tag_type_node_ptr == NULL)
{
tag_type_node_ptr = AST_type_node(location, AST_structure_k);
AST_SET_DEF_AS_TAG(tag_type_node_ptr);
ASTP_add_tag_binding(location, identifier, tag_type_node_ptr);
ASTP_save_tag_ref(identifier, AST_structure_k, tag_type_node_ptr);
tag_type_node_ptr->type_structure.structure = structure_node_ptr;
}
else
{
if (tag_type_node_ptr->kind != AST_structure_k)
{
char const *identifier_text;
NAMETABLE_id_to_string (identifier, &identifier_text);
log_error (location->lineno, NIDL_BADTAGREF, identifier_text,
NULL);
if ((tag_type_node_ptr->fe_info->source_line != 0) &&
(tag_type_node_ptr->fe_info->file != STRTAB_NULL_STR))
{
char const *filename;
STRTAB_str_to_string(tag_type_node_ptr->fe_info->file, &filename);
log_error (location->lineno, NIDL_NAMEPREVDECLAT,
identifier_text, filename,
tag_type_node_ptr->fe_info->source_line, NULL);
}
tag_type_node_ptr = AST_type_node(location, AST_structure_k);
AST_SET_DEF_AS_TAG(tag_type_node_ptr);
}
else if (tag_type_node_ptr->type_structure.structure != NULL)
{
char const *identifier_text;
NAMETABLE_id_to_string (identifier, &identifier_text);
if ((tag_type_node_ptr->fe_info->source_line != 0) &&
(tag_type_node_ptr->fe_info->file != STRTAB_NULL_STR))
{
char const *filename;
STRTAB_str_to_string(tag_type_node_ptr->fe_info->file, &filename);
log_error (location->lineno, NIDL_NAMEPREVDECLAT,
identifier_text, filename,
tag_type_node_ptr->fe_info->source_line, NULL);
}
else
log_error (location->lineno, NIDL_NAMEALRDEC,
identifier_text, NULL);
tag_type_node_ptr = AST_type_node(location, AST_structure_k);
AST_SET_DEF_AS_TAG(tag_type_node_ptr);
}
}
}
type_node_ptr = AST_type_node(location, AST_structure_k);
type_node_ptr->type_structure.structure = structure_node_ptr;
type_node_ptr->fe_info->tag_ptr = tag_type_node_ptr;
type_node_ptr->fe_info->tag_name = identifier;
if (tag_type_node_ptr != NULL)
{
ASTP_save_tag_ref(identifier, AST_structure_k, type_node_ptr);
tag_type_node_ptr->fe_info->original = type_node_ptr;
tag_type_node_ptr->fe_info->tag_ptr = tag_type_node_ptr;
tag_type_node_ptr->fe_info->tag_name = identifier;
tag_type_node_ptr->type_structure.structure = structure_node_ptr;
if (tag_type_node_ptr->array_rep_type != NULL)
tag_type_node_ptr->array_rep_type->type_structure.array->element_type = type_node_ptr;
}
return type_node_ptr;
}
AST_arm_n_t *AST_label_arm
(
AST_arm_n_t *member,
AST_case_label_n_t *case_labels
)
{
member->labels = case_labels;
return member;
}
AST_case_label_n_t *AST_case_label_node
(
parser_location_p location,
AST_constant_n_t *case_label
)
{
AST_case_label_n_t *case_label_node;
case_label_node = NEW (AST_case_label_n_t);
case_label_node->default_label = FALSE;
case_label_node->value = case_label;
ASTP_set_fe_info (location, &case_label_node->fe_info, fe_case_label_n_k);
return case_label_node;
}
AST_case_label_n_t *AST_default_case_label_node
(
parser_location_p location
)
{
AST_case_label_n_t *case_label_node;
case_label_node = AST_case_label_node(location, NULL);
case_label_node->default_label = TRUE;
return case_label_node;
}
AST_type_n_t *AST_disc_union_node
(
parser_location_p location,
NAMETABLE_id_t identifier,
NAMETABLE_id_t union_name,
NAMETABLE_id_t disc_name,
AST_type_n_t *disc_type,
AST_arm_n_t *arm_list
)
{
AST_disc_union_n_t *disc_union_node_ptr;
AST_type_n_t *type_node_ptr;
AST_type_n_t *tag_type_node_ptr;
disc_union_node_ptr = NEW (AST_disc_union_n_t);
disc_union_node_ptr->tag_name = identifier;
disc_union_node_ptr->union_name = union_name;
disc_union_node_ptr->discrim_name = disc_name;
disc_union_node_ptr->discrim_type = disc_type;
disc_union_node_ptr->arms = arm_list;
ASTP_set_fe_info (location, &disc_union_node_ptr->fe_info, fe_disc_union_n_k);
tag_type_node_ptr = NULL;
if (identifier != NAMETABLE_NIL_ID)
{
tag_type_node_ptr = (AST_type_n_t *) NAMETABLE_lookup_tag_binding(identifier);
if (tag_type_node_ptr == NULL)
{
tag_type_node_ptr = AST_type_node(location, AST_disc_union_k);
AST_SET_DEF_AS_TAG(tag_type_node_ptr);
ASTP_add_tag_binding(location, identifier, tag_type_node_ptr);
ASTP_save_tag_ref(identifier, AST_disc_union_k, tag_type_node_ptr);
tag_type_node_ptr->type_structure.disc_union = disc_union_node_ptr;
}
else
{
if (tag_type_node_ptr->kind != AST_disc_union_k)
{
char const *identifier_text;
NAMETABLE_id_to_string (identifier, &identifier_text);
log_error (location->lineno, NIDL_BADTAGREF, identifier_text,
NULL);
if ((tag_type_node_ptr->fe_info->source_line != 0) &&
(tag_type_node_ptr->fe_info->file != STRTAB_NULL_STR))
{
char const *filename;
STRTAB_str_to_string(tag_type_node_ptr->fe_info->file, &filename);
log_error (location->lineno, NIDL_NAMEPREVDECLAT,
identifier_text, filename,
tag_type_node_ptr->fe_info->source_line, NULL);
}
tag_type_node_ptr = AST_type_node(location, AST_disc_union_k);
AST_SET_DEF_AS_TAG(tag_type_node_ptr);
}
else if (tag_type_node_ptr->type_structure.disc_union != NULL)
{
char const *identifier_text;
NAMETABLE_id_to_string (identifier, &identifier_text);
if ((tag_type_node_ptr->fe_info->source_line != 0) &&
(tag_type_node_ptr->fe_info->file != STRTAB_NULL_STR))
{
char const *filename;
STRTAB_str_to_string(tag_type_node_ptr->fe_info->file, &filename);
log_error (location->lineno, NIDL_NAMEPREVDECLAT,
identifier_text, filename,
tag_type_node_ptr->fe_info->source_line, NULL);
}
else
log_error (location->lineno, NIDL_NAMEALRDEC,
identifier_text, NULL);
tag_type_node_ptr = AST_type_node(location, AST_disc_union_k);
AST_SET_DEF_AS_TAG(tag_type_node_ptr);
}
}
}
type_node_ptr = AST_type_node(location, AST_disc_union_k);
type_node_ptr->type_structure.disc_union = disc_union_node_ptr;
type_node_ptr->fe_info->tag_ptr = tag_type_node_ptr;
type_node_ptr->fe_info->tag_name = identifier;
if (tag_type_node_ptr != NULL)
{
ASTP_save_tag_ref(identifier, AST_disc_union_k, type_node_ptr);
tag_type_node_ptr->fe_info->original = type_node_ptr;
tag_type_node_ptr->fe_info->tag_ptr = tag_type_node_ptr;
tag_type_node_ptr->fe_info->tag_name = identifier;
tag_type_node_ptr->type_structure.disc_union = disc_union_node_ptr;
if (tag_type_node_ptr->array_rep_type != NULL)
tag_type_node_ptr->array_rep_type->type_structure.array->element_type = type_node_ptr;
}
return type_node_ptr;
}
AST_arm_n_t *AST_arm_node
(
parser_location_p location,
NAMETABLE_id_t name,
AST_case_label_n_t *label,
AST_type_n_t *type
)
{
AST_arm_n_t * arm_node_ptr;
arm_node_ptr = NEW (AST_arm_n_t);
arm_node_ptr->labels = label;
arm_node_ptr->name = name;
arm_node_ptr->type = type;
ASTP_set_fe_info (location, &arm_node_ptr->fe_info, fe_arm_n_k);
if (name != NAMETABLE_NIL_ID)
ASTP_add_name_binding (location, name, arm_node_ptr);
return arm_node_ptr;
}
AST_field_n_t * AST_field_node
(
parser_location_p location,
NAMETABLE_id_t field_name
)
{
AST_field_n_t * field_node_ptr;
field_node_ptr = NEW (AST_field_n_t);
field_node_ptr->name = field_name;
ASTP_set_fe_info (location, &field_node_ptr->fe_info, fe_field_n_k);
ASTP_add_name_binding (location, field_name, field_node_ptr);
return field_node_ptr;
}
AST_field_n_t *AST_declarators_to_fields
(
parser_location_p location,
ASTP_declarator_n_t *declarators_ptr,
AST_type_n_t *type_ptr,
ASTP_attributes_t *attributes
)
{
AST_field_n_t * field_list = NULL;
AST_field_n_t * new_field;
ASTP_declarator_n_t *dp;
ASTP_type_attr_n_t *attr_ptr;
for (dp = declarators_ptr; dp; dp = dp->next)
{
new_field = AST_field_node (location, dp->name);
new_field->type = AST_propagate_type(location,
type_ptr, declarators_ptr, attributes,
(ASTP_node_t *)new_field);
if (attributes != NULL)
{
for (attr_ptr = attributes->bounds;
attr_ptr != NULL;
attr_ptr = attr_ptr->next)
{
if (attr_ptr->is_expr && attr_ptr->b.simple.pointer)
log_error(attr_ptr->source_line, NIDL_ATTRVALIND, NULL);
}
}
new_field->field_attrs = AST_set_field_attrs(location, attributes,
(ASTP_node_t *)new_field, new_field->type);
AST_set_flags(location, &new_field->flags, (ASTP_node_t *)new_field, attributes);
field_list = (AST_field_n_t *)AST_concat_element(
(ASTP_node_t *)field_list, (ASTP_node_t *)new_field);
ASTP_validate_forward_ref(location, new_field->type);
}
ASTP_free_declarators(declarators_ptr);
return field_list;
}
AST_arm_n_t *AST_declarator_to_arm
(
parser_location_p location,
AST_type_n_t *type_ptr,
ASTP_declarator_n_t *declarator,
ASTP_attributes_t *attributes
)
{
AST_arm_n_t * arm_list = NULL;
AST_arm_n_t * new_arm;
ASTP_declarator_n_t * dp;
if (declarator == NULL)
{
arm_list = AST_arm_node(location, NAMETABLE_NIL_ID, NULL, NULL);
if (ASTP_TEST_ATTR(attributes, ASTP_DEFAULT))
{
if (ASTP_TEST_ATTR(attributes, ASTP_CASE))
{
ASTP_attr_flag_t attr1 = ASTP_CASE;
ASTP_attr_flag_t attr2 = ASTP_DEFAULT;
log_error(location->lineno, NIDL_CONFLICTATTR,
KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)),
NULL);
}
else
{
arm_list->labels = AST_default_case_label_node(location);
}
}
if (ASTP_TEST_ATTR(attributes, ASTP_CASE))
{
arm_list->labels = ASTP_case;
ASTP_case = NULL;
}
ASTP_CLR_ATTR(attributes, ASTP_CASE | ASTP_DEFAULT);
}
for (dp = declarator; dp; dp = dp->next) {
new_arm = AST_arm_node (location, dp->name,NULL,NULL);
if (ASTP_TEST_ATTR(attributes, ASTP_DEFAULT))
{
if (ASTP_TEST_ATTR(attributes, ASTP_CASE))
{
ASTP_attr_flag_t attr1 = ASTP_CASE;
ASTP_attr_flag_t attr2 = ASTP_DEFAULT;
log_error(location->lineno, NIDL_CONFLICTATTR,
KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)),
KEYWORDS_lookup_text(AST_attribute_to_token(&attr2)),
NULL);
}
else
{
new_arm->labels = AST_default_case_label_node(location);
}
}
if (ASTP_TEST_ATTR(attributes, ASTP_CASE))
{
new_arm->labels = ASTP_case;
ASTP_case = NULL;
}
ASTP_CLR_ATTR(attributes, ASTP_CASE | ASTP_DEFAULT);
new_arm->type = AST_propagate_type(location,
type_ptr, declarator, attributes,
(ASTP_node_t *)new_arm);
AST_set_flags(location, &new_arm->flags, (ASTP_node_t *)new_arm, attributes);
if (AST_STRING_SET(new_arm) && new_arm->type &&
new_arm->type->kind == AST_pointer_k)
{
ASTP_set_array_rep_type(location, new_arm->type,
new_arm->type->type_structure.pointer->pointee_type,
TRUE);
}
arm_list = (AST_arm_n_t *)AST_concat_element(
(ASTP_node_t *)arm_list, (ASTP_node_t *)new_arm);
ASTP_validate_forward_ref(location, new_arm->type);
}
ASTP_free_declarators(declarator);
return arm_list;
}
AST_type_n_t *AST_type_from_tag
(
parser_location_p location,
AST_type_k_t kind,
NAMETABLE_id_t identifier
)
{
AST_type_n_t *tag_type_node_ptr;
tag_type_node_ptr = (AST_type_n_t *) NAMETABLE_lookup_tag_binding(identifier);
if (tag_type_node_ptr != NULL)
{
if (tag_type_node_ptr->kind != kind)
{
char const *identifier_text;
NAMETABLE_id_to_string (identifier, &identifier_text);
log_error (location->lineno, NIDL_BADTAGREF, identifier_text, NULL);
if ((tag_type_node_ptr->fe_info->source_line != 0) &&
(tag_type_node_ptr->fe_info->file != STRTAB_NULL_STR))
{
char const *filename;
STRTAB_str_to_string(tag_type_node_ptr->fe_info->file, &filename);
log_error (location->lineno, NIDL_NAMEPREVDECLAT, identifier_text,
filename, tag_type_node_ptr->fe_info->source_line,
NULL);
}
tag_type_node_ptr = AST_type_node(location, kind);
AST_SET_DEF_AS_TAG(tag_type_node_ptr);
}
}
else {
tag_type_node_ptr = AST_type_node (location, kind);
AST_SET_DEF_AS_TAG(tag_type_node_ptr);
tag_type_node_ptr->type_structure.structure = NULL;
tag_type_node_ptr->fe_info->tag_ptr = tag_type_node_ptr;
tag_type_node_ptr->fe_info->tag_name = identifier;
ASTP_save_tag_ref(identifier, kind, tag_type_node_ptr);
ASTP_add_tag_binding(location, identifier,tag_type_node_ptr);
}
return tag_type_node_ptr;
}
void ASTP_patch_tag_references
(
parser_location_p location,
AST_interface_n_t *interface_node_ptr
)
{
AST_type_n_t *type_node_ptr;
ASTP_tag_ref_n_t *tag_ref_node_ptr;
for (tag_ref_node_ptr = ASTP_tag_ref_list; tag_ref_node_ptr;
tag_ref_node_ptr= tag_ref_node_ptr->next)
{
type_node_ptr = (AST_type_n_t *)
NAMETABLE_lookup_tag_binding(tag_ref_node_ptr->name);
if ((type_node_ptr != NULL) && (type_node_ptr->type_structure.structure != NULL))
{
if (tag_ref_node_ptr->ref_kind != type_node_ptr->kind)
{
char const *identifier;
NAMETABLE_id_to_string (tag_ref_node_ptr->name, &identifier);
log_source_error
(tag_ref_node_ptr->type_node_ptr->fe_info->file,
tag_ref_node_ptr->type_node_ptr->fe_info->source_line,
NIDL_BADTAGREF, identifier, NULL);
if ((type_node_ptr->fe_info->source_line != 0) &&
(type_node_ptr->fe_info->file != STRTAB_NULL_STR))
{
char const *filename;
STRTAB_str_to_string(type_node_ptr->fe_info->file, &filename);
log_source_error
(tag_ref_node_ptr->type_node_ptr->fe_info->file,
tag_ref_node_ptr->type_node_ptr->fe_info->source_line,
NIDL_NAMEPREVDECLAT, identifier, filename,
type_node_ptr->fe_info->source_line, NULL);
}
}
tag_ref_node_ptr->type_node_ptr->type_structure = type_node_ptr->type_structure;
FE_CLEAR(tag_ref_node_ptr->type_node_ptr->fe_info->flags,FE_INCOMPLETE);
}
else
{
char const *identifier;
if (type_node_ptr != NULL
&& tag_ref_node_ptr->ref_kind == AST_structure_k
&& AST_CONTEXT_RD_SET(type_node_ptr))
{
AST_structure_n_t *struct_p;
struct_p = type_node_ptr->type_structure.structure =
NEW (AST_structure_n_t);
ASTP_set_fe_info (location, &struct_p->fe_info, fe_structure_n_k);
struct_p->tag_name = tag_ref_node_ptr->name;
continue;
}
NAMETABLE_id_to_string (tag_ref_node_ptr->name, &identifier);
log_source_error
(tag_ref_node_ptr->type_node_ptr->fe_info->file,
tag_ref_node_ptr->type_node_ptr->fe_info->source_line,
NIDL_NAMENOTFND, identifier, NULL);
}
}
if (error_count == 0)
{
for (tag_ref_node_ptr = ASTP_tag_ref_list; tag_ref_node_ptr;
tag_ref_node_ptr = tag_ref_node_ptr->next)
{
if (AST_DEF_AS_TAG_SET(tag_ref_node_ptr->type_node_ptr)
&& tag_ref_node_ptr->type_node_ptr->type_structure.structure)
{
AST_find_self_reference(location, interface_node_ptr,
NULL, tag_ref_node_ptr->type_node_ptr);
}
}
while (ASTP_tag_ref_list != NULL)
{
AST_type_n_t *tp;
if (!AST_DEF_AS_TAG_SET(ASTP_tag_ref_list->type_node_ptr) &&
!AST_SELF_POINTER_SET(ASTP_tag_ref_list->type_node_ptr))
{
AST_find_self_reference(location, interface_node_ptr,
NULL, ASTP_tag_ref_list->type_node_ptr);
tp = ASTP_tag_ref_list->type_node_ptr->fe_info->tag_ptr;
if ((tp != NULL) && AST_SELF_POINTER_SET(tp))
{
ASTP_process_sp_type(location, interface_node_ptr, ASTP_tag_ref_list->type_node_ptr);
}
}
tag_ref_node_ptr = ASTP_tag_ref_list;
ASTP_tag_ref_list = ASTP_tag_ref_list->next;
FREE(tag_ref_node_ptr);
}
}
return;
}
static int ASTP_check_chain
(
parser_location_p location,
AST_interface_n_t *interface_node_ptr,
AST_type_p_n_t *active_type_chain,
AST_type_n_t *current_type_node_ptr
)
{
AST_type_p_n_t *tp;
int found;
if (AST_SELF_POINTER_SET(current_type_node_ptr))
found = TRUE;
else
found = FALSE;
for (tp = active_type_chain; tp; tp = tp->next)
{
if (tp->type == current_type_node_ptr) found = TRUE;
}
if (found)
{
for (tp = active_type_chain; tp; tp = tp->next)
ASTP_process_sp_type(location, interface_node_ptr, tp->type);
}
return found;
}
static void AST_find_self_reference
(
parser_location_p location,
AST_interface_n_t *interface_node_ptr,
AST_type_p_n_t *active_type_chain,
AST_type_n_t *current_type_node_ptr
)
{
AST_type_p_n_t link_node;
AST_field_n_t *fp;
AST_arm_n_t *ap;
if (ASTP_check_chain(location, interface_node_ptr, active_type_chain,
current_type_node_ptr)) return;
link_node.next = active_type_chain;
link_node.type = current_type_node_ptr;
switch (current_type_node_ptr->kind)
{
case AST_pointer_k:
AST_find_self_reference(location, interface_node_ptr, &link_node,
current_type_node_ptr->type_structure.pointer->pointee_type);
break;
case AST_structure_k:
{
AST_type_p_n_t tag_link_node;
AST_type_p_n_t *tag_link_node_ptr = &tag_link_node;
tag_link_node.next = &link_node;
tag_link_node.type = current_type_node_ptr->fe_info->tag_ptr;
if (tag_link_node.type == NULL)
tag_link_node_ptr = &link_node;
for (fp = current_type_node_ptr->type_structure.structure->fields;
fp; fp = fp->next)
AST_find_self_reference(location, interface_node_ptr,
tag_link_node_ptr, fp->type);
break;
}
case AST_disc_union_k:
{
AST_type_p_n_t tag_link_node;
AST_type_p_n_t *tag_link_node_ptr = &tag_link_node;
tag_link_node.next = &link_node;
tag_link_node.type = current_type_node_ptr->fe_info->tag_ptr;
if (tag_link_node.type == NULL)
tag_link_node_ptr = &link_node;
for (ap = current_type_node_ptr->type_structure.disc_union->arms;
ap; ap = ap->next)
{
if (ap->type != NULL)
{
AST_find_self_reference(location, interface_node_ptr,
tag_link_node_ptr, ap->type);
}
}
break;
}
case AST_array_k:
AST_find_self_reference(location, interface_node_ptr, &link_node,
current_type_node_ptr->type_structure.array->element_type);
break;
default:
break;
}
}
static void ASTP_process_sp_type
(
parser_location_p location,
AST_interface_n_t *interface_node_ptr,
AST_type_n_t *type_node_ptr
)
{
AST_type_p_n_t *tp_node;
if (FE_TEST(type_node_ptr->fe_info->flags,FE_SELF_POINTING)) return;
AST_SET_SELF_POINTER(type_node_ptr);
if ((type_node_ptr->kind == AST_pointer_k) &&
(type_node_ptr->type_structure.pointer->pointee_type->array_rep_type != NULL))
ASTP_process_sp_type(location, interface_node_ptr,
type_node_ptr->type_structure.pointer->pointee_type->array_rep_type);
if (AST_DEF_AS_TAG_SET(type_node_ptr) &&
(type_node_ptr->fe_info->original != NULL))
{
FE_SET(type_node_ptr->fe_info->flags,FE_SELF_POINTING);
type_node_ptr = type_node_ptr->fe_info->original;
AST_SET_SELF_POINTER(type_node_ptr);
FE_SET(type_node_ptr->fe_info->flags,FE_SELF_POINTING);
}
if ((type_node_ptr->kind == AST_pointer_k) &&
(type_node_ptr->name == NAMETABLE_NIL_ID)) return;
tp_node = AST_type_ptr_node(location);
tp_node->type = type_node_ptr;
FE_SET(type_node_ptr->fe_info->flags,FE_SELF_POINTING);
interface_node_ptr->sp_types = (AST_type_p_n_t *)AST_concat_element(
(ASTP_node_t *)interface_node_ptr->sp_types,
(ASTP_node_t *)tp_node);
}