/// <summary>
        /// Path to glapitemp.h file
        /// </summary>
        public FunctionNameDictionary Parse(string path)
        {
            StreamReader           sr        = File.OpenText(path);
            FunctionNameDictionary functions = new FunctionNameDictionary();

            string line     = null;
            int    matchpos = -1;

            while ((line = sr.ReadLine()) != null)
            {
                if ((matchpos = line.IndexOf("KEYWORD2 NAME(")) >= 0)
                {
                    int    closingbracketpos = line.IndexOf(")", matchpos);
                    string fname             = "gl" + line.Substring(matchpos + 14, closingbracketpos - 14 - matchpos);

                    if (fname.IndexOf("_dispatch_stub") >= 0)
                    {
                        continue;                         /* Trash not needed */
                    }
                    if (!functions.ContainsKey(fname))
                    {
                        functions.Add(fname, null);
                    }
                }
            }

            return(functions);
        }
        public void RemoveFunctionsExceptFor(FunctionNameDictionary functions)
        {
            FunctionList toBeRemoved = new FunctionList();

            foreach (Function f in this)
            {
                if (!functions.ContainsKey(f.Name))
                {
                    toBeRemoved.Add(f);
                }
                else
                {
                    functions.MarkAsMatched(f.Name);
                }
            }

            foreach (Function f in toBeRemoved)
            {
                this.Remove(f);
            }
        }
        /// <summary>
        /// Path to glapioffsets.h file
        /// </summary>
        public FunctionNameDictionary Parse(string path)
        {
            StreamReader           sr        = File.OpenText(path);
            FunctionNameDictionary functions = new FunctionNameDictionary();

            string line = null;

            while ((line = sr.ReadLine()) != null)
            {
                if (line.IndexOf("#define _gloffset_") >= 0)
                {
                    string part  = line.Substring(18, line.Length - 18);
                    string fname = "gl" + (part.Split(' ')[0].Trim());
                    if (!functions.ContainsKey(fname))
                    {
                        functions.Add(fname, null);
                    }
                }
            }

            return(functions);
        }
        public static void Main(string[] args)
        {
            string   PATH_TO_MESA = @"/ssd/deadwood/repo-gitorious-aros/AROS/AROS/workbench/libs/mesa/";
            string   OUTPUT_PATH  = @"/ssd/deadwood/temp/";
            CallType eglCallType  = CallType.StackCall;
            CallType vgCallType   = CallType.StackCall;
            CallType gluCallType  = CallType.StackCall;
            CallType glCallType   = CallType.StackCall;


            GLApiTempParser        apiParser            = new GLApiTempParser();
            FunctionNameDictionary implementedFunctions =
                apiParser.Parse(PATH_TO_MESA + @"/src/mapi/glapi/glapitemp.h");


            Console.WriteLine("Implemented functions: {0}", implementedFunctions.Keys.Count);

            /* Parsing part */
            APIHeaderParser p = new APIHeaderParser();

            FunctionList functionsglh      = p.Parse(PATH_TO_MESA + @"/include/GL/gl.h", APIHeaderParser.GLAPI, APIHeaderParser.GLAPIENTRY);
            FunctionList functionsglhquirk = p.Parse(PATH_TO_MESA + @"/include/GL/gl.h", APIHeaderParser.GLAPI, APIHeaderParser.APIENTRY);

            functionsglh.AddRange(functionsglhquirk);

            FunctionList functionsglexth = p.Parse(PATH_TO_MESA + @"/include/GL/glext.h", APIHeaderParser.GLAPI, APIHeaderParser.APIENTRY);


            ConfParser   confParser = new ConfParser();
            FunctionList orderedExistingFunctions = confParser.Parse(PATH_TO_MESA + @"/src/aros/arosmesa/gl.conf");

            Console.WriteLine("Initial parse results: GL: {0} GLEXT: {1}", functionsglh.Count, functionsglexth.Count);

            functionsglexth.RemoveFunctionsExceptFor(implementedFunctions);
            functionsglh.RemoveFunctionsExceptFor(implementedFunctions);
            functionsglexth.RemoveFunctions(functionsglh);

            implementedFunctions.WriteUnmatched();

            Console.WriteLine("After filtering of unimplemented functions: GL: {0} GLEXT: {1}", functionsglh.Count, functionsglexth.Count);

            /* Generation part */

            /* GL */
            FunctionList functionsGL = new FunctionList();

            Console.WriteLine("After duplicates removal GL: {0}, GLEXT: {1}", functionsglh.Count, functionsglexth.Count);
            functionsGL.AddRange(functionsglh);

            functionsGL.RemoveFunctionByName("glBlendEquationSeparateATI");             /* Extension found in gl.h instead of glext.h */
            functionsGL.RemoveFunctionByName("glFramebufferTextureLayerEXT");           /* Extension found in gl.h instead of glext.h */
            functionsGL.RemoveFunctionByName("glEGLImageTargetTexture2DOES");           /* Extension found in gl.h instead of glext.h */
            functionsGL.RemoveFunctionByName("glEGLImageTargetRenderbufferStorageOES"); /* Extension found in gl.h instead of glext.h */

            Console.WriteLine("After merging GL {0}", functionsGL.Count);


            FunctionList functionsfinal = new FunctionList();

            functionsfinal.AddRange(functionsGL);

            functionsfinal.CorrectionForArrayArguments();
            functionsfinal.ReorderToMatch(orderedExistingFunctions);

            if (glCallType == CallType.RegCall)
            {
                functionsfinal.CalculateRegisters();

                StubsFileWriter sfw = new StubsFileWriter(false, "Mesa", 35);
                sfw.Write(OUTPUT_PATH + @"arosmesa_library_api.c", functionsfinal);
            }

            ConfFileWriter cfw = new ConfFileWriter(glCallType);

            cfw.Write(OUTPUT_PATH + @"gl.conf", functionsfinal);

            /*MangledImplementationFileWriter glmifw = new MangledImplementationFileWriter();
             * glmifw.Write(OUTPUT_PATH + @"hostgl_gl_api.c", functionsfinal);
             *
             * GLFUNCFileWriter glfuncfw = new GLFUNCFileWriter();
             * glfuncfw.Write(OUTPUT_PATH + @"gl_func.ch", functionsfinal);*/

            /* EGL */
            FunctionList functionseglh = p.Parse(PATH_TO_MESA + @"/include/EGL/egl.h", APIHeaderParser.EGLAPI, APIHeaderParser.EGLAPIENTRY);
            FunctionList orderedExistingFunctionsEGL = confParser.Parse(PATH_TO_MESA + @"/src/aros/egl/egl.conf");

            FunctionList functionsEGL = new FunctionList();

            functionsEGL.AddRange(functionseglh);

            Console.WriteLine("After merging EGL {0}", functionsEGL.Count);

            functionsfinal.Clear();
            functionsfinal.AddRange(functionsEGL);

            functionsfinal.CorrectionForArrayArguments();

            functionsfinal.ReorderToMatch(orderedExistingFunctionsEGL);

            if (eglCallType == CallType.RegCall)
            {
                functionsfinal.CalculateRegisters();

                StubsFileWriter eglsfw = new StubsFileWriter(false, "EGL", 35);
                eglsfw.Write(OUTPUT_PATH + @"egl_library_api.c", functionsfinal);
            }

            ConfFileWriter eglcfw = new ConfFileWriter(eglCallType);

            eglcfw.Write(OUTPUT_PATH + @"egl.conf", functionsfinal);


            /* VG */
            FunctionList functionsopenvgh = p.Parse(PATH_TO_MESA + @"/include/VG/openvg.h", APIHeaderParser.VGAPI, APIHeaderParser.VGAPIENTRY);
            FunctionList functionsvguh    = p.Parse(PATH_TO_MESA + @"/include/VG/vgu.h", APIHeaderParser.VGUAPI, APIHeaderParser.VGUAPIENTRY);

            FunctionList orderedExistingFunctionsVG = confParser.Parse(PATH_TO_MESA + @"/src/aros/vega/vega.conf");

            FunctionList functionsVG = new FunctionList();

            functionsVG.AddRange(functionsopenvgh);
            functionsVG.AddRange(functionsvguh);

            Console.WriteLine("After merging VG {0}", functionsVG.Count);

            functionsfinal.Clear();
            functionsfinal.AddRange(functionsVG);

            functionsfinal.CorrectionForArrayArguments();
            functionsfinal.ReorderToMatch(orderedExistingFunctionsVG);

            if (vgCallType == CallType.RegCall)
            {
                functionsVG.RemoveFunctionByName("vguComputeWarpQuadToQuad");                 /* Too many parameters */
                functionsfinal.CalculateRegisters();

                StubsFileWriter vgsfw = new StubsFileWriter(false, "Vega", 35);
                vgsfw.Write(OUTPUT_PATH + @"vega_library_api.c", functionsfinal);
            }

            ConfFileWriter vgcfw = new ConfFileWriter(vgCallType);

            vgcfw.Write(OUTPUT_PATH + @"vega.conf", functionsfinal);


            /* GLU */
            FunctionList functionsgluh = p.Parse(PATH_TO_MESA + @"/include/GL/glu.h", APIHeaderParser.GLAPI, APIHeaderParser.GLAPIENTRY);

            FunctionList orderedExistingFunctionsGLU = confParser.Parse(PATH_TO_MESA + @"/src/aros/glu/glu.conf");

            FunctionList functionsGLU = new FunctionList();

            functionsGLU.AddRange(functionsgluh);

            Console.WriteLine("After merging GLU {0}", functionsGLU.Count);

            functionsfinal.Clear();
            functionsfinal.AddRange(functionsGLU);

            functionsfinal.CorrectionForArrayArguments();
            functionsfinal.ReorderToMatch(orderedExistingFunctionsGLU);

            if (gluCallType == CallType.RegCall)
            {
                functionsGLU.RemoveFunctionByName("gluUnProject4");                 /* Too many parameters */
                functionsfinal.CalculateRegisters();

                StubsFileWriter glusfw = new StubsFileWriter(false, "GLU", 35);
                glusfw.Write(OUTPUT_PATH + @"glu_library_api.c", functionsfinal);
            }

            ConfFileWriter glucfw = new ConfFileWriter(gluCallType);

            glucfw.Write(OUTPUT_PATH + @"glu.conf", functionsfinal);
        }