#include "config.h"
#include "orbit-idl-c-backend.h"
#include <string.h>
char *
orbit_cbe_get_typecode_name (IDL_tree tree)
{
if (!tree)
return g_strdup ("TC_FIXME");
else
return g_strconcat ("TC_", orbit_cbe_get_typespec_str (tree), NULL);
}
gboolean
orbit_cbe_type_is_builtin(IDL_tree tree)
{
return FALSE;
switch(IDL_NODE_TYPE(tree)) {
case IDLN_LIST:
case IDLN_GENTREE:
case IDLN_MEMBER:
case IDLN_NATIVE:
case IDLN_CASE_STMT:
case IDLN_MODULE:
case IDLN_BINOP:
case IDLN_UNARYOP:
case IDLN_CODEFRAG:
g_error("Strange type for being a builtin");
break;
case IDLN_INTEGER:
case IDLN_STRING:
case IDLN_WIDE_STRING:
case IDLN_CHAR:
case IDLN_WIDE_CHAR:
case IDLN_FIXED:
case IDLN_FLOAT:
case IDLN_BOOLEAN:
case IDLN_CONST_DCL:
case IDLN_TYPE_INTEGER:
case IDLN_TYPE_FLOAT:
case IDLN_TYPE_CHAR:
case IDLN_TYPE_WIDE_CHAR:
case IDLN_TYPE_STRING:
case IDLN_TYPE_WIDE_STRING:
case IDLN_TYPE_BOOLEAN:
case IDLN_TYPE_OCTET:
case IDLN_TYPE_ANY:
case IDLN_TYPE_OBJECT:
case IDLN_TYPE_TYPECODE:
case IDLN_TYPE_ENUM:
return TRUE;
break;
case IDLN_TYPE_DCL:
case IDLN_EXCEPT_DCL:
case IDLN_ATTR_DCL:
case IDLN_OP_DCL:
case IDLN_PARAM_DCL:
case IDLN_TYPE_FIXED:
case IDLN_TYPE_SEQUENCE:
case IDLN_TYPE_ARRAY:
case IDLN_TYPE_STRUCT:
case IDLN_TYPE_UNION:
case IDLN_IDENT:
case IDLN_INTERFACE:
case IDLN_FORWARD_DCL:
default:
return FALSE;
break;
}
return FALSE;
}
/**
Gets the "type" of {tree} as known in C.
The return value was alloc'd via g_malloc, and must be g_free'd.
**/
char *
orbit_cbe_get_typespec_str(IDL_tree tree)
{
char *retval = NULL;
GString *tmpstr = NULL;
if(!tree) {
return g_strdup("void");
}
switch(IDL_NODE_TYPE(tree)) {
case IDLN_MEMBER:
return orbit_cbe_get_typespec_str(IDL_MEMBER(tree).type_spec);
break;
case IDLN_TYPE_ANY:
retval = "CORBA_any";
break;
case IDLN_TYPE_FLOAT:
switch(IDL_TYPE_FLOAT(tree).f_type) {
case IDL_FLOAT_TYPE_FLOAT:
retval = "CORBA_float";
break;
case IDL_FLOAT_TYPE_DOUBLE:
retval = "CORBA_double";
break;
case IDL_FLOAT_TYPE_LONGDOUBLE:
retval = "CORBA_long_double";
break;
}
break;
case IDLN_TYPE_FIXED:
return g_strdup_printf( "CORBA_fixed_%" IDL_LL "d_%" IDL_LL "d",
IDL_INTEGER(IDL_TYPE_FIXED(tree).positive_int_const).value,
IDL_INTEGER(IDL_TYPE_FIXED(tree).integer_lit).value);
break;
case IDLN_TYPE_INTEGER:
tmpstr = g_string_new(NULL);
g_string_append(tmpstr, "CORBA_");
if(!IDL_TYPE_INTEGER(tree).f_signed)
g_string_append(tmpstr, "unsigned_");
switch(IDL_TYPE_INTEGER(tree).f_type) {
case IDL_INTEGER_TYPE_SHORT:
g_string_append(tmpstr, "short");
break;
case IDL_INTEGER_TYPE_LONGLONG:
g_string_append(tmpstr, "long_");
/* FALLTHROUGH */
case IDL_INTEGER_TYPE_LONG:
g_string_append(tmpstr, "long");
break;
}
break;
case IDLN_TYPE_STRING:
retval = "CORBA_string"; /* this is non-standard! */
break;
case IDLN_TYPE_OCTET:
retval = "CORBA_octet";
break;
case IDLN_TYPE_WIDE_STRING:
retval = "CORBA_wstring"; /* this is non-standard! */
break;
case IDLN_TYPE_CHAR:
retval = "CORBA_char";
break;
case IDLN_TYPE_WIDE_CHAR:
retval = "CORBA_wchar";
break;
case IDLN_TYPE_BOOLEAN:
retval = "CORBA_boolean";
break;
case IDLN_TYPE_STRUCT:
return orbit_cbe_get_typespec_str(IDL_TYPE_STRUCT(tree).ident);
case IDLN_EXCEPT_DCL:
return orbit_cbe_get_typespec_str(IDL_EXCEPT_DCL(tree).ident);
case IDLN_TYPE_ARRAY:
return orbit_cbe_get_typespec_str(IDL_TYPE_ARRAY(tree).ident);
case IDLN_TYPE_UNION:
return orbit_cbe_get_typespec_str(IDL_TYPE_UNION(tree).ident);
case IDLN_TYPE_ENUM:
return orbit_cbe_get_typespec_str(IDL_TYPE_ENUM(tree).ident);
case IDLN_IDENT:
return IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(tree), "_", 0);
case IDLN_PARAM_DCL:
return orbit_cbe_get_typespec_str(IDL_PARAM_DCL(tree).param_type_spec);
case IDLN_TYPE_SEQUENCE:
{
IDL_tree subtype = IDL_TYPE_SEQUENCE(tree).simple_type_spec;
char *ctmp, *base;
ctmp = orbit_cbe_get_typespec_str(subtype);
/* We should have built-in alias to make this next line not needed */
base = orbit_cbe_type_is_builtin(subtype)
? ctmp + strlen("CORBA_") : ctmp;
retval = g_strdup_printf( "CORBA_sequence_%s", base);
g_free(ctmp);
return retval;
}
break;
case IDLN_NATIVE:
retval = "gpointer";
break;
case IDLN_FORWARD_DCL:
case IDLN_INTERFACE:
return orbit_cbe_get_typespec_str(IDL_INTERFACE(tree).ident);
case IDLN_TYPE_OBJECT:
retval = "CORBA_Object";
break;
case IDLN_TYPE_TYPECODE:
retval = "CORBA_TypeCode";
break;
default:
g_error("We were asked to get a typename for a %s",
IDL_tree_type_names[IDL_NODE_TYPE(tree)]);
break;
}
if (retval)
return g_strdup (retval);
else
return g_string_free (tmpstr, FALSE);
}
void
orbit_cbe_write_typespec(FILE *of, IDL_tree tree)
{
char *name = orbit_cbe_get_typespec_str(tree);
fprintf( of, name);
g_free(name);
}
/**
Parameters (e.g., arguments to methods, and the return value
have some complicated rules in the C mapping for how many
levels of pointer and the exact type involved. This function
generates the externally visible parameter type.
Note the hack below because "const CORBA_string" is not
promotable to "const CORBA_char*" (the later the standard
to which apps are written, while the former is what would
be produced without the hack).
**/
static char *
orbit_cbe_write_param_typespec_str(IDL_tree ts, IDL_ParamRole role)
{
int i, n;
gboolean isSlice;
char *name;
GString *str = g_string_sized_new (23);
IDL_tree typedef_spec;
char *typedef_name;
n = oidl_param_info (ts, role, &isSlice);
name = orbit_cbe_get_typespec_str (ts);
if ( role == DATA_IN ) {
/* We want to check if this is a typedef for CORBA_string so we can do special handling
* in that case.
*/
typedef_spec = orbit_cbe_get_typespec (ts);
typedef_name = orbit_cbe_get_typespec_str (typedef_spec);
g_string_printf (str, "const %s",
!strcmp (typedef_name, "CORBA_string") ?
"CORBA_char *" : name);
g_free (typedef_name);
} else
g_string_printf (str, "%s", name);
g_free (name);
if ( isSlice )
g_string_append (str, "_slice");
for (i = 0; i < n; i++)
g_string_append_c (str, '*');
return g_string_free (str, FALSE);
}
static void
orbit_cbe_write_param_typespec_raw (FILE *of, IDL_tree ts, IDL_ParamRole role)
{
char *str;
str = orbit_cbe_write_param_typespec_str (ts, role);
fprintf (of, str);
g_free (str);
}
void
orbit_cbe_write_param_typespec(FILE *of, IDL_tree tree) {
IDL_tree ts = NULL /* Quiet gcc */;
IDL_ParamRole role = 0 /* Quiet gcc */;
switch ( IDL_NODE_TYPE(tree) ) {
case IDLN_OP_DCL: /* means return value of method */
ts = IDL_OP_DCL(tree).op_type_spec;
role = DATA_RETURN;
break;
case IDLN_PARAM_DCL: /* one of the parameters */
ts = IDL_PARAM_DCL(tree).param_type_spec;
role = oidl_attr_to_paramrole(IDL_PARAM_DCL(tree).attr);
break;
default:
g_assert_not_reached();
}
orbit_cbe_write_param_typespec_raw(of, ts, role);
}
void
orbit_cbe_op_write_proto (FILE *of,
IDL_tree op,
const char *nom_prefix,
gboolean for_epv)
{
IDL_tree sub;
char *id;
g_assert (IDL_NODE_TYPE(op) == IDLN_OP_DCL);
orbit_cbe_write_param_typespec (of, op);
id = IDL_ns_ident_to_qstring (
IDL_IDENT_TO_NS (IDL_INTERFACE (
IDL_get_parent_node (op, IDLN_INTERFACE, NULL)).ident), "_", 0);
if (for_epv)
fprintf (of, " (*%s%s)", nom_prefix ? nom_prefix : "",
IDL_IDENT(IDL_OP_DCL(op).ident).str);
else
fprintf (of, " %s%s_%s", nom_prefix ? nom_prefix : "",
id, IDL_IDENT (IDL_OP_DCL (op).ident).str);
fprintf (of, "(");
if (for_epv)
fprintf (of, "PortableServer_Servant _servant, ");
else
fprintf (of, "%s _obj, ", id);
g_free (id);
for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
IDL_tree parm = IDL_LIST (sub).data;
orbit_cbe_write_param_typespec (of, parm);
fprintf (of, " %s, ", IDL_IDENT (IDL_PARAM_DCL (parm).simple_declarator).str);
}
if (IDL_OP_DCL (op).context_expr)
fprintf (of, "CORBA_Context _ctx, ");
fprintf (of, "CORBA_Environment *ev)");
}
/* Writes the value of the constant in 'tree' to file handle 'of' */
static char *
orbit_cbe_get_const(IDL_tree tree)
{
char *opc = NULL, *retval, *ctmp;
GString *tmpstr = g_string_new(NULL);
switch(IDL_NODE_TYPE(tree)) {
case IDLN_BOOLEAN:
g_string_printf(tmpstr, "%s", IDL_BOOLEAN(tree).value?"CORBA_TRUE":"CORBA_FALSE");
break;
case IDLN_CHAR:
g_string_printf(tmpstr, "'\\x%X'", *(unsigned char *)IDL_CHAR(tree).value);
break;
case IDLN_FLOAT:
g_string_printf(tmpstr, "%f", IDL_FLOAT(tree).value);
break;
case IDLN_INTEGER:
g_string_printf(tmpstr, "%" IDL_LL "d", IDL_INTEGER(tree).value);
break;
case IDLN_STRING:
g_string_printf(tmpstr, "\"%s\"", IDL_STRING(tree).value);
break;
case IDLN_WIDE_CHAR:
g_string_printf(tmpstr, "L'%ls'", IDL_WIDE_CHAR(tree).value);
break;
case IDLN_WIDE_STRING:
g_string_printf(tmpstr, "L\"%ls\"", IDL_WIDE_STRING(tree).value);
break;
case IDLN_BINOP:
g_string_printf(tmpstr, "(");
ctmp = orbit_cbe_get_const(IDL_BINOP(tree).left);
g_string_append(tmpstr, ctmp);
g_free(ctmp);
switch(IDL_BINOP(tree).op) {
case IDL_BINOP_OR:
opc = "|";
break;
case IDL_BINOP_XOR:
opc = "^";
break;
case IDL_BINOP_AND:
opc = "&";
break;
case IDL_BINOP_SHR:
opc = ">>";
break;
case IDL_BINOP_SHL:
opc = "<<";
break;
case IDL_BINOP_ADD:
opc = "+";
break;
case IDL_BINOP_SUB:
opc = "-";
break;
case IDL_BINOP_MULT:
opc = "*";
break;
case IDL_BINOP_DIV:
opc = "/";
break;
case IDL_BINOP_MOD:
opc = "%";
break;
}
g_string_append_printf(tmpstr, " %s ", opc);
ctmp = orbit_cbe_get_const(IDL_BINOP(tree).right);
g_string_append_printf(tmpstr, "%s)", ctmp);
g_free(ctmp);
break;
case IDLN_UNARYOP:
switch(IDL_UNARYOP(tree).op) {
case IDL_UNARYOP_PLUS: opc = "+"; break;
case IDL_UNARYOP_MINUS: opc = "-"; break;
case IDL_UNARYOP_COMPLEMENT: opc = "~"; break;
}
ctmp = orbit_cbe_get_const(IDL_UNARYOP(tree).operand);
g_string_printf(tmpstr, "%s%s", opc, ctmp);
g_free(ctmp);
break;
case IDLN_IDENT:
{
char *id;
id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(tree), "_", 0);
g_string_printf(tmpstr, "%s", id);
g_free(id);
}
break;
default:
g_error("We were asked to print a constant for %s", IDL_tree_type_names[tree->_type]);
break;
}
retval = tmpstr->str;
g_string_free(tmpstr, FALSE);
return retval;
}
void
orbit_cbe_write_const(FILE *of, IDL_tree tree)
{
char *ctmp;
ctmp = orbit_cbe_get_const(tree);
fprintf(of, "%s", ctmp);
g_free(ctmp);
}
/* This is the WORST HACK in the WORLD, really truly, but the C preprocessor doesn't allow us to use
strings, so we have to work around it by using individual characters. */
void
orbit_cbe_id_define_hack(FILE *fh, const char *def_prefix, const char *def_name, const char *def_value)
{
int i, n;
n = strlen(def_value);
for(i = 0; i < n; i++)
fprintf(fh, "#define %s_%s_%d '%c'\n", def_prefix, def_name, i, def_value[i]);
}
void
orbit_cbe_id_cond_hack(FILE *fh, const char *def_prefix, const char *def_name, const char *def_value)
{
int i, n;
n = strlen(def_value);
if(n <= 0)
return;
fprintf(fh, "(");
for(i = 0; i < n; i++)
fprintf(fh, "%s (%s_%s_%d == '%c') \\\n", i?"&&":"", def_prefix, def_name, i, def_value[i]);
fprintf(fh, ")");
}
#define BASE_TYPES \
IDLN_TYPE_INTEGER: \
case IDLN_TYPE_FLOAT: \
case IDLN_TYPE_ENUM: \
case IDLN_TYPE_BOOLEAN: \
case IDLN_TYPE_CHAR: \
case IDLN_TYPE_WIDE_CHAR: \
case IDLN_TYPE_OCTET
#define STRING_TYPES \
IDLN_TYPE_STRING: \
case IDLN_TYPE_WIDE_STRING
#define OBJREF_TYPES \
IDLN_TYPE_OBJECT: \
case IDLN_INTERFACE: \
case IDLN_FORWARD_DCL
static const char *
orbit_cbe_flatten_ref (IDL_ParamRole role, IDL_tree typespec)
{
gboolean is_fixed;
is_fixed = orbit_cbe_type_is_fixed_length (typespec);
switch (role) {
case DATA_IN:
switch (IDL_NODE_TYPE (typespec)) {
case BASE_TYPES:
case STRING_TYPES:
case OBJREF_TYPES:
case IDLN_TYPE_TYPECODE:
case IDLN_NATIVE:
return "(gpointer)&";
case IDLN_TYPE_STRUCT:
case IDLN_TYPE_UNION:
case IDLN_TYPE_ANY:
case IDLN_TYPE_SEQUENCE:
case IDLN_TYPE_ARRAY:
return "(gpointer)";
default:
case IDLN_TYPE_FIXED:
g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
};
return NULL;
case DATA_INOUT:
switch (IDL_NODE_TYPE (typespec)) {
case BASE_TYPES:
case STRING_TYPES:
case OBJREF_TYPES:
case IDLN_TYPE_TYPECODE:
case IDLN_TYPE_STRUCT:
case IDLN_TYPE_UNION:
case IDLN_TYPE_ARRAY:
case IDLN_NATIVE:
case IDLN_TYPE_ANY:
case IDLN_TYPE_SEQUENCE:
return "";
default:
case IDLN_TYPE_FIXED:
g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
};
return NULL;
case DATA_OUT:
switch (IDL_NODE_TYPE (typespec)) {
case BASE_TYPES:
case STRING_TYPES:
case OBJREF_TYPES:
case IDLN_TYPE_TYPECODE:
case IDLN_NATIVE:
return "&";
case IDLN_TYPE_STRUCT:
case IDLN_TYPE_UNION:
case IDLN_TYPE_ARRAY:
if (is_fixed)
return "&";
else /* drop through */
case IDLN_TYPE_SEQUENCE:
case IDLN_TYPE_ANY:
return "";
default:
case IDLN_TYPE_FIXED:
g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
};
return NULL;
case DATA_RETURN:
g_error ("No data return handler");
return NULL;
}
return NULL;
}
void
orbit_cbe_flatten_args (IDL_tree tree, FILE *of, const char *name)
{
int i = 0;
IDL_tree l;
for (l = IDL_OP_DCL(tree).parameter_dcls; l;
l = IDL_LIST(l).next)
i++;
fprintf (of, "gpointer %s[%d];\n", name, i);
i = 0;
for (l = IDL_OP_DCL(tree).parameter_dcls; l;
l = IDL_LIST(l).next) {
IDL_tree decl = IDL_LIST (l).data;
IDL_tree tspec = orbit_cbe_get_typespec (decl);
IDL_ParamRole r = 0;
switch(IDL_PARAM_DCL(decl).attr) {
case IDL_PARAM_IN: r = DATA_IN; break;
case IDL_PARAM_INOUT: r = DATA_INOUT; break;
case IDL_PARAM_OUT: r = DATA_OUT; break;
default:
g_error("Unknown IDL_PARAM type");
}
fprintf (of, "%s[%d] = %s%s;\n",
name, i,
orbit_cbe_flatten_ref (r, tspec),
IDL_IDENT (IDL_PARAM_DCL (decl).simple_declarator).str);
i++;
}
}
static char *
orbit_cbe_unflatten_ref (IDL_ParamRole role, IDL_tree typespec)
{
gboolean is_fixed;
char *typestr;
char *retval;
is_fixed = orbit_cbe_type_is_fixed_length (typespec);
typestr = orbit_cbe_write_param_typespec_str (typespec, role);
switch (role) {
case DATA_IN:
switch (IDL_NODE_TYPE (typespec)) {
case BASE_TYPES:
case STRING_TYPES:
case OBJREF_TYPES:
case IDLN_TYPE_TYPECODE:
case IDLN_NATIVE:
retval = g_strdup_printf ("*(%s *)", typestr);
break;
case IDLN_TYPE_ARRAY:
retval = g_strdup_printf ("(%s_slice *)", typestr);
break;
case IDLN_TYPE_STRUCT:
case IDLN_TYPE_UNION:
case IDLN_TYPE_ANY:
case IDLN_TYPE_SEQUENCE:
retval = g_strdup_printf ("(%s)", typestr);
break;
default:
case IDLN_TYPE_FIXED:
g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
retval = NULL;
break;
};
break;
case DATA_INOUT:
switch (IDL_NODE_TYPE (typespec)) {
case IDLN_TYPE_ARRAY:
retval = g_strdup_printf ("(%s_slice *)", typestr);
break;
case BASE_TYPES:
case STRING_TYPES:
case OBJREF_TYPES:
case IDLN_TYPE_TYPECODE:
case IDLN_TYPE_STRUCT:
case IDLN_TYPE_UNION:
case IDLN_NATIVE:
case IDLN_TYPE_ANY:
case IDLN_TYPE_SEQUENCE:
retval = g_strdup_printf ("(%s)", typestr);
break;
default:
case IDLN_TYPE_FIXED:
g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
retval = NULL;
break;
};
break;
case DATA_OUT:
switch (IDL_NODE_TYPE (typespec)) {
case BASE_TYPES:
case STRING_TYPES:
case OBJREF_TYPES:
case IDLN_TYPE_TYPECODE:
case IDLN_NATIVE:
retval = g_strdup_printf ("*(%s *)", typestr);
break;
case IDLN_TYPE_ARRAY:
if (is_fixed) {
retval = g_strdup_printf ("*(%s_slice **)", typestr);
break;
}
/* drop through */
case IDLN_TYPE_STRUCT:
case IDLN_TYPE_UNION:
if (is_fixed) {
retval = g_strdup_printf ("*(%s *)", typestr);
break;
}
/* drop through */
case IDLN_TYPE_SEQUENCE:
case IDLN_TYPE_ANY:
retval = g_strdup_printf ("(%s)", typestr);
break;
default:
case IDLN_TYPE_FIXED:
g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
retval = NULL;
break;
};
break;
case DATA_RETURN:
default:
g_error ("No data return handler");
retval = NULL;
break;
}
g_free (typestr);
return retval;
}
void
orbit_cbe_unflatten_args (IDL_tree tree, FILE *of, const char *name)
{
IDL_tree l;
int i = 0;
for (l = IDL_OP_DCL(tree).parameter_dcls; l;
l = IDL_LIST(l).next) {
IDL_tree decl = IDL_LIST (l).data;
IDL_tree tspec = orbit_cbe_get_typespec (decl);
IDL_ParamRole r = 0;
char *unflatten;
switch(IDL_PARAM_DCL(decl).attr) {
case IDL_PARAM_IN: r = DATA_IN; break;
case IDL_PARAM_INOUT: r = DATA_INOUT; break;
case IDL_PARAM_OUT: r = DATA_OUT; break;
default:
g_error("Unknown IDL_PARAM type");
}
unflatten = orbit_cbe_unflatten_ref (r, tspec);
fprintf (of, "%s%s[%d], ", unflatten, name, i++);
g_free (unflatten);
}
}
syntax highlighted by Code2HTML, v. 0.9.1