1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/
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.
13
* The Original Code is mozilla.org code.
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
21
* Michael Allen (michael.allen@sun.com)
22
* Frank Mitchell (frank.mitchell@sun.com)
26
* Generate Java interfaces from XPIDL.
34
struct java_priv_data {
35
GHashTable *typedefTable;
38
#define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable)
41
write_classname_iid_define(FILE *file, const char *className)
44
if (className[0] == 'n' && className[1] == 's') {
45
/* backcompat naming styles */
47
iidName = className + 2;
53
fputc(toupper(*iidName++), file);
61
java_prolog(TreeState *state)
63
state->priv = calloc(1, sizeof(struct java_priv_data));
67
TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal);
68
if (!TYPEDEFS(state)) {
69
/* XXX report error */
78
fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n",
82
" *\n * This file was automatically generated from %s.idl.\n",
85
fputs(" */\n\n", state->file);
91
java_epilog(TreeState *state)
93
/* points to other elements of the tree, so just destroy the table */
94
g_hash_table_destroy(TYPEDEFS(state));
102
fprintf(state->file, "\n/*\n * end\n */\n");
108
forward_declaration(TreeState *state)
111
* Java doesn't need forward declarations unless the declared
112
* class resides in a different package.
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";
120
/* XXX: Get package name and compare */
121
fprintf(state->file, "import %s.%s;\n", pkgName, className);
128
interface_declaration(TreeState *state)
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;
135
if (!verify_interface_declaration(interface))
138
* Write out JavaDoc comment
141
fprintf(state->file, "\n/**\n * Interface %s\n", interface_name);
143
#ifndef LIBIDL_MAJOR_VERSION
144
iid = IDL_tree_property_get(interface, "uuid");
146
iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid");
150
fprintf(state->file, " *\n * IID: 0x%s\n */\n\n", iid);
152
fputs(" */\n\n", state->file);
157
* Write "public interface <foo>"
160
fprintf(state->file, "public interface %s ", interface_name);
163
* Check for inheritence, and iterator over the inherited names,
167
if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) {
168
fputs("extends ", state->file);
172
fprintf(state->file, "%s",
173
IDL_IDENT(IDL_LIST(iterator).data).str);
175
if (IDL_LIST(iterator).next) {
176
fputs(", ", state->file);
178
} while ((iterator = IDL_LIST(iterator).next));
182
fputs("\n{\n", state->file);
186
* Write interface constants for IID
189
fputs(" public static final String ", state->file);
191
/* XXX s.b just "IID" ? */
192
if (!write_classname_iid_define(state->file, interface_name)) {
196
fprintf(state->file, "_STRING =\n \"%s\";\n\n", iid);
198
fputs(" public static final nsID ", state->file);
200
/* XXX s.b just "IID" ? */
201
if (!write_classname_iid_define(state->file, interface_name)) {
205
fprintf(state->file, " =\n new nsID(\"%s\");\n\n", iid);
209
* Advance the state of the tree, go on to process more
212
state->tree = IDL_INTERFACE(interface).body;
214
if (state->tree && !xpidl_process_node(state)) {
219
fputs("\n}\n", state->file);
225
process_list(TreeState *state)
228
for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
229
state->tree = IDL_LIST(iter).data;
230
if (!xpidl_process_node(state))
237
xpcom_to_java_type (TreeState *state)
240
fputs("Object", state->file);
244
switch(IDL_NODE_TYPE(state->tree)) {
246
case IDLN_TYPE_INTEGER: {
248
switch(IDL_TYPE_INTEGER(state->tree).f_type) {
250
case IDL_INTEGER_TYPE_SHORT:
251
fputs("short", state->file);
254
case IDL_INTEGER_TYPE_LONG:
255
fputs("int", state->file);
258
case IDL_INTEGER_TYPE_LONGLONG:
259
fputs("long", state->file);
263
g_error(" Unknown integer type: %d\n",
264
IDL_TYPE_INTEGER(state->tree).f_type);
273
case IDLN_TYPE_WIDE_CHAR:
274
fputs("char", state->file);
277
case IDLN_TYPE_WIDE_STRING:
278
case IDLN_TYPE_STRING:
279
fputs("String", state->file);
282
case IDLN_TYPE_BOOLEAN:
283
fputs("boolean", state->file);
286
case IDLN_TYPE_OCTET:
287
fputs("byte", state->file);
290
case IDLN_TYPE_FLOAT:
291
switch(IDL_TYPE_FLOAT(state->tree).f_type) {
293
case IDL_FLOAT_TYPE_FLOAT:
294
fputs("float", state->file);
297
case IDL_FLOAT_TYPE_DOUBLE:
298
fputs("double", state->file);
302
g_error(" Unknown floating point typ: %d\n",
303
IDL_NODE_TYPE(state->tree));
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);
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);
324
/* XXX: special class for opaque types */
325
fputs("OpaqueValue", state->file);
328
const char *ident_str = IDL_IDENT(state->tree).str;
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);
335
else if (strcmp(ident_str, "PRInt16") == 0 ||
336
strcmp(ident_str, "PRUint16") == 0) {
337
fputs("short", state->file);
339
else if (strcmp(ident_str, "PRInt32") == 0 ||
340
strcmp(ident_str, "PRUint32") == 0) {
341
fputs("int", state->file);
343
else if (strcmp(ident_str, "PRInt64") == 0 ||
344
strcmp(ident_str, "PRUint64") == 0) {
345
fputs("long", state->file);
347
else if (strcmp(ident_str, "PRBool") == 0) {
348
fputs("boolean", state->file);
350
else if (strcmp(ident_str, "nsrefcnt") == 0) {
351
fputs("int", state->file);
355
g_hash_table_lookup(TYPEDEFS(state), ident_str);
358
IDL_tree orig_tree = state->tree;
360
state->tree = real_type;
361
xpcom_to_java_type(state);
363
state->tree = orig_tree;
366
fputs(ident_str, state->file);
374
case IDLN_TYPE_OBJECT:
376
g_error(" Unknown type: %d\n",
377
IDL_TYPE_FLOAT(state->tree).f_type);
386
xpcom_to_java_param(TreeState *state)
388
IDL_tree param = state->tree;
389
state->tree = IDL_PARAM_DCL(param).param_type_spec;
392
* Put in type of parameter
395
if (!xpcom_to_java_type(state)) {
400
* If the parameter is out or inout, make it a Java array of the
404
if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) {
405
fputs("[]", state->file);
409
* Put in name of parameter
412
fputc(' ', state->file);
414
fputs(IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str, state->file);
421
type_declaration(TreeState *state)
424
* Unlike C, Java has no type declaration directive.
425
* Instead, we record the mapping, and look up the actual type
428
IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
429
IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
431
/* XXX: check for illegal types */
433
g_hash_table_insert(TYPEDEFS(state),
434
IDL_IDENT(IDL_LIST(dcls).data).str,
441
method_declaration(TreeState *state)
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;
453
if (!verify_method_declaration(state->tree))
456
fputc('\n', state->file);
457
xpidl_write_comment(state, 4);
460
* Write beginning of method declaration
462
fputs(" ", state->file);
463
if (!method_noscript) {
464
/* Nonscriptable methods become package-protected */
465
fputs("public ", state->file);
470
* Unlike C++ headers, Java interfaces return the declared
471
* return value; an exception indicates XPCOM method failure.
473
if (method_notxpcom || method->op_type_spec) {
474
state->tree = method->op_type_spec;
475
if (!xpcom_to_java_type(state)) {
479
/* Check for retval attribute */
480
for (iterator = method->parameter_dcls; iterator != NULL;
481
iterator = IDL_LIST(iterator).next) {
483
IDL_tree original_tree = state->tree;
485
state->tree = IDL_LIST(iterator).data;
487
if (IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
489
retval_param = iterator;
491
state->tree = IDL_PARAM_DCL(state->tree).param_type_spec;
494
* Put in type of parameter
497
if (!xpcom_to_java_type(state)) {
502
state->tree = original_tree;
505
if (retval_param == NULL) {
506
fputs("void", state->file);
513
fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1);
518
for (iterator = method->parameter_dcls; iterator != NULL;
519
iterator = IDL_LIST(iterator).next) {
522
if (iterator == retval_param) {
526
if (iterator != method->parameter_dcls) {
527
fputs(", ", state->file);
530
state->tree = IDL_LIST(iterator).data;
532
if (!xpcom_to_java_param(state)) {
537
fputs(")", state->file);
539
if (method->raises_expr) {
540
IDL_tree iter = method->raises_expr;
541
IDL_tree dataNode = IDL_LIST(iter).data;
543
fputs(" throws ", state->file);
544
fputs(IDL_IDENT(dataNode).str, state->file);
545
iter = IDL_LIST(iter).next;
548
dataNode = IDL_LIST(iter).data;
549
fprintf(state->file, ", %s", IDL_IDENT(dataNode).str);
550
iter = IDL_LIST(iter).next;
554
fputs(";\n", state->file);
562
constant_declaration(TreeState *state)
564
struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree);
565
const char *name = IDL_IDENT(declaration->ident).str;
568
if (!verify_const_declaration(state->tree))
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;
575
fputc('\n', state->file);
576
xpidl_write_comment(state, 4);
578
fprintf(state->file, " public static final %s %s = %d;\n",
579
(IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG
581
name, (int) IDL_INTEGER(declaration->const_exp).value);
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)
593
attribute_declaration(TreeState *state)
595
gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
596
char *attribute_name = ATTR_IDENT(state->tree).str;
598
gboolean method_noscript =
599
(IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") != NULL);
603
* Disabled here because I can't verify this check against possible
604
* users of the java xpidl backend.
606
if (!verify_attribute_declaration(state->tree))
611
fputc('\n', state->file);
612
xpidl_write_comment(state, 4);
614
state->tree = ATTR_TYPE_DECL(state->tree);
617
* Write access permission ("public" unless nonscriptable)
619
fputs(" ", state->file);
620
if (!method_noscript) {
621
fputs("public ", state->file);
625
* Write the proper Java return value for the get operation
627
if (!xpcom_to_java_type(state)) {
632
* Write the name of the accessor ("get") method.
634
fprintf(state->file, " get%c%s();\n",
635
toupper(attribute_name[0]), attribute_name + 1);
639
/* Nonscriptable methods become package-protected */
640
fputs(" ", state->file);
641
if (!method_noscript) {
642
fputs("public ", state->file);
646
* Write attribute access method name and return type
648
fprintf(state->file, "void set%c%s(",
649
toupper(attribute_name[0]),
653
* Write the proper Java type for the set operation
655
if (!xpcom_to_java_type(state)) {
660
* Write the name of the formal parameter.
662
fputs(" value);\n", state->file);
670
enum_declaration(TreeState *state)
672
XPIDL_WARNING((state->tree, IDL_WARNING1,
673
"enums not supported, enum \'%s\' ignored",
674
IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
679
xpidl_java_dispatch(void)
681
static backend result;
682
static nodeHandler table[IDLN_LAST];
683
static gboolean initialized = FALSE;
685
result.emit_prolog = java_prolog;
686
result.emit_epilog = java_epilog;
689
table[IDLN_INTERFACE] = interface_declaration;
690
table[IDLN_LIST] = process_list;
692
table[IDLN_OP_DCL] = method_declaration;
693
table[IDLN_ATTR_DCL] = attribute_declaration;
694
table[IDLN_CONST_DCL] = constant_declaration;
696
table[IDLN_TYPE_DCL] = type_declaration;
697
table[IDLN_FORWARD_DCL] = forward_declaration;
699
table[IDLN_TYPE_ENUM] = enum_declaration;
704
result.dispatch_table = table;