]> rtime.felk.cvut.cz Git - frescor/forb.git/blob - forb-idl/forb-idl-c-utils.c
IDL generated files can be compiled without errors now
[frescor/forb.git] / forb-idl / forb-idl-c-utils.c
1 #include "config.h"
2
3 #include "forb-idl-c-backend.h"
4
5 #include <string.h>
6
7 /** 
8  * 
9  * 
10  * @param of 
11  * @param ts Type spec.
12  * @param name decl
13  * @param use_name use identifier from name 
14  * @param var_prefix prefix for identifier taken from name
15  * @param serialization 
16  */
17 void
18 forb_cbe_write_ser_var(FILE *of, IDL_tree ts, IDL_tree name,
19                        bool use_name,
20                        char *var_prefix,
21                        enum forb_ser serialization)
22 {
23         int indent = 0, i;
24         GString *id = g_string_new("");
25         char *serialize = (serialization == SERIALIZE) ? "serialize" : "deserialize";
26         
27         switch(IDL_NODE_TYPE(name)) {
28         case IDLN_IDENT:
29                 fprintf(of, "  ");
30                 if (use_name)
31                         g_string_assign(id, IDL_IDENT(name).str);
32                 break;
33         case IDLN_TYPE_ARRAY:
34         {
35                 IDL_tree curitem;
36                 char var;
37                 if (use_name)
38                         g_string_assign(id, IDL_IDENT(IDL_TYPE_ARRAY(name).ident).str);
39
40                 var = 'i';
41                 fprintf(of, "  {\n    CORBA_unsigned_long ");
42                 for(curitem = IDL_TYPE_ARRAY(name).size_list; curitem; curitem = IDL_LIST(curitem).next) {
43                         fprintf(of, "%c", var);
44                         if (IDL_LIST(curitem).next)
45                                 fprintf(of, ", ");
46                         g_string_append_printf(id, "[%c]", var);
47                         var++;
48                 }
49                 fprintf(of, ";\n");
50
51                 var = 'i';
52                 for(curitem = IDL_TYPE_ARRAY(name).size_list; curitem; curitem = IDL_LIST(curitem).next) {
53                         indent++;
54                         for (i=0; i<indent+1; i++)
55                                 fprintf(of, "  ");
56                         fprintf(of, "for (%c=0; %c<%" IDL_LL "d; %c++) \n",
57                                 var, var, IDL_INTEGER(IDL_LIST(curitem).data).value, var);
58                         var++;
59                 }
60
61
62                 for (i=0; i<indent+2; i++)
63                         fprintf(of, "  ");
64
65         }
66         break;
67         default:
68                 g_error("Weird varname - %s", IDL_tree_type_names[IDL_NODE_TYPE(name)]);
69                 break;
70         }
71         fprintf(of, "if (!");
72         forb_cbe_write_typespec(of, ts);
73         fprintf(of, "_%s(codec, &%s%s)) goto ser_exception;\n",
74                 serialize, var_prefix, id->str);
75         if (indent)
76                 fprintf(of, "  }\n");
77
78         g_string_free(id, TRUE);
79 }
80
81
82 char *
83 forb_cbe_get_typecode_name (IDL_tree tree)
84 {
85         if (!tree)
86                 return g_strdup ("TC_FIXME");
87         else
88                 return g_strconcat ("TC_", forb_cbe_get_typespec_str (tree), NULL);
89 }
90
91 gboolean
92 forb_cbe_type_is_builtin(IDL_tree tree)
93
94   return FALSE;
95   switch(IDL_NODE_TYPE(tree)) {
96   case IDLN_LIST:
97   case IDLN_GENTREE:
98   case IDLN_MEMBER:
99   case IDLN_NATIVE:
100   case IDLN_CASE_STMT:
101   case IDLN_MODULE:
102   case IDLN_BINOP:
103   case IDLN_UNARYOP:
104   case IDLN_CODEFRAG:
105     g_error("Strange type for being a builtin");
106     break;
107   case IDLN_INTEGER:
108   case IDLN_STRING:
109   case IDLN_WIDE_STRING:
110   case IDLN_CHAR:
111   case IDLN_WIDE_CHAR:
112   case IDLN_FIXED:
113   case IDLN_FLOAT:
114   case IDLN_BOOLEAN:
115   case IDLN_CONST_DCL:
116   case IDLN_TYPE_INTEGER:
117   case IDLN_TYPE_FLOAT:
118   case IDLN_TYPE_CHAR:
119   case IDLN_TYPE_WIDE_CHAR:
120   case IDLN_TYPE_STRING:
121   case IDLN_TYPE_WIDE_STRING:
122   case IDLN_TYPE_BOOLEAN:
123   case IDLN_TYPE_OCTET:
124   case IDLN_TYPE_ANY:
125   case IDLN_TYPE_OBJECT:
126   case IDLN_TYPE_TYPECODE:
127   case IDLN_TYPE_ENUM:
128     return TRUE;
129     break;
130   case IDLN_TYPE_DCL:
131   case IDLN_EXCEPT_DCL:
132   case IDLN_ATTR_DCL:
133   case IDLN_OP_DCL:
134   case IDLN_PARAM_DCL:
135   case IDLN_TYPE_FIXED:
136   case IDLN_TYPE_SEQUENCE:
137   case IDLN_TYPE_ARRAY:
138   case IDLN_TYPE_STRUCT:
139   case IDLN_TYPE_UNION:
140   case IDLN_IDENT:
141   case IDLN_INTERFACE:
142   case IDLN_FORWARD_DCL:
143   default:
144     return FALSE;
145     break;
146   }
147
148   return FALSE;
149 }
150
151 /**
152     Gets the "type" of {tree} as known in C.
153     The return value was alloc'd via g_malloc, and must be g_free'd.
154 **/
155 char *
156 forb_cbe_get_typespec_str(IDL_tree tree)
157 {
158   char *retval = NULL;
159   GString *tmpstr = NULL;
160
161   if(!tree) {
162     return g_strdup("void");
163   }
164
165   switch(IDL_NODE_TYPE(tree)) {
166   case IDLN_MEMBER:
167     return forb_cbe_get_typespec_str(IDL_MEMBER(tree).type_spec);
168     break;
169   case IDLN_TYPE_ANY:
170     retval = "CORBA_any";
171     break;
172   case IDLN_TYPE_FLOAT:
173     switch(IDL_TYPE_FLOAT(tree).f_type) {
174     case IDL_FLOAT_TYPE_FLOAT:
175       retval = "CORBA_float";
176       break;
177     case IDL_FLOAT_TYPE_DOUBLE:
178       retval = "CORBA_double";
179       break;
180     case IDL_FLOAT_TYPE_LONGDOUBLE:
181       retval = "CORBA_long_double";
182       break;
183     }
184     break;
185   case IDLN_TYPE_FIXED:
186     return g_strdup_printf( "CORBA_fixed_%" IDL_LL "d_%" IDL_LL "d",
187                      IDL_INTEGER(IDL_TYPE_FIXED(tree).positive_int_const).value,
188                      IDL_INTEGER(IDL_TYPE_FIXED(tree).integer_lit).value);
189     break;
190   case IDLN_TYPE_INTEGER:
191     tmpstr = g_string_new(NULL);
192     g_string_append(tmpstr, "CORBA_");
193     if(!IDL_TYPE_INTEGER(tree).f_signed)
194         g_string_append(tmpstr, "unsigned_");
195
196     switch(IDL_TYPE_INTEGER(tree).f_type) {
197     case IDL_INTEGER_TYPE_SHORT:
198         g_string_append(tmpstr, "short");
199         break;
200     case IDL_INTEGER_TYPE_LONGLONG:
201         g_string_append(tmpstr, "long_");
202         /* FALLTHROUGH */
203     case IDL_INTEGER_TYPE_LONG:
204         g_string_append(tmpstr, "long");
205         break;
206     }
207     break;
208   case IDLN_TYPE_STRING:
209     retval = "CORBA_string";    /* this is non-standard! */
210     break;
211   case IDLN_TYPE_OCTET:
212     retval = "CORBA_octet";
213     break;
214   case IDLN_TYPE_WIDE_STRING:
215     retval = "CORBA_wstring";   /* this is non-standard! */
216     break;
217   case IDLN_TYPE_CHAR:
218     retval = "CORBA_char";
219     break;
220   case IDLN_TYPE_WIDE_CHAR:
221     retval = "CORBA_wchar";
222     break;
223   case IDLN_TYPE_BOOLEAN:
224     retval = "CORBA_boolean";
225     break;
226   case IDLN_TYPE_STRUCT:
227     return forb_cbe_get_typespec_str(IDL_TYPE_STRUCT(tree).ident);
228   case IDLN_EXCEPT_DCL:
229     return forb_cbe_get_typespec_str(IDL_EXCEPT_DCL(tree).ident);
230   case IDLN_TYPE_ARRAY:
231     return forb_cbe_get_typespec_str(IDL_TYPE_ARRAY(tree).ident);
232   case IDLN_TYPE_UNION:
233     return forb_cbe_get_typespec_str(IDL_TYPE_UNION(tree).ident);
234   case IDLN_TYPE_ENUM:
235     return forb_cbe_get_typespec_str(IDL_TYPE_ENUM(tree).ident);
236   case IDLN_IDENT:
237     return IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(tree), "_", 0);
238   case IDLN_PARAM_DCL:
239     return forb_cbe_get_typespec_str(IDL_PARAM_DCL(tree).param_type_spec);
240   case IDLN_TYPE_SEQUENCE:
241     {
242         IDL_tree subtype = IDL_TYPE_SEQUENCE(tree).simple_type_spec;
243         char *ctmp, *base;
244         ctmp = forb_cbe_get_typespec_str(subtype);
245         /* We should have built-in alias to make this next line not needed */
246         base = forb_cbe_type_is_builtin(subtype)
247           ? ctmp + strlen("CORBA_") : ctmp;
248         retval = g_strdup_printf( "CORBA_sequence_%s", base);
249         g_free(ctmp);
250         return retval;
251     }
252     break;
253   case IDLN_NATIVE:
254     retval = "gpointer";
255     break;
256   case IDLN_FORWARD_DCL:
257   case IDLN_INTERFACE:
258     return forb_cbe_get_typespec_str(IDL_INTERFACE(tree).ident);
259   case IDLN_TYPE_OBJECT:
260     retval = "CORBA_Object";
261     break;
262   case IDLN_TYPE_TYPECODE:
263     retval = "CORBA_TypeCode";
264     break;
265   default:
266     g_error("We were asked to get a typename for a %s",
267             IDL_tree_type_names[IDL_NODE_TYPE(tree)]);
268     break;
269   }
270
271   if (retval)
272     return g_strdup (retval);
273   else
274     return g_string_free (tmpstr, FALSE);
275 }
276
277 void
278 forb_cbe_write_typespec(FILE *of, IDL_tree tree)
279 {
280     char *name = forb_cbe_get_typespec_str(tree);
281     fprintf( of, name);
282     g_free(name);
283 }
284
285 /**
286     Parameters (e.g., arguments to methods, and the return value
287     have some complicated rules in the C mapping for how many
288     levels of pointer and the exact type involved. This function
289     generates the externally visible parameter type.
290
291     Note the hack below because "const CORBA_string" is not
292     promotable to "const CORBA_char*" (the later the standard
293     to which apps are written, while the former is what would
294     be produced without the hack).
295 **/
296 static char *
297 forb_cbe_write_param_typespec_str(IDL_tree ts, IDL_ParamRole role)
298 {
299         int      i, n;
300         gboolean isSlice;
301         char    *name;
302         GString *str = g_string_sized_new (23);
303         IDL_tree typedef_spec;
304         char *typedef_name;
305
306         n = oidl_param_info (ts, role, &isSlice);
307         name = forb_cbe_get_typespec_str (ts);
308
309         if ( role == DATA_IN ) {
310                 /* We want to check if this is a typedef for CORBA_string so we can do special handling 
311                  * in that case. 
312                  */
313                 typedef_spec = forb_cbe_get_typespec (ts);
314                 typedef_name = forb_cbe_get_typespec_str (typedef_spec);
315
316                 g_string_printf (str, "const %s", 
317                                  !strcmp (typedef_name, "CORBA_string") ?
318                                  "CORBA_char *" : name);
319
320                 g_free (typedef_name);
321         } else
322                 g_string_printf (str, "%s", name);
323
324         g_free (name);
325
326         if ( isSlice )
327                 g_string_append (str, "_slice");
328
329         for (i = 0; i < n; i++)
330                 g_string_append_c (str, '*');
331
332         return g_string_free (str, FALSE);
333 }
334
335 static void
336 forb_cbe_write_param_typespec_raw (FILE *of, IDL_tree ts, IDL_ParamRole role)
337 {
338     char *str;
339     str = forb_cbe_write_param_typespec_str (ts, role);
340     fprintf (of, str);
341     g_free (str);
342 }
343
344 void
345 forb_cbe_write_param_typespec(FILE *of, IDL_tree tree) {
346     IDL_tree            ts = NULL /* Quiet gcc */;
347     IDL_ParamRole       role = 0 /* Quiet gcc */;
348
349     switch ( IDL_NODE_TYPE(tree) ) {
350     case IDLN_OP_DCL: /* means return value of method */
351         ts = IDL_OP_DCL(tree).op_type_spec;
352         role = DATA_RETURN;
353         break;
354     case IDLN_PARAM_DCL: /* one of the parameters */
355         ts = IDL_PARAM_DCL(tree).param_type_spec;
356         role = oidl_attr_to_paramrole(IDL_PARAM_DCL(tree).attr);
357         break;
358     default:
359         g_assert_not_reached();
360     }
361     forb_cbe_write_param_typespec_raw(of, ts, role);
362 }
363
364 void
365 forb_cbe_op_write_proto (FILE       *of,
366                           IDL_tree    op,
367                           const char *nom_prefix,
368                           gboolean    for_epv)
369 {
370         IDL_tree  sub;
371         char     *id;
372
373         g_assert (IDL_NODE_TYPE(op) == IDLN_OP_DCL);
374
375         forb_cbe_write_param_typespec (of, op);
376
377         id = IDL_ns_ident_to_qstring (
378                 IDL_IDENT_TO_NS (IDL_INTERFACE (
379                         IDL_get_parent_node (op, IDLN_INTERFACE, NULL)).ident), "_", 0);
380
381         if (for_epv)
382                 fprintf (of, "\t(*%s%s)", nom_prefix ? nom_prefix : "",
383                          IDL_IDENT(IDL_OP_DCL(op).ident).str);
384         else 
385                 fprintf (of, " %s%s_%s", nom_prefix ? nom_prefix : "",
386                          id, IDL_IDENT (IDL_OP_DCL (op).ident).str);
387
388         fprintf (of, "(");
389
390 /*      if (for_epv) */
391 /*              fprintf (of, "PortableServer_Servant _servant, "); */
392 /*      else */
393                 fprintf (of, "%s _obj, ", id);
394
395         g_free (id);
396
397         for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
398                 IDL_tree parm = IDL_LIST (sub).data;
399
400                 forb_cbe_write_param_typespec (of, parm);
401
402                 fprintf (of, " %s, ", IDL_IDENT (IDL_PARAM_DCL (parm).simple_declarator).str);
403         }
404
405         if (IDL_OP_DCL (op).context_expr)
406                 fprintf (of, "CORBA_Context _ctx, ");
407
408         fprintf (of, "CORBA_Environment *ev)");
409 }
410
411 /* Writes the value of the constant in 'tree' to file handle 'of' */
412 static char *
413 forb_cbe_get_const(IDL_tree tree)
414 {
415   char *opc = NULL, *retval, *ctmp;
416   GString *tmpstr = g_string_new(NULL);
417
418   switch(IDL_NODE_TYPE(tree)) {
419   case IDLN_BOOLEAN:
420     g_string_printf(tmpstr, "%s", IDL_BOOLEAN(tree).value?"CORBA_TRUE":"CORBA_FALSE");
421     break;
422   case IDLN_CHAR:
423     g_string_printf(tmpstr, "'\\x%X'", *(unsigned char *)IDL_CHAR(tree).value);
424     break;
425   case IDLN_FLOAT:
426     g_string_printf(tmpstr, "%f", IDL_FLOAT(tree).value);
427     break;
428   case IDLN_INTEGER:
429     g_string_printf(tmpstr, "%" IDL_LL "d", IDL_INTEGER(tree).value);
430     break;
431   case IDLN_STRING:
432     g_string_printf(tmpstr, "\"%s\"", IDL_STRING(tree).value);
433     break;
434   case IDLN_WIDE_CHAR:
435     g_string_printf(tmpstr, "L'%ls'", IDL_WIDE_CHAR(tree).value);
436     break;
437   case IDLN_WIDE_STRING:
438     g_string_printf(tmpstr, "L\"%ls\"", IDL_WIDE_STRING(tree).value);
439     break;
440   case IDLN_BINOP:
441     g_string_printf(tmpstr, "(");
442     ctmp = forb_cbe_get_const(IDL_BINOP(tree).left);
443     g_string_append(tmpstr, ctmp);
444     g_free(ctmp);
445     switch(IDL_BINOP(tree).op) {
446     case IDL_BINOP_OR:
447       opc = "|";
448       break;
449     case IDL_BINOP_XOR:
450       opc = "^";
451       break;
452     case IDL_BINOP_AND:
453       opc = "&";
454       break;
455     case IDL_BINOP_SHR:
456       opc = ">>";
457       break;
458     case IDL_BINOP_SHL:
459       opc = "<<";
460       break;
461     case IDL_BINOP_ADD:
462       opc = "+";
463       break;
464     case IDL_BINOP_SUB:
465       opc = "-";
466       break;
467     case IDL_BINOP_MULT:
468       opc = "*";
469       break;
470     case IDL_BINOP_DIV:
471       opc = "/";
472       break;
473     case IDL_BINOP_MOD:
474       opc = "%";
475       break;
476     }
477     g_string_append_printf(tmpstr, " %s ", opc);
478     ctmp = forb_cbe_get_const(IDL_BINOP(tree).right);
479     g_string_append_printf(tmpstr, "%s)", ctmp);
480     g_free(ctmp);
481     break;
482   case IDLN_UNARYOP:
483     switch(IDL_UNARYOP(tree).op) {
484     case IDL_UNARYOP_PLUS: opc = "+"; break;
485     case IDL_UNARYOP_MINUS: opc = "-"; break;
486     case IDL_UNARYOP_COMPLEMENT: opc = "~"; break;
487     }
488     ctmp = forb_cbe_get_const(IDL_UNARYOP(tree).operand);
489     g_string_printf(tmpstr, "%s%s", opc, ctmp);
490     g_free(ctmp);
491     break;
492   case IDLN_IDENT:
493     {
494       char *id;
495       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(tree), "_", 0);
496       g_string_printf(tmpstr, "%s", id);
497       g_free(id);
498     }
499     break;
500   default:
501     g_error("We were asked to print a constant for %s", IDL_tree_type_names[tree->_type]);
502     break;
503   }
504
505   retval = tmpstr->str;
506
507   g_string_free(tmpstr, FALSE);
508
509   return retval;
510 }
511
512 void
513 forb_cbe_write_const(FILE *of, IDL_tree tree)
514 {
515   char *ctmp;
516
517   ctmp = forb_cbe_get_const(tree);
518   fprintf(of, "%s", ctmp);
519   g_free(ctmp);
520 }
521
522 /* This is the WORST HACK in the WORLD, really truly, but the C preprocessor doesn't allow us to use
523    strings, so we have to work around it by using individual characters. */
524 void
525 forb_cbe_id_define_hack(FILE *fh, const char *def_prefix, const char *def_name, const char *def_value)
526 {
527   int i, n;
528   n = strlen(def_value);
529   for(i = 0; i < n; i++)
530     fprintf(fh, "#define %s_%s_%d '%c'\n", def_prefix, def_name, i, def_value[i]);
531 }
532
533 void
534 forb_cbe_id_cond_hack(FILE *fh, const char *def_prefix, const char *def_name, const char *def_value)
535 {
536   int i, n;
537   n = strlen(def_value);
538   if(n <= 0)
539     return;
540
541   fprintf(fh, "(");
542
543   for(i = 0; i < n; i++)
544     fprintf(fh, "%s (%s_%s_%d == '%c') \\\n", i?"&&":"", def_prefix, def_name, i, def_value[i]);
545   fprintf(fh, ")");
546 }
547
548 #define BASE_TYPES \
549              IDLN_TYPE_INTEGER: \
550         case IDLN_TYPE_FLOAT: \
551         case IDLN_TYPE_ENUM: \
552         case IDLN_TYPE_BOOLEAN: \
553         case IDLN_TYPE_CHAR: \
554         case IDLN_TYPE_WIDE_CHAR: \
555         case IDLN_TYPE_OCTET
556
557 #define STRING_TYPES \
558              IDLN_TYPE_STRING: \
559         case IDLN_TYPE_WIDE_STRING
560
561 #define OBJREF_TYPES \
562              IDLN_TYPE_OBJECT: \
563         case IDLN_INTERFACE: \
564         case IDLN_FORWARD_DCL
565
566 static const char *
567 forb_cbe_flatten_ref (IDL_ParamRole role, IDL_tree typespec)
568 {
569         gboolean is_fixed;
570
571         is_fixed = forb_cbe_type_is_fixed_length (typespec);
572
573         switch (role) {
574         case DATA_IN:
575                 switch (IDL_NODE_TYPE (typespec)) {
576                 case BASE_TYPES:
577                 case STRING_TYPES:
578                 case OBJREF_TYPES:
579                 case IDLN_TYPE_TYPECODE:
580                 case IDLN_NATIVE:
581                         return "(gpointer)&";
582
583                 case IDLN_TYPE_STRUCT:
584                 case IDLN_TYPE_UNION:
585                 case IDLN_TYPE_ANY:
586                 case IDLN_TYPE_SEQUENCE:
587                 case IDLN_TYPE_ARRAY:
588                         return "(gpointer)";
589                         
590                 default:
591                 case IDLN_TYPE_FIXED:
592                         g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
593                 };
594                 return NULL;
595
596         case DATA_INOUT:
597                 switch (IDL_NODE_TYPE (typespec)) {
598                 case BASE_TYPES:
599                 case STRING_TYPES:
600                 case OBJREF_TYPES:
601                 case IDLN_TYPE_TYPECODE:
602                 case IDLN_TYPE_STRUCT:
603                 case IDLN_TYPE_UNION:
604                 case IDLN_TYPE_ARRAY:
605                 case IDLN_NATIVE:
606                 case IDLN_TYPE_ANY:
607                 case IDLN_TYPE_SEQUENCE:
608                         return "";
609
610                 default:
611                 case IDLN_TYPE_FIXED:
612                         g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
613                 };
614                 return NULL;
615
616         case DATA_OUT:
617                 switch (IDL_NODE_TYPE (typespec)) {
618                 case BASE_TYPES:
619                 case STRING_TYPES:
620                 case OBJREF_TYPES:
621                 case IDLN_TYPE_TYPECODE:
622                 case IDLN_NATIVE:
623                         return "&";
624
625                 case IDLN_TYPE_STRUCT:
626                 case IDLN_TYPE_UNION:
627                 case IDLN_TYPE_ARRAY:
628                         if (is_fixed)
629                                 return "&";
630                         else /* drop through */
631
632                 case IDLN_TYPE_SEQUENCE:
633                 case IDLN_TYPE_ANY:
634                         return "";
635
636                 default:
637                 case IDLN_TYPE_FIXED:
638                         g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
639                 };
640                 return NULL;
641
642         case DATA_RETURN:
643                 g_error ("No data return handler");
644                 return NULL;
645         }
646
647         return NULL;
648 }
649
650 void
651 forb_cbe_flatten_args (IDL_tree tree, FILE *of, const char *name)
652 {
653         int i = 0;
654         IDL_tree l;
655
656         for (l = IDL_OP_DCL(tree).parameter_dcls; l;
657              l = IDL_LIST(l).next)
658                 i++;
659
660         fprintf (of, "gpointer %s[%d];\n", name, i);
661         
662         i = 0;
663         for (l = IDL_OP_DCL(tree).parameter_dcls; l;
664              l = IDL_LIST(l).next) {
665                 IDL_tree decl = IDL_LIST (l).data;
666                 IDL_tree tspec = forb_cbe_get_typespec (decl);
667                 IDL_ParamRole r = 0;
668
669                 switch(IDL_PARAM_DCL(decl).attr) {
670                 case IDL_PARAM_IN:    r = DATA_IN;    break;
671                 case IDL_PARAM_INOUT: r = DATA_INOUT; break;
672                 case IDL_PARAM_OUT:   r = DATA_OUT;   break;
673                 default:
674                         g_error("Unknown IDL_PARAM type");
675                 }
676                 
677                 fprintf (of, "%s[%d] = %s%s;\n",
678                          name, i,
679                          forb_cbe_flatten_ref (r, tspec),
680                          IDL_IDENT (IDL_PARAM_DCL (decl).simple_declarator).str);
681                 i++;
682         }
683 }
684
685 static char *
686 forb_cbe_unflatten_ref (IDL_ParamRole role, IDL_tree typespec)
687 {
688         gboolean is_fixed;
689         char    *typestr;
690         char    *retval;
691
692         is_fixed = forb_cbe_type_is_fixed_length (typespec);
693
694         typestr = forb_cbe_write_param_typespec_str (typespec, role);
695
696         switch (role) {
697         case DATA_IN:
698                 switch (IDL_NODE_TYPE (typespec)) {
699                 case BASE_TYPES:
700                 case STRING_TYPES:
701                 case OBJREF_TYPES:
702                 case IDLN_TYPE_TYPECODE:
703                 case IDLN_NATIVE:
704                         retval = g_strdup_printf ("*(%s *)", typestr);
705                         break;
706
707
708                 case IDLN_TYPE_ARRAY:
709                         retval = g_strdup_printf ("(%s_slice *)", typestr);
710                         break;
711
712                 case IDLN_TYPE_STRUCT:
713                 case IDLN_TYPE_UNION:
714                 case IDLN_TYPE_ANY:
715                 case IDLN_TYPE_SEQUENCE:
716                         retval = g_strdup_printf ("(%s)", typestr);
717                         break;
718                         
719                 default:
720                 case IDLN_TYPE_FIXED:
721                         g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
722                         retval = NULL;
723                         break;
724                 };
725                 break;
726
727         case DATA_INOUT:
728                 switch (IDL_NODE_TYPE (typespec)) {
729                 case IDLN_TYPE_ARRAY:
730                         retval = g_strdup_printf ("(%s_slice *)", typestr);
731                         break;
732
733                 case BASE_TYPES:
734                 case STRING_TYPES:
735                 case OBJREF_TYPES:
736                 case IDLN_TYPE_TYPECODE:
737                 case IDLN_TYPE_STRUCT:
738                 case IDLN_TYPE_UNION:
739                 case IDLN_NATIVE:
740                 case IDLN_TYPE_ANY:
741                 case IDLN_TYPE_SEQUENCE:
742                         retval = g_strdup_printf ("(%s)", typestr);
743                         break;
744
745                 default:
746                 case IDLN_TYPE_FIXED:
747                         g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
748                         retval = NULL;
749                         break;
750                 };
751                 break;
752
753         case DATA_OUT:
754                 switch (IDL_NODE_TYPE (typespec)) {
755                 case BASE_TYPES:
756                 case STRING_TYPES:
757                 case OBJREF_TYPES:
758                 case IDLN_TYPE_TYPECODE:
759                 case IDLN_NATIVE:
760                         retval = g_strdup_printf ("*(%s *)", typestr);
761                         break;
762
763                 case IDLN_TYPE_ARRAY:
764                         if (is_fixed) {
765                                 retval = g_strdup_printf ("*(%s_slice **)", typestr);
766                                 break;
767                         }
768                         /* drop through */
769
770                 case IDLN_TYPE_STRUCT:
771                 case IDLN_TYPE_UNION:
772                         if (is_fixed) {
773                                 retval = g_strdup_printf ("*(%s *)", typestr);
774                                 break;
775                         }
776                         /* drop through */
777
778                 case IDLN_TYPE_SEQUENCE:
779                 case IDLN_TYPE_ANY:
780                         retval = g_strdup_printf ("(%s)", typestr);
781                         break;
782
783                 default:
784                 case IDLN_TYPE_FIXED:
785                         g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
786                         retval = NULL;
787                         break;
788                 };
789                 break;
790
791         case DATA_RETURN:
792         default:
793                 g_error ("No data return handler");
794                 retval = NULL;
795                 break;
796         }
797
798         g_free (typestr);
799
800         return retval;
801 }
802
803 void
804 forb_cbe_unflatten_args (IDL_tree tree, FILE *of, const char *name)
805 {
806         IDL_tree l;
807         int      i = 0;
808
809         for (l = IDL_OP_DCL(tree).parameter_dcls; l;
810              l = IDL_LIST(l).next) {
811                 IDL_tree decl = IDL_LIST (l).data;
812                 IDL_tree tspec = forb_cbe_get_typespec (decl);
813                 IDL_ParamRole r = 0;
814                 char *unflatten;
815
816                 switch(IDL_PARAM_DCL(decl).attr) {
817                 case IDL_PARAM_IN:    r = DATA_IN;    break;
818                 case IDL_PARAM_INOUT: r = DATA_INOUT; break;
819                 case IDL_PARAM_OUT:   r = DATA_OUT;   break;
820                 default:
821                         g_error("Unknown IDL_PARAM type");
822                 }
823
824                 unflatten = forb_cbe_unflatten_ref (r, tspec);
825                 fprintf (of, "%s%s[%d], ", unflatten, name, i++);
826                 g_free (unflatten);
827         }
828 }