/* * 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; }
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; }