From 7c28c101fba7692fe17b86a7b6a1fe6670e7c9dc Mon Sep 17 00:00:00 2001 From: "sdv%sparc.spb.su" Date: Thu, 5 Oct 2000 14:54:47 +0000 Subject: [PATCH] part of xipidl compiler to generate java interfaces --- java/xpcom/java/xpidl/Makefile | 73 +++ java/xpcom/java/xpidl/Makefile.in | 73 +++ java/xpcom/java/xpidl/makefile.win | 68 +++ java/xpcom/java/xpidl/xpidl_idl.c | 746 +++++++++++++++++++++++++ java/xpcom/java/xpidl/xpidl_java.c | 859 +++++++++++++++++++++++++++++ 5 files changed, 1819 insertions(+) create mode 100644 java/xpcom/java/xpidl/Makefile create mode 100644 java/xpcom/java/xpidl/Makefile.in create mode 100644 java/xpcom/java/xpidl/makefile.win create mode 100644 java/xpcom/java/xpidl/xpidl_idl.c create mode 100644 java/xpcom/java/xpidl/xpidl_java.c diff --git a/java/xpcom/java/xpidl/Makefile b/java/xpcom/java/xpidl/Makefile new file mode 100644 index 00000000000..bc89935e2e3 --- /dev/null +++ b/java/xpcom/java/xpidl/Makefile @@ -0,0 +1,73 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../../.. +topsrcdir = ../../../.. +srcdir = . +VPATH = . +XPIDLDIR = $(DEPTH)/xpcom/typelib/xpidl + +include $(DEPTH)/config/autoconf.mk + +PROGRAM = xpidl$(BIN_SUFFIX) +INTERNAL_TOOLS = 1 + +CSRCS = \ + $(XPIDLDIR)/xpidl.c \ + xpidl_idl.c \ + $(XPIDLDIR)/xpidl_util.c \ + $(XPIDLDIR)/xpidl_header.c \ + $(XPIDLDIR)/xpidl_typelib.c \ + $(XPIDLDIR)/xpidl_doc.c \ + xpidl_java.c \ + $(NULL) + + +CFLAGS += $(LIBIDL_CFLAGS) -I$(XPIDLDIR) + +ifdef CROSS_COMPILE +HOST_PROGRAM = host_xpidl +HOST_CSRCS = $(CSRCS) +endif + +include $(topsrcdir)/config/rules.mk + + + +# Compile directly against the static lib, so we can use xpidl during the build +# without the shared library path being set. +LIBS = $(DIST)/lib/libxpt.$(LIB_SUFFIX) $(LIBIDL_LIBS) + +# Tell the $(PROGRAM) target that we need to be recompiled when libxpt changes. +EXTRA_DEPS = $(wildcard $(DIST)/lib/libxpt.*) + +ifdef CROSS_COMPILE +HOST_CFLAGS += $(HOST_LIBIDL_CFLAGS) +HOST_LIBS = $(DIST)/host/lib/libhostxpt.$(LIB_SUFFIX) $(HOST_LIBIDL_LIBS) +HOST_EXTRA_DEPS = $(wildcard $(DIST)/host/lib/libhostxpt.*) + +ifdef HOST_NSPR_MDCPUCFG +HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG) +endif +endif + +export:: install + diff --git a/java/xpcom/java/xpidl/Makefile.in b/java/xpcom/java/xpidl/Makefile.in new file mode 100644 index 00000000000..431f1a48e57 --- /dev/null +++ b/java/xpcom/java/xpidl/Makefile.in @@ -0,0 +1,73 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +XPIDLDIR = $(DEPTH)/xpcom/typelib/xpidl + +include $(DEPTH)/config/autoconf.mk + +PROGRAM = xpidl$(BIN_SUFFIX) +INTERNAL_TOOLS = 1 + +CSRCS = \ + $(XPIDLDIR)/xpidl.c \ + xpidl_idl.c \ + $(XPIDLDIR)/xpidl_util.c \ + $(XPIDLDIR)/xpidl_header.c \ + $(XPIDLDIR)/xpidl_typelib.c \ + $(XPIDLDIR)/xpidl_doc.c \ + xpidl_java.c \ + $(NULL) + + +CFLAGS += $(LIBIDL_CFLAGS) -I$(XPIDLDIR) + +ifdef CROSS_COMPILE +HOST_PROGRAM = host_xpidl +HOST_CSRCS = $(CSRCS) +endif + +include $(topsrcdir)/config/rules.mk + + + +# Compile directly against the static lib, so we can use xpidl during the build +# without the shared library path being set. +LIBS = $(DIST)/lib/libxpt.$(LIB_SUFFIX) $(LIBIDL_LIBS) + +# Tell the $(PROGRAM) target that we need to be recompiled when libxpt changes. +EXTRA_DEPS = $(wildcard $(DIST)/lib/libxpt.*) + +ifdef CROSS_COMPILE +HOST_CFLAGS += $(HOST_LIBIDL_CFLAGS) +HOST_LIBS = $(DIST)/host/lib/libhostxpt.$(LIB_SUFFIX) $(HOST_LIBIDL_LIBS) +HOST_EXTRA_DEPS = $(wildcard $(DIST)/host/lib/libhostxpt.*) + +ifdef HOST_NSPR_MDCPUCFG +HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG) +endif +endif + +export:: install + diff --git a/java/xpcom/java/xpidl/makefile.win b/java/xpcom/java/xpidl/makefile.win new file mode 100644 index 00000000000..cecd59873d9 --- /dev/null +++ b/java/xpcom/java/xpidl/makefile.win @@ -0,0 +1,68 @@ +#!nmake +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + +DEPTH=..\..\..\.. + +MAKE_OBJ_TYPE = EXE +PROGRAM = .\$(OBJDIR)\xpidl.exe +#RESFILE = xpidl.res + +# glib and libIDL link against the non-debug msvcrt +MOZ_NO_DEBUG_RTL=1 +XPIDLDIR = $(DEPTH)\xpcom\typelib\xpidl + + +OBJS = \ + $(XPIDLDIR)\$(OBJDIR)\xpidl.obj \ + .\$(OBJDIR)\xpidl_idl.obj \ + $(XPIDLDIR)\$(OBJDIR)\xpidl_util.obj \ + $(XPIDLDIR)\$(OBJDIR)\xpidl_header.obj \ + $(XPIDLDIR)\$(OBJDIR)\xpidl_typelib.obj \ + $(XPIDLDIR)\$(OBJDIR)\xpidl_doc.obj \ + .\$(OBJDIR)\xpidl_java.obj \ + $(NULL) + +LINCS=-I$(PUBLIC)\xpcom \ + -I$(MOZ_TOOLS)\include \ + -I$(XPIDLDIR) \ + $(NULL) + +LCFLAGS = -DEXPORT_XPT_API + +MYDIR=C:\USR\LOCAL + +LLIBS= \ + $(DIST)\lib\xpcomxpt_s.lib \ + $(MOZ_TOOLS)\lib\glib-1.2.lib \ + $(MOZ_TOOLS)\lib\libidl-0.6.lib \ + $(NULL) + +LLFLAGS= $(LLFLAGS) -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRTD + +include <$(DEPTH)\config\rules.mak> + +export:: $(PROGRAM) + $(MAKE_INSTALL) $(PROGRAM) $(DIST)\bin + +clobber:: + rm -f $(DIST)\bin\xpidl.exe + +$(PROGRAM):: $(OBJS) $(MYLIBS) diff --git a/java/xpcom/java/xpidl/xpidl_idl.c b/java/xpcom/java/xpidl/xpidl_idl.c new file mode 100644 index 00000000000..4142f791e56 --- /dev/null +++ b/java/xpcom/java/xpidl/xpidl_idl.c @@ -0,0 +1,746 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/* + * Common IDL-processing code. + */ + +#include "xpidl.h" + +/* + * The bulk of the generation happens here. + */ +gboolean +xpidl_process_node(TreeState *state) +{ + gint type; + nodeHandler *dispatch, handler; + + assert(state->tree); + type = IDL_NODE_TYPE(state->tree); + + if ((dispatch = state->dispatch) && (handler = dispatch[type])) + return handler(state); + return TRUE; +} + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) +extern void mac_warning(const char* warning_message); +#endif + +static int +msg_callback(int level, int num, int line, const char *file, + const char *message) +{ + char *warning_message; + + if (!file) + file = ""; + warning_message = g_strdup_printf("%s:%d: %s\n", file, line, message); + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) + mac_warning(warning_message); +#else + fputs(warning_message, stderr); +#endif + + free(warning_message); + return 1; +} + +/* + * To keep track of the state associated with a given input file. The 'next' + * field lets us maintain a stack of input files. + */ +typedef struct input_data { + char *filename; /* where did I come from? */ + unsigned int lineno; /* last lineno processed */ + char *buf; /* contents of file */ + char *point; /* next char to feed to libIDL */ + char *max; /* 1 past last char in buf */ + struct input_data *next; /* file from which we were included */ +} input_data; + +/* + * Passed to us by libIDL. Holds global information and the current stack of + * include files. + */ +typedef struct input_callback_state { + struct input_data *input_stack; /* linked list of input_data */ + GHashTable *already_included; /* to prevent redundant includes */ + IncludePathEntry *include_path; /* search path for included files */ + GSList *base_includes; /* to accumulate #includes from *first* file; + * for passing thru TreeState to + * xpidl_header backend. */ +} input_callback_state; + +static FILE * +fopen_from_includes(const char *filename, const char *mode, + IncludePathEntry *include_path) +{ + IncludePathEntry *current_path = include_path; + char *pathname; + FILE *inputfile; + if (!strcmp(filename, "-")) + return stdin; + + if (filename[0] != '/') { + while (current_path) { + pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", + current_path->directory, filename); + if (!pathname) + return NULL; + inputfile = fopen(pathname, mode); + free(pathname); + if (inputfile) + return inputfile; + current_path = current_path->next; + } + } else { + inputfile = fopen(filename, mode); + if (inputfile) + return inputfile; + } + return NULL; +} + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) +extern FILE* mac_fopen(const char* filename, const char *mode); +#endif + +static input_data * +new_input_data(const char *filename, IncludePathEntry *include_path) +{ + input_data *new_data; + FILE *inputfile; + char *buffer = NULL; + size_t offset = 0; + size_t buffer_size; +#ifdef XP_MAC + size_t i; +#endif + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) + // on Mac, fopen knows how to find files. + inputfile = fopen(filename, "r"); +#else + inputfile = fopen_from_includes(filename, "r", include_path); +#endif + + if (!inputfile) + return NULL; + + /* + * Rather than try to keep track of many different varieties of state + * around the boundaries of a circular buffer, we just read in the entire + * file. + * + * We iteratively grow the buffer here; an alternative would be to use + * stat to find the exact buffer size we need, as xpt_dump does. + */ + for (buffer_size = 8191; ; buffer_size *= 2) { + size_t just_read; + buffer = realloc(buffer, buffer_size + 1); /* +1 for trailing nul */ + just_read = fread(buffer + offset, 1, buffer_size - offset, inputfile); + if (ferror(inputfile)) + return NULL; + + if (just_read < buffer_size - offset || just_read == 0) { + /* Done reading. */ + offset += just_read; + break; + } + offset += just_read; + } + fclose(inputfile); + +#ifdef XP_MAC + /* + * libIDL doesn't speak '\r' properly - always make sure lines end with + * '\n'. + */ + for (i = 0; i < offset; i++) { + if (buffer[i] == '\r') + buffer[i] = '\n'; + } +#endif + + new_data = xpidl_malloc(sizeof (struct input_data)); + new_data->point = new_data->buf = buffer; + new_data->max = buffer + offset; + *new_data->max = '\0'; + new_data->filename = xpidl_strdup(filename); + /* libIDL expects the line number to be that of the *next* line */ + new_data->lineno = 2; + new_data->next = NULL; + + return new_data; +} + +/* process pending raw section */ +static int +NextIsRaw(input_data *data, char **startp, int *lenp) +{ + char *end, *start; + + /* + * XXXmccabe still needed: an in_raw flag to handle the case where we're in + * a raw block, but haven't managed to copy it all to xpidl. This will + * happen when we have a raw block larger than + * IDL_input_data->fill.max_size (currently 8192.) + */ + if (!(data->point[0] == '%' && data->point[1] == '{')) + return 0; + + start = *startp = data->point; + + end = NULL; + while (start < data->max && (end = strstr(start, "%}"))) { + if (end[-1] == '\r' || + end[-1] == '\n') + break; + start = end + 1; + } + + if (end && start < data->max) { + *lenp = end - data->point + 2; + return 1; + } else { + const char *filename; + int lineno; + + IDL_file_get(&filename, &lineno); + msg_callback(IDL_ERROR, 0, lineno, filename, + "unterminated %{ block"); + return -1; + } +} + +/* process pending comment */ +static int +NextIsComment(input_data *data, char **startp, int *lenp) +{ + char *end; + + if (!(data->point[0] == '/' && data->point[1] == '*')) + return 0; + + end = strstr(data->point, "*/"); + *lenp = 0; + if (end) { + int skippedLines = 0; + char *tempPoint; + + /* get current lineno */ + IDL_file_get(NULL,(int *)&data->lineno); + + /* get line count */ + for (tempPoint = data->point; tempPoint < end; tempPoint++) { + if (*tempPoint == '\n') + skippedLines++; + } + + data->lineno += skippedLines; + IDL_file_set(data->filename, (int)data->lineno); + + *startp = end + 2; + + /* If it's a ** comment, tell libIDL about it. */ + if (data->point[2] == '*') { + /* hack termination. +2 to get past '*' '/' */ + char t = *(end + 2); + *(end + 2) = '\0'; + IDL_queue_new_ident_comment(data->point); + *(end + 2) = t; + } + + data->point = *startp; /* XXXmccabe move this out of function? */ + return 1; + } else { + const char *filename; + int lineno; + + IDL_file_get(&filename, &lineno); + msg_callback(IDL_ERROR, 0, lineno, filename, + "unterminated comment"); + return -1; + } +} + +static int +NextIsInclude(input_callback_state *callback_state, char **startp, + int *lenp) +{ + input_data *data = callback_state->input_stack; + input_data *new_data; + char *filename, *start, *end; + const char *scratch; + + /* process the #include that we're in now */ + if (strncmp(data->point, "#include \"", 10)) { + return 0; + } + + filename = data->point + 10; /* skip #include " */ + assert(filename < data->max); + end = filename; + while (end < data->max) { + if (*end == '\"' || *end == '\n' || *end == '\r') + break; + end++; + } + + if (*end != '\"') { + /* + * Didn't find end of include file. Scan 'til next whitespace to find + * some reasonable approximation of the filename, and use it to report + * an error. + */ + + end = filename; + while (end < data->max) { + if (*end == ' ' || *end == '\n' || *end == '\r' || *end == '\t') + break; + end++; + } + *end = '\0'; + + /* make sure we have accurate line info */ + IDL_file_get(&scratch, (int *)&data->lineno); + fprintf(stderr, + "%s:%d: didn't find end of quoted include name \"%s\n", + scratch, data->lineno, filename); + return -1; + } + + *end = '\0'; + *startp = end + 1; + + if (data->next == NULL) { + /* + * If we're in the initial file, add this filename to the list + * of filenames to be turned into #include "filename.h" + * directives in xpidl_header.c. We do it here rather than in the + * block below so it still gets added to the list even if it's + * already been recursively included from some other file. + */ + char *filename_cp = xpidl_strdup(filename); + + /* note that g_slist_append accepts and likes null as list-start. */ + callback_state->base_includes = + g_slist_append(callback_state->base_includes, filename_cp); + } + + /* store offset for when we pop, or if we skip this one */ + data->point = *startp; + + if (!g_hash_table_lookup(callback_state->already_included, filename)) { + filename = xpidl_strdup(filename); + g_hash_table_insert(callback_state->already_included, + filename, (void *)TRUE); + new_data = new_input_data(filename, callback_state->include_path); + if (!new_data) { + char *error_message; + IDL_file_get(&scratch, (int *)&data->lineno); + error_message = + g_strdup_printf("can't open included file %s for reading\n", + filename); + msg_callback(IDL_ERROR, 0, + data->lineno, scratch, error_message); + free(error_message); + return -1; + } + + new_data->next = data; + /* tell libIDL to exclude this IDL from the toplevel tree */ + IDL_inhibit_push(); + IDL_file_get(&scratch, (int *)&data->lineno); + callback_state->input_stack = new_data; + IDL_file_set(new_data->filename, (int)new_data->lineno); + } + + *lenp = 0; /* this is magic, see the comment below */ + return 1; +} + +static void +FindSpecial(input_data *data, char **startp, int *lenp) +{ + char *point = data->point; + + /* magic sequences are: + * "%{" raw block + * "/\*" comment + * "#include \"" include + * The first and last want a newline [\r\n] before, or the start of the + * file. + */ + +#define LINE_START(data, point) (point == data->buf || \ + (point > data->point && \ + (point[-1] == '\r' || point[-1] == '\n'))) + + while (point < data->max) { + if (point[0] == '/' && point[1] == '*') + break; + if (LINE_START(data, point)) { + if (point[0] == '%' && point[1] == '{') + break; + if (point[0] == '#' && !strncmp(point + 1, "include \"", 9)) + break; + } + point++; + } + +#undef LINE_START + + *startp = data->point; + *lenp = point - data->point; +} + +/* set this with a debugger to see exactly what libIDL sees */ +static FILE *tracefile; + +static int +input_callback(IDL_input_reason reason, union IDL_input_data *cb_data, + gpointer user_data) +{ + input_callback_state *callback_state = user_data; + input_data *data = callback_state->input_stack; + input_data *new_data = NULL; + unsigned int len, copy; + int rv; + char *start; + + switch(reason) { + case IDL_INPUT_REASON_INIT: + if (data == NULL || data->next == NULL) { + /* + * This is the first file being processed. As it's the target + * file, we only look for it in the first entry in the include + * path, which we assume to be the current directory. + */ + + /* XXXmccabe proper assumption? Do we handle files in other + directories? */ + + IncludePathEntry first_entry; + + first_entry.directory = callback_state->include_path->directory; + first_entry.next = NULL; + + new_data = new_input_data(cb_data->init.filename, + &first_entry); + } else { + new_data = new_input_data(cb_data->init.filename, + callback_state->include_path); + } + + if (!new_data) + return -1; + + IDL_file_set(new_data->filename, (int)new_data->lineno); + callback_state->input_stack = new_data; + return 0; + + case IDL_INPUT_REASON_FILL: + start = NULL; + len = 0; + + while (data->point >= data->max) { + if (!data->next) + return 0; + + /* Current file is done; revert to including file */ + callback_state->input_stack = data->next; + free(data->filename); + free(data->buf); + free(data); + data = callback_state->input_stack; + + IDL_file_set(data->filename, (int)data->lineno); + IDL_inhibit_pop(); + } + + /* + * Now we scan for sequences which require special attention: + * \n#include begins an include statement + * \n%{ begins a raw-source block + * /\* begins a comment + * + * We used to be fancier here, so make sure that we sent the most + * data possible at any given time. To that end, we skipped over + * \n%{ raw \n%} blocks and then _continued_ the search for special + * sequences like \n#include or /\* comments . + * + * It was really ugly, though -- liberal use of goto! lots of implicit + * state! what fun! -- so now we just do this: + * + * if (special at start) { + * process that special - + * - raw: send it to libIDL, and don't look inside for specials + * - comments: adjust point and start over + * - includes: push new input_data struct for included file, and + * start over + * } else { + * scan for next special + * send data up to that special to libIDL + * } + * + * If len is set to zero, it is a sentinel value indicating we a comment + * or include was found, and parsing should start over. + * + * XXX const string foo = "/\*" will just screw us horribly. + * Hm but. We could treat strings as we treat raw blocks, eh? + */ + + /* + * Order is important, so that you can have /\* comments and + * #includes within raw sections, and so that you can comment out + * #includes. + */ + rv = NextIsRaw(data, &start, (int *)&len); + if (rv == -1) return -1; + if (!rv) { + /* + * When NextIsComment succeeds, it returns a 0 len (requesting a + * restart) and adjusts data->point to pick up after the comment. + */ + rv = NextIsComment(data, &start, (int *)&len); + if (rv == -1) return -1; + if (!rv) { + /* + * NextIsInclude might push a new input_data struct; if so, it + * will return a 0 len, letting the callback pick up the new + * file the next time around. + */ + rv = NextIsInclude(callback_state, &start, (int *)&len); + if (rv == -1) return -1; + if (!rv) + FindSpecial(data, &start, (int *)&len); + } + } + + if (len == 0) { + /* + * len == 0 is a sentinel value that means we found a comment or + * include. If we found a comment, point has been adjusted to + * point past the comment. If we found an include, a new input_data + * has been pushed. In both cases, calling the input_callback again + * will pick up the new state. + */ + return input_callback(reason, cb_data, user_data); + } + + copy = MIN(len, (unsigned int) cb_data->fill.max_size); + memcpy(cb_data->fill.buffer, start, copy); + data->point = start + copy; + + if (tracefile) + fwrite(cb_data->fill.buffer, copy, 1, tracefile); + + return copy; + + case IDL_INPUT_REASON_ABORT: + case IDL_INPUT_REASON_FINISH: + while (data != NULL) { + input_data *next; + + next = data->next; + free(data->filename); + free(data->buf); + free(data); + data = next; + } + return 0; + + default: + g_error("unknown input reason %d!", reason); + return -1; + } +} + +static void +free_ghash_key(gpointer key, gpointer value, gpointer user_data) +{ + /* We're only storing TRUE in the value... */ + free(key); +} + +static void +free_gslist_data(gpointer data, gpointer user_data) +{ + free(data); +} + +/* Pick up unlink. */ +#ifdef XP_UNIX +#include +#elif XP_WIN +/* We get it from stdio.h. */ +#endif + +int +xpidl_process_idl(char *filename, IncludePathEntry *include_path, + char *file_basename, ModeData *mode) +{ + char *tmp, *outname, *mode_outname = NULL; + IDL_tree top; + TreeState state; + int rv; + input_callback_state callback_state; + gboolean ok; + backend *emitter; + + callback_state.input_stack = NULL; + callback_state.base_includes = NULL; + callback_state.include_path = include_path; + callback_state.already_included = g_hash_table_new(g_str_hash, g_str_equal); + + if (!callback_state.already_included) { + fprintf(stderr, "failed to create hashtable. out of memory?\n"); + return 0; + } + + state.basename = xpidl_strdup(filename); + + /* if basename has an .extension, truncate it. */ + tmp = strrchr(state.basename, '.'); + if (tmp) + *tmp = '\0'; + + if (!file_basename) + outname = xpidl_strdup(state.basename); + else + outname = xpidl_strdup(file_basename); + + /* so we don't include it again! */ + g_hash_table_insert(callback_state.already_included, + xpidl_strdup(filename), (void *)TRUE); + + rv = IDL_parse_filename_with_input(filename, input_callback, &callback_state, + msg_callback, &top, + &state.ns, + IDLF_IGNORE_FORWARDS | + IDLF_XPIDL, + enable_warnings ? IDL_WARNING1 : + IDL_ERROR); + if (rv != IDL_SUCCESS) { + if (rv == -1) { + g_warning("Parse of %s failed: %s", filename, g_strerror(errno)); + } else { + g_warning("Parse of %s failed", filename); + } + return 0; + } + + state.basename = xpidl_strdup(filename); + tmp = strrchr(state.basename, '.'); + if (tmp) + *tmp = '\0'; + + /* so xpidl_header.c can use it to generate a list of #include directives */ + state.base_includes = callback_state.base_includes; + + emitter = mode->factory(); + state.dispatch = emitter->dispatch_table; + + if (strcmp(outname, "-")) { + // don't open file if the mode is "java" + if (strcmp(mode->mode, "java")) { + const char *fopen_mode; + mode_outname = g_strdup_printf("%s.%s", outname, mode->suffix); + /* Use binary write for typelib mode */ + fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb"; + state.file = fopen(mode_outname, fopen_mode); + if (!state.file) { + perror("error opening output file"); + return 0; + } + } else { + state.file = NULL; + } + } else { + state.file = stdout; + } + state.tree = top; + + if (emitter->emit_prolog) + emitter->emit_prolog(&state); + ok = xpidl_process_node(&state); + if (emitter->emit_epilog) + emitter->emit_epilog(&state); + + if (state.file && state.file != stdout) + fclose(state.file); + free(state.basename); + free(outname); + g_hash_table_foreach(callback_state.already_included, free_ghash_key, NULL); + g_hash_table_destroy(callback_state.already_included); + g_slist_foreach(callback_state.base_includes, free_gslist_data, NULL); + + IDL_ns_free(state.ns); + IDL_tree_free(top); + + if (mode_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(mode_outname); +#endif + free(mode_outname); + } + + return ok; +} + +/* + * Our own version of IDL_tree_warning, which we use when IDL_tree_warning + * would crash on us. + */ +void +xpidl_tree_warning(IDL_tree p, int level, const char *fmt, ...) +{ + va_list ap; + char *msg, *file; + int lineno; + + /* XXX need to check against __IDL_max_msg_level, no accessor */ + va_start(ap, fmt); + msg = g_strdup_vprintf(fmt, ap); + + if (p) { + file = p->_file; + lineno = p->_line; + } else { + file = NULL; + lineno = 0; + } + + /* call our message callback, like IDL_tree_warning would */ + msg_callback(level, 0, lineno, file, msg); + + va_end(ap); +} diff --git a/java/xpcom/java/xpidl/xpidl_java.c b/java/xpcom/java/xpidl/xpidl_java.c new file mode 100644 index 00000000000..b40da0bf986 --- /dev/null +++ b/java/xpcom/java/xpidl/xpidl_java.c @@ -0,0 +1,859 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Sun Microsystems, + * Inc. Portions created by Sun are + * Copyright (C) 1999 Sun Microsystems, Inc. All + * Rights Reserved. + * + * Contributor(s): + * Michael Allen (michael.allen@sun.com) + * Frank Mitchell (frank.mitchell@sun.com) + */ + +/* + * Generate Java interfaces from XPIDL. + */ + +#include "xpidl.h" +#include +#include + + +/* + * Write a one-line comment containing IDL + * source decompiled from state->tree. + */ +void write_comment(TreeState *state); + +struct java_priv_data { + GHashTable *typedefTable; + FILE *file; +}; + +#define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable) +#define FILENAME(state) (((struct java_priv_data *)state->priv)->file) + +static gboolean +write_classname_iid_define(FILE *file, const char *className) +{ + const char *iidName; + if (className[0] == 'n' && className[1] == 's') { + /* backcompat naming styles */ + fputs("NS_", file); + iidName = className + 2; + } else { + iidName = className; + } + + while (*iidName) { + fputc(toupper(*iidName++), file); + } + + fputs("_IID", file); + + return TRUE; +} + +static gboolean +java_prolog(TreeState *state) +{ + 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)) { + /* XXX report error */ + free(state->priv); + return FALSE; + } + + return TRUE; +} + +static gboolean +java_epilog(TreeState *state) +{ + /* points to other elements of the tree, so just destroy the table */ + g_hash_table_destroy(TYPEDEFS(state)); + free(state->priv); + state->priv = NULL; + + return TRUE; +} + +static gboolean +forward_declaration(TreeState *state) +{ + /* + * Java doesn't need forward declarations unless the declared + * class resides in a different package. + */ +#if 0 + IDL_tree iface = state->tree; + const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str; + const char *pkgName = "org.mozilla.xpcom"; + if (!className) + return FALSE; + /* XXX: Get package name and compare */ + fprintf(FILENAME(state), "import %s.%s;\n", pkgName, className); +#endif + return TRUE; +} + + +static gboolean +interface_declaration(TreeState *state) +{ + + char *outname; + IDL_tree interface = state->tree; + IDL_tree iterator = NULL; + char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str; + const char *iid = NULL; + GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(interface).ident).comments; + char *prefix = IDL_GENTREE(IDL_NS(state->ns).current)._cur_prefix; + + /* + * Each interface decl is a single file + */ + outname = g_strdup_printf("%s.%s", interface_name, "java"); + FILENAME(state) = fopen(outname, "w"); + if (!FILENAME(state)) { + perror("error opening output file"); + return FALSE; + } + + fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n", + FILENAME(state)); + + fprintf(FILENAME(state), + " *\n * This file was automatically generated from %s.idl.\n", + state->basename); + + fputs(" */\n\n", FILENAME(state)); + + if (prefix) { + if (strlen(prefix)) + fprintf(FILENAME(state), "\npackage %s;\n\n", prefix); + fputs("import org.mozilla.xpcom.*;\n\n", FILENAME(state)); + } else { + fputs("\npackage org.mozilla.xpcom;\n\n", FILENAME(state)); + } + + /* + * Write out JavaDoc comment + */ + + fprintf(FILENAME(state), "\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"); +#endif + + if (iid != NULL) { + fprintf(FILENAME(state), " *\n * IID: 0x%s\n */\n\n", iid); + } else { + fputs(" */\n\n", FILENAME(state)); + } + + if (doc_comments != NULL) + printlist(FILENAME(state), doc_comments); + + /* + * Write "public interface " + */ + + fprintf(FILENAME(state), "public interface %s ", interface_name); + + /* + * Check for inheritence, and iterator over the inherited names, + * if any. + */ + + if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) { + fputs("extends ", FILENAME(state)); + + do { + + fprintf(FILENAME(state), "%s", + IDL_IDENT(IDL_LIST(iterator).data).str); + + if (IDL_LIST(iterator).next) { + fputs(", ", FILENAME(state)); + } + } while ((iterator = IDL_LIST(iterator).next)); + + } + + fputs("\n{\n", FILENAME(state)); + + if (iid) { + /* + * Write interface constants for IID + */ + +/* fputs(" public static final String ", FILENAME(state)); */ + + /* XXX s.b just "IID" ? */ +/* if (!write_classname_iid_define(FILENAME(state), interface_name)) { */ +/* return FALSE; */ +/* } */ + +/* fprintf(FILENAME(state), "_STRING =\n \"%s\";\n\n", iid); */ + +/* fputs(" public static final nsID ", FILENAME(state)); */ + + /* XXX s.b just "IID" ? */ +/* if (!write_classname_iid_define(FILENAME(state), interface_name)) { */ +/* return FALSE; */ +/* } */ + +/* fprintf(FILENAME(state), " =\n new nsID(\"%s\");\n\n", iid); */ + fprintf(FILENAME(state), " public static final String IID =\n \"%s\";\n\n", iid); + } + + /* + * Advance the state of the tree, go on to process more + */ + + state->tree = IDL_INTERFACE(interface).body; + + if (state->tree && !xpidl_process_node(state)) { + return FALSE; + } + + + fputs("\n}\n", FILENAME(state)); + fprintf(FILENAME(state), "\n/*\n * end\n */\n"); + fclose(FILENAME(state)); + free(outname); + + return TRUE; +} + +static gboolean +process_list(TreeState *state) +{ + IDL_tree iter; + gint type; + for (iter = state->tree; iter; iter = IDL_LIST(iter).next) { + state->tree = IDL_LIST(iter).data; + type = IDL_NODE_TYPE(state->tree); + if (!xpidl_process_node(state)) + return FALSE; + } + return TRUE; +} + +static gboolean +xpcom_to_java_type (TreeState *state) +{ + if (!state->tree) { + fputs("Object", FILENAME(state)); + return TRUE; + } + + + switch(IDL_NODE_TYPE(state->tree)) { + + case IDLN_TYPE_INTEGER: { + + switch(IDL_TYPE_INTEGER(state->tree).f_type) { + + case IDL_INTEGER_TYPE_SHORT: + fputs("short", FILENAME(state)); + break; + + case IDL_INTEGER_TYPE_LONG: + fputs("int", FILENAME(state)); + break; + + case IDL_INTEGER_TYPE_LONGLONG: + fputs("long", FILENAME(state)); + break; + + default: + g_error(" Unknown integer type: %d\n", + IDL_TYPE_INTEGER(state->tree).f_type); + return FALSE; + + } + + break; + } + + case IDLN_TYPE_CHAR: + case IDLN_TYPE_WIDE_CHAR: + fputs("char", FILENAME(state)); + break; + + case IDLN_TYPE_WIDE_STRING: + case IDLN_TYPE_STRING: + fputs("String", FILENAME(state)); + break; + + case IDLN_TYPE_BOOLEAN: + fputs("boolean", FILENAME(state)); + break; + + case IDLN_TYPE_OCTET: + fputs("byte", FILENAME(state)); + break; + + case IDLN_TYPE_FLOAT: + switch(IDL_TYPE_FLOAT(state->tree).f_type) { + + case IDL_FLOAT_TYPE_FLOAT: + fputs("float", FILENAME(state)); + break; + + case IDL_FLOAT_TYPE_DOUBLE: + fputs("double", FILENAME(state)); + break; + + default: + g_error(" Unknown floating point typ: %d\n", + IDL_NODE_TYPE(state->tree)); + 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; + const char *ident_str = IDL_IDENT(IDL_NATIVE(IDL_NODE_UP(state->tree)).ident).str; + if (strcmp(user_type, "void") == 0) { + fputs("Object", FILENAME(state)); + } + 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("IID", FILENAME(state)); + } + else { + /* XXX: special class for opaque types */ + fputs("OpaqueValue", FILENAME(state)); + } + } else { + const char *ident_str = IDL_IDENT(state->tree).str; + + /* XXX: big kludge; s.b. way to match to typedefs */ + if (strcmp(ident_str, "PRInt8") == 0 || + strcmp(ident_str, "PRUint8") == 0) { + fputs("byte", FILENAME(state)); + } + else if (strcmp(ident_str, "PRInt16") == 0 || + strcmp(ident_str, "PRUint16") == 0) { + fputs("short", FILENAME(state)); + } + else if (strcmp(ident_str, "PRInt32") == 0 || + strcmp(ident_str, "PRUint32") == 0) { + fputs("int", FILENAME(state)); + } + else if (strcmp(ident_str, "PRInt64") == 0 || + strcmp(ident_str, "PRUint64") == 0) { + fputs("long", FILENAME(state)); + } + else if (strcmp(ident_str, "PRBool") == 0) { + fputs("boolean", FILENAME(state)); + } + else if (strcmp(ident_str, "nsrefcnt") == 0) { + fputs("int", FILENAME(state)); + } + else { + IDL_tree real_type = + g_hash_table_lookup(TYPEDEFS(state), ident_str); + + if (real_type) { + IDL_tree orig_tree = state->tree; + + state->tree = real_type; + xpcom_to_java_type(state); + + state->tree = orig_tree; + } + else { + fputs(ident_str, FILENAME(state)); + } + } + } + + break; + + case IDLN_TYPE_ENUM: + case IDLN_TYPE_OBJECT: + default: + g_error(" Unknown type: %d\n", + IDL_TYPE_FLOAT(state->tree).f_type); + break; + } + + return TRUE; + +} + +static gboolean +xpcom_to_java_param(TreeState *state) +{ + IDL_tree param = state->tree; + state->tree = IDL_PARAM_DCL(param).param_type_spec; + + /* + * Put in type of parameter + */ + + if (!xpcom_to_java_type(state)) { + return FALSE; + } + + /* + * If the parameter is out or inout, make it a Java array of the + * appropriate type + */ + + if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) { + fputs("[]", FILENAME(state)); + } + + /* + * If the parameter is an array make it a Java array + */ + if (IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array")) + fputs("[]", FILENAME(state)); + + /* + * Put in name of parameter + */ + + fputc(' ', FILENAME(state)); + + fputs(IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str, FILENAME(state)); + return TRUE; +} + + +static gboolean +type_declaration(TreeState *state) +{ + /* + * Unlike C, Java has no type declaration directive. + * Instead, we record the mapping, and look up the actual type + * when needed. + */ + IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec; + IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls; + + /* XXX: check for illegal types */ + + g_hash_table_insert(TYPEDEFS(state), + IDL_IDENT(IDL_LIST(dcls).data).str, + type); + + return TRUE; +} + +static gboolean +method_declaration(TreeState *state) +{ + /* IDL_tree method_tree = state->tree; */ + const char* array = NULL; + GSList *doc_comments = IDL_IDENT(IDL_OP_DCL(state->tree).ident).comments; + struct _IDL_OP_DCL *method = &IDL_OP_DCL(state->tree); + gboolean method_notxpcom = + (IDL_tree_property_get(method->ident, "notxpcom") != NULL); + gboolean method_noscript = + (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; + + if (doc_comments != NULL) { + fputs(" ", FILENAME(state)); + printlist(FILENAME(state), doc_comments); + } + + if (method_notxpcom || method_noscript) + return TRUE; + + if (!verify_method_declaration(state->tree)) + return FALSE; + + fputc('\n', FILENAME(state)); + write_comment(state); + + /* + * Write beginning of method declaration + */ + fputs(" ", FILENAME(state)); + if (!method_noscript) { + /* Nonscriptable methods become package-protected */ + fputs("public ", FILENAME(state)); + } + + /* + * Write return type + * Unlike C++ headers, Java interfaces return the declared + * return value; an exception indicates XPCOM method failure. + */ + if (method_notxpcom || method->op_type_spec) { + state->tree = method->op_type_spec; + if (!xpcom_to_java_type(state)) { + return FALSE; + } + } else { + + /* Check for retval attribute */ + for (iterator = method->parameter_dcls; iterator != NULL; + iterator = IDL_LIST(iterator).next) { + + IDL_tree original_tree = state->tree; + + state->tree = IDL_LIST(iterator).data; + + if (IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, + "retval")) { + retval_param = iterator; + + array = + IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, + "array"); + state->tree = IDL_PARAM_DCL(state->tree).param_type_spec; + /* + * Put in type of parameter + */ + if (!xpcom_to_java_type(state)) { + return FALSE; + } + if (array) + fputs("[]", FILENAME(state)); + + } + + state->tree = original_tree; + } + + if (retval_param == NULL) { + fputs("void", FILENAME(state)); + } + } + + /* + * Write method name + */ + fprintf(FILENAME(state), " %c%s(", tolower(method_name[0]), method_name + 1); + + /* + * Write parameters + */ + for (iterator = method->parameter_dcls; iterator != NULL; + iterator = IDL_LIST(iterator).next) { + + /* Skip "retval" */ + if (iterator == retval_param) { + continue; + } + + + if (iterator != method->parameter_dcls) { + fputs(", ", FILENAME(state)); + } + + state->tree = IDL_LIST(iterator).data; + if (!xpcom_to_java_param(state)) { + return FALSE; + } + } + + fputs(")", FILENAME(state)); + + if (method->raises_expr) { + IDL_tree iter = method->raises_expr; + IDL_tree dataNode = IDL_LIST(iter).data; + + fputs(" throws ", FILENAME(state)); + fputs(IDL_IDENT(dataNode).str, FILENAME(state)); + iter = IDL_LIST(iter).next; + + while (iter) { + dataNode = IDL_LIST(iter).data; + fprintf(FILENAME(state), ", %s", IDL_IDENT(dataNode).str); + iter = IDL_LIST(iter).next; + } + } + + fputs(";\n", FILENAME(state)); + + return TRUE; + +} + + +static gboolean +constant_declaration(TreeState *state) +{ + /* + * The C++ header XPIDL module only allows for shorts and longs (ints) + * to be constants, so we will follow the same convention + */ + + struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree); + const char *name = IDL_IDENT(declaration->ident).str; + + gboolean success; + gboolean isshort = FALSE; + GSList *doc_comments = IDL_IDENT(declaration->ident).comments; + + /* + * 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) { + + XPIDL_WARNING((state->tree, IDL_WARNING1, + "A constant \"%s\" was declared outside an interface." + " It was ignored.", name)); + + return TRUE; + } + + /* + * Make sure this is a numeric short or long constant. + */ + + success = (IDLN_TYPE_INTEGER == IDL_NODE_TYPE(declaration->const_type)); + + if (success) { + /* + * We aren't successful yet, we know it's an integer, but what *kind* + * of integer? + */ + + switch(IDL_TYPE_INTEGER(declaration->const_type).f_type) { + + case IDL_INTEGER_TYPE_SHORT: + /* + * We're OK + */ + isshort = TRUE; + break; + + case IDL_INTEGER_TYPE_LONG: + /* + * We're OK + */ + break; + + default: + /* + * Whoops, it's some other kind of number + */ + + success = FALSE; + } + } + + if (doc_comments != NULL) { + fputs(" ", FILENAME(state)); + printlist(FILENAME(state), doc_comments); + } + + if (success) { + fputc('\n', FILENAME(state)); + write_comment(state); + + fprintf(FILENAME(state), " public static final %s %s = %d;\n", + (isshort ? "short" : "int"), + name, (int) IDL_INTEGER(declaration->const_exp).value); + } else { + XPIDL_WARNING((state->tree, IDL_WARNING1, + "A constant \"%s\" was not of type short or long." + " It was ignored.", name)); + } + + return TRUE; + +} + +#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data)) +#define ATTR_PROPS(tree) (IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data) +#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL((tree)).param_type_spec) + + +static gboolean +attribute_declaration(TreeState *state) +{ + gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly; + char *attribute_name = ATTR_IDENT(state->tree).str; + + gboolean method_noscript = + (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") != NULL); + GSList *doc_comments = + IDL_IDENT(IDL_LIST(IDL_ATTR_DCL + (state->tree).simple_declarations).data).comments; + + if (doc_comments != NULL) { + fputs(" ", FILENAME(state)); + printlist(FILENAME(state), doc_comments); + } + +#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; +#endif + + /* Comment */ + fputc('\n', FILENAME(state)); + write_comment(state); + + state->tree = ATTR_TYPE_DECL(state->tree); + + /* + * Write access permission ("public" unless nonscriptable) + */ + fputs(" ", FILENAME(state)); + if (!method_noscript) { + fputs("public ", FILENAME(state)); + } + + /* + * Write the proper Java return value for the get operation + */ + if (!xpcom_to_java_type(state)) { + return FALSE; + } + + /* + * Write the name of the accessor ("get") method. + */ + fprintf(FILENAME(state), " get%c%s();\n", + toupper(attribute_name[0]), attribute_name + 1); + + + if (!read_only) { + /* Nonscriptable methods become package-protected */ + fputs(" ", FILENAME(state)); + if (!method_noscript) { + fputs("public ", FILENAME(state)); + } + + /* + * Write attribute access method name and return type + */ + fprintf(FILENAME(state), "void set%c%s(", + toupper(attribute_name[0]), + attribute_name+1); + + /* + * Write the proper Java type for the set operation + */ + if (!xpcom_to_java_type(state)) { + return FALSE; + } + + /* + * Write the name of the formal parameter. + */ + fputs(" value);\n", FILENAME(state)); + } + + return TRUE; +} + + +static gboolean +enum_declaration(TreeState *state) +{ + XPIDL_WARNING((state->tree, IDL_WARNING1, + "enums not supported, enum \'%s\' ignored", + IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str)); + return TRUE; +} + +static gboolean +module_declaration(TreeState *state) +{ + // do not use modules yet +#if 0 + IDL_tree scope = + IDL_tree_get_scope(state->tree); + + char *module_name = IDL_IDENT(IDL_MODULE(state->tree).ident).str; + printf("\n\n I've go a module declared!!! \n name: %s \n\n", + module_name); + + fprintf(FILENAME(state), "package %s;\n", module_name); + state->tree = IDL_MODULE(state->tree).definition_list; + + type = IDL_NODE_TYPE(state->tree); + printf("\n type: %d\n\n", type); + + return process_list(state); +#endif + return TRUE; +} + +backend * +xpidl_java_dispatch(void) +{ + static backend result; + static nodeHandler table[IDLN_LAST]; + static gboolean initialized = FALSE; + + result.emit_prolog = java_prolog; + result.emit_epilog = java_epilog; + + if (!initialized) { + table[IDLN_INTERFACE] = interface_declaration; + table[IDLN_LIST] = process_list; + + table[IDLN_OP_DCL] = method_declaration; + table[IDLN_ATTR_DCL] = attribute_declaration; + table[IDLN_CONST_DCL] = constant_declaration; + + table[IDLN_TYPE_DCL] = type_declaration; + /* table[IDLN_FORWARD_DCL] = forward_declaration;*/ + + table[IDLN_TYPE_ENUM] = enum_declaration; + /* table[IDLN_MODULE] = module_declaration;*/ + + initialized = TRUE; + } + + result.dispatch_table = table; + return &result; +} + +void write_comment(TreeState *state) +{ + fprintf(FILENAME(state), " /* "); + IDL_tree_to_IDL(state->tree, state->ns, FILENAME(state), + IDLF_OUTPUT_NO_NEWLINES | + IDLF_OUTPUT_NO_QUALIFY_IDENTS | + IDLF_OUTPUT_PROPERTIES); + fputs(" */\n", FILENAME(state)); +}