1 #include "config.h"
2 
3 #include "orbit-idl-c-backend.h"
4 
5 #include <string.h>
6 
7 typedef struct {
8 	OIDL_C_Info *ci;
9 	GSList      *oplist;
10 	int          curlevel;
11 } CBESkelInterfaceTraverseInfo;
12 
13 typedef struct {
14 	char     *iface_id;
15 	char     *opname;
16 	IDL_tree  op;
17 	int       idx;
18 } CBESkelOpInfo;
19 
20 static void cbe_skel_do_interface(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
21 
22 static void
ck_output_poastuff(IDL_tree tree,OIDL_Run_Info * rinfo,OIDL_C_Info * ci)23 ck_output_poastuff(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
24 {
25   if( !tree || (tree->declspec & IDLF_DECLSPEC_PIDL)!=0 )
26     return;
27 
28   switch(IDL_NODE_TYPE(tree)) {
29   case IDLN_MODULE:
30     ck_output_poastuff(IDL_MODULE(tree).definition_list, rinfo, ci);
31     break;
32   case IDLN_LIST:
33     {
34       IDL_tree sub;
35       for(sub = tree; sub; sub = IDL_LIST(sub).next) {
36 	ck_output_poastuff(IDL_LIST(sub).data, rinfo, ci);
37       }
38     }
39     break;
40   case IDLN_INTERFACE:
41     cbe_skel_do_interface(tree, rinfo, ci);
42     break;
43   default:
44     break;
45   }
46 }
47 
48 static gint
cbe_skel_compare_op_dcls(CBESkelOpInfo * op1,CBESkelOpInfo * op2)49 cbe_skel_compare_op_dcls(CBESkelOpInfo *op1, CBESkelOpInfo *op2)
50 {
51   return strcmp(op1->opname, op2->opname);
52 }
53 
54 static void
cbe_skel_free_op_info(CBESkelOpInfo * op)55 cbe_skel_free_op_info(CBESkelOpInfo *op)
56 {
57   g_free(op->opname);
58   g_free(op->iface_id);
59   g_free(op);
60 }
61 
62 static void
cbe_skel_interface_add_relayer(IDL_tree intf,CBESkelInterfaceTraverseInfo * iti)63 cbe_skel_interface_add_relayer (IDL_tree intf, CBESkelInterfaceTraverseInfo *iti)
64 {
65   CBESkelOpInfo *newopi;
66   IDL_tree curitem, curdcl, curattr, curattrdcl;
67   char *iface_id;
68   int   idx = 0;
69 
70   iface_id =
71     IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(intf).ident),
72 			    "_", 0);
73 
74   for(curitem = IDL_INTERFACE(intf).body; curitem;
75       curitem = IDL_LIST(curitem).next) {
76     curdcl = IDL_LIST(curitem).data;
77 
78     switch(IDL_NODE_TYPE(curdcl)) {
79     case IDLN_OP_DCL:
80       newopi = g_new0(CBESkelOpInfo, 1);
81       newopi->iface_id = g_strdup(iface_id);
82       newopi->opname = g_strdup(IDL_IDENT(IDL_OP_DCL(curdcl).ident).str);
83       newopi->idx = idx++;
84       iti->oplist = g_slist_insert_sorted(iti->oplist, newopi,
85 					  (GCompareFunc)cbe_skel_compare_op_dcls);
86       break;
87     case IDLN_ATTR_DCL:
88       for(curattr = IDL_ATTR_DCL(curdcl).simple_declarations;
89 	  curattr; curattr = IDL_LIST(curattr).next) {
90 	curattrdcl = IDL_LIST(curattr).data;
91 
92 	newopi = g_new0(CBESkelOpInfo, 1);
93 	newopi->iface_id = g_strdup(iface_id);
94 	newopi->opname = g_strdup_printf("_get_%s", IDL_IDENT(curattrdcl).str);
95 	newopi->idx = idx++;
96 	iti->oplist = g_slist_insert_sorted(iti->oplist, newopi,
97 					    (GCompareFunc)cbe_skel_compare_op_dcls);
98 	if(!IDL_ATTR_DCL(curdcl).f_readonly) {
99 	  newopi = g_new0(CBESkelOpInfo, 1);
100 	  newopi->iface_id = g_strdup(iface_id);
101 	  newopi->opname = g_strdup_printf("_set_%s", IDL_IDENT(curattrdcl).str);
102 	  newopi->idx = idx++;
103 	  iti->oplist = g_slist_insert_sorted(iti->oplist, newopi,
104 					      (GCompareFunc)cbe_skel_compare_op_dcls);
105 	}
106       }
107       break;
108     default:
109       break;
110     }
111   }
112 
113   g_free(iface_id);
114 }
115 
116 static void
cbe_skel_interface_print_relayers(const CBESkelInterfaceTraverseInfo * iti)117 cbe_skel_interface_print_relayers(const CBESkelInterfaceTraverseInfo *iti)
118 {
119   CBESkelInterfaceTraverseInfo subiti = *iti;
120   GSList *curnode;
121   CBESkelOpInfo *opi;
122   char curchar;
123 
124   curnode = iti->oplist;
125   subiti.curlevel = iti->curlevel+1;
126   fprintf(iti->ci->fh, "switch(opname[%d]) {\n", iti->curlevel);
127   while(curnode) {
128     opi = (CBESkelOpInfo *)curnode->data;
129     if(iti->curlevel > strlen(opi->opname)) {
130       curnode = g_slist_next(curnode);
131       continue;
132     }
133     curchar = opi->opname[iti->curlevel];
134     if(curchar)
135       fprintf(iti->ci->fh, "case '%c':\n", curchar);
136     else
137       fprintf(iti->ci->fh, "case '\\0':\n");
138     subiti.oplist = NULL;
139     while(curnode && ((CBESkelOpInfo *)curnode->data)->opname[iti->curlevel]
140 	  == curchar) {
141       subiti.oplist = g_slist_append(subiti.oplist, curnode->data);
142       curnode = g_slist_next(curnode);
143     }
144 
145     if(g_slist_length(subiti.oplist) > 1) {
146       if(curchar)
147 	cbe_skel_interface_print_relayers(&subiti);
148       else
149 	g_error("two ops with same name!!!!");
150     } else {
151       if(strlen(opi->opname + iti->curlevel))
152 	fprintf(iti->ci->fh, "if(strcmp((opname + %d), \"%s\")) break;\n",
153 		iti->curlevel + 1, opi->opname + iti->curlevel+1);
154       fprintf(iti->ci->fh, "*impl = (gpointer)servant->vepv->%s_epv->%s;\n",
155 	      opi->iface_id, opi->opname);
156       fprintf(iti->ci->fh, "{ORBit_IInterface *volatile _t_=&%s__iinterface;*m_data = (gpointer)&_t_->methods._buffer [%d];}\n",
157 	      opi->iface_id, opi->idx);
158       fprintf(iti->ci->fh, "return (ORBitSmallSkeleton)_ORBIT_skel_small_%s_%s;\n",
159 	      opi->iface_id, opi->opname);
160     }
161     fprintf(iti->ci->fh, "break;\n");
162     g_slist_free(subiti.oplist);
163   }
164   fprintf(iti->ci->fh, "default: break; \n}\n");
165 }
166 
167 static void
cbe_skel_interface_print_relayer(IDL_tree tree,OIDL_Run_Info * rinfo,OIDL_C_Info * ci)168 cbe_skel_interface_print_relayer(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
169 {
170   char *id;
171   CBESkelInterfaceTraverseInfo iti;
172 
173   id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(tree).ident), "_", 0);
174   fprintf(ci->fh, "static ORBitSmallSkeleton get_skel_small_%s(POA_%s *servant,\nconst char *opname,"
175 	  "gpointer *m_data, gpointer *impl)\n{\n", id, id);
176 
177   iti.ci = ci;
178   iti.oplist = NULL;
179   iti.curlevel = 0;
180 
181   IDL_tree_traverse_parents(tree,
182 			    (GFunc)cbe_skel_interface_add_relayer, &iti);
183 
184   cbe_skel_interface_print_relayers(&iti);
185 
186   g_slist_foreach(iti.oplist, (GFunc)cbe_skel_free_op_info, NULL);
187   g_slist_free(iti.oplist);
188 
189   fprintf(ci->fh, "return NULL;\n");
190   fprintf(ci->fh, "}\n\n");
191 
192   g_free(id);
193 }
194 
195 typedef struct {
196 	OIDL_C_Info *ci;
197 	const char  *for_id;
198 } CBESkelVEPVMapTraverseInfo;
199 
200 static void
cbe_skel_interface_print_vepvmap_offsets(IDL_tree node,CBESkelVEPVMapTraverseInfo * ti)201 cbe_skel_interface_print_vepvmap_offsets (IDL_tree node, CBESkelVEPVMapTraverseInfo *ti)
202 {
203 	char *id;
204 	id = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (IDL_INTERFACE (node).ident), "_", 0);
205 	fprintf (ti->ci->fh, "(CORBA_unsigned_long) %s__classid,\n", id);
206 	fprintf (ti->ci->fh, "ORBIT_VEPV_OFFSET (POA_%s__vepv, %s_epv),\n", ti->for_id, id);
207 	g_free (id);
208 }
209 
210 static void
cbe_skel_do_interface(IDL_tree tree,OIDL_Run_Info * rinfo,OIDL_C_Info * ci)211 cbe_skel_do_interface(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
212 {
213   char *id, *id2;
214   IDL_tree curitem, pnt;
215   int i;
216   CBESkelVEPVMapTraverseInfo ti;
217 
218   /* PIDL methods dont have normal skel functions. */
219   for ( pnt=tree; pnt; pnt=IDL_NODE_UP(pnt) ) {
220       if ( pnt->declspec & IDLF_DECLSPEC_PIDL )
221 	return;
222   }
223 
224   id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(tree).ident), "_", 0);
225 
226   cbe_skel_interface_print_relayer(tree, rinfo, ci);
227 
228   fprintf(ci->fh,
229 	  "void POA_%s__init(PortableServer_Servant servant,\nCORBA_Environment *env)\n",
230 	  id);
231   fprintf(ci->fh, "{\n");
232   fprintf(ci->fh,"  static PortableServer_ClassInfo class_info = {");
233 
234   fprintf(ci->fh, "NULL, (ORBit_small_impl_finder)&get_skel_small_%s, ", id);
235 
236   fprintf(ci->fh,"\"%s\", &%s__classid, NULL, &%s__iinterface};\n",
237 	  IDL_IDENT(IDL_INTERFACE(tree).ident).repo_id, id, id);
238 
239   fprintf(ci->fh,"  PortableServer_ServantBase__init ("
240 	         "       ((PortableServer_ServantBase *)servant), env);\n");
241 
242   for(curitem = IDL_INTERFACE(tree).inheritance_spec; curitem;
243       curitem = IDL_LIST(curitem).next) {
244     id2 = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_LIST(curitem).data),
245 				  "_", 0);
246     fprintf(ci->fh, "  POA_%s__init(servant, env);\n", id2);
247     g_free(id2);
248   }
249 
250   /* registering after other __inits() makes the classids increment nicely. */
251   fprintf (ci->fh, "   ORBit_skel_class_register (&class_info,\n");
252   fprintf (ci->fh, "   (PortableServer_ServantBase *)servant, POA_%s__fini,\n", id);
253   fprintf (ci->fh, "   ORBIT_VEPV_OFFSET (POA_%s__vepv, %s_epv),\n", id, id);
254   ti.for_id = id; ti.ci = ci;
255   IDL_tree_traverse_parents_full (tree, (GFunc) cbe_skel_interface_print_vepvmap_offsets, &ti, FALSE);
256   fprintf (ci->fh, "   (CORBA_unsigned_long) 0);");
257 
258   fprintf(ci->fh, "}\n\n");
259 
260   fprintf(ci->fh,
261 	  "void POA_%s__fini(PortableServer_Servant servant,\nCORBA_Environment *env)\n",
262 	  id);
263   fprintf(ci->fh, "{\n");
264   if(IDL_INTERFACE(tree).inheritance_spec)
265     {
266       for(i = IDL_list_length(IDL_INTERFACE(tree).inheritance_spec) - 1;
267 	  i >= 0; i--) {
268 	curitem = IDL_list_nth(IDL_INTERFACE(tree).inheritance_spec, i);
269 	id2 = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_LIST(curitem).data),
270 				      "_", 0);
271 	/* XXX fixme - this is going to call ServantBase__fini multiple times */
272 	fprintf(ci->fh, "  POA_%s__fini(servant, env);\n",
273 		id2);
274 	g_free(id2);
275       }
276     }
277   fprintf(ci->fh, "  PortableServer_ServantBase__fini(servant, env);\n");
278   fprintf(ci->fh, "}\n\n");
279 
280   g_free(id);
281 }
282 
283 void
orbit_idl_output_c_skeletons(IDL_tree tree,OIDL_Run_Info * rinfo,OIDL_C_Info * ci)284 orbit_idl_output_c_skeletons (IDL_tree       tree,
285 			      OIDL_Run_Info *rinfo,
286 			      OIDL_C_Info   *ci)
287 {
288 	fprintf (ci->fh, OIDL_C_WARNING);
289 	fprintf (ci->fh, "#include <string.h>\n");
290 	fprintf (ci->fh, "#define ORBIT2_STUBS_API\n");
291 	fprintf (ci->fh, "#include \"%s.h\"\n\n", ci->base_name);
292 
293 	ck_output_poastuff (tree, rinfo, ci);
294 }
295