Fix saving arguments in wrong order when parsing "Functions" section in gamedata

ke::HashMap doesn't keep the order the elements are added of course. Switch to a vector structure instead.
This commit is contained in:
Peace-Maker 2018-04-21 11:50:07 +02:00
parent d9778021c7
commit 3e2471f93a
3 changed files with 51 additions and 40 deletions

View File

@ -131,12 +131,10 @@ cell_t Native_DHookCreateFromConf(IPluginContext *pContext, const cell_t *params
} }
// Push all the arguments. // Push all the arguments.
auto args = sig->args.iter(); for (ArgumentInfo &arg : sig->args)
while (!args.empty())
{ {
ParamInfo info = args->value; ParamInfo info = arg.info;
setup->params.push_back(info); setup->params.push_back(info);
args.next();
} }
// Create the handle to hold this setup. // Create the handle to hold this setup.

View File

@ -18,8 +18,7 @@ ParseState g_PlatformOnlyState;
SignatureWrapper *g_CurrentSignature; SignatureWrapper *g_CurrentSignature;
ke::AString g_CurrentFunctionName; ke::AString g_CurrentFunctionName;
ParamInfo g_CurrentArgumentInfo; ArgumentInfo g_CurrentArgumentInfo;
ke::AString g_CurrentArgumentName;
SignatureWrapper *SignatureGameConfig::GetFunctionSignature(const char *function) SignatureWrapper *SignatureGameConfig::GetFunctionSignature(const char *function)
{ {
@ -118,20 +117,21 @@ SMCResult SignatureGameConfig::ReadSMC_NewSection(const SMCStates *states, const
case PState_Arguments: case PState_Arguments:
{ {
g_ParseState = PState_Argument; g_ParseState = PState_Argument;
g_CurrentArgumentName = name; g_CurrentArgumentInfo.name = name;
auto arg = g_CurrentSignature->args.find(name); // Reset the parameter info.
// Continue changing that argument now. ParamInfo info;
if (arg.found()) memset(&info, 0, sizeof(info));
{ info.flags = PASSFLAG_BYVAL;
g_CurrentArgumentInfo = arg->value; g_CurrentArgumentInfo.info = info;
}
else // See if we already have info about this argument.
{ for (auto &arg : g_CurrentSignature->args) {
ParamInfo info; if (!arg.name.compare(name)) {
memset(&info, 0, sizeof(info)); // Continue changing that argument now.
info.flags = PASSFLAG_BYVAL; g_CurrentArgumentInfo.info = arg.info;
g_CurrentArgumentInfo = info; break;
}
} }
break; break;
} }
@ -251,20 +251,20 @@ SMCResult SignatureGameConfig::ReadSMC_KeyValue(const SMCStates *states, const c
if (!strcmp(key, "type")) if (!strcmp(key, "type"))
{ {
g_CurrentArgumentInfo.type = GetHookParamTypeFromString(value); g_CurrentArgumentInfo.info.type = GetHookParamTypeFromString(value);
if (g_CurrentArgumentInfo.type == HookParamType_Unknown) if (g_CurrentArgumentInfo.info.type == HookParamType_Unknown)
{ {
smutils->LogError(myself, "Invalid argument type \"%s\" for argument \"%s\": line: %i col: %i", value, g_CurrentArgumentName.chars(), states->line, states->col); smutils->LogError(myself, "Invalid argument type \"%s\" for argument \"%s\": line: %i col: %i", value, g_CurrentArgumentInfo.name.chars(), states->line, states->col);
return SMCResult_HaltFail; return SMCResult_HaltFail;
} }
} }
else if (!strcmp(key, "size")) else if (!strcmp(key, "size"))
{ {
g_CurrentArgumentInfo.size = atoi(value); g_CurrentArgumentInfo.info.size = atoi(value);
if (g_CurrentArgumentInfo.size < 1) if (g_CurrentArgumentInfo.info.size < 1)
{ {
smutils->LogError(myself, "Invalid argument size \"%s\" for argument \"%s\": line: %i col: %i", value, g_CurrentArgumentName.chars(), states->line, states->col); smutils->LogError(myself, "Invalid argument size \"%s\" for argument \"%s\": line: %i col: %i", value, g_CurrentArgumentInfo.name.chars(), states->line, states->col);
return SMCResult_HaltFail; return SMCResult_HaltFail;
} }
} }
@ -290,13 +290,13 @@ SMCResult SignatureGameConfig::ReadSMC_KeyValue(const SMCStates *states, const c
flags |= PASSFLAG_OUNALIGN; flags |= PASSFLAG_OUNALIGN;
#endif #endif
g_CurrentArgumentInfo.flags = flags; g_CurrentArgumentInfo.info.flags = flags;
} }
else if (!strcmp(key, "register")) else if (!strcmp(key, "register"))
{ {
g_CurrentArgumentInfo.custom_register = GetCustomRegisterFromString(value); g_CurrentArgumentInfo.info.custom_register = GetCustomRegisterFromString(value);
if (g_CurrentArgumentInfo.custom_register == Register_t::None) if (g_CurrentArgumentInfo.info.custom_register == Register_t::None)
{ {
smutils->LogError(myself, "Invalid register \"%s\": line: %i col: %i", value, states->line, states->col); smutils->LogError(myself, "Invalid register \"%s\": line: %i col: %i", value, states->line, states->col);
return SMCResult_HaltFail; return SMCResult_HaltFail;
@ -357,31 +357,32 @@ SMCResult SignatureGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
case PState_Argument: case PState_Argument:
g_ParseState = PState_Arguments; g_ParseState = PState_Arguments;
if (g_CurrentArgumentInfo.type == HookParamType_Unknown) if (g_CurrentArgumentInfo.info.type == HookParamType_Unknown)
{ {
smutils->LogError(myself, "Missing argument type for argument \"%s\": line: %i col: %i", g_CurrentArgumentName.chars(), states->line, states->col); smutils->LogError(myself, "Missing argument type for argument \"%s\": line: %i col: %i", g_CurrentArgumentInfo.name.chars(), states->line, states->col);
return SMCResult_HaltFail; return SMCResult_HaltFail;
} }
// The size wasn't set in the config. See if that's fine and we can guess it from the type. // The size wasn't set in the config. See if that's fine and we can guess it from the type.
if (!g_CurrentArgumentInfo.size) if (!g_CurrentArgumentInfo.info.size)
{ {
if (g_CurrentArgumentInfo.type == HookParamType_Object) if (g_CurrentArgumentInfo.info.type == HookParamType_Object)
{ {
smutils->LogError(myself, "Object param \"%s\" being set with no size: line: %i col: %i", g_CurrentArgumentName.chars(), states->line, states->col); smutils->LogError(myself, "Object param \"%s\" being set with no size: line: %i col: %i", g_CurrentArgumentInfo.name.chars(), states->line, states->col);
return SMCResult_HaltFail; return SMCResult_HaltFail;
} }
else else
{ {
g_CurrentArgumentInfo.size = GetParamTypeSize(g_CurrentArgumentInfo.type); g_CurrentArgumentInfo.info.size = GetParamTypeSize(g_CurrentArgumentInfo.info.type);
} }
} }
if (g_CurrentArgumentInfo.pass_type == SourceHook::PassInfo::PassType::PassType_Unknown) if (g_CurrentArgumentInfo.info.pass_type == SourceHook::PassInfo::PassType::PassType_Unknown)
g_CurrentArgumentInfo.pass_type = GetParamTypePassType(g_CurrentArgumentInfo.type); g_CurrentArgumentInfo.info.pass_type = GetParamTypePassType(g_CurrentArgumentInfo.info.type);
g_CurrentSignature->args.insert(g_CurrentArgumentName.chars(), g_CurrentArgumentInfo);
g_CurrentArgumentName = nullptr; g_CurrentSignature->args.append(g_CurrentArgumentInfo);
g_CurrentArgumentInfo.name = nullptr;
break; break;
} }
@ -395,7 +396,7 @@ void SignatureGameConfig::ReadSMC_ParseStart()
g_PlatformOnlyState = PState_None; g_PlatformOnlyState = PState_None;
g_CurrentSignature = nullptr; g_CurrentSignature = nullptr;
g_CurrentFunctionName = nullptr; g_CurrentFunctionName = nullptr;
g_CurrentArgumentName = nullptr; g_CurrentArgumentInfo.name = nullptr;
} }
ReturnType SignatureGameConfig::GetReturnTypeFromString(const char *str) ReturnType SignatureGameConfig::GetReturnTypeFromString(const char *str)

View File

@ -4,14 +4,26 @@
#include "extension.h" #include "extension.h"
#include "util.h" #include "util.h"
#include <am-string.h> #include <am-string.h>
#include <am-vector.h>
#include <sm_stringhashmap.h> #include <sm_stringhashmap.h>
struct ArgumentInfo {
ArgumentInfo() : name(nullptr)
{ }
ArgumentInfo(ke::AString name, ParamInfo info) : name(name), info(info)
{ }
ke::AString name;
ParamInfo info;
};
class SignatureWrapper { class SignatureWrapper {
public: public:
ke::AString signature; ke::AString signature;
ke::AString address; ke::AString address;
ke::AString offset; ke::AString offset;
StringHashMap<ParamInfo> args; ke::Vector<ArgumentInfo> args;
CallingConvention callConv; CallingConvention callConv;
HookType hookType; HookType hookType;
ReturnType retType; ReturnType retType;