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