VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c@ 4837

Last change on this file since 4837 was 1, checked in by vboxsync, 54 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.7 KB
Line 
1/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * The contents of this file are subject to the Mozilla Public
4 * License Version 1.1 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of
6 * the License at http://www.mozilla.org/MPL/
7 *
8 * Software distributed under the License is distributed on an "AS
9 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10 * implied. See the License for the specific language governing
11 * rights and limitations under the License.
12 *
13 * The Original Code is mozilla.org code.
14 *
15 * The Initial Developer of the Original Code is Sun Microsystems,
16 * Inc. Portions created by Sun are
17 * Copyright (C) 1999 Sun Microsystems, Inc. All
18 * Rights Reserved.
19 *
20 * Contributor(s):
21 * Michael Allen (michael.allen@sun.com)
22 * Frank Mitchell (frank.mitchell@sun.com)
23 */
24
25/*
26 * Generate Java interfaces from XPIDL.
27 */
28
29#include "xpidl.h"
30#include <ctype.h>
31#include <glib.h>
32
33
34struct java_priv_data {
35 GHashTable *typedefTable;
36};
37
38#define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable)
39
40static gboolean
41write_classname_iid_define(FILE *file, const char *className)
42{
43 const char *iidName;
44 if (className[0] == 'n' && className[1] == 's') {
45 /* backcompat naming styles */
46 fputs("NS_", file);
47 iidName = className + 2;
48 } else {
49 iidName = className;
50 }
51
52 while (*iidName) {
53 fputc(toupper(*iidName++), file);
54 }
55
56 fputs("_IID", file);
57 return TRUE;
58}
59
60static gboolean
61java_prolog(TreeState *state)
62{
63 state->priv = calloc(1, sizeof(struct java_priv_data));
64 if (!state->priv)
65 return FALSE;
66 TYPEDEFS(state) = 0;
67 TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal);
68 if (!TYPEDEFS(state)) {
69 /* XXX report error */
70 free(state->priv);
71 return FALSE;
72 }
73
74 /*
75 * First pass
76 */
77
78 fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n",
79 state->file);
80
81 fprintf(state->file,
82 " *\n * This file was automatically generated from %s.idl.\n",
83 state->basename);
84
85 fputs(" */\n\n", state->file);
86
87 return TRUE;
88}
89
90static gboolean
91java_epilog(TreeState *state)
92{
93 /* points to other elements of the tree, so just destroy the table */
94 g_hash_table_destroy(TYPEDEFS(state));
95 free(state->priv);
96 state->priv = NULL;
97
98 /*
99 * Last pass
100 */
101
102 fprintf(state->file, "\n/*\n * end\n */\n");
103
104 return TRUE;
105}
106
107static gboolean
108forward_declaration(TreeState *state)
109{
110 /*
111 * Java doesn't need forward declarations unless the declared
112 * class resides in a different package.
113 */
114#if 0
115 IDL_tree iface = state->tree;
116 const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
117 const char *pkgName = "org.mozilla.xpcom";
118 if (!className)
119 return FALSE;
120 /* XXX: Get package name and compare */
121 fprintf(state->file, "import %s.%s;\n", pkgName, className);
122#endif
123 return TRUE;
124}
125
126
127static gboolean
128interface_declaration(TreeState *state)
129{
130 IDL_tree interface = state->tree;
131 IDL_tree iterator = NULL;
132 char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str;
133 const char *iid = NULL;
134
135 if (!verify_interface_declaration(interface))
136 return FALSE;
137 /*
138 * Write out JavaDoc comment
139 */
140
141 fprintf(state->file, "\n/**\n * Interface %s\n", interface_name);
142
143#ifndef LIBIDL_MAJOR_VERSION
144 iid = IDL_tree_property_get(interface, "uuid");
145#else
146 iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid");
147#endif
148
149 if (iid != NULL) {
150 fprintf(state->file, " *\n * IID: 0x%s\n */\n\n", iid);
151 } else {
152 fputs(" */\n\n", state->file);
153 }
154
155
156 /*
157 * Write "public interface <foo>"
158 */
159
160 fprintf(state->file, "public interface %s ", interface_name);
161
162 /*
163 * Check for inheritence, and iterator over the inherited names,
164 * if any.
165 */
166
167 if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) {
168 fputs("extends ", state->file);
169
170 do {
171
172 fprintf(state->file, "%s",
173 IDL_IDENT(IDL_LIST(iterator).data).str);
174
175 if (IDL_LIST(iterator).next) {
176 fputs(", ", state->file);
177 }
178 } while ((iterator = IDL_LIST(iterator).next));
179
180 }
181
182 fputs("\n{\n", state->file);
183
184 if (iid) {
185 /*
186 * Write interface constants for IID
187 */
188
189 fputs(" public static final String ", state->file);
190
191 /* XXX s.b just "IID" ? */
192 if (!write_classname_iid_define(state->file, interface_name)) {
193 return FALSE;
194 }
195
196 fprintf(state->file, "_STRING =\n \"%s\";\n\n", iid);
197
198 fputs(" public static final nsID ", state->file);
199
200 /* XXX s.b just "IID" ? */
201 if (!write_classname_iid_define(state->file, interface_name)) {
202 return FALSE;
203 }
204
205 fprintf(state->file, " =\n new nsID(\"%s\");\n\n", iid);
206 }
207
208 /*
209 * Advance the state of the tree, go on to process more
210 */
211
212 state->tree = IDL_INTERFACE(interface).body;
213
214 if (state->tree && !xpidl_process_node(state)) {
215 return FALSE;
216 }
217
218
219 fputs("\n}\n", state->file);
220
221 return TRUE;
222}
223
224static gboolean
225process_list(TreeState *state)
226{
227 IDL_tree iter;
228 for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
229 state->tree = IDL_LIST(iter).data;
230 if (!xpidl_process_node(state))
231 return FALSE;
232 }
233 return TRUE;
234}
235
236static gboolean
237xpcom_to_java_type (TreeState *state)
238{
239 if (!state->tree) {
240 fputs("Object", state->file);
241 return TRUE;
242 }
243
244 switch(IDL_NODE_TYPE(state->tree)) {
245
246 case IDLN_TYPE_INTEGER: {
247
248 switch(IDL_TYPE_INTEGER(state->tree).f_type) {
249
250 case IDL_INTEGER_TYPE_SHORT:
251 fputs("short", state->file);
252 break;
253
254 case IDL_INTEGER_TYPE_LONG:
255 fputs("int", state->file);
256 break;
257
258 case IDL_INTEGER_TYPE_LONGLONG:
259 fputs("long", state->file);
260 break;
261
262 default:
263 g_error(" Unknown integer type: %d\n",
264 IDL_TYPE_INTEGER(state->tree).f_type);
265 return FALSE;
266
267 }
268
269 break;
270 }
271
272 case IDLN_TYPE_CHAR:
273 case IDLN_TYPE_WIDE_CHAR:
274 fputs("char", state->file);
275 break;
276
277 case IDLN_TYPE_WIDE_STRING:
278 case IDLN_TYPE_STRING:
279 fputs("String", state->file);
280 break;
281
282 case IDLN_TYPE_BOOLEAN:
283 fputs("boolean", state->file);
284 break;
285
286 case IDLN_TYPE_OCTET:
287 fputs("byte", state->file);
288 break;
289
290 case IDLN_TYPE_FLOAT:
291 switch(IDL_TYPE_FLOAT(state->tree).f_type) {
292
293 case IDL_FLOAT_TYPE_FLOAT:
294 fputs("float", state->file);
295 break;
296
297 case IDL_FLOAT_TYPE_DOUBLE:
298 fputs("double", state->file);
299 break;
300
301 default:
302 g_error(" Unknown floating point typ: %d\n",
303 IDL_NODE_TYPE(state->tree));
304 break;
305 }
306 break;
307
308
309 case IDLN_IDENT:
310 if (IDL_NODE_UP(state->tree) &&
311 IDL_NODE_TYPE(IDL_NODE_UP(state->tree)) == IDLN_NATIVE) {
312 const char *user_type = IDL_NATIVE(IDL_NODE_UP(state->tree)).user_type;
313 if (strcmp(user_type, "void") == 0) {
314 fputs("Object", state->file);
315 }
316 else if (strcmp(user_type, "nsID") == 0 ||
317 strcmp(user_type, "nsIID") == 0 ||
318 strcmp(user_type, "nsCID") == 0) {
319 /* XXX: s.b test for "iid" attribute */
320 /* XXX: special class for nsIDs */
321 fputs("nsID", state->file);
322 }
323 else {
324 /* XXX: special class for opaque types */
325 fputs("OpaqueValue", state->file);
326 }
327 } else {
328 const char *ident_str = IDL_IDENT(state->tree).str;
329
330 /* XXX: big kludge; s.b. way to match to typedefs */
331 if (strcmp(ident_str, "PRInt8") == 0 ||
332 strcmp(ident_str, "PRUint8") == 0) {
333 fputs("byte", state->file);
334 }
335 else if (strcmp(ident_str, "PRInt16") == 0 ||
336 strcmp(ident_str, "PRUint16") == 0) {
337 fputs("short", state->file);
338 }
339 else if (strcmp(ident_str, "PRInt32") == 0 ||
340 strcmp(ident_str, "PRUint32") == 0) {
341 fputs("int", state->file);
342 }
343 else if (strcmp(ident_str, "PRInt64") == 0 ||
344 strcmp(ident_str, "PRUint64") == 0) {
345 fputs("long", state->file);
346 }
347 else if (strcmp(ident_str, "PRBool") == 0) {
348 fputs("boolean", state->file);
349 }
350 else if (strcmp(ident_str, "nsrefcnt") == 0) {
351 fputs("int", state->file);
352 }
353 else {
354 IDL_tree real_type =
355 g_hash_table_lookup(TYPEDEFS(state), ident_str);
356
357 if (real_type) {
358 IDL_tree orig_tree = state->tree;
359
360 state->tree = real_type;
361 xpcom_to_java_type(state);
362
363 state->tree = orig_tree;
364 }
365 else {
366 fputs(ident_str, state->file);
367 }
368 }
369 }
370
371 break;
372
373 case IDLN_TYPE_ENUM:
374 case IDLN_TYPE_OBJECT:
375 default:
376 g_error(" Unknown type: %d\n",
377 IDL_TYPE_FLOAT(state->tree).f_type);
378 break;
379 }
380
381 return TRUE;
382
383}
384
385static gboolean
386xpcom_to_java_param(TreeState *state)
387{
388 IDL_tree param = state->tree;
389 state->tree = IDL_PARAM_DCL(param).param_type_spec;
390
391 /*
392 * Put in type of parameter
393 */
394
395 if (!xpcom_to_java_type(state)) {
396 return FALSE;
397 }
398
399 /*
400 * If the parameter is out or inout, make it a Java array of the
401 * appropriate type
402 */
403
404 if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) {
405 fputs("[]", state->file);
406 }
407
408 /*
409 * Put in name of parameter
410 */
411
412 fputc(' ', state->file);
413
414 fputs(IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str, state->file);
415
416 return TRUE;
417}
418
419
420static gboolean
421type_declaration(TreeState *state)
422{
423 /*
424 * Unlike C, Java has no type declaration directive.
425 * Instead, we record the mapping, and look up the actual type
426 * when needed.
427 */
428 IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
429 IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
430
431 /* XXX: check for illegal types */
432
433 g_hash_table_insert(TYPEDEFS(state),
434 IDL_IDENT(IDL_LIST(dcls).data).str,
435 type);
436
437 return TRUE;
438}
439
440static gboolean
441method_declaration(TreeState *state)
442{
443 /* IDL_tree method_tree = state->tree; */
444 struct _IDL_OP_DCL *method = &IDL_OP_DCL(state->tree);
445 gboolean method_notxpcom =
446 (IDL_tree_property_get(method->ident, "notxpcom") != NULL);
447 gboolean method_noscript =
448 (IDL_tree_property_get(method->ident, "noscript") != NULL);
449 IDL_tree iterator = NULL;
450 IDL_tree retval_param = NULL;
451 const char *method_name = IDL_IDENT(method->ident).str;
452
453 if (!verify_method_declaration(state->tree))
454 return FALSE;
455
456 fputc('\n', state->file);
457 xpidl_write_comment(state, 4);
458
459 /*
460 * Write beginning of method declaration
461 */
462 fputs(" ", state->file);
463 if (!method_noscript) {
464 /* Nonscriptable methods become package-protected */
465 fputs("public ", state->file);
466 }
467
468 /*
469 * Write return type
470 * Unlike C++ headers, Java interfaces return the declared
471 * return value; an exception indicates XPCOM method failure.
472 */
473 if (method_notxpcom || method->op_type_spec) {
474 state->tree = method->op_type_spec;
475 if (!xpcom_to_java_type(state)) {
476 return FALSE;
477 }
478 } else {
479 /* Check for retval attribute */
480 for (iterator = method->parameter_dcls; iterator != NULL;
481 iterator = IDL_LIST(iterator).next) {
482
483 IDL_tree original_tree = state->tree;
484
485 state->tree = IDL_LIST(iterator).data;
486
487 if (IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
488 "retval")) {
489 retval_param = iterator;
490
491 state->tree = IDL_PARAM_DCL(state->tree).param_type_spec;
492
493 /*
494 * Put in type of parameter
495 */
496
497 if (!xpcom_to_java_type(state)) {
498 return FALSE;
499 }
500 }
501
502 state->tree = original_tree;
503 }
504
505 if (retval_param == NULL) {
506 fputs("void", state->file);
507 }
508 }
509
510 /*
511 * Write method name
512 */
513 fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1);
514
515 /*
516 * Write parameters
517 */
518 for (iterator = method->parameter_dcls; iterator != NULL;
519 iterator = IDL_LIST(iterator).next) {
520
521 /* Skip "retval" */
522 if (iterator == retval_param) {
523 continue;
524 }
525
526 if (iterator != method->parameter_dcls) {
527 fputs(", ", state->file);
528 }
529
530 state->tree = IDL_LIST(iterator).data;
531
532 if (!xpcom_to_java_param(state)) {
533 return FALSE;
534 }
535 }
536
537 fputs(")", state->file);
538
539 if (method->raises_expr) {
540 IDL_tree iter = method->raises_expr;
541 IDL_tree dataNode = IDL_LIST(iter).data;
542
543 fputs(" throws ", state->file);
544 fputs(IDL_IDENT(dataNode).str, state->file);
545 iter = IDL_LIST(iter).next;
546
547 while (iter) {
548 dataNode = IDL_LIST(iter).data;
549 fprintf(state->file, ", %s", IDL_IDENT(dataNode).str);
550 iter = IDL_LIST(iter).next;
551 }
552 }
553
554 fputs(";\n", state->file);
555
556 return TRUE;
557
558}
559
560
561static gboolean
562constant_declaration(TreeState *state)
563{
564 struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree);
565 const char *name = IDL_IDENT(declaration->ident).str;
566 IDL_tree real_type;
567
568 if (!verify_const_declaration(state->tree))
569 return FALSE;
570
571 /* Could be a typedef; try to map it to the real type. */
572 real_type = find_underlying_type(declaration->const_type);
573 real_type = real_type ? real_type : declaration->const_type;
574
575 fputc('\n', state->file);
576 xpidl_write_comment(state, 4);
577
578 fprintf(state->file, " public static final %s %s = %d;\n",
579 (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG
580 ? "long" : "short"),
581 name, (int) IDL_INTEGER(declaration->const_exp).value);
582
583 return TRUE;
584
585}
586
587#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data))
588#define ATTR_PROPS(tree) (IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data)
589#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL((tree)).param_type_spec)
590
591
592static gboolean
593attribute_declaration(TreeState *state)
594{
595 gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
596 char *attribute_name = ATTR_IDENT(state->tree).str;
597
598 gboolean method_noscript =
599 (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") != NULL);
600
601#if 0
602 /*
603 * Disabled here because I can't verify this check against possible
604 * users of the java xpidl backend.
605 */
606 if (!verify_attribute_declaration(state->tree))
607 return FALSE;
608#endif
609
610 /* Comment */
611 fputc('\n', state->file);
612 xpidl_write_comment(state, 4);
613
614 state->tree = ATTR_TYPE_DECL(state->tree);
615
616 /*
617 * Write access permission ("public" unless nonscriptable)
618 */
619 fputs(" ", state->file);
620 if (!method_noscript) {
621 fputs("public ", state->file);
622 }
623
624 /*
625 * Write the proper Java return value for the get operation
626 */
627 if (!xpcom_to_java_type(state)) {
628 return FALSE;
629 }
630
631 /*
632 * Write the name of the accessor ("get") method.
633 */
634 fprintf(state->file, " get%c%s();\n",
635 toupper(attribute_name[0]), attribute_name + 1);
636
637
638 if (!read_only) {
639 /* Nonscriptable methods become package-protected */
640 fputs(" ", state->file);
641 if (!method_noscript) {
642 fputs("public ", state->file);
643 }
644
645 /*
646 * Write attribute access method name and return type
647 */
648 fprintf(state->file, "void set%c%s(",
649 toupper(attribute_name[0]),
650 attribute_name+1);
651
652 /*
653 * Write the proper Java type for the set operation
654 */
655 if (!xpcom_to_java_type(state)) {
656 return FALSE;
657 }
658
659 /*
660 * Write the name of the formal parameter.
661 */
662 fputs(" value);\n", state->file);
663 }
664
665 return TRUE;
666}
667
668
669static gboolean
670enum_declaration(TreeState *state)
671{
672 XPIDL_WARNING((state->tree, IDL_WARNING1,
673 "enums not supported, enum \'%s\' ignored",
674 IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
675 return TRUE;
676}
677
678backend *
679xpidl_java_dispatch(void)
680{
681 static backend result;
682 static nodeHandler table[IDLN_LAST];
683 static gboolean initialized = FALSE;
684
685 result.emit_prolog = java_prolog;
686 result.emit_epilog = java_epilog;
687
688 if (!initialized) {
689 table[IDLN_INTERFACE] = interface_declaration;
690 table[IDLN_LIST] = process_list;
691
692 table[IDLN_OP_DCL] = method_declaration;
693 table[IDLN_ATTR_DCL] = attribute_declaration;
694 table[IDLN_CONST_DCL] = constant_declaration;
695
696 table[IDLN_TYPE_DCL] = type_declaration;
697 table[IDLN_FORWARD_DCL] = forward_declaration;
698
699 table[IDLN_TYPE_ENUM] = enum_declaration;
700
701 initialized = TRUE;
702 }
703
704 result.dispatch_table = table;
705 return &result;
706}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use