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