write_indent(state->file); fprintf(state->file, "virtual ~%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);
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);    write_indent(state->file);    fprintf(state->file, "virtual ~%s();\n", classNameImpl);    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 FAILout:    if (classNameUpper)        free(classNameUpper);    if (classNameImpl)        free(classNameImpl);    return ok;}