Commits

Jason McKesson committed ec5a2ef

Generation code is complete, but not debugged.

Comments (0)

Files changed (6)

 ]]
 end
 
+function common.GetParseVersionFromString()
+	return [[
+static void ParseVersionFromString(int *pOutMajor, int *pOutMinor, const char *strVersion)
+{
+	const char *strDotPos = NULL;
+	int iLength = 0;
+	char strWorkBuff[10];
+	*pOutMinor = 0;
+	*pOutMajor = 0;
+
+	strDotPos = strchr(strVersion, '.');
+	if(!strDotPos)
+		return;
+
+	iLength = (int)((ptrdiff_t)strDotPos - (ptrdiff_t)strVersion);
+	strncpy(strWorkBuff, strVersion, iLength);
+	strWorkBuff[iLength] = '\0';
+
+	*pOutMajor = atoi(strWorkBuff);
+	strDotPos = strchr(strVersion + iLength + 1, ' ');
+	if(!strDotPos)
+	{
+		//No extra data. Take the whole rest of the string.
+		strcpy(strWorkBuff, strVersion + iLength + 1);
+	}
+	else
+	{
+		//Copy only up until the space.
+		int iLengthMinor = (int)((ptrdiff_t)strDotPos - (ptrdiff_t)strVersion);
+		iLengthMinor = iLengthMinor - (iLength + 1);
+		strncpy(strWorkBuff, strVersion + iLength + 1, iLengthMinor);
+		strWorkBuff[iLengthMinor] = '\0';
+	}
+
+	*pOutMinor = atoi(strWorkBuff);
+}
+]]
+end
+
 local function DeepCopyTable(tbl)
 	local ret = {}
 	for key, value in pairs(tbl) do

StylePointerC.lua

 
 function my_style.header.WriteEndEnumDeclBlock(hFile, specData, options) end
 
+local function GetEnumName(enum, spec, options)
+	return spec.EnumNamePrefix() .. enum.name
+end
+
 function my_style.header.WriteEnumDecl(hFile, enum, enumTable, spec, options)
-	hFile:fmt("#define %s%s = %s\n",
-		spec.EnumNamePrefix(),
-		enum.name,
+	hFile:fmt("#define %s = %s\n",
+		GetEnumName(enum, spec, options),
 		common.ResolveEnumValue(enum, enumTable))
 end
 
 	hFile:inc()
 		hFile:write(GetStatusCodeName("LOAD_FAILED", spec, options), " = 0,\n")
 		hFile:write(GetStatusCodeName("LOAD_SUCCEEDED", spec, options), " = 1,\n")
-		hFile:write(GetStatusCodeName("LOAD_PARTIAL", spec, options), " = 2,\n")
+--		hFile:write(GetStatusCodeName("LOAD_PARTIAL", spec, options), " = 2,\n")
 	hFile:dec()
 	hFile:write("};\n")
 end
 end
 
 function my_style.header.WriteMainLoaderFuncDecl(hFile, spec, options)
-	hFile:fmt("%s %s(%s);\n",
-		GetStatusCodeEnumName(spec, options),
+	hFile:fmt("int %s(%s);\n",
 		GetLoaderFuncName(spec, options),
 		spec.GetLoaderParams())
 end
 	
 	hFile:fmt("int %s();\n", DecorateFuncName("GetMinorVersion", spec, options))
 	hFile:fmt("int %s();\n", DecorateFuncName("GetMajorVersion", spec, options))
-	hFile:fmt("int %s(int iMajorVersion, int iMinorVersion);\n",
+	hFile:fmt("int %s(int majorVersion, int minorVersion);\n",
 		DecorateFuncName("IsVersionGEQ", spec, options))
 end
 
 	end
 end
 
+function my_style.source.WriteGetExtStringFuncDef(hFile, func, typemap, spec, options)
+	my_style.source.WriteFuncDef(hFile, func, typemap, spec, options)
+end
+
 local function GetMapTableStructName(spec, options)
 	return string.format("%s%sStrToExtMap", options.prefix, spec.DeclPrefix())
 end
 			else
 			{
 				*(entry->extensionVariable) = ]] ..
-				GetStatusCodeName("LOAD_PARTIAL", spec, options) ..
+				GetStatusCodeName("LOAD_SUCCEEDED", spec, options) ..
 				[[ + numFailed;
 			}
 		}
 	
 end
 
-function my_style.source.WriteMainLoaderFunc(hFile, specData, spec, options)
-	--Write our ancillary extension function, per the spec/options
-
-	--Write a function that walks the extension string and processes each one.
-	hFile:writeblock(common.GetProcessExtsFromStringFunc("LoadExtByName"))
-end
-
-function my_style.source.WriteVersioningFuncs(hFile, specData, 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()
 {
 	GLint iLoop;
 	GLint iNumExtensions = 0;
-	_ptrc_glGetIntegerv(GL_NUM_EXTENSIONS, &iNumExtensions);
+	]] .. GetFuncPtrName(indexed[1], spec, options)
+	.. [[(]] .. GetEnumName(indexed[2], spec, options)
+	.. [[, &iNumExtensions);
 
 	for(iLoop = 0; iLoop < iNumExtensions; iLoop++)
 	{
-		const char *strExtensionName = (const char *)_ptrc_glGetStringi(GL_EXTENSIONS, iLoop);
+		const char *strExtensionName = (const char *)]] ..
+		GetFuncPtrName(indexed[3], spec, options) ..
+		[[(]] .. GetEnumName(indexed[4], spec, options) .. [[, iLoop);
 		LoadExtByName(strExtensionName)
 	}
 }
-]];
+]])
+	elseif(options.version) then
+		hFile:writeblock(common.GetProcessExtsFromStringFunc("LoadExtByName"))
+	end
+	
+	hFile:write "\n"
 
