/*
* Copyright (c) 1998, 1999 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software is hereby
* granted provided that (1) source code retains these copyright, permission,
* and disclaimer notices, and (2) redistributions including binaries
* reproduce the notices in supporting documentation.
*
* THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
* IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
* ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* CSL requests users of this software to return to csl-dist@cs.utah.edu any
* improvements that they make and grant CSL redistribution rights.
*/
/*
* ANY CHANGES TO THIS FILE MUST BE MADE TO `corba-excepts.c' IN ALL LINK LIBS!
* IT IS IDENTICAL IN ALL LINK LIBS --- EXCEPT THAT THE INCLUDED LINK HEADER
* DIFFERS FROM ONE RUNTIME TO THE NEXT.
*/
/*
* This file contains functions that are required when using CORBA
* presentation.
*/
#include <flick/link/iiop.h>
#include <flick/pres/corba.h>
/*****************************************************************************/
/*
* We allocate CORBA system exception structures out of a static array, called
* the `system_exception_buffer'. This allows us, for instance, to produce a
* CORBA_NO_MEMORY exception without needing to allocate memory for the
* exception structure at runtime.
*/
#define FLICK_SYSTEM_EXCEPTION_BUFFER_SIZE (16)
static int
system_exception_slot_used[FLICK_SYSTEM_EXCEPTION_BUFFER_SIZE]
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static flick_system_exception
system_exception_buffer[FLICK_SYSTEM_EXCEPTION_BUFFER_SIZE];
/* Index of the last-allocated table element. */
static int
system_exception_index = 0;
/*
* Allocate a system exception structure from the table of exception structs.
*/
flick_system_exception *
flick_system_exception_alloc()
{
int i;
for (;;) {
for (i = 1; (i <= FLICK_SYSTEM_EXCEPTION_BUFFER_SIZE); i++)
if (!system_exception_slot_used[
((system_exception_index + i)
% FLICK_SYSTEM_EXCEPTION_BUFFER_SIZE)]) {
goto found;
}
/* XXX --- sleep, wait for slot to open up. */
}
found:
system_exception_index = (system_exception_index + i)
% FLICK_SYSTEM_EXCEPTION_BUFFER_SIZE;
system_exception_slot_used[system_exception_index] = 1;
return &(system_exception_buffer[system_exception_index]);
}
/*
* Free a system exception structure.
*/
void
flick_system_exception_free(void *system_except)
{
int i;
if ((((flick_system_exception *) system_except)
< &(system_exception_buffer[0]))
|| (((flick_system_exception *) system_except)
> &(system_exception_buffer[FLICK_SYSTEM_EXCEPTION_BUFFER_SIZE
- 1]))
) {
/*
* `system_except' doesn't point into `system_exception_buffer'
* so warn and return.
*/
fprintf(stderr,
"Warning: "
"attempt to free invalid system exception.\n");
return;
}
i = ((flick_system_exception *) system_except)
- system_exception_buffer;
system_exception_slot_used[i] = 0;
}
/*****************************************************************************/
/*
* Just as we keep a table of system exception structures, we also keep a table
* of system exception identifiers (names).
*/
/*
* Return a CORBA-runtime-managed string that is equal to `name'; i.e., intern
* the `name' and return the interned version.
*
* The returned string may be statically allocated; it may be returned many
* times by different invocations of this function; it may not be modified or
* freed by the caller.
*/
char *
find_system_exception_id(char *name, int size)
{
static char **table = 0;
static int count = 0, max = 0;
int i;
/*
* If `name' matches a known CORBA system exception, return a
* statically allocated string.
*/
#define if_return(exname) if(!strcmp(name, ex_##exname)) return ex_##exname
if_return(CORBA_UNKNOWN);
if_return(CORBA_BAD_PARAM);
if_return(CORBA_NO_MEMORY);
if_return(CORBA_IMP_LIMIT);
if_return(CORBA_COMM_FAILURE);
if_return(CORBA_INV_OBJREF);
if_return(CORBA_NO_PERMISSION);
if_return(CORBA_INTERNAL);
if_return(CORBA_MARSHAL);
if_return(CORBA_INITIALIZE);
if_return(CORBA_NO_IMPLEMENT);
if_return(CORBA_BAD_TYPECODE);
if_return(CORBA_BAD_OPERATION);
if_return(CORBA_NO_RESOURCES);
if_return(CORBA_NO_RESPONSE);
if_return(CORBA_PERSIST_STORE);
if_return(CORBA_BAD_INV_ORDER);
if_return(CORBA_TRANSIENT);
if_return(CORBA_FREE_MEM);
if_return(CORBA_INV_IDENT);
if_return(CORBA_INV_FLAG);
if_return(CORBA_INTF_REPOS);
if_return(CORBA_BAD_CONTEXT);
if_return(CORBA_OBJ_ADAPTER);
if_return(CORBA_DATA_CONVERSION);
if_return(CORBA_OBJECT_NOT_EXIST);
if_return(CORBA_TRANSACTION_REQUIRED);
if_return(CORBA_TRANSACTION_ROLLEDBACK);
if_return(CORBA_INVALID_TRANSACTION);
/*
* Otherwise, we must search our table and possibly add a copy of
* `name' to the table.
*/
for (i = 0; i < count; i++)
if (!strcmp(table[i], name)) return table[i];
/* Add a copy of `name' to the table. */
if (count >= max) {
int new_max = max + 10;
char **new_table = t_realloc(table, char *, new_max);
if (!new_table) {
fprintf(stderr,
"Error: can't allocate space for "
"system exception identifier.\n");
/* XXX --- Is this a reasonable thing to do? */
return ex_CORBA_NO_MEMORY;
}
table = new_table;
max = new_max;
}
table[count] = t_malloc(char, size);
if (!table[count]) {
fprintf(stderr,
"Error: can't allocate space for "
"system exception identifier.\n");
/* XXX --- Is this a reasonable thing to do? */
return ex_CORBA_NO_MEMORY;
}
i = count++;
strncpy(table[i], name, size);
return table[i];
}
/*****************************************************************************/
/*
* Here are functions for translating between Flick's internal error codes and
* CORBA exception identifiers.
*/
/*
* Translate a Flick internal error code into a CORBA system exception id.
*
* At one time, this error --> id translation was implemented as a macro in
* <flick/pres/corba.h>: since the `errval' argument is always known at compile
* time, the CORBA system exception id can be determined at compile time, too.
* But it's not a big win to have this be a macro; exceptions are supposed to
* be exceptional.
*/
char *
flick_error_to_CORBA_exception_id(int errval)
{
switch (errval) {
default: return ex_CORBA_UNKNOWN;
case FLICK_ERROR_CONSTANT: return ex_CORBA_MARSHAL;
case FLICK_ERROR_VIRTUAL_UNION: return ex_CORBA_UNKNOWN;
case FLICK_ERROR_STRUCT_UNION: return ex_CORBA_BAD_PARAM;
case FLICK_ERROR_DECODE_SWITCH: return ex_CORBA_BAD_OPERATION;
case FLICK_ERROR_COLLAPSED_UNION: return ex_CORBA_BAD_OPERATION;
case FLICK_ERROR_VOID_UNION: return ex_CORBA_UNKNOWN;
case FLICK_ERROR_COMMUNICATION: return ex_CORBA_COMM_FAILURE;
case FLICK_ERROR_OUT_OF_BOUNDS: return ex_CORBA_BAD_PARAM;
case FLICK_ERROR_INVALID_TARGET: return ex_CORBA_INV_OBJREF;
case FLICK_ERROR_NO_MEMORY: return ex_CORBA_NO_MEMORY;
}
}
/*****************************************************************************/
/*
* This section contains the CORBA-specified functions for managing exceptions.
*/
/*
* Define the allocators for the standard CORBA exceptions.
*/
#define sys_except__alloc(name) \
name *name##__alloc() { return (name *) flick_system_exception_alloc(); }
sys_except__alloc(CORBA_UNKNOWN)
sys_except__alloc(CORBA_BAD_PARAM)
sys_except__alloc(CORBA_NO_MEMORY)
sys_except__alloc(CORBA_IMP_LIMIT)
sys_except__alloc(CORBA_COMM_FAILURE)
sys_except__alloc(CORBA_INV_OBJREF)
sys_except__alloc(CORBA_NO_PERMISSION)
sys_except__alloc(CORBA_INTERNAL)
sys_except__alloc(CORBA_MARSHAL)
sys_except__alloc(CORBA_INITIALIZE)
sys_except__alloc(CORBA_NO_IMPLEMENT)
sys_except__alloc(CORBA_BAD_TYPECODE)
sys_except__alloc(CORBA_BAD_OPERATION)
sys_except__alloc(CORBA_NO_RESOURCES)
sys_except__alloc(CORBA_NO_RESPONSE)
sys_except__alloc(CORBA_PERSIST_STORE)
sys_except__alloc(CORBA_BAD_INV_ORDER)
sys_except__alloc(CORBA_TRANSIENT)
sys_except__alloc(CORBA_FREE_MEM)
sys_except__alloc(CORBA_INV_IDENT)
sys_except__alloc(CORBA_INV_FLAG)
sys_except__alloc(CORBA_INTF_REPOS)
sys_except__alloc(CORBA_BAD_CONTEXT)
sys_except__alloc(CORBA_OBJ_ADAPTER)
sys_except__alloc(CORBA_DATA_CONVERSION)
sys_except__alloc(CORBA_OBJECT_NOT_EXIST)
sys_except__alloc(CORBA_TRANSACTION_REQUIRED)
sys_except__alloc(CORBA_TRANSACTION_ROLLEDBACK)
sys_except__alloc(CORBA_INVALID_TRANSACTION)
#undef sys_except__alloc
/*
* CORBA::ORB::InvalidName is a user exception raised by `resolve_initial_
* references'; see Section 17.29 of the CORBA 2.1 spec.
*/
CORBA_ORB_InvalidName *
CORBA_ORB_InvalidName__alloc()
{
/*
* A `CORBA::ORB::InvalidName' has no exception data, but the mapped C
* structure contains one (dummy) field, because C structures must have
* at least one member.
*
* But: presumably, if one of these is allocated, the reason is so that
* it may be passed to `CORBA_BOA_set_exception'. But Section 17.27.2
* of the CORBA 2.1 specification says that if the exception has no
* members, then the passed pointer-to-exception-struct must be null.
*
* So: we return null here, so that one may use a consistent technique
* to allocate exceptions to pass to `CORBA_BOA_set_exception', without
* suffering possible memory leakage.
*/
return 0;
/*
* (CORBA_ORB_InvalidName *) CORBA_alloc(sizeof CORBA_ORB_InvalidName);
*/
}
/*
* This function returns the value of an exception. It could be a macro.
*/
void *
CORBA_exception_value(CORBA_Environment *ev)
{
if (ev->_major == CORBA_SYSTEM_EXCEPTION)
return &((ev)->_value._system_except);
else
return (ev)->_value._user_except;
}
/*
* Here is the function that one calls in order to signal an exception. See
* Section 17.27.2 of the CORBA 2.1 specification.
*
* The `exceptname' is considered to be a static or ``interned'' string, e.g.,
* ex_NAME, and is therefore not copied. (Nor is it freed later on; see
* `CORBA_exception_free'.)
*
* System exceptions are handled specially: the `minor' and `completed' values
* are copied directly into the `CORBA_Environment' structure, thus avoiding
* any need to allocate memory when throwing a system (e.g., CORBA_NO_MEMORY)
* exception. When signaling a system exception, `param' MUST have been
* allocated using one of the standard CORBA system exception allocators (e.g.,
* `CORBA_NO_MEMORY__alloc').
*
* In all cases, the `param' becomes ``owned'' by the environment structure,
* and therefore doesn't need to be copied. The runtime will take care of
* freeing the storage (either now in the case of system exceptions, or later
* in the case of user exceptions --- see `CORBA_exception_free').
*/
void
CORBA_BOA_set_exception(CORBA_BOA boa, CORBA_Environment *ev,
CORBA_exception_type major,
CORBA_char *exceptname, void *param)
{
ev->_major = major;
ev->_id = exceptname;
switch (major) {
case CORBA_SYSTEM_EXCEPTION:
ev->_value._system_except.minor
= ((flick_system_exception *) param)->minor;
ev->_value._system_except.completed
= ((flick_system_exception *) param)->completed;
/*
* We've copied the fields into the environment, so we can
* now free the system exception structure.
*/
flick_system_exception_free(param);
break;
case CORBA_USER_EXCEPTION:
ev->_value._user_except = param;
/* `param' will be freed later by `CORBA_excpetion_free'. */
break;
case CORBA_NO_EXCEPTION:
/* assert(param == 0); */
ev->_value._user_except = 0;
break;
default:
fprintf(stderr,
("Warning: invalid exception type (value = %d) "
"passed to `CORBA_BOA_set_exception'.\n"),
major);
/* User code blew it! Manufacture a system exception. */
ev->_major = CORBA_SYSTEM_EXCEPTION;
ev->_id = ex_CORBA_BAD_PARAM;
ev->_value._system_except.minor = 0;
ev->_value._system_except.completed = CORBA_COMPLETED_MAYBE;
break;
}
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1