/*
 * 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.
 */

/*
 * These functions are used in mom/c/pfe/ programs.
 *
 * See comments in mom/mom/aoi.x and mom/mom/mint.x, as well as the
 * "Flick Internals" document for a description of AOI and MINT.
 */


#include <stdlib.h>
#include <mom/compiler.h>
#include <mom/libaoi.h>
#include <mom/libmint.h>
#include <assert.h>

/* global variables */
mint_1 out_mint;
mint_ref mom_msg = mint_ref_null;
mint_ref *aoi_to_mint_association;
aoi in_aoi;

static int mint_max = 0;
extern int custom_const;
static char *a_name;

/* Quickie lookup macro */
#define m(n) (out_mint.defs.defs_val[n])
#define a(n) (in_aoi.defs.defs_val[n])

mint_const (*mint_custom_op_const)(aoi_interface *this_interface,
				   char *this_interface_name,
				   aoi_interface *derived_interface,
				   char *derived_interface_name,
				   aoi_operation *op,
				   int type_of_constant) = 0;
mint_const (*mint_custom_attrib_const)(aoi_interface *this_interface,
				       char *this_interface_name,
				       aoi_interface *derived_interface,
				       char *derived_interface_name,
				       aoi_attribute *attrib,
				       int type_of_constant) = 0;
mint_const (*mint_custom_exception_const)(aoi_ref exception_ref,
					  unsigned int exception_num) = 0;

mint_ref mint_custom_exception_discrim_ref = 0;

/* prototype declarations for static functions defined in this file */
void translate_aoi_to_mint(void);
static void tam_aoi_type(aoi_type aoi_type, mint_ref *mr);
static mint_ref tam_ref(aoi_ref ref);
static mint_ref tam_integer(aoi_integer *integer_def);
static mint_ref tam_float(aoi_float *float_def);
static mint_ref tam_char(aoi_char *char_def);
static mint_ref tam_scalar(aoi_scalar *scalar_def);
static mint_ref tam_array(aoi_array *array_def);
static mint_ref tam_struct(aoi_struct *struct_def);
static mint_ref tam_union(aoi_union *union_def);

static void tam_interface(aoi_interface *aoi_interface_def);
static void tam_interface_contents(aoi_interface *this_interface,
				   char *this_interface_name,
				   aoi_interface *derived_interface,
				   char *derived_interface_name,
				   mint_ref interface_union);
static void tam_interface_contents_add(mint_ref interface_union,
				       mint_const discrim,
				       mint_ref type,
				       char *interface_name,
				       char *type_name);

static mint_ref tam_operation_request_struct(aoi_operation *ops_val);
static mint_ref tam_operation_reply_struct(aoi_operation *ops_val,
					   mint_ref req);

static mint_ref tam_attribute_read_request_struct(aoi_attribute *attribs_val);
static mint_ref tam_attribute_read_reply_struct(aoi_attribute *attribs_val);
static mint_ref tam_attribute_write_request_struct(aoi_attribute *attribs_val);
static mint_ref tam_attribute_write_reply_struct(aoi_attribute *attribs_val);

/*
 * Presentation generators need to look up MINT request and reply
 * discriminator values, so we record these types during translation.
 *
 * We keep a table of `interface_mint_table_elem's so that we can map from a
 * given AOI (interface, operation/attribute) pair onto the MINT request and
 * reply discriminator values that were produced.
 *
 * `interface_mint_table' is our table, `interface_mint_table_size' is the
 * number of elements in the table (i.e., the size of the array), and
 * `interface_mint_table_count' is the number of records that have been used.
 */
typedef struct {
	aoi_interface *interface;
	void *op_or_attr; /* `aoi_operation *' or `aoi_attribute *'. */
	mint_const request_discrim;
	mint_const reply_discrim;
} interface_mint_table_elem;

#define INTERFACE_MINT_TABLE_INCREMENT (128)

static interface_mint_table_elem *interface_mint_table;
static int interface_mint_table_size;
static int interface_mint_table_count;

void tam_interface_record_mint_discrims(aoi_interface *interface,
					void *op_or_attr,
					mint_const request_discrim,
					mint_const reply_discrim);
int lookup_interface_mint_discrims(aoi_interface *interface,
				   void *op_or_attr,
				   /* OUT */ mint_const *request_discrim,
				   /* OUT */ mint_const *reply_discrim);
static void init_interface_mint_table();

/*****/

static mint_ref tam_exception(aoi_exception *exception_def);
/* static mint_ref tam_const(aoi_const *const_def); */
static mint_ref tam_void();
static mint_ref tam_optional(aoi_optional *optional_def);
static mint_ref tam_any();
static mint_ref tam_type_tag();
static mint_ref tam_typed(aoi_typed *typed_def);
static int get_def();
static mint_ref get_union_def(int len);
static int expand_union_cases(mint_ref r);
#if 0  /* currently unused, but might be used later */
static int xl_int(int min, unsigned range);
#endif
static mint_ref get_union_def_given_discriminator_type(
	int len, mint_ref discriminator_type);
#if 0  /* currently unused, but might be used later */
static int xl_array_minlen(mint_ref type_d, int min, unsigned len);
#endif

/* function definitions */


/*
 * translate_aoi_to_mint() translates an AOI data structure to a MINT
 * structure.  This function is available for PFE components of the
 * MOM IDL Compiler.  It allocates memory as needed to build the MINT.
 * It also assigns values to aoi_to_mint_association and
 * aoi_to_mint_array_size.
 */

