Example #1
0
int XmlToKross::start()
{
    inclass=0;
    while (!xml.atEnd())
    {
        QXmlStreamReader::TokenType t=xml.readNext(); 
        QString str;
        
        switch(t)
        {
            case QXmlStreamReader::Invalid:
                qDebug() << "invalid token!" << xml.errorString() << endl;
                break;
            case QXmlStreamReader::StartDocument:
                writeDocument();
                break;
            case QXmlStreamReader::StartElement:
//                         qDebug() << "Element " << xml.name().toString() << endl;
                str=xml.name().toString();
                if(str=="Class")
                {
                    inclass++;
                    if(inclass==1) writeClass(xml.attributes().value(QString(), "name").toString(), QString(), QList<QStringList>());
                }
                else if(str=="Function")
                {
                    QString funcname=xml.attributes().value(QString(), "name").toString();
                    QString rettype=xml.attributes().value(QString(), "type_name").toString();
                    
                    bool isConst=xml.attributes().value(QString(), "constant").toString()==QChar('1');
                    bool isVirtual=xml.attributes().value(QString(), "virtual").toString()==QChar('1');
                    currentMethod=method();
                    currentMethod.access=xml.attributes().value(QString(), "access").toString();
                    currentMethod.funcname=funcname;
                    currentMethod.returnType=rettype;
                    currentMethod.isConst=isConst;
                    currentMethod.isVirtual=isVirtual;
                    if(!definedClasses.isEmpty() && ( funcname==definedClasses.last() || funcname=='~'+definedClasses.last() ) )
                        currentMethod.access="constructor";
                }
                else if(str=="Argument")
                {
                    method::argument arg;
                    arg.name=xml.attributes().value(QString(), "name").toString();
                    arg.type=xml.attributes().value(QString(), "type_name").toString();
                    arg.def=xml.attributes().value(QString(), "defaultvalue").toString();
                    QString context=xml.attributes().value(QString(), "context").toString();
                    if(!arg.def.isEmpty() && arg.type.startsWith(context))
                        arg.def.prepend(context+"::");
                    
                    currentMethod.args.append(arg);
                }
                else if(str=="Namespace")
                {
                    QString name=xml.attributes().value(QString(), "name").toString();
                    
                    qDebug() << "entering to namespace " << name << inNamespace;
                    if(inNamespace!=name)
                    {
                        if(!inNamespace.isEmpty())
                            inNamespace.append("::");
                        inNamespace.append(name);
                        writeNamespace(name);
                        qDebug() << "current status" << inNamespace;
                    }
                }
                else if(str=="Variable" && inclass==1 &&
                    xml.attributes().value(QString(), "access").toString()=="public")
                {
                    writeVariable(xml.attributes().value(QString(), "name").toString(),
                                    xml.attributes().value(QString(), "type_name").toString(), xml.attributes().value(QString(), "type_constant").toString()=="1");
                }
                else if(str=="Enum")
                {
                    flags.clear();
                    flags.append(xml.attributes().value(QString(), "name").toString());
                }
                else if(str=="Enumerator")
                    flags.append(xml.attributes().value(QString(), "name").toString());
                break;
            case QXmlStreamReader::EndDocument:
                writeEndDocument();
                break;
            case QXmlStreamReader::EndElement:
                str=xml.name().toString();
                if(str=="Class")
                {
                    if(inclass==1) writeEndClass();
                    inclass--;
                }
                else if(str=="Function" && currentMethod.access=="public" && inclass==1)
                    writeEndFunction(currentMethod);
                else if(str=="Enum")
                    writeEndEnum(flags);
                else if(str=="Namespace")
                {
                    inNamespace.resize(inNamespace.lastIndexOf("::"));
                }
                break;
            default:
                break;
        }
    }
    if (xml.error())
    {
        qDebug() << "error!" << xml.errorString();
        return 2;
    }
    return 0;
}
Example #2
0
int
main(int argc,
     char** argv)
{
    if (argc != 6) {
        std::cout << "This program takes in input glad.h and outputs the include and implementation files for OSMesa OpenGL function and regular OpenGL functions." << std::endl;
        std::cout << "Usage: generateGLIncludes <glad.h path> <output dir path> <namespace name> <baseFileName> <inlcude glad debug symbols>" << std::endl;
        std::cout << "Example: generateGLIncludes /Users/alexandre/development/Natron/Global/gladRel/include/glad/glad.h /Users/alexandre/development/Natron/Engine Natron OSGLFunctions 1" << std::endl;

        return 1;
    }

    QFile f(argv[1]);
    if ( !f.open(QIODevice::ReadOnly) ) {
        std::cout << "Could not open " << argv[1] << std::endl;

        return 1;
    }

    // Check that output path exists

    QDir outputDir(argv[2]);
    if ( !outputDir.exists() ) {
        std::cout << argv[2] << " does not seem to be a valid directory" << std::endl;

        return 1;
    }

    QString namespaceName(argv[3]);
    QString baseFilename(argv[4]);
    bool supportGladDebug;
    {
        QString supportDebugSymbolsStr(argv[5]);
        supportGladDebug = (bool)supportDebugSymbolsStr.toInt();
    }
    QString absoluteDirPath = outputDir.absolutePath();
    QString outputHeaderFilename = absoluteDirPath + "/" + baseFilename + ".h";
    QFile of_header(outputHeaderFilename);
    if ( !of_header.open(QIODevice::WriteOnly) ) {
        std::cout << "Could not open " << outputHeaderFilename.toStdString() << std::endl;

        return 1;
    }
    QTextStream ots_header(&of_header);
    QTextStream its(&f);
    QString definesStr;

    std::list<FunctionSignature> signatures;
    QString functionTypedefsStr;
    QString prevLine;
    while ( !its.atEnd() ) {
        // Read each line of glad.h
        QString line = its.readLine();

        {
            // Search for a define
            QString toFind = "#define GL_";
            int found = line.indexOf(toFind);
            if (found != -1) {
                definesStr += line;
                definesStr += "\n";
            }
        }

        // Search for a function
        QString typedefToken("typedef ");
        QString pfnToken("(APIENTRYP PFNGL");
        int foundFuncDef = line.indexOf(typedefToken);
        int foundPNFToken = line.indexOf(pfnToken);
        if ( (foundFuncDef != -1) && (foundPNFToken != -1) ) {
            int pos = foundPNFToken + pfnToken.size();
            int foundFirstEndParenthesis = line.indexOf(')', pos);
            assert(foundFirstEndParenthesis != -1);


            FunctionSignature signature;
            QString lastFuncNameCaps = line.mid(pos, foundFirstEndParenthesis - pos);
            signature.signature = line.mid(foundFirstEndParenthesis);
            // "near" and "far" are defined as macros in windows.h
            signature.signature.replace("GLdouble near, GLdouble far", "GLdouble nearVal, GLdouble farVal");

            signature.returnType = line.mid( foundFuncDef + typedefToken.size(), foundPNFToken - 1 - ( foundFuncDef + typedefToken.size() ) );
            QString funcTypeDefStr = "typedef ";
            funcTypeDefStr += signature.returnType;
            funcTypeDefStr += " (*PFNGL";
            funcTypeDefStr += lastFuncNameCaps;
            funcTypeDefStr += signature.signature;
            funcTypeDefStr += "\n";
            functionTypedefsStr += funcTypeDefStr;

            // Remove the extraneous ; at the end of the signature
            // Also remove the prepending )
            signature.signature.remove(0, 1);
            signature.signature.remove(signature.signature.size() - 1, 1);

            signature.funcPNType = "PFNGL";
            signature.funcPNType += lastFuncNameCaps;

            // extract parameters
            {
                int i = 1; // start after the leading (
                while ( i < signature.signature.size() ) {
                    QString param;
                    while ( signature.signature[i] != QChar(',') && signature.signature[i] != QChar(')') ) {
                        param.append(signature.signature[i]);
                        ++i;
                    }

                    // Now only keep the name of the parameter
                    {
                        int j = param.size() - 1;
                        while ( j >= 0 && param[j].isLetterOrNumber() ) {
                            --j;
                        }
                        param = param.mid(j + 1);
                    }
                    signature.parameters.append(param);

                    assert( signature.signature[i] == QChar(',') || signature.signature[i] == QChar(')') );
                    ++i; // bypass last character

                    if ( signature.signature[i] == QChar(')') ) {
                        break;
                    }
                }
            }

            // we caught a function typedef before, we expect to read the following #define glXxxx function with the appropriate case
            // in release glad.h, the next line is of the type GLAPI PFNGLCOLOR4FVPROC glad_glColor4fv;
            // the line after that is the one we want #define glColor4fv glad_glColor4fv
            line = its.readLine();
            assert( !its.atEnd() );
            line = its.readLine();

            QString toFind("#define gl");
            int foundDefine = line.indexOf(toFind);
            if (foundDefine == -1) {
                std::cout << "Parser failed to find #define glXXX statement 2 lines after a function typedef, make sure that you are running this program against a release version of glad.h" << std::endl;

                return 1;
            }

            // Check that this is the same symbol
            // Remove the PROC at the end of the func def
            lastFuncNameCaps.remove("PROC");
            int checkIndex = toFind.size();
            QString symbolStart = line.mid(checkIndex);
            assert( symbolStart.startsWith(lastFuncNameCaps, Qt::CaseInsensitive) );

            {
                int i = 8; // start on the g
                //extract the function name
                while ( i < line.size() && line.at(i) != QChar(' ') ) {
                    signature.funcName.push_back( line.at(i) );
                    ++i;
                }
            }

            signatures.push_back(signature);
        } // if (foundFuncDef != -1 && foundPNFToken != -1) {

        prevLine = line;
    }

    writeHeader(ots_header);
    writePODs(ots_header);
    ots_header <<
        definesStr << "\n"
        "\n";
    ots_header <<
        functionTypedefsStr << "\n"
        "\n";
    writeStartClass(namespaceName, ots_header);

    // Define the singleton
    ots_header <<
        "    static OSGLFunctions<USEOPENGL>& getInstance()\n"
        "    {\n"
        "        static OSGLFunctions<USEOPENGL> instance;\n"
        "\n"
        "        return instance;\n"
        "    }\n"
        "\n"
        "    // load function, implemented in _gl.h and _mesa.h\n"
        "    void load_functions();\n"
        "\n"
        "    // private constructor\n"
        "    OSGLFunctions() { load_functions(); }\n"
        "\n";

    // Declare member functions
    for (std::list<FunctionSignature>::iterator it = signatures.begin(); it != signatures.end(); ++it) {
        ots_header << "    " << it->funcPNType << " _" << it->funcName << ";\n";
    }

    ots_header <<
        "\n";

    ots_header <<
        "public:\n"
        "\n";


    ots_header <<
        "    // static non MT-safe load function that must be called once to initialize functions\n"
        "    static void load()\n"
        "    {\n"
        "        (void)getInstance();\n"
        "    }\n"
        "\n"
        "    static bool isGPU()\n"
        "    {\n"
        "        return USEOPENGL;\n"
        "    }\n";

    for (std::list<FunctionSignature>::iterator it = signatures.begin(); it != signatures.end(); ++it) {
        QString lineStart = "    static " +  it->returnType + " " + it->funcName;
        QString indentedSig = it->signature;
        indentedSig.replace( ", ", ",\n" + QString(lineStart.size() + 1, ' ') );
        ots_header << "\n" <<
            lineStart << indentedSig << "\n"
            "    {\n";
        if (it->returnType == "void") {
            ots_header << "        ";
        } else {
            ots_header << "        return ";
        }
        ots_header << "getInstance()._" << it->funcName << "(";
        QStringList::const_iterator next = it->parameters.begin();
        if ( !it->parameters.isEmpty() ) {
            ++next;
        }
        for (QStringList::const_iterator it2 = it->parameters.begin(); it2 != it->parameters.end(); ++it2) {
            ots_header << *it2;
            if ( next != it->parameters.end() ) {
                ots_header << ", ";
                ++next;
            }
        }

        ots_header <<
            ");\n"
            "    }\n";
    }
    writeEndClass(namespaceName, ots_header);

    writeFooter(ots_header);

    writeImplementationCppFile(namespaceName, baseFilename, signatures, absoluteDirPath, "gl", true, supportGladDebug);
    writeImplementationCppFile(namespaceName, baseFilename, signatures, absoluteDirPath, "mesa", false, supportGladDebug);


    return 0;
} // main