On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / xpcom / typelib / xpidl / xpidl_java.c
blob68be7d29f138b981c1f4c007c12ad5d0575d4a61
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Sun Microsystems, Inc.
19 * Portions created by the Initial Developer are Copyright (C) 1999
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Michael Allen (michael.allen@sun.com)
24 * Frank Mitchell (frank.mitchell@sun.com)
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 * Generate Java interfaces from XPIDL.
44 #include "xpidl.h"
45 #include <ctype.h>
46 #include <glib.h>
48 #ifdef XP_WIN
49 #include <windef.h>
50 #define PATH_MAX MAX_PATH
51 #elif defined(XP_OS2) && !defined(PATH_MAX)
52 #include <os2.h>
53 #define PATH_MAX CCHMAXPATH
54 #endif
56 /* XXX Bug 331178 - nsIScriptSecurityManager inherits from non-scriptable
57 * interface nsIXPCSecurityManager. To work around that, we write out a
58 * Java interface for nsIXPCSecurityManager, but don't give it any methods.
60 #define CREATE_NSIXPCSECURITYMANAGER
62 /* XXX Bug 324035 - XPIDL cannot tell whether a forward declared interface is
63 * itself defined in an IDL file (in which case XPIDL will have also written
64 * out a Java interface file) or if it is just defined in a C header (in which
65 * case there will be an error when trying to compile the Java interfaces).
66 * This workaround lists the infringing interfaces and writes out "nsISupports"
67 * when encountering those types.
69 #define HANDLE_NON_IDL_IFACES
71 /* XXX Bug 340009 - SWT depends on several [noscript] methods in order to
72 * embed Mozilla in an SWT view. This hack makes those methods available
73 * to Java embedders.
75 #define OUTPUT_SWT_NOSCRIPT_METHODS
77 /* XXX If an interface method throws an exception, how do we handle it? */
78 /*#define HANDLE_EXCEPTIONS*/
81 static char* subscriptIdentifier(TreeState *state, char *str);
83 static char* javaKeywords[] = {
84 "abstract", "default" , "if" , "private" , "throw" ,
85 "boolean" , "do" , "implements", "protected" , "throws" ,
86 "break" , "double" , "import", "public" , "transient" ,
87 "byte" , "else" , "instanceof", "return" , "try" ,
88 "case" , "extends" , "int" , "short" , "void" ,
89 "catch" , "final" , "interface" , "static" , "volatile" ,
90 "char" , "finally" , "long" , "super" , "while" ,
91 "class" , "float" , "native" , "switch" ,
92 "const" , "for" , "new" , "synchronized",
93 "continue", "goto" , "package" , "this" ,
94 /* added in Java 1.2 */
95 "strictfp",
96 /* added in Java 1.4 */
97 "assert" ,
98 /* added in Java 5.0 */
99 "enum" ,
100 /* Java constants */
101 "true" , "false" , "null" ,
102 /* java.lang.Object methods *
103 * - don't worry about "toString", since it does the same thing *
104 * as Object's "toString" */
105 "clone" , "equals" , "finalize" , "getClass" , "hashCode" ,
106 "notify" , "notifyAll", /*"toString" ,*/ "wait"
109 #ifdef HANDLE_NON_IDL_IFACES
110 static char* nonIDLIfaces[] = {
111 "nsIPresShell",
112 "nsIDocument",
113 "nsIObjectFrame",
114 "nsObjectFrame",
115 "nsIFrame",
116 "nsIContent",
117 "nsILayoutHistoryState",
118 "nsIMdbEnv",
119 "nsIMdbTable",
120 "nsIMdbRow",
121 "nsIChannelSecurityInfo",
122 "nsIUnicodeDecoder",
123 "nsIUnicodeEncoder",
124 "nsIServiceManagerObsolete",
125 "nsIWordBreaker",
126 "nsISecureEnv",
127 "nsIScrollbarMediator",
128 "nsIScriptContext",
129 "nsIScriptGlobalObject",
130 "nsIScriptElement",
131 "nsIFrameSelection",
132 "nsIWidget",
133 "nsIMenuItem"
135 #define NONIDLS(state) (((struct java_priv_data *)state->priv)->nonIDLIfaces)
136 #endif
138 #define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable)
139 #define PRIVDATA(state) (((struct java_priv_data *)state->priv))
140 #define KEYWORDS(state) (((struct java_priv_data *)state->priv)->keywords)
142 static void
143 write_indent(FILE *outfile) {
144 fputs(" ", outfile);
147 static GSList*
148 add_deprecated(GSList *comments)
150 GSList *last;
151 char *buffer;
152 char *replaced;
153 const char deprecated[] = "* @deprecated */";
155 /* Handle the easy case: no documentation. */
156 if (comments == NULL) {
157 buffer = malloc(sizeof(deprecated)+2);
158 buffer[0] = '/';
159 buffer[1] = '*';
160 strcpy(buffer+2, deprecated);
162 return g_slist_append(comments, buffer);
165 /* xpidl is so nice in that they give us the data as a single node.
166 * We are going to have to (very hackishly) strip out the the end of the
167 * documentation comment, add the tag, and then pop it back together.
170 /* Step 1: Move the comment into a larger buffer, so that we can have
171 * more space to work with.
173 last = g_slist_last(comments);
174 buffer = last->data;
175 replaced = (char *)malloc(strlen(buffer) + sizeof(deprecated));
176 strcpy(replaced, buffer);
177 last->data = replaced;
178 free(buffer);
180 /* Now replaced has the comment, with a large enough buffer to put in the
181 * @deprecated tag. We search for the last / in hopes that the previous
182 * character is the * we're looking for...
184 buffer = strrchr(replaced, '/');
185 if (buffer == NULL || buffer == replaced || buffer[-1] == '*') {
186 /* We can't find a '/', so there's no comment, or this is not the end
187 * of a comment, so we'll ignore adding the deprecated tag.
189 return comments;
191 /* buffer now points to '*' '/'. Overwrite both. */
192 strcpy(buffer-1, deprecated);
193 return comments;
196 static gboolean
197 write_classname_iid_define(FILE *file, const char *className)
199 const char *iidName;
200 if (className[0] == 'n' && className[1] == 's') {
201 /* backcompat naming styles */
202 fputs("NS_", file);
203 iidName = className + 2;
204 } else {
205 iidName = className;
208 while (*iidName) {
209 fputc(toupper(*iidName++), file);
212 fputs("_IID", file);
213 return TRUE;
216 static gboolean
217 java_prolog(TreeState *state)
219 int len, i;
220 state->priv = calloc(1, sizeof(struct java_priv_data));
221 if (!state->priv)
222 return FALSE;
224 TYPEDEFS(state) = 0;
225 TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal);
226 if (!TYPEDEFS(state)) {
227 /* XXX report error */
228 free(state->priv);
229 return FALSE;
232 KEYWORDS(state) = 0;
233 KEYWORDS(state) = g_hash_table_new(g_str_hash, g_str_equal);
234 if (!KEYWORDS(state)) {
235 g_hash_table_destroy(TYPEDEFS(state));
236 free(state->priv);
237 return FALSE;
239 len = sizeof(javaKeywords)/sizeof(*javaKeywords);
240 for (i = 0; i < len; i++) {
241 g_hash_table_insert(KEYWORDS(state),
242 javaKeywords[i],
243 javaKeywords[i]);
246 #ifdef HANDLE_NON_IDL_IFACES
247 NONIDLS(state) = 0;
248 NONIDLS(state) = g_hash_table_new(g_str_hash, g_str_equal);
249 if (!NONIDLS(state)) {
250 g_hash_table_destroy(TYPEDEFS(state));
251 free(state->priv);
252 return FALSE;
254 len = sizeof(nonIDLIfaces)/sizeof(*nonIDLIfaces);
255 for (i = 0; i < len; i++) {
256 g_hash_table_insert(NONIDLS(state),
257 nonIDLIfaces[i],
258 nonIDLIfaces[i]);
260 #endif
262 return TRUE;
265 static gboolean
266 java_epilog(TreeState *state)
268 /* points to other elements of the tree, so just destroy the table */
269 g_hash_table_destroy(TYPEDEFS(state));
270 g_hash_table_destroy(KEYWORDS(state));
271 #ifdef HANDLE_NON_IDL_IFACES
272 g_hash_table_destroy(NONIDLS(state));
273 #endif
275 free(state->priv);
276 state->priv = NULL;
278 return TRUE;
281 static gboolean
282 forward_declaration(TreeState *state)
285 * Java doesn't need forward declarations unless the declared
286 * class resides in a different package.
288 #if 0
289 IDL_tree iface = state->tree;
290 const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
291 const char *pkgName = "org.mozilla.xpcom";
292 if (!className)
293 return FALSE;
294 /* XXX: Get package name and compare */
295 fprintf(state->file, "import %s.%s;\n", pkgName, className);
296 #endif
298 return TRUE;
302 static gboolean
303 interface_declaration(TreeState *state)
305 char outname[PATH_MAX];
306 char* p;
307 IDL_tree interface = state->tree;
308 IDL_tree iterator = NULL;
309 char *interface_name =
310 subscriptIdentifier(state, IDL_IDENT(IDL_INTERFACE(interface).ident).str);
311 const char *iid = NULL;
312 char iid_parsed[UUID_LENGTH];
313 GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(interface).ident).comments;
315 if (!verify_interface_declaration(interface))
316 return FALSE;
319 * We only want to output scriptable interfaces
321 if (!IDL_tree_property_get(IDL_INTERFACE(interface).ident, "scriptable")) {
323 * XXX SWT uses non-scriptable interface 'nsIAppShell' (bug 270892), so
324 * include that one.
326 if (strcmp(interface_name, "nsIAppShell") != 0
327 #ifdef CREATE_NSIXPCSECURITYMANAGER
328 && strcmp(interface_name, "nsIXPCSecurityManager") != 0
329 #endif
331 return TRUE;
335 * Each Java interface must be in its own file.
337 p = strrchr(state->filename, '/');
338 if (p) {
339 strncpy(outname, state->filename, p + 1 - state->filename);
340 outname[p + 1 - state->filename] = '\0';
342 else {
343 outname[0] = '\0';
345 strcat(outname, interface_name);
346 strcat(outname, ".java");
348 state->file = fopen(outname, "w");
349 if (!state->file) {
350 perror("error opening output file");
351 return FALSE;
354 fprintf(state->file, "/*\n * DO NOT EDIT. THIS FILE IS GENERATED FROM\n"
355 " * %s.idl\n */\n", state->basename);
357 /* package name (namespace) */
358 fputs("\npackage org.mozilla.interfaces;\n\n", state->file);
361 iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid");
362 if (iid) {
364 * Parse uuid and then output resulting nsID to string, to
365 * validate uuid.
367 struct nsID id;
368 if (!xpidl_parse_iid(&id, iid)) {
369 IDL_tree_error(state->tree, "cannot parse IID %s\n", iid);
370 return FALSE;
372 if (!xpidl_sprint_iid(&id, iid_parsed)) {
373 IDL_tree_error(state->tree, "error formatting IID %s\n", iid);
374 return FALSE;
376 } else {
377 IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n",
378 interface_name);
379 return FALSE;
383 * Add deprecated tags if the interface is deprecated
385 if (IDL_tree_property_get(IDL_INTERFACE(interface).ident, "deprecated")) {
386 doc_comments = add_deprecated(doc_comments);
390 * Write any interface comments
392 if (doc_comments != NULL)
393 printlist(state->file, doc_comments);
396 * Write "public interface <foo>"
398 fprintf(state->file, "public interface %s", interface_name);
401 * Check for inheritence, and iterator over the inherited names,
402 * if any.
405 if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) {
406 fputs(" extends ", state->file);
408 do {
409 fprintf(state->file, "%s",
410 IDL_IDENT(IDL_LIST(iterator).data).str);
412 if (IDL_LIST(iterator).next) {
413 fputs(", ", state->file);
415 } while ((iterator = IDL_LIST(iterator).next));
418 fputs(" {\n\n", state->file);
421 * Write interface constants for IID
423 if (iid) {
424 /* String NS_ISUPPORTS_IID = "{00000000-0000-0000-c000-000000000046}";*/
425 write_indent(state->file);
426 fputs("String ", state->file);
427 write_classname_iid_define(state->file, interface_name);
428 fputs(" =\n", state->file);
429 write_indent(state->file);
430 write_indent(state->file);
431 fprintf(state->file, "\"{%s}\";\n\n", iid_parsed);
435 * Advance the state of the tree, go on to process more
438 state->tree = IDL_INTERFACE(interface).body;
440 if (state->tree && !xpidl_process_node(state)) {
441 return FALSE;
445 fputs("}", state->file);
447 fclose(state->file);
449 return TRUE;
452 static gboolean
453 process_list(TreeState *state)
455 IDL_tree iter;
456 for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
457 state->tree = IDL_LIST(iter).data;
458 if (!xpidl_process_node(state))
459 return FALSE;
461 return TRUE;
464 static gboolean
465 xpcom_to_java_type(TreeState *state, IDL_tree param)
467 IDL_tree real_type, type;
468 IDL_tree up;
470 if (!state->tree) {
471 fputs("Object", state->file);
472 return TRUE;
475 /* Could be a typedef; try to map it to the real type */
476 real_type = find_underlying_type(state->tree);
477 type = real_type ? real_type : state->tree;
479 switch(IDL_NODE_TYPE(type)) {
481 case IDLN_TYPE_INTEGER: {
483 switch(IDL_TYPE_INTEGER(type).f_type) {
485 case IDL_INTEGER_TYPE_SHORT:
486 if (IDL_TYPE_INTEGER(type).f_signed)
487 fputs("short", state->file);
488 else
489 fputs("int", state->file);
490 break;
492 case IDL_INTEGER_TYPE_LONG:
493 if (IDL_TYPE_INTEGER(type).f_signed)
494 fputs("int", state->file);
495 else
496 fputs("long", state->file);
497 break;
499 case IDL_INTEGER_TYPE_LONGLONG:
500 if (IDL_TYPE_INTEGER(type).f_signed)
501 fputs("long", state->file);
502 else
503 fputs("double", state->file);
504 break;
506 default:
507 g_error(" Unknown integer type: %d\n",
508 IDL_TYPE_INTEGER(type).f_type);
509 return FALSE;
513 break;
516 case IDLN_TYPE_CHAR:
517 case IDLN_TYPE_WIDE_CHAR:
518 fputs("char", state->file);
519 break;
521 case IDLN_TYPE_WIDE_STRING:
522 case IDLN_TYPE_STRING:
523 fputs("String", state->file);
524 break;
526 case IDLN_TYPE_BOOLEAN:
527 fputs("boolean", state->file);
528 break;
530 case IDLN_TYPE_OCTET:
531 if (param && IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array"))
532 fputs("byte", state->file);
533 else
534 fputs("short", state->file);
535 break;
537 case IDLN_TYPE_FLOAT:
538 switch(IDL_TYPE_FLOAT(type).f_type) {
540 case IDL_FLOAT_TYPE_FLOAT:
541 fputs("float", state->file);
542 break;
544 case IDL_FLOAT_TYPE_DOUBLE:
545 fputs("double", state->file);
546 break;
548 default:
549 g_error(" Unknown floating point typ: %d\n",
550 IDL_NODE_TYPE(type));
551 break;
553 break;
556 case IDLN_IDENT:
557 if (!(up = IDL_NODE_UP(type))) {
558 IDL_tree_error(state->tree,
559 "ERROR: orphan ident %s in param list\n",
560 IDL_IDENT(state->tree).str);
561 return FALSE;
563 switch (IDL_NODE_TYPE(up)) {
564 case IDLN_FORWARD_DCL:
565 case IDLN_INTERFACE: {
566 char *className;
567 const char *iid_is;
568 handle_iid_is:
569 /* might get here via the goto, so re-check type */
570 if (IDL_NODE_TYPE(up) == IDLN_INTERFACE)
571 className = IDL_IDENT(IDL_INTERFACE(up).ident).str;
572 else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL)
573 className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str;
574 else
575 className = IDL_IDENT(IDL_NATIVE(up).ident).str;
577 iid_is = NULL;
578 if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
579 IDL_tree simple = IDL_PARAM_DCL(state->tree).simple_declarator;
580 iid_is = IDL_tree_property_get(simple, "iid_is");
583 if (iid_is) {
584 fputs("nsISupports", state->file);
585 } else {
587 * In JavaXPCOM, we handle weak references internally; no need
588 * for the |nsIWeakReference| interface. So just return
589 * |nsISupports|.
591 if (strcmp(className, "nsIWeakReference") == 0) {
592 fputs("nsISupports", state->file);
593 } else {
594 #ifdef HANDLE_NON_IDL_IFACES
595 char *nonidl = g_hash_table_lookup(NONIDLS(state), className);
596 if (nonidl) {
597 fputs("nsISupports", state->file);
598 } else
599 #endif
601 fprintf(state->file, "%s", className);
605 break;
607 case IDLN_NATIVE: {
608 char *ident;
610 /* jband - adding goto for iid_is when type is native */
611 if (param) {
612 if (IDL_NODE_TYPE(param) == IDLN_PARAM_DCL &&
613 IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator,
614 "iid_is"))
616 state->tree = param;
617 goto handle_iid_is;
621 ident = IDL_IDENT(type).str;
622 if (IDL_tree_property_get(type, "nsid")) {
623 fputs("String", state->file);
624 } else if (IDL_tree_property_get(type, "domstring")) {
625 fputs("String", state->file);
626 } else if (IDL_tree_property_get(type, "astring")) {
627 fputs("String", state->file);
628 } else if (IDL_tree_property_get(type, "utf8string")) {
629 fputs("String", state->file);
630 } else if (IDL_tree_property_get(type, "cstring")) {
631 fputs("String", state->file);
632 } else {
633 const char* user_type = IDL_NATIVE(IDL_NODE_UP(type)).user_type;
634 IDL_tree real_type =
635 g_hash_table_lookup(TYPEDEFS(state), user_type);
637 if (real_type) {
638 gboolean rc;
639 IDL_tree orig_tree = state->tree;
641 state->tree = real_type;
642 rc = xpcom_to_java_type(state, param);
644 state->tree = orig_tree;
645 return rc;
646 } else {
647 if (strcmp(user_type, "PRInt8") == 0) {
648 fputs("byte", state->file);
649 } else if (strcmp(user_type, "PRInt16") == 0 ||
650 strcmp(user_type, "PRUint8") == 0) {
651 fputs("short", state->file);
652 } else if (strcmp(user_type, "PRInt32") == 0 ||
653 strcmp(user_type, "int") == 0 ||
654 strcmp(user_type, "PRUint16") == 0) {
655 fputs("int", state->file);
656 } else if (strcmp(user_type, "PRInt64") == 0 ||
657 strcmp(user_type, "PRUint32") == 0) {
658 fputs("long", state->file);
659 } else if (strcmp(user_type, "PRUint64") == 0) {
660 fputs("double", state->file);
661 } else if (strcmp(user_type, "PRBool") == 0) {
662 fputs("boolean", state->file);
663 } else if (strcmp(user_type, "char") == 0 ||
664 strcmp(user_type, "const char") == 0 ||
665 strcmp(user_type, "unsigned char") == 0) {
666 if (IDL_tree_property_get(type, "ptr")) {
667 fputs("byte[]", state->file);
668 } else {
669 fputs("char", state->file);
671 } else if (strcmp(user_type, "nsIID") == 0) {
672 fputs("String", state->file);
673 } else if (strcmp(user_type, "nsString") == 0 ||
674 strcmp(user_type, "nsAString") == 0 ||
675 strcmp(user_type, "nsACString") == 0) {
676 fputs("String", state->file);
677 } else {
678 fputs("long", state->file);
682 break;
684 default:
685 if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) {
686 /* restart with the underlying type */
687 gboolean rc;
688 IDL_tree orig_tree = state->tree;
689 state->tree = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec;
690 rc = xpcom_to_java_type(state, param);
691 state->tree = orig_tree;
692 return rc;
694 IDL_tree_error(state->tree,
695 "can't handle %s ident in param list\n",
696 "that type of"
698 return FALSE;
700 break;
702 default:
703 IDL_tree_error(state->tree, "can't handle %s in param list\n",
704 #ifdef DEBUG_shaver
705 /* XXX is this safe to use on Win now? */
706 IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
707 #else
708 "that type"
709 #endif
711 return FALSE;
714 return TRUE;
718 static gboolean
719 xpcom_to_java_param(TreeState *state)
721 IDL_tree param = state->tree;
722 state->tree = IDL_PARAM_DCL(param).param_type_spec;
725 * Put in type of parameter
728 if (!xpcom_to_java_type(state, param)) {
729 return FALSE;
733 * If the parameter is out or inout, make it a Java array of the
734 * appropriate type
737 if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) {
738 fputs("[]", state->file);
742 * If the parameter is an array make it a Java array
744 if (IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array"))
745 fputs("[]", state->file);
748 * Put in name of parameter
750 fputc(' ', state->file);
751 fputs(subscriptIdentifier(state,
752 IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str),
753 state->file);
755 return TRUE;
759 static gboolean
760 type_declaration(TreeState *state)
763 * Unlike C, Java has no type declaration directive.
764 * Instead, we record the mapping, and look up the actual type
765 * when needed.
767 IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
768 IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
770 /* XXX: check for illegal types */
772 g_hash_table_insert(TYPEDEFS(state),
773 IDL_IDENT(IDL_LIST(dcls).data).str,
774 type);
776 return TRUE;
779 #ifdef OUTPUT_SWT_NOSCRIPT_METHODS
780 static gboolean
781 print_noscript_method(TreeState *state)
783 IDL_tree iface = IDL_NODE_UP(IDL_NODE_UP(state->tree));
784 char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
785 if (strcmp(className, "nsIBaseWindow") == 0 ||
786 strcmp(className, "nsIEmbeddingSiteWindow") == 0)
787 return TRUE;
788 return FALSE;
790 #endif
792 static gboolean
793 method_declaration(TreeState *state)
795 const char* array = NULL;
796 struct _IDL_OP_DCL *method = &IDL_OP_DCL(state->tree);
797 gboolean method_notxpcom =
798 (IDL_tree_property_get(method->ident, "notxpcom") != NULL);
799 gboolean method_noscript =
800 (IDL_tree_property_get(method->ident, "noscript") != NULL);
801 IDL_tree iterator = NULL;
802 IDL_tree retval_param = NULL;
803 char *method_name =
804 g_strdup_printf("%c%s",
805 tolower(IDL_IDENT(method->ident).str[0]),
806 IDL_IDENT(method->ident).str + 1);
807 GSList *doc_comments = IDL_IDENT(method->ident).comments;
809 if (!verify_method_declaration(state->tree))
810 return FALSE;
812 #ifdef OUTPUT_SWT_NOSCRIPT_METHODS
813 if (method_notxpcom)
814 return TRUE;
815 if (method_noscript && !print_noscript_method(state))
816 return TRUE;
817 #else
818 /* do not write nonscriptable methods */
819 if (method_notxpcom || method_noscript) {
820 return TRUE;
822 #endif
824 #ifdef CREATE_NSIXPCSECURITYMANAGER
825 /* Since this interface is non-scriptable, we treat all of its methods
826 * as if they were [noscript] */
828 IDL_tree iface = IDL_NODE_UP(IDL_NODE_UP(state->tree));
829 char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
830 if (strcmp(className, "nsIXPCSecurityManager") == 0)
831 return TRUE;
833 #endif
836 * Add deprecated tags if the interface is deprecated
838 if (IDL_tree_property_get(method->ident, "deprecated")) {
839 doc_comments = add_deprecated(doc_comments);
842 if (doc_comments != NULL) {
843 write_indent(state->file);
844 printlist(state->file, doc_comments);
848 * Write return type
849 * Unlike C++ headers, Java interfaces return the declared
850 * return value; an exception indicates XPCOM method failure.
852 write_indent(state->file);
853 if (method->op_type_spec) {
854 state->tree = method->op_type_spec;
855 if (!xpcom_to_java_type(state, NULL)) {
856 return FALSE;
858 } else {
859 /* Check for retval attribute */
860 for (iterator = method->parameter_dcls; iterator != NULL;
861 iterator = IDL_LIST(iterator).next) {
863 IDL_tree original_tree = state->tree;
864 IDL_tree simple_decl;
866 state->tree = IDL_LIST(iterator).data;
867 simple_decl = IDL_PARAM_DCL(state->tree).simple_declarator;
869 if (IDL_tree_property_get(simple_decl, "retval")) {
870 IDL_tree param;
872 retval_param = iterator;
873 array = IDL_tree_property_get(simple_decl, "array");
876 * Put in type of parameter
878 param = state->tree;
879 state->tree = IDL_PARAM_DCL(state->tree).param_type_spec;
880 if (!xpcom_to_java_type(state, param)) {
881 return FALSE;
884 if (array) {
885 fputs("[]", state->file);
889 state->tree = original_tree;
892 if (retval_param == NULL) {
893 fputs("void", state->file);
898 * Write method name
900 fprintf(state->file, " %s(", subscriptIdentifier(state, method_name));
903 * Write parameters
905 for (iterator = method->parameter_dcls; iterator != NULL;
906 iterator = IDL_LIST(iterator).next) {
908 /* Skip "retval" */
909 if (iterator == retval_param) {
910 continue;
913 if (iterator != method->parameter_dcls) {
914 fputs(", ", state->file);
917 state->tree = IDL_LIST(iterator).data;
919 if (!xpcom_to_java_param(state)) {
920 return FALSE;
924 fputs(")", state->file);
926 #ifdef HANDLE_EXCEPTIONS
927 if (method->raises_expr) {
928 IDL_tree iter = method->raises_expr;
929 IDL_tree dataNode = IDL_LIST(iter).data;
931 fputs(" throws ", state->file);
932 fputs(IDL_IDENT(dataNode).str, state->file);
933 iter = IDL_LIST(iter).next;
935 while (iter) {
936 dataNode = IDL_LIST(iter).data;
937 fprintf(state->file, ", %s", IDL_IDENT(dataNode).str);
938 iter = IDL_LIST(iter).next;
941 #endif
943 fputs(";\n\n", state->file);
945 return TRUE;
949 static gboolean
950 constant_declaration(TreeState *state)
952 struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree);
953 const char *name = IDL_IDENT(declaration->ident).str;
954 GSList *doc_comments = IDL_IDENT(declaration->ident).comments;
955 IDL_tree real_type;
957 const char* format;
958 const char* type_str;
959 gboolean is_long;
961 gboolean success;
963 if (!verify_const_declaration(state->tree))
964 return FALSE;
966 /* Could be a typedef; try to map it to the real type. */
967 real_type = find_underlying_type(declaration->const_type);
968 real_type = real_type ? real_type : declaration->const_type;
970 /* Consts must be in an interface */
971 if (!IDL_NODE_UP(IDL_NODE_UP(state->tree)) ||
972 IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(state->tree))) !=
973 IDLN_INTERFACE) {
975 XPIDL_WARNING((state->tree, IDL_WARNING1,
976 "A constant \"%s\" was declared outside an interface."
977 " It was ignored.", name));
979 return TRUE;
983 * The C++ header XPIDL module only allows for shorts and longs (ints)
984 * to be constants, so we will follow the same convention
987 is_long = FALSE;
989 success = (IDLN_TYPE_INTEGER == IDL_NODE_TYPE(real_type));
991 if (success) {
992 gboolean is_signed = IDL_TYPE_INTEGER(real_type).f_signed;
993 format = is_signed ? "%" IDL_LL "d" : "%" IDL_LL "u";
995 switch(IDL_TYPE_INTEGER(real_type).f_type) {
996 case IDL_INTEGER_TYPE_SHORT:
997 if (is_signed)
998 type_str = "short";
999 else
1000 type_str = "int";
1001 break;
1003 case IDL_INTEGER_TYPE_LONG:
1004 if (is_signed) {
1005 type_str = "int";
1006 } else {
1007 type_str = "long";
1008 is_long = TRUE;
1010 break;
1012 default:
1013 /* Whoops, it's some other kind of number */
1014 success = FALSE;
1015 break;
1017 } else {
1018 IDL_tree_error(state->tree,
1019 "const declaration \'%s\' must be of type short or long",
1020 name);
1021 return FALSE;
1024 if (!success) {
1025 XPIDL_WARNING((state->tree, IDL_WARNING1,
1026 "A constant \"%s\" was not of type short or long."
1027 " It was ignored.", name));
1028 return FALSE;
1031 if (doc_comments != NULL) {
1032 write_indent(state->file);
1033 printlist(state->file, doc_comments);
1036 write_indent(state->file);
1037 fprintf(state->file, "%s %s = ", type_str,
1038 subscriptIdentifier(state, (char*) name));
1039 fprintf(state->file, format, IDL_INTEGER(declaration->const_exp).value);
1040 fprintf(state->file, "%s;\n\n", is_long ? "L" : "");
1042 return TRUE;
1046 #define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data))
1047 #define ATTR_PROPS(tree) (IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data)
1048 #define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL((tree)).param_type_spec)
1051 static gboolean
1052 attribute_declaration(TreeState *state)
1054 char *attribute_name;
1055 GSList *doc_comments;
1056 gboolean read_only;
1058 if (!verify_attribute_declaration(state->tree))
1059 return FALSE;
1061 attribute_name = ATTR_IDENT(state->tree).str;
1062 read_only = IDL_ATTR_DCL(state->tree).f_readonly;
1064 #ifdef OUTPUT_SWT_NOSCRIPT_METHODS
1065 if (IDL_tree_property_get(ATTR_PROPS(state->tree), "notxpcom"))
1066 return TRUE;
1067 if (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") &&
1068 !print_noscript_method(state))
1069 return TRUE;
1070 #else
1071 if (IDL_tree_property_get(ATTR_PROPS(state->tree), "notxpcom") ||
1072 IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript"))
1073 return TRUE;
1074 #endif
1076 doc_comments =
1077 IDL_IDENT(IDL_LIST(IDL_ATTR_DCL
1078 (state->tree).simple_declarations).data).comments;
1081 * Add deprecated tags if the interface is deprecated
1083 if (IDL_tree_property_get(ATTR_PROPS(state->tree), "deprecated")) {
1084 doc_comments = add_deprecated(doc_comments);
1087 if (doc_comments != NULL) {
1088 write_indent(state->file);
1089 printlist(state->file, doc_comments);
1093 * Write the proper Java return value for the get operation
1095 write_indent(state->file);
1096 state->tree = ATTR_TYPE_DECL(state->tree);
1097 if (!xpcom_to_java_type(state, NULL)) {
1098 return FALSE;
1102 * Write the name of the accessor ("get") method.
1104 fprintf(state->file, " get%c%s();\n\n",
1105 toupper(attribute_name[0]), attribute_name + 1);
1107 if (!read_only) {
1108 if (doc_comments != NULL) {
1109 write_indent(state->file);
1110 printlist(state->file, doc_comments);
1114 * Write attribute access method name and return type
1116 write_indent(state->file);
1117 fprintf(state->file, "void set%c%s(",
1118 toupper(attribute_name[0]),
1119 attribute_name+1);
1122 * Write the proper Java type for the set operation
1124 if (!xpcom_to_java_type(state, NULL)) {
1125 return FALSE;
1129 * Write the name of the formal parameter.
1131 fprintf(state->file, " a%c%s);\n\n", toupper(attribute_name[0]),
1132 attribute_name + 1);
1135 return TRUE;
1139 static gboolean
1140 enum_declaration(TreeState *state)
1142 XPIDL_WARNING((state->tree, IDL_WARNING1,
1143 "enums not supported, enum \'%s\' ignored",
1144 IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
1145 return TRUE;
1148 backend *
1149 xpidl_java_dispatch(void)
1151 static backend result;
1152 static nodeHandler table[IDLN_LAST];
1153 static gboolean initialized = FALSE;
1155 result.emit_prolog = java_prolog;
1156 result.emit_epilog = java_epilog;
1158 if (!initialized) {
1159 table[IDLN_INTERFACE] = interface_declaration;
1160 table[IDLN_LIST] = process_list;
1162 table[IDLN_OP_DCL] = method_declaration;
1163 table[IDLN_ATTR_DCL] = attribute_declaration;
1164 table[IDLN_CONST_DCL] = constant_declaration;
1166 table[IDLN_TYPE_DCL] = type_declaration;
1167 table[IDLN_FORWARD_DCL] = forward_declaration;
1169 table[IDLN_TYPE_ENUM] = enum_declaration;
1171 initialized = TRUE;
1174 result.dispatch_table = table;
1175 return &result;
1178 char* subscriptIdentifier(TreeState *state, char *str)
1180 char *sstr = NULL;
1181 char *keyword = g_hash_table_lookup(KEYWORDS(state), str);
1182 if (keyword) {
1183 sstr = g_strdup_printf("_%s", keyword);
1184 return sstr;
1186 return str;