void translate_aoi_to_mint(void)
{
	int i, number_of_aoi_names;

	number_of_aoi_names = in_aoi.defs.defs_len;
	
	/*
	 * `out_mint' must already be initialized to contain the standard MINT
	 * types.  (We used to call `mint_add_standard_defs' here, but that
	 * made it more difficult to link the presentation generators.)
	 */
	if (out_mint.defs.defs_len == 0)
		panic("In `translate_aoi_to_mint', `out_mint' has not been "
		      "preloaded with the standard MINT types.");
	
	/*
	 * We try to be clever when reallocating the `out_mint.defs.def_val'
	 * array; see `get_def'.
	 */
	mint_max = out_mint.defs.defs_len;
	
	init_interface_mint_table();
	
	/*
	 * Create a MINT_UNION definition to serve as the top-level mom_msg
	 * union.  Initially, this union will have no cases, and
	 * get_union_def() assigns to it a 32-bit integer discriminator type.
	 */
	
	/*
	 * Assert that only the declaration-time initialization of mom_msg
	 * should have been done.
	 */
	assert(mom_msg == mint_ref_null);
	
	mom_msg = get_union_def(0);
	
	for (i = 0; i < number_of_aoi_names; i++)
		aoi_to_mint_association[i] = get_def();
	
	for (i = 0; i < number_of_aoi_names; i++) {
		aoi_type a_type;
		mint_ref temp;
		
		/* Select the AOI type to translate. */
		a_type = a(i).binding;
		a_name = a(i).name;
		/* Do the translation. */
		tam_aoi_type(a_type, &temp);
		m(aoi_to_mint_association[i]) = m(temp);
		if (a_type->kind == AOI_INDIRECT)
			aoi_to_mint_association[i]
				= aoi_to_mint_association[a_type->aoi_type_u_u.
							 indirect_ref];
		
		/* Similar to the above indirect case */
		if( (a_type->kind == AOI_FWD_INTRFC) &&
		    (a_type->aoi_type_u_u.fwd_intrfc_def != -1) ) {
			aoi_to_mint_association[i]
				= aoi_to_mint_association[a_type->aoi_type_u_u.
							 fwd_intrfc_def];
		}
		/*
		 * Check to see that the returned value is in the correct
		 * range.  It should always be that 0 <= new_mint_index <
		 * out_mint.defs.defs_len.
		 */
		/* assert(0 <= new_mint_index); */
		/*
		 * This has been changed.  Forward refs will be -1 until
		 * corrected...
		 */
		assert(aoi_to_mint_association[i]
		       < (signed int) out_mint.defs.defs_len);
		
		/*
		 * Make the aoi_name-to-mint_ref association, so that AOI_REF
		 * types can be translated.
		 */
		/* aoi_to_mint_association[i] = new_mint_index; */
	}
}


/*
 * `tam_aoi_type' translates an AOI type, and returns a new mint_ref in `*mr'.
 */
static void tam_aoi_type(aoi_type aoi_type, mint_ref *mr)
{
	mint_ref r;  /* return value for this function */
	mint_def *initial_defs_val = out_mint.defs.defs_val;
	int mr_inside_buffer;
	
	/*
	 * Many of the `tam_*' functions can potentially reallocate the
	 * `out_mint.defs.defs_val' array.  However, it's very likely that `mr'
	 * is a pointer into this buffer!  Therefore, we must be careful to fix
	 * `mr' if we discover that the buffer has changed.  What a mess.
	 */
	initial_defs_val = out_mint.defs.defs_val;
	mr_inside_buffer = (((char *) mr) >= ((char *) out_mint.defs.defs_val))
			   &&
			   (((char *) mr) < ((char *)
					     (out_mint.defs.defs_val +
					      out_mint.defs.defs_len)));
	
	switch (aoi_type->kind) {
	case AOI_INDIRECT:
		r = tam_ref(aoi_type->aoi_type_u_u.indirect_ref);
		break;
	case AOI_INTEGER:
		r = tam_integer(&(aoi_type->aoi_type_u_u.integer_def));
		break;
	case AOI_SCALAR:
		r = tam_scalar(&(aoi_type->aoi_type_u_u.scalar_def));
		break;
	case AOI_FLOAT:
		r = tam_float(&(aoi_type->aoi_type_u_u.float_def));
		break;
	case AOI_CHAR:
		r = tam_char(&(aoi_type->aoi_type_u_u.char_def));
		break;
	case AOI_ARRAY:
		r = tam_array(&(aoi_type->aoi_type_u_u.array_def));
		break;
	case AOI_STRUCT:
		r = tam_struct(&(aoi_type->aoi_type_u_u.struct_def));
		break;
	case AOI_UNION:
		r = tam_union(&(aoi_type->aoi_type_u_u.union_def));
		break;
	case AOI_INTERFACE:
		tam_interface(&(aoi_type->aoi_type_u_u.interface_def));
		/*
		 * We return a reference to the standard interface name def,
		 * and `tam_aoi_to_mint' copies that definition to produce a
		 * unique `mint_ref' for the interface.  This is important
		 * because the BE currently uses `mint_ref's to identify m/u
		 * stubs; see the function `pres_c_find_mu_stub'.  Without a
		 * unique `mint_ref' we couldn't distinguish the m/u stubs for
		 * different interfaces.
		 */
		r = out_mint.standard_refs.interface_name_ref;
		break;
	case AOI_FWD_INTRFC:
		/*
		 * The above comment applies here, too, although now we have a
		 * subtle problem: the forward interface and the real interface
		 * will have different `mint_ref's.  But this isn't a problem
		 * in practice because the m/u stubs will be identical.
		 */
		r = out_mint.standard_refs.interface_name_ref;
		break;		
	case AOI_EXCEPTION:
		r = tam_exception(&(aoi_type->aoi_type_u_u.exception_def));
		break;
	case AOI_CONST:
		r = tam_void();  /* XXX - ignore aoi_const, as test */
		break;
	case AOI_ENUM: {
		/*
		 * As discussed (by crum and baford) on 9-Aug-1995,
		 * aoi_enum values are "compiled out", i.e., not translated
		 * to any MINT definitions.  Also, mint_enum_def is obsolete.
		 * XXX - For now, return a MINT_VOID.
		 */
		/*
		 * CORBA needs something - you can't have a void parameter! 
		 * So, it's being moved to a u_int - Corba specifies that,
		 * and no one else uses enums, anyway! KBF - 7/22/96
		 */
		aoi_integer i = {0, ~0U};
		r = tam_integer(&i);
		break;
	}
	case AOI_NAMESPACE:
		/* we don't do anything - they're strictly mapping
		   instructions */
	case AOI_VOID:
		r = tam_void();
		break;
	case AOI_OPTIONAL:
		r = tam_optional(&(aoi_type->aoi_type_u_u.optional_def));
		break;
	case AOI_ANY:
		r = tam_any();
		break;
	case AOI_TYPE_TAG:
		r = tam_type_tag();
		break;
	case AOI_TYPED:
		r = tam_typed(&(aoi_type->aoi_type_u_u.typed_def));
		break;
	case AOI_ERROR:
		panic("In `tam_aoi_type', found a binding to an AOI_ERROR.  "
		      "AOI_ERRORs represent IDL parse errors and should never "
		      "appear in AOI files.");
		break;
	default:
		panic("Unexpected AOI binding %d in `tam_aoi_type'",
		      aoi_type->kind);
		break;
	}
	
	if (mr_inside_buffer && (initial_defs_val != out_mint.defs.defs_val)) {
		/*
		 * `mr' pointed to an address inside `out_mint.defs.defs_val',
		 * and that array has moved since this function was invoked.
		 * We must fix `mr'.
		 */
		mr = (mint_ref *)
		     (((char *) out_mint.defs.defs_val) +
		      (((char *) mr) - ((char *) initial_defs_val)));
	}
	
	*mr = r;
}


