Exemplo n.º 1
2
/*
 * 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;
}
static gboolean
write_type(IDL_tree type_tree, gboolean is_out, FILE *outfile)
{
    if (!type_tree) {
        fputs("void", outfile);
        return TRUE;
    }

    switch (IDL_NODE_TYPE(type_tree)) {
      case IDLN_TYPE_INTEGER: {
        gboolean sign = IDL_TYPE_INTEGER(type_tree).f_signed;
        switch (IDL_TYPE_INTEGER(type_tree).f_type) {
          case IDL_INTEGER_TYPE_SHORT:
            fputs(sign ? "PRInt16" : "PRUint16", outfile);
            break;
          case IDL_INTEGER_TYPE_LONG:
            fputs(sign ? "PRInt32" : "PRUint32", outfile);
            break;
          case IDL_INTEGER_TYPE_LONGLONG:
            fputs(sign ? "PRInt64" : "PRUint64", outfile);
            break;
          default:
            g_error("Unknown integer type %d\n",
                    IDL_TYPE_INTEGER(type_tree).f_type);
            return FALSE;
        }
        break;
      }
      case IDLN_TYPE_CHAR:
        fputs("char", outfile);
        break;
      case IDLN_TYPE_WIDE_CHAR:
        fputs("PRUnichar", outfile); /* wchar_t? */
        break;
      case IDLN_TYPE_WIDE_STRING:
        fputs("PRUnichar *", outfile);
        break;
      case IDLN_TYPE_STRING:
        fputs("char *", outfile);
        break;
      case IDLN_TYPE_BOOLEAN:
        fputs("PRBool", outfile);
        break;
      case IDLN_TYPE_OCTET:
        fputs("PRUint8", outfile);
        break;
      case IDLN_TYPE_FLOAT:
        switch (IDL_TYPE_FLOAT(type_tree).f_type) {
          case IDL_FLOAT_TYPE_FLOAT:
            fputs("float", outfile);
            break;
          case IDL_FLOAT_TYPE_DOUBLE:
            fputs("double", outfile);
            break;
          /* XXX 'long double' just ignored, or what? */
          default:
            fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
            break;
        }
        break;
      case IDLN_IDENT:
        if (UP_IS_NATIVE(type_tree)) {
            if (IDL_tree_property_get(type_tree, "domstring") ||
                IDL_tree_property_get(type_tree, "astring")) {
                fputs("nsAString", outfile);
            } else if (IDL_tree_property_get(type_tree, "utf8string")) {
                fputs("nsACString", outfile);
            } else if (IDL_tree_property_get(type_tree, "cstring")) {
                fputs("nsACString", outfile);
            } else {
                fputs(IDL_NATIVE(IDL_NODE_UP(type_tree)).user_type, outfile);
            }
            if (IDL_tree_property_get(type_tree, "ptr")) {
                fputs(" *", outfile);
            } else if (IDL_tree_property_get(type_tree, "ref")) {
                fputs(" &", outfile);
            }
        } else {
            fputs(IDL_IDENT(type_tree).str, outfile);
        }
        if (UP_IS_AGGREGATE(type_tree))
            fputs(" *", outfile);
        break;
      default:
        fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
        break;
    }
    return TRUE;
}
Exemplo n.º 3
0
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;
}