/*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
*
* This file is part of Flick, the Flexible IDL Compiler Kit.
*
* Flick 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.
*
* Flick 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 Flick; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place #330, Boston, MA 02111, USA.
*/
#include <mom/compiler.h>
#include <mom/c/libpres_c.h>
#include <mom/c/libcast.h>
#include "private.hh"
/* presentation generation routine for AOI_UNION type */
pres_c_inline pg_state::p_inline_struct_union(aoi_union *au,
p_type_collection */*inl_ptc*/,
cast_type inl_ctype)
{
char *old_name;
pres_c_inline inl;
pres_c_inline_struct_union *suinl;
p_type_collection *ptc;
p_type_node *ptn;
cast_type discrim_ctype, union_ctype, variant_ctype;
pres_c_mapping discrim_map, union_map, variant_map;
int union_ctype_cases_len, union_ctype_cases_idx;
unsigned int i;
int cdef;
cast_scope *scope;
/* Save the original name context for when we return. */
old_name = name;
/* Count the number of non-void union variants in our AOI_UNION. */
union_ctype_cases_len = 0;
for (i = 0; i < au->cases.cases_len; ++i)
if (au->cases.cases_val[i].var.type->kind != AOI_VOID)
++union_ctype_cases_len;
if (au->dfault && (au->dfault->type->kind != AOI_VOID))
++union_ctype_cases_len;
/* Create the pres_c_inline_struct_union which will be the return
value of this function. This object will describe how the pieces of
our discriminated union (AOI_UNION) match up with the pieces within
the C structure definition we are creating (`inl_ctype'). */
inl = pres_c_new_inline_struct_union(union_ctype_cases_len);
suinl = &(inl->pres_c_inline_u_u.struct_union);
/* Fill out `suinl'. */
/* `discrim.index' is the index of the discriminator in the CAST
structure definition (`inl_ctype') that we are constructing to
represent the current AOI_UNION. The discriminator will be the
zeroth element of that structure (i.e., the first slot). */
suinl->discrim.index = 0;
/* `union_index' is the index of the CAST union within the CAST
structure defintion that we are constructing. The slots within this
union will correspond to the variants of the AOI_UNION we are
processing. */
suinl->union_index = 1;
/* `cases' is the array that describe how variants of our discriminated
union match up with the variants within the C presentation of that
union. These correspondences are established later in this function
(in the `for' loop below). */
suinl->cases.cases_len = au->cases.cases_len;
suinl->cases.cases_val =
(pres_c_inline_struct_union_case *)
mustmalloc(sizeof(pres_c_inline_struct_union_case) *
au->cases.cases_len);
/* Prepare the discriminator mapping, save it in `suinl', and add the
slot for the discriminator to our structure definition `inl_ctype'.
*/
name = calc_struct_slot_name(au->discriminator.name);
ptc = 0;
p_type(au->discriminator.type, &ptc);
ptn = ptc->find_type("definition");
discrim_ctype = ptn->get_type();
discrim_map = ptn->get_mapping();
suinl->discrim.mapping = discrim_map;
/* The following invocation of `p_inline_add_atom' has the side effect
of adding the discriminator slot to the structure definition. */
p_inline_add_atom(inl_ctype,
calc_struct_slot_name(au->discriminator.name),
discrim_ctype,
discrim_map);
/* Create a cast_union_type to contain the slots that correspond to the
variants of our discriminated union. */
union_ctype = cast_new_aggregate_type(union_aggregate_type, 0);
union_ctype->cast_type_u_u.agg_type.name =
cast_new_scoped_name(
calc_struct_union_tag_name(au->union_label), NULL);
push_ptr(scope_stack, &union_ctype->cast_type_u_u.agg_type.scope);
scope = (cast_scope *)top_ptr(scope_stack);
/* Compute the name of the union member; this will be used by
`p_inline_add_atom' below. */
name = calc_struct_slot_name(au->union_label);
/* Now process the variants of our discriminated union. */
for (i = 0, union_ctype_cases_idx = 0; i < au->cases.cases_len; i++) {
/*
* XXX --- We must set `name' here for the benefit of `pg_sun::
* p_variable_array_type'. Grrr.
*/
name = calc_struct_slot_name(au->cases.cases_val[i].var.name);
ptc = 0;
p_type(au->cases.cases_val[i].var.type,
&ptc);
ptn = ptc->find_type("definition");
variant_ctype = ptn->get_type();
variant_map = ptn->get_mapping();
suinl->cases.cases_val[i].mapping = variant_map;
if (au->cases.cases_val[i].var.type->kind == AOI_VOID) {
/* In the PRES_C description, we must indicate that
this variant of the union doesn't correspond to
any member of the `union_ctype'. (There are no
void members!) */
suinl->cases.cases_val[i].index = -1;
} else {
/* Otherwise, we must remember which member of the
`union_ctype' corresponds to this AOI union case.
*/
suinl->cases.cases_val[i].index =
union_ctype_cases_idx;
/* Add the member to the `union_ctype'. */
cdef = cast_add_def(
scope,
cast_new_scoped_name(
calc_struct_slot_name(au->cases.
cases_val[i].
var.name),
NULL),
CAST_SC_NONE,
CAST_VAR_DEF,
ch(cur_aoi_idx, PG_CHANNEL_CLIENT_DECL),
current_protection);
scope->cast_scope_val[cdef].u.cast_def_u_u.var_def.
type = variant_ctype;
++union_ctype_cases_idx;
}
}
if (au->dfault) {
suinl->dfault = (pres_c_inline_struct_union_case *)
mustmalloc(
sizeof(pres_c_inline_struct_union_case)
);
/*
* XXX --- We must set `name' here for the benefit of `pg_sun::
* p_variable_array_type'. Grrr.
*/
name = calc_struct_slot_name(au->dfault->name);
ptc = 0;
p_type(au->dfault->type, &ptc);
ptn = ptc->find_type("definition");
variant_ctype = ptn->get_type();
variant_map = ptn->get_mapping();
suinl->dfault->mapping = variant_map;
if (au->dfault->type->kind == AOI_VOID) {
/* As described above, remember that there is no
member of the `union_ctype' that corresponds to this
case. */
suinl->dfault->index = -1;
} else {
/* Remember which member of the `union_ctype'
corresponds to this AOI union case. */
suinl->dfault->index = union_ctype_cases_len - 1;
/* Add the member to the `union_ctype'. */
cdef = cast_add_def(
scope,
cast_new_scoped_name(
calc_struct_slot_name(au->dfault->
name),
NULL),
CAST_SC_NONE,
CAST_VAR_DEF,
ch(cur_aoi_idx, PG_CHANNEL_CLIENT_DECL),
current_protection);
scope->cast_scope_val[cdef].u.cast_def_u_u.var_def.
type = variant_ctype;
}
} else
/* Remember that there is no default case. */
suinl->dfault = 0;
/* Create a direct pres_c_mapping for the C union, and add the union
slot to the structure definition we are creating (`inl_ctype'). */
union_map = (pres_c_mapping)
mustcalloc(sizeof(struct pres_c_mapping_u));
union_map->kind = PRES_C_MAPPING_DIRECT;
pop_ptr(scope_stack);
/* The following invocation of `p_inline_add_atom' has the side effect
of adding the union slot to the structure definition. */
p_inline_add_atom(inl_ctype,
calc_struct_slot_name(au->union_label),
union_ctype,
union_map);
/* Restore the name context. */
name = old_name;
return inl;
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1