/* "tam_" stands for "Translate from AOI to MINT", and
   functions with the "tam_" prefix are used to translate
   particular definition types.  They are used in the
   translate_aoi_name_to_mint_def() function, which is defined
   later in this file.
*/


/* translate an AOI reference to a MINT reference */
static mint_ref tam_ref(aoi_ref ref)
{
	/*
	 * In this case, no new mint_def needs to be allocated.  We can simply
	 * use the `aoi_to_mint_association' array.
	 * Caveat: if ``ref'' refers to another AOI_INDIRECT (reference),
	 * we need to dig until we find the ``real'' AOI type.
	 */
	while (a(ref).binding->kind == AOI_INDIRECT)
		ref = a(ref).binding->aoi_type_u_u.indirect_ref;
	
	return aoi_to_mint_association[ref];
}


static mint_ref tam_integer(aoi_integer *integer_def)
{
	mint_ref r = get_def();

	m(r).kind = MINT_INTEGER;
	m(r).mint_def_u.integer_def.min = integer_def->min;
	m(r).mint_def_u.integer_def.range = integer_def->range;

	return(r);
}


static mint_ref tam_scalar(aoi_scalar *scalar_def) 
{
	mint_ref r = get_def();
	
	m(r).kind = MINT_SCALAR;
	m(r).mint_def_u.scalar_def.bits = scalar_def->bits;
	switch (scalar_def->flags) {
	case AOI_SCALAR_FLAG_NONE:
		m(r).mint_def_u.scalar_def.flags = MINT_SCALAR_FLAG_NONE;
		break;
	case AOI_SCALAR_FLAG_SIGNED:
		m(r).mint_def_u.scalar_def.flags = MINT_SCALAR_FLAG_SIGNED;
		break;
	case AOI_SCALAR_FLAG_UNSIGNED:
		m(r).mint_def_u.scalar_def.flags = MINT_SCALAR_FLAG_UNSIGNED;
		break;
	default:
		panic("Unrecognized value of aoi_scalar_flags: %d",
		      scalar_def->flags);
	}
	return(r);
}


static mint_ref tam_float(aoi_float *float_def)
{
	mint_ref r = get_def();

	m(r).kind = MINT_FLOAT;
	m(r).mint_def_u.float_def.bits = float_def->bits;

	return(r);
}


static mint_ref tam_char(aoi_char *char_def)
{
	aoi_char_flags flags = char_def->flags;
	mint_ref r = get_def();
	
	m(r).kind = MINT_CHAR;
	m(r).mint_def_u.char_def.bits = char_def->bits;
	switch (flags) {
	case AOI_CHAR_FLAG_NONE:
		m(r).mint_def_u.char_def.flags = MINT_CHAR_FLAG_NONE;
		break;
	case AOI_CHAR_FLAG_SIGNED:
		m(r).mint_def_u.char_def.flags = MINT_CHAR_FLAG_SIGNED;
		break;
	case AOI_CHAR_FLAG_UNSIGNED:
		m(r).mint_def_u.char_def.flags = MINT_CHAR_FLAG_UNSIGNED;
		break;
	default:
		panic("Unrecognized value of aoi_char_flags: %d", flags);
		break;
	}
	return(r);
}


static mint_ref tam_array(aoi_array *array_def)
{
	mint_ref r = get_def();

	m(r).kind = MINT_ARRAY;
	tam_aoi_type(array_def->element_type,
		     &(m(r).mint_def_u.array_def.element_type));
	tam_aoi_type(array_def->length_type,
		     &(m(r).mint_def_u.array_def.length_type));

	return(r);
}


static mint_ref tam_struct(aoi_struct *struct_def)
{
	mint_ref r = get_def();
	int slots_len = struct_def->slots.slots_len;
	int i;

	m(r).kind = MINT_STRUCT;
	m(r).mint_def_u.struct_def.slots.slots_len = slots_len;
	m(r).mint_def_u.struct_def.slots.slots_val =
		(mint_ref *)mustmalloc(sizeof(mint_ref)*slots_len);

	/*
	 * For each slot in the struct, translate the slot AOI type to a
	 * mint_ref.
	 */
	for (i = 0; i < slots_len; i++)
		tam_aoi_type(struct_def->slots.slots_val[i].type,
			     &(m(r).mint_def_u.struct_def.slots.slots_val[i]));
	
	return(r);
}


static mint_ref tam_union(aoi_union *union_def)
{
	mint_ref r = get_def();
	int cases_len = union_def->cases.cases_len;
	int i;
	
	m(r).kind = MINT_UNION;
	
	/* Translate the discriminator type. */
	tam_aoi_type(union_def->discriminator.type,
		     &(m(r).mint_def_u.union_def.discrim));
	
	/* Translate the union cases. */
	m(r).mint_def_u.union_def.cases.cases_len = cases_len;
	m(r).mint_def_u.union_def.cases.cases_val =
		(mint_union_case *) mustmalloc(sizeof(mint_union_case) *
					       cases_len);
	
	/* For each case in the union, translate the case field types (val and
	   var) into mint_refs. */
	for (i = 0; i < cases_len; i++)	{
		/* The mint_union_def `val' is a mint_const,
		   and the aoi_union `val' is an aoi_const. */
		m(r).mint_def_u.union_def.cases.cases_val[i].val =
			mint_new_const_from_aoi_const(union_def->
						      cases.cases_val[i].val);
		/* The mint_union_def `var' is a MINT type. */
		tam_aoi_type(union_def->cases.cases_val[i].var.type,
			     &(m(r).mint_def_u.union_def.cases.cases_val[i].
			       var));
	}
	
	/* Translate the default case, too. */
	if (union_def->dfault)
		tam_aoi_type(union_def->dfault->type,
			     &(m(r).mint_def_u.union_def.dfault));
	else
		/* `mint_ref_null' indicates that there is no default case. */
		m(r).mint_def_u.union_def.dfault = mint_ref_null;
	
	return r;
}


