3 * - By John Hodge (thePowersGang)
6 * - Metalanguage-to-Environment Interface
11 #include <udi_internal.h>
14 tUDI_DeferredCall DCall;
15 const udi_mei_op_template_t *mei_op;
19 void _udi_mei_call_unmarshal(tUDI_DeferredCall *DCall)
21 tUDI_MeiCall *Call = (void*)DCall;
22 const udi_mei_op_template_t *mei_op = Call->mei_op;
23 LOG("%s backend", mei_op->op_name);
24 mei_op->backend_stub(Call->DCall.Handler, Call->DCall.cb, Call+1);
27 void udi_mei_call(udi_cb_t *gcb, udi_mei_init_t *meta_info, udi_index_t meta_ops_num, udi_index_t vec_idx, ...)
29 // ENTER("pgcb pmeta_info imeta_ops_num ivec_idx",
30 // gcb, meta_info, meta_ops_num, vec_idx);
31 const udi_mei_op_template_t *mei_op;
34 udi_mei_ops_vec_template_t *ops = meta_info->ops_vec_template_list;
35 for( ; ops->meta_ops_num && ops->meta_ops_num != meta_ops_num; ops ++ )
37 if( !ops->meta_ops_num ) {
41 mei_op = &ops->op_template_list[vec_idx-1];
46 tUDI_MetaLang *metalang = UDI_int_GetCbType(gcb, &cb_type);
47 if( meta_info != metalang->MeiInfo && mei_op->meta_cb_num != cb_type ) {
48 Log_Warning("UDI", "%s meta cb mismatch want %p:%i got %p:%i",
50 meta_info, mei_op->meta_cb_num,
51 metalang->MeiInfo, cb_type
53 ASSERTC(meta_info, ==, metalang->MeiInfo);
54 ASSERTC(mei_op->meta_cb_num, ==, cb_type);
59 // Determine if indirect call is needed
60 // > check stack depth?
62 int indirect_call = (mei_op->op_category == UDI_MEI_OPCAT_REQ)
63 || (mei_op->op_category == UDI_MEI_OPCAT_IND);
65 LOG("%s %sdirect", mei_op->op_name, (indirect_call ? "in" : ""));
68 udi_op_t *const*ops = UDI_int_ChannelPrepForCall(gcb, metalang, meta_ops_num);
69 udi_op_t *op = ops[vec_idx];
71 // Change ownership of chained cbs
72 size_t chain_ofs = metalang->CbTypes[cb_type].ChainOfs;
75 udi_cb_t *chained_cb = gcb;
76 while( (chained_cb = *(udi_cb_t**)((void*)chained_cb + chain_ofs)) )
77 UDI_int_ChannelFlip(chained_cb);
83 va_start(args, vec_idx);
84 size_t marshal_size = _udi_marshal_values(NULL, mei_op->marshal_layout, args);
86 tUDI_MeiCall *call = malloc(sizeof(tUDI_MeiCall) + marshal_size);
87 call->DCall.Next = NULL;
88 call->DCall.Unmarshal = _udi_mei_call_unmarshal;
90 call->DCall.Handler = op;
91 call->mei_op = mei_op;
92 void *marshal_space = (void*)(call+1);
93 va_start(args, vec_idx);
94 _udi_marshal_values(marshal_space, mei_op->marshal_layout, args);
97 UDI_int_AddDeferred(&call->DCall);
102 va_start(args, vec_idx);
103 mei_op->direct_stub( op, gcb, args );