/* -*- mode: C++; c-file-style: "bsd" -*- */
#include "errors.h"
#include "porbit-perl.h"
typedef struct _SystemExceptionRec SystemExceptionRec;
typedef struct _BuiltinExceptionRec BuiltinExceptionRec;
struct _SystemExceptionRec {
char *repoid;
char *package;
char *text;
};
struct _BuiltinExceptionRec {
char *repoid;
char *package;
};
static SystemExceptionRec system_exceptions[] = {
{ "IDL:omg.org/CORBA/SystemException:1.0",
"CORBA::SystemException",
"Unspecified system exception" },
{ "IDL:omg.org/CORBA/UNKNOWN:1.0",
"CORBA::UNKNOWN",
"The unknown exception" },
{ "IDL:omg.org/CORBA/BAD_PARAM:1.0",
"CORBA::BAD_PARAM",
"An invalid parameter was passed" },
{ "IDL:omg.org/CORBA/NO_MEMORY:1.0",
"CORBA::NO_MEMORY",
"Dynamic memory allocation failure" },
{ "IDL:omg.org/CORBA/IMP_LIMIT:1.0",
"CORBA::IMP_LIMIT",
"Violated implementation limit" },
{ "IDL:omg.org/CORBA/COMM_FAILURE:1.0" ,
"CORBA::COMM_FAILURE",
"Communication failure" },
{ "IDL:omg.org/CORBA/INV_OBJREF:1.0",
"CORBA::INV_OBJREF",
"Invalid object reference" },
{ "IDL:omg.org/CORBA/NO_PERMISSION:1.0",
"CORBA::NO_PERMISSION",
"No permission for attempted operation" },
{ "IDL:omg.org/CORBA/INTERNAL:1.0",
"CORBA::INTERNAL",
"ORB internal error" },
{ "IDL:omg.org/CORBA/MARSHAL:1.0",
"CORBA::MARSHAL",
"Error marshalling parameter or result" },
{ "IDL:omg.org/CORBA/INITIALIZE:1.0",
"CORBA::INITIALIZE",
"ORB initialization failure" },
{ "IDL:omg.org/CORBA/NO_IMPLEMENT:1.0",
"CORBA::NO_IMPLEMENT",
"Operation implementation unavailable" },
{ "IDL:omg.org/CORBA/BAD_TYPECODE:1.0",
"CORBA::BAD_TYPECODE",
"Bad typecode" },
{ "IDL:omg.org/CORBA/BAD_OPERATION:1.0",
"CORBA::BAD_OPERATION",
"Invalid operation" },
{ "IDL:omg.org/CORBA/NO_RESOURCES:1.0",
"CORBA::NO_RESOURCES",
"Insufficient resources for request" },
{ "IDL:omg.org/CORBA/NO_RESPONSE:1.0",
"CORBA::NO_RESPONSE",
"Response to request not yet available" },
{ "IDL:omg.org/CORBA/PERSIST_STORE:1.0",
"CORBA::PERSIST_STORE",
"Persistant storage failure" },
{ "IDL:omg.org/CORBA/BAD_INV_ORDER:1.0",
"CORBA::BAD_INV_ORDER",
"Routine invocations out of order" },
{ "IDL:omg.org/CORBA/TRANSIENT:1.0",
"CORBA::TRANSIENT",
"Transient failure - reissue request" },
{ "IDL:omg.org/CORBA/FREE_MEM:1.0",
"CORBA::FREE_MEM",
"Cannot free memory" },
{ "IDL:omg.org/CORBA/INV_IDENT:1.0",
"CORBA::INV_IDENT",
"Invalid identifier syntax" },
{ "IDL:omg.org/CORBA/INV_FLAG:1.0",
"CORBA::INV_FLAG",
"Invalid flag was specified" },
{ "IDL:omg.org/CORBA/INTF_REPOS:1.0",
"CORBA::INTF_REPOS",
"Error accessing interface repository" },
{ "IDL:omg.org/CORBA/BAD_CONTEXT:1.0",
"CORBA::BAD_CONTEXT",
"Error processing context" },
{ "IDL:omg.org/CORBA/OBJ_ADAPTER:1.0",
"CORBA::OBJ_ADAPTER",
"Failure detected by object adapter" },
{ "IDL:omg.org/CORBA/DATA_CONVERSION:1.0",
"CORBA::DATA_CONVERSION",
"Data conversion error" },
{ "IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0",
"CORBA::OBJECT_NOT_EXIST",
"Non-existent object, delete reference" },
{ "IDL:omg.org/CORBA/TRANSACTION_REQUIRED:1.0",
"CORBA::TRANSACTION_REQUIRED",
"Transaction required" },
{ "IDL:omg.org/CORBA/TRANSACTION_ROLLEDBACK:1.0",
"CORBA::TRANSACTION_ROLLEDBACK",
"Transaction rolled back" },
{ "IDL:omg.org/CORBA/INVALID_TRANSACTION:1.0",
"CORBA::INVALID_TRANSACTION",
"Invalid transaction" },
};
static const int num_system_exceptions =
sizeof(system_exceptions)/sizeof(SystemExceptionRec);
static BuiltinExceptionRec builtin_exceptions[] = {
{ "IDL:omg.org/PortableServer/POA/AdapterAlreadyExists:1.0",
"PortableServer::POA::AdapterAlreadyExists" },
{ "IDL:omg.org/PortableServer/POA/AdapterInactive:1.0",
"PortableServer::POA::AdapterInactive" },
{ "IDL:omg.org/PortableServer/POA/AdapterNonExistant:1.0",
"PortableServer::POA::AdapterNonExistant" },
{ "IDL:omg.org/PortableServer/POA/InvalidPolicy:1.0",
"PortableServer::POA::InvalidPolicy" },
{ "IDL:omg.org/PortableServer/POA/NoServant:1.0",
"PortableServer::POA::NoServant" },
{ "IDL:omg.org/PortableServer/POA/ObjectAlreadyActive:1.0",
"PortableServer::POA::ObjectAlreadyActive" },
{ "IDL:omg.org/PortableServer/POA/ObjectNotActive:1.0",
"PortableServer::POA::ObjectNotActive" },
{ "IDL:omg.org/PortableServer/POA/ServantAlreadyActive:1.0",
"PortableServer::POA::ServantAlreadyActive" },
{ "IDL:omg.org/PortableServer/POA/ServantNotActive:1.0",
"PortableServer::POA::ServantNotActive" },
{ "IDL:omg.org/PortableServer/POA/WrongAdapter:1.0",
"PortableServer::POA::WrongAdapter" },
{ "IDL:omg.org/PortableServer/POA/WrongPolicy:1.0",
"PortableServer::POA::WrongPolicy" },
{ "IDL:omg.org/PortableServer/POAManager/AdapterInactive:1.0",
"PortableServer::POAManager::AdapterInactive" },
{ "IDL:omg.org/PortableServer/Current/NoContext:1.0",
"PortableServer::Current::NoContext" },
{ "IDL:omg.org/CORBA/TypeCode/Bounds:1.0",
"CORBA::TypeCode::Bounds" },
{ "IDL:omg.org/CORBA/TypeCode/BadKind:1.0",
"CORBA::TypeCode::BadKind" },
};
static const int num_builtin_exceptions =
sizeof(builtin_exceptions)/sizeof(BuiltinExceptionRec);
static HV *exceptions_hv;
/* Takes ownership of exception object
*/
void
porbit_throw (SV *e)
{
dSP;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(e));
PUTBACK;
perl_call_pv("Error::throw", G_DISCARD);
fprintf(stderr,"panic: Exception throw returned!");
exit(1);
SPAGAIN;
FREETMPS;
LEAVE;
}
const char *
porbit_find_exception (const char *repoid)
{
dTHR;
SV **svp;
if (!exceptions_hv)
return NULL;
svp = hv_fetch (exceptions_hv, (char *)repoid, strlen(repoid), 0);
if (!svp)
return NULL;
return SvPV(*svp, PL_na);
}
void
porbit_setup_exception (const char *repoid, const char *pkg,
const char *parent)
{
char *varname;
SV *sv;
AV *av;
if (!exceptions_hv)
exceptions_hv = newHV();
/* Check if this package has been set up (FIXME: this isn't really
* necessary, since we do it in define_exception)
*/
if (porbit_find_exception (repoid))
return;
varname = g_strconcat (pkg, "::_repoid", NULL);
sv = perl_get_sv (varname, TRUE);
sv_setsv (sv, newSVpv((char *)repoid, 0));
g_free (varname);
varname = g_strconcat (pkg, "::ISA", NULL);
av = perl_get_av (varname, TRUE);
av_push (av, newSVpv((char *)parent, 0));
g_free (varname);
hv_store (exceptions_hv, (char *)repoid, strlen(repoid),
newSVpv((char *)pkg, 0), 0);
}
void
porbit_init_exceptions (void)
{
int i;
for (i=1; i<num_system_exceptions; i++) {
porbit_setup_exception (system_exceptions[i].repoid,
system_exceptions[i].package,
"CORBA::SystemException");
}
for (i=1; i<num_builtin_exceptions; i++) {
porbit_setup_exception (builtin_exceptions[i].repoid,
builtin_exceptions[i].package,
"CORBA::UserException");
}
porbit_setup_exception ("IDL:omg.org/CORBA/SystemException:1.0",
"CORBA::SystemException",
"CORBA::Exception");
porbit_setup_exception ("IDL:omg.org/CORBA/UserException:1.0",
"CORBA::UserException",
"CORBA::Exception");
}
SV *
porbit_system_except (const char *repoid, CORBA_unsigned_long minor,
CORBA_completion_status status)
{
char *pkg = NULL;
char *text = NULL;
int i;
SV *tmp_sv;
char *status_str;
char *tmp_str = NULL;
int count;
dSP;
/* HACK: ORBit omits the omg.org from repoid names */
if (strncmp (repoid, "IDL:CORBA", 9) == 0) {
tmp_str = g_strconcat ("IDL:omg.org/", repoid + 4, NULL);
repoid = tmp_str;
}
for (i=0; i<num_system_exceptions; i++) {
if (!strcmp(repoid, system_exceptions[i].repoid)) {
pkg = system_exceptions[i].package;
text = system_exceptions[i].text;
break;
}
}
if (tmp_str)
g_free (tmp_str);
if (!pkg) {
pkg = system_exceptions[0].package;
text = system_exceptions[0].text;
}
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSVpv(pkg, 0)));
XPUSHs(sv_2mortal(newSVpv("-text", 0)));
XPUSHs(sv_2mortal(newSVpv(text, 0)));
XPUSHs(sv_2mortal(newSVpv("-minor",0)));
tmp_sv = newSV(0);
sv_setuv (tmp_sv, minor);
XPUSHs(sv_2mortal(tmp_sv));
XPUSHs(sv_2mortal(newSVpv("-status",0)));
switch (status) {
case CORBA_COMPLETED_YES:
status_str = "COMPLETED_YES";
break;
case CORBA_COMPLETED_NO:
status_str = "COMPLETED_NO";
break;
case CORBA_COMPLETED_MAYBE:
status_str = "COMPLETED_MAYBE";
break;
}
XPUSHs(sv_2mortal(newSVpv(status_str, 0)));
PUTBACK;
count = perl_call_method("new", G_SCALAR);
SPAGAIN;
if (count != 1) {
while (count--)
(void)POPs;
PUTBACK;
croak("Exception constructor returned wrong number of items");
}
tmp_sv = POPs;
PUTBACK;
return newSVsv(tmp_sv);
}
SV *
porbit_user_except (const char *repoid, SV *value)
{
dSP;
const char *pkg;
int count;
SV *tmp_sv;
if (value)
sv_2mortal(value);
pkg = porbit_find_exception (repoid);
if (!pkg)
return porbit_system_except ( "IDL:omg.org/CORBA/UNKNOWN:1.0",
0, CORBA_COMPLETED_MAYBE );
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSVpv((char *)pkg, 0)));
if (value) {
XPUSHs(value);
}
PUTBACK;
count = perl_call_method("new", G_SCALAR);
SPAGAIN;
if (count != 1) {
while (count--)
(void)POPs;
PUTBACK;
croak("Exception constructor returned wrong number of items");
}
tmp_sv = POPs;
PUTBACK;
return newSVsv(tmp_sv);
}
SV *
porbit_builtin_except (CORBA_Environment *ev)
{
const char *repoid = CORBA_exception_id (ev);
CORBA_SystemException *sysex;
switch (ev->_major) {
case CORBA_NO_EXCEPTION:
return NULL;
case CORBA_USER_EXCEPTION:
if (!strcmp (repoid, ex_PortableServer_POA_InvalidPolicy)) {
PortableServer_POA_InvalidPolicy *ipex =
(PortableServer_POA_InvalidPolicy *)CORBA_exception_value (ev);
AV *av = newAV();
av_push(av, newSVpv("index", 0));
av_push(av, newSViv(ipex->index));
return porbit_user_except (repoid, (SV *)av);
} else
return porbit_user_except (repoid, (SV *)newAV());
default:
sysex = (CORBA_SystemException *)CORBA_exception_value (ev);
return porbit_system_except (repoid, sysex->minor, sysex->completed);
}
}