static void tam_interface(aoi_interface *a)
{
	mint_const idl_const, code_const;
	mint_ref l2_union, l3_union, returned_ref;
	mint_ref code_type, op_code_type;
	int l2_union_case, l3_union_case;
	
	/* level 1 (mom_msg union) */

	idl_const = mint_new_const_int((int)a->idl);
	/* XXX ---
	   We should use symbolic constants, now that we have them!  But until
	   then, assert that we have a literal.  Really, the whole `switch'
	   below should become obsolete when we fix the parts of AOI that are
	   IDL dependent. */
	assert(idl_const->mint_const_u_u.const_int.kind == MINT_CONST_LITERAL);
	
	switch (idl_const->mint_const_u_u.const_int.mint_const_int_u_u.value) {
	case AOI_IDL_SUN:
		/* With Sun RPC, AOI interfaces represent both programs and
		   versions.
		   We represent versions in the MINT;
		   however, programs add nothing to our MINT representation.
		   The AOI for a version already contains the number of the
		   program in which it is contained.
		   */
		if (a->parents.parents_len <= 0) {
			/* The interface `a' represents a program.  We're done!
			   It is important to punt here ---
			   the AOI_INTERFACE for a program has a different
			   code_type than an AOI_INTERFACE for a version.
			   If we didn't punt, then the second-level union would
			   be created with the wrong discriminator code type!
			   */
			return;
		}
		break;
		
	default:
		break;
	}
	
	/* If a case for this IDL does not already exist, then add it. */
	l2_union = mint_find_union_case(&out_mint, mom_msg, idl_const);
	if (l2_union == mint_ref_null) {
		tam_aoi_type(a->code_type, &code_type);
		/* If `a->code_type' were an AOI_INDIRECT, then it would be
		   possible for it to be a forward reference to another AOI
		   type.  If it were a forward reference, `code_type' would be
		   set to -1.  However, we can't deal with that --- because
		   `code_ref' is a local variable, and the forward-reference
		   tracking code will save the address of `code_type', and it
		   won't know that it really has to fix the reference to the
		   discriminator in the `l2_union' instead.  This difficulty
		   could be avoided by rewriting the code in this area, but
		   it's not really worth the effort right now. */
		assert(code_type != -1);
		l2_union =
			get_union_def_given_discriminator_type(0, code_type); 
		l2_union_case = expand_union_cases(mom_msg);  /* adds a case */
	   	m(mom_msg).mint_def_u.union_def.cases.
			cases_val[l2_union_case].val
		 = idl_const;
		m(mom_msg).mint_def_u.union_def.cases.
			cases_val[l2_union_case].var
		 = l2_union;
	}


	/* level 2 (interface code) */
	code_const = mint_new_const_from_aoi_const(a->code);
	tam_aoi_type(a->op_code_type, &op_code_type);
	/* Similar to `a->code_type', we can't allow `a->op_code_type' to be an
	   AOI_INDIRECT forward reference, because as this code now stands, the
	   forward-reference tracking code wouldn't be able to cope. */
	assert(op_code_type != -1);
	
	/* This interface should not already have a case value. */
	returned_ref = mint_find_union_case(&out_mint, l2_union, code_const);
	if (returned_ref != mint_ref_null)
	{
		panic("unexpected duplicate interface code value");
	}

	l3_union = get_union_def_given_discriminator_type(0, op_code_type);
	l3_union_case = expand_union_cases(l2_union);  /* adds a case */
	m(l2_union).mint_def_u.union_def.cases.cases_val[l3_union_case].val
	 = code_const;
	m(l2_union).mint_def_u.union_def.cases.cases_val[l3_union_case].var
	 = l3_union;

	/* Level 3 (operations, attributes and exceptions in the interface) */
	tam_interface_contents(a, a_name, a, a_name, l3_union);
}

