void
orbit_cbe_write_typespec(FILE *of, IDL_tree tree)
{
    char *name = orbit_cbe_get_typespec_str(tree);
    fprintf( of, name);
    g_free(name);
}
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);
}
static void
cc_typecode_prep_sequence (IDL_tree     tree,
			   OIDL_C_Info *ci)
{
	IDL_tree  seq_type;
	IDL_tree  fake_seq_type = NULL;
	char     *type_str;
	char     *seq_type_str;

	seq_type = orbit_cbe_get_typespec (IDL_TYPE_SEQUENCE (tree).simple_type_spec);

	if (IDL_NODE_TYPE (seq_type) != IDLN_INTERFACE)
		seq_type_str = orbit_cbe_get_typespec_str (seq_type);
	else {
		seq_type_str = g_strdup ("CORBA_Object");
		fake_seq_type = IDL_type_object_new ();
	}

	type_str = orbit_cbe_get_typespec_str (IDL_TYPE_SEQUENCE (tree).simple_type_spec);

	if (strcmp (type_str, seq_type_str)) {
		IDL_tree fake_seq;

		fake_seq = IDL_type_sequence_new (
				fake_seq_type ? fake_seq_type : seq_type,
				NULL);
		IDL_NODE_UP (fake_seq) = IDL_NODE_UP (tree);

		cc_output_typecodes (fake_seq, ci);

		IDL_TYPE_SEQUENCE (fake_seq).simple_type_spec = NULL;
		IDL_tree_free (fake_seq);
	}

	if (fake_seq_type)
		IDL_tree_free (fake_seq_type);

	g_free (type_str);
	g_free (seq_type_str);
}
/*
  This is almost the same like orbit_cbe_write_param_typespec_str(). We only omit the
  'const' qualifier because we only need the parameter type.
 */
