diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c | |
parent | Initial commit. (diff) | |
download | virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.tar.xz virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c')
-rw-r--r-- | src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c | 851 |
1 files changed, 851 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c new file mode 100644 index 00000000..25d04212 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c @@ -0,0 +1,851 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Utility functions called by various backends. + */ + +#include "xpidl.h" + +/* XXXbe static */ char OOM[] = "ERROR: out of memory\n"; + +void * +xpidl_malloc(size_t nbytes) +{ + void *p = malloc(nbytes); + if (!p) { + fputs(OOM, stderr); + exit(1); + } + return p; +} + +char * +xpidl_strdup(const char *s) +{ +#if defined(XP_MAC) || defined(XP_SOLARIS) /* bird: dunno why this is required, but whatever*/ + size_t len = strlen(s); + char *ns = malloc(len + 1); + if (ns) + memcpy(ns, s, len + 1); +#else + char *ns = strdup(s); +#endif + if (!ns) { + fputs(OOM, stderr); + exit(1); + } + return ns; +} + +void +xpidl_write_comment(TreeState *state, int indent) +{ + fprintf(state->file, "%*s/* ", indent, ""); + IDL_tree_to_IDL(state->tree, state->ns, state->file, + IDLF_OUTPUT_NO_NEWLINES | + IDLF_OUTPUT_NO_QUALIFY_IDENTS | + IDLF_OUTPUT_PROPERTIES); + fputs(" */\n", state->file); +} + +/* + * Print an iid to into a supplied buffer; the buffer should be at least + * UUID_LENGTH bytes. + */ +gboolean +xpidl_sprint_iid(nsID *id, char iidbuf[]) +{ + int printed; + + printed = sprintf(iidbuf, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (PRUint32) id->m0, (PRUint32) id->m1,(PRUint32) id->m2, + (PRUint32) id->m3[0], (PRUint32) id->m3[1], + (PRUint32) id->m3[2], (PRUint32) id->m3[3], + (PRUint32) id->m3[4], (PRUint32) id->m3[5], + (PRUint32) id->m3[6], (PRUint32) id->m3[7]); + +#ifdef SPRINTF_RETURNS_STRING + return (printed && strlen((char *)printed) == 36); +#else + return (printed == 36); +#endif +} + +/* We only parse the {}-less format. */ +static const char nsIDFmt2[] = + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; + +/* + * Parse a uuid string into an nsID struct. We cannot link against libxpcom, + * so we re-implement nsID::Parse here. + */ +gboolean +xpidl_parse_iid(nsID *id, const char *str) +{ + PRInt32 count = 0; + PRInt32 n1, n2, n3[8]; + PRInt32 n0, i; + + XPT_ASSERT(str != NULL); + + if (strlen(str) != 36) { + return FALSE; + } + +#ifdef DEBUG_shaver_iid + fprintf(stderr, "parsing iid %s\n", str); +#endif + + count = sscanf(str, nsIDFmt2, + &n0, &n1, &n2, + &n3[0],&n3[1],&n3[2],&n3[3], + &n3[4],&n3[5],&n3[6],&n3[7]); + + id->m0 = (PRInt32) n0; + id->m1 = (PRInt16) n1; + id->m2 = (PRInt16) n2; + for (i = 0; i < 8; i++) { + id->m3[i] = (PRInt8) n3[i]; + } + +#ifdef DEBUG_shaver_iid + if (count == 11) { + fprintf(stderr, "IID parsed to "); + print_IID(id, stderr); + fputs("\n", stderr); + } +#endif + return (gboolean)(count == 11); +} + +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; +} + + + +/* + * 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; +} + +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; +} + +/* + * Find the underlying type of an identifier typedef. + * + * All the needed tree-walking seems pretty shaky; isn't there something in + * libIDL to automate this? + */ +IDL_tree /* IDL_TYPE_DCL */ +find_underlying_type(IDL_tree typedef_ident) +{ + IDL_tree up; + + if (typedef_ident == NULL || IDL_NODE_TYPE(typedef_ident) != IDLN_IDENT) + return NULL; + + up = IDL_NODE_UP(typedef_ident); + if (up == NULL || IDL_NODE_TYPE(up) != IDLN_LIST) + return NULL; + up = IDL_NODE_UP(up); + if (up == NULL || IDL_NODE_TYPE(up) != IDLN_TYPE_DCL) + return NULL; + + return IDL_TYPE_DCL(up).type_spec; +} + +static IDL_tree /* IDL_PARAM_DCL */ +find_named_parameter(IDL_tree method_tree, const char *param_name) +{ + IDL_tree iter; + for (iter = IDL_OP_DCL(method_tree).parameter_dcls; iter; + iter = IDL_LIST(iter).next) + { + IDL_tree param = IDL_LIST(iter).data; + IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator; + const char *current_name = IDL_IDENT(simple_decl).str; + if (strcmp(current_name, param_name) == 0) + return param; + } + return NULL; +} + +typedef enum ParamAttrType { + IID_IS, + LENGTH_IS, + SIZE_IS +} ParamAttrType; + +/* + * 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; +} + + +/* + * 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; +} + +/* + * 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; +} + +/* + * Print a GSList as char strings to a file. + */ +void +printlist(FILE *outfile, GSList *slist) +{ + guint i; + guint len = g_slist_length(slist); + + for(i = 0; i < len; i++) { + fprintf(outfile, + "%s\n", (char *)g_slist_nth_data(slist, i)); + } +} + +void +xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data) +{ + IDL_tree_func_data tfd; + + while (p) { + struct _IDL_LIST *list = &IDL_LIST(p); + tfd.tree = list->data; + if (!foreach(&tfd, user_data)) + return; + p = list->next; + } +} + +/* + * Verify that the interface declaration is correct + */ +gboolean +verify_interface_declaration(IDL_tree interface_tree) +{ + IDL_tree iter; + /* + * If we have the scriptable attribute then make sure all of our direct + * parents have it as well. + * NOTE: We don't recurse since all interfaces will fall through here + */ + if (IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident, + "scriptable")) { + for (iter = IDL_INTERFACE(interface_tree).inheritance_spec; iter; + iter = IDL_LIST(iter).next) { + if (IDL_tree_property_get( + IDL_INTERFACE(iter).ident, "scriptable") == 0) { + XPIDL_WARNING((interface_tree,IDL_WARNING1, + "%s is scriptable but inherits from the non-scriptable interface %s\n", + IDL_IDENT(IDL_INTERFACE(interface_tree).ident).str, + IDL_IDENT(IDL_INTERFACE(iter).ident).str)); + } + } + } + return TRUE; +} + +/* + * Return a pointer to the start of the base filename of path + */ +char * +xpidl_basename(const char * path) +{ + char * result = g_path_get_basename(path); + /* + *If this is windows then we'll handle either / or \ as a separator + * g_basename only handles \ for windows + */ +#if defined(XP_WIN32) +# error adapt regarding g_basename() vs. g_path_get_basename()! + const char * slash = strrchr(path, '/'); + /* If we found a slash and its after the current default OS separator */ + if (slash != NULL && (slash > result)) + result = slash + 1; +#endif + return result; +} |