static void tam_interface_contents(aoi_interface *this_interface,
				   char *this_interface_name,
				   aoi_interface *derived_interface,
				   char *derived_interface_name,
				   mint_ref interface_union)
{
	u_int ops_len = this_interface->ops.ops_len;
	u_int attribs_len = this_interface->attribs.attribs_len;
	u_int parents_len = this_interface->parents.parents_len;
	u_int i;
	
	mint_const request_discrim, reply_discrim;
	mint_ref request_type, reply_type;
	
	/* Add all of the operations that are part of this interface. */
	for (i = 0; i < ops_len; ++i) {
		aoi_operation *op_val = &(this_interface->ops.ops_val[i]);
		
		/*
		 * Determine the MINT discriminator that corresponds to the
		 * request code for this operation.
		 */
		if (mint_custom_op_const)
			request_discrim =
				(*mint_custom_op_const)(this_interface,
							this_interface_name,
							derived_interface,
							derived_interface_name,
							op_val,
							MAKE_OP_REQUEST);
		else
			request_discrim =
				mint_new_const_from_aoi_const(op_val->
							      request_code);
		
		/*
		 * Add this request to the MINT union that represents the
		 * interface.
		 */
		if (mint_find_union_case(&out_mint,
					 interface_union, request_discrim)
		    != mint_ref_null)
			/*
			 * This request is already defined in the MINT for the
			 * `derived_interface'.  This will occur if the
			 * operation was overridden by an interface derived
			 * from `this_interface', or if we are revisiting
			 * `this_interface' because there are multiple paths of
			 * inheritance between `derived_interface' and
			 * `this_interface'.
			 *
			 * In any case, the assumption is that we can ignore
			 * this redefinition and that we don't need to process
			 * the reply type.
			 */
			continue;
		
		request_type = tam_operation_request_struct(op_val);
		tam_interface_contents_add(interface_union,
					   request_discrim,
					   request_type,
					   derived_interface_name,
					   "operation request");
		
		/*
		 * Determine the MINT discriminator that corresponds to the
		 * reply code for this operation.
		 *
		 * XXX --- Yes, the request and reply codes must be distinct.
		 * This is a bug.
		 */
		if (mint_custom_op_const)
			reply_discrim =
				(*mint_custom_op_const)(this_interface,
							this_interface_name,
							derived_interface,
							derived_interface_name,
							op_val,
							MAKE_OP_REPLY);
		else
			reply_discrim =
				mint_new_const_from_aoi_const(op_val->
							      reply_code);
		
		/*
		 * Add this reply to the MINT union that represents the
		 * interface.
		 */
		if (mint_find_union_case(&out_mint,
					 interface_union, reply_discrim)
		    != mint_ref_null)
			/*
			 * This reply is already defined in the MINT for the
			 * `derived_interface'.
			 *
			 * As before, the assumption is that we can ignore
			 * this redefinition.  However, we can't `continue'
			 * here because we still need to record the connection
			 * between the `request_discrim' and `op_val'.
			 */
			/* Do nothing. */ ;
		else {
			reply_type = tam_operation_reply_struct(op_val,
								request_type);
			tam_interface_contents_add(interface_union,
						   reply_discrim,
						   reply_type,
						   derived_interface_name,
						   "operation reply");
		}
		
		/*
		 * Record the request and reply MINT discriminators so that the
		 * presentation generator can easily find them later.
		 */
		tam_interface_record_mint_discrims(derived_interface,
						   op_val,
						   request_discrim,
						   reply_discrim);
	}
	
	for (i = 0; i < attribs_len; ++i) {
		aoi_attribute *attrib_val = &(this_interface->
					      attribs.attribs_val[i]);
		
		/*
		 * Determine the MINT discriminator that corresponds to the
		 * read-request code for this attribute.
		 */
		if (mint_custom_attrib_const)
			request_discrim =
				(*mint_custom_attrib_const)(
					this_interface,
					this_interface_name,
					derived_interface,
					derived_interface_name,
					attrib_val,
					MAKE_ATTRIB_READ_REQUEST);
		else
			request_discrim =
				mint_new_const_from_aoi_const(
					attrib_val->read_request_code);
		
		/*
		 * Add this read-request to the MINT union that represents the
		 * interface.
		 */
		if (mint_find_union_case(&out_mint,
					 interface_union, request_discrim)
		    != mint_ref_null)
			/*
			 * This read-request is already defined in the MINT for
			 * the `derived_interface'.
			 *
			 * The assumption is that we can ignore this
			 * redefinition and that we don't need to process
			 * the read-reply type or any write-attribute stuff.
			 */
			continue;
		
		request_type = tam_attribute_read_request_struct(attrib_val);
		tam_interface_contents_add(interface_union,
					   request_discrim,
					   request_type,
					   derived_interface_name,
					   "attribute read request");
		
		/*
		 * Determine the MINT discriminator that corresponds to the
		 * read-reply code for this operation.
		 *
		 * XXX --- Yes, the request and reply codes must be distinct.
		 * This is a bug.
		 */
		if (mint_custom_attrib_const)
			reply_discrim =
				(*mint_custom_attrib_const)(
					this_interface,
					this_interface_name,
					derived_interface,
					derived_interface_name,
					attrib_val,
					MAKE_ATTRIB_READ_REPLY);
		else
			reply_discrim =
				mint_new_const_from_aoi_const(
					attrib_val->read_reply_code);
		
		/*
		 * Add this read-reply to the MINT union that represents the
		 * interface.
		 */
		if (mint_find_union_case(&out_mint,
					 interface_union, reply_discrim)
		    != mint_ref_null)
			/*
			 * This read-reply is already defined in the MINT for
			 * the `derived_interface'.
			 *
			 * As before, the assumption is that we can ignore
			 * this redefinition.  However, we can't `continue'
			 * here because we still need to record the connection
			 * between the `request_discrim' and `attrib_val'.
			 */
			/* Do nothing */ ;
		else {
			reply_type =
				tam_attribute_read_reply_struct(attrib_val);
			tam_interface_contents_add(interface_union,
						   reply_discrim,
						   reply_type,
						   derived_interface_name,
						   "attribute read reply");
		}
		
		/*
		 * Record the request and reply MINT discriminators so that the
		 * presentation generator can easily find them later.
		 */
		tam_interface_record_mint_discrims(derived_interface,
						   attrib_val,
						   request_discrim,
						   reply_discrim);
		
		/* If this attribute is read-only, skip the writing stuff. */
		if (attrib_val->readonly)
			continue;
		
		/*
		 * Determine the MINT discriminator that corresponds to the
		 * write-request code for this attribute.
		 */
		if (mint_custom_attrib_const)
			request_discrim =
				(*mint_custom_attrib_const)(
					this_interface,
					this_interface_name,
					derived_interface,
					derived_interface_name,
					attrib_val,
					MAKE_ATTRIB_WRITE_REQUEST);
		else
			request_discrim =
				mint_new_const_from_aoi_const(
					attrib_val->write_request_code);
		
		/*
		 * Add this write-request to the MINT union that represents the
		 * interface.
		 */
		if (mint_find_union_case(&out_mint,
					 interface_union, request_discrim)
		    != mint_ref_null)
			/*
			 * This write-request is already defined in the MINT
			 * for the `derived_interface'.
			 *
			 * The assumption is that we can ignore this
			 * redefinition and that we don't need to process
			 * the write-reply type.
			 */
			continue;
		
		request_type = tam_attribute_write_request_struct(attrib_val);
		tam_interface_contents_add(interface_union,
					   request_discrim,
					   request_type,
					   derived_interface_name,
					   "attribute write request");
		
		/*
		 * Determine the MINT discriminator that corresponds to the
		 * write-reply code for this operation.
		 *
		 * XXX --- Yes, the request and reply codes must be distinct.
		 * This is a bug.
		 */
		if (mint_custom_attrib_const)
			reply_discrim =
				(*mint_custom_attrib_const)(
					this_interface,
					this_interface_name,
					derived_interface,
					derived_interface_name,
					/* a_name */
					attrib_val,
					MAKE_ATTRIB_WRITE_REPLY);
		else
			reply_discrim =
				mint_new_const_from_aoi_const(
					attrib_val->write_reply_code);
		
		/*
		 * Add this write-reply to the MINT union that represents the
		 * interface.
		 */
		if (mint_find_union_case(&out_mint,
					 interface_union, reply_discrim)
		    != mint_ref_null)
			/*
			 * This write-reply is already defined in the MINT for
			 * the `derived_interface'.
			 *
			 * As before, the assumption is that we can ignore
			 * this redefinition.  However, we can't `continue'
			 * here because we still need to record the connection
			 * between the `request_discrim' and `attrib_val'.
			 */
			/* Do nothing */ ;
		else {
			reply_type =
				tam_attribute_write_reply_struct(attrib_val);
			tam_interface_contents_add(interface_union,
						   reply_discrim,
						   reply_type,
						   derived_interface_name,
						   "attribute write reply");
		}
		
		/*
		 * Record the request and reply MINT discriminators so that the
		 * presentation generator can easily find them later.
		 */
		tam_interface_record_mint_discrims(derived_interface,
						   attrib_val,
						   request_discrim,
						   reply_discrim);
		
	}
	
	/*
	 * Finally, we must process all of the operations and attributes
	 * defined by the inherited interfaces as well.
	 */
	for (i = 0; i < parents_len; ++i) {
		aoi_type parent_val = this_interface->parents.parents_val[i];
		aoi_ref  parent_ref;
		
		/*
		 * All parent references must be through indirects so that
		 * we can find the name to go with the parent interface!
		 */
		assert(parent_val->kind == AOI_INDIRECT);
		
		parent_ref = parent_val->aoi_type_u_u.indirect_ref;
		/*
		 * If `parent_ref' references a forward interface definition,
		 * find the real interface definition.
		 */
		parent_ref = aoi_deref_fwd(&in_aoi, parent_ref);
		
		tam_interface_contents(&(a(parent_ref).binding->
					 aoi_type_u_u.interface_def),
				       a(parent_ref).name,
				       derived_interface,
				       derived_interface_name,
				       interface_union);
	}
}

