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

#include <mom/compiler.h>
#include <mom/libaoi.h>
#include <mom/c/pfe.hh>
#include <mom/c/libcast.h>
#include <mom/c/libpres_c.h>

#include "pg_sun.hh"

/*
 * This method determines how `p_param' processes a parameter type.
 */
void pg_sun::p_param_type(aoi_type at, mint_ref /* mr */, aoi_direction dir,
			  cast_type *out_ctype, pres_c_mapping *out_mapping)
{
	/*
	 * `real_at' is the ``concrete'' AOI type referenced by `at'.  If `at'
	 * is an `AOI_INDIRECT', `real_at' is the type referenced through the
	 * indirection.
	 */
	aoi_type real_at;
	
	/*
	 * `is_string' and `is_array' are flags indicating that the AOI type at
	 * hand is being presented as an C string or array, respectively.
	 */
	int is_string, is_array;
	
	/*********************************************************************/
	
	/*
	 * The library verion of this method checks for `inout' and `out'
	 * parameters at this point.  However, Sun RPC doesn't allow for these
	 * parameter types.
	 */
	assert(dir == AOI_DIR_IN);
	
	/*
	 * Get the basic presentation for this type: the `out_ctype' and the
	 * `out_mapping'.
	 */
	p_type_collection *ptc = 0;
	p_type_node *ptn;
	
	p_type(at, &ptc);
	ptn = ptc->find_type("definition");
	*out_ctype = ptn->get_type();
	*out_mapping = ptn->get_mapping();
	
	/*
	 * Get the actual AOI type (not an AOI_INDIRECT type).  If the actual
	 * AOI type is an AOI_ARRAY, determine if it corresponds to an ONC RPC
	 * string or fixed-length array.
	 */
	real_at = at;
	while (real_at->kind == AOI_INDIRECT)
		real_at = in_aoi->defs.
			defs_val[real_at->aoi_type_u_u.indirect_ref].binding;
	
	if (real_at->kind == AOI_ARRAY) {
		unsigned int min, max;
		
		aoi_get_array_len(in_aoi, &(real_at->aoi_type_u_u.array_def),
				  &min, &max);
		
		is_string   = (real_at->aoi_type_u_u.array_def.flgs
			       == AOI_ARRAY_FLAG_NULL_TERMINATED_STRING);
		is_array    = ((min == max) && !is_string);
	} else {
		is_string = 0;
		is_array = 0;
	}
	
	/*
	 * Now determine the C type of this parameter.
	 */
	if (is_array)
		/*
		 * Do nothing.  IDL arrays are presented as C arrays, which are
		 * automatically passed by reference.
		 */
		;
	else {
		/*
		 * Otherwise, interpose an indirection pointer so that the
		 * parameter will be passed by reference:
		 *   Client side never allocs nor deallocs.
		 *   Server side always allocs and deallocs.
		 *
		 * I think it is surprising that `rpcgen' doesn't omit this
		 * ``extra'' pointer before string types (which are presented
		 * as `char *'s) and optional types (which are presented as
		 * pointers).
		 */
		pres_c_allocation alloc;
		alloc.cases[PRES_C_DIRECTION_IN].allow
			= PRES_C_ALLOCATION_ALLOW;
		/* Let the back end choose the allocator. */
		alloc.cases[PRES_C_DIRECTION_IN].pres_c_allocation_u_u.val.
			allocator.kind = PRES_C_ALLOCATOR_DONTCARE;
		alloc.cases[PRES_C_DIRECTION_IN].pres_c_allocation_u_u.val.
			alloc_init = 0;
		
		if (gen_client) {
			alloc.cases[PRES_C_DIRECTION_IN].
				pres_c_allocation_u_u.val.flags
				= PRES_C_ALLOC_NEVER | PRES_C_DEALLOC_NEVER;
		} else if (gen_server) {
			alloc.cases[PRES_C_DIRECTION_IN].
				pres_c_allocation_u_u.val.flags
				= PRES_C_ALLOC_ALWAYS | PRES_C_DEALLOC_ALWAYS;
		} else
			panic("In `pg_sun::p_param_type', "
			      "generating neither client nor server.");
		
		/* All other allocation cases are invalid. */
		alloc.cases[PRES_C_DIRECTION_UNKNOWN].allow
			= PRES_C_ALLOCATION_INVALID;
		alloc.cases[PRES_C_DIRECTION_INOUT].allow
			= PRES_C_ALLOCATION_INVALID;
		alloc.cases[PRES_C_DIRECTION_OUT].allow
			= PRES_C_ALLOCATION_INVALID;
		alloc.cases[PRES_C_DIRECTION_RETURN].allow
			= PRES_C_ALLOCATION_INVALID;
		
		pres_c_interpose_indirection_pointer(out_ctype, out_mapping,
						     alloc);
	}
	
	/*
	 * Tell the back end that this is the ``root'' of the parameter.
	 */
	pres_c_interpose_param_root(out_mapping, 0, 0);
	
	/*
	 * Finally, wrap the mapping in a `hint' that tells the back end what
	 * kind of parameter this is: `in', `out', etc.
	 */
	pres_c_interpose_direction(out_mapping, dir);
}

/* End of file. */



syntax highlighted by Code2HTML, v. 0.9.1