558 lines
15 KiB
Lua
558 lines
15 KiB
Lua
--[[Useful style utility functions. This file will contain commonly useful strings and functions that generate useful data.]]
|
|
|
|
local util = require "util"
|
|
local struct = require "Structure"
|
|
|
|
local common = {}
|
|
|
|
--Creates a tabbed file.
|
|
function common.CreateFile(filename, indent)
|
|
return util.CreateFile(filename, indent)
|
|
end
|
|
|
|
--Retrieves the common typedefs used by OpenGL 1.1.
|
|
function common.GetStdTypedefs()
|
|
return dofile(util.GetDataFilePath() .. "style_commontypedefs.lua")
|
|
end
|
|
|
|
--Writes passthru data from the specData, with proper indentation.
|
|
function common.WritePassthruData(hFile, strArray)
|
|
for _, str in ipairs(strArray) do
|
|
--unindent after #endif
|
|
if(str:match("^#endif") or str:match("^#elif")) then
|
|
hFile:dec()
|
|
end
|
|
|
|
hFile:write(str, "\n")
|
|
|
|
--Indent after #if.
|
|
if(str:match("^#if") or str:match("^#elif")) then
|
|
hFile:inc()
|
|
end
|
|
end
|
|
end
|
|
|
|
function common.WriteExternCStart(hFile)
|
|
hFile:write("#ifdef __cplusplus\n")
|
|
hFile:write('extern "C" {\n')
|
|
hFile:write("#endif /*__cplusplus*/\n")
|
|
hFile:write("\n")
|
|
end
|
|
|
|
function common.WriteExternCEnd(hFile)
|
|
hFile:write("#ifdef __cplusplus\n")
|
|
hFile:write('}\n')
|
|
hFile:write("#endif /*__cplusplus*/\n")
|
|
hFile:write("\n")
|
|
end
|
|
|
|
--Determines the value of the enumeration.
|
|
local function ResolveEnumValue(enum, enumTable)
|
|
if(enum.copy) then
|
|
return common.ResolveEnumValue(enumTable[enum.value], enumTable),
|
|
enum.value;
|
|
else
|
|
return enum.value;
|
|
end
|
|
end
|
|
common.ResolveEnumValue = ResolveEnumValue
|
|
|
|
function common.GetCppEnumName(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
|
|
end
|
|
|
|
--Also, certain identifiers can need it because they conflict.
|
|
local badIdent = {"TRUE", "FALSE", "NO_ERROR", "WAIT_FAILED", "DOMAIN"}
|
|
for _, ident in ipairs(badIdent) do
|
|
if(enumName == ident) then
|
|
enumName = enumName .. "_"
|
|
break
|
|
end
|
|
end
|
|
|
|
return enumName
|
|
end
|
|
|
|
function common.GetNameLengthPadding(name, length)
|
|
local numSpaces = length - #name
|
|
if(numSpaces < 1) then
|
|
numSpaces = 1
|
|
end
|
|
|
|
return string.rep(" ", numSpaces)
|
|
end
|
|
|
|
--Gets the return type for a function.
|
|
function common.GetFuncReturnType(func)
|
|
return func["return_ctype"]
|
|
end
|
|
|
|
function common.DoesFuncReturnSomething(func)
|
|
local returnType = func["return_ctype"]
|
|
return (returnType == "void") or (returnType == "GLvoid")
|
|
end
|
|
|
|
local bIsKindPtr ={
|
|
value = false,
|
|
array = true,
|
|
reference = true,
|
|
};
|
|
|
|
--Important due to name conflicts. Some names have to re-mapped to others.
|
|
--Won't really affect things.
|
|
local paramNameRemap = {
|
|
near = "ren_near",
|
|
far = "ren_far",
|
|
array = "ren_array",
|
|
};
|
|
|
|
--Returns the parameter list as a string.
|
|
--Parameter list does not include parenthesis.
|
|
function common.GetFuncParamList(func, bWriteVarNames)
|
|
local paramList = {}
|
|
for i, param in ipairs(func.parameters) do
|
|
local paramType = param.ctype;
|
|
if(bWriteVarNames) then
|
|
local paramName = param.name
|
|
if(paramNameRemap[paramName]) then paramName = paramNameRemap[paramName]end
|
|
paramList[#paramList + 1] = string.format("%s %s", paramType, paramName)
|
|
else
|
|
paramList[#paramList + 1] = paramType
|
|
end
|
|
end
|
|
|
|
return table.concat(paramList, ", ");
|
|
end
|
|
|
|
--Get the list of parameter names, as a string ready to be put into ().
|
|
function common.GetFuncParamCallList(func)
|
|
local paramList = {}
|
|
for i, param in ipairs(func.parameters) do
|
|
local paramName = param.name
|
|
if(paramNameRemap[paramName]) then
|
|
paramName = paramNameRemap[paramName]
|
|
end
|
|
|
|
paramList[#paramList + 1] = paramName
|
|
end
|
|
|
|
return table.concat(paramList, ", ");
|
|
end
|
|
|
|
--Retrieves the name of the function according to OpenGL.
|
|
function common.GetOpenGLFuncName(func, spec)
|
|
return spec.FuncNamePrefix() .. func.name
|
|
end
|
|
|
|
function common.GetProcAddressName(spec)
|
|
return spec.GetPtrLoaderFuncName()
|
|
end
|
|
|
|
function common.FixupIndexedList(specData, indexed)
|
|
assert(indexed)
|
|
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.enumerators) do
|
|
if(indexed[2] == enum.name) then
|
|
indexed[2] = enum
|
|
end
|
|
if(indexed[4] == enum.name) then
|
|
indexed[4] = enum
|
|
end
|
|
end
|
|
end
|
|
|
|
function common.GetProcExtsFromExtListFunc(hFile, specData, spec, options,
|
|
indexed, GetFuncPtrName, GetEnumName)
|
|
return [[
|
|
static void ProcExtsFromExtList()
|
|
{
|
|
GLint iLoop;
|
|
GLint iNumExtensions = 0;
|
|
]] .. GetFuncPtrName(indexed[1], spec, options)
|
|
.. [[(]] .. GetEnumName(indexed[2], spec, options)
|
|
.. [[, &iNumExtensions);
|
|
|
|
for(iLoop = 0; iLoop < iNumExtensions; iLoop++)
|
|
{
|
|
const char *strExtensionName = (const char *)]] ..
|
|
GetFuncPtrName(indexed[3], spec, options) ..
|
|
[[(]] .. GetEnumName(indexed[4], spec, options) .. [[, iLoop);
|
|
LoadExtByName(strExtensionName);
|
|
}
|
|
}
|
|
]]
|
|
end
|
|
|
|
--You give it a function that takes a const char*.
|
|
function common.GetProcessExtsFromStringFunc(funcFormat, arguments)
|
|
return [[
|
|
static void ProcExtsFromExtString(const char *strExtList]] .. (arguments or "") .. [[)
|
|
{
|
|
size_t iExtListLen = strlen(strExtList);
|
|
const char *strExtListEnd = strExtList + iExtListLen;
|
|
const char *strCurrPos = strExtList;
|
|
char strWorkBuff[256];
|
|
|
|
while(*strCurrPos)
|
|
{
|
|
/*Get the extension at our position.*/
|
|
int iStrLen = 0;
|
|
const char *strEndStr = strchr(strCurrPos, ' ');
|
|
int iStop = 0;
|
|
if(strEndStr == NULL)
|
|
{
|
|
strEndStr = strExtListEnd;
|
|
iStop = 1;
|
|
}
|
|
|
|
iStrLen = (int)((ptrdiff_t)strEndStr - (ptrdiff_t)strCurrPos);
|
|
|
|
if(iStrLen > 255)
|
|
return;
|
|
|
|
strncpy(strWorkBuff, strCurrPos, iStrLen);
|
|
strWorkBuff[iStrLen] = '\0';
|
|
|
|
]] .. funcFormat:format("strWorkBuff") ..[[;
|
|
|
|
strCurrPos = strEndStr + 1;
|
|
if(iStop) break;
|
|
}
|
|
}
|
|
]]
|
|
end
|
|
|
|
function common.WriteProcessExtsFromStringFunc(hFile, ...)
|
|
hFile:writeblock(common.GetProcessExtsFromStringFunc(...))
|
|
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
|
|
if(type(value) == "table") then
|
|
ret[key] = DeepCopyTable(value)
|
|
else
|
|
ret[key] = value
|
|
end
|
|
end
|
|
return ret
|
|
end
|
|
|
|
function common.WriteCMappingTable(hFile, specData, spec,
|
|
options, structName, varName, GetExtVariableName, GetExtLoaderFuncName)
|
|
--Write the struct for the mapping table.
|
|
hFile:write("typedef int (*PFN_LOADFUNCPOINTERS)();\n")
|
|
hFile:fmt("typedef struct %s%sStrToExtMap_s\n",
|
|
options.prefix, spec.DeclPrefix())
|
|
hFile:write("{\n")
|
|
hFile:inc()
|
|
hFile:write("char *extensionName;\n")
|
|
hFile:write("int *extensionVariable;\n")
|
|
hFile:write("PFN_LOADFUNCPOINTERS LoadExtension;\n")
|
|
hFile:dec()
|
|
hFile:fmt("} %s;\n", structName)
|
|
hFile:write "\n"
|
|
|
|
--Write the mapping table itself.
|
|
local arrayLength = #options.extensions
|
|
if(arrayLength == 0) then arrayLength = 1 end
|
|
hFile:fmt("static %s %s[%i] = {\n",
|
|
structName,
|
|
varName,
|
|
arrayLength)
|
|
hFile:inc()
|
|
for _, extName in ipairs(options.extensions) do
|
|
if(#specData.extdefs[extName].funcs > 0) then
|
|
hFile:fmt('{"%s", &%s, %s},\n',
|
|
spec.ExtNamePrefix() .. extName,
|
|
GetExtVariableName(extName, spec, options),
|
|
GetExtLoaderFuncName(extName, spec, options))
|
|
else
|
|
hFile:fmt('{"%s", &%s, NULL},\n',
|
|
spec.ExtNamePrefix() .. extName,
|
|
GetExtVariableName(extName, spec, options))
|
|
end
|
|
end
|
|
--Because C is stupid, write bogus entry.
|
|
if(#options.extensions == 0) then
|
|
hFile:fmt('{"", NULL, NULL},\n')
|
|
end
|
|
hFile:dec()
|
|
hFile:write("};\n")
|
|
|
|
hFile:write "\n"
|
|
hFile:fmt("static int g_extensionMapSize = %i;\n", #options.extensions);
|
|
end
|
|
|
|
function common.WriteCFindExtEntryFunc(hFile, specData, spec,
|
|
options, structName, varName, sizeName)
|
|
hFile:fmt("static %s *FindExtEntry(const char *extensionName)\n",
|
|
structName)
|
|
hFile:write("{\n")
|
|
hFile:inc()
|
|
hFile:write("int loop;\n")
|
|
hFile:fmt("%s *currLoc = %s;\n",
|
|
structName,
|
|
varName)
|
|
hFile:writeblock([[
|
|
for(loop = 0; loop < g_extensionMapSize; ++loop, ++currLoc)
|
|
{
|
|
if(strcmp(extensionName, currLoc->extensionName) == 0)
|
|
return currLoc;
|
|
}
|
|
|
|
return NULL;
|
|
]])
|
|
hFile:dec()
|
|
hFile:write("}\n")
|
|
end
|
|
|
|
function common.WriteCClearExtensionVarsFunc(hFile, specData, spec,
|
|
options, GetExtVariableName, clearValue)
|
|
hFile:fmt("static void ClearExtensionVars()\n")
|
|
hFile:write("{\n")
|
|
hFile:inc()
|
|
for _, extName in ipairs(options.extensions) do
|
|
hFile:fmt('%s = %s;\n',
|
|
GetExtVariableName(extName, spec, options),
|
|
clearValue)
|
|
end
|
|
hFile:dec()
|
|
hFile:write("}\n")
|
|
hFile:write "\n"
|
|
end
|
|
|
|
--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.
|
|
function common.WriteCLoadExtByNameFunc(hFile, specData, spec,
|
|
options, structName, successValue)
|
|
hFile:writeblock([[
|
|
static void LoadExtByName(const char *extensionName)
|
|
{
|
|
]] .. structName .. [[ *entry = NULL;
|
|
entry = FindExtEntry(extensionName);
|
|
if(entry)
|
|
{
|
|
if(entry->LoadExtension)
|
|
{
|
|
int numFailed = entry->LoadExtension();
|
|
if(numFailed == 0)
|
|
{
|
|
*(entry->extensionVariable) = ]] ..
|
|
successValue ..
|
|
[[;
|
|
}
|
|
else
|
|
{
|
|
*(entry->extensionVariable) = ]] ..
|
|
successValue ..
|
|
[[ + numFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*(entry->extensionVariable) = ]] ..
|
|
successValue ..
|
|
[[;
|
|
}
|
|
}
|
|
}
|
|
]])
|
|
end
|
|
|
|
function common.WriteNamespaceBegin(hFile, namespace)
|
|
hFile:fmt("namespace %s\n", namespace)
|
|
hFile:write("{\n")
|
|
hFile:inc()
|
|
end
|
|
|
|
function common.WriteNamespaceEnd(hFile)
|
|
hFile:dec()
|
|
hFile:write("}\n")
|
|
end
|
|
|
|
|
|
common.DeepCopyTable = DeepCopyTable
|
|
|
|
local my_struct =
|
|
{
|
|
{ type="file", style="header", name="GetFilename",
|
|
{ type="write", name="FilePreamble", optional=true} ,
|
|
{ type="block", name="IncludeGuard(hFile, spec, options)",
|
|
{ type="blank"},
|
|
{ type="write", name="Init(hFile, spec, options)", },
|
|
{ type="blank"},
|
|
{ type="write", name="StdTypedefs(hFile, specData, options)",},
|
|
{ type="blank"},
|
|
{ type="write", name="SpecTypedefs(hFile, specData, options)",},
|
|
{ type="blank"},
|
|
{ type="block", name="Decl(hFile, spec, options)",
|
|
{ type="block", name="ExtVarDecl(hFile, spec, options)",
|
|
{ type="ext-iter",
|
|
{ type="write", name="ExtVariableDecl(hFile, extName, specData, spec, options)" },
|
|
{ type="blank", last=true },
|
|
},
|
|
},
|
|
{ type="block", name="EnumDecl(hFile, spec, options)",
|
|
{ type="enum-seen",
|
|
{ type="ext-iter",
|
|
{type="enum-iter",
|
|
{ type="write", name="EnumDecl(hFile, enum, enumTable, spec, options, enumSeen)", },
|
|
{ type="blank", last=true },
|
|
},
|
|
},
|
|
{ type="version-iter",
|
|
{type="enum-iter",
|
|
{ type="write", name="EnumDecl(hFile, enum, enumTable, spec, options, enumSeen)", },
|
|
{ type="blank", last=true },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{ type="block", name="FuncDecl(hFile, spec, options)",
|
|
{ type="func-seen",
|
|
{ type="ext-iter",
|
|
{ type="block", name="ExtFuncDecl(hFile, extName, spec, options)", cond="func-iter",
|
|
{type="func-iter",
|
|
{ type="write", name="FuncDecl(hFile, func, spec, options, funcSeen)", },
|
|
},
|
|
},
|
|
{ type="blank"},
|
|
},
|
|
{ type="version-iter",
|
|
{type="func-iter",
|
|
{ type="write", name="FuncDecl(hFile, func, spec, options, funcSeen)", },
|
|
{ type="blank", last=true },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{ type="block", name="SysDecl(hFile, spec, options)",
|
|
{ type="write", name="UtilityDecls(hFile, spec, options)",},
|
|
{ type="blank" },
|
|
{ type="write", name="MainLoaderFuncDecl(hFile, spec, options)",},
|
|
{ type="blank" },
|
|
{ type="write", name="VersioningFuncDecls(hFile, spec, options)",},
|
|
{ type="blank" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{ type="file", style="source", name="GetFilename",
|
|
{ type="write", name="FilePreamble", optional=true} ,
|
|
{ type="write", name="Includes(hFile, basename, spec, options)",},
|
|
{ type="blank"},
|
|
{ type="write", name="LoaderData(hFile, spec, options)",},
|
|
{ type="blank"},
|
|
{ type="block", name="Def(hFile, spec, options)",
|
|
{ type="block", name="ExtVarDef(hFile, spec, options)",
|
|
{ type="ext-iter",
|
|
{ type="write", name="ExtVariableDef(hFile, extName, specData, spec, options)",},
|
|
{ type="blank", last=true},
|
|
},
|
|
},
|
|
{ type="func-seen",
|
|
{ type="ext-iter",
|
|
{ type="block", name="ExtFuncDef(hFile, extName, spec, options)", cond="func-iter",
|
|
{ type="func-iter",
|
|
{ type="write", name="FuncDef(hFile, func, spec, options, funcSeen)", },
|
|
},
|
|
{ type="blank"},
|
|
{ type="block", name="ExtLoader(hFile, extName, spec, options)",
|
|
{ type="func-iter",
|
|
{ type="write", name="ExtFuncLoader(hFile, func, spec, options)", }
|
|
}
|
|
},
|
|
{ type="blank"},
|
|
},
|
|
},
|
|
{ type="block", name="CoreFuncDef(hFile, spec, options)",
|
|
cond="core-funcs",
|
|
{ type="version-iter",
|
|
{type="func-iter",
|
|
{ type="write", name="FuncDef(hFile, func, spec, options, funcSeen)", },
|
|
{ type="blank", last=true },
|
|
},
|
|
},
|
|
{ type="block", name="CoreLoader(hFile, spec, options)",
|
|
{ type="version-iter",
|
|
{type="func-iter",
|
|
{ type="write", name="CoreFuncLoader(hFile, func, spec, options)", },
|
|
},
|
|
},
|
|
},
|
|
{ type="blank"},
|
|
},
|
|
{ type="write", name="ExtStringFuncDef(hFile, specData, spec, options, funcSeen)"},
|
|
},
|
|
{ type="block", name="SysDef(hFile, spec, options)",
|
|
{ type="write", name="UtilityDefs(hFile, specData, spec, options)",},
|
|
{ type="blank" },
|
|
{ type="write", name="MainLoaderFunc(hFile, specData, spec, options)",},
|
|
{ type="blank" },
|
|
{ type="write", name="VersioningFuncs(hFile, specData, spec, options)", cond="version-iter"},
|
|
{ type="blank", cond="version-iter" },
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
my_struct = struct.BuildStructure(my_struct)
|
|
|
|
function common.GetStandardStructure()
|
|
return my_struct
|
|
end
|
|
|
|
return common
|