static void tam_interface_contents_add(mint_ref interface_union,
				       mint_const discrim,
				       mint_ref type,
				       char *interface_name,
				       char *type_name)
{
	int union_case;
	
	/*
	 * This check should *never* be true.  The callee is responsible for
	 * checking `mint_find_union_case' *before* calling this function.
	 */
	if (mint_find_union_case(&out_mint, interface_union, discrim)
	    != mint_ref_null)
		warn("Duplicate %s ignored for interface `%s'.",
		     type_name,
		     interface_name);
	else {
		union_case = expand_union_cases(interface_union);
		
		m(interface_union).mint_def_u.union_def.cases.
			cases_val[union_case].val
			= discrim;
		m(interface_union).mint_def_u.union_def.cases.
			cases_val[union_case].var
			= type;
	}
}

static mint_ref tam_operation_request_struct(aoi_operation *ops_val)
{
	mint_ref r = get_def();
	u_int slots_len = 0;
	u_int params_len = ops_val->params.params_len;
	u_int i;

	m(r).kind = MINT_STRUCT;
	m(r).mint_def_u.struct_def.slots.slots_len = slots_len;
	m(r).mint_def_u.struct_def.slots.slots_val =
		(mint_ref *)mustmalloc(sizeof(mint_ref)*params_len);

	/*
	 * For each parameter, add it to the structure if it should be in
	 * the request message.
	 */
	for (i = 0; i < params_len; i++)
	{
		aoi_parameter *params_val = &ops_val->params.params_val[i];
		if (params_val->direction == AOI_DIR_IN
		    || params_val->direction == AOI_DIR_INOUT)
		{
			/* Add the parameter to the structure. */
			tam_aoi_type(params_val->type,
				     &(m(r).mint_def_u.struct_def.slots.
				       slots_val[slots_len]));
			slots_len++;
			m(r).mint_def_u.struct_def.slots.slots_len = slots_len;
		}
	}

	return(r);
}

static mint_ref
tam_operation_reply_struct(aoi_operation *ops_val, mint_ref request_i)
{
	mint_ref u = get_def();
	u_int slots_len = 0;
	u_int params_len = ops_val->params.params_len;
	u_int i;
	u_int req_idx = 0;
	
	mint_ref r = get_def();
	
	m(r).kind = MINT_STRUCT;
	m(r).mint_def_u.struct_def.slots.slots_len = slots_len;
	/*
	 * Allocate params_len+1 mint refs, including one for the return value.
	 */
	m(r).mint_def_u.struct_def.slots.slots_val =
		(mint_ref *)mustmalloc(sizeof(mint_ref)*(params_len+1));
	
	/* provide the default for an exception discriminator */
	if (!mint_custom_exception_discrim_ref)
		mint_custom_exception_discrim_ref
			= out_mint.standard_refs.unsigned32_ref;
	
	/*
	 * For each parameter, add it to the structure if it should be in
         * the reply message.
	 */
	for (i = 0; i < params_len; i++)
	{
		aoi_parameter *params_val = &ops_val->params.params_val[i];
		if (params_val->direction == AOI_DIR_OUT
		    || params_val->direction == AOI_DIR_INOUT)
		{
			/* Add the parameter to the structure. */
			/*
			 * If it's an inout, don't retype it - just use the
			 * same type.
			 */
			if (params_val->direction == AOI_DIR_INOUT)
				m(r).mint_def_u.struct_def.slots.
					slots_val[slots_len] 
					= m(request_i).mint_def_u.
					struct_def.slots.slots_val[req_idx++];
			else
				tam_aoi_type(params_val->type,
					     &(m(r).mint_def_u.struct_def.
					       slots.slots_val[slots_len]));
			slots_len++;
			m(r).mint_def_u.struct_def.slots.slots_len = slots_len;
		} else
			req_idx++;
	}

	/* Add the return value of the operation. */
	tam_aoi_type(ops_val->return_type,
		     &(m(r).mint_def_u.struct_def.slots.
		       slots_val[slots_len]));
	slots_len++;
	m(r).mint_def_u.struct_def.slots.slots_len = slots_len;
	
	/*
	 * What we really want to return is the union of a normal response,
	 * system exception responses, & user exception responses
	 */
	m(u).kind = MINT_UNION;
	
	/*
	 * XXX --- It is not really correct to set the discriminator type to
	 * the unsigned32 type, although this is what the BE currently expects.
	 * Really, the back end should determine the actual type of exception
	 * discriminators.  We should just make ``symbolic'' discriminators
	 * here --- abstract MINT_EXCEPTIONs --- that are given on-the-wire
	 * encodings by the BE.
	 *
	 * The same comment applies to all of the other ``internal'' unions
	 * that we produce (i.e., those unions whose types are not explicitly
	 * defined by the source AOI).
	 */
	m(u).mint_def_u.union_def.discrim
		= out_mint.standard_refs.signed32_ref;
	m(u).mint_def_u.union_def.cases.cases_len
		= 2;
	m(u).mint_def_u.union_def.cases.cases_val
		= (mint_union_case *) mustmalloc(sizeof(mint_union_case) * 2);
	m(u).mint_def_u.union_def.cases.cases_val[0].val
		= mint_new_const_int(0);
	m(u).mint_def_u.union_def.cases.cases_val[0].var
		= r;
	m(u).mint_def_u.union_def.cases.cases_val[1].val
		= mint_new_const_int(-1);
	m(u).mint_def_u.union_def.cases.cases_val[1].var
		= out_mint.standard_refs.system_exception_ref;
	
	if (ops_val->exceps.exceps_len) {
		mint_ref uu;
		
		/* User-Union */
		uu = get_union_def_given_discriminator_type(
			ops_val->exceps.exceps_len,
			mint_custom_exception_discrim_ref);
			
		/*
		 * XXX --- See comment above about the types of ``internal''
		 * union discriminators.  It applies here too, except that
		 * here, a string discriminator is assumed, while each
		 * presentation could have different types.  XXX - This is
		 * currently a bug since the Fluke presentation expects an
		 * unsigned32 discriminator.
		 */
		for (i = 0; i < ops_val->exceps.exceps_len; i++) {
			mint_ref r;
			/*
			 * We must have an indirect ref to the exception's
			 * structure.
			 */
			assert(ops_val->exceps.exceps_val[i]->kind
			       == AOI_INDIRECT);
			r = aoi_to_mint_association[ops_val->exceps.
						   exceps_val[i]->aoi_type_u_u.
						   indirect_ref];
			/*
			 * Add the discriminator, then add the exception
			 * structure.
			 * XXX This should compute the RepositoryID for the
			 * discriminator.  Right now we just use the
			 * exception's unscoped name.
			 */
			if (mint_custom_exception_const) 
				m(uu).mint_def_u.union_def.cases.
					cases_val[i].val
				= (*mint_custom_exception_const)(
					(ops_val->exceps.exceps_val[i]->
					 aoi_type_u_u.indirect_ref),
					i);
			else
				m(uu).mint_def_u.union_def.cases.
					cases_val[i].val
					= mint_new_const_int(i);
			m(uu).mint_def_u.union_def.cases.cases_val[i].var
				= r;
		}
		/* No default value... */
		m(uu).mint_def_u.union_def.dfault = mint_ref_null;
		/* User exceptions are the default value of the return union */
		m(u).mint_def_u.union_def.dfault = uu;
	} else
		m(u).mint_def_u.union_def.dfault = mint_ref_null;
	
	return(u);
}