-[[
-int LoaderFunction()
+	return indexed
+end
+
+local function WriteInMainFuncLoader(hFile, func, spec, options)
+	hFile:fmt('%s = %s("%s%s");\n',
+		GetFuncPtrName(func, spec, options),
+		common.GetProcAddressName(spec),
+		spec.FuncNamePrefix(), func.name)
+	hFile:fmt('if(!%s) return %s;\n',
+		GetFuncPtrName(func, spec, options),
+		GetStatusCodeName("LOAD_FAILED", spec, options))
+end
+
+
+function my_style.source.WriteMainLoaderFunc(hFile, specData, spec, options)
+	local indexed = WriteAncillaryFuncs(hFile, specData, spec, options)
+
+	--Write the function that calls the extension and core loaders.
+	hFile:fmt("int %s(%s)\n",
+		GetLoaderFuncName(spec, options),
+		spec.GetLoaderParams())
+	hFile:write("{\n")
+	hFile:inc()
+	
+	hFile:writeblock([[
+int numFailed = 0;
+ClearExtensionVars();
+	
+]])
+
+	--Load the extension, using runtime-facilities to tell what is available.
+	if(indexed) then
+		WriteInMainFuncLoader(hFile, indexed[1], spec, options)
+		WriteInMainFuncLoader(hFile, indexed[3], spec, options)
+		hFile:write("\n")
+		hFile:write("ProcExtsFromExtList();\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
+				end
+			end
+			
+			WriteInMainFuncLoader(hFile, extListName, spec, options)
+			
+			extListName = GetFuncPtrName(extListName, spec, options);
+		end
+
+		local function EnumResolve(enumName)
+			return GetEnumName(specData.enumtable[enumName], spec, options)
+		end
+		
+		hFile:write "\n"
+		hFile:fmt("ProcExtFromExtString((const char *)%s(%s));\n",
+			extListName,
+			spec.GetExtStringParamList(EnumResolve))
+	end
+	
+	hFile:fmt("numFailed = %s();\n",
+		GetCoreLoaderFuncName(options.version, spec, options))
+	hFile:write "\n"
+	
+	hFile:fmtblock([[
+if(numFailed == 0)
+	return %s;
+else
+	return %s + numFailed;
+]],
+		GetStatusCodeName("LOAD_SUCCEEDED", spec, options),
+		GetStatusCodeName("LOAD_SUCCEEDED", spec, options))
+	
+	hFile:dec()
+	hFile:write("}\n")
+end
+
+function my_style.source.WriteVersioningFuncs(hFile, specData, spec, options)
+	--Only for GL
+	if(options.spec ~= "gl") then
+		return
+	end
+	
+	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()
 {
-	int numFailed = 0;
-	ClearExtensionVars();
+	glGetIntegerv(GL_MAJOR_VERSION, &g_major_version);
+	glGetIntegerv(GL_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, glGetString(GL_VERSION));
+}
+]])
+	end
 	
