Back to index

lightning-sunbird  0.9+nobinonly
xpidl_javastub.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  * ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Sun Microsystems, Inc.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Michael Allen (michael.allen@sun.com)
00024  *   Frank Mitchell (frank.mitchell@sun.com)
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /*
00041  * Generate Java interfaces from XPIDL.
00042  */
00043 
00044 #define COUNT_METHODS
00045 
00046 #include "xpidl.h"
00047 #include <ctype.h>
00048 #include <glib.h>
00049 
00050 #ifdef XP_WIN
00051 #include "windef.h"
00052 #define PATH_MAX  MAX_PATH
00053 #endif
00054 
00055 static char* subscriptIdentifier(TreeState *state, char *str);
00056 
00057 /*
00058 struct java_priv_data {
00059     GHashTable *typedefTable;
00060        int numMethods;
00061        gboolean bHasBaseClass;
00062        gboolean bCountingMethods;
00063 };
00064 */
00065 
00066 static char* javaKeywords[] = {
00067     "abstract", "default", "if"        , "private"     , "this"     ,
00068     "boolean" , "do"     , "implements", "protected"   , "throw"    ,
00069     "break"   , "double" , "import",     "public"      , "throws"   ,
00070     "byte"    , "else"   , "instanceof", "return"      , "transient",
00071     "case"    , "extends", "int"       , "short"       , "try"      ,
00072     "catch"   , "final"  , "interface" , "static"      , "void"     ,
00073     "char"    , "finally", "long"      , "strictfp"    , "volatile" ,
00074     "class"   , "float"  , "native"    , "super"       , "while"    ,
00075     "const"   , "for"    , "new"       , "switch"      , "assert"   ,
00076     "continue", "goto"   , "package"   , "synchronized",
00077     "clone"   ,  /* clone is a member function of java.lang.Object */
00078     "finalize"   /* finalize is a member function of java.lang.Object */};
00079 
00080 #define TYPEDEFS(state)     (((struct java_priv_data *)state->priv)->typedefTable)
00081 #define PRIVDATA(state)     (((struct java_priv_data *)state->priv))
00082 #define KEYWORDS(state)     (((struct java_priv_data *)state->priv)->keywords)
00083 
00084 static gboolean
00085 write_classname_iid_define(FILE *file, const char *className)
00086 {
00087     const char *iidName;
00088     if (className[0] == 'n' && className[1] == 's') {
00089         /* backcompat naming styles */
00090         fputs("NS_", file);
00091         iidName = className + 2;
00092     } else {
00093         iidName = className;
00094     }
00095 
00096     while (*iidName) {
00097         fputc(toupper(*iidName++), file);
00098     }
00099 
00100     fputs("_IID", file);
00101     return TRUE;
00102 }
00103 
00104 static gboolean
00105 java_prolog(TreeState *state)
00106 {
00107     int len, i;
00108     state->priv = calloc(1, sizeof(struct java_priv_data));
00109     if (!state->priv)
00110         return FALSE;
00111 
00112 #ifdef COUNT_METHODS
00113        PRIVDATA(state)->numMethods = 0;
00114        PRIVDATA(state)->bHasBaseClass = FALSE; 
00115        PRIVDATA(state)->bCountingMethods = FALSE;
00116 #endif
00117 
00118     TYPEDEFS(state) = 0;
00119     TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal);
00120     if (!TYPEDEFS(state)) {
00121         /* XXX report error */
00122         free(state->priv);
00123         return FALSE;
00124     }
00125 
00126     KEYWORDS(state) = 0;
00127     KEYWORDS(state) = g_hash_table_new(g_str_hash, g_str_equal);
00128     if (!KEYWORDS(state)) {
00129         g_hash_table_destroy(TYPEDEFS(state));
00130         free(state->priv);
00131         return FALSE;
00132     }
00133     len = sizeof(javaKeywords)/sizeof(*javaKeywords);
00134     for (i = 0; i < len; i++) {
00135         g_hash_table_insert(KEYWORDS(state),
00136                             javaKeywords[i],
00137                             javaKeywords[i]);
00138     }
00139 
00140     return TRUE;
00141 }
00142 
00143 static gboolean 
00144 java_epilog(TreeState *state)
00145 {
00146     /* points to other elements of the tree, so just destroy the table */
00147     g_hash_table_destroy(TYPEDEFS(state));
00148     g_hash_table_destroy(KEYWORDS(state));
00149 
00150     free(state->priv);
00151     state->priv = NULL;
00152     
00153     return TRUE;
00154 }
00155 
00156 static gboolean
00157 forward_declaration(TreeState *state) 
00158 {
00159     return TRUE;
00160 }
00161 
00162 
00163 static gboolean
00164 interface_declaration(TreeState *state) 
00165 {
00166     char outname[PATH_MAX];
00167     char* p;
00168     IDL_tree interface = state->tree;
00169     IDL_tree iterator = NULL;
00170     char *interface_name = 
00171         subscriptIdentifier(state, IDL_IDENT(IDL_INTERFACE(interface).ident).str);
00172 #ifdef COUNT_METHODS
00173        char *baseclass_name = NULL;
00174 #endif
00175 
00176     if (!verify_interface_declaration(interface))
00177         return FALSE;
00178 
00179     /*
00180      * Each interface decl is a single file
00181      */
00182     p = strrchr(state->filename, '/');
00183     if (p) {
00184       strncpy(outname, state->filename, p + 1 - state->filename);
00185       outname[p + 1 - state->filename] = '\0';
00186     }
00187     strcat(outname, interface_name);
00188     strcat(outname, "_Stub.java");
00189 
00190     state->file =  fopen(outname, "w");
00191     if (!state->file) {
00192         perror("error opening output file");
00193         return FALSE;
00194     }
00195 
00196     fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n",
00197           state->file);
00198     
00199     fprintf(state->file, 
00200             " *\n * This file was automatically generated from %s.idl.\n", 
00201             state->basename);
00202     
00203     fputs(" */\n\n", state->file);
00204 
00205     if (state->package) {
00206         fprintf(state->file, "\npackage %s.stubs;\n\n", state->package);
00207         fprintf(state->file, "import %s.*;\n", state->package);
00208     }
00209 
00210     if (!state->package || strcmp(state->package, "org.mozilla.xpcom") != 0)
00211         fputs("import org.mozilla.xpcom.*;\n", state->file);
00212 
00213     fputs("\n", state->file);
00214 
00215     /*
00216      * Write "public class <foo>"
00217      */
00218 
00219      fprintf(state->file, "public class %s_Stub", interface_name);
00220 
00221     /*
00222      * Check for inheritence, and iterator over the inherited names,
00223      * if any.
00224      */
00225 
00226     if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) {
00227         fputs(" extends ", state->file);
00228 
00229         do {
00230 #ifdef COUNT_METHODS
00231             if (baseclass_name == NULL) {
00232                 baseclass_name = IDL_IDENT(IDL_LIST(iterator).data).str;
00233                 PRIVDATA(state)->bHasBaseClass = TRUE;
00234             }
00235 #endif
00236 
00237             fprintf(state->file, "%s_Stub", 
00238                     IDL_IDENT(IDL_LIST(iterator).data).str);
00239            
00240             if (IDL_LIST(iterator).next) {
00241                 fputs(", ", state->file);
00242             }
00243         } while ((iterator = IDL_LIST(iterator).next));
00244     } else {
00245         fputs(" extends Object", state->file);
00246     }
00247 
00248     fprintf(state->file, " implements %s\n{\n", interface_name);
00249 
00250 #ifdef COUNT_METHODS
00251        /*
00252      * Count number of methods
00253      */
00254     
00255     state->tree = IDL_INTERFACE(interface).body;
00256 
00257        PRIVDATA(state)->bCountingMethods = TRUE;
00258        PRIVDATA(state)->numMethods = 0;
00259 
00260     if (state->tree && !xpidl_process_node(state)) {
00261         return FALSE;
00262     }  
00263 
00264     if (PRIVDATA(state)->numMethods) {
00265         fputs("\n    static final int LAST_METHOD_ID = ", state->file);
00266         if (!PRIVDATA(state)->bHasBaseClass) 
00267             fprintf(state->file, "%d;\n\n",PRIVDATA(state)->numMethods - 1);
00268         else
00269             fprintf(state->file, "%s_Stub.LAST_METHOD_ID + %d;\n\n", baseclass_name,
00270                     PRIVDATA(state)->numMethods);
00271     }
00272 
00273        state->tree = interface;
00274 #endif
00275 
00276     /*
00277      * Check for inheritence.
00278      */
00279 #if !defined(COUNT_METHODS)
00280        PRIVDATA(state)->bHasBaseClass = FALSE; 
00281     if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) {
00282         PRIVDATA(state)->bHasBaseClass = TRUE;
00283     }
00284 #endif
00285 
00286     /*
00287      * Advance the state of the tree, go on to process more
00288      */
00289     
00290     state->tree = IDL_INTERFACE(interface).body;
00291 
00292        PRIVDATA(state)->bCountingMethods = FALSE;
00293        PRIVDATA(state)->numMethods = 0;
00294 
00295     if (state->tree && !xpidl_process_node(state)) {
00296         return FALSE;
00297     }
00298 
00299     /*
00300      * Create the finalize() method
00301      */
00302     fputs("    protected void finalize() throws Throwable {\n", state->file);
00303     fputs("        XPCOMPrivate.FinalizeStub(this);\n    }", state->file);
00304 /*    fputs("        try {\n", state->file);
00305     fputs("            XPCOM.FinalizeStub(this);\n", state->file);
00306     fputs("        } finally {\n            super.finalize();\n", state->file);
00307     fputs("        }\n    }", state->file);*/
00308 
00309     fputs("\n}\n", state->file);
00310 
00311     fprintf(state->file, "\n/*\n * end\n */\n");
00312     fclose(state->file);
00313 
00314     return TRUE;
00315 }
00316 
00317 static gboolean
00318 process_list(TreeState *state)
00319 {
00320     IDL_tree iter;
00321     for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
00322         state->tree = IDL_LIST(iter).data;
00323         if (!xpidl_process_node(state))
00324             return FALSE;
00325     }
00326     return TRUE;
00327 }
00328 
00329 typedef enum JavaNativeType {
00330     JAVA_NATIVE_ERROR,      /* error condition */
00331     JAVA_BYTE,
00332     JAVA_SHORT,
00333     JAVA_INT,
00334     JAVA_LONG,
00335     JAVA_FLOAT,
00336     JAVA_DOUBLE,
00337     JAVA_CHAR,
00338     JAVA_BOOL,
00339     JAVA_BYTEARRAY,
00340     JAVA_STRING,
00341     JAVA_NSISUPPORTS,
00342     JAVA_OBJECT
00343 } JavaNativeType;
00344 
00345 static JavaNativeType
00346 xpcom_to_java_type2(TreeState *state, IDL_tree type)
00347 {
00348     IDL_tree real_type;
00349     IDL_tree up;
00350 
00351     if (!type) {
00352         return JAVA_OBJECT;
00353     }
00354 
00355     /* Could be a typedef; try to map it to the real type */
00356     real_type = find_underlying_type(type);
00357     type = real_type ? real_type : type;
00358 
00359     switch(IDL_NODE_TYPE(type)) {
00360       case IDLN_TYPE_INTEGER: {
00361         switch(IDL_TYPE_INTEGER(type).f_type) {
00362           case IDL_INTEGER_TYPE_SHORT:
00363               return JAVA_SHORT;
00364               break;
00365           case IDL_INTEGER_TYPE_LONG:
00366               return JAVA_INT;
00367               break;
00368           case IDL_INTEGER_TYPE_LONGLONG:
00369               return JAVA_LONG;
00370               break;
00371           default:
00372               g_error("Unknown integer type: %d\n",
00373                       IDL_TYPE_INTEGER(type).f_type);
00374               return JAVA_NATIVE_ERROR;
00375         }
00376         break;
00377       }
00378 
00379       case IDLN_TYPE_CHAR:
00380       case IDLN_TYPE_WIDE_CHAR:
00381         return JAVA_CHAR;
00382         break;
00383 
00384       case IDLN_TYPE_WIDE_STRING:
00385       case IDLN_TYPE_STRING:
00386         return JAVA_STRING;
00387         break;
00388 
00389       case IDLN_TYPE_BOOLEAN:
00390         return JAVA_BOOL;
00391         break;
00392 
00393       case IDLN_TYPE_OCTET:
00394         return JAVA_BYTE;
00395         break;
00396 
00397       case IDLN_TYPE_FLOAT:
00398         switch(IDL_TYPE_FLOAT(type).f_type) {
00399           case IDL_FLOAT_TYPE_FLOAT:
00400             return JAVA_FLOAT;
00401             break;
00402           case IDL_FLOAT_TYPE_DOUBLE:
00403             return JAVA_DOUBLE;
00404             break;
00405           default:
00406             g_error("Unknown floating point type: %d\n",
00407                     IDL_TYPE_FLOAT(type).f_type);
00408             return JAVA_NATIVE_ERROR;
00409             break;
00410         }
00411         break;
00412 
00413       case IDLN_IDENT:
00414         if (!(up = IDL_NODE_UP(type))) {
00415             IDL_tree_error(state->tree,
00416                            "ERROR: orphan ident %s in param list\n",
00417                            IDL_IDENT(state->tree).str);
00418             return JAVA_NATIVE_ERROR;
00419         }
00420         switch (IDL_NODE_TYPE(up)) {
00421             /* This whole section is abominably ugly */
00422           case IDLN_FORWARD_DCL:
00423           case IDLN_INTERFACE: {
00424             return JAVA_NSISUPPORTS;
00425             break;
00426           }
00427           case IDLN_NATIVE: {
00428               if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL &&
00429                   IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
00430                                           "iid_is"))
00431                   return JAVA_NSISUPPORTS;
00432 
00433               if (IDL_tree_property_get(type, "nsid")) {
00434                   return JAVA_STRING;
00435               } else if (IDL_tree_property_get(type, "domstring")) {
00436                   return JAVA_STRING;
00437               } else if (IDL_tree_property_get(type, "astring")) {
00438                   return JAVA_STRING;
00439               } else if (IDL_tree_property_get(type, "utf8string")) {
00440                   return JAVA_STRING;
00441               } else if (IDL_tree_property_get(type, "cstring")) {
00442                   return JAVA_STRING;
00443               } else {
00444                   const char* user_type = IDL_NATIVE(IDL_NODE_UP(type)).user_type;
00445                   IDL_tree real_type = 
00446                       g_hash_table_lookup(TYPEDEFS(state), user_type);
00447 
00448                   if (real_type) {
00449                       return xpcom_to_java_type2(state, real_type);
00450                   } else {
00451                       if (strcmp(user_type, "PRInt8") == 0 ||
00452                           strcmp(user_type, "PRUint8") == 0) {
00453                           return JAVA_BYTE;
00454                       } else if (strcmp(user_type, "PRInt16") == 0 ||
00455                                  strcmp(user_type, "PRUint16") == 0) {
00456                           return JAVA_SHORT;
00457                       } else if (strcmp(user_type, "PRInt32") == 0 ||
00458                                  strcmp(user_type, "PRUint32") == 0 ||
00459                                  strcmp(user_type, "int") == 0) {
00460                           return JAVA_INT;
00461                       } else if (strcmp(user_type, "PRInt64") == 0 ||
00462                                  strcmp(user_type, "PRUint64") == 0) {
00463                           return JAVA_LONG;
00464                       } else if (strcmp(user_type, "PRBool") == 0) {
00465                           return JAVA_BOOL;
00466                       } else if (strncmp(user_type, "char", 4) == 0 ||
00467                                  strncmp(user_type, "const char", 10) == 0 ||
00468                                  strncmp(user_type, "unsigned char", 13) == 0) {
00469                           if (IDL_tree_property_get(type, "ptr")) {
00470                               return JAVA_BYTEARRAY;
00471                           } else {
00472                               return JAVA_CHAR;
00473                           }
00474                       } else if (strcmp(user_type, "nsIID") == 0) {
00475                           return JAVA_STRING;
00476                       } else if (strcmp(user_type, "nsString") == 0 ||
00477                                  strcmp(user_type, "nsAString") == 0 ||
00478                                  strcmp(user_type, "nsACString") == 0) {
00479                           return JAVA_STRING;
00480                       } else {
00481                           return JAVA_INT;
00482                       }
00483                   }
00484               }
00485               break;
00486             }
00487           default:
00488             if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) {
00489                 /* restart with the underlying type */
00490                 IDL_tree new_type;
00491                 new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec;
00492                 if (new_type) {
00493                     return xpcom_to_java_type2(state, new_type);
00494                 } else {
00495                     /* do what we would do in recursion if !type */
00496                     return JAVA_OBJECT;
00497                 }
00498             }
00499             IDL_tree_error(state->tree,
00500                            "can't handle %s ident in param list\n",
00501                                /* XXX is this safe to use on Win now? */
00502                                IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
00503 /*                           "that type of"*/
00504                            );
00505             return JAVA_NATIVE_ERROR;
00506         }
00507         break;
00508 
00509     default:
00510       IDL_tree_error(state->tree, "can't handle %s in param list\n",
00511                      /* XXX is this safe to use on Win now? */
00512                      IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
00513 /*                  "that type"*/
00514       );
00515       return JAVA_NATIVE_ERROR;
00516     }
00517 
00518     return JAVA_NATIVE_ERROR;
00519 }
00520 
00521 static gboolean 
00522 xpcom_to_java_type(TreeState *state, IDL_tree type) 
00523 {
00524     IDL_tree real_type;
00525     IDL_tree up;
00526 
00527     if (!type) {
00528         fputs("Object", state->file);
00529         return TRUE;
00530     }
00531 
00532     /* Could be a typedef; try to map it to the real type */
00533     real_type = find_underlying_type(type);
00534     type = real_type ? real_type : type;
00535 
00536     switch(IDL_NODE_TYPE(type)) {
00537 
00538     case IDLN_TYPE_INTEGER: {
00539 
00540         switch(IDL_TYPE_INTEGER(type).f_type) {
00541 
00542         case IDL_INTEGER_TYPE_SHORT:
00543             fputs("short", state->file);
00544             break;
00545 
00546         case IDL_INTEGER_TYPE_LONG:
00547             fputs("int", state->file);
00548             break;
00549 
00550         case IDL_INTEGER_TYPE_LONGLONG:
00551             fputs("long", state->file);
00552             break;
00553            
00554         default:
00555             g_error("   Unknown integer type: %d\n",
00556                     IDL_TYPE_INTEGER(type).f_type);
00557             return FALSE;
00558 
00559         }
00560 
00561         break;
00562     }
00563 
00564     case IDLN_TYPE_CHAR:
00565     case IDLN_TYPE_WIDE_CHAR:
00566         fputs("char", state->file);
00567         break;
00568 
00569     case IDLN_TYPE_WIDE_STRING:
00570     case IDLN_TYPE_STRING:
00571         fputs("String", state->file);
00572         break;
00573 
00574     case IDLN_TYPE_BOOLEAN:
00575         fputs("boolean", state->file);
00576         break;
00577 
00578     case IDLN_TYPE_OCTET:
00579         fputs("byte", state->file);
00580         break;
00581 
00582     case IDLN_TYPE_FLOAT:
00583         switch(IDL_TYPE_FLOAT(type).f_type) {
00584 
00585         case IDL_FLOAT_TYPE_FLOAT:
00586             fputs("float", state->file);
00587             break;
00588 
00589         case IDL_FLOAT_TYPE_DOUBLE:
00590             fputs("double", state->file);
00591             break;
00592            
00593         default:
00594             g_error("    Unknown floating point typ: %d\n",
00595                     IDL_NODE_TYPE(type));
00596             break;
00597         }
00598         break;
00599 
00600 
00601     case IDLN_IDENT:
00602       if (!(up = IDL_NODE_UP(type))) {
00603           IDL_tree_error(state->tree,
00604                          "ERROR: orphan ident %s in param list\n",
00605                          IDL_IDENT(state->tree).str);
00606           return FALSE;
00607       }
00608       switch (IDL_NODE_TYPE(up)) {
00609         case IDLN_FORWARD_DCL:
00610         case IDLN_INTERFACE: {
00611           char *className;
00612           const char *iid_is;
00613 handle_iid_is:
00614           /* might get here via the goto, so re-check type */
00615           if (IDL_NODE_TYPE(up) == IDLN_INTERFACE)
00616               className = IDL_IDENT(IDL_INTERFACE(up).ident).str;
00617           else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL)
00618               className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str;
00619           else
00620               className = IDL_IDENT(IDL_NATIVE(up).ident).str;
00621           iid_is = NULL;
00622 
00623           if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
00624               iid_is =
00625                   IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
00626                                         "iid_is");
00627           }
00628           if (iid_is) {
00629               fputs("nsISupports", state->file);
00630           } else {
00631               /* XXX How do we want to handle this? If it's an IDLN_INTERFACE,
00632                *  then we can just output the name of the class, since the IDL
00633                *  files exist for those classes.  However, if it's an
00634                *  IDLN_FORWARD_DCL, some of those interfaces are not defined in
00635                *  IDL files, so we get an error when trying to compile the java
00636                *  files.  So, for now, we just output them as the base iface
00637                *  (nsISupports). 
00638                */
00639               if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL)
00640                   fputs("nsISupports", state->file);
00641               else
00642                   fprintf(state->file, "%s", className);
00643           }
00644           break;
00645         }
00646         case IDLN_NATIVE: {
00647             char *ident;
00648 
00649             /* jband - adding goto for iid_is when type is native */
00650             if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL &&
00651                 IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
00652                                         "iid_is"))
00653             {
00654                 goto handle_iid_is;
00655 /*                fputs("nsISupports", state->file); */
00656                 break;
00657             }
00658 
00659             ident = IDL_IDENT(type).str;
00660             if (IDL_tree_property_get(type, "nsid")) {
00661                 fputs("String", state->file);
00662             } else if (IDL_tree_property_get(type, "domstring")) {
00663                 fputs("String", state->file);
00664             } else if (IDL_tree_property_get(type, "astring")) {
00665                 fputs("String", state->file);
00666             } else if (IDL_tree_property_get(type, "utf8string")) {
00667                 fputs("String", state->file);
00668             } else if (IDL_tree_property_get(type, "cstring")) {
00669                 fputs("String", state->file);
00670             } else {
00671                 const char* user_type = IDL_NATIVE(IDL_NODE_UP(type)).user_type;
00672                 IDL_tree real_type = 
00673                     g_hash_table_lookup(TYPEDEFS(state), user_type);
00674 
00675                 if (real_type) {
00676                     return xpcom_to_java_type(state, real_type);
00677                 } else {
00678                     if (strcmp(user_type, "PRInt8") == 0 ||
00679                         strcmp(user_type, "PRUint8") == 0) {
00680                         fputs("byte", state->file);
00681                     } else if (strcmp(user_type, "PRInt16") == 0 ||
00682                                strcmp(user_type, "PRUint16") == 0) {
00683                         fputs("short", state->file);
00684                     } else if (strcmp(user_type, "PRInt32") == 0 ||
00685                                strcmp(user_type, "PRUint32") == 0 ||
00686                                strcmp(user_type, "int") == 0) {
00687                         fputs("int", state->file);
00688                     } else if (strcmp(user_type, "PRInt64") == 0 ||
00689                                strcmp(user_type, "PRUint64") == 0) {
00690                         fputs("long", state->file);
00691                     } else if (strcmp(user_type, "PRBool") == 0) {
00692                         fputs("boolean", state->file);
00693                     } else if (strncmp(user_type, "char", 4) == 0 ||
00694                                strncmp(user_type, "const char", 10) == 0 ||
00695                                strncmp(user_type, "unsigned char", 13) == 0) {
00696                         if (IDL_tree_property_get(type, "ptr")) {
00697                             fputs("byte[]", state->file);
00698                         } else {
00699                             fputs("char", state->file);
00700                         }
00701                     } else if (strcmp(user_type, "nsIID") == 0) {
00702                         fputs("String", state->file);
00703                     } else if (strcmp(user_type, "nsString") == 0 ||
00704                                strcmp(user_type, "nsAString") == 0 ||
00705                                strcmp(user_type, "nsACString") == 0) {
00706                         fputs("String", state->file);
00707                     } else {
00708                         fputs("int", state->file);
00709                     }
00710                 }
00711             }
00712             break;
00713           }
00714         default:
00715           if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) {
00716               /* restart with the underlying type */
00717               IDL_tree new_type;
00718               new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec;
00719               if (new_type) {
00720                   gboolean rc = xpcom_to_java_type(state, new_type);
00721                   return rc;
00722               } else {
00723                   /* do what we would do in recursion if !type */
00724                   fputs("Object", state->file);
00725                   return TRUE;
00726               }
00727           }
00728           IDL_tree_error(state->tree,
00729                          "can't handle %s ident in param list [1]\n",
00730                                /* XXX is this safe to use on Win now? */
00731                                IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
00732 /*                         "that type of"*/
00733                          );
00734           return FALSE;
00735       }
00736       break;
00737 
00738     default:
00739       IDL_tree_error(state->tree, "can't handle %s in param list [1]\n",
00740                      /* XXX is this safe to use on Win now? */
00741                      IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
00742 /*                  "that type"*/
00743       );
00744       return FALSE;
00745     }
00746 
00747     return TRUE;
00748 
00749 }
00750 
00751 static gboolean
00752 xpcom_to_java_object_type(TreeState *state, IDL_tree type, char* parmName, gboolean is_object)
00753 {
00754     JavaNativeType jtype = xpcom_to_java_type2(state, type);
00755     
00756     switch (jtype) {
00757         case JAVA_BYTE:
00758             if (is_object) {
00759                 fputs(parmName, state->file);
00760             } else {
00761                 fprintf(state->file, "new Byte(%s)", parmName);
00762             }
00763             break;
00764         case JAVA_SHORT:
00765             if (is_object) {
00766                 fputs(parmName, state->file);
00767             } else {
00768                 fprintf(state->file, "new Short(%s)", parmName);
00769             }
00770             break;
00771         case JAVA_INT:
00772             if (is_object) {
00773                 fputs(parmName, state->file);
00774             } else {
00775                 fprintf(state->file, "new Integer(%s)", parmName);
00776             }
00777             break;
00778         case JAVA_LONG:
00779             if (is_object) {
00780                 fputs(parmName, state->file);
00781             } else {
00782                 fprintf(state->file, "new Long(%s)", parmName);
00783             }
00784             break;
00785         case JAVA_FLOAT:
00786             if (is_object) {
00787                 fputs(parmName, state->file);
00788             } else {
00789                 fprintf(state->file, "new Float(%s)", parmName);
00790             }
00791             break;
00792         case JAVA_DOUBLE:
00793             if (is_object) {
00794                 fputs(parmName, state->file);
00795             } else {
00796                 fprintf(state->file, "new Double(%s)", parmName);
00797             }
00798             break;
00799         case JAVA_CHAR:
00800             if (is_object) {
00801                 fputs(parmName, state->file);
00802             } else {
00803                 fprintf(state->file, "new Character(%s)", parmName);
00804             }
00805             break;
00806         case JAVA_BOOL:
00807             if (is_object) {
00808                 fputs(parmName, state->file);
00809             } else {
00810                 fprintf(state->file, "new Boolean(%s)", parmName);
00811             }
00812             break;
00813         case JAVA_BYTEARRAY:
00814         case JAVA_STRING:
00815         case JAVA_OBJECT:
00816         case JAVA_NSISUPPORTS:
00817             fputs(parmName, state->file);
00818             break;
00819         default:
00820             g_error("Unknown java type\n");
00821             return FALSE;
00822             break;
00823     }
00824     
00825     return TRUE;
00826 }
00827 
00828 static gboolean
00829 xpcom_to_java_param(TreeState *state) 
00830 {
00831     IDL_tree param = state->tree;
00832 
00833     /*
00834      * Put in type of parameter
00835      */
00836 
00837     if (!xpcom_to_java_type(state, IDL_PARAM_DCL(param).param_type_spec)) {
00838         return FALSE;
00839     }
00840 
00841     /*
00842      * If the parameter is out or inout, make it a Java array of the
00843      * appropriate type
00844      */
00845 
00846     if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) {
00847         fputs("[]", state->file);
00848     }
00849 
00850     /*
00851      * If the parameter is an array make it a Java array
00852      */
00853     if (IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array"))
00854         fputs("[]", state->file);
00855 
00856     /*
00857      * Put in name of parameter 
00858      */
00859 
00860     fputc(' ', state->file);
00861 
00862     fputs(subscriptIdentifier(state, 
00863                               IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str), 
00864           state->file);
00865 
00866     return TRUE;
00867 }
00868 
00869 static gboolean
00870 xpcom_to_java_object(TreeState *state) 
00871 {
00872     char* paramName;
00873     gboolean is_object;
00874 
00875     /*
00876      * Write Java object param
00877      */
00878     paramName = IDL_IDENT(IDL_PARAM_DCL(state->tree).simple_declarator).str;
00879     is_object = IDL_PARAM_DCL(state->tree).attr != IDL_PARAM_IN ||
00880                 IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, "array");
00881     if (!xpcom_to_java_object_type(state,
00882                                    IDL_PARAM_DCL(state->tree).param_type_spec,
00883                                    paramName, is_object)) {
00884         return FALSE;
00885     }
00886     
00887     return TRUE;
00888 }
00889 
00890 
00891 static gboolean
00892 type_declaration(TreeState *state) 
00893 {
00894     /*
00895      * Unlike C, Java has no type declaration directive.
00896      * Instead, we record the mapping, and look up the actual type
00897      * when needed.
00898      */
00899     IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
00900     IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
00901 
00902 #ifdef COUNT_METHODS
00903        if (PRIVDATA(state)->bCountingMethods) {
00904               return TRUE;
00905        }
00906 #endif
00907 
00908     /* XXX: check for illegal types */
00909 
00910     g_hash_table_insert(TYPEDEFS(state),
00911                         IDL_IDENT(IDL_LIST(dcls).data).str,
00912                         type);
00913 
00914     return TRUE;
00915 }
00916 
00917 static gboolean
00918 method_declaration(TreeState *state) 
00919 {
00920        gboolean bHasOutParm = FALSE; 
00921        gboolean bHasReturnValue = TRUE; 
00922        char *parmBuffer = NULL;
00923        IDL_tree orig_tree = NULL;
00924     GSList *doc_comments = IDL_IDENT(IDL_OP_DCL(state->tree).ident).comments;
00925     int numMethods;
00926     const char* array = NULL;
00927 
00928     struct _IDL_OP_DCL *method = &IDL_OP_DCL(state->tree);
00929     gboolean method_notxpcom = 
00930         (IDL_tree_property_get(method->ident, "notxpcom") != NULL);
00931     gboolean method_noscript = 
00932         (IDL_tree_property_get(method->ident, "noscript") != NULL);
00933     IDL_tree iterator = NULL;
00934     IDL_tree retval_param = NULL;
00935     char *method_name =
00936                   g_strdup_printf("%c%s",
00937                                   tolower(IDL_IDENT(method->ident).str[0]),
00938                                   IDL_IDENT(method->ident).str + 1);
00939 
00940     if (!verify_method_declaration(state->tree))
00941         return FALSE;
00942 
00943 #ifdef COUNT_METHODS
00944        if (PRIVDATA(state)->bCountingMethods) {
00945               PRIVDATA(state)->numMethods++;
00946               return TRUE;
00947        }
00948 #endif
00949 
00950 #if 1
00951     /* do not write non-xpcom methods */
00952     if (method_notxpcom) {
00953         xpidl_write_comment(state, 4);
00954         fputc('\n', state->file);
00955         PRIVDATA(state)->numMethods++;
00956         return TRUE;
00957     }
00958 
00959     /*
00960      * Write beginning of method declaration
00961      */
00962     fputs("    public ", state->file);
00963 #else
00964     /* do not write nonscriptable methods */
00965     if (method_notxpcom || method_noscript) {
00966         xpidl_write_comment(state, 4);
00967         fputc('\n', state->file);
00968         PRIVDATA(state)->numMethods++;
00969         return TRUE;
00970     }
00971 
00972     /*
00973      * Write beginning of method declaration
00974      */
00975     fputs("    ", state->file);
00976     if (!method_noscript) {
00977         /* Nonscriptable methods become package-protected */
00978         fputs("public ", state->file);
00979     }
00980 #endif
00981 
00982     /*
00983      * Write return type
00984      * Unlike C++ headers, Java interfaces return the declared 
00985      * return value; an exception indicates XPCOM method failure.
00986      */
00987     if (method->op_type_spec) {
00988         state->tree = method->op_type_spec;
00989         if (!xpcom_to_java_type(state, method->op_type_spec)) {
00990             return FALSE;
00991         }
00992     } else {
00993         /* Check for retval attribute */
00994         for (iterator = method->parameter_dcls; iterator != NULL; 
00995              iterator = IDL_LIST(iterator).next) {
00996 
00997             IDL_tree original_tree = state->tree;
00998 
00999             state->tree = IDL_LIST(iterator).data;
01000 
01001             if (IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, 
01002                                       "retval")) {
01003                 retval_param = iterator;
01004 
01005                 array = 
01006                     IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
01007                                           "array");
01008 
01009                 /*
01010                  * Put in type of parameter
01011                  */
01012                 if (!xpcom_to_java_type(state,
01013                                         IDL_PARAM_DCL(state->tree).param_type_spec)) {
01014                     return FALSE;
01015                 }
01016                 if (array)
01017                     fputs("[]", state->file);
01018             }
01019 
01020             state->tree = original_tree;
01021         }
01022 
01023         if (retval_param == NULL) {
01024             fputs("void", state->file);
01025         }
01026     }
01027 
01028     /*
01029      * Write method name
01030      */
01031     fprintf(state->file, " %s(", subscriptIdentifier(state, method_name));
01032 
01033     /*
01034      * Write parameters
01035      */
01036     for (iterator = method->parameter_dcls; iterator != NULL; 
01037          iterator = IDL_LIST(iterator).next) {
01038 
01039         /* Skip "retval" */
01040         if (iterator == retval_param) {
01041             continue;
01042         }
01043 
01044         if (iterator != method->parameter_dcls) {
01045             fputs(", ", state->file);
01046         }
01047         
01048         state->tree = IDL_LIST(iterator).data;
01049 
01050         if (!xpcom_to_java_param(state)) {
01051             return FALSE;
01052         }
01053     }
01054 
01055     fputs(")", state->file);
01056 
01057 /*    if (method->raises_expr) {
01058         IDL_tree iter = method->raises_expr;
01059         IDL_tree dataNode = IDL_LIST(iter).data;
01060 
01061         fputs(" throws ", state->file);
01062         fputs(IDL_IDENT(dataNode).str, state->file);
01063         iter = IDL_LIST(iter).next;
01064 
01065         while (iter) {
01066             dataNode = IDL_LIST(iter).data;
01067             fprintf(state->file, ", %s", IDL_IDENT(dataNode).str);
01068             iter = IDL_LIST(iter).next;
01069         }
01070     }   */
01071 
01072     fputs(" {\n        ", state->file);
01073     
01074     /*
01075      * If method has a return value, then we will return what we
01076      * get from CallXPCOMMethod()
01077      */
01078     if (method->op_type_spec || retval_param)
01079         fputs("return ", state->file);
01080     
01081     /*
01082      * Create CallXPCOMMethod invocation
01083      */
01084     if (method->op_type_spec || retval_param) {
01085         IDL_tree list = NULL;
01086         const char* is_array = NULL;
01087         JavaNativeType jtype = JAVA_NATIVE_ERROR;
01088 
01089         if (method->op_type_spec) {
01090             jtype = xpcom_to_java_type2(state, method->op_type_spec);
01091         } else {
01092             IDL_tree original_tree = state->tree;
01093             state->tree = IDL_LIST(retval_param).data;
01094             jtype = xpcom_to_java_type2(state,
01095                                         IDL_PARAM_DCL(state->tree).param_type_spec);
01096             state->tree = original_tree;
01097         }
01098 
01099         if (jtype == JAVA_NATIVE_ERROR)
01100             return FALSE;
01101 
01102         /* is return type an array? */
01103         if (retval_param) {
01104             list = IDL_LIST(retval_param).data;
01105             is_array = IDL_tree_property_get(IDL_PARAM_DCL(list).simple_declarator,
01106                                              "array");
01107         }
01108 
01109         switch (jtype) {
01110             case JAVA_BYTE:
01111                 fputs("XPCOMPrivate.CallXPCOMMethodByte", state->file);
01112                 break;
01113             case JAVA_BYTEARRAY:
01114                 fputs("(byte[]) XPCOMPrivate.CallXPCOMMethodObj", state->file);
01115                 break;
01116             case JAVA_SHORT:
01117                 fputs("XPCOMPrivate.CallXPCOMMethodShort", state->file);
01118                 break;
01119             case JAVA_INT:
01120                 fputs("XPCOMPrivate.CallXPCOMMethodInt", state->file);
01121                 break;
01122             case JAVA_LONG:
01123                 fputs("XPCOMPrivate.CallXPCOMMethodLong", state->file);
01124                 break;
01125             case JAVA_FLOAT:
01126                 fputs("XPCOMPrivate.CallXPCOMMethodFloat", state->file);
01127                 break;
01128             case JAVA_DOUBLE:
01129                 fputs("XPCOMPrivate.CallXPCOMMethodDouble", state->file);
01130                 break;
01131             case JAVA_CHAR:
01132                 fputs("XPCOMPrivate.CallXPCOMMethodChar", state->file);
01133                 break;
01134             case JAVA_BOOL:
01135                 fputs("XPCOMPrivate.CallXPCOMMethodBool", state->file);
01136                 break;
01137             case JAVA_STRING:
01138                 fputs("(String", state->file);
01139                 if (is_array)
01140                     fputs("[]", state->file);
01141                 fputs(") XPCOMPrivate.CallXPCOMMethodObj", state->file);
01142                 break;
01143             case JAVA_NSISUPPORTS:
01144                 fputs("(", state->file);
01145                 if (method->op_type_spec) {
01146                     if (!xpcom_to_java_type(state, method->op_type_spec))
01147                         return FALSE;
01148                 } else {
01149                     IDL_tree original_tree = state->tree;
01150                     state->tree = IDL_LIST(retval_param).data;
01151                     if (!xpcom_to_java_type(state, IDL_PARAM_DCL(state->tree).param_type_spec))
01152                       return FALSE;
01153                     state->tree = original_tree;
01154                 }
01155                 if (is_array)
01156                     fputs("[]", state->file);
01157                 fputs(") XPCOMPrivate.CallXPCOMMethodObj", state->file);
01158                 break;
01159             case JAVA_OBJECT:
01160                 fputs("XPCOMPrivate.CallXPCOMMethodObj", state->file);
01161                 break;
01162             default:
01163                 g_error("Unknown jtype: %d\n", jtype);
01164                 return FALSE;
01165         }
01166 
01167         if (is_array)
01168             fputs("A", state->file);
01169 
01170         state->tree = orig_tree;
01171     } else {
01172         fputs("XPCOMPrivate.CallXPCOMMethodVoid", state->file);
01173     }
01174     fputs("(this, ", state->file);
01175 
01176     numMethods = PRIVDATA(state)->numMethods;
01177     if (PRIVDATA(state)->bHasBaseClass) {
01178         numMethods++;
01179         fputs("super.LAST_METHOD_ID + ", state->file);
01180     }
01181     fprintf(state->file, "%d, ", numMethods);
01182 
01183     /*
01184      * Write parameters
01185      */
01186     for (iterator = method->parameter_dcls; iterator != NULL; 
01187          iterator = IDL_LIST(iterator).next) {
01188 
01189         /* Skip "retval" */
01190         if (iterator == retval_param) {
01191             if (iterator == method->parameter_dcls)
01192                 fputs("null", state->file);
01193             continue;
01194         }
01195 
01196         /* Start of object array decl */
01197         if (iterator == method->parameter_dcls) {
01198           fputs("new Object[] { ", state->file);
01199         }
01200 
01201         if (iterator != method->parameter_dcls) {
01202             fputs(", ", state->file);
01203         }
01204 
01205         state->tree = IDL_LIST(iterator).data;
01206 
01207         if (!xpcom_to_java_object(state)) {
01208             return FALSE;
01209         }
01210 
01211         /* Close object array decl */
01212         if (IDL_LIST(iterator).next == NULL ||
01213             (IDL_LIST(iterator).next == retval_param &&
01214              IDL_LIST(retval_param).next == NULL))
01215             fputs(" }", state->file);
01216     }
01217 
01218     if (method->parameter_dcls == NULL) {
01219         fputs("null", state->file);
01220     }
01221 
01222     fputs(");\n    }\n\n", state->file);
01223 
01224        PRIVDATA(state)->numMethods++;
01225 
01226        return TRUE;
01227 }
01228 
01229 
01230 static gboolean
01231 constant_declaration(TreeState *state)
01232 {
01233     /* Don't output constants for stubs */
01234     return TRUE;
01235 
01236 }
01237 
01238 #define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data))
01239 #define ATTR_PROPS(tree) (IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data)
01240 #define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL((tree)).param_type_spec)
01241 
01242 
01243 static gboolean
01244 attribute_declaration(TreeState *state)
01245 {
01246     char* attribute_text;
01247     char* name;
01248     int numMethods;
01249     JavaNativeType jtype;
01250 
01251     gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
01252     char *attribute_name = ATTR_IDENT(state->tree).str;
01253 
01254     gboolean method_noscript = 
01255         (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") != NULL);
01256 
01257     gboolean method_notxpcom = 
01258         (IDL_tree_property_get(ATTR_PROPS(state->tree), "notxpcom") != NULL);
01259 
01260 #ifdef COUNT_METHODS
01261        if (PRIVDATA(state)->bCountingMethods) {
01262               PRIVDATA(state)->numMethods++;
01263               if (!read_only) 
01264                      PRIVDATA(state)->numMethods++;
01265 
01266               return TRUE;
01267        }
01268 #endif
01269 
01270 #if 1
01271     /*
01272      * Write access permission ("public")
01273      */
01274     fputs("    public ", state->file);
01275 #else
01276     if (method_notxpcom || method_noscript)
01277         return TRUE;
01278 
01279     /*
01280      * Write access permission ("public" unless nonscriptable)
01281      */
01282     fputs("    ", state->file);
01283     if (!method_noscript) {
01284         fputs("public ", state->file);
01285     }
01286 #endif
01287 
01288     /*
01289      * Write the proper Java return value for the get operation
01290      */
01291     if (!xpcom_to_java_type(state, ATTR_TYPE_DECL(state->tree))) {
01292         return FALSE;
01293     }
01294 
01295     /*
01296      * Write the name of the accessor ("get") method.
01297      */
01298     fprintf(state->file, " get%c%s()\n",
01299             toupper(attribute_name[0]), attribute_name + 1);
01300 
01301     fputs("    {\n        ", state->file);
01302 
01303     jtype = xpcom_to_java_type2(state, ATTR_TYPE_DECL(state->tree));
01304     if (jtype == JAVA_NATIVE_ERROR)
01305         return FALSE;
01306     fputs("return ", state->file);
01307     switch (jtype) {
01308         case JAVA_BYTE:
01309             fputs("XPCOMPrivate.CallXPCOMMethodByte", state->file);
01310             break;
01311         case JAVA_BYTEARRAY:
01312             fputs("(byte[]) XPCOMPrivate.CallXPCOMMethodObj", state->file);
01313             break;
01314         case JAVA_SHORT:
01315             fputs("XPCOMPrivate.CallXPCOMMethodShort", state->file);
01316             break;
01317         case JAVA_INT:
01318             fputs("XPCOMPrivate.CallXPCOMMethodInt", state->file);
01319             break;
01320         case JAVA_LONG:
01321             fputs("XPCOMPrivate.CallXPCOMMethodLong", state->file);
01322             break;
01323         case JAVA_FLOAT:
01324             fputs("XPCOMPrivate.CallXPCOMMethodFloat", state->file);
01325             break;
01326         case JAVA_DOUBLE:
01327             fputs("XPCOMPrivate.CallXPCOMMethodDouble", state->file);
01328             break;
01329         case JAVA_CHAR:
01330             fputs("XPCOMPrivate.CallXPCOMMethodChar", state->file);
01331             break;
01332         case JAVA_BOOL:
01333             fputs("XPCOMPrivate.CallXPCOMMethodBool", state->file);
01334             break;
01335         case JAVA_STRING:
01336             fputs("(String) XPCOMPrivate.CallXPCOMMethodObj", state->file);
01337             break;
01338         case JAVA_NSISUPPORTS:
01339             fputs("(", state->file);
01340             if (!xpcom_to_java_type(state, ATTR_TYPE_DECL(state->tree))) {
01341                 return FALSE;
01342             }
01343             fputs(") XPCOMPrivate.CallXPCOMMethodObj", state->file);
01344             break;
01345         case JAVA_OBJECT:
01346             fputs("XPCOMPrivate.CallXPCOMMethodObj", state->file);
01347             break;
01348         default:
01349             g_error("Unknown jtype: %d\n", jtype);
01350             return FALSE;
01351     }
01352     fputs("(this, ", state->file);
01353 
01354     numMethods = PRIVDATA(state)->numMethods;
01355     if (PRIVDATA(state)->bHasBaseClass) {
01356         numMethods++;
01357         fputs("super.LAST_METHOD_ID + ", state->file);
01358     }
01359     fprintf(state->file, "%d, null);\n", numMethods);
01360 
01361        fputs("    }\n\n", state->file);
01362 
01363        PRIVDATA(state)->numMethods++;
01364 
01365     if (!read_only) {
01366 #if 1
01367         fputs("    public ", state->file);
01368 #else
01369         /* Nonscriptable methods become package-protected */
01370         fputs("    ", state->file);
01371         if (!method_noscript) {
01372             fputs("public ", state->file);
01373         }
01374 #endif
01375 
01376         /*
01377          * Write attribute access method name and return type
01378          */
01379         fprintf(state->file, "void set%c%s(",
01380                 toupper(attribute_name[0]), 
01381                 attribute_name+1);
01382 
01383         /*
01384          * Write the proper Java type for the set operation
01385          */
01386         if (!xpcom_to_java_type(state, ATTR_TYPE_DECL(state->tree))) {
01387             return FALSE;
01388         }
01389 
01390         /*
01391          * Write the name of the formal parameter.
01392          */
01393         fputs(" value)\n", state->file);
01394 /*        fprintf(state->file, " a%c%s)\n", toupper(attribute_name[0]), attribute_name + 1);*/
01395         
01396         fputs("    {\n        ", state->file);
01397 
01398         /*
01399          * Write CallXPCOMMethod invocation
01400          */
01401         fputs("XPCOMPrivate.CallXPCOMMethodVoid(this, ", state->file);
01402         numMethods = PRIVDATA(state)->numMethods;
01403               if (PRIVDATA(state)->bHasBaseClass) {
01404             numMethods++;
01405             fputs("super.LAST_METHOD_ID + ", state->file);
01406         }
01407         fprintf(state->file, "%d, ", numMethods);
01408         
01409         /*
01410          * Write parameter
01411          */
01412         fputs("new Object[] { ", state->file);
01413 /*        if (!xpcom_to_java_object(state)) {
01414             return FALSE;
01415         }   */
01416         if (!xpcom_to_java_object_type(state, ATTR_TYPE_DECL(state->tree), "value", 0)) {
01417             return FALSE;
01418         }
01419         fputs(" });", state->file);
01420 
01421               fputs("\n    }\n\n", state->file);
01422 
01423               PRIVDATA(state)->numMethods++;
01424     }
01425 
01426     return TRUE;
01427 }
01428 
01429 
01430 static gboolean
01431 enum_declaration(TreeState *state)
01432 {
01433     XPIDL_WARNING((state->tree, IDL_WARNING1,
01434                    "enums not supported, enum \'%s\' ignored",
01435                    IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
01436     return TRUE;
01437 }
01438 
01439 backend *
01440 xpidl_javastub_dispatch(void)
01441 {
01442     static backend result;
01443     static nodeHandler table[IDLN_LAST];
01444     static gboolean initialized = FALSE;
01445 
01446     result.emit_prolog = java_prolog;
01447     result.emit_epilog = java_epilog;
01448 
01449     if (!initialized) {
01450         table[IDLN_INTERFACE] = interface_declaration;
01451         table[IDLN_LIST] = process_list;
01452 
01453         table[IDLN_OP_DCL] = method_declaration;
01454         table[IDLN_ATTR_DCL] = attribute_declaration;
01455         table[IDLN_CONST_DCL] = constant_declaration;
01456 
01457         table[IDLN_TYPE_DCL] = type_declaration;
01458         table[IDLN_FORWARD_DCL] = forward_declaration;
01459 
01460         table[IDLN_TYPE_ENUM] = enum_declaration;
01461 
01462         initialized = TRUE;
01463     }
01464 
01465     result.dispatch_table = table;
01466     return &result;
01467 }
01468 
01469 char* subscriptIdentifier(TreeState *state, char *str)
01470 {
01471     char *sstr = NULL;
01472     char *keyword = g_hash_table_lookup(KEYWORDS(state), str);
01473     if (keyword) {
01474         sstr = g_strdup_printf("%s_", keyword);
01475         return sstr;
01476     }
01477     return str;
01478 }
01479