static mint_ref tam_attribute_read_request_struct(aoi_attribute *attribs_val)
{
	/* A read request is a request to "get" an attribute value.
	   So, the message has no parameters and "void" return value.
	   This function may simply return a MINT_VOID definition.  */
  /* That's WRONG - it needs to be a MINT_STRUCT */
  
  /*	return void_d;*/
	mint_ref r = get_def();

	m(r).kind = MINT_STRUCT;
	m(r).mint_def_u.struct_def.slots.slots_len = 0;
	m(r).mint_def_u.struct_def.slots.slots_val = 0 /* (mint_ref *)
							  mustmalloc(
							  sizeof(mint_ref));*/;
	
	/*	m(r).mint_def_u.struct_def.slots.slots_val[0] = void_d;*/

	return r;
}

static mint_ref tam_attribute_read_reply_struct(aoi_attribute *attribs_val)
{
	/* Create a MINT_STRUCT with the attribute type in it
	   (as the attribute value returned).  */

	mint_ref r = get_def();

	m(r).kind = MINT_STRUCT;
	m(r).mint_def_u.struct_def.slots.slots_len = 1;
	m(r).mint_def_u.struct_def.slots.slots_val =
		(mint_ref *)mustmalloc(sizeof(mint_ref));

	tam_aoi_type(attribs_val->type,
		     &(m(r).mint_def_u.struct_def.slots.slots_val[0]));

	return r;
}

static mint_ref tam_attribute_write_request_struct(aoi_attribute *attribs_val)
{
	/* Create a MINT_STRUCT with the attribute type in it
	   (as a parameter, which is the attribute to set). */

	mint_ref r = get_def();

	m(r).kind = MINT_STRUCT;
	m(r).mint_def_u.struct_def.slots.slots_len = 1;
	m(r).mint_def_u.struct_def.slots.slots_val =
		(mint_ref *)mustmalloc(sizeof(mint_ref));

	tam_aoi_type(attribs_val->type,
		     &(m(r).mint_def_u.struct_def.slots.slots_val[0]));

	return r;
}

static mint_ref tam_attribute_write_reply_struct(aoi_attribute *attribs_val)
{
	/* A write reply is a reply after an attribute value has been "set".
	   So, the message has no parameters and "void" return value.
	   This function may simply return a MINT_VOID definition.  */
  /* That's WRONG - it needs to be a MINT_STRUCT*/
  
  /*	return void_d;*/
	mint_ref r = get_def();

	m(r).kind = MINT_STRUCT;
	m(r).mint_def_u.struct_def.slots.slots_len = 0;
	m(r).mint_def_u.struct_def.slots.slots_val = 0 /* (mint_ref *)
							  mustmalloc(
							  sizeof(mint_ref));*/;
	/*	m(r).mint_def_u.struct_def.slots.slots_val[0] = void_d;*/

	return r;
}

void tam_interface_record_mint_discrims(aoi_interface *interface,
					void *op_or_attr,
					mint_const request_discrim,
					mint_const reply_discrim)
{
	mint_const dummy_request_discrim;
	mint_const dummy_reply_discrim;
	
	interface_mint_table_elem *this_elem;
	
	/*****/
	
	if (lookup_interface_mint_discrims(interface, op_or_attr,
					   &dummy_request_discrim,
					   &dummy_reply_discrim)) {
		/*
		 * We already have this (interface, operation/attribute) pair
		 * in the table.  We should never get here; however, we'll let
		 * it slide *if* we're not trying to change the associations.
		 */
		if ((request_discrim != dummy_request_discrim)
		    || (reply_discrim != dummy_reply_discrim))
			/* XXX --- Should panic. */
			warn("In `tam_record_operation_mint_discrims', "
			     "attempt to change previously-recorded MINT "
			     "discriminators.");
		return;
	}
	
	if (interface_mint_table_count >= interface_mint_table_size) {
		/*
		 * Grow the `interface_mint_table'.
		 */
		interface_mint_table_size = interface_mint_table_count
					    + INTERFACE_MINT_TABLE_INCREMENT;
		interface_mint_table =
			(interface_mint_table_elem *)
			mustrealloc(interface_mint_table,
				    (sizeof(interface_mint_table_elem)
				     * interface_mint_table_size));
	}
	
	this_elem = &(interface_mint_table[interface_mint_table_count]);
	
	this_elem->interface = interface;
	this_elem->op_or_attr = op_or_attr;
	this_elem->request_discrim = request_discrim;
	this_elem->reply_discrim = reply_discrim;
	
	++interface_mint_table_count;
}

int lookup_interface_mint_discrims(aoi_interface *interface,
				   void *op_or_attr,
				   /* OUT */ mint_const *request_discrim,
				   /* OUT */ mint_const *reply_discrim)
{
	int i;
	
	for (i = 0; i < interface_mint_table_count; ++i)
		if ((interface_mint_table[i].interface == interface)
		    && (interface_mint_table[i].op_or_attr == op_or_attr)) {
			/*
			 * We've found the right table element.
			 */
			*request_discrim = interface_mint_table[i].
					   request_discrim;
			*reply_discrim   = interface_mint_table[i].
					   reply_discrim;
			return 1;
		}
	
	*request_discrim = 0;
	*reply_discrim = 0;
	return 0;
}

static void init_interface_mint_table()
{
	/*
	 * Clear our associations for (interface, operation/attribute) to MINT
	 * discriminators.
	 */
	interface_mint_table_count = 0;
	interface_mint_table_size = INTERFACE_MINT_TABLE_INCREMENT;
	interface_mint_table =
		(interface_mint_table_elem *)
		mustmalloc(sizeof(interface_mint_table_elem)
			   * interface_mint_table_size);
}