-	{
-		_ptrc_glGetString = IntGetProcAddress("glGetString");
-		if(!_ptrc_glGetString) return ogl_LOAD_FAILED;	
+	hFile:write "\n"
+	hFile:fmt("int %s()\n", DecorateFuncName("GetMinorVersion", spec, options))
+	hFile:writeblock([[
+{
+	if(g_major_version == 0)
+		GetGLVersion();
+	return g_major_version
+}
+]])
+	hFile:write "\n"
+
+	hFile:fmt("int %s()\n", DecorateFuncName("GetMajorVersion", spec, options))
+	hFile:writeblock([[
+{
+	if(g_major_version == 0) //Yes, check the major version to get the minor one.
+		GetGLVersion();
+	return g_minor_version
+}
+]])
+	hFile:write "\n"
+	
+	hFile:fmt("int %s(int majorVersion, int minorVersion)\n",
+		DecorateFuncName("IsVersionGEQ", spec, options))
+	hFile:writeblock([[
+{
+	if(g_major_version == 0)
+		GetGLVersion();
 		
-		ProcExtFromExtString((const char *)_ptrc_glGetString(GL_EXTENSIONS));
-	}
-	else
-	{
-		_ptrc_glGetStringi = IntGetProcAddress("glGetStringi");
-		if(!_ptrc_glGetStringi) return ogl_LOAD_FAILED;	
-		_ptrc_glGetIntegerv = IntGetProcAddress("glGetIntegerv");
-		if(!_ptrc_glGetIntegerv) return ogl_LOAD_FAILED;	
-	}
-	
-	numFailed = Load_Version_3_3()
-	
-	if(numFailed == 0)
-		return ogl_LOAD_SUCCEEDED;
-	else
-		return ogl_LOAD_PARTIAL + numFailed;
+	if(majorVersion > g_major_version) return 1;
+	if(majorVersion < g_major_version) return 0;
+	if(minorVersion >= g_minor_version) return 1;
+	return 0;
 }
-]];
+]])
 
-]=]
+end
+
+
+
 --------------------------------------------------
 -- Style retrieval machinery
 
 					version, options, spec, style, specData)
 
 				hFile:write("\n")
-				table.insert(writtenData.corefuncs, funcList)
 			end
 		end
 	end
 	
-	--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.
 	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
 					funcList, options, spec, style, specData)
 			end
 		end
-
 		source.WriteEndCoreLoaderBlock(hFile, options.version, spec, options)
-
+		
 		source.WriteEndCoreFuncDefBlock(hFile, options.version, spec, options)
 	end
