2019-10-23 23:20:58 +00:00
|
|
|
#ifndef __SC_MAN_H__
|
|
|
|
#define __SC_MAN_H__
|
|
|
|
|
|
|
|
#include "zstring.h"
|
2020-06-23 22:40:22 +00:00
|
|
|
#include "tarray.h"
|
2019-10-23 23:20:58 +00:00
|
|
|
#include "name.h"
|
|
|
|
#include "basics.h"
|
|
|
|
|
2020-04-11 22:04:02 +00:00
|
|
|
struct VersionInfo
|
|
|
|
{
|
|
|
|
uint16_t major;
|
|
|
|
uint16_t minor;
|
|
|
|
uint32_t revision;
|
|
|
|
|
2022-08-03 12:13:42 +00:00
|
|
|
constexpr bool operator <=(const VersionInfo& o) const
|
2020-04-11 22:04:02 +00:00
|
|
|
{
|
|
|
|
return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision >= this->revision);
|
|
|
|
}
|
2022-08-03 12:13:42 +00:00
|
|
|
constexpr bool operator >=(const VersionInfo& o) const
|
2020-04-11 22:04:02 +00:00
|
|
|
{
|
|
|
|
return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision <= this->revision);
|
|
|
|
}
|
2022-08-03 12:13:42 +00:00
|
|
|
constexpr bool operator > (const VersionInfo& o) const
|
2020-04-11 22:04:02 +00:00
|
|
|
{
|
|
|
|
return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision < this->revision);
|
|
|
|
}
|
2022-08-03 12:13:42 +00:00
|
|
|
constexpr bool operator < (const VersionInfo& o) const
|
2020-04-11 22:04:02 +00:00
|
|
|
{
|
|
|
|
return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision > this->revision);
|
|
|
|
}
|
|
|
|
void operator=(const char* string);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Cannot be a constructor because Lemon would puke on it.
|
2022-08-03 12:13:42 +00:00
|
|
|
constexpr VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re = 0)
|
2020-04-11 22:04:02 +00:00
|
|
|
{
|
|
|
|
return{ (uint16_t)ma, (uint16_t)mi, (uint32_t)re };
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-23 23:20:58 +00:00
|
|
|
class FScanner
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct SavedPos
|
|
|
|
{
|
|
|
|
const char *SavedScriptPtr;
|
|
|
|
int SavedScriptLine;
|
|
|
|
};
|
|
|
|
|
2020-09-10 15:46:54 +00:00
|
|
|
struct Symbol
|
|
|
|
{
|
|
|
|
int tokenType;
|
|
|
|
int64_t Number;
|
|
|
|
double Float;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
TMap<FName, Symbol> symbols;
|
|
|
|
|
2019-10-23 23:20:58 +00:00
|
|
|
// Methods ------------------------------------------------------
|
|
|
|
FScanner();
|
|
|
|
FScanner(const FScanner &other);
|
|
|
|
FScanner(int lumpnum);
|
|
|
|
~FScanner();
|
|
|
|
|
|
|
|
FScanner &operator=(const FScanner &other);
|
|
|
|
|
|
|
|
void Open(const char *lumpname);
|
2020-04-11 22:04:02 +00:00
|
|
|
bool OpenFile(const char *filename);
|
2019-10-23 23:20:58 +00:00
|
|
|
void OpenMem(const char *name, const char *buffer, int size);
|
2020-04-11 22:04:02 +00:00
|
|
|
void OpenMem(const char *name, const TArray<uint8_t> &buffer)
|
|
|
|
{
|
|
|
|
OpenMem(name, (const char*)buffer.Data(), buffer.Size());
|
|
|
|
}
|
2019-10-23 23:20:58 +00:00
|
|
|
void OpenString(const char *name, FString buffer);
|
2020-04-11 22:04:02 +00:00
|
|
|
void OpenLumpNum(int lump);
|
2019-10-23 23:20:58 +00:00
|
|
|
void Close();
|
2020-04-11 22:04:02 +00:00
|
|
|
void SetParseVersion(VersionInfo ver)
|
|
|
|
{
|
|
|
|
ParseVersion = ver;
|
|
|
|
}
|
2019-10-23 23:20:58 +00:00
|
|
|
|
|
|
|
void SetCMode(bool cmode);
|
2020-09-10 15:46:54 +00:00
|
|
|
void SetNoOctals(bool cmode) { NoOctals = cmode; }
|
2020-09-12 08:23:47 +00:00
|
|
|
void SetNoFatalErrors(bool cmode) { NoFatalErrors = cmode; }
|
2019-10-23 23:20:58 +00:00
|
|
|
void SetEscape(bool esc);
|
|
|
|
void SetStateMode(bool stately);
|
|
|
|
void DisableStateOptions();
|
|
|
|
const SavedPos SavePos();
|
|
|
|
void RestorePos(const SavedPos &pos);
|
2020-09-10 15:46:54 +00:00
|
|
|
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);
|
2020-09-10 22:18:13 +00:00
|
|
|
void SkipToEndOfBlock();
|
2021-04-07 19:59:47 +00:00
|
|
|
int StartBraces(FScanner::SavedPos* braceend);
|
|
|
|
bool FoundEndBrace(FScanner::SavedPos& braceend);
|
2019-10-23 23:20:58 +00:00
|
|
|
|
|
|
|
static FString TokenName(int token, const char *string=NULL);
|
|
|
|
|
|
|
|
bool GetString();
|
|
|
|
void MustGetString();
|
|
|
|
void MustGetStringName(const char *name);
|
|
|
|
bool CheckString(const char *name);
|
|
|
|
|
2020-09-10 15:46:54 +00:00
|
|
|
bool GetToken(bool evaluate = false);
|
|
|
|
void MustGetAnyToken(bool evaluate = false);
|
2019-10-23 23:20:58 +00:00
|
|
|
void TokenMustBe(int token);
|
2020-09-10 15:46:54 +00:00
|
|
|
void MustGetToken(int token, bool evaluate = false);
|
|
|
|
bool CheckToken(int token, bool evaluate = false);
|
2019-10-23 23:20:58 +00:00
|
|
|
bool CheckTokenId(ENamedName id);
|
|
|
|
|
2020-09-12 08:23:47 +00:00
|
|
|
bool GetNumber(bool evaluate = false);
|
|
|
|
void MustGetNumber(bool evaluate = false);
|
|
|
|
bool CheckNumber(bool evaluate = false);
|
2019-10-23 23:20:58 +00:00
|
|
|
|
2021-04-06 13:07:12 +00:00
|
|
|
bool GetNumber(int& var, bool evaluate = false)
|
|
|
|
{
|
|
|
|
if (!GetNumber(evaluate)) return false;
|
|
|
|
var = Number;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-13 16:17:28 +00:00
|
|
|
bool GetNumber(int64_t& var, bool evaluate = false)
|
|
|
|
{
|
|
|
|
if (!GetNumber(evaluate)) return false;
|
|
|
|
var = BigNumber;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-07 19:59:47 +00:00
|
|
|
bool GetString(FString& var)
|
|
|
|
{
|
|
|
|
if (!GetString()) return false;
|
|
|
|
var = String;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-09-12 08:23:47 +00:00
|
|
|
bool GetFloat(bool evaluate = false);
|
2021-04-10 12:09:08 +00:00
|
|
|
|
|
|
|
bool GetFloat(double& var, bool evaluate = false)
|
|
|
|
{
|
|
|
|
if (!GetFloat(evaluate)) return false;
|
|
|
|
var = Float;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-05-11 23:55:06 +00:00
|
|
|
bool GetFloat(float& var, bool evaluate = false)
|
|
|
|
{
|
|
|
|
if (!GetFloat(evaluate)) return false;
|
|
|
|
var = float(Float);
|
|
|
|
return true;
|
|
|
|
}
|
2021-04-10 12:09:08 +00:00
|
|
|
|
2020-09-12 08:23:47 +00:00
|
|
|
void MustGetFloat(bool evaluate = false);
|
|
|
|
bool CheckFloat(bool evaluate = false);
|
2020-06-23 22:40:22 +00:00
|
|
|
|
|
|
|
double *LookupConstant(FName name)
|
|
|
|
{
|
|
|
|
return constants.CheckKey(name);
|
|
|
|
}
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2019-12-23 09:53:58 +00:00
|
|
|
// Token based variant
|
2020-09-10 15:46:54 +00:00
|
|
|
bool CheckValue(bool allowfloat, bool evaluate = true);
|
|
|
|
void MustGetValue(bool allowfloat, bool evaluate = true);
|
2019-12-23 09:53:58 +00:00
|
|
|
bool CheckBoolToken();
|
|
|
|
void MustGetBoolToken();
|
2019-10-23 23:20:58 +00:00
|
|
|
|
|
|
|
void UnGet();
|
|
|
|
|
|
|
|
bool Compare(const char *text);
|
2020-09-15 19:21:16 +00:00
|
|
|
inline bool Compare(const std::initializer_list<const char*>& list)
|
|
|
|
{
|
|
|
|
for (auto c : list) if (Compare(c)) return true;
|
|
|
|
return false;
|
|
|
|
}
|
2019-10-23 23:20:58 +00:00
|
|
|
int MatchString(const char * const *strings, size_t stride = sizeof(char*));
|
|
|
|
int MustMatchString(const char * const *strings, size_t stride = sizeof(char*));
|
|
|
|
int GetMessageLine();
|
|
|
|
|
|
|
|
void ScriptError(const char *message, ...) GCCPRINTF(2,3);
|
|
|
|
void ScriptMessage(const char *message, ...) GCCPRINTF(2,3);
|
|
|
|
|
|
|
|
bool isText();
|
|
|
|
|
|
|
|
// Members ------------------------------------------------------
|
|
|
|
char *String;
|
|
|
|
int StringLen;
|
|
|
|
int TokenType;
|
|
|
|
int Number;
|
2019-10-30 17:09:00 +00:00
|
|
|
int64_t BigNumber;
|
2019-10-23 23:20:58 +00:00
|
|
|
double Float;
|
|
|
|
int Line;
|
|
|
|
bool End;
|
2020-09-12 08:23:47 +00:00
|
|
|
bool ParseError = false;
|
2019-10-23 23:20:58 +00:00
|
|
|
bool Crossed;
|
|
|
|
int LumpNum;
|
|
|
|
FString ScriptName;
|
|
|
|
|
|
|
|
protected:
|
2020-09-10 15:46:54 +00:00
|
|
|
long long mystrtoll(const char* p, char** endp, int base);
|
2019-10-23 23:20:58 +00:00
|
|
|
void PrepareScript();
|
|
|
|
void CheckOpen();
|
|
|
|
bool ScanString(bool tokens);
|
|
|
|
|
|
|
|
// Strings longer than this minus one will be dynamically allocated.
|
|
|
|
static const int MAX_STRING_SIZE = 128;
|
|
|
|
|
2020-06-23 22:40:22 +00:00
|
|
|
TMap<FName, double> constants;
|
|
|
|
|
2019-10-23 23:20:58 +00:00
|
|
|
bool ScriptOpen;
|
|
|
|
FString ScriptBuffer;
|
|
|
|
const char *ScriptPtr;
|
|
|
|
const char *ScriptEndPtr;
|
|
|
|
char StringBuffer[MAX_STRING_SIZE];
|
|
|
|
FString BigStringBuffer;
|
|
|
|
bool AlreadyGot;
|
|
|
|
int AlreadyGotLine;
|
|
|
|
bool LastGotToken;
|
|
|
|
const char *LastGotPtr;
|
|
|
|
int LastGotLine;
|
|
|
|
bool CMode;
|
2020-09-10 15:46:54 +00:00
|
|
|
bool NoOctals = false;
|
2020-09-12 08:23:47 +00:00
|
|
|
bool NoFatalErrors = false;
|
2019-12-23 09:53:58 +00:00
|
|
|
uint8_t StateMode;
|
2019-10-23 23:20:58 +00:00
|
|
|
bool StateOptions;
|
|
|
|
bool Escape;
|
2020-04-11 22:04:02 +00:00
|
|
|
VersionInfo ParseVersion = { 0, 0, 0 }; // no ZScript extensions by default
|
2019-12-23 09:53:58 +00:00
|
|
|
|
|
|
|
|
2020-09-10 15:46:54 +00:00
|
|
|
bool ScanValue(bool allowfloat, bool evaluate);
|
2019-10-23 23:20:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
TK_SequenceStart = 256,
|
|
|
|
#define xx(sym,str) sym,
|
|
|
|
#include "sc_man_tokens.h"
|
|
|
|
TK_LastToken
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
MSG_WARNING,
|
|
|
|
MSG_FATAL,
|
|
|
|
MSG_ERROR,
|
|
|
|
MSG_OPTERROR,
|
|
|
|
MSG_DEBUGERROR,
|
|
|
|
MSG_DEBUGWARN,
|
|
|
|
MSG_DEBUGMSG,
|
|
|
|
MSG_LOG,
|
|
|
|
MSG_DEBUGLOG,
|
|
|
|
MSG_MESSAGE
|
|
|
|
};
|
|
|
|
|
2019-12-23 09:53:58 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// a class that remembers a parser position
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
struct FScriptPosition
|
|
|
|
{
|
|
|
|
static int WarnCounter;
|
|
|
|
static int ErrorCounter;
|
|
|
|
static bool StrictErrors;
|
2020-04-11 22:04:02 +00:00
|
|
|
static int Developer;
|
2019-12-23 09:53:58 +00:00
|
|
|
static bool errorout;
|
|
|
|
FName FileName;
|
|
|
|
int ScriptLine;
|
|
|
|
|
|
|
|
FScriptPosition()
|
|
|
|
{
|
|
|
|
FileName = NAME_None;
|
|
|
|
ScriptLine=0;
|
|
|
|
}
|
|
|
|
FScriptPosition(const FScriptPosition &other) = default;
|
|
|
|
FScriptPosition(FString fname, int line);
|
|
|
|
FScriptPosition(FScanner &sc);
|
|
|
|
FScriptPosition &operator=(const FScriptPosition &other) = default;
|
|
|
|
FScriptPosition &operator=(FScanner &sc);
|
|
|
|
void Message(int severity, const char *message,...) const GCCPRINTF(3,4);
|
|
|
|
static void ResetErrorCounter()
|
|
|
|
{
|
|
|
|
WarnCounter = 0;
|
|
|
|
ErrorCounter = 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
int ParseHex(const char* hex, FScriptPosition* sc);
|
|
|
|
|
2019-10-23 23:20:58 +00:00
|
|
|
|
|
|
|
#endif //__SC_MAN_H__
|