Commits

Jason McKesson committed 91f08f2

pointer_cpp seems to work.

Comments (0)

Files changed (7)

docs/Style_Creation.xml

         These functions will be called by the system to do specific things at specific times.</para>
     <para>You should not need to keep state between function invocations (the
             <literal>pointer_c</literal> style works completely statelessly, relying only on
-        function arguments). However, you can use local variables to store state if you wish. The
-        system will never ask your style to run twice (at least, not without a process
-        restart).</para>
+        function arguments). However, if you need state, you can create it by using the
+            <literal>Create</literal> function to associate actual state with each instance. The
+        system guarantees that the particular table returned by your style's
+            <literal>Create</literal> function will only be used to generate a single header/source
+        pair.</para>
     <para>The <literal>style</literal> table will need two sub-tables named
             <literal>source</literal> and <literal>header</literal>. They contain functions for
         generating material for source and header files, respectively. Most of the functions are in
 source.WriteIncludes(hFile, spec, options)
 #include "HEADER_FILENAME"
 
+//Function pointer loader func from spec.loaderFunc()
+
 source.WriteBeginDef(hFile, spec, options)
 
   source.WriteBeginExtVarDefBlock(hFile, spec, options)

docs/Style_Pointer_C.xml

     <para>If the value is <literal>LOAD_FAILED</literal>, then the extension was not found in the
         extension string, so no attempt was made to load it. If the value is
             <literal>LOAD_SUCCEEDED</literal>, then the extension was loaded in its entirety (all
-        function pointers accounted for). Otherwise, some number of function pointers failed to
-        load. To get the number of functions that failed to load for the extension, take the integer
-        value and subtract <literal>LOAD_SUCCEEDED</literal> from it.</para>
+        function pointers accounted for, if it has some). Otherwise, some number of function
+        pointers failed to load. To get the number of functions that failed to load for the
+        extension, take the integer value and subtract <literal>LOAD_SUCCEEDED</literal> from
+        it.</para>
     <para>The return value for the function loader works mostly the same way.
             <literal>LOAD_FAILED</literal> does not signal the failure to load the core functions or
         some extensions. It signals the failure of the process to work <emphasis>at all.</emphasis>

modules/CommonStyle.lua

 
 
 --You give it a function that takes a const char*.