/*****************************************************************************/

static mint_ref tam_exception(aoi_exception *exception_def)
{
	mint_ref r = get_def();
	int slots_len = exception_def->slots.slots_len;
	int i;

	m(r).kind = MINT_STRUCT;
	m(r).mint_def_u.struct_def.slots.slots_len = slots_len;
	m(r).mint_def_u.struct_def.slots.slots_val =
		(mint_ref *)mustmalloc(sizeof(mint_ref)*slots_len);

	/* For each slot in the exception, translate the slot AOI type to a
           mint_ref. */
	for (i = 0; i < slots_len; i++)
		tam_aoi_type(exception_def->slots.slots_val[i].type,
			     &(m(r).mint_def_u.struct_def.slots.slots_val[i]));
	
	return(r);
}


static mint_ref tam_void()
{
	mint_ref r = get_def();
	
	/* Translate the AOI_VOID type to MINT_VOID. */
	m(r).kind = MINT_VOID;
	
	return(r);
}


static mint_ref tam_optional(aoi_optional *optional_def)
{
	/* An AOI_OPTIONAL translates into a variable-length MINT array.
	   The array may contain zero elements or one element. */
	mint_ref r = get_def();
	
	m(r).kind = MINT_ARRAY;
	tam_aoi_type(optional_def->type,
		     &(m(r).mint_def_u.array_def.element_type));
	m(r).mint_def_u.array_def.length_type
		= out_mint.standard_refs.bool_ref;
	
	return r;
}


static mint_ref tam_any()
{
	mint_ref r = get_def();
	
	/* Translate the AOI_ANY type to MINT_ANY. */
	m(r).kind = MINT_ANY;
	
	return(r);
}


static mint_ref tam_type_tag()
{
	mint_ref r = get_def();
	
	/* Translate the AOI_TYPE_TAG type to MINT_TYPE_TAG. */
	m(r).kind = MINT_TYPE_TAG;
	
	return(r);
}


static mint_ref tam_typed(aoi_typed *typed_def)
{
	/* An `AOI_TYPED' translates into a corresponding `MINT_TYPED'. */
	mint_ref r = get_def();
	
	m(r).kind = MINT_TYPED;
	tam_aoi_type(typed_def->tag,
		     &(m(r).mint_def_u.typed_def.tag));
	tam_aoi_type(typed_def->type,
		     &(m(r).mint_def_u.typed_def.ref));
	
	return r;
}


/* auxiliary, helper routine as in mom/fe/sun/xlate.c */

/* Allocate a new (uninitialized) definition in the out_mint.  */
/* This is an auxiliary, helper routine as in mom/fe/sun/xlate.c */
static int get_def()
{
	int result;
	
	result = out_mint.defs.defs_len++;
	if (out_mint.defs.defs_len > (unsigned int) mint_max) {
		/* Reallocate our buffer. */
		mint_max = mint_max ? (mint_max *2) : 8;
		out_mint.defs.defs_val
			= ((mint_def *)
			   mustrealloc((void *) out_mint.defs.defs_val,
				       (size_t) (sizeof(mint_def)
						 * mint_max)));
	}
	
	return result;
}

static mint_ref get_union_def(int len)
{
	mint_ref r = get_def();
	m(r).kind = MINT_UNION;
	m(r).mint_def_u.union_def.discrim
		= out_mint.standard_refs.signed32_ref;
	m(r).mint_def_u.union_def.cases.cases_len
		= len;
	m(r).mint_def_u.union_def.cases.cases_val
		= mustmalloc(len ? (len * sizeof(mint_union_case)) : 1);
	m(r).mint_def_u.union_def.dfault
		= mint_ref_null;
	
	return r;
}

static int expand_union_cases(mint_ref r)
{
	int i = m(r).mint_def_u.union_def.cases.cases_len++;
	m(r).mint_def_u.union_def.cases.cases_val =
		(mint_union_case *)
		mustrealloc(m(r).mint_def_u.union_def.cases.cases_val,
			    sizeof(mint_union_case) * (i+1));
	return i;
}

#if 0  /* currently unused, but might be used later */
static int xl_int(int min, unsigned range)
{
	unsigned int i;

        /* See if there's already a matching int defined.  */
        for (i = 0; i < out_mint.defs.defs_len; i++)
        {
                if ((m(i).kind == MINT_INTEGER)
                    && (m(i).mint_def_u.integer_def.min == min)
                    && (m(i).mint_def_u.integer_def.range == range))
                {
                        fprintf(stderr, "Returning dup int %d.\n", i);
                        return i;
                }
        }

        /* If not, create one.  */
        i = get_def();
        m(i).kind = MINT_INTEGER;
        m(i).mint_def_u.integer_def.min = min;
        m(i).mint_def_u.integer_def.range = range;
        return i;
}
#endif /* 0 */

#if 0  /* currently unused, but might be used later */
/* translate array, taking min and length args */
static int xl_array_minlen(mint_ref type_d, int min, unsigned len)
{
	mint_ref length_d;
        int i;

	/* Find/produce a datatype representing the possible array lengths.  */
	length_d = xl_int(min, len);

        /* See if there's already a matching array defined.  */
        for (i = 0; i < out_mint.defs.defs_len; i++)
        {
                if ((m(i).kind == MINT_ARRAY)
                    && (m(i).mint_def_u.array_def.element_type == type_d)
                    && (m(i).mint_def_u.array_def.length_type == length_d))
                {
                        fprintf(stderr, "returning dup array %d.\n", i);
                        return i;
                }
        }

        /* If not, create one.  */
        i = get_def();
        m(i).kind = MINT_ARRAY;

        m(i).mint_def_u.array_def.element_type = type_d;
        m(i).mint_def_u.array_def.length_type = length_d;
        return i;
}
#endif


/* auxiliarly, helper routines (not taken from mom/fe/sun/xlate.c) */

/* Return a new union, as in get_union_def() but with a discriminator type
   given as an argument (rather than assuming a 32-bit integer type). */
static mint_ref
get_union_def_given_discriminator_type(int len, mint_ref discriminator_type)
{
	mint_ref r = get_def();
	m(r).kind = MINT_UNION;
	m(r).mint_def_u.union_def.discrim = discriminator_type;
	m(r).mint_def_u.union_def.cases.cases_len = len;
	m(r).mint_def_u.union_def.cases.cases_val =
		mustmalloc(len ? len*sizeof(mint_union_case) : 1);
	m(r).mint_def_u.union_def.dfault = mint_ref_null;
	return r;
}

/* End of file. */



syntax highlighted by Code2HTML, v. 0.9.1