xpidl_java.c revision 18c69e356f013090fd1890c717eb2e723393edc0
/* -*- 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 <ctype.h>
#include <glib.h>
struct java_priv_data {
GHashTable *typedefTable;
};
#define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable)
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)
{
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
const char *basename;
const char *ext;
#endif
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;
}
/*
* First pass
*/
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
basename = xpidl_basename(state->real_outname ? state->real_outname : state->basename);
ext = strrchr(basename, '.');
if (!ext)
ext = strchr(basename, '\0');
fprintf(state->file,
"/**\n"
" * NOTE: THIS IS A GENERATED FILE. PLEASE CONSULT THE ORIGINAL IDL FILE\n"
" * FOR THE FULL DOCUMENTATION AND LICENSE.\n"
" *\n"
" * @see <a href=\"http://lxr.mozilla.org/mozilla/search?string=interface+%.*s\">\n"
" **/\n"
"\n"
"package org.mozilla.interfaces;\n\n"
"import java.math.BigInteger;\n\n"
"\n"
, ext - basename >= 19 ? 19 : (int)(ext - basename), basename);
#else
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);
#endif
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;
#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
/*
* Last pass
*/
fprintf(state->file, "\n/*\n * end\n */\n");
#endif
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(state->file, "import %s.%s;\n", pkgName, className);
#endif
return TRUE;
}
static gboolean
interface_declaration(TreeState *state)
{
IDL_tree interface = state->tree;
IDL_tree iterator = NULL;
char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str;
const char *iid = NULL;
if (!verify_interface_declaration(interface))
return FALSE;
#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
/*
* Write out JavaDoc comment
*/
fprintf(state->file, "\n/**\n * Interface %s\n", interface_name);
#endif
#ifndef LIBIDL_MAJOR_VERSION
iid = IDL_tree_property_get(interface, "uuid");
#else
iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid");
#endif
#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
if (iid != NULL) {
fprintf(state->file, " *\n * IID: 0x%s\n */\n\n", iid);
} else {
fputs(" */\n\n", state->file);
}
#endif
/*
* Write "public interface <foo>"
*/
fprintf(state->file, "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 ", 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);
if (iid) {
/*
* Write interface constants for IID
*/
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
fputs(" public static final String ", state->file);
#else
fputs(" public static final String ", state->file);
#endif
/* XXX s.b just "IID" ? */
if (!write_classname_iid_define(state->file, interface_name)) {
return FALSE;
}
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
fputs(" =\n \"{", state->file);
while (*iid) {
fputc(tolower(*iid++), state->file);
}
fputs("}\";\n", state->file);
#else
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);
#endif
}
/*
* 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", state->file);
return TRUE;
}
static gboolean
process_list(TreeState *state)
{
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
/* To make the diffing simple, group the constants, methods and attributes. */
IDL_tree list = state->tree;
IDL_tree iter;
for (iter = list; iter; iter = IDL_LIST(iter).next) {
if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_CONST_DCL) {
state->tree = IDL_LIST(iter).data;
if (!xpidl_process_node(state))
return FALSE;
}
}
for (iter = list; iter; iter = IDL_LIST(iter).next) {
if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_ATTR_DCL) {
state->tree = IDL_LIST(iter).data;
if (!xpidl_process_node(state))
return FALSE;
}
}
for (iter = list; iter; iter = IDL_LIST(iter).next) {
if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_OP_DCL) {
state->tree = IDL_LIST(iter).data;
if (!xpidl_process_node(state))
return FALSE;
}
}
for (iter = list; iter; iter = IDL_LIST(iter).next) {
if ( IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_CONST_DCL
&& IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_OP_DCL
&& IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_ATTR_DCL ) {
state->tree = IDL_LIST(iter).data;
if (!xpidl_process_node(state))
return FALSE;
}
}
#else
IDL_tree iter;
for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
state->tree = IDL_LIST(iter).data;
if (!xpidl_process_node(state))
return FALSE;
}
#endif
return TRUE;
}
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
static gboolean
interface_declaration_wrapper(TreeState *state)
{
IDL_tree interface = state->tree;
char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str;
FILE *org_file = state->file;
char *org_name = state->real_outname;
void *org_priv = state->priv;
gboolean rc;
/*
* Skip non-scriptable interfaces.
*/
if ( !IDL_tree_property_get(IDL_INTERFACE(interface).ident, "scriptable")
&& strcmp(interface_name, "nsIAppShell") )
return TRUE;
/*
* GROSS HACK: If the interface isn't the same as the file name,
* temporarily switch output file.
*/
if (state->real_outname) {
const char *basename = xpidl_basename(state->real_outname);
const char *ext = strrchr(basename, '.');
if ( ext
&& !strcmp(ext, ".java")
&& ( strncmp(interface_name, basename, ext - basename)
|| interface_name[ext - basename] != '.') ) {
size_t needed = strlen(state->real_outname) + strlen(interface_name) + strlen(".java") + 4;
char *tmp = malloc(needed);
if (basename != state->real_outname)
sprintf(tmp,"%.*s/%s.java", (int)(basename - state->real_outname - 1), state->real_outname, interface_name);
else
sprintf(tmp,"%s.java", interface_name);
state->file = fopen(tmp, "w");
if (!state->file) {
perror("error opening output file");
state->file = org_file;
free(tmp);
return FALSE;
}
state->real_outname = tmp;
java_prolog(state);
}
}
rc = interface_declaration(state);
if (state->file != org_file) {
java_epilog(state);
fclose(state->file);
free(state->real_outname);
state->file = org_file;
state->real_outname = org_name;
state->priv = org_priv;
}
return rc;
}
#endif /* VBOX_XPIDL_EMULATE_GENJIFACES */
static gboolean
xpcom_to_java_type (TreeState *state)
{
if (!state->tree) {
fputs("Object", state->file);
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:
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
if (IDL_TYPE_INTEGER(state->tree).f_signed)
fputs("short", state->file);
else
fputs("int", state->file);
#else
fputs("short", state->file);
#endif
break;
case IDL_INTEGER_TYPE_LONG:
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
if (IDL_TYPE_INTEGER(state->tree).f_signed)
fputs("int", state->file);
else
fputs("long", state->file);
#else
fputs("int", state->file);
#endif
break;
case IDL_INTEGER_TYPE_LONGLONG:
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
if (IDL_TYPE_INTEGER(state->tree).f_signed)
fputs("long", state->file);
else
fputs("double", state->file);
#else
fputs("long", state->file);
#endif
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", state->file);
break;
case IDLN_TYPE_WIDE_STRING:
case IDLN_TYPE_STRING:
fputs("String", state->file);
break;
case IDLN_TYPE_BOOLEAN:
fputs("boolean", state->file);
break;
case IDLN_TYPE_OCTET:
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
fputs("short", state->file);
#else
fputs("byte", state->file);
#endif
break;
case IDLN_TYPE_FLOAT:
switch(IDL_TYPE_FLOAT(state->tree).f_type) {
case IDL_FLOAT_TYPE_FLOAT:
fputs("float", state->file);
break;
case IDL_FLOAT_TYPE_DOUBLE:
fputs("double", state->file);
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;
if (strcmp(user_type, "void") == 0) {
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
fputs("nsISupports", state->file);
#else
fputs("Object", state->file);
#endif
}
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 */
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
fputs("String", state->file);
#else
fputs("nsID", state->file);
#endif
}
else {
/* XXX: special class for opaque types */
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
fputs("String", state->file);
#else
fputs("OpaqueValue", state->file);
#endif
}
} else {
const char *ident_str = IDL_IDENT(state->tree).str;
/* XXX: big kludge; s.b. way to match to typedefs */
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
if (strcmp(ident_str, "PRInt8") == 0) {
fputs("byte", state->file);
}
else if (strcmp(ident_str, "PRInt16") == 0 ||
strcmp(ident_str, "PRUint8") == 0) {
fputs("short", state->file);
}
else if (strcmp(ident_str, "PRInt32") == 0 ||
strcmp(ident_str, "PRUint16") == 0) {
fputs("int", state->file);
}
else if (strcmp(ident_str, "PRInt64") == 0 ||
strcmp(ident_str, "PRUint32") == 0 ||
strcmp(ident_str, "PRThreadPriority") == 0 ||
strcmp(ident_str, "PRThreadScope") == 0 ||
strcmp(ident_str, "PRThreadState") == 0) {
fputs("long", state->file);
}
else if (strcmp(ident_str, "PRUint64") == 0) {
fputs("double", state->file);
}
#else
if (strcmp(ident_str, "PRInt8") == 0 ||
strcmp(ident_str, "PRUint8") == 0) {
fputs("byte", state->file);
}
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);
}
#endif
else if (strcmp(ident_str, "PRBool") == 0) {
fputs("boolean", state->file);
}
else if (strcmp(ident_str, "nsrefcnt") == 0) {
fputs("int", state->file);
}
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
/* XXX: Use find_underlying_type instead? */
else if ( strcmp(ident_str, "nsresult") == 0
|| strcmp(ident_str, "size_t") == 0) {
fputs("long", state->file);
}
else if ( strcmp(ident_str, "PRTime") == 0) {
fputs("double", state->file);
}
/* In Javaconnect, we handle weak references internally; no need for the
|nsIWeakReference| interface. So just return |nsISupports|. */
else if (strcmp(ident_str, "nsIWeakReference") == 0) {
fputs("nsISupports", state->file);
}
#endif
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, state->file);
}
}
}
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
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
xpcom_to_java_param(TreeState *state, unsigned nparam)
#else
xpcom_to_java_param(TreeState *state)
#endif
{
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
*/
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
/* XXX: Causes nsILineInputStream::readLine(String[] arg1) where genjifaces drops the []. */
#endif
if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) {
fputs("[]", state->file);
}
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
/*XXX: nsIConsoleService::getMessageArray ends up with [][] arg1... */
/*else*/ if (IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array")) {
fputs("[]", state->file);
}
#endif
/*
* Put in name of parameter
*/
fputc(' ', state->file);
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
fprintf(state->file, "arg%u", nparam+1);
#else
fputs(IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str, state->file);
#endif
return TRUE;
}
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
static gboolean is_java_keyword(char ch0, const char *name)
{
static const char * const kJavaKeywords[] = {
"abstract", "default", "if" , "private" , "this" ,
"boolean" , "do" , "implements", "protected" , "throw" ,
"break" , "double" , "import", "public" , "throws" ,
"byte" , "else" , "instanceof", "return" , "transient",
"case" , "extends", "int" , "short" , "try" ,
"catch" , "final" , "interface" , "static" , "void" ,
"char" , "finally", "long" , "strictfp" , "volatile" ,
"class" , "float" , "native" , "super" , "while" ,
"const" , "for" , "new" , "switch" ,
"continue", "goto" , "package" , "synchronized",
"assert" , /* added in Java 1.4 */
"enum" , /* added in Java 5.0 */
"clone" , /* clone is a member function of java.lang.Object */
"finalize" /* finalize is a member function of java.lang.Object */
};
unsigned i;
for (i = 0; i < sizeof(kJavaKeywords) / sizeof(kJavaKeywords[0]); i++) {
if (kJavaKeywords[i][0] == ch0 && !strcmp(&kJavaKeywords[i][1], &name[1])) {
return TRUE;
}
}
return FALSE;
}
#endif
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; */
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;
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
unsigned nparam = 0;
#endif
if (!verify_method_declaration(state->tree))
return FALSE;
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
/*
* Skip most (todo) non-scriptable and not-xpcom methods.
*/
if (method_noscript || method_notxpcom) {
return TRUE;
}
#endif
fputc('\n', state->file);
#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
xpidl_write_comment(state, 4);
#endif
/*
* Write beginning of method declaration
*/
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
fputs(" ", state->file);
#else
fputs(" ", state->file);
#endif
if (!method_noscript) {
/* Nonscriptable methods become package-protected */
fputs("public ", state->file);
}
/*
* 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;
state->tree = IDL_PARAM_DCL(state->tree).param_type_spec;
/*
* Put in type of parameter
*/
if (!xpcom_to_java_type(state)) {
return FALSE;
}
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
if (IDL_tree_property_get(IDL_PARAM_DCL(IDL_LIST(iterator).data).simple_declarator, "array")) {
fputs("[]", state->file);
}
#endif
}
state->tree = original_tree;
}
if (retval_param == NULL) {
fputs("void", state->file);
}
}
/*
* Write method name
*/
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
if (is_java_keyword(tolower(method_name[0]), method_name)) {
fprintf(state->file, " %c%s_(", tolower(method_name[0]), method_name + 1);
} else {
fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1);
}
#else
fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1);
#endif
/*
* 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(", ", state->file);
}
state->tree = IDL_LIST(iterator).data;
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
if (!xpcom_to_java_param(state, nparam++)) {
#else
if (!xpcom_to_java_param(state)) {
#endif
return FALSE;
}
}
fputs(")", state->file);
if (method->raises_expr) {
IDL_tree iter = method->raises_expr;
IDL_tree dataNode = IDL_LIST(iter).data;
fputs(" throws ", state->file);
fputs(IDL_IDENT(dataNode).str, state->file);
iter = IDL_LIST(iter).next;
while (iter) {
dataNode = IDL_LIST(iter).data;
fprintf(state->file, ", %s", IDL_IDENT(dataNode).str);
iter = IDL_LIST(iter).next;
}
}
fputs(";\n", state->file);
return TRUE;
}
static gboolean
constant_declaration(TreeState *state)
{
struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree);
const char *name = IDL_IDENT(declaration->ident).str;
IDL_tree real_type;
if (!verify_const_declaration(state->tree))
return FALSE;
/* Could be a typedef; try to map it to the real type. */
real_type = find_underlying_type(declaration->const_type);
real_type = real_type ? real_type : declaration->const_type;
fputc('\n', state->file);
#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
xpidl_write_comment(state, 4);
#endif
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
# ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
fputs(" public static final ", state->file);
# else
fputs(" public static final ", state->file);
# endif
if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG) {
if (IDL_TYPE_INTEGER(real_type).f_signed)
fprintf(state->file, "int %s = %" IDL_LL "d;\n", name, IDL_INTEGER(declaration->const_exp).value);
else
fprintf(state->file, "long %s = %" IDL_LL "uL;\n", name, IDL_INTEGER(declaration->const_exp).value);
} else {
if (IDL_TYPE_INTEGER(real_type).f_signed)
fprintf(state->file, "short %s = %" IDL_LL "d;\n", name, IDL_INTEGER(declaration->const_exp).value);
else
fprintf(state->file, "int %s = %" IDL_LL "u;\n", name, IDL_INTEGER(declaration->const_exp).value);
}
#else /* !VBOX_XPIDL_EMULATE_GENJIFACES */
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);
#endif /* !VBOX_XPIDL_EMULATE_GENJIFACES */
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);
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
/*
* Skip most non-scriptable attributes.
*/
if (method_noscript) {
return TRUE;
}
#endif
#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', state->file);
#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
xpidl_write_comment(state, 4);
#endif
state->tree = ATTR_TYPE_DECL(state->tree);
/*
* Write access permission ("public" unless nonscriptable)
*/
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
fputs(" ", state->file);
#else
fputs(" ", state->file);
#endif
if (!method_noscript) {
fputs("public ", state->file);
}
/*
* 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(state->file, " get%c%s();\n",
toupper(attribute_name[0]), attribute_name + 1);
if (!read_only) {
/* Nonscriptable methods become package-protected */
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
fputs("\n ", state->file);
#else
fputs(" ", state->file);
#endif
if (!method_noscript) {
fputs("public ", state->file);
}
/*
* Write attribute access method name and return type
*/
fprintf(state->file, "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.
*/
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
fputs(" arg1);\n", state->file);
#else
fputs(" value);\n", state->file);
#endif
}
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;
}
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) {
#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
table[IDLN_INTERFACE] = interface_declaration_wrapper;
#else
table[IDLN_INTERFACE] = interface_declaration;
#endif
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;
initialized = TRUE;
}
result.dispatch_table = table;
return &result;
}