#include "config.h" #include "orbit-idl-c-backend.h" #include static void cs_output_stubs(IDL_tree tree, OIDL_C_Info *ci); void orbit_idl_output_c_stubs(OIDL_Output_Tree *tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci) { fprintf(ci->fh, "/*\n" " * This file was generated by orbit-idl - DO NOT EDIT!\n" " */\n\n"); fprintf(ci->fh, "#include \n"); fprintf(ci->fh, "#include \"%s.h\"\n\n", ci->base_name); cs_output_stubs(tree->tree, ci); } static void cs_output_stub(IDL_tree tree, OIDL_C_Info *ci); static void cs_output_except(IDL_tree tree, OIDL_C_Info *ci); static void cs_output_stubs(IDL_tree tree, OIDL_C_Info *ci) { if(!tree) return; switch(IDL_NODE_TYPE(tree)) { case IDLN_MODULE: cs_output_stubs(IDL_MODULE(tree).definition_list, ci); break; case IDLN_LIST: { IDL_tree sub; for(sub = tree; sub; sub = IDL_LIST(sub).next) { cs_output_stubs(IDL_LIST(sub).data, ci); } } break; case IDLN_ATTR_DCL: { OIDL_Attr_Info *ai = tree->data; IDL_tree curitem; for(curitem = IDL_ATTR_DCL(tree).simple_declarations; curitem; curitem = IDL_LIST(curitem).next) { ai = IDL_LIST(curitem).data->data; cs_output_stubs(ai->op1, ci); if(ai->op2) cs_output_stubs(ai->op2, ci); } } break; case IDLN_INTERFACE: cs_output_stubs(IDL_INTERFACE(tree).body, ci); break; case IDLN_OP_DCL: cs_output_stub(tree, ci); break; case IDLN_EXCEPT_DCL: cs_output_except(tree, ci); break; default: break; } } /* Here's the fun part ;-) */ static void cs_stub_alloc_tmpvars(OIDL_Marshal_Node *node, OIDL_C_Info *ci); static void cs_stub_alloc_params(IDL_tree tree, OIDL_C_Info *ci); static void cs_free_inout_params(IDL_tree tree, OIDL_C_Info *ci); static void cs_stub_print_return(IDL_tree tree, OIDL_C_Info *ci); static void cs_output_stub(IDL_tree tree, OIDL_C_Info *ci) { OIDL_Op_Info *oi; oi = tree->data; g_assert(oi); orbit_cbe_op_write_proto(ci->fh, tree, "", FALSE); fprintf(ci->fh, "{\n"); if(IDL_OP_DCL(tree).raises_expr) { IDL_tree curitem; fprintf(ci->fh, "static const ORBit_exception_demarshal_info _ORBIT_user_exceptions[] = { "); for(curitem = IDL_OP_DCL(tree).raises_expr; curitem; curitem = IDL_LIST(curitem).next) { char *id; IDL_tree curnode = IDL_LIST(curitem).data; id = orbit_cbe_get_typename(curnode); fprintf(ci->fh, "{(const CORBA_TypeCode)&TC_%s_struct, (gpointer)_ORBIT_%s_demarshal},", id, id); g_free(id); } fprintf(ci->fh, "{CORBA_OBJECT_NIL, NULL}};\n"); } if(IDL_OP_DCL(tree).context_expr) { IDL_tree curitem; fprintf(ci->fh, "static const ORBit_ContextMarshalItem _context_items[] = {\n"); for(curitem = IDL_OP_DCL(tree).context_expr; curitem; curitem = IDL_LIST(curitem).next) { fprintf(ci->fh, "{%u, \"%s\"},\n", strlen(IDL_STRING(IDL_LIST(curitem).data).value) + 1, IDL_STRING(IDL_LIST(curitem).data).value); } fprintf(ci->fh, "};\n"); } fprintf(ci->fh, "register GIOP_unsigned_long _ORBIT_request_id, _ORBIT_system_exception_minor;\n"); fprintf(ci->fh, "register CORBA_completion_status _ORBIT_completion_status;\n"); fprintf(ci->fh, "register GIOPSendBuffer *_ORBIT_send_buffer;\n"); fprintf(ci->fh, "register GIOPRecvBuffer *_ORBIT_recv_buffer;\n"); fprintf(ci->fh, "register GIOPConnection *_cnx;\n"); if(oi->out_stubs) /* Lame hack to ensure we get _ORBIT_retval available */ cs_stub_alloc_tmpvars(oi->out_stubs, ci); /* Check if we can do a direct call, and if so, do it */ { IDL_tree curitem; char *id; curitem = IDL_get_parent_node(tree, IDLN_INTERFACE, 0); g_assert(curitem); id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(curitem).ident), "_", 0); fprintf(ci->fh, "if(_obj->servant && _obj->vepv && %s__classid)\n{\n", id); #ifndef BACKWARDS_COMPAT_0_4 fprintf(ci->fh, "int *_use_count; GFunc _death_func; gpointer _user_data; ORBit_POAObject *_pobj;\n"); fprintf(ci->fh, "_pobj = ORBIT_OBJECT_KEY(((PortableServer_ServantBase *)_obj->servant)->_private)->object;\n"); fprintf(ci->fh, "_use_count = _pobj->use_count;\n _death_func = _pobj->death_callback; _user_data = _pobj->user_data;\n"); fprintf(ci->fh, "if(_use_count) (*_use_count)++;\n"); #endif fprintf(ci->fh, "%s((POA_%s__epv *)_obj->vepv[%s__classid])->%s(_obj->servant, ", IDL_OP_DCL(tree).op_type_spec?"_ORBIT_retval = ":"", id, id, IDL_IDENT(IDL_OP_DCL(tree).ident).str); g_free(id); for(curitem = IDL_OP_DCL(tree).parameter_dcls; curitem; curitem = IDL_LIST(curitem).next) { fprintf(ci->fh, "%s, ", IDL_IDENT(IDL_PARAM_DCL(IDL_LIST(curitem).data).simple_declarator).str); } if(IDL_OP_DCL(tree).context_expr) fprintf(ci->fh, "_ctx, "); fprintf(ci->fh, "ev);\n"); #ifndef BACKWARDS_COMPAT_0_4 fprintf(ci->fh, "if(_use_count) { if(!(--(*_use_count))) _death_func(_use_count, _user_data); }\n"); #endif fprintf(ci->fh, "return %s;\n}\n", IDL_OP_DCL(tree).op_type_spec?"_ORBIT_retval":""); } /* Ensure that the compiler thinks _ORBIT_retval is initialized */ if (IDL_OP_DCL(tree).op_type_spec) fprintf (ci->fh, "if (0) return *(&_ORBIT_retval);\n"); fprintf(ci->fh, "_cnx = ORBit_object_get_connection(_obj);\n"); if(!IDL_OP_DCL(tree).f_oneway) /* For location forwarding */ fprintf(ci->fh, "_ORBIT_retry_request:\n"); fprintf(ci->fh, "_ORBIT_send_buffer = NULL;\n_ORBIT_recv_buffer = NULL;\n"); fprintf(ci->fh, "_ORBIT_completion_status = CORBA_COMPLETED_NO;\n"); if(sizeof(gpointer) > sizeof(GIOP_unsigned_long)) fprintf(ci->fh, "_ORBIT_request_id = giop_get_request_id();\n"); else fprintf(ci->fh, "_ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));\n"); fprintf(ci->fh, "{ /* marshalling */\n"); fprintf(ci->fh, "static const struct { CORBA_unsigned_long len; char opname[%u]; } _ORBIT_operation_name_data = { %u, \"%s\" };\n", strlen(IDL_IDENT(IDL_OP_DCL(tree).ident).str) + 1, strlen(IDL_IDENT(IDL_OP_DCL(tree).ident).str) + 1, IDL_IDENT(IDL_OP_DCL(tree).ident).str); fprintf(ci->fh, "static const struct iovec _ORBIT_operation_vec = {(gpointer)&_ORBIT_operation_name_data, %u};\n", sizeof(CORBA_unsigned_long) + strlen(IDL_IDENT(IDL_OP_DCL(tree).ident).str) + 1); cs_stub_alloc_tmpvars(oi->in_stubs, ci); fprintf(ci->fh, "_ORBIT_send_buffer = \n"); fprintf(ci->fh, "giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id, %s,\n", IDL_OP_DCL(tree).f_oneway?"CORBA_FALSE":"CORBA_TRUE"); fprintf(ci->fh, "&(_obj->active_profile->object_key_vec), &_ORBIT_operation_vec, &ORBit_default_principal_iovec);\n\n"); fprintf(ci->fh, "_ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;\n"); fprintf(ci->fh, "if(!_ORBIT_send_buffer) goto _ORBIT_system_exception;\n"); c_marshalling_generate(oi->in_stubs, ci, TRUE); #ifdef BACKWARDS_COMPAT_0_4 fprintf(ci->fh, "giop_send_buffer_write(_ORBIT_send_buffer);\n"); #else fprintf(ci->fh, "if(giop_send_buffer_write(_ORBIT_send_buffer)) goto _ORBIT_system_exception;\n"); #endif fprintf(ci->fh, "_ORBIT_completion_status = CORBA_COMPLETED_MAYBE;\n"); fprintf(ci->fh, "giop_send_buffer_unuse(_ORBIT_send_buffer); _ORBIT_send_buffer = NULL;\n"); fprintf(ci->fh, "}\n"); if(!IDL_OP_DCL(tree).f_oneway) { /* free inout params as needed */ cs_free_inout_params(tree, ci); fprintf(ci->fh, "{ /* demarshalling */\n"); if(oi->out_stubs) fprintf(ci->fh, "register guchar *_ORBIT_curptr;\n"); fprintf(ci->fh, "_ORBIT_recv_buffer = giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);\n"); fprintf(ci->fh, "if(!_ORBIT_recv_buffer) goto _ORBIT_system_exception;\n"); fprintf(ci->fh, "_ORBIT_completion_status = CORBA_COMPLETED_YES;\n"); fprintf(ci->fh, "if(_ORBIT_recv_buffer->message.u.reply.reply_status != GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;\n"); cs_stub_alloc_params(tree, ci); c_demarshalling_generate(oi->out_stubs, ci, FALSE); fprintf(ci->fh, "giop_recv_buffer_unuse(_ORBIT_recv_buffer);\n"); cs_stub_print_return (tree, ci); } else fprintf(ci->fh, "return;\n"); fprintf(ci->fh, "_ORBIT_system_exception:\n"); #ifdef BACKWARDS_COMPAT_0_4 fprintf(ci->fh, "CORBA_exception_set_system(ev, _ORBIT_system_exception_minor, _ORBIT_completion_status);\n"); fprintf(ci->fh, "giop_recv_buffer_unuse(_ORBIT_recv_buffer);\n"); fprintf(ci->fh, "giop_send_buffer_unuse(_ORBIT_send_buffer);\n"); #else fprintf(ci->fh, "ORBit_handle_system_exception(ev, _ORBIT_system_exception_minor, _ORBIT_completion_status, _ORBIT_recv_buffer, _ORBIT_send_buffer);\n"); #endif cs_stub_print_return (tree, ci); if(!IDL_OP_DCL(tree).f_oneway) { fprintf(ci->fh, "_ORBIT_msg_exception:\n"); /* deal with LOCATION_FORWARD exceptions */ fprintf(ci->fh, "if(_ORBIT_recv_buffer->message.u.reply.reply_status == GIOP_LOCATION_FORWARD) {\n"); #ifdef BACKWARDS_COMPAT_0_4 fprintf(ci->fh, "if (_obj->forward_locations != NULL) ORBit_delete_profiles(_obj->forward_locations);\n"); fprintf(ci->fh, "_obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);\n"); fprintf(ci->fh, "_cnx = ORBit_object_get_forwarded_connection(_obj);\n"); fprintf(ci->fh, "giop_recv_buffer_unuse(_ORBIT_recv_buffer);\n"); #else fprintf(ci->fh, "_cnx = ORBit_handle_location_forward(_ORBIT_recv_buffer, _obj);\n"); #endif fprintf(ci->fh, "\ngoto _ORBIT_retry_request;\n"); fprintf(ci->fh, "} else {\n"); fprintf(ci->fh, "ORBit_handle_exception(_ORBIT_recv_buffer, ev, %s, _obj->orb);\n", IDL_OP_DCL(tree).raises_expr?"_ORBIT_user_exceptions":"NULL"); fprintf(ci->fh, "giop_recv_buffer_unuse(_ORBIT_recv_buffer);\n"); cs_stub_print_return (tree, ci); fprintf(ci->fh, "}\n}\n"); } fprintf(ci->fh, "}\n"); } static void cs_stub_print_return(IDL_tree tree, OIDL_C_Info *ci) { if(IDL_OP_DCL(tree).op_type_spec) fprintf(ci->fh, "return %s;\n", ORBIT_RETVAL_VAR_NAME); else fprintf(ci->fh, "return;\n"); } static void cbe_stub_op_param_alloc(FILE *of, IDL_tree node, GString *tmpstr) { int n, i; char *id; IDL_tree ts = orbit_cbe_get_typespec(node); n = oidl_param_numptrs(node, oidl_attr_to_paramrole(IDL_PARAM_DCL(node).attr)); if(((n - 1) <= 0) && IDL_NODE_TYPE(ts) != IDLN_TYPE_ARRAY) return; switch(IDL_NODE_TYPE(ts)) { case IDLN_TYPE_ARRAY: if((IDL_PARAM_DCL(node).attr != IDL_PARAM_OUT) || orbit_cbe_type_is_fixed_length(ts)) return; n++; break; case IDLN_TYPE_SEQUENCE: case IDLN_TYPE_ANY: if(IDL_PARAM_DCL(node).attr == IDL_PARAM_INOUT) return; break; case IDLN_TYPE_UNION: case IDLN_TYPE_STRUCT: if(orbit_cbe_type_is_fixed_length(ts)) return; default: break; } g_string_assign(tmpstr, ""); for(i = 0; i < n - 1; i++) g_string_append_c(tmpstr, '*'); g_string_sprintfa(tmpstr, "%s", IDL_IDENT(IDL_PARAM_DCL(node).simple_declarator).str); id = orbit_cbe_get_typename(IDL_PARAM_DCL(node).param_type_spec); fprintf(of, "%s = %s__alloc();\n", tmpstr->str, id); g_free(id); } static void cbe_stub_op_retval_alloc(FILE *of, IDL_tree node, GString *tmpstr) { int n; char *id; IDL_tree ts = orbit_cbe_get_typespec(node); n = oidl_param_numptrs(node, DATA_RETURN); if((n <= 0) && (IDL_NODE_TYPE(ts) != IDLN_TYPE_ARRAY)) return; g_string_assign(tmpstr, ORBIT_RETVAL_VAR_NAME ); switch(IDL_NODE_TYPE(ts)) { case IDLN_TYPE_UNION: case IDLN_TYPE_STRUCT: if(orbit_cbe_type_is_fixed_length(ts)) return; case IDLN_TYPE_ANY: case IDLN_TYPE_SEQUENCE: case IDLN_TYPE_ARRAY: break; default: return; } id = orbit_cbe_get_typename(node); fprintf(of, "%s = %s__alloc();\n", tmpstr->str, id); g_free(id); } static void cs_stub_alloc_params(IDL_tree tree, OIDL_C_Info *ci) { IDL_tree curitem, param; GString *tmpstr = g_string_new(NULL); if(IDL_OP_DCL(tree).op_type_spec) cbe_stub_op_retval_alloc(ci->fh, IDL_OP_DCL(tree).op_type_spec, tmpstr); for(curitem = IDL_OP_DCL(tree).parameter_dcls; curitem; curitem = IDL_LIST(curitem).next) { param = IDL_LIST(curitem).data; if(IDL_PARAM_DCL(param).attr == IDL_PARAM_INOUT || IDL_PARAM_DCL(param).attr == IDL_PARAM_OUT) cbe_stub_op_param_alloc(ci->fh, param, tmpstr); } g_string_free(tmpstr, TRUE); } static void cs_stub_alloc_tmpvar(OIDL_Marshal_Node *node, OIDL_C_Info *ci) { if(!(node->flags & MN_NEED_TMPVAR)) return; if(node->flags & MN_NOMARSHAL) fprintf(ci->fh, "register "); /* Help the compiler out */ if(node->tree) { int i; orbit_cbe_write_typespec(ci->fh, node->tree); if(IDL_NODE_TYPE(node->tree) != IDLN_PARAM_DCL) { IDL_tree ts = orbit_cbe_get_typespec(node->tree); if(IDL_NODE_TYPE(ts) == IDLN_TYPE_ARRAY) fprintf(ci->fh, "_slice*"); } for(i = 0; i < node->nptrs; i++) fprintf(ci->fh, "*"); fprintf(ci->fh, " %s;\n", node->name); } else if(node->type == MARSHAL_DATUM) { const char * ctmp; static const char * const size_names[] = {NULL, "CORBA_unsigned_char", "CORBA_unsigned_short", NULL, "CORBA_unsigned_long", NULL, NULL, NULL, "CORBA_unsigned_long_long"}; ctmp = size_names[node->u.datum_info.datum_size]; g_assert(ctmp); fprintf(ci->fh, "%s %s;\n", ctmp, node->name); } else g_error("Don't know how to handle tmpvar %s", node->name); } static void cs_stub_alloc_tmpvars(OIDL_Marshal_Node *node, OIDL_C_Info *ci) { orbit_idl_node_foreach(node, (GFunc)cs_stub_alloc_tmpvar, ci); } /* This param freeing stuff really could be done better - perhaps shared code with the skels generation. */ static void cbe_stub_op_param_free(FILE *of, IDL_tree node, GString *tmpstr) { int n, i; IDL_tree ts; char *id; ts = orbit_cbe_get_typespec(IDL_PARAM_DCL(node).param_type_spec); n = oidl_param_numptrs(node, DATA_INOUT); g_string_assign(tmpstr, ""); if(IDL_NODE_TYPE(ts) == IDLN_TYPE_STRUCT || IDL_NODE_TYPE(ts) == IDLN_TYPE_UNION) n--; for(i = 0; i < n; i++) g_string_append_c(tmpstr, '*'); g_string_sprintfa(tmpstr, "%s", IDL_IDENT(IDL_PARAM_DCL(node).simple_declarator).str); switch(IDL_NODE_TYPE(ts)) { case IDLN_TYPE_ANY: fprintf(of, "if(CORBA_any_get_release(&(%s))) CORBA_free((%s)._value);\n", tmpstr->str, tmpstr->str); fprintf(of, "CORBA_Object_release((CORBA_Object)(%s)._type, ev);\n", tmpstr->str); break; case IDLN_TYPE_SEQUENCE: fprintf(of, "if((%s)._release) CORBA_free((%s)._buffer);\n", tmpstr->str, tmpstr->str); break; case IDLN_TYPE_STRUCT: case IDLN_TYPE_UNION: case IDLN_TYPE_ARRAY: if(orbit_cbe_type_is_fixed_length(ts)) break; id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_TYPE_STRUCT(ts).ident), "_", 0); fprintf(of, "%s__free(%s, NULL, CORBA_TRUE);\n", id, tmpstr->str); g_free(id); break; case IDLN_TYPE_STRING: fprintf(of, "CORBA_free(%s);\n", tmpstr->str); break; case IDLN_INTERFACE: case IDLN_FORWARD_DCL: case IDLN_TYPE_OBJECT: case IDLN_TYPE_TYPECODE: fprintf(of, "CORBA_Object_release((CORBA_Object)%s, ev);\n", tmpstr->str); break; default: g_assert(orbit_cbe_type_is_fixed_length(node)); break; } } static void cs_free_inout_params(IDL_tree tree, OIDL_C_Info *ci) { IDL_tree curitem; GString *tmpstr; tmpstr = g_string_new(NULL); for(curitem = IDL_OP_DCL(tree).parameter_dcls; curitem; curitem = IDL_LIST(curitem).next) { IDL_tree curparam; curparam = IDL_LIST(curitem).data; if(IDL_PARAM_DCL(curparam).attr != IDL_PARAM_INOUT) continue; cbe_stub_op_param_free(ci->fh, curparam, tmpstr); } g_string_free(tmpstr, TRUE); } static void cs_output_except(IDL_tree tree, OIDL_C_Info *ci) { char *id; OIDL_Except_Info *ei; ei = tree->data; g_assert(ei); id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_EXCEPT_DCL(tree).ident), "_", 0); fprintf(ci->fh, "void\n_ORBIT_%s_demarshal(GIOPRecvBuffer *_ORBIT_recv_buffer, CORBA_Environment *ev)\n", id); fprintf(ci->fh, "{\n"); if(IDL_EXCEPT_DCL(tree).members) { fprintf(ci->fh, "guchar *_ORBIT_curptr;\n"); cs_stub_alloc_tmpvars(ei->demarshal, ci); fprintf(ci->fh, "%s *_ORBIT_exdata = %s__alloc();\n", id, id); c_demarshalling_generate(ei->demarshal, ci, FALSE); } fprintf(ci->fh, "CORBA_exception_set(ev, CORBA_USER_EXCEPTION, TC_%s_struct.repo_id, %s);\n", id, IDL_EXCEPT_DCL(tree).members?"_ORBIT_exdata":"NULL"); fprintf(ci->fh, "}\n"); }