"    JSObject *obj = JS_NewObject(cx, &foo_class, 0, 0);\n"
"    JSObject *obj = JS_NewObject(cx, &%s_class, 0, 0);\n"
stub_interface(TreeState *state){    IDL_tree iface = state->tree;    const char *className;    struct stub_private *priv, *save_priv;    gboolean ok;    className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;    priv = xpidl_malloc(sizeof *priv);    memset(priv, 0, sizeof *priv);    priv->iface = iface;    save_priv = state->priv;    state->priv = priv;    state->tree = IDL_INTERFACE(iface).body;    ok = !state->tree || xpidl_process_node(state);    if (ok) {        gboolean allreadonly = TRUE;        unsigned i;        if (priv->funcs) {            fprintf(state->file,                    "\nstatic JSFunctionSpec %s_funcs[] = {\n",                    className);            for (i = 0; i < priv->nfuncs; i++) {                IDL_tree method = priv->funcs[i];                unsigned nargs = 0;                IDL_tree iter;                for (iter = IDL_OP_DCL(method).parameter_dcls;                     iter;                     iter = IDL_LIST(iter).next) {                     nargs++;                }                fprintf(state->file, "  {\"%s\", %s_%s, %u},\n",                        IDL_IDENT(IDL_OP_DCL(method).ident).str,                        className,                        IDL_IDENT(IDL_OP_DCL(method).ident).str,                        nargs);            }            fputs("  {0}\n};\n", state->file);        }        if (priv->const_dbls) {            fprintf(state->file,                    "\nstatic JSConstDoubleSpec %s_const_dbls[] = {\n",                    className);            for (i = 0; i < priv->nconst_dbls; i++) {                fprintf(state->file, "  {%g, \"%s\"},\n", 0., "d'oh!");            }            fputs("  {0}\n};\n", state->file);        }        if (priv->props) {            /* XXXbe check for tinyid overflow */            fprintf(state->file,                    "\nstatic JSPropertySpec %s_props[] = {\n",                    className);            for (i = 0; i < priv->nprops; i++) {                IDL_tree attr = priv->props[i];                if (!IDL_ATTR_DCL(attr).f_readonly)                    allreadonly = FALSE;                fprintf(state->file, "  {\"%s\", %d",                  IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(attr).simple_declarations)                            .data).str, -1 - (int)i);                if (IDL_ATTR_DCL(attr).f_readonly)                    fputs(", JSPROP_READONLY", state->file);                fputs("},\n", state->file);            }            fputs("  {0}\n};\n", state->file);            /* Emit GetProperty. */            if (!emit_property_op(state, className, 'G'))                return FALSE;            /* Emit SetProperty. */            if (!allreadonly && !emit_property_op(state, className, 'S'))                return FALSE;        }        /* Emit a finalizer. */        fprintf(state->file,                "\nstatic void\n"                "%s_Finalize(JSContext *cx, JSObject *obj)\n"                "{\n"                "  %s *priv = (%s *)JS_GetPrivate(cx, obj);\n"                "  if (!priv)\n"                "    return;\n"                "  JSObject *globj = JS_GetGlobalObject(cx);\n"                "  if (globj)\n"                "    (void) JS_DeleteElement(cx, globj, (jsint)priv >> 1);\n"                "  NS_RELEASE(priv);\n"                "}\n",                className, className, className);        /* Emit a constructor. */        fprintf(state->file,                "\nstatic JSBool\n"                "%s_ctor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,"                       " jsval *rval)\n"                "{\n"                "  return JS_TRUE;\n"                "}\n",                className);        /* Emit an initialized JSClass struct. */        fprintf(state->file,                "\nstatic JSClass %s_class = {\n"                "  \"%s\",\n"                "  JSCLASS_HAS_PRIVATE,\n"                "  JS_PropertyStub, JS_PropertyStub, ",                className, className);        if (priv->props) {            fprintf(state->file, "%s_GetProperty, ", className);            if (!allreadonly)                fprintf(state->file, "%s_SetProperty", className);            else                fputs("JS_PropertyStub", state->file);        } else {            fputs("JS_PropertyStub, JS_PropertyStub",                  state->file);        }        fputs(",\n  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, ",              state->file);        fprintf(state->file, "%s_Finalize\n};\n", className);        /* Emit a InitJSClass static method. */        fprintf(state->file,                "\nJSObject *\n"                "%s::InitJSClass(JSContext *cx)\n"                "{\n"                "  JSObject *globj = JS_GetGlobalObject(cx);\n"                "  if (!globj)\n"                "    return 0;\n"                "  JSObject *proto = JS_InitClass(cx, globj, 0, &%s_class, %s_ctor, 0,\n",                className, className, className);        fputs(  "                                 ",                state->file);        if (priv->props)            fprintf(state->file, "%s_props", className);        else            fputc('0', state->file);        fputs(", ", state->file);        if (priv->funcs)            fprintf(state->file, "%s_funcs", className);        else            fputc('0', state->file);        fputs(  ", 0, 0);\n", state->file);        if (priv->const_dbls) {            fprintf(state->file,                    "  if (!proto)\n"                    "    return 0;\n"                    "  JSObject *ctor = JS_GetConstructor(cx, proto);\n"                    "  if (!ctor || !JS_DefineConstDoubles(cx, ctor, &%s_const_dbls))\n"                    "    return 0;\n",                    className);        }        fputs(  "  return proto;\n"                "}\n",                state->file);        /* Emit a GetJSObject static method. */        fprintf(state->file,                "\nJSObject *\n"                "%s::GetJSObject(JSContext *cx, %s *priv)\n"                "{\n"                "  JSObject *globj = JS_GetGlobalObject(cx);\n"                "  if (!globj)\n"                "    return 0;\n"                "  if (!JS_LookupElement(cx, globj, (jsint)priv >> 1, &v))\n"                "    return 0;\n"                "  if (JSVAL_IS_VOID(v)) {\n"                "    JSObject *obj = JS_NewObject(cx, &foo_class, 0, 0);\n"                "    if (!obj || !JS_SetPrivate(cx, obj, priv))\n"                "      return 0;\n"                "    NS_ADDREF(priv);\n"                "    v = PRIVATE_TO_JSVAL(obj);\n"                "    if (!JS_DefineElement(cx, globj, (jsint)priv >> 1, v, 0, 0,\n"                "                          JSPROP_READONLY | JSPROP_PERMANENT)) {\n"                "      return 0;\n"                "    }\n"                "  }\n"                "  return (JSObject *)JSVAL_TO_PRIVATE(v);\n"                "}\n",                className, className);    }    /* Clean up whether or not there were errors. */    state->priv = save_priv;    free_stub_private(priv);    return ok;}