+	
+	local function FindFuncName(funcName)
+		for _, func in ipairs(specData.funcData.functions) do
+			if(func.name == funcName) then
+				return func
+			end
+		end
+		
+		return nil
+	end
+	
+	--Write the function declaration needed to load the extension string.
+	--But only if it's available in the spec data and hasn't already been written.
+	local funcExtString = FindFuncName(spec.GetExtStringFuncName())
+	if(funcExtString and not funcSeen[spec.GetExtStringFuncName()]) then
+		hFile:write("\n")
+		source.WriteGetExtStringFuncDef(hFile, funcExtString,
+			specData.typemap, spec, options)
+	end
 end
 
 local function BuildSource(options, spec, style, specData, basename,
 	
 	--Write utility definitions needed by the loader.
 	source.WriteUtilityDefs(hFile, specData, spec, options)
+	hFile:write "\n"
 	
 	--Write the main loading function which loads everything.
 	source.WriteMainLoaderFunc(hFile, specData, spec, options)
+	hFile:write "\n"
 	
 	--Write any additional functions that load other things.
+	source.WriteVersioningFuncs(hFile, specData, spec, options)
+	hFile:write "\n"
 
 	--Write any definitions scoping end.
 	source.WriteEndDef(hFile, spec, options)
 function wgl_spec.GetPtrLoaderFuncName() return "IntGetProcAddress" end
 function glx_spec.GetPtrLoaderFuncName() return "IntGetProcAddress" end
 
+--Name of extension string function. Also returns true if this function needs to be loaded. If false is returned, then use the string name *exactly as is*.
+function gl_spec.GetExtStringFuncName() return "GetString", true end
+function wgl_spec.GetExtStringFuncName() return "GetExtensionsStringARB", true end
+function glx_spec.GetExtStringFuncName() return "glXQueryExtensionsString", false end
+
+--Gets the list of parameters that the extension string function will use. No (), just the internals. Pass a function used to resolve enumerator names into actual enumerator identifiers.
+function gl_spec.GetExtStringParamList(enumResolve)
+	return enumResolve("EXTENSIONS")
+end
+function wgl_spec.GetExtStringParamList(enumResolve) return "hdc" end
+function glx_spec.GetExtStringParamList(enumResolve) return "display, screen" end
+
+--Returns a table if it should use the indexed extension string functions. Returns false/nil otherwise.
+-- The table is an array of:
+--	Function name used to get the number of extensions.
+--	Enumerator name used to get the number of extensions.
+--	Function name used to get an extension string.
+--	Enumerator name used to get an extension string.
+function gl_spec.GetIndexedExtStringFunc(options)
+	if(tonumber(options.version) >= 3.0) then
+		return {"GetIntegerv", "NUM_EXTENSIONS", "GetStringi", "EXTENSIONS"}
+	end
+	return nil
+end
+function wgl_spec.GetIndexedExtStringFunc(options) return nil end
+function glx_spec.GetIndexedExtStringFunc(options) return nil end
+
 local fileProps =
 {
 	{"GetHeaderInit", "init"},
 - source.WriteEndCoreFuncDefBlock(hFile, version, spec, options)
 --	Writes the end of the core loader's block that contains function pointer definitions and the loader function for `version`.
 
+- source.WriteGetExtStringFuncDef(hFile, func, typemap, spec, options)
+--	Writes a function definition for the function that gets the extension string list. It is written outside of ALL block definitions, so if you need scoping, scope it internally. Will only be called if the function's definition was not previously written.
+
 - source.WriteBeginCoreLoaderBlock(hFile, version, spec, options)
 --	Writes the start of the actual function that loads the function pointers for `version`.
 
 - fmt: As string.format followed by an indented write
 - write: An indented write; everything is written after the indent.
 - writeblock: Takes a single string, breaks it down into multiple lines, and writes each line indented.
+- fmtblock: As string.format, followed by calling `writeblock`.
 - rawfmt: As string.format followed by a NON-indented write.
 - rawwrite: hFile:write.
 
+
 Each call to one of the non-raw writing functions will indent the text.
 ]]
 
 	end
 	
 	local last = block:match("\n([^\n]*)$")
-	if(#last ~= 0) then
+	if(last and #last ~= 0) then
 		self:write(last)
 	end
 end
 
+function members:fmtblock(block, ...)
+	self:writeblock(block:format(...))
+end
+
 function members:rawwrite(...)
 	rawget(self, "_hFile"):write(...)
 end