-function common.GetProcessExtsFromStringFunc(funcToCall)
+function common.GetProcessExtsFromStringFunc(funcFormat, arguments)
 	return [[
-static void ProcExtsFromExtString(const char *strExtList)
+static void ProcExtsFromExtString(const char *strExtList]] .. (arguments or "") .. [[)
 {
 	size_t iExtListLen = strlen(strExtList);
 	const char *strExtListEnd = strExtList + iExtListLen;
 		strncpy(strWorkBuff, strCurrPos, iStrLen);
 		strWorkBuff[iStrLen] = '\0';
 
-		]] .. funcToCall ..[[(strWorkBuff);
+		]] .. funcFormat:format("strWorkBuff") ..[[;
 
 		strCurrPos = strEndStr + 1;
 		if(iStop) break;

modules/Generate.lua

 	if(options.version) then
 		hFile:write("\n")
 		style.WriteSmallHeading(hFile, "Core Functions")
-	else
-		--No version to export, so don't bother.
-		return
-	end
 	
-	--Write the core function definitions, maintaining a list of everything
-	--that was written.
-	local coreExts = spec.GetCoreExts()
-	local bWrittenBeginCore = false
-	for _, version in ipairs(spec.GetVersions()) do
-		if(tonumber(version) <= tonumber(options.version)) then
-			--Write any core extensions for that version.
-			if(coreExts[version]) then
-				for _, extName in ipairs(coreExts[version]) do
-					if(not extSeen[extName]) then
-						if(not bWrittenBeginCore) then
-							source.WriteBeginCoreFuncDefBlock(hFile, options.version, spec, options)
-							bWrittenBeginCore = true
-						end
-						extSeen[extName] = true
-						WriteFuncDefsForCoreExt(hFile, extName, funcSeen,
-							options, spec, style, specData)
-					end
-				end
-			end
-			
-			--Write the actual core functions, if any.
-			local funcList = GetCoreFunctions(specData.coredefs[version],
-				specData, spec, options, version)
-				
-			if(#funcList > 0) then
-				if(not bWrittenBeginCore) then
-					source.WriteBeginCoreFuncDefBlock(hFile, options.version, spec, options)
-					bWrittenBeginCore = true
-				end
-				style.WriteSmallHeading(hFile, "Version " .. version)
-				
-				WriteFuncDefsFromList(hFile, funcList, funcSeen,
-					version, options, spec, style, specData)
-
-				hFile:write("\n")
-			end
-		end
-	end
-	
-	if(bWrittenBeginCore) then
-		--Now, write the function that loads the core version. Include
-		--ALL core extensions, not just the ones we wrote.
-		--This allows us to build an accurate count of what core stuff is missing.
-		source.WriteBeginCoreLoaderBlock(hFile, options.version, spec, options)
+		--Write the core function definitions, maintaining a list of everything
+		--that was written.
+		local coreExts = spec.GetCoreExts()
+		local bWrittenBeginCore = false
 		for _, version in ipairs(spec.GetVersions()) do
 			if(tonumber(version) <= tonumber(options.version)) then
+				--Write any core extensions for that version.
 				if(coreExts[version]) then
-					source.WriteBeginExtFuncDefBlock(hFile, extName, spec, options)
-
 					for _, extName in ipairs(coreExts[version]) do
-						WriteCoreFuncLoaderFromList(hFile,
-							specData.extdefs[extName].funcs,
-							options, spec, style, specData)
+						if(not extSeen[extName]) then
+							if(not bWrittenBeginCore) then
+								source.WriteBeginCoreFuncDefBlock(hFile, options.version, spec, options)
+								bWrittenBeginCore = true
+							end
+							extSeen[extName] = true
+							WriteFuncDefsForCoreExt(hFile, extName, funcSeen,
+								options, spec, style, specData)
+						end
 					end
-					
-					source.WriteEndExtFuncDefBlock(hFile, extName, spec, options)
-
 				end
 				
 				--Write the actual core functions, if any.
 					specData, spec, options, version)
 					
 				if(#funcList > 0) then
-					WriteCoreFuncLoaderFromList(hFile,
-						funcList, options, spec, style, specData)
+					if(not bWrittenBeginCore) then
+						source.WriteBeginCoreFuncDefBlock(hFile, options.version, spec, options)
+						bWrittenBeginCore = true
+					end
+					style.WriteSmallHeading(hFile, "Version " .. version)
+					
+					WriteFuncDefsFromList(hFile, funcList, funcSeen,
+						version, options, spec, style, specData)
+
+					hFile:write("\n")
 				end
 			end
 		end
-		source.WriteEndCoreLoaderBlock(hFile, options.version, spec, options)
 		
-		source.WriteEndCoreFuncDefBlock(hFile, options.version, spec, options)
+		if(bWrittenBeginCore) then
+			--Now, write the function that loads the core version. Include
+			--ALL core extensions, not just the ones we wrote.
+			--This allows us to build an accurate count of what core stuff is missing.
+			source.WriteBeginCoreLoaderBlock(hFile, options.version, spec, options)
+			for _, version in ipairs(spec.GetVersions()) do
+				if(tonumber(version) <= tonumber(options.version)) then
+					if(coreExts[version]) then
+						source.WriteBeginExtFuncDefBlock(hFile, extName, spec, options)
+
+						for _, extName in ipairs(coreExts[version]) do
+							WriteCoreFuncLoaderFromList(hFile,
+								specData.extdefs[extName].funcs,
+								options, spec, style, specData)
+						end
+						
+						source.WriteEndExtFuncDefBlock(hFile, extName, spec, options)
+
+					end
+					
+					--Write the actual core functions, if any.
+					local funcList = GetCoreFunctions(specData.coredefs[version],
+						specData, spec, options, version)
+						
+					if(#funcList > 0) then
+						WriteCoreFuncLoaderFromList(hFile,
+							funcList, options, spec, style, specData)
+					end
+				end
+			end
+			source.WriteEndCoreLoaderBlock(hFile, options.version, spec, options)
+			
+			source.WriteEndCoreFuncDefBlock(hFile, options.version, spec, options)
+		end
 	end
 	
 	local function FindFuncName(funcName)
 	for _, ext in ipairs(options.extensions) do
 		source.WriteExtVariableDef(hFile, ext, specData, spec, options)
 	end
+	source.WriteEndExtVarDefBlock(hFile, spec, options)
 	hFile:write("\n")
-	source.WriteEndExtVarDefBlock(hFile, spec, options)
 	
 	--Write all of the loader definitions.
 	style.WriteLargeHeading(hFile, "Function Definitions and Loaders")

modules/StylePointerC.lua

 end
 
 function my_style.source.WriteGetExtStringFuncDef(hFile, func, typemap, spec, options)
-	my_style.source.WriteFuncDef(hFile, func, typemap, spec, options)
+	hFile:fmt("static %s = NULL;\n",
+		GetFuncPtrDef(hFile, func, typemap, spec, options))
 end
 
 local function GetMapTableStructName(spec, options)
 }
 ]])
 	else
-		hFile:writeblock(common.GetProcessExtsFromStringFunc("LoadExtByName"))
+		hFile:writeblock(common.GetProcessExtsFromStringFunc("LoadExtByName(%s)"))
 	end
 	
 	hFile:write "\n"

modules/StylePointerCPP.lua

 	return common.CreateFile(filename, options.indent), filename
 end
 
-local function GenIncludeGuardName(hFile, spec, options)
-	local str = "POINTER_CPP_GENERATED_HEADER" ..
-		spec.GetIncludeGuardString() .. "_HPP"
+	local function GenIncludeGuardName(hFile, spec, options)
+		local str = "POINTER_CPP_GENERATED_HEADER" ..
+			spec.GetIncludeGuardString() .. "_HPP"
 
-	if(#options.prefix > 0) then
-		return options.prefix:upper() .. "_" .. str
+		if(#options.prefix > 0) then
+			return options.prefix:upper() .. "_" .. str
+		end
+		
+		return str
 	end
-	
-	return str
-end
 
 function my_style.header.WriteBeginIncludeGuard(hFile, spec, options)
 	local inclGuard = GenIncludeGuardName(hFile, spec, options)
 	hFile:pop()
 end
 
-local function StartNamespace(hFile, namespaceName)
-	hFile:fmt("namespace %s\n", namespaceName)
-	hFile:write("{\n")
-	hFile:inc()
-end
+	local function StartNamespace(hFile, namespaceName)
+		hFile:fmt("namespace %s\n", namespaceName or "")
+		hFile:write("{\n")
+		hFile:inc()
+	end
 
-local function EndNamespace(hFile, namespaceName)
-	hFile:dec()
-	hFile:fmt("} //namespace %s\n", namespaceName)
-end
+	local function EndNamespace(hFile, namespaceName)
+		hFile:dec()
+		hFile:fmt("} //namespace %s\n", namespaceName or "")
+	end
 
 function my_style.header.WriteBeginDecl(hFile, spec, options)
 	if(#options.prefix > 0) then
 	end
 end
 
-local extBlockNamespace = "exts"
-local extVariableTypeDefinition = [[
+	local extBlockNamespace = "exts"
+	local extVariableTypeDefinition = [[
 class LoadTest
 {
 private:
 	
 	int GetNumMissing() const {return m_numMissing;}
 	
-	void IgnoreThis(bool isLoaded, int numMissing)
-	{
-		m_isLoaded = isLoaded;
-		m_numMissing = numMissing;
-	}
-	
 	LoadTest() : m_isLoaded(false), m_numMissing(0) {}
+	LoadTest(bool isLoaded, int numMissing) : m_isLoaded(isLoaded), m_numMissing(numMissing) {}
 private:
 	bool m_isLoaded;
 	int m_numMissing;
 	EndNamespace(hFile, extBlockNamespace)
 end
 
-local function GenExtensionVarName(extName, spec, options)
-	return "var_" .. extName;
-end
+	local function GenExtensionVarName(extName, spec, options)
+		return "var_" .. extName;
+	end
 
 function my_style.header.WriteExtVariableDecl(hFile, extName,
 	specData, spec, options)
 
 function my_style.header.WriteEndEnumDeclBlock(hFile, spec, options)
 	hFile:dec()
-	hFile:write("}\n")
+	hFile:write("};\n")
 end
 
-local function GenEnumName(enum)
-	--Note: some enumerators start with characters C++ forbids as initial
-	--identifiers. If we detect such an enum, prefix it with `_`.
-	local enumName = enum.name
-	if(not enumName:match("^[a-zA-Z_]")) then
-		enumName = "_" .. enumName
+	local function GenEnumName(enum)
+		--Note: some enumerators start with characters C++ forbids as initial
+		--identifiers. If we detect such an enum, prefix it with `_`.
+		--Also, certain identifiers can need it.
+		local enumName = enum.name
+		if(not enumName:match("^[a-zA-Z_]")) then
+			enumName = "_" .. enumName
+		end
+		
+		local badIdent = {"TRUE", "FALSE", "NO_ERROR", "WAIT_FAILED"}
+		for _, ident in ipairs(badIdent) do
+			if(enumName == ident) then
+				enumName = enumName .. "_"
+				break
+			end
+		end
+		
+		return enumName
 	end
-	
-	return enumName
-end
 
 function my_style.header.WriteEnumDecl(hFile, enum, enumTable, spec, options)
 	local enumName = GenEnumName(enum)
 	--Block containing all spec function declarations for a particular extension.
 end
 
-local function GenFuncPtrName(func, spec, options)
-	return func.name
-end
+	local function GenFuncPtrName(func, spec, options)
+		return func.name
+	end
 
-local function GenFuncPtrTypedefName(func, spec, options)
-	return "PFN" .. GenFuncPtrName(func, spec, options):upper()
-end
+	local function GenFuncPtrTypedefName(func, spec, options)
+		return "PFN" .. GenFuncPtrName(func, spec, options):upper()
+	end
 
-local function WriteFuncPtrTypedefStmt(hFile, func, typemap, spec, options)
-	hFile:fmt("typedef %s (%s *%s)(%s);\n",
-		common.GetFuncReturnType(func, typemap),
-		spec.GetCodegenPtrType(),
-		GenFuncPtrTypedefName(func, spec, options),
-		common.GetFuncParamList(func, typemap))
-end
+	local function WriteFuncPtrTypedefStmt(hFile, func, typemap, spec, options)
+		hFile:fmt("typedef %s (%s *%s)(%s);\n",
+			common.GetFuncReturnType(func, typemap),
+			spec.GetCodegenPtrType(),
+			GenFuncPtrTypedefName(func, spec, options),
+			common.GetFuncParamList(func, typemap))
+	end
 
-local function GenFuncPtrDefDirect(func, typemap, spec, options)
-	return string.format("%s (%s *%s)(%s)",
-		common.GetFuncReturnType(func, typemap),
-		spec.GetCodegenPtrType(),
-		GenFuncPtrName(func, spec, options),
-		common.GetFuncParamList(func, typemap))
-end
+	local function GenFuncPtrDefDirect(func, typemap, spec, options)
+		return string.format("%s (%s *%s)(%s)",
+			common.GetFuncReturnType(func, typemap),
+			spec.GetCodegenPtrType(),
+			GenFuncPtrName(func, spec, options),
+			common.GetFuncParamList(func, typemap))
+	end
 
-local function GenFuncPtrDefTypedef(func, typemap, spec, options)
-	return string.format("%s %s",
-		GenFuncPtrTypedefName(func, spec, options),
-		GenFuncPtrName(func, spec, options))
-end
+	local function GenFuncPtrDefTypedef(func, typemap, spec, options)
+		return string.format("%s %s",
+			GenFuncPtrTypedefName(func, spec, options),
+			GenFuncPtrName(func, spec, options))
+	end
 
 function my_style.header.WriteFuncDecl(hFile, func, typemap, spec, options)
 	hFile:write("extern ",
 end
 
 function my_style.header.WriteMainLoaderFuncDecl(hFile, spec, options)
-	hFile:write("LoadTest LoadFunctions(%s);\n", spec.GetLoaderParams())
+	hFile:fmt("%s::LoadTest LoadFunctions(%s);\n", extBlockNamespace, spec.GetLoaderParams())
 end
 
 function my_style.header.WriteVersioningFuncDecls(hFile, spec, options)
 end
 
 function my_style.source.WriteIncludes(hFile, spec, options)
-	--Write the system include files for things you wish to use.
+	hFile:writeblock([[
+#include <algorithm>
+#include <vector>
+#include <string.h>
+#ifdef WIN32
+#define strcasecmp(lhs, rhs) _stricmp((lhs), (rhs))
+#endif
+]])
 end
 
 function my_style.source.WriteBeginDef(hFile, spec, options)
-	--Block containing the entire set of definitions.
+	if(#options.prefix > 0) then
+		StartNamespace(hFile, options.prefix)
+	end
+	StartNamespace(hFile, spec.FuncNamePrefix())
 end
 
 function my_style.source.WriteEndDef(hFile, spec, options)
-	--Block containing the entire set of definitions.
+	EndNamespace(hFile, spec.FuncNamePrefix())
+	if(#options.prefix > 0) then
+		EndNamespace(hFile, options.prefix)
+	end
 end
 
 function my_style.source.WriteBeginExtVarDefBlock(hFile, spec, options)
-	--Block containing the extension variable definitions.
+	StartNamespace(hFile, extBlockNamespace)
 end
 
 function my_style.source.WriteEndExtVarDefBlock(hFile, spec, options)
-	--Block containing the extension variable definitions.
+	EndNamespace(hFile, extBlockNamespace)
 end
 
 function my_style.source.WriteExtVariableDef(hFile, extName,
 	specData, spec, options)
-	--Writes the definition for the extension variable `extName`.
+	hFile:fmt("LoadTest %s;\n",
+		GenExtensionVarName(extName, spec, options));
 end
 
 function my_style.source.WriteBeginExtFuncDefBlock(hFile, extName, spec, options)
 end
 
 function my_style.source.WriteFuncDef(hFile, func, typemap, spec, options)
-	--Writes the definition of an extension function.
-	--Function pointers should be declared with spec.GetCodegenPtrType().
-	--common.GetFuncReturnType(func, typemap) and
-	--common.GetFuncParamList(func, typemap) can get the function types.
-	--A third parameter passed to GetFuncParamList can tell it to provide
-	--parameter names.
-	--common.GetOpenGLFuncName(func, spec) can be used to get the
-	--proper OpenGL name of the function.
+	WriteFuncPtrTypedefStmt(hFile, func, typemap, spec, options)
+	hFile:write(GenFuncPtrDefTypedef(func, typemap, spec, options),
+		" = 0;\n")
 end
 
+	local function GenExtLoaderFuncName(extName, spec, options)
+		return "Load_" .. extName;
+	end
+
 function my_style.source.WriteBeginExtLoaderBlock(hFile, extName, spec, options)
-	--The start of the loader function for the extension `extName`.
-	--The general idea is that this function should write the beginning of
-	--a file-static function that will contain the results of later
-	--WriteExtFuncLoader calls.
+	hFile:fmt("static int %s()\n", GenExtLoaderFuncName(extName, spec, options))
+	hFile:write("{\n")
+	hFile:inc()
+	hFile:write("int numFailed = 0;\n")
 end
 
 function my_style.source.WriteEndExtLoaderBlock(hFile, extName, spec, options)
-	--The end of the loader function for the extension `extName`.
+	hFile:write "return numFailed;\n"
+	hFile:dec()
+	hFile:write("}\n")
 end
 
 function my_style.source.WriteExtFuncLoader(hFile, func, typemap, spec, options)
-	--Writes the code to load the function `func` into a function pointer.
-	--It should also write test code to check if the pointer is null
-	--and possibly deal with that in some way.
-	--To get the name for the function that you should call to load a
-	--pointer (which takes the string name of the function), use:
-	--common.GetProcAddressName(spec)
+	hFile:fmt('%s = reinterpret_cast<%s>(%s("%s%s"));\n',
+		GenFuncPtrName(func, spec, options),
+		GenFuncPtrTypedefName(func, spec, options),
+		common.GetProcAddressName(spec),
+		spec.FuncNamePrefix(), func.name)
+	hFile:fmt('if(!%s) numFailed++;\n', GenFuncPtrName(func, spec, options))
 end
 
 function my_style.source.WriteBeginCoreFuncDefBlock(hFile, version, spec, options)
 
 function my_style.source.WriteGetExtStringFuncDef(hFile, func, typemap,
 	spec, options)
-	--This should write a *file static* function definition for the
-	--given function.
-	--This is used to ensure that the function needed to get the extension
-	--string will be available. Will only ever be called in WGL, because
-	--wglGetExtensionStringARB is an extension function. In GL, glGetString
-	--will always be there; even in post-3.0, glGetStringi is required to
-	--be there. and glXQueryExtensionString is core GLX 1.4.
+	WriteFuncPtrTypedefStmt(hFile, func, typemap, spec, options)
+	hFile:write("static ", GenFuncPtrDefTypedef(func, typemap, spec, options),
+		" = 0;\n")
 end
 
+	local function GenCoreLoaderFuncName(version, spec, options)
+		return "LoadCoreFunctions"
+	end
+
 function my_style.source.WriteBeginCoreLoaderBlock(hFile, version, spec, options)
-	--The start of the loader function for the version `version`.
-	--The general idea is that this function should write the beginning of
-	--a file-static function that will contain the results of later
-	--WriteCoreFuncLoader calls.
+	hFile:fmt("static int %s()\n", GenCoreLoaderFuncName(version, spec, options))
+	hFile:write("{\n")
+	hFile:inc()
+	hFile:write("int numFailed = 0;\n")
+
 end
 
 function my_style.source.WriteEndCoreLoaderBlock(hFile, version, spec, options)
-	--The end of the loader function for the version `version`.
+	hFile:write "return numFailed;\n"
+	hFile:dec()
+	hFile:write("}\n")
 end
 
 function my_style.source.WriteCoreFuncLoader(hFile, func, typemap, spec, options)
-	--Writes the code to load the function `func` into a function pointer.
-	--It should also write test code to check if the pointer is null
-	--and possibly deal with that in some way.
-	--To get the name for the function that you should call to load a
-	--pointer (which takes the string name of the function), use:
-	--common.GetProcAddressName(spec)
-	--This is separate from WriteExtFuncLoader because certain core extension
-	--functions, like glTextureStorage2DEXT are from EXT_DSA, but not really.
-	--So this is a way to not erronously report the absence of EXT_DSA
-	--functions. If func.name ends in "EXT", then it's a DSA function,
-	--so don't count it if it's not there.
+	hFile:fmt('%s = reinterpret_cast<%s>(%s("%s%s"));\n',
+		GenFuncPtrName(func, spec, options),
+		GenFuncPtrTypedefName(func, spec, options),
+		common.GetProcAddressName(spec),
+		spec.FuncNamePrefix(), func.name)
+		
+	--Special hack for DSA_EXT functions in core functions.
+	--They do not count against the loaded count.
+	if(func.name:match("EXT$")) then
+		hFile:write("//An EXT_direct_state_access-based function. Don't count it if it fails to load.")
+	else
+		hFile:fmt('if(!%s) numFailed++;\n', GenFuncPtrName(func, spec, options))
+	end
 end
 
 function my_style.source.WriteBeginSysDefBlock(hFile, spec, options)
-	--Block containing the definitions of the system functions.
-	--IE: the functions (and other definitions) used by the user
-	--to actually load things. Useful for wrapping it in a namespace.
+	StartNamespace(hFile, "sys")
 end
 
 function my_style.source.WriteEndSysDefBlock(hFile, spec, options)
-	--Block containing the definitions of the system functions.
+	EndNamespace(hFile, "sys")
 end
 
 function my_style.source.WriteUtilityDefs(hFile, specData, spec, options)
-	--Writes utility function definitions.
+	--Write our mapping table definitions.
+	StartNamespace(hFile)
+	hFile:writeblock[[
+typedef int (*PFN_LOADEXTENSION)();
+struct MapEntry
+{
+	MapEntry(const char *_extName, exts::LoadTest *_extVariable)
+		: extName(_extName)
+		, extVariable(_extVariable)
+		, loaderFunc(0)
+		{}
+		
+	MapEntry(const char *_extName, exts::LoadTest *_extVariable, PFN_LOADEXTENSION _loaderFunc)
+		: extName(_extName)
+		, extVariable(_extVariable)
+		, loaderFunc(_loaderFunc)
+		{}
+	
+	const char *extName;
+	exts::LoadTest *extVariable;
+	PFN_LOADEXTENSION loaderFunc;
+};
+
+struct MapCompare
+{
+	MapCompare(const char *test_) : test(test_) {}
+	bool operator()(const MapEntry &other) { return strcasecmp(test, other.extName) == 0; }
+	const char *test;
+};
+
+]]
+
+	--Write the table initialization function.
+	hFile:write "void InitializeMappingTable(std::vector<MapEntry> &table)\n"
+	hFile:write "{\n"
+	hFile:inc()
+	hFile:fmt("table.reserve(%i);\n", #options.extensions)
+	for _, extName in ipairs(options.extensions) do
+		if(#specData.extdefs[extName].funcs > 0) then
+			hFile:fmt('table.push_back(MapEntry("%s", &exts::%s, %s));\n',
+				spec.ExtNamePrefix() .. extName,
+				GenExtensionVarName(extName, spec, options),
+				GenExtLoaderFuncName(extName, spec, options))
+		else
+			hFile:fmt('table.push_back(MapEntry("%s", &exts::%s));\n',
+				spec.ExtNamePrefix() .. extName,
+				GenExtensionVarName(extName, spec, options))
+		end
+	end
+	hFile:dec()
+	hFile:write "}\n"
+	hFile:write "\n"
+	
+	--Write the function to clear the extension variables.
+	hFile:fmt("void ClearExtensionVars()\n")
+	hFile:write("{\n")
+	hFile:inc()
+	for _, extName in ipairs(options.extensions) do
+		hFile:fmt('exts::%s = exts::LoadTest();\n',
+			GenExtensionVarName(extName, spec, options))
+	end
+	hFile:dec()
+	hFile:write("}\n")
+	hFile:write "\n"
+	
+	--Write a function that loads an extension by name. It is called when
+	--processing, so it should also set the extension variable based on the load.
+	hFile:writeblock([[
+void LoadExtByName(std::vector<MapEntry> &table, const char *extensionName)
+{
+	std::vector<MapEntry>::iterator entry = std::find_if(table.begin(), table.end(), MapCompare(extensionName));
+	
+	if(entry != table.end())
+	{
+		if(entry->loaderFunc)
+			(*entry->extVariable) = exts::LoadTest(true, entry->loaderFunc());
+		else
+			(*entry->extVariable) = exts::LoadTest(true, 0);
+	}
+}
+]])
+	EndNamespace(hFile)
+	hFile:write "\n"
 end
 
+	local function GenQualifier(spec, options)
+		local ret = ""
+		if(#options.prefix > 0) then
+			ret = options.prefix .. "::"
+		end
+		ret = ret .. spec.FuncNamePrefix() .. "::"
+		return ret
+	end
+
+	local function GenQualifiedEnumName(enum, spec, options)
+		return GenQualifier(spec, options) .. GenEnumName(enum, spec, options)
+	end
+	
+	local function GenQualifiedFuncPtrName(func, spec, options)
+		return GenQualifier(spec, options) .. GenFuncPtrName(func, spec, options)
+	end
+	
+	local function WriteAncillaryFuncs(hFile, specData, spec, options)
+		local indexed = spec.GetIndexedExtStringFunc(options);
+		if(indexed) then
+			for _, func in ipairs(specData.funcData.functions) do
+				if(indexed[1] == func.name) then
+					indexed[1] = func
+				end
+				if(indexed[3] == func.name) then
+					indexed[3] = func
+				end
+			end
+			for _, enum in ipairs(specData.enumerations) do
+				if(indexed[2] == enum.name) then
+					indexed[2] = enum
+				end
+				if(indexed[4] == enum.name) then
+					indexed[4] = enum
+				end
+			end
+		
+			hFile:writeblock([[
+static void ProcExtsFromExtList(std::vector<MapEntry> &table)
+{
+	GLint iLoop;
+	GLint iNumExtensions = 0;
+	]] .. GenQualifiedFuncPtrName(indexed[1], spec, options)
+	.. [[(]] .. GenQualifiedEnumName(indexed[2], spec, options)
+	.. [[, &iNumExtensions);
+
+	for(iLoop = 0; iLoop < iNumExtensions; iLoop++)
+	{
+		const char *strExtensionName = (const char *)]] ..
+		GenQualifiedFuncPtrName(indexed[3], spec, options) ..
+		[[(]] .. GenQualifiedEnumName(indexed[4], spec, options) .. [[, iLoop);
+		LoadExtByName(table, strExtensionName);
+	}
+}
+]])
+		else
+			hFile:writeblock(common.GetProcessExtsFromStringFunc(
+				"LoadExtByName(table, %s)", ", std::vector<MapEntry> &table"))
+		end
+		
+		hFile:write "\n"
+
+		return indexed
+	end
+
+	
+	local function WriteInMainFuncLoader(hFile, func, spec, options)
+		hFile:fmt('%s = reinterpret_cast<%s>(%s("%s%s"));\n',
+			GenFuncPtrName(func, spec, options),
+			GenFuncPtrTypedefName(func, spec, options),
+			common.GetProcAddressName(spec),
+			spec.FuncNamePrefix(), func.name)
+		hFile:fmt('if(!%s) return exts::LoadTest();\n',
+			GenFuncPtrName(func, spec, options))
+	end
+
 function my_style.source.WriteMainLoaderFunc(hFile, specData, spec, options)
-	--Writes the actual loader function. Possibly also some utilities used
-	--by it.
+	StartNamespace(hFile)
+	local indexed = WriteAncillaryFuncs(hFile, specData, spec, options)
+	EndNamespace(hFile)
+	
+	hFile:write "\n"
+	
+	hFile:fmt("exts::LoadTest LoadFunctions(%s)\n", spec.GetLoaderParams())
+	hFile:write("{\n")
+	hFile:inc()
+	hFile:writeblock[[
+ClearExtensionVars();
+std::vector<MapEntry> table;
+InitializeMappingTable(table);
+]]
+	hFile:write("\n")
+	
+	if(indexed) then
+		WriteInMainFuncLoader(hFile, indexed[1], spec, options)
+		WriteInMainFuncLoader(hFile, indexed[3], spec, options)
+		hFile:write("\n")
+		hFile:write("ProcExtsFromExtList(table);\n")
+	else
+		local extListName, needLoad = spec.GetExtStringFuncName()
+		if(needLoad) then
+			for _, func in ipairs(specData.funcData.functions) do
+				if(extListName == func.name) then
+					extListName = func
+					break
+				end
+			end
+			
+			WriteInMainFuncLoader(hFile, extListName, spec, options)
+			
+			extListName = GenQualifiedFuncPtrName(extListName, spec, options);
+		end
+
+		local function EnumResolve(enumName)
+			return GenQualifiedEnumName(specData.enumtable[enumName], spec, options)
+		end
+		
+		hFile:write "\n"
+		hFile:fmt("ProcExtsFromExtString((const char *)%s(%s), table);\n",
+			extListName,
+			spec.GetExtStringParamList(EnumResolve))
+	end
+	
+	if(options.version) then
+		hFile:write "\n"
+		hFile:fmt("int numFailed = %s();\n",
+			GenCoreLoaderFuncName(options.version, spec, options))
+		
+		hFile:write("return exts::LoadTest(true, numFailed);\n")
+	else
+		hFile:fmt("return exts::LoadTest(true, 0);\n")
+	end
+
+
+	hFile:dec()
+	hFile:write("}\n")
 end
 
 function my_style.source.WriteVersioningFuncs(hFile, specData, spec, options)
-	--Write definitions for versioning functions.
-	--Will only be called if using a spec that has a version (ie: OpenGL).
+	hFile:fmt("static int g_major_version = 0;\n")
+	hFile:fmt("static int g_minor_version = 0;\n")
+	hFile:write "\n"
+	
+	if(tonumber(options.version) >= 3.0) then
+		hFile:writeblock([[
+static void GetGLVersion()
+{
+	GetIntegerv(MAJOR_VERSION, &g_major_version);
+	GetIntegerv(MINOR_VERSION, &g_minor_version);
+}
+]])
+	else
+		hFile:writeblock(common.GetParseVersionFromString())
+		hFile:write "\n"
+		
+		hFile:writeblock([[
+static void GetGLVersion()
+{
+	ParseVersionFromString(&g_major_version, &g_minor_version, GetString(VERSION));
+}
+]])
+	end
+	
+	hFile:write "\n"
+	hFile:writeblock([[
+int GetMinorVersion()
+{
+	if(g_major_version == 0)
+		GetGLVersion();
+	return g_major_version;
+}
+]])
+	hFile:write "\n"
+
+	hFile:writeblock([[
+int GetMajorVersion()
+{
+	if(g_major_version == 0) //Yes, check the major version to get the minor one.
+		GetGLVersion();
+	return g_minor_version;
+}
+]])
+	hFile:write "\n"
+	
+	hFile:writeblock([[
+bool IsVersionGEQ(int majorVersion, int minorVersion)
+{
+	if(g_major_version == 0)
+		GetGLVersion();
+		
+	if(majorVersion > g_major_version) return true;
+	if(majorVersion < g_major_version) return false;
+	if(minorVersion >= g_minor_version) return true;
+	return false;
+}
+]])
+
 end
 
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "gl_load.h"
-#include "wgl_load.h"
+#include "gl_test_cpp.hpp"
+#include "wgl_test_cpp.hpp"
 #include <GL/freeglut.h>
 
 GLuint positionBufferObject;
 
 GLuint BuildShader(GLenum eShaderType, const std::string &shaderText)
 {
-	GLuint shader = glCreateShader(eShaderType);
+	GLuint shader = gl::CreateShader(eShaderType);
 	const char *strFileData = shaderText.c_str();
-	glShaderSource(shader, 1, &strFileData, NULL);
+	gl::ShaderSource(shader, 1, &strFileData, NULL);
 
-	glCompileShader(shader);
+	gl::CompileShader(shader);
 
 	GLint status;
-	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
-	if (status == GL_FALSE)
+	gl::GetShaderiv(shader, gl::COMPILE_STATUS, &status);
+	if(!status)
 	{
 		GLint infoLogLength;
-		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+		gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &infoLogLength);
 
 		GLchar *strInfoLog = new GLchar[infoLogLength + 1];
-		glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
+		gl::GetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
 
 		const char *strShaderType = NULL;
 		switch(eShaderType)
 		{
-		case GL_VERTEX_SHADER: strShaderType = "vertex"; break;
-//		case GL_GEOMETRY_SHADER: strShaderType = "geometry"; break;
-		case GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
+		case gl::VERTEX_SHADER: strShaderType = "vertex"; break;
+//		case gl::GEOMETRY_SHADER: strShaderType = "geometry"; break;
+		case gl::FRAGMENT_SHADER: strShaderType = "fragment"; break;
 		}
 
 		fprintf(stderr, "Compile failure in %s shader:\n%s\n", strShaderType, strInfoLog);
 
 void init()
 {
-	glGenVertexArrays(1, &vao);
-	glBindVertexArray(vao);
+	gl::GenVertexArrays(1, &vao);
+	gl::BindVertexArray(vao);
 
 	const float vertexPositions[] = {
 		0.75f, 0.75f, 0.0f, 1.0f,
 		-0.75f, -0.75f, 0.0f, 1.0f,
 	};
 
-	glGenBuffers(1, &positionBufferObject);
-	glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
-	glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
-	glBindBuffer(GL_ARRAY_BUFFER, 0);
+	gl::GenBuffers(1, &positionBufferObject);
+	gl::BindBuffer(gl::ARRAY_BUFFER, positionBufferObject);
+	gl::BufferData(gl::ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, gl::STATIC_DRAW);
+	gl::BindBuffer(gl::ARRAY_BUFFER, 0);
 
 	const std::string vertexShader(
 		"#version 330\n"
 		"}\n"
 		);
 
-	GLuint vertShader = BuildShader(GL_VERTEX_SHADER, vertexShader);
-	GLuint fragShader = BuildShader(GL_FRAGMENT_SHADER, fragmentShader);
+	GLuint vertShader = BuildShader(gl::VERTEX_SHADER, vertexShader);
+	GLuint fragShader = BuildShader(gl::FRAGMENT_SHADER, fragmentShader);
 
-	program = glCreateProgram();
-	glAttachShader(program, vertShader);
-	glAttachShader(program, fragShader);	
-	glLinkProgram(program);
+	program = gl::CreateProgram();
+	gl::AttachShader(program, vertShader);
+	gl::AttachShader(program, fragShader);	
+	gl::LinkProgram(program);
 
 	GLint status;
-	glGetProgramiv (program, GL_LINK_STATUS, &status);
-	if (status == GL_FALSE)
+	gl::GetProgramiv (program, gl::LINK_STATUS, &status);
+	if(!status)
 	{
 		GLint infoLogLength;
-		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
+		gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &infoLogLength);
 
 		GLchar *strInfoLog = new GLchar[infoLogLength + 1];
-		glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
+		gl::GetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
 		fprintf(stderr, "Linker failure: %s\n", strInfoLog);
 		delete[] strInfoLog;
 
 //If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
 void display()
 {
-	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
-	glClear(GL_COLOR_BUFFER_BIT);
+	gl::ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+	gl::Clear(gl::COLOR_BUFFER_BIT);
 
-	glUseProgram(program);
+	gl::UseProgram(program);
 
-	glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
-	glEnableVertexAttribArray(0);
-	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
+	gl::BindBuffer(gl::ARRAY_BUFFER, positionBufferObject);
+	gl::EnableVertexAttribArray(0);
+	gl::VertexAttribPointer(0, 4, gl::FLOAT, gl::FALSE_, 0, 0);
 
-	glDrawArrays(GL_TRIANGLES, 0, 3);
+	gl::DrawArrays(gl::TRIANGLES, 0, 3);
 
-	glDisableVertexAttribArray(0);
-	glUseProgram(0);
+	gl::DisableVertexAttribArray(0);
+	gl::UseProgram(0);
 
 	glutSwapBuffers();
 }
 //This is an opportunity to call glViewport or glScissor to keep up with the change in size.
 void reshape (int w, int h)
 {
-	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
+	gl::Viewport(0, 0, (GLsizei) w, (GLsizei) h);
 }
 
 //Called whenever a key on the keyboard was pressed.
 
 	glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
 
-	ogl_LoadFunctions();
+	gl::exts::LoadTest test = gl::sys::LoadFunctions();
+
+	if(test)
+		printf("%i\n", test.GetNumMissing());
+	else
+		return 1;
 
 	init();