// Geometric Tools, Inc.
// http://www.geometrictools.com
// Copyright (c) 1998-2005.  All Rights Reserved
//
// The Wild Magic Library (WM3) source code is supplied under the terms of
// the license agreement
//     http://www.geometrictools.com/License/WildMagic3License.pdf
// and may not be copied or disclosed except in accordance with the terms
// of that agreement.

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;

//----------------------------------------------------------------------------
static void CreateOglExtensions ()
{
    const int iMaxLine = 4096;
    char* acLine = new char[iMaxLine];
    char* acTmp = new char[iMaxLine];
    char* pcResult;
    char* pcRetType;
    char* pcSignature;
    char* pcFunction;
    char* acFCopy;
    int i;

    FILE* pkHFile = fopen("Wm3OpenGLExtensions.h","wt");
    FILE* pkCFile = fopen("Wm3OpenGLExtensions.c","wt");

    // write the starting text in the H file
    FILE* pkIFile = fopen("OglExtHStart.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkHFile);
    }
    fclose(pkIFile);

    // write the starting text in the C file
    pkIFile = fopen("OglExtCStart.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkCFile);
    }
    fclose(pkIFile);

    std::vector<char*> kExtension;
    pkIFile = fopen("OglExt.txt","rt");
    while ( (pcResult = fgets(acLine,iMaxLine,pkIFile)) != 0 )
    {
        // skip blank lines
        while ( pcResult && acLine[0] != '{' )
            pcResult = fgets(acLine,iMaxLine,pkIFile);

        // get extension name
        assert( strlen(acLine) >= 5 && strncmp(acLine,"{ GL_",5) == 0 );
        char* acExtension = &acLine[2];
        char* pcEnd = strpbrk(acExtension," \t\n");
        assert( pcEnd );
        *pcEnd = 0;

        // save extension for initialization function
        char* acECopy = new char[strlen(acExtension)+1];
        strcpy(acECopy,acExtension);
        kExtension.push_back(acECopy);

        std::vector<char*> kFunction;
        acECopy = new char[strlen(acExtension)+1];
        strcpy(acECopy,acExtension);
        kFunction.push_back(acECopy);
        int iNumFunctions = 0;

        // start extension block in H file
        fputs("\n",pkHFile);
        fputs("/*--------------------------------------------------------------------------*/\n",pkHFile);
        sprintf(acTmp,"extern int Wm3Exists_%s;\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"extern int Wm3NumFunctions_%s;\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#ifndef %s\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#define %s\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#define WM3_DEFINED_%s\n",acExtension);
        fputs(acTmp,pkHFile);

        // start extension block in C file
        fputs("\n",pkCFile);
        fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);
        sprintf(acTmp,"int Wm3Exists_%s;\n",acExtension);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"int Wm3NumFunctions_%s;\n",acExtension);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"#ifdef WM3_DEFINED_%s\n",acExtension);
        fputs(acTmp,pkCFile);

        // get extension information
        bool bFirstDefine = true;
        bool bFirstTypedef = true;
        bool bFirstPrototype = true;
        while ( true )
        {
            pcResult = fgets(acLine,iMaxLine,pkIFile);
            assert( pcResult );

            if ( acLine[0] == '}' )
            {
                // end of extension block
                break;
            }

            assert( acLine[0] == '@' );

            switch ( acLine[1] )
            {
            case 'v':  // verbatim
                fputs(&acLine[3],pkHFile);
                break;

            case 'f':  // function pointer definition
                iNumFunctions++;

                // return type of function
                assert( acLine[3] != ' ');
                pcRetType = &acLine[3];

                // function name
                pcFunction = pcRetType;
                while ( *pcFunction != 'g' || *(pcFunction+1) != 'l' )
                {
                    pcFunction++;
                }
                pcFunction--;
                *pcFunction = 0;
                pcFunction++;

                // signature of function
                pcSignature = pcFunction;
                while ( *pcSignature != ' ' )
                {
                    pcSignature++;
                }
                *pcSignature = 0;
                pcSignature++;

                // H file information
                fputs("\n",pkHFile);
                sprintf(acTmp,"typedef %s (APIENTRY* pfn_%s) %s",
                    pcRetType,pcFunction,pcSignature);
                fputs(acTmp,pkHFile);
                sprintf(acTmp,"extern pfn_%s Wm3%s;\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkHFile);
                sprintf(acTmp,"#define %s Wm3%s\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkHFile);

                // C file information
                acFCopy = new char[strlen(pcFunction)+1];
                strcpy(acFCopy,pcFunction);
                kFunction.push_back(acFCopy);

                sprintf(acTmp,"pfn_%s Wm3%s = 0;\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkCFile);
                break;

            case 'p':  // function prototype (OpenGL 1.1)
                iNumFunctions++;

                // return type of function
                assert( acLine[3] != ' ');
                pcRetType = &acLine[3];

                // function name
                pcFunction = pcRetType;
                while ( *pcFunction != 'g' || *(pcFunction+1) != 'l' )
                {
                    pcFunction++;
                }
                pcFunction--;
                *pcFunction = 0;
                pcFunction++;

                // signature of function
                pcSignature = pcFunction;
                while ( *pcSignature != ' ' )
                {
                    pcSignature++;
                }
                *pcSignature = 0;
                pcSignature++;

                // H file information
                sprintf(acTmp,"WINGDIAPI %s APIENTRY %s %s",pcRetType,
                    pcFunction,pcSignature);
                fputs(acTmp,pkHFile);
                break;

            default:
                assert( false );
                break;
            }
        }

        // end of extension block in H file
        fputs("#endif\n",pkHFile);

        // end of extension block in C file
        if ( kFunction.size() > 1 )
            fputs("\n",pkCFile);

        sprintf(acTmp,"static void Init_%s ()\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("{\n",pkCFile);

        if ( kFunction.size() == 1 )
        {
            // all prototypes (GL_VERSION_1_1)
            sprintf(acTmp,"    Wm3NumFunctions_%s = %d;\n",kFunction[0],
                iNumFunctions);
            fputs(acTmp,pkCFile);

            sprintf(acTmp,"    Wm3Exists_%s = WM3_EXT_FULLY_EXISTS;\n",
                kFunction[0]);
            fputs(acTmp,pkCFile);
        }
        else
        {
            sprintf(acTmp,"    Wm3NumFunctions_%s = 0;\n\n",kFunction[0]);
            fputs(acTmp,pkCFile);
            for (i = 1; i <= iNumFunctions; i++)
            {
                sprintf(acTmp,
                    "    Wm3%s = (pfn_%s)GetFunctionPointer(\"%s\");\n",
                    kFunction[i],kFunction[i],kFunction[i]);
                fputs(acTmp,pkCFile);

                sprintf(acTmp,"    if ( Wm3%s )\n",kFunction[i]);
                fputs(acTmp,pkCFile);

                sprintf(acTmp,"        ++Wm3NumFunctions_%s;\n\n",
                    kFunction[0]);
                fputs(acTmp,pkCFile);
            }
            sprintf(acTmp,"    if ( Wm3NumFunctions_%s == %d )\n",
                kFunction[0],iNumFunctions);
            fputs(acTmp,pkCFile);
            sprintf(acTmp,"        Wm3Exists_%s = WM3_EXT_FULLY_EXISTS;\n",
                kFunction[0]);
            fputs(acTmp,pkCFile);
            fputs("    else\n",pkCFile);
            sprintf(acTmp,
                "        Wm3Exists_%s = WM3_EXT_PARTIALLY_EXISTS;\n",
                kFunction[0]);
            fputs(acTmp,pkCFile);
        }
        fputs("}\n",pkCFile);

        fputs("#else\n",pkCFile);

        sprintf(acTmp,"static void Init_%s ()\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("{\n",pkCFile);
        sprintf(acTmp,"    Wm3NumFunctions_%s = 0;\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"    Wm3Exists_%s = WM3_EXT_DOES_NOT_EXIST;\n",
            kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("}\n",pkCFile);

        fputs("#endif\n",pkCFile);

        for (i = 0; i < (int)kFunction.size(); i++)
            delete kFunction[i];
    }
    fclose(pkIFile);

    // initialization function
    fputs("\n",pkCFile);
    fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);
    fputs("void InitializeOpenGL ()\n",pkCFile);
    fputs("{\n",pkCFile);
    for (i = 0; i < (int)kExtension.size(); i++)
    {
        sprintf(acTmp,"    Init_%s();\n",kExtension[i]);
        fputs(acTmp,pkCFile);
    }
    fputs("}\n",pkCFile);
    fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);

    pkIFile = fopen("OglExtHFinal.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkHFile);
    }
    fclose(pkIFile);

    fclose(pkCFile);
    fclose(pkHFile);

    delete[] acTmp;
    delete[] acLine;
}
//----------------------------------------------------------------------------
static void CreateWglExtensions ()
{
    const int iMaxLine = 4096;
    char* acLine = new char[iMaxLine];
    char* acTmp = new char[iMaxLine];
    char* pcResult;
    char* pcRetType;
    char* pcSignature;
    char* pcFunction;
    char* acFCopy;
    int i;

    FILE* pkHFile = fopen("Wm3WglExtensions.h","wt");
    FILE* pkCFile = fopen("Wm3WglExtensions.c","wt");

    // write the starting text in the H file
    FILE* pkIFile = fopen("WglExtHStart.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkHFile);
    }
    fclose(pkIFile);

    // write the starting text in the C file
    pkIFile = fopen("WglExtCStart.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkCFile);
    }
    fclose(pkIFile);

    std::vector<char*> kExtension;
    pkIFile = fopen("WglExt.txt","rt");
    while ( (pcResult = fgets(acLine,iMaxLine,pkIFile)) != 0 )
    {
        // skip blank lines
        while ( pcResult && acLine[0] != '{' )
            pcResult = fgets(acLine,iMaxLine,pkIFile);

        // get extension name
        assert( strlen(acLine) >= 6 && strncmp(acLine,"{ WGL_",6) == 0 );
        char* acExtension = &acLine[2];
        char* pcEnd = strpbrk(acExtension," \t\n");
        assert( pcEnd );
        *pcEnd = 0;

        // save extension for initialization function
        char* acECopy = new char[strlen(acExtension)+1];
        strcpy(acECopy,acExtension);
        kExtension.push_back(acECopy);

        std::vector<char*> kFunction;
        acECopy = new char[strlen(acExtension)+1];
        strcpy(acECopy,acExtension);
        kFunction.push_back(acECopy);
        int iNumFunctions = 0;

        // start extension block in H file
        fputs("\n",pkHFile);
        fputs("/*--------------------------------------------------------------------------*/\n",pkHFile);
        sprintf(acTmp,"extern int Wm3Exists_%s;\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"extern int Wm3NumFunctions_%s;\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#ifndef %s\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#define %s\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#define WM3_DEFINED_%s\n",acExtension);
        fputs(acTmp,pkHFile);

        // start extension block in C file
        fputs("\n",pkCFile);
        fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);
        sprintf(acTmp,"int Wm3Exists_%s;\n",acExtension);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"int Wm3NumFunctions_%s;\n",acExtension);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"#ifdef WM3_DEFINED_%s\n",acExtension);
        fputs(acTmp,pkCFile);

        // get extension information
        bool bFirstDefine = true;
        bool bFirstTypedef = true;
        bool bFirstPrototype = true;
        while ( true )
        {
            pcResult = fgets(acLine,iMaxLine,pkIFile);
            assert( pcResult );

            if ( acLine[0] == '}' )
            {
                // end of extension block
                break;
            }

            assert( acLine[0] == '@' );

            switch ( acLine[1] )
            {
            case 'v':  // verbatim
                fputs(&acLine[3],pkHFile);
                break;

            case 'f':  // function pointer definition
                iNumFunctions++;

                // return type of function
                assert( acLine[3] != ' ');
                pcRetType = &acLine[3];

                // function name
                pcFunction = pcRetType;
                while ( *pcFunction != 'w'
                ||      *(pcFunction+1) != 'g'
                ||      *(pcFunction+2) != 'l' )
                {
                    pcFunction++;
                }
                pcFunction--;
                *pcFunction = 0;
                pcFunction++;

                // signature of function
                pcSignature = pcFunction;
                while ( *pcSignature != ' ' )
                {
                    pcSignature++;
                }
                *pcSignature = 0;
                pcSignature++;

                // H file information
                fputs("\n",pkHFile);
                sprintf(acTmp,"typedef %s (WINAPI* pfn_%s) %s",pcRetType,
                    pcFunction,pcSignature);
                fputs(acTmp,pkHFile);
                sprintf(acTmp,"extern pfn_%s Wm3%s;\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkHFile);
                sprintf(acTmp,"#define %s Wm3%s\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkHFile);

                // C file information
                acFCopy = new char[strlen(pcFunction)+1];
                strcpy(acFCopy,pcFunction);
                kFunction.push_back(acFCopy);

                sprintf(acTmp,"pfn_%s Wm3%s = 0;\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkCFile);
                break;

            default:
                assert( false );
                break;
            }
        }

        // end of extension block in H file
        fputs("#endif\n",pkHFile);

        // end of extension block in C file
        fputs("\n",pkCFile);

        sprintf(acTmp,"static void Init_%s ()\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("{\n",pkCFile);

        sprintf(acTmp,"    Wm3NumFunctions_%s = 0;\n\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        for (i = 1; i <= iNumFunctions; i++)
        {
            sprintf(acTmp,
                "    Wm3%s = (pfn_%s)GetFunctionPointer(\"%s\");\n",
                kFunction[i],kFunction[i],kFunction[i]);
            fputs(acTmp,pkCFile);

            sprintf(acTmp,"    if ( Wm3%s )\n",kFunction[i]);
            fputs(acTmp,pkCFile);

            sprintf(acTmp,"        ++Wm3NumFunctions_%s;\n\n",
                kFunction[0]);
            fputs(acTmp,pkCFile);
        }
        sprintf(acTmp,"    if ( Wm3NumFunctions_%s == %d )\n",
            kFunction[0],iNumFunctions);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"        Wm3Exists_%s = WM3_EXT_FULLY_EXISTS;\n",
            kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("    else\n",pkCFile);
        sprintf(acTmp,
            "        Wm3Exists_%s = WM3_EXT_PARTIALLY_EXISTS;\n",
            kFunction[0]);
        fputs(acTmp,pkCFile);

        fputs("}\n",pkCFile);

        fputs("#else\n",pkCFile);

        sprintf(acTmp,"static void Init_%s ()\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("{\n",pkCFile);
        sprintf(acTmp,"    Wm3NumFunctions_%s = 0;\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"    Wm3Exists_%s = WM3_EXT_DOES_NOT_EXIST;\n",
            kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("}\n",pkCFile);

        fputs("#endif\n",pkCFile);

        for (i = 0; i < (int)kFunction.size(); i++)
            delete kFunction[i];
    }
    fclose(pkIFile);

    // initialization function
    fputs("\n",pkCFile);
    fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);
    fputs("void InitializeWgl ()\n",pkCFile);
    fputs("{\n",pkCFile);
    for (i = 0; i < (int)kExtension.size(); i++)
    {
        sprintf(acTmp,"    Init_%s();\n",kExtension[i]);
        fputs(acTmp,pkCFile);
    }
    fputs("}\n",pkCFile);
    fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);
    fputs("#endif\n",pkCFile);

    pkIFile = fopen("WglExtHFinal.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkHFile);
    }
    fclose(pkIFile);

    fclose(pkCFile);
    fclose(pkHFile);

    delete[] acTmp;
    delete[] acLine;
}
//----------------------------------------------------------------------------
static void CreateGlxExtensions ()
{
    const int iMaxLine = 4096;
    char* acLine = new char[iMaxLine];
    char* acTmp = new char[iMaxLine];
    char* pcResult;
    char* pcRetType;
    char* pcSignature;
    char* pcFunction;
    char* acFCopy;
    int i;

    FILE* pkHFile = fopen("Wm3GlxExtensions.h","wt");
    FILE* pkCFile = fopen("Wm3GlxExtensions.c","wt");

    // write the starting text in the H file
    FILE* pkIFile = fopen("GlxExtHStart.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkHFile);
    }
    fclose(pkIFile);

    // write the starting text in the C file
    pkIFile = fopen("GlxExtCStart.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkCFile);
    }
    fclose(pkIFile);

    std::vector<char*> kExtension;
    pkIFile = fopen("GlxExt.txt","rt");
    while ( (pcResult = fgets(acLine,iMaxLine,pkIFile)) != 0 )
    {
        // skip blank lines
        while ( pcResult && acLine[0] != '{' )
            pcResult = fgets(acLine,iMaxLine,pkIFile);

        // get extension name
        assert( strlen(acLine) >= 6 && strncmp(acLine,"{ GLX_",6) == 0 );
        char* acExtension = &acLine[2];
        char* pcEnd = strpbrk(acExtension," \t\n");
        assert( pcEnd );
        *pcEnd = 0;

        // save extension for initialization function
        char* acECopy = new char[strlen(acExtension)+1];
        strcpy(acECopy,acExtension);
        kExtension.push_back(acECopy);

        std::vector<char*> kFunction;
        acECopy = new char[strlen(acExtension)+1];
        strcpy(acECopy,acExtension);
        kFunction.push_back(acECopy);
        int iNumFunctions = 0;

        // start extension block in H file
        fputs("\n",pkHFile);
        fputs("/*--------------------------------------------------------------------------*/\n",pkHFile);
        sprintf(acTmp,"extern int Wm3Exists_%s;\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"extern int Wm3NumFunctions_%s;\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#ifndef %s\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#define %s\n",acExtension);
        fputs(acTmp,pkHFile);
        sprintf(acTmp,"#define WM3_DEFINED_%s\n",acExtension);
        fputs(acTmp,pkHFile);

        // start extension block in C file
        fputs("\n",pkCFile);
        fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);
        sprintf(acTmp,"int Wm3Exists_%s;\n",acExtension);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"int Wm3NumFunctions_%s;\n",acExtension);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"#ifdef WM3_DEFINED_%s\n",acExtension);
        fputs(acTmp,pkCFile);

        // get extension information
        bool bFirstDefine = true;
        bool bFirstTypedef = true;
        bool bFirstPrototype = true;
        while ( true )
        {
            pcResult = fgets(acLine,iMaxLine,pkIFile);
            assert( pcResult );

            if ( acLine[0] == '}' )
            {
                // end of extension block
                break;
            }

            assert( acLine[0] == '@' );

            switch ( acLine[1] )
            {
            case 'v':  // verbatim
                fputs(&acLine[3],pkHFile);
                break;

            case 'f':  // function pointer definition
                iNumFunctions++;

                // return type of function
                assert( acLine[3] != ' ');
                pcRetType = &acLine[3];

                // function name
                pcFunction = pcRetType;
                while ( *pcFunction != 'g'
                ||      *(pcFunction+1) != 'l'
                ||      *(pcFunction+2) != 'X' )
                {
                    pcFunction++;
                }
                pcFunction--;
                *pcFunction = 0;
                pcFunction++;

                // signature of function
                pcSignature = pcFunction;
                while ( *pcSignature != ' ' )
                {
                    pcSignature++;
                }
                *pcSignature = 0;
                pcSignature++;

                // H file information
                fputs("\n",pkHFile);
                sprintf(acTmp,"typedef %s (* pfn_%s) %s",
                    pcRetType,pcFunction,pcSignature);
                fputs(acTmp,pkHFile);
                sprintf(acTmp,"extern pfn_%s Wm3%s;\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkHFile);
                sprintf(acTmp,"#define %s Wm3%s\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkHFile);

                // C file information
                acFCopy = new char[strlen(pcFunction)+1];
                strcpy(acFCopy,pcFunction);
                kFunction.push_back(acFCopy);

                sprintf(acTmp,"pfn_%s Wm3%s = 0;\n",pcFunction,
                    pcFunction);
                fputs(acTmp,pkCFile);
                break;

            case 'p':  // function prototype
                iNumFunctions++;

                // return type of function
                assert( acLine[3] != ' ');
                pcRetType = &acLine[3];

                // function name
                pcFunction = pcRetType;
                while ( *pcFunction != 'g'
                ||      *(pcFunction+1) != 'l'
                ||      *(pcFunction+2) != 'X' )
                {
                    pcFunction++;
                }
                pcFunction--;
                *pcFunction = 0;
                pcFunction++;

                // signature of function
                pcSignature = pcFunction;
                while ( *pcSignature != ' ' )
                {
                    pcSignature++;
                }
                *pcSignature = 0;
                pcSignature++;

                // H file information
                sprintf(acTmp,"extern %s %s %s",pcRetType,pcFunction,
                    pcSignature);
                fputs(acTmp,pkHFile);
                break;

            default:
                assert( false );
                break;
            }
        }

        // end of extension block in H file
        fputs("#endif\n",pkHFile);

        // end of extension block in C file
        if ( kFunction.size() > 1 )
            fputs("\n",pkCFile);

        sprintf(acTmp,"static void Init_%s ()\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("{\n",pkCFile);

        if ( kFunction.size() == 1 )
        {
            // all prototypes
            sprintf(acTmp,"    Wm3NumFunctions_%s = %d;\n",kFunction[0],
                iNumFunctions);
            fputs(acTmp,pkCFile);

            sprintf(acTmp,"    Wm3Exists_%s = WM3_EXT_FULLY_EXISTS;\n",
                kFunction[0]);
            fputs(acTmp,pkCFile);
        }
        else
        {
            sprintf(acTmp,"    Wm3NumFunctions_%s = 0;\n\n",kFunction[0]);
            fputs(acTmp,pkCFile);
            for (i = 1; i <= iNumFunctions; i++)
            {
                sprintf(acTmp,
                    "    Wm3%s = (pfn_%s)GetFunctionPointer(\"%s\");\n",
                    kFunction[i],kFunction[i],kFunction[i]);
                fputs(acTmp,pkCFile);

                sprintf(acTmp,"    if ( Wm3%s )\n",kFunction[i]);
                fputs(acTmp,pkCFile);

                sprintf(acTmp,"        ++Wm3NumFunctions_%s;\n\n",
                    kFunction[0]);
                fputs(acTmp,pkCFile);
            }
            sprintf(acTmp,"    if ( Wm3NumFunctions_%s == %d )\n",
                kFunction[0],iNumFunctions);
            fputs(acTmp,pkCFile);
            sprintf(acTmp,"        Wm3Exists_%s = WM3_EXT_FULLY_EXISTS;\n",
                kFunction[0]);
            fputs(acTmp,pkCFile);
            fputs("    else\n",pkCFile);
            sprintf(acTmp,
                "        Wm3Exists_%s = WM3_EXT_PARTIALLY_EXISTS;\n",
                kFunction[0]);
            fputs(acTmp,pkCFile);
        }
        fputs("}\n",pkCFile);

        fputs("#else\n",pkCFile);

        sprintf(acTmp,"static void Init_%s ()\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("{\n",pkCFile);
        sprintf(acTmp,"    Wm3NumFunctions_%s = 0;\n",kFunction[0]);
        fputs(acTmp,pkCFile);
        sprintf(acTmp,"    Wm3Exists_%s = WM3_EXT_DOES_NOT_EXIST;\n",
            kFunction[0]);
        fputs(acTmp,pkCFile);
        fputs("}\n",pkCFile);

        fputs("#endif\n",pkCFile);

        for (i = 0; i < (int)kFunction.size(); i++)
            delete kFunction[i];
    }
    fclose(pkIFile);

    // initialization function
    fputs("\n",pkCFile);
    fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);
    fputs("void InitializeGlx ()\n",pkCFile);
    fputs("{\n",pkCFile);
    for (i = 0; i < (int)kExtension.size(); i++)
    {
        sprintf(acTmp,"    Init_%s();\n",kExtension[i]);
        fputs(acTmp,pkCFile);
    }
    fputs("}\n",pkCFile);
    fputs("/*--------------------------------------------------------------------------*/\n",pkCFile);
    fputs("#endif\n",pkCFile);

    pkIFile = fopen("GlxExtHFinal.txt","rt");
    while ( fgets(acLine,iMaxLine,pkIFile) )
    {
        fputs(acLine,pkHFile);
    }
    fclose(pkIFile);

    fclose(pkCFile);
    fclose(pkHFile);

    delete[] acTmp;
    delete[] acLine;
}
//----------------------------------------------------------------------------
int main ()
{
    CreateOglExtensions();
    CreateWglExtensions();
    CreateGlxExtensions();
    return 0;
}
//----------------------------------------------------------------------------

