static void GenClassHeader()

in Unix/gen/gen.cpp [2925:3250]


static void GenClassHeader(
    Parser& parser, 
    const MI_ClassDecl* cd,
    set<string>& classIdentifiers)
{
    const string alias = AliasOf(cd->name);

    // Refuse to generate same class more than once.

    if (generated_headers.find(cd->name) != generated_headers.end())
        return;

    generated_headers.insert(cd->name);

    // Find direct dependencies of this class.
    vector<string> deps;
    FindDirectDependencies(cd, deps);

    // Recurse on dependencies.
    for (size_t i = 0; i < deps.size(); i++)
    {
        const MI_ClassDecl* tcd = parser.findClassDecl(deps[i].c_str());

        if (!tcd)
            err(ID_UNKNOWN_CLASS, "unknown class: %s", deps[i].c_str());

        GenClassHeader(parser, tcd, classIdentifiers);
    }

    // Open class header file.
    string path = ExpandPath(alias + ".h");
    Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());

    FILE* os = File_Open(path.c_str(), "w");
    
    if (!os)
        err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());

    GenStatikGenLine(os);

    // Put comment header.
    PutCommentBox(os, WARNING);

    // Prevent multiple inclusion.
    putl(os, "#ifndef _%s_h", alias.c_str());
    putl(os, "#define _%s_h", alias.c_str());
    nl(os);

    // Include <MI.h>
    putl(os, "#include <MI.h>");

    // Generate includes for direct dependencies.
    for (size_t i = 0; i < deps.size(); i++)
    {
        string al = AliasOf(deps[i]);
        putl(os, "#include \"%s.h\"", al.c_str());
    }

    nl(os);

    // Put comment box for the class structure. List the key names for this
    // class.
    {
        putl(os, "/*");
        PutRule(os);
        putl(os, "**");
        putl(os, "** %s [%s]", alias.c_str(), cd->name);
        putl(os, "**");
        putl(os, "** Keys:");

        for (size_t i = 0; i < cd->numProperties; i++)
        {
            const MI_PropertyDecl* pd = cd->properties[i];

            if (pd->flags & MI_FLAG_KEY)
                putl(os, "**    %s", pd->name);
        }

        putl(os, "**");
        PutRule(os);
        putl(os, "*/");
        nl(os);
    }

    // Put class structure definition with all its properties.
    if (cd->superClass)
    {
        putl(os, "typedef struct _%s /* extends %s */", 
            alias.c_str(), cd->superClass);
    }
    else
    {
        putl(os, "typedef struct _%s", alias.c_str());
    }

    putl(os, "{");
    putl(os, "    MI_Instance __instance;");
    NameClassMap map;
    GenProperties(os, parser, cd, cd, map);
    putl(os, "}");
    putl(os, "%s;", alias.c_str());
    nl(os);

    // Generate a reference of this type (if not an association or indication).
#if 0
    if (!(cd->flags & MI_FLAG_ASSOCIATION || cd->flags & MI_FLAG_INDICATION))
