/* * Common method verification code, called by *op_dcl in the various backends. */ gboolean verify_method_declaration(IDL_tree method_tree) { struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree); IDL_tree iface; IDL_tree iter; gboolean notxpcom; gboolean scriptable_interface; gboolean scriptable_method; gboolean seen_retval = FALSE; const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str; /* We don't support attributes named IID, conflicts with static GetIID * member. The conflict is due to certain compilers (VC++) choosing a * different vtable order, placing GetIID at the beginning regardless * of it's placement */ if (strcmp(method_name, "GetIID") == 0) { IDL_tree_error(method_tree, "Methods named GetIID not supported, causes vtable " "ordering problems"); return FALSE; } if (op->f_varargs) { /* We don't currently support varargs. */ IDL_tree_error(method_tree, "varargs are not currently supported"); return FALSE; } /* * Verify that we've been called on an interface, and decide if the * interface was marked [scriptable]. */ if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) && IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree))) == IDLN_INTERFACE) { scriptable_interface = (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable") != NULL); } else { IDL_tree_error(method_tree, "verify_method_declaration called on a non-interface?"); return FALSE; } /* * Require that any method in an interface marked as [scriptable], that * *isn't* scriptable because it refers to some native type, be marked * [noscript] or [notxpcom]. * * Also check that iid_is points to nsid, and length_is, size_is points * to unsigned long. */ notxpcom = IDL_tree_property_get(op->ident, "notxpcom") != NULL; scriptable_method = scriptable_interface && !notxpcom && IDL_tree_property_get(op->ident, "noscript") == NULL; /* Loop through the parameters and check. */ for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) { IDL_tree param = IDL_LIST(iter).data; IDL_tree param_type = IDL_PARAM_DCL(param).param_type_spec; IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator; const char *param_name = IDL_IDENT(simple_decl).str; /* * Reject this method if it should be scriptable and some parameter is * native that isn't marked with either nsid, domstring, utf8string, * cstring, astring or iid_is. */ if (scriptable_method && UP_IS_NATIVE(param_type) && IDL_tree_property_get(param_type, "nsid") == NULL && IDL_tree_property_get(simple_decl, "iid_is") == NULL && IDL_tree_property_get(param_type, "domstring") == NULL && IDL_tree_property_get(param_type, "utf8string") == NULL && IDL_tree_property_get(param_type, "cstring") == NULL && IDL_tree_property_get(param_type, "astring") == NULL) { IDL_tree_error(method_tree, "methods in [scriptable] interfaces that are " "non-scriptable because they refer to native " "types (parameter \"%s\") must be marked " "[noscript]", param_name); return FALSE; } /* * nsid's parameters that aren't ptr's or ref's are not currently * supported in xpcom or non-xpcom (marked with [notxpcom]) methods * as input parameters */ if (!(notxpcom && IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) && IDL_tree_property_get(param_type, "nsid") != NULL && IDL_tree_property_get(param_type, "ptr") == NULL && IDL_tree_property_get(param_type, "ref") == NULL) { IDL_tree_error(method_tree, "Feature currently not supported: " "parameter \"%s\" is of type nsid and " "must be marked either [ptr] or [ref] " "or method \"%s\" must be marked [notxpcom] " "and must not be an input parameter", param_name, method_name); return FALSE; } /* * Sanity checks on return values. */ if (IDL_tree_property_get(simple_decl, "retval") != NULL) { if (IDL_LIST(iter).next != NULL) { IDL_tree_error(method_tree, "only the last parameter can be marked [retval]"); return FALSE; } if (op->op_type_spec) { IDL_tree_error(method_tree, "can't have [retval] with non-void return type"); return FALSE; } /* In case XPConnect relaxes the retval-is-last restriction. */ if (seen_retval) { IDL_tree_error(method_tree, "can't have more than one [retval] parameter"); return FALSE; } seen_retval = TRUE; } /* * Confirm that [shared] attributes are only used with string, wstring, * or native (but not nsid, domstring, utf8string, cstring or astring) * and can't be used with [array]. */ if (IDL_tree_property_get(simple_decl, "shared") != NULL) { IDL_tree real_type; real_type = find_underlying_type(param_type); real_type = real_type ? real_type : param_type; if (IDL_tree_property_get(simple_decl, "array") != NULL) { IDL_tree_error(method_tree, "[shared] parameter \"%s\" cannot " "be of array type", param_name); return FALSE; } if (!(IDL_NODE_TYPE(real_type) == IDLN_TYPE_STRING || IDL_NODE_TYPE(real_type) == IDLN_TYPE_WIDE_STRING || (UP_IS_NATIVE(real_type) && !IDL_tree_property_get(real_type, "nsid") && !IDL_tree_property_get(real_type, "domstring") && !IDL_tree_property_get(real_type, "utf8string") && !IDL_tree_property_get(real_type, "cstring") && !IDL_tree_property_get(real_type, "astring")))) { IDL_tree_error(method_tree, "[shared] parameter \"%s\" must be of type " "string, wstring or native", param_name); return FALSE; } } /* * inout is not allowed with "domstring", "UTF8String", "CString" * and "AString" types */ if (IDL_PARAM_DCL(param).attr == IDL_PARAM_INOUT && UP_IS_NATIVE(param_type) && (IDL_tree_property_get(param_type, "domstring") != NULL || IDL_tree_property_get(param_type, "utf8string") != NULL || IDL_tree_property_get(param_type, "cstring") != NULL || IDL_tree_property_get(param_type, "astring") != NULL )) { IDL_tree_error(method_tree, "[domstring], [utf8string], [cstring], [astring] " "types cannot be used as inout parameters"); return FALSE; } /* * arrays of domstring, utf8string, cstring, astring types not allowed */ if (IDL_tree_property_get(simple_decl, "array") != NULL && UP_IS_NATIVE(param_type) && (IDL_tree_property_get(param_type, "domstring") != NULL || IDL_tree_property_get(param_type, "utf8string") != NULL || IDL_tree_property_get(param_type, "cstring") != NULL || IDL_tree_property_get(param_type, "astring") != NULL)) { IDL_tree_error(method_tree, "[domstring], [utf8string], [cstring], [astring] " "types cannot be used in array parameters"); return FALSE; } if (!check_param_attribute(method_tree, param, IID_IS) || !check_param_attribute(method_tree, param, LENGTH_IS) || !check_param_attribute(method_tree, param, SIZE_IS)) return FALSE; /* * Run additional error checks on the parameter type if targetting an * older version of XPConnect. */ if (!verify_type_fits_version(param_type, method_tree)) return FALSE; } /* XXX q: can return type be nsid? */ /* Native return type? */ if (scriptable_method && op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec) && IDL_tree_property_get(op->op_type_spec, "nsid") == NULL && IDL_tree_property_get(op->op_type_spec, "domstring") == NULL && IDL_tree_property_get(op->op_type_spec, "utf8string") == NULL && IDL_tree_property_get(op->op_type_spec, "cstring") == NULL && IDL_tree_property_get(op->op_type_spec, "astring") == NULL) { IDL_tree_error(method_tree, "methods in [scriptable] interfaces that are " "non-scriptable because they return native " "types must be marked [noscript]"); return FALSE; } /* * nsid's parameters that aren't ptr's or ref's are not currently * supported in xpcom */ if (!notxpcom && op->op_type_spec != NULL && IDL_tree_property_get(op->op_type_spec, "nsid") != NULL && IDL_tree_property_get(op->op_type_spec, "ptr") == NULL && IDL_tree_property_get(op->op_type_spec, "ref") == NULL) { IDL_tree_error(method_tree, "Feature currently not supported: " "return value is of type nsid and " "must be marked either [ptr] or [ref], " "or else method \"%s\" must be marked [notxpcom] ", method_name); return FALSE; } /* * Run additional error checks on the return type if targetting an * older version of XPConnect. */ if (op->op_type_spec != NULL && !verify_type_fits_version(op->op_type_spec, method_tree)) { return FALSE; } return TRUE; }
gboolean verify_const_declaration(IDL_tree const_tree) { struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(const_tree); const char *name = IDL_IDENT(dcl->ident).str; IDL_tree real_type; /* const -> list -> interface */ if (!IDL_NODE_UP(IDL_NODE_UP(const_tree)) || IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(const_tree))) != IDLN_INTERFACE) { IDL_tree_error(const_tree, "const declaration \'%s\' outside interface", name); return FALSE; } /* Could be a typedef; try to map it to the real type. */ real_type = find_underlying_type(dcl->const_type); real_type = real_type ? real_type : dcl->const_type; if (IDL_NODE_TYPE(real_type) == IDLN_TYPE_INTEGER && (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_SHORT || IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG)) { if (!IDL_TYPE_INTEGER(real_type).f_signed && IDL_INTEGER(dcl->const_exp).value < 0) { #ifndef G_HAVE_GINT64 /* * For platforms without longlong support turned on we can get * confused by the high bit of the long value and think that it * represents a negative value in an unsigned declaration. * In that case we don't know if it is the programmer who is * confused or the compiler. So we issue a warning instead of * an error. */ if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG) { XPIDL_WARNING((const_tree, IDL_WARNING1, "unsigned const declaration \'%s\' " "initialized with (possibly) negative constant", name)); return TRUE; } #endif IDL_tree_error(const_tree, "unsigned const declaration \'%s\' initialized with " "negative constant", name); return FALSE; } } else { IDL_tree_error(const_tree, "const declaration \'%s\' must be of type short or long", name); return FALSE; } return TRUE; }
static gboolean fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree) { uint8 flags = 0; gboolean is_dipper_type = DIPPER_TYPE(IDL_PARAM_DCL(tree).param_type_spec); switch (IDL_PARAM_DCL(tree).attr) { case IDL_PARAM_IN: flags = XPT_PD_IN; break; case IDL_PARAM_OUT: flags = XPT_PD_OUT; break; case IDL_PARAM_INOUT: flags = XPT_PD_IN | XPT_PD_OUT; break; } if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator, "retval")) { if (flags != XPT_PD_OUT) { IDL_tree_error(tree, "can't have [retval] with in%s param " "(only out)\n", flags & XPT_PD_OUT ? "out" : ""); return FALSE; } flags |= XPT_PD_RETVAL; } if (is_dipper_type && (flags & XPT_PD_OUT)) { flags &= ~XPT_PD_OUT; flags |= XPT_PD_IN | XPT_PD_DIPPER; } if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator, "shared")) { if (flags & XPT_PD_IN) { IDL_tree_error(tree, "can't have [shared] with in%s param " "(only out)\n", flags & XPT_PD_OUT ? "out" : ""); return FALSE; } flags |= XPT_PD_SHARED; } if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator, "optional")) { flags |= XPT_PD_OPTIONAL; } /* stick param where we can see it later */ state->tree = tree; return fill_pd_from_type(state, pd, flags, IDL_PARAM_DCL(tree).param_type_spec); }
static gboolean do_enum(TreeState *state) { IDL_tree_error(state->tree, "enums not supported, " "see http://bugzilla.mozilla.org/show_bug.cgi?id=8781"); return FALSE; }
/* If insertion was made, return true, else there was a collision */ static gboolean heap_insert_ident (IDL_tree interface_ident, GTree *heap, IDL_tree any) { IDL_tree p; assert (any != NULL); assert (heap != NULL); if ((p = g_tree_lookup (heap, any))) { char *newi; char *i1, *i2; char *what1 = "identifier", *what2 = what1; char *who1, *who2; IDL_tree q; assert (IDL_NODE_TYPE (p) == IDLN_IDENT); newi = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (interface_ident), "::", 0); i1 = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (p), "::", 0); i2 = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (any), "::", 0); q = p; while (q && (IDL_NODE_TYPE (q) == IDLN_IDENT || IDL_NODE_TYPE (q) == IDLN_LIST)) q = IDL_NODE_UP (q); assert (q != NULL); IDL_tree_get_node_info (q, &what1, &who1); q = any; while (q && (IDL_NODE_TYPE (q) == IDLN_IDENT || IDL_NODE_TYPE (q) == IDLN_LIST)) q = IDL_NODE_UP (q); assert (q != NULL); IDL_tree_get_node_info (q, &what2, &who2); yyerrorv ("Ambiguous inheritance in interface `%s' from %s `%s' and %s `%s'", newi, what1, i1, what2, i2); IDL_tree_error (p, "%s `%s' conflicts with", what1, i1); IDL_tree_error (any, "%s `%s'", what2, i2); g_free (newi); g_free (i1); g_free (i2); return FALSE; } g_tree_insert (heap, any, any); return TRUE; }
/* fill the interface_directory IDE table from the interface_map */ static gboolean fill_ide_table(gpointer key, gpointer value, gpointer user_data) { TreeState *state = user_data; NewInterfaceHolder *holder = (NewInterfaceHolder *) value; struct nsID id; XPTInterfaceDirectoryEntry *ide; XPT_ASSERT(holder); #ifdef DEBUG_shaver_ifaces fprintf(stderr, "filling %s\n", holder->full_name); #endif if (holder->iid) { if (strlen(holder->iid) != 36) { IDL_tree_error(state->tree, "IID %s is the wrong length\n", holder->iid); return FALSE; } if (!xpidl_parse_iid(&id, holder->iid)) { IDL_tree_error(state->tree, "cannot parse IID %s\n", holder->iid); return FALSE; } } else { memset(&id, 0, sizeof(id)); } ide = &(HEADER(state)->interface_directory[IFACES(state)]); if (!XPT_FillInterfaceDirectoryEntry(ARENA(state), ide, &id, holder->name, holder->name_space, NULL)) { IDL_tree_error(state->tree, "INTERNAL: XPT_FillIDE failed for %s\n", holder->full_name); return FALSE; } IFACES(state)++; DeleteNewInterfaceHolder(holder); return TRUE; }
/* * Verify that a native declaration has an associated C++ expression, i.e. that * it's of the form native <idl-name>(<c++-name>) */ gboolean check_native(TreeState *state) { char *native_name; /* require that native declarations give a native type */ if (IDL_NATIVE(state->tree).user_type) return TRUE; native_name = IDL_IDENT(IDL_NATIVE(state->tree).ident).str; IDL_tree_error(state->tree, "``native %s;'' needs C++ type: ``native %s(<C++ type>);''", native_name, native_name); return FALSE; }
/* return value is for success or failure */ static gboolean get_size_and_length(TreeState *state, IDL_tree type, int16 *size_is_argnum, int16 *length_is_argnum, gboolean *has_size_is, gboolean *has_length_is) { *has_size_is = FALSE; *has_length_is = FALSE; if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator; const char *size_is; const char *length_is; /* only if size_is is found does any of this matter */ size_is = IDL_tree_property_get(sd, "size_is"); if (!size_is) return TRUE; if (!find_arg_with_name(state, size_is, size_is_argnum)) { IDL_tree_error(state->tree, "can't find matching argument for " "[size_is(%s)]\n", size_is); return FALSE; } *has_size_is = TRUE; /* length_is is optional */ length_is = IDL_tree_property_get(sd, "length_is"); if (length_is) { *has_length_is = TRUE; if (!find_arg_with_name(state, length_is, length_is_argnum)) { IDL_tree_error(state->tree, "can't find matching argument for " "[length_is(%s)]\n", length_is); return FALSE; } } } return TRUE; }
/* * This method consolidates error checking needed when coercing the XPIDL compiler * via the -t flag to generate output for a specific version of XPConnect. */ static gboolean verify_type_fits_version(IDL_tree in_tree, IDL_tree error_tree) { if (major_version == 1 && minor_version == 1) { /* XPIDL Version 1.1 checks */ /* utf8string, cstring, and astring types are not supported */ if (IDL_tree_property_get(in_tree, "utf8string") != NULL || IDL_tree_property_get(in_tree, "cstring") != NULL || IDL_tree_property_get(in_tree, "astring") != NULL) { IDL_tree_error(error_tree, "Cannot use [utf8string], [cstring] and [astring] " "types when generating version 1.1 typelibs\n"); return FALSE; } } return TRUE; }
static gboolean interface_declaration(TreeState *state) { char outname[PATH_MAX]; char* p; IDL_tree interface = state->tree; IDL_tree iterator = NULL; char *interface_name = subscriptIdentifier(state, IDL_IDENT(IDL_INTERFACE(interface).ident).str); const char *iid = NULL; char iid_parsed[UUID_LENGTH]; if (!verify_interface_declaration(interface)) return FALSE; /* * Each interface decl is a single file */ p = strrchr(state->filename, '/'); if (p) { strncpy(outname, state->filename, p + 1 - state->filename); outname[p + 1 - state->filename] = '\0'; } strcat(outname, interface_name); strcat(outname, ".java"); state->file = fopen(outname, "w"); if (!state->file) { perror("error opening output file"); return FALSE; } 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); if (state->package) fprintf(state->file, "\npackage %s;\n\n", state->package); if (!state->package || strcmp(state->package, "org.mozilla.xpcom") != 0) fputs("import org.mozilla.xpcom.*;\n", state->file); fputs("\n", state->file); #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) { struct nsID id; /* Redundant, but a better error than 'cannot parse.' */ if (strlen(iid) != 36) { IDL_tree_error(state->tree, "IID %s is the wrong length\n", iid); return FALSE; } /* * Parse uuid and then output resulting nsID to string, to validate * uuid and normalize resulting .h files. */ if (!xpidl_parse_iid(&id, iid)) { IDL_tree_error(state->tree, "cannot parse IID %s\n", iid); return FALSE; } if (!xpidl_sprint_iid(&id, iid_parsed)) { IDL_tree_error(state->tree, "error formatting IID %s\n", iid); return FALSE; } } else { IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n", interface_name); return FALSE; } /* * Write out JavaDoc comment */ fprintf(state->file, "\n/**\n * Interface %s\n", interface_name); if (iid != NULL) { fprintf(state->file, " *\n * IID: 0x%s\n */\n\n", iid_parsed); } else { fputs(" */\n\n", state->file); } /* * 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); /* * Write interface constants for IID */ if (iid) { /* public static final String NS_ISUPPORTS_IID = "00000000-0000-0000-c000-000000000046" */ fputs(" public static final String ", state->file); write_classname_iid_define(state->file, interface_name); fprintf(state->file, " =\n \"{%s}\";\n\n", iid_parsed); } /* * Advance the state of the tree, go on to process more */ state->tree = IDL_INTERFACE(interface).body; PRIVDATA(state)->bCountingMethods = FALSE; PRIVDATA(state)->numMethods = 0; if (state->tree && !xpidl_process_node(state)) { return FALSE; } fputs("\n}\n", state->file); fprintf(state->file, "\n/*\n * end\n */\n"); fclose(state->file); return TRUE; }
static gboolean fill_td_from_type(TreeState *state, XPTTypeDescriptor *td, IDL_tree type) { IDL_tree up; int16 size_is_argnum; int16 length_is_argnum; gboolean has_size_is; gboolean has_length_is; gboolean is_array = FALSE; if (type) { /* deal with array */ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator; if (IDL_tree_property_get(sd, "array")) { is_array = TRUE; /* size_is is required! */ if (!get_size_and_length(state, type, &size_is_argnum, &length_is_argnum, &has_size_is, &has_length_is)) { /* error was reported by helper function */ return FALSE; } if (!has_size_is) { IDL_tree_error(state->tree, "[array] requires [size_is()]\n"); return FALSE; } td->prefix.flags = TD_ARRAY | XPT_TDP_POINTER; td->argnum = size_is_argnum; if (has_length_is) td->argnum2 = length_is_argnum; else td->argnum2 = size_is_argnum; /* * XXX - NOTE - this will be broken for multidimensional * arrays because of the realloc XPT_InterfaceDescriptorAddTypes * uses. The underlying 'td' can change as we recurse in to get * additional dimensions. Luckily, we don't yet support more * than on dimension in the arrays */ /* setup the additional_type */ if (!XPT_InterfaceDescriptorAddTypes(ARENA(state), CURRENT(state), 1)) { g_error("out of memory\n"); return FALSE; } td->type.additional_type = NEXT_TYPE(state); td = &CURRENT(state)->additional_types[NEXT_TYPE(state)]; NEXT_TYPE(state)++ ; } } handle_typedef: switch (IDL_NODE_TYPE(type)) { case IDLN_TYPE_INTEGER: { gboolean sign = IDL_TYPE_INTEGER(type).f_signed; switch(IDL_TYPE_INTEGER(type).f_type) { case IDL_INTEGER_TYPE_SHORT: td->prefix.flags = sign ? TD_INT16 : TD_UINT16; break; case IDL_INTEGER_TYPE_LONG: td->prefix.flags = sign ? TD_INT32 : TD_UINT32; break; case IDL_INTEGER_TYPE_LONGLONG: td->prefix.flags = sign ? TD_INT64 : TD_UINT64; break; } break; } case IDLN_TYPE_CHAR: td->prefix.flags = TD_CHAR; break; case IDLN_TYPE_WIDE_CHAR: td->prefix.flags = TD_WCHAR; break; case IDLN_TYPE_STRING: if (is_array) { td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER; } else { if (!get_size_and_length(state, type, &size_is_argnum, &length_is_argnum, &has_size_is, &has_length_is)) { /* error was reported by helper function */ return FALSE; } if (has_size_is) { td->prefix.flags = TD_PSTRING_SIZE_IS | XPT_TDP_POINTER; td->argnum = size_is_argnum; if (has_length_is) td->argnum2 = length_is_argnum; else td->argnum2 = size_is_argnum; } else { td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER; } } break; case IDLN_TYPE_WIDE_STRING: if (is_array) { td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER; } else { if (!get_size_and_length(state, type, &size_is_argnum, &length_is_argnum, &has_size_is, &has_length_is)) { /* error was reported by helper function */ return FALSE; } if (has_size_is) { td->prefix.flags = TD_PWSTRING_SIZE_IS | XPT_TDP_POINTER; td->argnum = size_is_argnum; if (has_length_is) td->argnum2 = length_is_argnum; else td->argnum2 = size_is_argnum; } else { td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER; } } break; case IDLN_TYPE_BOOLEAN: td->prefix.flags = TD_BOOL; break; case IDLN_TYPE_OCTET: td->prefix.flags = TD_UINT8; break; case IDLN_TYPE_FLOAT: switch (IDL_TYPE_FLOAT (type).f_type) { case IDL_FLOAT_TYPE_FLOAT: td->prefix.flags = TD_FLOAT; break; case IDL_FLOAT_TYPE_DOUBLE: td->prefix.flags = TD_DOUBLE; break; /* XXX 'long double' just ignored, or what? */ default: break; } break; case IDLN_IDENT: if (!(up = IDL_NODE_UP(type))) { IDL_tree_error(state->tree, "ERROR: orphan ident %s in param list\n", IDL_IDENT(type).str); return FALSE; } switch (IDL_NODE_TYPE(up)) { /* This whole section is abominably ugly */ case IDLN_FORWARD_DCL: case IDLN_INTERFACE: { XPTInterfaceDirectoryEntry *ide, *ides; uint16 num_ifaces; char *className; const char *iid_is; handle_iid_is: ides = HEADER(state)->interface_directory; num_ifaces = HEADER(state)->num_interfaces; /* might get here via the goto, so re-check type */ if (IDL_NODE_TYPE(up) == IDLN_INTERFACE) className = IDL_IDENT(IDL_INTERFACE(up).ident).str; else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL) className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str; else className = IDL_IDENT(IDL_NATIVE(up).ident).str; iid_is = NULL; if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { iid_is = IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, "iid_is"); } if (iid_is) { int16 argnum; if (!find_arg_with_name(state, iid_is, &argnum)) { IDL_tree_error(state->tree, "can't find matching argument for " "[iid_is(%s)]\n", iid_is); return FALSE; } td->prefix.flags = TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER; td->argnum = argnum; } else { td->prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER; ide = FindInterfaceByName(ides, num_ifaces, className); if (!ide || ide < ides || ide > ides + num_ifaces) { IDL_tree_error(state->tree, "unknown iface %s in param\n", className); return FALSE; } td->type.iface = ide - ides + 1; #ifdef DEBUG_shaver_index fprintf(stderr, "DBG: index %d for %s\n", td->type.iface, className); #endif } break; } case IDLN_NATIVE: { char *ident; /* jband - adding goto for iid_is when type is native */ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL && IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, "iid_is")) goto handle_iid_is; ident = IDL_IDENT(type).str; if (IDL_tree_property_get(type, "nsid")) { td->prefix.flags = TD_PNSIID; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_POINTER | XPT_TDP_REFERENCE; else if (IDL_tree_property_get(type,"ptr")) td->prefix.flags |= XPT_TDP_POINTER; } else if (IDL_tree_property_get(type, "domstring")) { td->prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_REFERENCE; } else if (IDL_tree_property_get(type, "astring")) { td->prefix.flags = TD_ASTRING | XPT_TDP_POINTER; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_REFERENCE; } else if (IDL_tree_property_get(type, "utf8string")) { td->prefix.flags = TD_UTF8STRING | XPT_TDP_POINTER; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_REFERENCE; } else if (IDL_tree_property_get(type, "cstring")) { td->prefix.flags = TD_CSTRING | XPT_TDP_POINTER; if (IDL_tree_property_get(type, "ref")) td->prefix.flags |= XPT_TDP_REFERENCE; } else if (IDL_tree_property_get(type, "jsval")) { td->prefix.flags = TD_JSVAL; if (IDL_tree_property_get(type, "ptr")) td->prefix.flags |= XPT_TDP_POINTER; } else { td->prefix.flags = TD_VOID | XPT_TDP_POINTER; } break; } default: if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) { /* restart with the underlying type */ IDL_tree new_type; new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec; #ifdef DEBUG_shaver_misc fprintf(stderr, "following %s typedef to %s\n", IDL_IDENT(type).str, IDL_NODE_TYPE_NAME(new_type)); #endif /* * Do a nice messy goto rather than recursion so that * we can avoid screwing up the *array* information. */ /* return fill_td_from_type(state, td, new_type); */ if (new_type) { type = new_type; goto handle_typedef; } else { /* do what we would do in recursion if !type */ td->prefix.flags = TD_VOID; return TRUE; } } IDL_tree_error(state->tree, "can't handle %s ident in param list\n", #ifdef DEBUG_shaver /* XXX is this safe to use on Win now? */ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type)) #else "that type of" #endif ); #ifdef DEBUG_shaver XPT_ASSERT(0); #endif return FALSE; } break; default: IDL_tree_error(state->tree, "can't handle %s in param list\n", #ifdef DEBUG_shaver /* XXX is this safe to use on Win now? */ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type)) #else "that type" #endif ); return FALSE; } } else { td->prefix.flags = TD_VOID; } return TRUE; }
static gboolean typelib_interface(TreeState *state) { IDL_tree iface = state->tree, iter; char *name = IDL_IDENT(IDL_INTERFACE(iface).ident).str; XPTInterfaceDirectoryEntry *ide; XPTInterfaceDescriptor *id; uint16 parent_id = 0; PRUint8 interface_flags = 0; if (!verify_interface_declaration(iface)) return FALSE; if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")) interface_flags |= XPT_ID_SCRIPTABLE; if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "function")) interface_flags |= XPT_ID_FUNCTION; ide = FindInterfaceByName(HEADER(state)->interface_directory, HEADER(state)->num_interfaces, name); if (!ide) { IDL_tree_error(iface, "ERROR: didn't find interface %s in " "IDE block. Giving up.\n", name); return FALSE; } if ((iter = IDL_INTERFACE(iface).inheritance_spec)) { char *parent; if (IDL_LIST(iter).next) { IDL_tree_error(iface, "ERROR: more than one parent interface for %s\n", name); return FALSE; } parent = IDL_IDENT(IDL_LIST(iter).data).str; parent_id = (uint16)(uint32)g_hash_table_lookup(IFACE_MAP(state), parent); if (!parent_id) { IDL_tree_error(iface, "ERROR: no index found for %s. Giving up.\n", parent); return FALSE; } } id = XPT_NewInterfaceDescriptor(ARENA(state), parent_id, 0, 0, interface_flags); if (!id) return FALSE; CURRENT(state) = ide->interface_descriptor = id; #ifdef DEBUG_shaver_ifaces fprintf(stderr, "DBG: starting interface %s @ %p\n", name, id); #endif NEXT_METH(state) = 0; NEXT_CONST(state) = 0; NEXT_TYPE(state) = 0; state->tree = IDL_INTERFACE(iface).body; if (state->tree && !xpidl_process_node(state)) return FALSE; #ifdef DEBUG_shaver_ifaces fprintf(stderr, "DBG: ending interface %s\n", name); #endif return TRUE; }
static gboolean interface(TreeState *state) { IDL_tree iface = state->tree, iter, orig; char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str; char *classNameUpper = NULL; char *classNameImpl = NULL; char *cp; gboolean ok = TRUE; gboolean keepvtable; const char *iid; const char *name_space; struct nsID id; char iid_parsed[UUID_LENGTH]; GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments; if (!verify_interface_declaration(iface)) return FALSE; #define FAIL do {ok = FALSE; goto out;} while(0) fprintf(state->file, "\n/* starting interface: %s */\n", className); name_space = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "namespace"); if (name_space) { fprintf(state->file, "/* namespace: %s */\n", name_space); fprintf(state->file, "/* fully qualified name: %s.%s */\n", name_space,className); } iid = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "uuid"); if (iid) { /* Redundant, but a better error than 'cannot parse.' */ if (strlen(iid) != 36) { IDL_tree_error(state->tree, "IID %s is the wrong length\n", iid); FAIL; } /* * Parse uuid and then output resulting nsID to string, to validate * uuid and normalize resulting .h files. */ if (!xpidl_parse_iid(&id, iid)) { IDL_tree_error(state->tree, "cannot parse IID %s\n", iid); FAIL; } if (!xpidl_sprint_iid(&id, iid_parsed)) { IDL_tree_error(state->tree, "error formatting IID %s\n", iid); FAIL; } /* #define NS_ISUPPORTS_IID_STR "00000000-0000-0000-c000-000000000046" */ fputs("#define ", state->file); write_classname_iid_define(state->file, className); fprintf(state->file, "_STR \"%s\"\n", iid_parsed); fputc('\n', state->file); /* #define NS_ISUPPORTS_IID { {0x00000000 .... 0x46 }} */ fprintf(state->file, "#define "); write_classname_iid_define(state->file, className); fprintf(state->file, " \\\n" " {0x%.8x, 0x%.4x, 0x%.4x, \\\n" " { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, " "0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }}\n", id.m0, id.m1, id.m2, id.m3[0], id.m3[1], id.m3[2], id.m3[3], id.m3[4], id.m3[5], id.m3[6], id.m3[7]); fputc('\n', state->file); } else { IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n", className); FAIL; } if (doc_comments != NULL) printlist(state->file, doc_comments); /* * NS_NO_VTABLE is defined in nsISupportsUtils.h, and defined on windows * to __declspec(novtable) on windows. This optimization is safe * whenever the constructor calls no virtual methods. Writing in IDL * almost guarantees this, except for the case when a %{C++ block occurs in * the interface. We detect that case, and emit a macro call that disables * the optimization. */ keepvtable = FALSE; for (iter = IDL_INTERFACE(state->tree).body; iter != NULL; iter = IDL_LIST(iter).next) { IDL_tree data = IDL_LIST(iter).data; if (IDL_NODE_TYPE(data) == IDLN_CODEFRAG) keepvtable = TRUE; } /* The interface declaration itself. */ fprintf(state->file, "class %s%s", (keepvtable ? "" : "NS_NO_VTABLE "), className); if ((iter = IDL_INTERFACE(iface).inheritance_spec)) { fputs(" : ", state->file); if (IDL_LIST(iter).next != NULL) { IDL_tree_error(iter, "multiple inheritance is not supported by xpidl"); FAIL; } fprintf(state->file, "public %s", IDL_IDENT(IDL_LIST(iter).data).str); } fputs(" {\n" " public: \n\n", state->file); if (iid) { fputs(" NS_DEFINE_STATIC_IID_ACCESSOR(", state->file); write_classname_iid_define(state->file, className); fputs(")\n\n", state->file); } orig = state->tree; /* It would be nice to remove this state-twiddling. */ state->tree = IDL_INTERFACE(iface).body; if (state->tree && !xpidl_process_node(state)) FAIL; fputs("};\n", state->file); fputc('\n', state->file); /* * #define NS_DECL_NSIFOO - create method prototypes that can be used in * class definitions that support this interface. * * Walk the tree explicitly to prototype a reworking of xpidl to get rid of * the callback mechanism. */ state->tree = orig; fputs("/* Use this macro when declaring classes that implement this " "interface. */\n", state->file); fputs("#define NS_DECL_", state->file); classNameUpper = xpidl_strdup(className); for (cp = classNameUpper; *cp != '\0'; cp++) *cp = toupper(*cp); fprintf(state->file, "%s \\\n", classNameUpper); if (IDL_INTERFACE(state->tree).body == NULL) { write_indent(state->file); fputs("/* no methods! */\n", state->file); } for (iter = IDL_INTERFACE(state->tree).body; iter != NULL; iter = IDL_LIST(iter).next) { IDL_tree data = IDL_LIST(iter).data; switch(IDL_NODE_TYPE(data)) { case IDLN_OP_DCL: write_indent(state->file); write_method_signature(data, state->file, AS_DECL, NULL); break; case IDLN_ATTR_DCL: write_indent(state->file); if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL)) FAIL; if (!IDL_ATTR_DCL(data).f_readonly) { fputs("; \\\n", state->file); /* Terminate the previous one. */ write_indent(state->file); if (!write_attr_accessor(data, state->file, FALSE, AS_DECL, NULL)) FAIL; /* '; \n' at end will clean up. */ } break; case IDLN_CONST_DCL: /* ignore it here; it doesn't contribute to the macro. */ continue; case IDLN_CODEFRAG: XPIDL_WARNING((iter, IDL_WARNING1, "%%{ .. %%} code fragment within interface " "ignored when generating NS_DECL_%s macro; " "if the code fragment contains method " "declarations, the macro probably isn't " "complete.", classNameUpper)); continue; default: IDL_tree_error(iter, "unexpected node type %d! " "Please file a bug against the xpidl component.", IDL_NODE_TYPE(data)); FAIL; } if (IDL_LIST(iter).next != NULL) { fprintf(state->file, "; \\\n"); } else { fprintf(state->file, "; \n"); } } fputc('\n', state->file); /* XXX abstract above and below into one function? */ /* * #define NS_FORWARD_NSIFOO - create forwarding methods that can delegate * behavior from in implementation to another object. As generated by * idlc. */ fprintf(state->file, "/* Use this macro to declare functions that forward the " "behavior of this interface to another object. */\n" "#define NS_FORWARD_%s(_to) \\\n", classNameUpper); if (IDL_INTERFACE(state->tree).body == NULL) { write_indent(state->file); fputs("/* no methods! */\n", state->file); } for (iter = IDL_INTERFACE(state->tree).body; iter != NULL; iter = IDL_LIST(iter).next) { IDL_tree data = IDL_LIST(iter).data; switch(IDL_NODE_TYPE(data)) { case IDLN_OP_DCL: write_indent(state->file); write_method_signature(data, state->file, AS_DECL, NULL); fputs(" { return _to ", state->file); write_method_signature(data, state->file, AS_CALL, NULL); break; case IDLN_ATTR_DCL: write_indent(state->file); if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL)) FAIL; fputs(" { return _to ", state->file); if (!write_attr_accessor(data, state->file, TRUE, AS_CALL, NULL)) FAIL; if (!IDL_ATTR_DCL(data).f_readonly) { fputs("; } \\\n", state->file); /* Terminate the previous one. */ write_indent(state->file); if (!write_attr_accessor(data, state->file, FALSE, AS_DECL, NULL)) FAIL; fputs(" { return _to ", state->file); if (!write_attr_accessor(data, state->file, FALSE, AS_CALL, NULL)) FAIL; /* '; } \n' at end will clean up. */ } break; case IDLN_CONST_DCL: case IDLN_CODEFRAG: continue; default: FAIL; } if (IDL_LIST(iter).next != NULL) { fprintf(state->file, "; } \\\n"); } else { fprintf(state->file, "; } \n"); } } fputc('\n', state->file); /* XXX abstract above and below into one function? */ /* * #define NS_FORWARD_SAFE_NSIFOO - create forwarding methods that can delegate * behavior from in implementation to another object. As generated by * idlc. */ fprintf(state->file, "/* Use this macro to declare functions that forward the " "behavior of this interface to another object in a safe way. */\n" "#define NS_FORWARD_SAFE_%s(_to) \\\n", classNameUpper); if (IDL_INTERFACE(state->tree).body == NULL) { write_indent(state->file); fputs("/* no methods! */\n", state->file); } for (iter = IDL_INTERFACE(state->tree).body; iter != NULL; iter = IDL_LIST(iter).next) { IDL_tree data = IDL_LIST(iter).data; switch(IDL_NODE_TYPE(data)) { case IDLN_OP_DCL: write_indent(state->file); write_method_signature(data, state->file, AS_DECL, NULL); fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file); write_method_signature(data, state->file, AS_CALL, NULL); break; case IDLN_ATTR_DCL: write_indent(state->file); if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL)) FAIL; fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file); if (!write_attr_accessor(data, state->file, TRUE, AS_CALL, NULL)) FAIL; if (!IDL_ATTR_DCL(data).f_readonly) { fputs("; } \\\n", state->file); /* Terminate the previous one. */ write_indent(state->file); if (!write_attr_accessor(data, state->file, FALSE, AS_DECL, NULL)) FAIL; fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file); if (!write_attr_accessor(data, state->file, FALSE, AS_CALL, NULL)) FAIL; /* '; } \n' at end will clean up. */ } break; case IDLN_CONST_DCL: case IDLN_CODEFRAG: continue; default: FAIL; } if (IDL_LIST(iter).next != NULL) { fprintf(state->file, "; } \\\n"); } else { fprintf(state->file, "; } \n"); } } fputc('\n', state->file); /* * Build a sample implementation template. */ if (strlen(className) >= 3 && className[2] == 'I') { classNameImpl = xpidl_strdup(className); if (!classNameImpl) FAIL; memmove(&classNameImpl[2], &classNameImpl[3], strlen(classNameImpl) - 2); } else { classNameImpl = xpidl_strdup("_MYCLASS_"); if (!classNameImpl) FAIL; } fputs("#if 0\n" "/* Use the code below as a template for the " "implementation class for this interface. */\n" "\n" "/* Header file */" "\n", state->file); fprintf(state->file, "class %s : public %s\n", classNameImpl, className); fputs("{\n" "public:\n", state->file); write_indent(state->file); fputs("NS_DECL_ISUPPORTS\n", state->file); write_indent(state->file); fprintf(state->file, "NS_DECL_%s\n", classNameUpper); fputs("\n", state->file); write_indent(state->file); fprintf(state->file, "%s();\n", classNameImpl); fputs("\n" "private:\n", state->file); write_indent(state->file); fprintf(state->file, "~%s();\n", classNameImpl); fputs("\n" "protected:\n", state->file); write_indent(state->file); fputs("/* additional members */\n", state->file); fputs("};\n\n", state->file); fputs("/* Implementation file */\n", state->file); fprintf(state->file, "NS_IMPL_ISUPPORTS1(%s, %s)\n", classNameImpl, className); fputs("\n", state->file); fprintf(state->file, "%s::%s()\n", classNameImpl, classNameImpl); fputs("{\n", state->file); write_indent(state->file); fputs("/* member initializers and constructor code */\n", state->file); fputs("}\n\n", state->file); fprintf(state->file, "%s::~%s()\n", classNameImpl, classNameImpl); fputs("{\n", state->file); write_indent(state->file); fputs("/* destructor code */\n", state->file); fputs("}\n\n", state->file); for (iter = IDL_INTERFACE(state->tree).body; iter != NULL; iter = IDL_LIST(iter).next) { IDL_tree data = IDL_LIST(iter).data; switch(IDL_NODE_TYPE(data)) { case IDLN_OP_DCL: /* It would be nice to remove this state-twiddling. */ orig = state->tree; state->tree = data; xpidl_write_comment(state, 0); state->tree = orig; write_method_signature(data, state->file, AS_IMPL, classNameImpl); fputs("\n{\n", state->file); write_indent(state->file); write_indent(state->file); fputs("return NS_ERROR_NOT_IMPLEMENTED;\n" "}\n" "\n", state->file); break; case IDLN_ATTR_DCL: /* It would be nice to remove this state-twiddling. */ orig = state->tree; state->tree = data; xpidl_write_comment(state, 0); state->tree = orig; if (!write_attr_accessor(data, state->file, TRUE, AS_IMPL, classNameImpl)) FAIL; fputs("\n{\n", state->file); write_indent(state->file); write_indent(state->file); fputs("return NS_ERROR_NOT_IMPLEMENTED;\n" "}\n", state->file); if (!IDL_ATTR_DCL(data).f_readonly) { if (!write_attr_accessor(data, state->file, FALSE, AS_IMPL, classNameImpl)) FAIL; fputs("\n{\n", state->file); write_indent(state->file); write_indent(state->file); fputs("return NS_ERROR_NOT_IMPLEMENTED;\n" "}\n", state->file); } fputs("\n", state->file); break; case IDLN_CONST_DCL: case IDLN_CODEFRAG: continue; default: FAIL; } } fputs("/* End of implementation class template. */\n" "#endif\n" "\n", state->file); #undef FAIL out: if (classNameUpper) free(classNameUpper); if (classNameImpl) free(classNameImpl); return ok; }
static gboolean xpcom_to_java_type(TreeState *state, IDL_tree type) { IDL_tree real_type; IDL_tree up; if (!type) { fputs("Object", state->file); return TRUE; } /* Could be a typedef; try to map it to the real type */ real_type = find_underlying_type(type); type = real_type ? real_type : type; switch(IDL_NODE_TYPE(type)) { case IDLN_TYPE_INTEGER: { switch(IDL_TYPE_INTEGER(type).f_type) { case IDL_INTEGER_TYPE_SHORT: fputs("short", state->file); break; case IDL_INTEGER_TYPE_LONG: fputs("int", state->file); break; case IDL_INTEGER_TYPE_LONGLONG: fputs("long", state->file); break; default: g_error(" Unknown integer type: %d\n", IDL_TYPE_INTEGER(type).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: fputs("byte", state->file); break; case IDLN_TYPE_FLOAT: switch(IDL_TYPE_FLOAT(type).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(type)); break; } break; case IDLN_IDENT: if (!(up = IDL_NODE_UP(type))) { IDL_tree_error(state->tree, "ERROR: orphan ident %s in param list\n", IDL_IDENT(state->tree).str); return FALSE; } switch (IDL_NODE_TYPE(up)) { case IDLN_FORWARD_DCL: case IDLN_INTERFACE: { char *className; const char *iid_is; handle_iid_is: /* might get here via the goto, so re-check type */ if (IDL_NODE_TYPE(up) == IDLN_INTERFACE) className = IDL_IDENT(IDL_INTERFACE(up).ident).str; else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL) className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str; else className = IDL_IDENT(IDL_NATIVE(up).ident).str; iid_is = NULL; if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { iid_is = IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, "iid_is"); } if (iid_is) { fputs("nsISupports", state->file); } else { /* XXX How do we want to handle this? If it's an IDLN_INTERFACE, * then we can just output the name of the class, since the IDL * files exist for those classes. However, if it's an * IDLN_FORWARD_DCL, some of those interfaces are not defined in * IDL files, so we get an error when trying to compile the java * files. So, for now, we just output them as the base iface * (nsISupports). */ if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL) fputs("nsISupports", state->file); else fprintf(state->file, "%s", className); } break; } case IDLN_NATIVE: { char *ident; /* jband - adding goto for iid_is when type is native */ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL && IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, "iid_is")) { goto handle_iid_is; /* fputs("nsISupports", state->file); */ break; } ident = IDL_IDENT(type).str; if (IDL_tree_property_get(type, "nsid")) { fputs("String", state->file); } else if (IDL_tree_property_get(type, "domstring")) { fputs("String", state->file); } else if (IDL_tree_property_get(type, "astring")) { fputs("String", state->file); } else if (IDL_tree_property_get(type, "utf8string")) { fputs("String", state->file); } else if (IDL_tree_property_get(type, "cstring")) { fputs("String", state->file); } else { const char* user_type = IDL_NATIVE(IDL_NODE_UP(type)).user_type; IDL_tree real_type = g_hash_table_lookup(TYPEDEFS(state), user_type); if (real_type) { return xpcom_to_java_type(state, real_type); } else { if (strcmp(user_type, "PRInt8") == 0 || strcmp(user_type, "PRUint8") == 0) { fputs("byte", state->file); } else if (strcmp(user_type, "PRInt16") == 0 || strcmp(user_type, "PRUint16") == 0) { fputs("short", state->file); } else if (strcmp(user_type, "PRInt32") == 0 || strcmp(user_type, "PRUint32") == 0 || strcmp(user_type, "int") == 0) { fputs("int", state->file); } else if (strcmp(user_type, "PRInt64") == 0 || strcmp(user_type, "PRUint64") == 0) { fputs("long", state->file); } else if (strcmp(user_type, "PRBool") == 0) { fputs("boolean", state->file); } else if (strncmp(user_type, "char", 4) == 0 || strncmp(user_type, "const char", 10) == 0 || strncmp(user_type, "unsigned char", 13) == 0) { if (IDL_tree_property_get(type, "ptr")) { fputs("byte[]", state->file); } else { fputs("char", state->file); } } else if (strcmp(user_type, "nsIID") == 0) { fputs("String", state->file); } else if (strcmp(user_type, "nsString") == 0 || strcmp(user_type, "nsAString") == 0 || strcmp(user_type, "nsACString") == 0) { fputs("String", state->file); } else { fputs("int", state->file); } } } break; } default: if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) { /* restart with the underlying type */ IDL_tree new_type; new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec; if (new_type) { gboolean rc = xpcom_to_java_type(state, new_type); return rc; } else { /* do what we would do in recursion if !type */ fputs("Object", state->file); return TRUE; } } IDL_tree_error(state->tree, "can't handle %s ident in param list\n", "that type of" ); return FALSE; } break; default: IDL_tree_error(state->tree, "can't handle %s in param list\n", #ifdef DEBUG_shaver /* XXX is this safe to use on Win now? */ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type)) #else "that type" #endif ); return FALSE; } return TRUE; }
/* * Check that parameters referred to by attributes such as size_is exist and * refer to parameters of the appropriate type. */ static gboolean check_param_attribute(IDL_tree method_tree, IDL_tree param, ParamAttrType whattocheck) { const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str; const char *referred_name = NULL; IDL_tree param_type = IDL_PARAM_DCL(param).param_type_spec; IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator; const char *param_name = IDL_IDENT(simple_decl).str; const char *attr_name; const char *needed_type; if (whattocheck == IID_IS) { attr_name = "iid_is"; needed_type = "IID"; } else if (whattocheck == LENGTH_IS) { attr_name = "length_is"; needed_type = "unsigned long (or PRUint32)"; } else if (whattocheck == SIZE_IS) { attr_name = "size_is"; needed_type = "unsigned long (or PRUint32)"; } else { XPT_ASSERT("asked to check an unknown attribute type!"); return TRUE; } referred_name = IDL_tree_property_get(simple_decl, attr_name); if (referred_name != NULL) { IDL_tree referred_param = find_named_parameter(method_tree, referred_name); IDL_tree referred_param_type; if (referred_param == NULL) { IDL_tree_error(method_tree, "attribute [%s(%s)] refers to missing " "parameter \"%s\"", attr_name, referred_name, referred_name); return FALSE; } if (referred_param == param) { IDL_tree_error(method_tree, "attribute [%s(%s)] refers to it's own parameter", attr_name, referred_name); return FALSE; } referred_param_type = IDL_PARAM_DCL(referred_param).param_type_spec; if (whattocheck == IID_IS) { /* require IID type */ if (IDL_tree_property_get(referred_param_type, "nsid") == NULL) { IDL_tree_error(method_tree, "target \"%s\" of [%s(%s)] attribute " "must be of %s type", referred_name, attr_name, referred_name, needed_type); return FALSE; } } else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) { /* require PRUint32 type */ IDL_tree real_type; /* Could be a typedef; try to map it to the real type. */ real_type = find_underlying_type(referred_param_type); real_type = real_type ? real_type : referred_param_type; if (IDL_NODE_TYPE(real_type) != IDLN_TYPE_INTEGER || IDL_TYPE_INTEGER(real_type).f_signed != FALSE || IDL_TYPE_INTEGER(real_type).f_type != IDL_INTEGER_TYPE_LONG) { IDL_tree_error(method_tree, "target \"%s\" of [%s(%s)] attribute " "must be of %s type", referred_name, attr_name, referred_name, needed_type); return FALSE; } } } return TRUE; }
gboolean verify_attribute_declaration(IDL_tree attr_tree) { IDL_tree iface; IDL_tree ident; IDL_tree attr_type; gboolean scriptable_interface; /* We don't support attributes named IID, conflicts with static GetIID * member. The conflict is due to certain compilers (VC++) choosing a * different vtable order, placing GetIID at the beginning regardless * of it's placement */ if (strcmp( IDL_IDENT( IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data).str, "IID") == 0) { IDL_tree_error(attr_tree, "Attributes named IID not supported, causes vtable " "ordering problems"); return FALSE; } /* * Verify that we've been called on an interface, and decide if the * interface was marked [scriptable]. */ if (IDL_NODE_UP(attr_tree) && IDL_NODE_UP(IDL_NODE_UP(attr_tree)) && IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(attr_tree))) == IDLN_INTERFACE) { scriptable_interface = (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable") != NULL); } else { IDL_tree_error(attr_tree, "verify_attribute_declaration called on a non-interface?"); return FALSE; } /* * Grab the first of the list of idents and hope that it'll * say scriptable or no. */ ident = IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data; /* * If the interface isn't scriptable, or the attribute is marked noscript, * there's no need to check. */ if (!scriptable_interface || IDL_tree_property_get(ident, "noscript") != NULL) return TRUE; /* * If it should be scriptable, check that the type is non-native. nsid, * domstring, utf8string, cstring, astring are exempted. */ attr_type = IDL_ATTR_DCL(attr_tree).param_type_spec; if (attr_type != NULL) { if (UP_IS_NATIVE(attr_type) && IDL_tree_property_get(attr_type, "nsid") == NULL && IDL_tree_property_get(attr_type, "domstring") == NULL && IDL_tree_property_get(attr_type, "utf8string") == NULL && IDL_tree_property_get(attr_type, "cstring") == NULL && IDL_tree_property_get(attr_type, "astring") == NULL) { IDL_tree_error(attr_tree, "attributes in [scriptable] interfaces that are " "non-scriptable because they refer to native " "types must be marked [noscript]\n"); return FALSE; } /* * We currently don't support properties of type nsid that aren't * pointers or references, unless they are marked [notxpcom} and * must be read-only */ if ((IDL_tree_property_get(ident, "notxpcom") == NULL || !(IDL_ATTR_DCL(attr_tree).f_readonly)) && IDL_tree_property_get(attr_type,"nsid") != NULL && IDL_tree_property_get(attr_type,"ptr") == NULL && IDL_tree_property_get(attr_type,"ref") == NULL) { IDL_tree_error(attr_tree, "Feature not currently supported: " "attributes with a type of nsid must be marked " "either [ptr] or [ref], or " "else must be marked [notxpcom] " "and must be read-only\n"); return FALSE; } /* * Run additional error checks on the attribute type if targetting an * older version of XPConnect. */ if (!verify_type_fits_version(attr_type, attr_tree)) return FALSE; } if (IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).next != NULL) { IDL_tree_error(attr_tree, "multiple attributes in a single declaration is not supported\n"); return FALSE; } 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; IDL_tree real_type; gboolean success; gboolean isshort = FALSE; 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; /* * 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(real_type)); if (success) { /* * We aren't successful yet, we know it's an integer, but what *kind* * of integer? */ switch(IDL_TYPE_INTEGER(real_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; } } else { IDL_tree_error(state->tree, "const declaration \'%s\' must be of type short or long", name); return FALSE; } /* if (doc_comments != NULL) { fputs(" ", state->file); printlist(state->file, doc_comments); } */ if (success) { /* Since Java does not have any concept of 'unsigned short', we need * to check that the value is in the proper range. If not, promote * it to an 'int'. */ int value = (int) IDL_INTEGER(declaration->const_exp).value; if (isshort && (value < -32768 || value > 32767)) isshort = FALSE; fputc('\n', state->file); xpidl_write_comment(state, 4); /* write_comment(state); */ fprintf(state->file, " public static final %s %s = %d;\n", (isshort ? "short" : "int"), subscriptIdentifier(state, (char*) 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; }