mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-01 08:31:45 +00:00
- backported symbol table support for FScanner from Raze.
This commit is contained in:
parent
8a0634ed0d
commit
b3a179b691
3 changed files with 246 additions and 41 deletions
|
@ -47,6 +47,7 @@
|
|||
#include "templates.h"
|
||||
#include "zstring.h"
|
||||
#include "name.h"
|
||||
#include <inttypes.h>
|
||||
#include "filesystem.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
@ -300,6 +301,12 @@ void FScanner :: OpenLumpNum (int lump)
|
|||
|
||||
void FScanner::PrepareScript ()
|
||||
{
|
||||
// If the file got a UTF-8 byte order mark, remove that.
|
||||
if (ScriptBuffer.Len() > 3 && ScriptBuffer[0] == (char)0xEF && ScriptBuffer[1] == (char)0xBB && ScriptBuffer[2] == (char)0xBF)
|
||||
{
|
||||
ScriptBuffer = ScriptBuffer.Mid(3);
|
||||
}
|
||||
|
||||
// The scanner requires the file to end with a '\n', so add one if
|
||||
// it doesn't already.
|
||||
if (ScriptBuffer.Len() == 0 || ScriptBuffer.Back() != '\n')
|
||||
|
@ -400,6 +407,13 @@ void FScanner::RestorePos (const FScanner::SavedPos &pos)
|
|||
Crossed = false;
|
||||
}
|
||||
|
||||
long long FScanner::mystrtoll(const char* p, char** endp, int base)
|
||||
{
|
||||
// Do not treat a leading 0 as an octal identifier if so desired.
|
||||
if (NoOctals && *p == '0' && p[1] != 'x' && p[1] != 'X' && base == 0) base = 10;
|
||||
return strtoll(p, endp, base);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FScanner :: isText
|
||||
|
@ -491,6 +505,7 @@ bool FScanner::ScanString (bool tokens)
|
|||
const char *marker, *tok;
|
||||
bool return_val;
|
||||
|
||||
ParseError = false;
|
||||
CheckOpen();
|
||||
if (AlreadyGot)
|
||||
{
|
||||
|
@ -590,7 +605,7 @@ bool FScanner::CheckString (const char *name)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::GetToken ()
|
||||
bool FScanner::GetToken (bool evaluate)
|
||||
{
|
||||
if (ScanString (true))
|
||||
{
|
||||
|
@ -608,7 +623,7 @@ bool FScanner::GetToken ()
|
|||
}
|
||||
else
|
||||
{
|
||||
BigNumber = strtoll(String, &stopper, 0);
|
||||
BigNumber = mystrtoll(String, &stopper, 0);
|
||||
Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX);
|
||||
Float = Number;
|
||||
}
|
||||
|
@ -620,7 +635,19 @@ bool FScanner::GetToken ()
|
|||
}
|
||||
else if (TokenType == TK_StringConst)
|
||||
{
|
||||
StringLen = strbin(String);
|
||||
StringLen = strbin(const_cast<char*>(String));
|
||||
}
|
||||
else if (TokenType == TK_Identifier && evaluate && symbols.CountUsed() > 0)
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym)
|
||||
{
|
||||
TokenType = sym->tokenType;
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -633,9 +660,9 @@ bool FScanner::GetToken ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::MustGetAnyToken (void)
|
||||
void FScanner::MustGetAnyToken (bool evaluate)
|
||||
{
|
||||
if (GetToken () == false)
|
||||
if (GetToken (evaluate) == false)
|
||||
{
|
||||
ScriptError ("Missing token (unexpected end of file).");
|
||||
}
|
||||
|
@ -663,9 +690,9 @@ void FScanner::TokenMustBe (int token)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::MustGetToken (int token)
|
||||
void FScanner::MustGetToken (int token, bool evaluate)
|
||||
{
|
||||
MustGetAnyToken ();
|
||||
MustGetAnyToken (evaluate);
|
||||
TokenMustBe(token);
|
||||
}
|
||||
|
||||
|
@ -678,9 +705,9 @@ void FScanner::MustGetToken (int token)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::CheckToken (int token)
|
||||
bool FScanner::CheckToken (int token, bool evaluate)
|
||||
{
|
||||
if (GetToken ())
|
||||
if (GetToken (evaluate))
|
||||
{
|
||||
if (TokenType == token)
|
||||
{
|
||||
|
@ -697,7 +724,7 @@ bool FScanner::CheckToken (int token)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::GetNumber ()
|
||||
bool FScanner::GetNumber (bool evaluate)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
|
@ -710,11 +737,25 @@ bool FScanner::GetNumber ()
|
|||
}
|
||||
else
|
||||
{
|
||||
BigNumber = strtoll(String, &stopper, 0);
|
||||
BigNumber = mystrtoll(String, &stopper, 0);
|
||||
Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
if (evaluate && symbols.CountUsed())
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym && sym->tokenType == TK_IntConst)
|
||||
{
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", String);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Float = Number;
|
||||
|
@ -732,9 +773,9 @@ bool FScanner::GetNumber ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::MustGetNumber ()
|
||||
void FScanner::MustGetNumber (bool evaluate)
|
||||
{
|
||||
if (GetNumber() == false)
|
||||
if (GetNumber(evaluate) == false)
|
||||
{
|
||||
ScriptError ("Missing integer (unexpected end of file).");
|
||||
}
|
||||
|
@ -749,7 +790,7 @@ void FScanner::MustGetNumber ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::CheckNumber ()
|
||||
bool FScanner::CheckNumber (bool evaluate)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
|
@ -767,10 +808,23 @@ bool FScanner::CheckNumber ()
|
|||
}
|
||||
else
|
||||
{
|
||||
BigNumber = strtoll (String, &stopper, 0);
|
||||
BigNumber = mystrtoll (String, &stopper, 0);
|
||||
Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
if (evaluate && symbols.CountUsed())
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym && sym->tokenType == TK_IntConst)
|
||||
{
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
UnGet();
|
||||
return false;
|
||||
}
|
||||
|
@ -792,7 +846,7 @@ bool FScanner::CheckNumber ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::CheckFloat ()
|
||||
bool FScanner::CheckFloat (bool evaluate)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
|
@ -807,6 +861,20 @@ bool FScanner::CheckFloat ()
|
|||
Float = strtod (String, &stopper);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
if (evaluate && symbols.CountUsed())
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym && sym->tokenType == TK_IntConst && sym->tokenType != TK_FloatConst)
|
||||
{
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UnGet();
|
||||
return false;
|
||||
}
|
||||
|
@ -825,7 +893,7 @@ bool FScanner::CheckFloat ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::GetFloat ()
|
||||
bool FScanner::GetFloat (bool evaluate)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
|
@ -835,7 +903,21 @@ bool FScanner::GetFloat ()
|
|||
Float = strtod (String, &stopper);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
if (evaluate && symbols.CountUsed())
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym && sym->tokenType == TK_IntConst && sym->tokenType != TK_FloatConst)
|
||||
{
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptError ("SC_GetFloat: Bad numeric constant \"%s\".", String);
|
||||
return false;
|
||||
}
|
||||
Number = (int)Float;
|
||||
return true;
|
||||
|
@ -852,9 +934,9 @@ bool FScanner::GetFloat ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::MustGetFloat ()
|
||||
void FScanner::MustGetFloat (bool evaluate)
|
||||
{
|
||||
if (GetFloat() == false)
|
||||
if (GetFloat(evaluate) == false)
|
||||
{
|
||||
ScriptError ("Missing floating-point number (unexpected end of file).");
|
||||
}
|
||||
|
@ -938,44 +1020,54 @@ bool FScanner::Compare (const char *text)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::ScanValue(bool allowfloat)
|
||||
bool FScanner::ScanValue(bool allowfloat, bool evaluate)
|
||||
{
|
||||
bool neg = false;
|
||||
if (!GetToken())
|
||||
if (!GetToken(evaluate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (TokenType == '-' || TokenType == '+')
|
||||
{
|
||||
neg = TokenType == '-';
|
||||
if (!GetToken())
|
||||
if (!GetToken(evaluate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (TokenType != TK_IntConst && (TokenType != TK_FloatConst || !allowfloat))
|
||||
{
|
||||
|
||||
if (TokenType == TK_FloatConst && !allowfloat)
|
||||
return false;
|
||||
|
||||
if (TokenType != TK_IntConst && TokenType != TK_FloatConst)
|
||||
{
|
||||
auto d = constants.CheckKey(String);
|
||||
if (!d) return false;
|
||||
if (!allowfloat && int64_t(*d) != *d) return false;
|
||||
BigNumber = *d;
|
||||
Number = *d;
|
||||
Float = *d;
|
||||
}
|
||||
if (neg)
|
||||
{
|
||||
BigNumber = -BigNumber;
|
||||
Number = -Number;
|
||||
Float = -Float;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FScanner::CheckValue(bool allowfloat)
|
||||
bool FScanner::CheckValue(bool allowfloat, bool evaluate)
|
||||
{
|
||||
auto savedstate = SavePos();
|
||||
bool res = ScanValue(allowfloat);
|
||||
bool res = ScanValue(allowfloat, evaluate);
|
||||
if (!res) RestorePos(savedstate);
|
||||
return res;
|
||||
}
|
||||
|
||||
void FScanner::MustGetValue(bool allowfloat)
|
||||
void FScanner::MustGetValue(bool allowfloat, bool evaluate)
|
||||
{
|
||||
if (!ScanValue(allowfloat)) ScriptError(allowfloat ? "Numeric constant expected" : "Integer constant expected");
|
||||
if (!ScanValue(allowfloat, evaluate)) ScriptError(allowfloat ? "Numeric constant expected" : "Integer constant expected");
|
||||
}
|
||||
|
||||
bool FScanner::CheckBoolToken()
|
||||
|
@ -1079,6 +1171,12 @@ void FScanner::ScriptError (const char *message, ...)
|
|||
va_end (arglist);
|
||||
}
|
||||
|
||||
if (NoFatalErrors)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED "Script error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(),
|
||||
AlreadyGot ? AlreadyGotLine : Line, composed.GetChars());
|
||||
return;
|
||||
}
|
||||
I_Error ("Script error, \"%s\" line %d:\n%s\n", ScriptName.GetChars(),
|
||||
AlreadyGot? AlreadyGotLine : Line, composed.GetChars());
|
||||
}
|
||||
|
@ -1123,6 +1221,72 @@ void FScanner::CheckOpen()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::AddSymbol(const char *name, int64_t value)
|
||||
{
|
||||
Symbol sym;
|
||||
sym.tokenType = TK_IntConst;
|
||||
sym.Number = value;
|
||||
sym.Float = value;
|
||||
symbols.Insert(name, sym);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::AddSymbol(const char* name, uint64_t value)
|
||||
{
|
||||
Symbol sym;
|
||||
sym.tokenType = TK_UIntConst;
|
||||
sym.Number = value;
|
||||
sym.Float = value;
|
||||
symbols.Insert(name, sym);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::SkipToEndOfBlock()
|
||||
{
|
||||
int depth = 0;
|
||||
while (1)
|
||||
{
|
||||
MustGetString(); // this will abort if it reaches the end of the file
|
||||
if (Compare("{")) depth++;
|
||||
else if (Compare("}"))
|
||||
{
|
||||
depth--;
|
||||
if (depth < 0) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::AddSymbol(const char* name, double value)
|
||||
{
|
||||
Symbol sym;
|
||||
sym.tokenType = TK_FloatConst;
|
||||
sym.Number = (int64_t)value;
|
||||
sym.Float = value;
|
||||
symbols.Insert(name, sym);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// a class that remembers a parser position
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __SC_MAN_H__
|
||||
|
||||
#include "zstring.h"
|
||||
#include "tarray.h"
|
||||
#include "name.h"
|
||||
#include "basics.h"
|
||||
|
||||
|
@ -46,6 +47,16 @@ public:
|
|||
int SavedScriptLine;
|
||||
};
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
int tokenType;
|
||||
int64_t Number;
|
||||
double Float;
|
||||
};
|
||||
|
||||
|
||||
TMap<FName, Symbol> symbols;
|
||||
|
||||
// Methods ------------------------------------------------------
|
||||
FScanner();
|
||||
FScanner(const FScanner &other);
|
||||
|
@ -70,11 +81,19 @@ public:
|
|||
}
|
||||
|
||||
void SetCMode(bool cmode);
|
||||
void SetNoOctals(bool cmode) { NoOctals = cmode; }
|
||||
void SetNoFatalErrors(bool cmode) { NoFatalErrors = cmode; }
|
||||
void SetEscape(bool esc);
|
||||
void SetStateMode(bool stately);
|
||||
void DisableStateOptions();
|
||||
const SavedPos SavePos();
|
||||
void RestorePos(const SavedPos &pos);
|
||||
void AddSymbol(const char* name, int64_t value);
|
||||
void AddSymbol(const char* name, uint64_t value);
|
||||
inline void AddSymbol(const char* name, int32_t value) { return AddSymbol(name, int64_t(value)); }
|
||||
inline void AddSymbol(const char* name, uint32_t value) { return AddSymbol(name, uint64_t(value)); }
|
||||
void AddSymbol(const char* name, double value);
|
||||
void SkipToEndOfBlock();
|
||||
|
||||
static FString TokenName(int token, const char *string=NULL);
|
||||
|
||||
|
@ -83,30 +102,40 @@ public:
|
|||
void MustGetStringName(const char *name);
|
||||
bool CheckString(const char *name);
|
||||
|
||||
bool GetToken();
|
||||
void MustGetAnyToken();
|
||||
bool GetToken(bool evaluate = false);
|
||||
void MustGetAnyToken(bool evaluate = false);
|
||||
void TokenMustBe(int token);
|
||||
void MustGetToken(int token);
|
||||
bool CheckToken(int token);
|
||||
void MustGetToken(int token, bool evaluate = false);
|
||||
bool CheckToken(int token, bool evaluate = false);
|
||||
bool CheckTokenId(ENamedName id);
|
||||
|
||||
bool GetNumber();
|
||||
void MustGetNumber();
|
||||
bool CheckNumber();
|
||||
bool GetNumber(bool evaluate = false);
|
||||
void MustGetNumber(bool evaluate = false);
|
||||
bool CheckNumber(bool evaluate = false);
|
||||
|
||||
bool GetFloat();
|
||||
void MustGetFloat();
|
||||
bool CheckFloat();
|
||||
bool GetFloat(bool evaluate = false);
|
||||
void MustGetFloat(bool evaluate = false);
|
||||
bool CheckFloat(bool evaluate = false);
|
||||
|
||||
double *LookupConstant(FName name)
|
||||
{
|
||||
return constants.CheckKey(name);
|
||||
}
|
||||
|
||||
// Token based variant
|
||||
bool CheckValue(bool allowfloat);
|
||||
void MustGetValue(bool allowfloat);
|
||||
bool CheckValue(bool allowfloat, bool evaluate = true);
|
||||
void MustGetValue(bool allowfloat, bool evaluate = true);
|
||||
bool CheckBoolToken();
|
||||
void MustGetBoolToken();
|
||||
|
||||
void UnGet();
|
||||
|
||||
bool Compare(const char *text);
|
||||
inline bool Compare(const std::initializer_list<const char*>& list)
|
||||
{
|
||||
for (auto c : list) if (Compare(c)) return true;
|
||||
return false;
|
||||
}
|
||||
int MatchString(const char * const *strings, size_t stride = sizeof(char*));
|
||||
int MustMatchString(const char * const *strings, size_t stride = sizeof(char*));
|
||||
int GetMessageLine();
|
||||
|
@ -125,11 +154,13 @@ public:
|
|||
double Float;
|
||||
int Line;
|
||||
bool End;
|
||||
bool ParseError = false;
|
||||
bool Crossed;
|
||||
int LumpNum;
|
||||
FString ScriptName;
|
||||
|
||||
protected:
|
||||
long long mystrtoll(const char* p, char** endp, int base);
|
||||
void PrepareScript();
|
||||
void CheckOpen();
|
||||
bool ScanString(bool tokens);
|
||||
|
@ -137,6 +168,8 @@ protected:
|
|||
// Strings longer than this minus one will be dynamically allocated.
|
||||
static const int MAX_STRING_SIZE = 128;
|
||||
|
||||
TMap<FName, double> constants;
|
||||
|
||||
bool ScriptOpen;
|
||||
FString ScriptBuffer;
|
||||
const char *ScriptPtr;
|
||||
|
@ -149,13 +182,15 @@ protected:
|
|||
const char *LastGotPtr;
|
||||
int LastGotLine;
|
||||
bool CMode;
|
||||
bool NoOctals = false;
|
||||
bool NoFatalErrors = false;
|
||||
uint8_t StateMode;
|
||||
bool StateOptions;
|
||||
bool Escape;
|
||||
VersionInfo ParseVersion = { 0, 0, 0 }; // no ZScript extensions by default
|
||||
|
||||
|
||||
bool ScanValue(bool allowfloat);
|
||||
bool ScanValue(bool allowfloat, bool evaluate);
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
|
@ -240,6 +240,12 @@ FSerializer &Serialize(FSerializer &arc, const char *key, TArray<T, TT> &value,
|
|||
return arc;
|
||||
}
|
||||
|
||||
template<int size>
|
||||
FSerializer& Serialize(FSerializer& arc, const char* key, FixedBitArray<size>& value, FixedBitArray<size>* def)
|
||||
{
|
||||
return arc.SerializeMemory(key, value.Storage(), value.StorageSize());
|
||||
}
|
||||
|
||||
template<> FSerializer& Serialize(FSerializer& arc, const char* key, PClass*& clst, PClass** def);
|
||||
template<> FSerializer& Serialize(FSerializer& arc, const char* key, FFont*& font, FFont** def);
|
||||
template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary *&dict, Dictionary **def);
|
||||
|
|
Loading…
Reference in a new issue