5
#include "orbit-idl-c-backend.h"
7
static void c_demarshal_generate(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
8
static void c_demarshal_datum(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
9
static void c_demarshal_loop(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
10
static void c_demarshal_switch(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
11
static void c_demarshal_complex(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
12
static void c_demarshal_set(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
13
static void c_demarshal_validate_curptr(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
14
static void c_demarshal_alignfor(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
15
static void c_demarshal_generate_alloc(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi);
16
static void c_demarshal_generate_check(OIDL_Marshal_Length *len, OIDL_C_Marshal_Info *cmi);
20
c_demarshalling_generate(OIDL_Marshal_Node *node, OIDL_C_Info *ci, gboolean in_skels, gboolean subfunc)
22
OIDL_C_Marshal_Info cmi;
25
cmi.last_tail_align = 1;
26
cmi.endian_swap_pass = TRUE;
27
cmi.in_skels = in_skels?1:0;
28
cmi.subfunc = subfunc;
30
cmi.marshal_error_exit = "goto _ORBIT_demarshal_error";
31
cmi.curptr_in_local = FALSE;
32
cmi.alloc_on_stack = in_skels;
34
cmi.orb_name = "ORBIT_SERVANT_TO_ORB(_ORBIT_servant)";
36
cmi.orb_name = "_ORBIT_recv_buffer->connection->orb_data";
38
if(node->flags & MN_ENDIAN_DEPENDANT)
40
gboolean start_in_local;
41
OIDL_Marshal_Length *len;
44
c_demarshal_validate_curptr(node, &cmi);
45
start_in_local = cmi.curptr_in_local;
46
c_demarshal_alignfor(node, &cmi);
47
cmi.last_tail_align = node->iiop_head_align; /* We already did the alignment outside of the 'if' */
50
c_demarshal_generate_check(len, &cmi);
54
fprintf(ci->fh, "if(giop_msg_conversion_needed(_ORBIT_recv_buffer)) {\n");
55
c_demarshal_generate(node, &cmi);
56
fprintf(ci->fh, "} else {\n");
57
cmi.last_tail_align = node->iiop_head_align; /* We already did the alignment outside of the 'if' */
58
cmi.endian_swap_pass = FALSE;
59
cmi.curptr_in_local = start_in_local;
60
c_demarshal_generate(node, &cmi);
61
fprintf(ci->fh, "}\n");
66
cmi.last_tail_align = 1;
67
cmi.endian_swap_pass = FALSE;
68
cmi.curptr_in_local = FALSE;
69
c_demarshal_generate(node, &cmi);
74
c_demarshal_generate_heap_alloc(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
78
if(!(node->flags & MN_ISSTRING)) /* Strings get handled specially */
80
g_assert(node->nptrs > 0);
82
ctmp2 = orbit_cbe_get_typespec_str(node->tree);
84
ctmp = oidl_marshal_node_valuestr(node);
86
fprintf(cmi->ci->fh, "%s = %s__alloc();\n", ctmp, ctmp2);
92
c_demarshal_generate_alloca_alloc(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
96
if(!(node->flags & MN_ISSTRING))
98
g_assert(node->nptrs > 0);
100
ctmp2 = orbit_cbe_get_typespec_str(node->tree);
102
ctmp = oidl_marshal_node_valuestr(node);
104
fprintf(cmi->ci->fh, "%s = g_alloca(sizeof(%s));\n", ctmp, ctmp2);
109
c_demarshal_generate_alloc(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
117
c_demarshal_generate_heap_alloc(node, cmi);
120
c_demarshal_generate_alloca_alloc(node, cmi);
128
c_demarshal_generate_check(OIDL_Marshal_Length *len, OIDL_C_Marshal_Info *cmi)
132
gboolean is_const = TRUE;
139
char *fqn = oidl_marshal_node_valuestr(len->mult_expr);
142
g_snprintf(len_str, sizeof(len_str), "%d + %s*%s", len->len, len->mult_const, fqn);
146
g_snprintf(len_str, sizeof(len_str), "%d", len->len);
147
curptr_name = cmi->curptr_in_local?"_ORBIT_curptr":"_ORBIT_recv_buffer->cur";
148
fprintf(cmi->ci->fh, "{\nregister const long _ORBIT_checklen = %s;\n", len_str);
150
fprintf(cmi->ci->fh, "if((%s + %s) > _ORBIT_buf_end)\n",
151
curptr_name, "_ORBIT_checklen");
153
fprintf(cmi->ci->fh, "if((%s + %s) < %s || (%s + %s) > _ORBIT_buf_end)\n", curptr_name, "_ORBIT_checklen", curptr_name,
154
curptr_name, "_ORBIT_checklen");
155
fprintf(cmi->ci->fh, "%s;\n", cmi->marshal_error_exit);
156
fprintf(cmi->ci->fh, "}\n");
160
c_demarshal_generate(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
164
if(node->flags & MN_NOMARSHAL) return;
165
if(node->use_count) return;
169
if(!cmi->curptr_in_local && node->flags & MN_NEED_CURPTR_LOCAL)
170
c_demarshal_validate_curptr(node, cmi); /* Help out c_demarshal_generate_check, which will prefer to use the local var */
172
c_demarshal_generate_check(node->pre, cmi);
174
/* This needs to be done _after_ generate_check because we don't
175
want to free the data for a parameter if it cannot possibly be
176
demarshalled - the marshal_error_exit label points to stuff that
177
knows how to free the demarshalled version of that parameter */
178
if(node->marshal_error_exit)
179
cmi->marshal_error_exit = node->marshal_error_exit;
181
if(node->flags & MN_TOPLEVEL)
182
c_demarshal_generate_alloc(node, cmi);
184
c_demarshal_validate_curptr(node, cmi);
188
c_demarshal_datum(node, cmi);
191
c_demarshal_loop(node, cmi);
194
c_demarshal_switch(node, cmi);
196
case MARSHAL_COMPLEX:
197
c_demarshal_complex(node, cmi);
200
c_demarshal_set(node, cmi);
203
g_assert_not_reached();
207
c_demarshal_generate_check(node->post, cmi);
213
c_demarshal_update_curptr(OIDL_Marshal_Node *node, char *sizestr, OIDL_C_Marshal_Info *cmi)
215
if((node->flags & MN_DEMARSHAL_UPDATE_AFTER)
216
|| (node->flags & MN_LOOPED))
217
fprintf(cmi->ci->fh, "_ORBIT_curptr += %s;\n", sizestr);
221
c_demarshal_validate_curptr(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
223
gboolean desired_curptr_in_local_state;
225
if(node->flags & MN_NEED_CURPTR_LOCAL)
226
desired_curptr_in_local_state = TRUE;
227
else if(node->flags & MN_NEED_CURPTR_RECVBUF)
228
desired_curptr_in_local_state = FALSE;
232
if(desired_curptr_in_local_state != cmi->curptr_in_local)
234
if(desired_curptr_in_local_state)
235
fprintf(cmi->ci->fh, "_ORBIT_curptr = _ORBIT_recv_buffer->cur;\n");
237
fprintf(cmi->ci->fh, "_ORBIT_recv_buffer->cur = _ORBIT_curptr;\n");
239
cmi->curptr_in_local = desired_curptr_in_local_state;
244
c_demarshal_alignfor(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
246
/* do we need to generate an alignment space? */
247
if(node->iiop_head_align > cmi->last_tail_align)
249
fprintf(cmi->ci->fh, "%s = ALIGN_ADDRESS(_ORBIT_curptr, %d);\n",
250
cmi->curptr_in_local?"_ORBIT_curptr":"_ORBIT_recv_buffer->cur",
251
node->iiop_head_align);
254
cmi->last_tail_align = node->iiop_tail_align;
258
c_demarshal_datum(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
262
ctmp = oidl_marshal_node_valuestr(node);
264
c_demarshal_alignfor(node, cmi);
266
if(cmi->endian_swap_pass
267
&& (node->flags & MN_ENDIAN_DEPENDANT)) {
270
n = node->u.datum_info.datum_size * 8;
272
if(node->u.datum_info.needs_bswap)
273
fprintf(cmi->ci->fh, "giop_byteswap((guchar *)&(%s), _ORBIT_curptr, %d);\n", ctmp, node->u.datum_info.datum_size);
275
fprintf(cmi->ci->fh, "(*((guint%d *)&(%s))) = ", n, ctmp);
276
fprintf(cmi->ci->fh, "GUINT%d_SWAP_LE_BE(*((guint%d *)_ORBIT_curptr));\n",
280
fprintf(cmi->ci->fh, "%s = *((", ctmp);
281
orbit_cbe_write_node_typespec(cmi->ci->fh, node);
282
fprintf(cmi->ci->fh, "*)_ORBIT_curptr);\n");
287
g_snprintf(buf, sizeof(buf), "%d", node->u.datum_info.datum_size);
288
c_demarshal_update_curptr(node, buf, cmi);
295
LOOP is the (de)marshalling equivalent of IDL sequence, array, string,
296
and wstring. In all cases, there is a single underlying type ("subtype").
297
Here, we are generating code which demarshals from a variable
298
of a given type, which consists of elements of the type's subtype.
300
- Where is the memory allocated?
301
- Does the variable data need to be munged, either for endianness,
302
format or alignment reasons?
303
- Can the elements be agregated?
304
All of these questions interact with each other.
307
c_demarshal_loop(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
309
char *ctmp, *ctmp_len, *ctmp_loop, *ctmp_contents;
310
gboolean loopvar_set = FALSE;
312
ctmp = oidl_marshal_node_valuestr(node);
313
ctmp_loop = oidl_marshal_node_valuestr(node->u.loop_info.loop_var);
314
ctmp_len = oidl_marshal_node_valuestr(node->u.loop_info.length_var);
315
ctmp_contents = oidl_marshal_node_valuestr(node->u.loop_info.contents);
317
c_demarshal_generate(node->u.loop_info.length_var, cmi);
318
if(node->flags & MN_WIDESTRING)
319
fprintf(cmi->ci->fh, "%s /= sizeof(CORBA_wchar);\n", ctmp_len);
321
if(cmi->alloc_on_stack && (node->u.loop_info.contents->where == MW_Alloca)) {
322
fprintf(cmi->ci->fh, "%s%s = g_alloca(sizeof(%s) * (%s%s));\n", ctmp, (node->flags & MN_ISSEQ)?"._buffer":"",
323
ctmp_contents, ctmp_len, (node->flags & MN_WIDESTRING)?"+1":"");
324
if(node->flags & MN_ISSEQ)
325
fprintf(cmi->ci->fh, "%s._release = CORBA_FALSE;\n", ctmp);
326
} else if(node->u.loop_info.contents->where == MW_Msg
327
|| node->where == MW_Null) {
328
/* No allocation necessary */
329
} else if(node->u.loop_info.contents->where == MW_Heap) {
330
char *tname, *tcname;
332
tname = orbit_cbe_get_typespec_str(node->tree);
333
tcname = orbit_cbe_get_typespec_str(node->u.loop_info.contents->tree);
335
if(node->flags & MN_ISSEQ) {
336
IDL_tree seq = orbit_cbe_get_typespec(node->tree);
337
if(orbit_cbe_type_is_builtin(node->u.loop_info.contents->tree))
338
fprintf(cmi->ci->fh, "%s._buffer = CORBA_sequence_%s_allocbuf(%s);\n", ctmp, tcname+strlen("CORBA_"), ctmp_len);
340
if(IDL_TYPE_SEQUENCE(seq).positive_int_const) {
342
fprintf(cmi->ci->fh,"%s._maximum = ",ctmp);
343
orbit_cbe_write_const(cmi->ci->fh, IDL_TYPE_SEQUENCE(seq).positive_int_const);
344
fprintf(cmi->ci->fh,";\n");
345
fprintf(cmi->ci->fh, "%s._buffer = CORBA_sequence_%s_allocbuf(%s._maximum);\n", ctmp, tcname, ctmp);
348
fprintf(cmi->ci->fh, "%s._maximum = %s._length;\n",ctmp,ctmp);
349
fprintf(cmi->ci->fh, "%s._buffer = CORBA_sequence_%s_allocbuf(%s);\n", ctmp, tcname, ctmp_len);
352
fprintf(cmi->ci->fh, "%s._release = CORBA_TRUE;\n", ctmp);
353
} else if(node->flags & MN_ISSTRING)
354
fprintf(cmi->ci->fh, "%s = CORBA_%sstring_alloc(%s%s);\n", ctmp, (node->flags & MN_WIDESTRING)?"w":"",
356
(node->flags & MN_WIDESTRING)?"+1":"");
360
g_error("Don't know how to allocate node %p", node);
362
if((!cmi->endian_swap_pass || !(node->u.loop_info.contents->flags & MN_ENDIAN_DEPENDANT))
363
&& (node->u.loop_info.contents->flags & MN_COALESCABLE)) {
364
GString *tmpstr, *tmpstr2;
366
c_demarshal_alignfor(node->u.loop_info.contents, cmi);
368
tmpstr = g_string_new(NULL);
369
tmpstr2 = g_string_new(NULL);
370
g_string_printf(tmpstr, "sizeof(%s) * %s", ctmp_contents, ctmp_len);
371
/* XXX badhack - what if 'node' is a pointer thingie? Need to find out whether to append '._buffer' or '->_buffer' */
372
g_string_printf(tmpstr2, "%s%s", ctmp, (node->flags & MN_ISSEQ)?"._buffer":"");
374
if(cmi->alloc_on_stack && (node->u.loop_info.contents->where & MW_Msg))
376
fprintf(cmi->ci->fh, "*(((gulong*)_ORBIT_curptr)-1) = ORBIT_MEMHOW_NONE;\n");
377
fprintf(cmi->ci->fh, "%s = (", tmpstr2->str);
378
orbit_cbe_write_typespec(cmi->ci->fh, node->u.loop_info.contents->tree);
379
fprintf(cmi->ci->fh, "*)_ORBIT_curptr;\n");
382
fprintf(cmi->ci->fh, "memcpy(%s, _ORBIT_curptr, %s);\n", tmpstr2->str, tmpstr->str);
384
c_demarshal_update_curptr(node, tmpstr->str, cmi);
386
g_string_free(tmpstr2, TRUE);
387
g_string_free(tmpstr, TRUE);
389
cmi->last_tail_align = MIN(cmi->last_tail_align, node->u.loop_info.contents->iiop_tail_align);
390
c_demarshal_validate_curptr(node->u.loop_info.contents, cmi); /* We must explicitly do this here,
391
otherwise bad things will happen -
392
it will keep updating local from recvbuf or vice versa,
393
inside the loop, and that is Very Bad(tm) */
394
fprintf(cmi->ci->fh, "for(%s = 0; %s < %s; %s++) {\n", ctmp_loop, ctmp_loop, ctmp_len, ctmp_loop);
395
/* XXX: what does the next line (loop_var) do? Anything useful? */
396
/* c_demarshal_generate(node->u.loop_info.loop_var, cmi); */
397
g_assert(node->u.loop_info.loop_var->flags & MN_NOMARSHAL);
398
/* this next line does the element-by-element work! */
399
c_demarshal_generate(node->u.loop_info.contents, cmi);
400
fprintf(cmi->ci->fh, "}\n\n");
403
if(node->flags & MN_WIDESTRING)
405
/* NUL-terminate it */
407
fprintf(cmi->ci->fh, "%s = %s;\n", ctmp_loop, ctmp_len);
408
fprintf(cmi->ci->fh, "%s = 0;\n", ctmp_contents);
411
g_free(ctmp_contents);
418
c_demarshal_switch(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
422
guint8 last_tail_align;
423
gboolean need_default;
425
c_demarshal_generate(node->u.switch_info.discrim, cmi);
427
last_tail_align = cmi->last_tail_align;
429
ctmp = oidl_marshal_node_valuestr(node->u.switch_info.discrim);
430
fprintf(cmi->ci->fh, "switch(%s) {\n", ctmp);
434
for(ltmp = node->u.switch_info.cases; ltmp; ltmp = g_slist_next(ltmp)) {
436
OIDL_Marshal_Node *sub;
438
cmi->last_tail_align = last_tail_align;
441
g_assert(sub->type == MARSHAL_CASE);
442
if(sub->u.case_info.labels) {
443
for(ltmp2 = sub->u.case_info.labels; ltmp2; ltmp2 = g_slist_next(ltmp2)) {
445
fprintf(cmi->ci->fh, "case ");
446
orbit_cbe_write_const_node(cmi->ci->fh, ltmp2->data);
447
fprintf(cmi->ci->fh, ":\n");
449
fprintf(cmi->ci->fh, "default:\n");
450
need_default = FALSE;
454
fprintf(cmi->ci->fh, "default:\n");
455
need_default = FALSE;
457
c_demarshal_generate(sub->u.case_info.contents, cmi);
458
fprintf(cmi->ci->fh, "break;\n");
461
fprintf(cmi->ci->fh, "default:\nbreak;\n");
463
fprintf(cmi->ci->fh, "}\n");
465
cmi->last_tail_align = node->iiop_tail_align;
469
c_demarshal_complex(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
474
ctmp = oidl_marshal_node_valuestr(node);
479
do_dup = (cmi->alloc_on_stack && (node->where & (MW_Alloca|MW_Msg)))?"CORBA_FALSE":"CORBA_TRUE";
481
switch(node->u.complex_info.type) {
483
g_error("Don't know how to demarshal a CORBA_fixed yet.");
486
fprintf(cmi->ci->fh, "if(ORBit_demarshal_any(_ORBIT_recv_buffer, &(%s), %s, %s))\n%s;\n",
487
ctmp, do_dup, cmi->orb_name, cmi->marshal_error_exit);
489
case CX_CORBA_OBJECT:
490
fprintf(cmi->ci->fh, "if(ORBit_demarshal_object(&(%s), _ORBIT_recv_buffer, %s))\n%s;\n",
491
ctmp, cmi->orb_name, cmi->marshal_error_exit);
493
case CX_CORBA_TYPECODE:
494
fprintf(cmi->ci->fh, "if(ORBit_decode_CORBA_TypeCode(&%s, _ORBIT_recv_buffer))\n%s;\n", ctmp,
495
cmi->marshal_error_exit);
497
case CX_CORBA_CONTEXT:
499
fprintf(cmi->ci->fh, "if(ORBit_Context_demarshal(NULL, &_ctx, _ORBIT_recv_buffer))\n%s;\n",
500
cmi->marshal_error_exit);
503
g_error("Don't know how to demarshal a NATIVE yet.");
505
case CX_MARSHAL_METHOD:
507
OIDL_Type_Marshal_Info *tmi;
510
tmi = oidl_marshal_context_find(cmi->ci->ctxt, node->tree);
512
ctmp = oidl_marshal_node_valuestr(node);
513
ctmp2 = orbit_cbe_get_typespec_str(node->tree);
518
fprintf(cmi->ci->fh, "if(%s_demarshal(_ORBIT_recv_buffer, %s(%s), %s, ev))\n%s;\n", ctmp2,
519
(node->flags & MN_ISSLICE)?"":"&",
521
cmi->marshal_error_exit);
524
fprintf(cmi->ci->fh, "{ gpointer _valref = &(%s);\n", ctmp);
525
fprintf(cmi->ci->fh, "if(ORBit_demarshal_value(TC_%s, &_valref, _ORBIT_recv_buffer, %s, %s))\n%s;\n",
526
ctmp2, do_dup, cmi->orb_name, cmi->marshal_error_exit);
527
fprintf(cmi->ci->fh, "}\n");
530
g_assert_not_reached();
536
g_assert_not_reached();
544
c_demarshal_set(OIDL_Marshal_Node *node, OIDL_C_Marshal_Info *cmi)
546
if((!cmi->endian_swap_pass || !(node->flags & MN_ENDIAN_DEPENDANT))
548
&& (node->flags & MN_COALESCABLE))
552
ctmp = oidl_marshal_node_valuestr(node);
554
c_demarshal_alignfor(node, cmi);
556
fprintf(cmi->ci->fh, "memcpy(&(%s), _ORBIT_curptr, sizeof(%s));\n", ctmp, ctmp);
557
ctmp2 = g_strdup_printf("sizeof(%s)", ctmp);
559
c_demarshal_update_curptr(node, ctmp2, cmi);
566
/* No need to do this if it is coalescable - obviously will be no need to do it then */
567
g_slist_foreach(node->u.set_info.subnodes, (GFunc)c_demarshal_generate_alloc, cmi);
569
g_slist_foreach(node->u.set_info.subnodes, (GFunc)c_demarshal_generate, cmi);