diff --git a/mozilla/Makefile.in b/mozilla/Makefile.in index a2d3fd9ff0a..e78132d5794 100644 --- a/mozilla/Makefile.in +++ b/mozilla/Makefile.in @@ -466,15 +466,10 @@ ifdef ENABLE_TESTS tier_99_dirs += tools/test-harness endif -# Don't build the Java interfaces when cross compiling since that depends on the -# program GenerateJavaInterfaces (which doesn't work when cross compiling). -# This ifndef can be removed when bug 333618 is checked in. -ifndef CROSS_COMPILE # This should be built last, after all IDL files in the tree have been processed ifdef MOZ_JAVAXPCOM tier_99_dirs += extensions/java/xpcom/interfaces endif -endif default alldep all:: $(RM) -rf $(DIST)/sdk diff --git a/mozilla/config/config.mk b/mozilla/config/config.mk index 76a7f2d704a..493c533592a 100644 --- a/mozilla/config/config.mk +++ b/mozilla/config/config.mk @@ -490,6 +490,11 @@ XPIDL_COMPILE = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/bin/xpidl$(BIN_SUFFIX) XPIDL_LINK = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/bin/xpt_link$(BIN_SUFFIX) endif +# Java macros +JAVA_GEN_DIR = _javagen +JAVA_DIST_DIR = $(DEPTH)/$(JAVA_GEN_DIR) +JAVA_IFACES_PKG_NAME = org/mozilla/xpcom + REQ_INCLUDES = $(foreach d,$(REQUIRES),-I$(DIST)/include/$d) -I$(DIST)/include ifdef LIBXUL_SDK REQ_INCLUDES_SDK = $(foreach d,$(REQUIRES),-I$(LIBXUL_SDK)/include/$d) -I$(LIBXUL_SDK)/include diff --git a/mozilla/config/rules.mk b/mozilla/config/rules.mk index d6cd874ee64..6dc9dcf4e95 100644 --- a/mozilla/config/rules.mk +++ b/mozilla/config/rules.mk @@ -1279,6 +1279,13 @@ $(SDK_PUBLIC) $(PUBLIC):: @if test ! -d $@; then echo Creating $@; rm -rf $@; $(NSINSTALL) -D $@; else true; fi endif +ifdef MOZ_JAVAXPCOM +ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),) +$(JAVA_DIST_DIR):: + $(NSINSTALL) -D $@ +endif +endif + ifneq ($(XPI_NAME),) export:: @if test ! -d $(FINAL_TARGET); then echo Creating $(FINAL_TARGET); rm -fr $(FINAL_TARGET); $(NSINSTALL) -D $(FINAL_TARGET); else true; fi @@ -1498,6 +1505,45 @@ endif endif # SDK_XPIDLSRCS + + +ifdef MOZ_JAVAXPCOM +ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),) + +JAVA_XPIDLSRCS = $(XPIDLSRCS) $(SDK_XPIDLSRCS) + +# A single IDL file can contain multiple interfaces, which result in multiple +# Java interface files. So use hidden dependency files. +JAVADEPFILES = $(addprefix $(JAVA_GEN_DIR)/.,$(JAVA_XPIDLSRCS:.idl=.java.pp)) + +$(JAVA_GEN_DIR): + $(NSINSTALL) -D $@ +GARBAGE_DIRS += $(JAVA_GEN_DIR) + +# generate .java files into _javagen/[package name dirs] +_JAVA_GEN_DIR = $(JAVA_GEN_DIR)/$(JAVA_IFACES_PKG_NAME) +$(_JAVA_GEN_DIR): + $(NSINSTALL) -D $@ + +$(JAVA_GEN_DIR)/.%.java.pp: %.idl $(XPIDL_COMPILE) $(_JAVA_GEN_DIR) + $(REPORT_BUILD) + $(ELOG) $(XPIDL_COMPILE) -m java -w -I$(srcdir) -I$(IDL_DIR) -o $(_JAVA_GEN_DIR)/$* $(_VPATH_SRCS) + @touch $@ + +# "Install" generated Java interfaces. We segregate them based on the XPI_NAME. +# If XPI_NAME is not set, install into the "default" directory. +ifneq ($(XPI_NAME),) +JAVA_INSTALL_DIR = $(JAVA_DIST_DIR)/$(XPI_NAME) +else +JAVA_INSTALL_DIR = $(JAVA_DIST_DIR)/default +endif +export:: $(JAVA_DIST_DIR) $(JAVADEPFILES) + cd $(JAVA_GEN_DIR) && find . -name "*.java" \ + -exec sh -c "dirname {} | sed 's/^\.\///' | xargs -I % $(NSINSTALL) $(IFLAGS1) {} ../$(JAVA_INSTALL_DIR)/%" \; + +endif # XPIDLSRCS || SDK_XPIDLSRCS +endif # MOZ_JAVAXPCOM + ################################################################################ # Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components ifdef EXTRA_COMPONENTS diff --git a/mozilla/extensions/java/xpcom/Makefile.in b/mozilla/extensions/java/xpcom/Makefile.in index e0d5a660291..2278bac7570 100644 --- a/mozilla/extensions/java/xpcom/Makefile.in +++ b/mozilla/extensions/java/xpcom/Makefile.in @@ -46,9 +46,5 @@ DIRS = src TOOL_DIRS = glue -ifndef CROSS_COMPILE -TOOL_DIRS += tools/genifaces -endif - include $(topsrcdir)/config/rules.mk diff --git a/mozilla/extensions/java/xpcom/interfaces/Makefile.in b/mozilla/extensions/java/xpcom/interfaces/Makefile.in index e12181514d3..3ddf3ea4b2c 100644 --- a/mozilla/extensions/java/xpcom/interfaces/Makefile.in +++ b/mozilla/extensions/java/xpcom/interfaces/Makefile.in @@ -56,68 +56,53 @@ JAVA_SRCS = \ $(srcdir)/VersionComparator.java \ $(NULL) -GEN_JAVA_SRCS = \ - IXPCOMError.java \ - $(NULL) - # install jars into SDK SDK_LIBRARY = $(JARFILE) $(JARFILE_SRC) -GARBAGE += $(JARFILE) $(JARFILE_SRC) $(GEN_JAVA_SRCS) java.files .done -GARBAGE_DIRS += _javagen org +GARBAGE += $(JARFILE) $(JARFILE_SRC) java.files +GARBAGE_DIRS += org include $(topsrcdir)/config/rules.mk -ifeq ($(OS_ARCH),WINNT) -RUN = -OUTPUT_DIR = $(shell cygpath -w $(CURDIR)/_javagen/org/mozilla/xpcom) -else -RUN = $(DIST)/bin/run-mozilla.sh -OUTPUT_DIR = $(CURDIR)/_javagen/org/mozilla/xpcom -endif +# XXX Need to copy Java source files to correct directory structure, until +# bug 328901 is fixed. -_javagen/org/mozilla/xpcom/.iface_done: $(JAVA_SRCS) $(DIST)/bin/GenerateJavaInterfaces$(BIN_SUFFIX) - @if test ! -d _javagen/org/mozilla/xpcom; then \ - touch .done; \ - $(INSTALL) -m 644 .done _javagen/org/mozilla/xpcom; \ - fi +JAVA_SRCS_DIR = _java/org/mozilla/xpcom +GARBAGE_DIRS += _java + +$(JAVA_SRCS_DIR):: + $(NSINSTALL) -D $@ + +$(JAVA_SRCS_DIR)/Mozilla.java: $(JAVA_SRCS_DIR) @echo Copying Java source files - @$(INSTALL) -m 644 $(JAVA_SRCS) \ - _javagen/org/mozilla/xpcom - @$(INSTALL) -m 644 $(GEN_JAVA_SRCS) _javagen/org/mozilla/xpcom - @echo Generating Java interface files - $(RUN) $(DIST)/bin/GenerateJavaInterfaces$(BIN_SUFFIX) -d $(OUTPUT_DIR) - @touch $@ + $(INSTALL) -m 644 $(JAVA_SRCS) $< + +$(JAVA_SRCS_DIR)/IXPCOMError.java: $(topsrcdir)/xpcom/base/nsError.h gen-nsError.pl Makefile Makefile.in $(JAVA_SRCS_DIR) + $(PERL) $(srcdir)/../gen-nsError.pl < $< > $@ + +# Don't include the interface nsIPref, since it depends on the obsolete +# interface nsIFileSpec. +IGNORE_IFACES_NAMES = nsIPref +ifneq (,$(IGNORE_IFACES_NAMES)) +IGNORE_IFACES = $(patsubst %, ! -name "*%.java", $(IGNORE_IFACES_NAMES)) +endif # Using the temporary "java.files" avoids an "argument list too long" # error on Windows when using *.java -org/mozilla/xpcom/.class_done: _javagen/org/mozilla/xpcom/.iface_done - @echo Compiling Java interface classes - find _javagen -name "*.java" > java.files - $(JAVAC) $(JAVAC_FLAGS) -classpath . -d . -sourcepath _javagen @java.files - @touch $@ +org/mozilla/xpcom/Mozilla.class: $(JAVA_SRCS_DIR)/IXPCOMError.java $(JAVA_SRCS_DIR)/Mozilla.java + @echo Compiling Java classes + find _java -name "*.java" > java.files + find $(JAVA_DIST_DIR)/default -name "*.java" $(IGNORE_IFACES) >> java.files + $(JAVAC) $(JAVAC_FLAGS) -classpath . -d . -sourcepath _java -sourcepath $(JAVA_DIST_DIR)/default @java.files -$(JARFILE): org/mozilla/xpcom/.class_done Makefile +$(JARFILE): org/mozilla/xpcom/Mozilla.class Makefile $(JAR) cf $@ org $(JARFILE_SRC): $(JARFILE) - $(JAR) cf $@ -C _javagen org - -IXPCOMError.java: $(topsrcdir)/xpcom/base/nsError.h gen-nsError.pl Makefile Makefile.in - $(PERL) $(srcdir)/../gen-nsError.pl < $< > $@ - -export:: IXPCOMError.java - -# Temporarily copy these not only to dist/sdk/lib but to dist/bin/sdk/lib - -TEMP_SDK_DIR = $(DIST)/bin/sdk/lib - -$(TEMP_SDK_DIR):: - $(NSINSTALL) -D $@ - -export:: $(JARFILE) $(JARFILE_SRC) $(TEMP_SDK_DIR) - $(INSTALL) $(IFLAGS2) $^ + $(JAR) cf $@ -C _java org + $(JAR) uf $@ -C $(JAVA_DIST_DIR)/default org + $(ZIP) -d $@ $(patsubst %, $(JAVA_IFACES_PKG_NAME)/%.java, $(IGNORE_IFACES_NAMES)) # Build the implementation Java classes, which depend on these interfaces -export:: +export:: $(JARFILE) $(JARFILE_SRC) $(MAKE) -C ../src jarfile diff --git a/mozilla/extensions/java/xpcom/src/Makefile.in b/mozilla/extensions/java/xpcom/src/Makefile.in index b7427fb464f..c2e52313666 100755 --- a/mozilla/extensions/java/xpcom/src/Makefile.in +++ b/mozilla/extensions/java/xpcom/src/Makefile.in @@ -111,7 +111,7 @@ _javagen/org/mozilla/xpcom/internal/.iface_done: $(JAVA_SRCS) # Using the temporary "java.files" avoids an "argument list too long" # error on Windows when using *.java -org/mozilla/xpcom/internal/.class_done: _javagen/org/mozilla/xpcom/internal/.iface_done +org/mozilla/xpcom/internal/.class_done: _javagen/org/mozilla/xpcom/internal/.iface_done ../interfaces/MozillaInterfaces.jar @echo Compiling Java implementation classes find _javagen -name "*.java" > java.files $(JAVAC) $(JAVAC_FLAGS) \ diff --git a/mozilla/xpcom/typelib/xpidl/xpidl.h b/mozilla/xpcom/typelib/xpidl/xpidl.h index e6d0e54f373..a1938e6ab2d 100644 --- a/mozilla/xpcom/typelib/xpidl/xpidl.h +++ b/mozilla/xpcom/typelib/xpidl/xpidl.h @@ -128,6 +128,7 @@ typedef struct IncludePathEntry { struct TreeState { FILE *file; + char *filename; /* Maybe supplied by -o. Not related to (g_)basename from string.h or glib */ char *basename; IDL_ns ns; @@ -137,6 +138,13 @@ struct TreeState { void *priv; /* mode-private data */ }; +struct java_priv_data { + GHashTable *typedefTable; + GHashTable *keywords; + char *filename; + GHashTable *nonIDLIfaces; +}; + /* * Process an IDL file, generating InterfaceInfo, documentation and headers as * appropriate. diff --git a/mozilla/xpcom/typelib/xpidl/xpidl_idl.c b/mozilla/xpcom/typelib/xpidl/xpidl_idl.c index 4993b7e447e..db799001c23 100644 --- a/mozilla/xpcom/typelib/xpidl/xpidl_idl.c +++ b/mozilla/xpcom/typelib/xpidl/xpidl_idl.c @@ -41,6 +41,7 @@ */ #include "xpidl.h" +#include #ifdef XP_MAC #include @@ -765,12 +766,17 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path, real_outname = g_strdup_printf("%s.%s", out_basename, mode->suffix); } - /* Use binary write for typelib mode */ - fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb"; - state.file = fopen(real_outname, fopen_mode); - if (!state.file) { - perror("error opening output file"); - return 0; + /* don't create/open file here for Java */ + if (strcmp(mode->mode, "java") == 0) { + state.filename = real_outname; + } else { + /* Use binary write for typelib mode */ + fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb"; + state.file = fopen(real_outname, fopen_mode); + if (!state.file) { + perror("error opening output file"); + return 0; + } } } else { state.file = stdout; @@ -784,8 +790,11 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path, if (emitter->emit_epilog) emitter->emit_epilog(&state); - if (state.file != stdout) - fclose(state.file); + if (strcmp(mode->mode, "java") != 0) { + if (state.file != stdout) + fclose(state.file); + } + free(state.basename); free(outname); g_hash_table_foreach(callback_state.already_included, free_ghash_key, NULL); @@ -797,16 +806,18 @@ xpidl_process_idl(char *filename, IncludePathEntry *include_path, if (top) IDL_tree_free(top); - if (real_outname != NULL) { - /* - * Delete partial output file on failure. (Mac does this in the plugin - * driver code, if the compiler returns failure.) - */ + if (strcmp(mode->mode, "java") != 0) { + if (real_outname != NULL) { + /* + * Delete partial output file on failure. (Mac does this in the + * plugin driver code, if the compiler returns failure.) + */ #if defined(XP_UNIX) || defined(XP_WIN) - if (!ok) - unlink(real_outname); + if (!ok) + unlink(real_outname); #endif - g_free(real_outname); + g_free(real_outname); + } } return ok; diff --git a/mozilla/xpcom/typelib/xpidl/xpidl_java.c b/mozilla/xpcom/typelib/xpidl/xpidl_java.c index 5c05f5bbf36..0da4fe003e2 100644 --- a/mozilla/xpcom/typelib/xpidl/xpidl_java.c +++ b/mozilla/xpcom/typelib/xpidl/xpidl_java.c @@ -45,12 +45,101 @@ #include #include +#ifdef XP_WIN +#include +#define PATH_MAX MAX_PATH +#endif -struct java_priv_data { - GHashTable *typedefTable; +/* XXX Bug 331178 - nsIScriptSecurityManager inherits from non-scriptable + * interface nsIXPCSecurityManager. To work around that, we write out a + * Java interface for nsIXPCSecurityManager, but don't give it any methods. + */ +#define CREATE_NSIXPCSECURITYMANAGER + +/* XXX Bug 324035 - XPIDL cannot tell whether a forward declared interface is + * itself defined in an IDL file (in which case XPIDL will have also written + * out a Java interface file) or if it is just defined in a C header (in which + * case there will be an error when trying to compile the Java interfaces). + * This workaround lists the infringing interfaces and writes out "nsISupports" + * when encountering those types. + */ +#define HANDLE_NON_IDL_IFACES + +/* XXX Bug 340009 - SWT depends on several [noscript] methods in order to + * embed Mozilla in an SWT view. This hack makes those methods available + * to Java embedders. + */ +#define OUTPUT_SWT_NOSCRIPT_METHODS + +/* XXX If an interface method throws an exception, how do we handle it? */ +/*#define HANDLE_EXCEPTIONS*/ + + +static char* subscriptIdentifier(TreeState *state, char *str); + +static char* javaKeywords[] = { + "abstract", "default" , "if" , "private" , "throw" , + "boolean" , "do" , "implements", "protected" , "throws" , + "break" , "double" , "import", "public" , "transient" , + "byte" , "else" , "instanceof", "return" , "try" , + "case" , "extends" , "int" , "short" , "void" , + "catch" , "final" , "interface" , "static" , "volatile" , + "char" , "finally" , "long" , "super" , "while" , + "class" , "float" , "native" , "switch" , + "const" , "for" , "new" , "synchronized", + "continue", "goto" , "package" , "this" , + /* added in Java 1.2 */ + "strictfp", + /* added in Java 1.4 */ + "assert" , + /* added in Java 5.0 */ + "enum" , + /* Java constants */ + "true" , "false" , "null" , + /* java.lang.Object methods * + * - don't worry about "toString", since it does the same thing * + * as Object's "toString" */ + "clone" , "equals" , "finalize" , "getClass" , "hashCode" , + "notify" , "notifyAll", /*"toString" ,*/ "wait" }; +#ifdef HANDLE_NON_IDL_IFACES +static char* nonIDLIfaces[] = { + "nsIPresShell", + "nsIDocument", + "nsIObjectFrame", + "nsObjectFrame", + "nsIFrame", + "nsIContent", + "nsILayoutHistoryState", + "nsIMdbEnv", + "nsIMdbTable", + "nsIMdbRow", + "nsIChannelSecurityInfo", + "nsIUnicodeDecoder", + "nsIUnicodeEncoder", + "nsIServiceManagerObsolete", + "nsIWordBreaker", + "nsISecureEnv", + "nsIScrollbarMediator", + "nsIScriptContext", + "nsIScriptGlobalObject", + "nsIScriptElement", + "nsIFrameSelection", + "nsIWidget", + "nsIMenuItem" +}; +#define NONIDLS(state) (((struct java_priv_data *)state->priv)->nonIDLIfaces) +#endif + #define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable) +#define PRIVDATA(state) (((struct java_priv_data *)state->priv)) +#define KEYWORDS(state) (((struct java_priv_data *)state->priv)->keywords) + +static void +write_indent(FILE *outfile) { + fputs(" ", outfile); +} static gboolean write_classname_iid_define(FILE *file, const char *className) @@ -75,9 +164,11 @@ write_classname_iid_define(FILE *file, const char *className) static gboolean java_prolog(TreeState *state) { + int len, i; state->priv = calloc(1, sizeof(struct java_priv_data)); if (!state->priv) return FALSE; + TYPEDEFS(state) = 0; TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal); if (!TYPEDEFS(state)) { @@ -85,20 +176,37 @@ java_prolog(TreeState *state) free(state->priv); return FALSE; } - - /* - * First pass - */ - - fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n", - state->file); - - fprintf(state->file, - " *\n * This file was automatically generated from %s.idl.\n", - state->basename); - - fputs(" */\n\n", state->file); - + + KEYWORDS(state) = 0; + KEYWORDS(state) = g_hash_table_new(g_str_hash, g_str_equal); + if (!KEYWORDS(state)) { + g_hash_table_destroy(TYPEDEFS(state)); + free(state->priv); + return FALSE; + } + len = sizeof(javaKeywords)/sizeof(*javaKeywords); + for (i = 0; i < len; i++) { + g_hash_table_insert(KEYWORDS(state), + javaKeywords[i], + javaKeywords[i]); + } + +#ifdef HANDLE_NON_IDL_IFACES + NONIDLS(state) = 0; + NONIDLS(state) = g_hash_table_new(g_str_hash, g_str_equal); + if (!NONIDLS(state)) { + g_hash_table_destroy(TYPEDEFS(state)); + free(state->priv); + return FALSE; + } + len = sizeof(nonIDLIfaces)/sizeof(*nonIDLIfaces); + for (i = 0; i < len; i++) { + g_hash_table_insert(NONIDLS(state), + nonIDLIfaces[i], + nonIDLIfaces[i]); + } +#endif + return TRUE; } @@ -107,15 +215,14 @@ java_epilog(TreeState *state) { /* points to other elements of the tree, so just destroy the table */ g_hash_table_destroy(TYPEDEFS(state)); + g_hash_table_destroy(KEYWORDS(state)); +#ifdef HANDLE_NON_IDL_IFACES + g_hash_table_destroy(NONIDLS(state)); +#endif + free(state->priv); state->priv = NULL; - /* - * Last pass - */ - - fprintf(state->file, "\n/*\n * end\n */\n"); - return TRUE; } @@ -135,6 +242,7 @@ forward_declaration(TreeState *state) /* XXX: Get package name and compare */ fprintf(state->file, "import %s.%s;\n", pkgName, className); #endif + return TRUE; } @@ -142,37 +250,90 @@ forward_declaration(TreeState *state) static gboolean interface_declaration(TreeState *state) { + char outname[PATH_MAX]; + char* p; IDL_tree interface = state->tree; IDL_tree iterator = NULL; - char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str; + char *interface_name = + subscriptIdentifier(state, IDL_IDENT(IDL_INTERFACE(interface).ident).str); const char *iid = NULL; + char iid_parsed[UUID_LENGTH]; + GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(interface).ident).comments; if (!verify_interface_declaration(interface)) return FALSE; + /* - * Write out JavaDoc comment + * We only want to output scriptable interfaces */ - - fprintf(state->file, "\n/**\n * Interface %s\n", interface_name); - -#ifndef LIBIDL_MAJOR_VERSION - iid = IDL_tree_property_get(interface, "uuid"); -#else - iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid"); + if (!IDL_tree_property_get(IDL_INTERFACE(interface).ident, "scriptable")) { + /* + * XXX SWT uses non-scriptable interface 'nsIAppShell' (bug 270892), so + * include that one. + */ + if (strcmp(interface_name, "nsIAppShell") != 0 +#ifdef CREATE_NSIXPCSECURITYMANAGER + && strcmp(interface_name, "nsIXPCSecurityManager") != 0 #endif - - if (iid != NULL) { - fprintf(state->file, " *\n * IID: 0x%s\n */\n\n", iid); - } else { - fputs(" */\n\n", state->file); + ) + return TRUE; } + /* + * Each Java interface must be in its own file. + */ + p = strrchr(state->filename, '/'); + if (p) { + strncpy(outname, state->filename, p + 1 - state->filename); + outname[p + 1 - state->filename] = '\0'; + } + strcat(outname, interface_name); + strcat(outname, ".java"); + + state->file = fopen(outname, "w"); + if (!state->file) { + perror("error opening output file"); + return FALSE; + } + + fprintf(state->file, "/*\n * DO NOT EDIT. THIS FILE IS GENERATED FROM\n" + " * %s.idl\n */\n", state->basename); + + /* package name (namespace) */ + fputs("\npackage org.mozilla.xpcom;\n\n", state->file); + + + iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid"); + if (iid) { + /* + * Parse uuid and then output resulting nsID to string, to + * validate uuid. + */ + struct nsID id; + if (!xpidl_parse_iid(&id, iid)) { + IDL_tree_error(state->tree, "cannot parse IID %s\n", iid); + return FALSE; + } + if (!xpidl_sprint_iid(&id, iid_parsed)) { + IDL_tree_error(state->tree, "error formatting IID %s\n", iid); + return FALSE; + } + } else { + IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n", + interface_name); + return FALSE; + } + + /* + * Write any interface comments + */ + if (doc_comments != NULL) + printlist(state->file, doc_comments); /* * Write "public interface " */ - - fprintf(state->file, "public interface %s ", interface_name); + fprintf(state->file, "public interface %s", interface_name); /* * Check for inheritence, and iterator over the inherited names, @@ -180,44 +341,32 @@ interface_declaration(TreeState *state) */ if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) { - fputs("extends ", state->file); + fputs(" extends ", state->file); do { - fprintf(state->file, "%s", IDL_IDENT(IDL_LIST(iterator).data).str); - + if (IDL_LIST(iterator).next) { fputs(", ", state->file); } } while ((iterator = IDL_LIST(iterator).next)); - } - fputs("\n{\n", state->file); - + fputs(" {\n\n", state->file); + + /* + * Write interface constants for IID + */ if (iid) { - /* - * Write interface constants for IID - */ - - fputs(" public static final String ", state->file); - - /* XXX s.b just "IID" ? */ - if (!write_classname_iid_define(state->file, interface_name)) { - return FALSE; - } - - fprintf(state->file, "_STRING =\n \"%s\";\n\n", iid); - - fputs(" public static final nsID ", state->file); - - /* XXX s.b just "IID" ? */ - if (!write_classname_iid_define(state->file, interface_name)) { - return FALSE; - } - - fprintf(state->file, " =\n new nsID(\"%s\");\n\n", iid); + /* String NS_ISUPPORTS_IID = "{00000000-0000-0000-c000-000000000046}";*/ + write_indent(state->file); + fputs("String ", state->file); + write_classname_iid_define(state->file, interface_name); + fputs(" =\n", state->file); + write_indent(state->file); + write_indent(state->file); + fprintf(state->file, "\"{%s}\";\n\n", iid_parsed); } /* @@ -231,7 +380,9 @@ interface_declaration(TreeState *state) } - fputs("\n}\n", state->file); + fputs("}", state->file); + + fclose(state->file); return TRUE; } @@ -249,34 +400,50 @@ process_list(TreeState *state) } static gboolean -xpcom_to_java_type (TreeState *state) +xpcom_to_java_type(TreeState *state, IDL_tree param) { + IDL_tree real_type, type; + IDL_tree up; + if (!state->tree) { fputs("Object", state->file); return TRUE; } - switch(IDL_NODE_TYPE(state->tree)) { + /* Could be a typedef; try to map it to the real type */ + real_type = find_underlying_type(state->tree); + type = real_type ? real_type : state->tree; + + switch(IDL_NODE_TYPE(type)) { case IDLN_TYPE_INTEGER: { - switch(IDL_TYPE_INTEGER(state->tree).f_type) { + switch(IDL_TYPE_INTEGER(type).f_type) { case IDL_INTEGER_TYPE_SHORT: - fputs("short", state->file); + if (IDL_TYPE_INTEGER(type).f_signed) + fputs("short", state->file); + else + fputs("int", state->file); break; case IDL_INTEGER_TYPE_LONG: - fputs("int", state->file); + if (IDL_TYPE_INTEGER(type).f_signed) + fputs("int", state->file); + else + fputs("long", state->file); break; case IDL_INTEGER_TYPE_LONGLONG: - fputs("long", state->file); + if (IDL_TYPE_INTEGER(type).f_signed) + fputs("long", state->file); + else + fputs("double", state->file); break; - + default: g_error(" Unknown integer type: %d\n", - IDL_TYPE_INTEGER(state->tree).f_type); + IDL_TYPE_INTEGER(type).f_type); return FALSE; } @@ -299,11 +466,18 @@ xpcom_to_java_type (TreeState *state) break; case IDLN_TYPE_OCTET: + /* If real type is 'PRUint8', promote to 'short' */ + if (IDL_NODE_TYPE(state->tree) == IDLN_IDENT) { + if (strcmp(IDL_IDENT(state->tree).str, "PRUint8") == 0) { + fputs("short", state->file); + break; + } + } fputs("byte", state->file); break; case IDLN_TYPE_FLOAT: - switch(IDL_TYPE_FLOAT(state->tree).f_type) { + switch(IDL_TYPE_FLOAT(type).f_type) { case IDL_FLOAT_TYPE_FLOAT: fputs("float", state->file); @@ -312,85 +486,171 @@ xpcom_to_java_type (TreeState *state) case IDL_FLOAT_TYPE_DOUBLE: fputs("double", state->file); break; - + default: g_error(" Unknown floating point typ: %d\n", - IDL_NODE_TYPE(state->tree)); + IDL_NODE_TYPE(type)); break; } break; case IDLN_IDENT: - if (IDL_NODE_UP(state->tree) && - IDL_NODE_TYPE(IDL_NODE_UP(state->tree)) == IDLN_NATIVE) { - const char *user_type = IDL_NATIVE(IDL_NODE_UP(state->tree)).user_type; - if (strcmp(user_type, "void") == 0) { - fputs("Object", state->file); - } - else if (strcmp(user_type, "nsID") == 0 || - strcmp(user_type, "nsIID") == 0 || - strcmp(user_type, "nsCID") == 0) { - /* XXX: s.b test for "iid" attribute */ - /* XXX: special class for nsIDs */ - fputs("nsID", state->file); - } - else { - /* XXX: special class for opaque types */ - fputs("OpaqueValue", state->file); - } - } else { - const char *ident_str = IDL_IDENT(state->tree).str; + if (!(up = IDL_NODE_UP(type))) { + IDL_tree_error(state->tree, + "ERROR: orphan ident %s in param list\n", + IDL_IDENT(state->tree).str); + return FALSE; + } + switch (IDL_NODE_TYPE(up)) { + case IDLN_FORWARD_DCL: + case IDLN_INTERFACE: { + char *className; + const char *iid_is; +handle_iid_is: + /* might get here via the goto, so re-check type */ + if (IDL_NODE_TYPE(up) == IDLN_INTERFACE) + className = IDL_IDENT(IDL_INTERFACE(up).ident).str; + else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL) + className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str; + else + className = IDL_IDENT(IDL_NATIVE(up).ident).str; - /* XXX: big kludge; s.b. way to match to typedefs */ - if (strcmp(ident_str, "PRInt8") == 0 || - strcmp(ident_str, "PRUint8") == 0) { - fputs("byte", state->file); + iid_is = NULL; + if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { + IDL_tree simple = IDL_PARAM_DCL(state->tree).simple_declarator; + iid_is = IDL_tree_property_get(simple, "iid_is"); + } + + if (iid_is) { + fputs("nsISupports", state->file); + } else { + /* + * In JavaXPCOM, we handle weak references internally; no need + * for the |nsIWeakReference| interface. So just return + * |nsISupports|. + */ + if (strcmp(className, "nsIWeakReference") == 0) { + fputs("nsISupports", state->file); + } else { +#ifdef HANDLE_NON_IDL_IFACES + char *nonidl = g_hash_table_lookup(NONIDLS(state), className); + if (nonidl) { + fputs("nsISupports", state->file); + } else +#endif + { + fprintf(state->file, "%s", className); + } + } + } + break; + } + case IDLN_NATIVE: { + char *ident; + + /* jband - adding goto for iid_is when type is native */ + if (param) { + if (IDL_NODE_TYPE(param) == IDLN_PARAM_DCL && + IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, + "iid_is")) + { + state->tree = param; + goto handle_iid_is; + } } - else if (strcmp(ident_str, "PRInt16") == 0 || - strcmp(ident_str, "PRUint16") == 0) { - fputs("short", state->file); - } - else if (strcmp(ident_str, "PRInt32") == 0 || - strcmp(ident_str, "PRUint32") == 0) { - fputs("int", state->file); - } - else if (strcmp(ident_str, "PRInt64") == 0 || - strcmp(ident_str, "PRUint64") == 0) { - fputs("long", state->file); - } - else if (strcmp(ident_str, "PRBool") == 0) { - fputs("boolean", state->file); - } - else if (strcmp(ident_str, "nsrefcnt") == 0) { - fputs("int", state->file); - } - else { + + ident = IDL_IDENT(type).str; + if (IDL_tree_property_get(type, "nsid")) { + fputs("String", state->file); + } else if (IDL_tree_property_get(type, "domstring")) { + fputs("String", state->file); + } else if (IDL_tree_property_get(type, "astring")) { + fputs("String", state->file); + } else if (IDL_tree_property_get(type, "utf8string")) { + fputs("String", state->file); + } else if (IDL_tree_property_get(type, "cstring")) { + fputs("String", state->file); + } else { + const char* user_type = IDL_NATIVE(IDL_NODE_UP(type)).user_type; IDL_tree real_type = - g_hash_table_lookup(TYPEDEFS(state), ident_str); + g_hash_table_lookup(TYPEDEFS(state), user_type); if (real_type) { + gboolean rc; IDL_tree orig_tree = state->tree; state->tree = real_type; - xpcom_to_java_type(state); + rc = xpcom_to_java_type(state, param); state->tree = orig_tree; - } - else { - fputs(ident_str, state->file); + return rc; + } else { + if (strcmp(user_type, "PRInt8") == 0) { + fputs("byte", state->file); + } else if (strcmp(user_type, "PRInt16") == 0 || + strcmp(user_type, "PRUint8") == 0) { + fputs("short", state->file); + } else if (strcmp(user_type, "PRInt32") == 0 || + strcmp(user_type, "int") == 0 || + strcmp(user_type, "PRUint16") == 0) { + fputs("int", state->file); + } else if (strcmp(user_type, "PRInt64") == 0 || + strcmp(user_type, "PRUint32") == 0) { + fputs("long", state->file); + } else if (strcmp(user_type, "PRUint64") == 0) { + fputs("double", state->file); + } else if (strcmp(user_type, "PRBool") == 0) { + fputs("boolean", state->file); + } else if (strcmp(user_type, "char") == 0 || + strcmp(user_type, "const char") == 0 || + strcmp(user_type, "unsigned char") == 0) { + if (IDL_tree_property_get(type, "ptr")) { + fputs("byte[]", state->file); + } else { + fputs("char", state->file); + } + } else if (strcmp(user_type, "nsIID") == 0) { + fputs("String", state->file); + } else if (strcmp(user_type, "nsString") == 0 || + strcmp(user_type, "nsAString") == 0 || + strcmp(user_type, "nsACString") == 0) { + fputs("String", state->file); + } else { + fputs("long", state->file); + } } } - } + break; + } + default: + if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) { + /* restart with the underlying type */ + gboolean rc; + IDL_tree orig_tree = state->tree; + state->tree = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec; + rc = xpcom_to_java_type(state, param); + state->tree = orig_tree; + return rc; + } + IDL_tree_error(state->tree, + "can't handle %s ident in param list\n", + "that type of" + ); + return FALSE; + } + break; - break; - - case IDLN_TYPE_ENUM: - case IDLN_TYPE_OBJECT: default: - g_error(" Unknown type: %d\n", - IDL_TYPE_FLOAT(state->tree).f_type); - break; + IDL_tree_error(state->tree, "can't handle %s in param list\n", +#ifdef DEBUG_shaver + /* XXX is this safe to use on Win now? */ + IDL_NODE_TYPE_NAME(IDL_NODE_UP(type)) +#else + "that type" +#endif + ); + return FALSE; } return TRUE; @@ -398,7 +658,7 @@ xpcom_to_java_type (TreeState *state) } static gboolean -xpcom_to_java_param(TreeState *state) +xpcom_to_java_param(TreeState *state) { IDL_tree param = state->tree; state->tree = IDL_PARAM_DCL(param).param_type_spec; @@ -407,7 +667,7 @@ xpcom_to_java_param(TreeState *state) * Put in type of parameter */ - if (!xpcom_to_java_type(state)) { + if (!xpcom_to_java_type(state, param)) { return FALSE; } @@ -420,13 +680,19 @@ xpcom_to_java_param(TreeState *state) fputs("[]", state->file); } + /* + * If the parameter is an array make it a Java array + */ + if (IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array")) + fputs("[]", state->file); + /* * Put in name of parameter */ - fputc(' ', state->file); - - fputs(IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str, state->file); + fputs(subscriptIdentifier(state, + IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str), + state->file); return TRUE; } @@ -452,10 +718,23 @@ type_declaration(TreeState *state) return TRUE; } +#ifdef OUTPUT_SWT_NOSCRIPT_METHODS +static gboolean +print_noscript_method(TreeState *state) +{ + IDL_tree iface = IDL_NODE_UP(IDL_NODE_UP(state->tree)); + char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str; + if (strcmp(className, "nsIBaseWindow") == 0 || + strcmp(className, "nsIEmbeddingSiteWindow") == 0) + return TRUE; + return FALSE; +} +#endif + static gboolean method_declaration(TreeState *state) { - /* IDL_tree method_tree = state->tree; */ + const char* array = NULL; struct _IDL_OP_DCL *method = &IDL_OP_DCL(state->tree); gboolean method_notxpcom = (IDL_tree_property_get(method->ident, "notxpcom") != NULL); @@ -463,21 +742,41 @@ method_declaration(TreeState *state) (IDL_tree_property_get(method->ident, "noscript") != NULL); IDL_tree iterator = NULL; IDL_tree retval_param = NULL; - const char *method_name = IDL_IDENT(method->ident).str; + char *method_name = + g_strdup_printf("%c%s", + tolower(IDL_IDENT(method->ident).str[0]), + IDL_IDENT(method->ident).str + 1); + GSList *doc_comments = IDL_IDENT(method->ident).comments; if (!verify_method_declaration(state->tree)) return FALSE; - fputc('\n', state->file); - xpidl_write_comment(state, 4); +#ifdef OUTPUT_SWT_NOSCRIPT_METHODS + if (method_notxpcom) + return TRUE; + if (method_noscript && !print_noscript_method(state)) + return TRUE; +#else + /* do not write nonscriptable methods */ + if (method_notxpcom || method_noscript) { + return TRUE; + } +#endif - /* - * Write beginning of method declaration - */ - fputs(" ", state->file); - if (!method_noscript) { - /* Nonscriptable methods become package-protected */ - fputs("public ", state->file); +#ifdef CREATE_NSIXPCSECURITYMANAGER + /* Since this interface is non-scriptable, we treat all of its methods + * as if they were [noscript] */ + { + IDL_tree iface = IDL_NODE_UP(IDL_NODE_UP(state->tree)); + char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str; + if (strcmp(className, "nsIXPCSecurityManager") == 0) + return TRUE; + } +#endif + + if (doc_comments != NULL) { + write_indent(state->file); + printlist(state->file, doc_comments); } /* @@ -485,9 +784,10 @@ method_declaration(TreeState *state) * Unlike C++ headers, Java interfaces return the declared * return value; an exception indicates XPCOM method failure. */ - if (method_notxpcom || method->op_type_spec) { + write_indent(state->file); + if (method->op_type_spec) { state->tree = method->op_type_spec; - if (!xpcom_to_java_type(state)) { + if (!xpcom_to_java_type(state, NULL)) { return FALSE; } } else { @@ -496,22 +796,29 @@ method_declaration(TreeState *state) iterator = IDL_LIST(iterator).next) { IDL_tree original_tree = state->tree; + IDL_tree simple_decl; state->tree = IDL_LIST(iterator).data; + simple_decl = IDL_PARAM_DCL(state->tree).simple_declarator; + + if (IDL_tree_property_get(simple_decl, "retval")) { + IDL_tree param; - if (IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, - "retval")) { retval_param = iterator; - - state->tree = IDL_PARAM_DCL(state->tree).param_type_spec; + array = IDL_tree_property_get(simple_decl, "array"); /* * Put in type of parameter */ - - if (!xpcom_to_java_type(state)) { + param = state->tree; + state->tree = IDL_PARAM_DCL(state->tree).param_type_spec; + if (!xpcom_to_java_type(state, param)) { return FALSE; } + + if (array) { + fputs("[]", state->file); + } } state->tree = original_tree; @@ -525,7 +832,7 @@ method_declaration(TreeState *state) /* * Write method name */ - fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1); + fprintf(state->file, " %s(", subscriptIdentifier(state, method_name)); /* * Write parameters @@ -551,6 +858,7 @@ method_declaration(TreeState *state) fputs(")", state->file); +#ifdef HANDLE_EXCEPTIONS if (method->raises_expr) { IDL_tree iter = method->raises_expr; IDL_tree dataNode = IDL_LIST(iter).data; @@ -565,11 +873,11 @@ method_declaration(TreeState *state) iter = IDL_LIST(iter).next; } } +#endif - fputs(";\n", state->file); + fputs(";\n\n", state->file); return TRUE; - } @@ -578,8 +886,15 @@ constant_declaration(TreeState *state) { struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree); const char *name = IDL_IDENT(declaration->ident).str; + GSList *doc_comments = IDL_IDENT(declaration->ident).comments; IDL_tree real_type; + const char* format; + const char* type_str; + gboolean is_long; + + gboolean success; + if (!verify_const_declaration(state->tree)) return FALSE; @@ -587,13 +902,77 @@ constant_declaration(TreeState *state) real_type = find_underlying_type(declaration->const_type); real_type = real_type ? real_type : declaration->const_type; - fputc('\n', state->file); - xpidl_write_comment(state, 4); + /* Consts must be in an interface */ + if (!IDL_NODE_UP(IDL_NODE_UP(state->tree)) || + IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(state->tree))) != + IDLN_INTERFACE) { - fprintf(state->file, " public static final %s %s = %d;\n", - (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG - ? "long" : "short"), - name, (int) IDL_INTEGER(declaration->const_exp).value); + XPIDL_WARNING((state->tree, IDL_WARNING1, + "A constant \"%s\" was declared outside an interface." + " It was ignored.", name)); + + return TRUE; + } + + /* + * The C++ header XPIDL module only allows for shorts and longs (ints) + * to be constants, so we will follow the same convention + */ + + is_long = FALSE; + + success = (IDLN_TYPE_INTEGER == IDL_NODE_TYPE(real_type)); + + if (success) { + gboolean is_signed = IDL_TYPE_INTEGER(real_type).f_signed; + format = is_signed ? "%" IDL_LL "d" : "%" IDL_LL "u"; + + switch(IDL_TYPE_INTEGER(real_type).f_type) { + case IDL_INTEGER_TYPE_SHORT: + if (is_signed) + type_str = "short"; + else + type_str = "int"; + break; + + case IDL_INTEGER_TYPE_LONG: + if (is_signed) { + type_str = "int"; + } else { + type_str = "long"; + is_long = TRUE; + } + break; + + default: + /* Whoops, it's some other kind of number */ + success = FALSE; + break; + } + } else { + IDL_tree_error(state->tree, + "const declaration \'%s\' must be of type short or long", + name); + return FALSE; + } + + if (!success) { + XPIDL_WARNING((state->tree, IDL_WARNING1, + "A constant \"%s\" was not of type short or long." + " It was ignored.", name)); + return FALSE; + } + + if (doc_comments != NULL) { + write_indent(state->file); + printlist(state->file, doc_comments); + } + + write_indent(state->file); + fprintf(state->file, "%s %s = ", type_str, + subscriptIdentifier(state, (char*) name)); + fprintf(state->file, format, IDL_INTEGER(declaration->const_exp).value); + fprintf(state->file, "%s;\n\n", is_long ? "L" : ""); return TRUE; @@ -607,59 +986,61 @@ constant_declaration(TreeState *state) static gboolean attribute_declaration(TreeState *state) { - gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly; - char *attribute_name = ATTR_IDENT(state->tree).str; + char *attribute_name; + GSList *doc_comments; + gboolean read_only; - gboolean method_noscript = - (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") != NULL); - -#if 0 - /* - * Disabled here because I can't verify this check against possible - * users of the java xpidl backend. - */ if (!verify_attribute_declaration(state->tree)) return FALSE; + + attribute_name = ATTR_IDENT(state->tree).str; + read_only = IDL_ATTR_DCL(state->tree).f_readonly; + +#ifdef OUTPUT_SWT_NOSCRIPT_METHODS + if (IDL_tree_property_get(ATTR_PROPS(state->tree), "notxpcom")) + return TRUE; + if (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") && + !print_noscript_method(state)) + return TRUE; +#else + if (IDL_tree_property_get(ATTR_PROPS(state->tree), "notxpcom") || + IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript")) + return TRUE; #endif - /* Comment */ - fputc('\n', state->file); - xpidl_write_comment(state, 4); - - state->tree = ATTR_TYPE_DECL(state->tree); - - /* - * Write access permission ("public" unless nonscriptable) - */ - fputs(" ", state->file); - if (!method_noscript) { - fputs("public ", state->file); + doc_comments = + IDL_IDENT(IDL_LIST(IDL_ATTR_DCL + (state->tree).simple_declarations).data).comments; + if (doc_comments != NULL) { + write_indent(state->file); + printlist(state->file, doc_comments); } /* * Write the proper Java return value for the get operation */ - if (!xpcom_to_java_type(state)) { + write_indent(state->file); + state->tree = ATTR_TYPE_DECL(state->tree); + if (!xpcom_to_java_type(state, NULL)) { return FALSE; } /* * Write the name of the accessor ("get") method. */ - fprintf(state->file, " get%c%s();\n", + fprintf(state->file, " get%c%s();\n\n", toupper(attribute_name[0]), attribute_name + 1); - if (!read_only) { - /* Nonscriptable methods become package-protected */ - fputs(" ", state->file); - if (!method_noscript) { - fputs("public ", state->file); + if (doc_comments != NULL) { + write_indent(state->file); + printlist(state->file, doc_comments); } /* * Write attribute access method name and return type */ + write_indent(state->file); fprintf(state->file, "void set%c%s(", toupper(attribute_name[0]), attribute_name+1); @@ -667,14 +1048,15 @@ attribute_declaration(TreeState *state) /* * Write the proper Java type for the set operation */ - if (!xpcom_to_java_type(state)) { + if (!xpcom_to_java_type(state, NULL)) { return FALSE; } /* * Write the name of the formal parameter. */ - fputs(" value);\n", state->file); + fprintf(state->file, " a%c%s);\n\n", toupper(attribute_name[0]), + attribute_name + 1); } return TRUE; @@ -719,3 +1101,15 @@ xpidl_java_dispatch(void) result.dispatch_table = table; return &result; } + +char* subscriptIdentifier(TreeState *state, char *str) +{ + char *sstr = NULL; + char *keyword = g_hash_table_lookup(KEYWORDS(state), str); + if (keyword) { + sstr = g_strdup_printf("_%s", keyword); + return sstr; + } + return str; +} +