static char *
orbit_cbe_voyager_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, "%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 char *
orbit_generate_tcstruct_name (IDL_tree node)
{
	GString *tmpstr;
	char    *retval;

	tmpstr = g_string_new (NULL);

	switch (IDL_NODE_TYPE (node)) {
	case IDLN_TYPE_INTEGER:
	case IDLN_TYPE_ANY:
	case IDLN_TYPE_STRING:
	case IDLN_TYPE_WIDE_STRING:
	case IDLN_TYPE_CHAR:
	case IDLN_TYPE_WIDE_CHAR:
	case IDLN_TYPE_FLOAT:
	case IDLN_TYPE_BOOLEAN:
	case IDLN_TYPE_OCTET:
	case IDLN_TYPE_SEQUENCE:
	case IDLN_TYPE_STRUCT:
	case IDLN_TYPE_UNION:
	case IDLN_TYPE_ENUM:
	case IDLN_IDENT:
	case IDLN_EXCEPT_DCL:
	case IDLN_INTERFACE:
	case IDLN_FORWARD_DCL:
	case IDLN_TYPE_OBJECT: {
		char *typespec = orbit_cbe_get_typespec_str (node);

		g_string_printf (tmpstr, "TC_%s", typespec);

		g_free (typespec);
		}
		break;
	default:
		g_string_printf (tmpstr, "anonTC_%d", random_id++);
		break;
	}

	retval = tmpstr->str;
	g_string_free (tmpstr, FALSE);

	return retval;
}
static void
orbit_output_tcstruct_discriminator (FILE *fh, IDL_tree node)
{
	switch (IDL_NODE_TYPE (node)) {
	case IDLN_TYPE_UNION: {
		char *switch_type_spec_str;

		switch_type_spec_str = 
			orbit_cbe_get_typespec_str (IDL_TYPE_UNION (node).switch_type_spec);

		fprintf (fh, "(CORBA_TypeCode)&TC_%s_struct", switch_type_spec_str);

		g_free (switch_type_spec_str);
		}
		break;
	default:
		fprintf (fh, "CORBA_OBJECT_NIL");
		break;
	}
}
static void
orbit_output_tcstruct_anon_subtypes_array (FILE     *fh,
					   IDL_tree  node,
					   int       subtypes_id,
					   char     *substructname)
{
	IDL_tree l;

	switch (IDL_NODE_TYPE (node)) {
	case IDLN_EXCEPT_DCL:
	case IDLN_TYPE_STRUCT:
		if (!IDL_TYPE_STRUCT (node).member_list)
			break;

		fprintf (fh, "static ORBIT2_MAYBE_CONST CORBA_TypeCode anon_subtypes_array%d[] = {",
			 subtypes_id);

		for (l = IDL_TYPE_STRUCT (node).member_list; l; l = IDL_LIST (l).next) {
			IDL_tree  dcl;
			char     *tmpstr;

			dcl = IDL_MEMBER (IDL_LIST (l).data).type_spec;

			switch (IDL_NODE_TYPE (dcl)) {
			case IDLN_IDENT:
			case IDLN_INTERFACE:
			case IDLN_TYPE_OBJECT:
			case IDLN_FORWARD_DCL:
				dcl = orbit_cbe_get_typespec (dcl);

				if (IDL_NODE_DECLSPEC (dcl) & IDLF_DECLSPEC_PIDL &&
				   (IDL_NODE_TYPE (dcl) == IDLN_INTERFACE ||
				    IDL_NODE_TYPE (dcl) == IDLN_FORWARD_DCL))
					tmpstr = g_strdup ("Object");
				else
					tmpstr = orbit_cbe_get_typespec_str (
							IDL_MEMBER (IDL_LIST (l).data).type_spec);
				break;
			default:
				tmpstr = orbit_cbe_get_typespec_str (
						IDL_MEMBER (IDL_LIST (l).data).type_spec);
				break;
			}

			g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_MEMBER);

			for (dcl = IDL_MEMBER (IDL_LIST (l).data).dcls; dcl;
			     dcl = IDL_LIST (dcl).next) {

				fprintf (fh, "(CORBA_TypeCode)&TC_%s_struct", tmpstr);

				if (IDL_LIST (dcl).next || IDL_LIST (l).next)
					fprintf (fh, ", ");
			}

			g_free (tmpstr);
		}

		fprintf (fh, "};\n");

		break;
	case IDLN_TYPE_UNION:
		if (!IDL_TYPE_UNION (node).switch_body)
			break;

		fprintf (fh, "static ORBIT2_MAYBE_CONST CORBA_TypeCode anon_subtypes_array%d[] = {", subtypes_id);

		for (l = IDL_TYPE_UNION (node).switch_body; l; l = IDL_LIST (l).next) {
			IDL_tree  label, dcl;
			char     *tmpstr;

			g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_CASE_STMT);

			dcl = IDL_MEMBER (IDL_CASE_STMT (IDL_LIST (l).data).element_spec).type_spec;

			switch (IDL_NODE_TYPE (orbit_cbe_get_typespec (dcl))) {
			case IDLN_INTERFACE:
			case IDLN_FORWARD_DCL:
				if (IDL_NODE_DECLSPEC (dcl) & IDLF_DECLSPEC_PIDL)
					tmpstr = g_strdup ( "Object");
				else
					tmpstr = orbit_cbe_get_typespec_str (dcl);
				break;
			default:
				tmpstr = orbit_cbe_get_typespec_str (dcl);
				break;
			}

			for (label = IDL_CASE_STMT (IDL_LIST (l).data).labels; label;
			     label = IDL_LIST (label).next) {
				fprintf (fh, "(CORBA_TypeCode)&TC_%s_struct", tmpstr);

				if (IDL_LIST (label).next || IDL_LIST (l).next)
					fprintf (fh, ", ");
			}

			g_free (tmpstr);
		}

		fprintf (fh, "};\n");

		break;
	case IDLN_TYPE_SEQUENCE: {
		IDL_tree  seqts;
		char     *tmpstr;

		seqts = orbit_cbe_get_typespec (IDL_TYPE_SEQUENCE (node).simple_type_spec);

		fprintf (fh, "static ORBIT2_MAYBE_CONST CORBA_TypeCode anon_subtypes_array%d[] = ", subtypes_id);

		switch (IDL_NODE_TYPE (seqts)) {
		case IDLN_INTERFACE:
		case IDLN_FORWARD_DCL:
			if (IDL_NODE_DECLSPEC (seqts) && IDLF_DECLSPEC_PIDL)
				tmpstr = g_strdup ("Object");
			else
				tmpstr = orbit_cbe_get_typespec_str (
						IDL_TYPE_SEQUENCE (node).simple_type_spec);
			break;
		default:
			tmpstr = orbit_cbe_get_typespec_str (
						IDL_TYPE_SEQUENCE (node).simple_type_spec);
			break;
		}

		fprintf (fh, "{(CORBA_TypeCode)&TC_%s_struct};\n", tmpstr);
		g_free (tmpstr);

		}
		break;
	case IDLN_TYPE_ARRAY:
	case IDLN_IDENT:
		fprintf (fh, "static ORBIT2_MAYBE_CONST CORBA_TypeCode anon_subtypes_array%d[] = ", subtypes_id);
		fprintf (fh, "{(CORBA_TypeCode)&%s_struct};\n", substructname);
		break;
	default:
		break;
	}
}
static void
cc_output_method (FILE *of, IDL_tree tree, const char *id)
{
	int arg_count;
	int except_count;
	int context_count;
	const char *method;
	char       *fullname;

	fullname = g_strconcat (id, "_", IDL_IDENT (
		IDL_OP_DCL (tree).ident).str, NULL);

	arg_count = IDL_list_length (IDL_OP_DCL (tree).parameter_dcls);
	except_count = IDL_list_length (IDL_OP_DCL (tree).raises_expr);
	context_count = IDL_list_length (IDL_OP_DCL (tree).context_expr);
	
	fprintf (of, "\t{\n");

	/* IArgs arguments */
	if (arg_count)
		fprintf (of, "\t\t{ %d, %d, %s__arginfo, FALSE },\n",
			 arg_count, arg_count, fullname);
	else
		fprintf (of, "\t\t{ 0, 0, NULL, FALSE },\n");

	/* IContexts contexts */
	if (context_count)
		fprintf (of, "\t\t{ %d, %d, %s__contextinfo, FALSE },\n",
			 context_count, context_count, fullname);
	else
		fprintf (of, "\t\t{ 0, 0, NULL, FALSE },\n");
		
	/* ITypes exceptions */
	if (IDL_OP_DCL (tree).raises_expr)
		fprintf (of, "\t\t{ %d, %d, %s__exceptinfo, FALSE },\n",
			 except_count, except_count, fullname);
	else
		fprintf (of, "\t\t{ 0, 0, NULL, FALSE },\n");

	/* TypeCode ret */
	if (IDL_OP_DCL (tree).op_type_spec) {
		char *type_id;

		type_id = orbit_cbe_get_typespec_str (
			IDL_OP_DCL (tree).op_type_spec);
		fprintf (of, "\t\tTC_%s, ", type_id);
		g_free (type_id);
	} else
		fprintf (of, "TC_void, ");

	/* string name, long name_len */
	method = IDL_IDENT (IDL_OP_DCL (tree).ident).str;
	fprintf (of, "\"%s\", %d,\n", method, strlen (method));

	/* IMethodFlags flags */
	fprintf (of, "\t\t0");

	if (IDL_OP_DCL(tree).f_oneway)
		fprintf (of, " | ORBit_I_METHOD_1_WAY");

/* FIXME: re-scan for no_out */
/*	if (no_out)
	fprintf (of, " | ORBit_I_METHOD_NO_OUT");*/

	if (IDL_OP_DCL (tree).op_type_spec &&
	    orbit_cbe_type_is_fixed_length (
		    IDL_OP_DCL (tree).op_type_spec))
		fprintf (of, "| ORBit_I_COMMON_FIXED_SIZE");

	if (IDL_OP_DCL(tree).context_expr)
		fprintf (of, "| ORBit_I_METHOD_HAS_CONTEXT");

	fprintf (of, "\n}\n");

	g_free (fullname);
}
/**
    Gets the "type" of {tree} as known in C.
    The return value was alloc'd via g_malloc, and must be g_free'd.
**/
gulong
orbit_cbe_get_typespec_size(IDL_tree tree)
{
  gulong retval=0;

  if(!tree) {
    return 0;
  }

  switch(IDL_NODE_TYPE(tree)) {
#if 0
  case IDLN_MEMBER:
    return orbit_cbe_get_typespec_str(IDL_MEMBER(tree).type_spec);
    break;
  case IDLN_TYPE_ANY:
    retval = sizeof(CORBA_any);
    break;
#endif
  case IDLN_TYPE_FLOAT:
    switch(IDL_TYPE_FLOAT(tree).f_type) {
    case IDL_FLOAT_TYPE_FLOAT:
      retval = sizeof(CORBA_float);
      break;
    case IDL_FLOAT_TYPE_DOUBLE:
      retval = sizeof(CORBA_double);
      break;
    case IDL_FLOAT_TYPE_LONGDOUBLE:
      retval = sizeof(CORBA_long_double);
      break;
    }
    break;
#if 0
  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;
#endif
  case IDLN_TYPE_INTEGER:
    if(!IDL_TYPE_INTEGER(tree).f_signed)
      {
        /* unsigned types */
        switch(IDL_TYPE_INTEGER(tree).f_type) 
          {
          case IDL_INTEGER_TYPE_SHORT:
            retval=sizeof(CORBA_unsigned_short);
            break;
          case IDL_INTEGER_TYPE_LONGLONG:
            retval=sizeof(CORBA_unsigned_long_long);
            break;
          case IDL_INTEGER_TYPE_LONG:
            retval=sizeof(CORBA_unsigned_long);
            break;
          }
      }
    else{
      switch(IDL_TYPE_INTEGER(tree).f_type) 
        {
          /* signed types */
        case IDL_INTEGER_TYPE_SHORT:
          retval=sizeof(CORBA_short);
          break;
        case IDL_INTEGER_TYPE_LONGLONG:
          retval=sizeof(CORBA_long_long);
          break;
        case IDL_INTEGER_TYPE_LONG:
          retval=sizeof(CORBA_long);
          break;
        }
    }
    break;
  case IDLN_TYPE_OCTET:
    retval = sizeof(CORBA_octet);
    break;
  case IDLN_TYPE_STRING:
    retval = sizeof(CORBA_string);	/* this is non-standard! */
    break;
  case IDLN_TYPE_BOOLEAN:
    retval = sizeof(CORBA_boolean);
    break;
  case IDLN_TYPE_CHAR:
    retval = sizeof(CORBA_char);
    break;
  case IDLN_TYPE_OBJECT:
    retval = sizeof(CORBA_Object);
    break;
  case IDLN_NATIVE:
    retval = sizeof(gpointer);
    break;
#if 0
  case IDLN_TYPE_WIDE_STRING:
    retval = "CORBA_wstring";	/* this is non-standard! */
    break;
  case IDLN_TYPE_WIDE_CHAR:
    retval = "CORBA_wchar";
    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_FORWARD_DCL:
  case IDLN_INTERFACE:
    return orbit_cbe_get_typespec_str(IDL_INTERFACE(tree).ident);
  case IDLN_TYPE_TYPECODE:
    retval = "CORBA_TypeCode";
    break;
#endif
  default:
    //    retval=sizeof(gpointer);
    //    g_error("We were asked to get a typesize for a %s (%s, %s line %d)",
    //	    IDL_tree_type_names[IDL_NODE_TYPE(tree)], __FILE__, __FUNCTION__, __LINE__);
    g_print("We were asked to get a typesize for a %s -> %s (%s line %d)\n",
            IDL_tree_type_names[IDL_NODE_TYPE(tree)], IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(tree), "_", 0), 
            __FUNCTION__, __LINE__);
    g_print("HACK: Returning sizeof(gpointer) now...\n", IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(tree), "_", 0));
    retval=sizeof(gpointer);
    break;
  }

    return retval;
}
/**
    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);
}