#endif
    // Associations can be used as endpoints in other associations.
    {
        {
            const char T[] =
                "typedef struct _<ALIAS>_Ref\n"
                "{\n"
                "    <ALIAS>* value;\n"
                "    MI_Boolean exists;\n"
                "    MI_Uint8 flags;\n"
                "}\n"
                "<ALIAS>_Ref;\n"
                "\n"
                "typedef struct _<ALIAS>_ConstRef\n"
                "{\n"
                "    MI_CONST <ALIAS>* value;\n"
                "    MI_Boolean exists;\n"
                "    MI_Uint8 flags;\n"
                "}\n"
                "<ALIAS>_ConstRef;\n"
                "\n";

            string r = sub(T, "<ALIAS>", alias);
            puts(os, r);
        }
        {
            const char T[] =
                "typedef struct _<ALIAS>_Array\n"
                "{\n"
                "    struct _<ALIAS>** data;\n"
                "    MI_Uint32 size;\n"
                "}\n"
                "<ALIAS>_Array;\n"
                "\n"
                "typedef struct _<ALIAS>_ConstArray\n"
                "{\n"
                "    struct _<ALIAS> MI_CONST* MI_CONST* data;\n"
                "    MI_Uint32 size;\n"
                "}\n"
                "<ALIAS>_ConstArray;\n"
                "\n"
                "typedef struct _<ALIAS>_ArrayRef\n"
                "{\n"
                "    <ALIAS>_Array value;\n"
                "    MI_Boolean exists;\n"
                "    MI_Uint8 flags;\n"
                "}\n"
                "<ALIAS>_ArrayRef;\n"
                "\n"
                "typedef struct _<ALIAS>_ConstArrayRef\n"
                "{\n"
                "    <ALIAS>_ConstArray value;\n"
                "    MI_Boolean exists;\n"
                "    MI_Uint8 flags;\n"
                "}\n"
                "<ALIAS>_ConstArrayRef;\n"
                "\n";

            string r = sub(T, "<ALIAS>", alias);
            puts(os, r);
        }
    }

    // Generate an external reference to the class RTTI instance.
    if (s_options.cpp || !s_options.noProviders)
    {
        putl(os, "MI_EXTERN_C MI_CONST MI_ClassDecl %s_rtti;", alias.c_str());
        nl(os);
    }

    // Generate Instance function
    if (!s_options.noProviders)
        GenInstanceFunctions(os,cd);

    // Gen setters.
    {
        for (size_t i = 0; i < cd->numProperties; i++)
            GenSetter(os, cd, NULL, (MI_ParameterDecl*)cd->properties[i]);
    }

    // Put method definitions and setters for each method parameter.
    for (size_t i = 0; i < cd->numMethods; i++)
    {
        const MI_MethodDecl* md = cd->methods[i];
        GenParametersStruct(os, cd, md);

        // Generate convenience functions.
        if (!s_options.noProviders)
        {
            if (Strcasecmp(cd->name, md->propagator) == 0 ||
                providerClasses.find(cd->name) != providerClasses.end())
            {
                GenMethodFunctions(os, cd, md);
            }
        }

        // Generate parameter setter for "MIReturn".
        if (!s_options.noProviders)
        {
            MI_ParameterDecl pd;
            memset(&pd, 0, sizeof(pd));
            pd.flags = MI_FLAG_PARAMETER|MI_FLAG_OUT;
            pd.name = (char*)"MIReturn";
            pd.type = md->returnType;
            pd.offset = sizeof(MI_Instance);
            pd.numQualifiers = md->numQualifiers;
            pd.qualifiers = md->qualifiers;
            GenSetter(os, cd, md, &pd);
        }

        if (!s_options.noProviders)
        {
            for (size_t j = 0; j < md->numParameters; j++)
            {
                const MI_ParameterDecl* pd = md->parameters[j];

                // Skip stream parameters:
                if (pd->flags & MI_FLAG_STREAM)
                    continue;

                GenSetter(os, cd, md, pd);
            }
        }
    }

    if (providerClasses.find(cd->name) != providerClasses.end())
    {

        // Write the intrinsic provider function prototypes.

        if (!s_options.noProviders)
        {
            PutCommentBox(os, alias + " provider function prototypes");
            nl(os);

            // Generate forward typedef for Self structure.
            putl(os,"/* The developer may optionally define this structure */");
            putl(os, "typedef struct _%s_Self %s_Self;\n", 
                alias.c_str(), alias.c_str());

            if (cd->flags & MI_FLAG_ASSOCIATION)
            {
                string r;

                if (CanGenerateAssocRoles(cd))
                {
                    if (s_options.association)
                        r = ASSOCIATION_PROVIDER_PROTOTYPES;
                    else
                    {
                        r = ROLE_PROVIDER_PROTOTYPES;
                        SubRoles(cd, r);
                    }
                }
                else
                    errRefPropCount(cd->name);

                r = sub(r, "<ALIAS>", alias);
                puts(os, r);
            }
            else if (cd->flags & MI_FLAG_INDICATION)
            {
                string r;
                r = INDICATION_PROVIDER_PROTOTYPES;
                r = sub(r, "<ALIAS>", alias);
                puts(os, r);
            }
            else
            {
                if (HasKeys(cd))
                {
                    string r = INSTANCE_PROVIDER_PROTOTYPES;
                    r = sub(r, "<ALIAS>", alias);
                    puts(os, r);
                }
                else
                {
                    string r = COMMON_PROVIDER_PROTOTYPES;
                    r = sub(r, "<ALIAS>", alias);
                    puts(os, r);
                }
            }
        }

        // Write the extrinsic provider function prototypes.
        if (!s_options.noProviders)
        {
            for (size_t i = 0; i < cd->numMethods; i++)
            {
                const MI_MethodDecl* md = cd->methods[i];
                string r = sub(EXTRINSIC_METHOD_PROTOTYPE, "<ALIAS>", alias);
                r = sub(r, "<METHOD>", md->name);
                puts(os, r);
            }
        }
    }

    // Generate the class identifier:
#if 0
    {
        char id[33];
        _MakeID(id);
        string classIdentifier = alias + "_" + id;
        classIdentifiers.insert(classIdentifier);
        putl(os, "#define %s\n", classIdentifier.c_str());
    }
#endif

    nl(os);

    // c++ part
    if (s_options.cpp)
        GenCppClassHeader(parser, cd, os);

    // End ifdef that Prevents multiple inclusion.
    putl(os, "#endif /* _%s_h */", alias.c_str());

    // Close file.
    fclose(os);
}