/*
 * Copyright (c) 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 <assert.h>

#include <mom/libmint.h>
#include <mom/c/libcast.h>
#include <mom/c/pbe.hh>
#include <mom/compiler.h>

/*
 * This routine handles an allocation context.
 */
void mu_state::mu_inline_allocation_context(inline_state *ist,
					    mint_ref itype,
					    pres_c_inline inl)
{
	/* Set the default length type to be an unsigned 32-bit integer. */
	mint_ref lenref = pres->mint.standard_refs.unsigned32_ref;
	mint_ref boolref = pres->mint.standard_refs.bool_ref;
	/* Set the default element type to be the current itype. */
	mint_ref elemref = itype;
	pres_c_inline_allocation_context *acinl
		= &(inl->pres_c_inline_u_u.acontext);
	
	/* Get the length of arrays. */
	assert(itype >= 0);
	assert(itype < (signed int) pres->mint.defs.defs_len);
	mint_def *idef = &(pres->mint.defs.defs_val[itype]);

	/* For arrays, we can determine the length and element itypes. */
	if (idef->kind == MINT_ARRAY) {
		lenref = idef->mint_def_u.array_def.length_type;
		elemref = idef->mint_def_u.array_def.element_type;
	}
	/* For MINT_VOIDs, we are strictly allocating or deallocating.
	   All refs we pass down will also be MINT_VOIDs. */
	if (idef->kind == MINT_VOID) {
		lenref = boolref = elemref = pres->mint.standard_refs.void_ref;
	}
	
	/* Setup an arglist for this context, named after the context. */
	mu_state_arglist *oldlist = arglist;
	arglist = new mu_state_arglist(acinl->arglist_name, oldlist);
	arglist->add(acinl->arglist_name,
		     "offset");    /* a.k.a. the first element of the array */
	arglist->add(acinl->arglist_name,
		     "length");    /* a.k.a. the # of items in the array */
	arglist->add(acinl->arglist_name,
		     "min_len");   /* a.k.a. the hard minimum length */
	arglist->add(acinl->arglist_name,
		     "max_len");   /* a.k.a. the hard maximum length */
	arglist->add(acinl->arglist_name,
		     "alloc_len"); /* a.k.a. the allocated length */
	arglist->add(acinl->arglist_name,
		     "min_alloc_len"); /* a.k.a. the min allocated length */
	arglist->add(acinl->arglist_name,
		     "max_alloc_len"); /* a.k.a. the max allocated length */
	arglist->add(acinl->arglist_name,
		     "release");   /* a.k.a. the owned buffer release flag */
	arglist->add(acinl->arglist_name,
		     "terminator");/* a.k.a. the buffer's termination value */
	arglist->add(acinl->arglist_name,
		     "mustcopy");  /* a.k.a. the must-copy-to-keep flag */
	
	/*
	 * Here we set up the `inline_alloc_context' to communicate more
	 * semantic allocation information down to mu_pointer_alloc() and
	 * mu_pointer_dealloc() (eventually called from one of our child nodes,
	 * such as a mapping_internal_array or mapping_pointer).
	 */
	mu_inline_alloc_context ac;
	ac.name = acinl->arglist_name;
	ac.overwrite = acinl->overwrite;
	ac.owner = acinl->owner;
	ac.alloc = &acinl->alloc;
	ac.parent_context = inline_alloc_context;
	inline_alloc_context = &ac;
	
	/*
	 * Here we (optionally) marshal/unmarshal the inlines within the
	 * allocation context.  Each inline that exists should contain an
	 * appropriate PRES_C_MAPPING_ARGUMENT, so the environment we just set
	 * up can be filled in and provide an ``environment'' or ``context''
	 * for the sub inline below us (usually an array of some sort).  This
	 * allows the allocation semantics to have more complete knowledge of
	 * what's really going on.
	 *
	 * Note: The length is not an optional inline; it must ALWAYS exist.
	 */
	cast_expr cexpr = 0;
	cast_type ctype = 0;
	
	/* Set the flag to indicate we're handling length entities. */
	ac.is_length = 1;
	
	if (acinl->offset) {
		mu_inline(ist, lenref, acinl->offset);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "length",
					&cexpr, &ctype) && cexpr && ctype);
	}
	assert(acinl->length);
	mu_inline(ist, lenref, acinl->length);
	/* Make sure we defined the argument. */
	assert(arglist->getargs(acinl->arglist_name, "length",
				&cexpr, &ctype) && cexpr && ctype);
	if (acinl->min_len) {
		mu_inline(ist, lenref, acinl->min_len);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "min_len",
					&cexpr, &ctype) && cexpr && ctype);
	}
	if (acinl->max_len) {
		mu_inline(ist, lenref, acinl->max_len);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "max_len",
					&cexpr, &ctype) && cexpr && ctype);
	}
	if (acinl->alloc_len) {
		mu_inline(ist, lenref, acinl->alloc_len);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "alloc_len",
					&cexpr, &ctype) && cexpr && ctype);
	}
	if (acinl->min_alloc_len) {
		mu_inline(ist, lenref, acinl->min_alloc_len);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "min_alloc_len",
					&cexpr, &ctype) && cexpr && ctype);
	}
	if (acinl->max_alloc_len) {
		mu_inline(ist, lenref, acinl->max_alloc_len);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "max_alloc_len",
					&cexpr, &ctype) && cexpr && ctype);
	}
	
	/* Done handling length entities, reset the flag. */
	ac.is_length = 0;
	
	if (acinl->release) {
		mu_inline(ist, boolref, acinl->release);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "release",
					&cexpr, &ctype) && cexpr && ctype);
	}
	if (acinl->terminator) {
		mu_inline(ist, elemref, acinl->terminator);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "terminator",
					&cexpr, &ctype) && cexpr && ctype);
	}
	if (acinl->mustcopy) {
		mu_inline(ist, boolref, acinl->mustcopy);
		/* Make sure we defined the argument. */
		assert(arglist->getargs(acinl->arglist_name, "mustcopy",
					&cexpr, &ctype) && cexpr && ctype);
	}
	
	/* Marshal/unmarshal the array/pointer contents. */
	mu_inline(ist, itype, acinl->ptr);
	
	/*
	 * Restore the old `inline_alloc_context' and old `arglist'.
	 */
	assert(inline_alloc_context == &ac);
	inline_alloc_context = ac.parent_context;
	delete arglist;
	arglist = oldlist;
}

/* End of file. */



syntax highlighted by Code2HTML, v. 0.9.1