mirror of
https://github.com/ZDoom/Raze.git
synced 2025-05-30 08:51:08 +00:00
- base.zs cleanup and extendable structs.
This commit is contained in:
parent
be55e26689
commit
c03644ea76
5 changed files with 287 additions and 155 deletions
|
@ -234,6 +234,7 @@ class_head(X) ::= EXTEND CLASS(T) IDENTIFIER(A).
|
|||
X = head;
|
||||
}
|
||||
|
||||
|
||||
class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C).
|
||||
{
|
||||
NEW_AST_NODE(Class,head,T);
|
||||
|
@ -394,6 +395,17 @@ struct_def(X) ::= STRUCT(T) IDENTIFIER(A) struct_flags(S) LBRACE opt_struct_body
|
|||
X = def;
|
||||
}
|
||||
|
||||
struct_def(X) ::= EXTEND STRUCT(T) IDENTIFIER(A) LBRACE opt_struct_body(B) RBRACE opt_semicolon.
|
||||
{
|
||||
NEW_AST_NODE(Struct,def,T);
|
||||
def->NodeName = A.Name();
|
||||
def->Body = B;
|
||||
def->Type = nullptr;
|
||||
def->Symbol = nullptr;
|
||||
def->Flags = ZCC_Extension;
|
||||
X = def;
|
||||
}
|
||||
|
||||
%type struct_flags{ClassFlagsBlock}
|
||||
struct_flags(X) ::= . { X.Flags = 0; X.Version = {0, 0}; }
|
||||
struct_flags(X) ::= struct_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; }
|
||||
|
|
|
@ -377,8 +377,30 @@ void ZCCCompiler::ProcessMixin(ZCC_MixinDef *cnode, PSymbolTreeNode *treenode)
|
|||
|
||||
void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZCC_Class *outer)
|
||||
{
|
||||
Structs.Push(new ZCC_StructWork(static_cast<ZCC_Struct *>(cnode), treenode, outer));
|
||||
ZCC_StructWork *cls = Structs.Last();
|
||||
ZCC_StructWork* cls = nullptr;
|
||||
|
||||
// If this is a struct extension, put the new node directly into the existing class.
|
||||
if (cnode->Flags == ZCC_Extension)
|
||||
{
|
||||
for (auto strct : Structs)
|
||||
{
|
||||
if (strct->NodeName() == cnode->NodeName)
|
||||
{
|
||||
cls = strct;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cls == nullptr)
|
||||
{
|
||||
Error(cnode, "Struct %s cannot be found in the current translation unit.", FName(cnode->NodeName).GetChars());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Structs.Push(new ZCC_StructWork(static_cast<ZCC_Struct*>(cnode), treenode, outer));
|
||||
cls = Structs.Last();
|
||||
}
|
||||
|
||||
auto node = cnode->Body;
|
||||
PSymbolTreeNode *childnode;
|
||||
|
@ -494,7 +516,15 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols,
|
|||
ProcessClass(static_cast<ZCC_Class *>(node), tnode);
|
||||
break;
|
||||
}
|
||||
goto common;
|
||||
case AST_Struct:
|
||||
if (static_cast<ZCC_Class*>(node)->Flags == ZCC_Extension)
|
||||
{
|
||||
ProcessStruct(static_cast<ZCC_Struct*>(node), tnode, nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
common:
|
||||
case AST_ConstantDef:
|
||||
case AST_Enum:
|
||||
if ((tnode = AddTreeNode(static_cast<ZCC_NamedNode *>(node)->NodeName, node, GlobalTreeNodes)))
|
||||
|
|
|
@ -653,6 +653,85 @@ DEFINE_ACTION_FUNCTION(_Console, Printf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=====================================================================================
|
||||
|
||||
extern time_t epochoffset;
|
||||
|
||||
static int GetEpochTime()
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
return now != (time_t)(-1) ? int(now + epochoffset) : -1;
|
||||
}
|
||||
|
||||
//Returns an empty string if the Strf tokens are valid, otherwise returns the problematic token
|
||||
static FString CheckStrfString(FString timeForm)
|
||||
{
|
||||
// Valid Characters after %
|
||||
const char validSingles[] = { 'a','A','b','B','c','C','d','D','e','F','g','G','h','H','I','j','m','M','n','p','r','R','S','t','T','u','U','V','w','W','x','X','y','Y','z','Z' };
|
||||
|
||||
timeForm.Substitute("%%", "%a"); //Prevent %% from causing tokenizing problems
|
||||
timeForm = "a" + timeForm; //Prevent %* at the beginning from causing a false error from tokenizing
|
||||
|
||||
auto tokens = timeForm.Split("%");
|
||||
for (auto t : tokens)
|
||||
{
|
||||
bool found = false;
|
||||
// % at end
|
||||
if (t.Len() == 0) return FString("%");
|
||||
|
||||
// Single Character
|
||||
for (size_t i = 0; i < sizeof(validSingles) / sizeof(validSingles[0]); i++)
|
||||
{
|
||||
if (t[0] == validSingles[i])
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
return FString("%") + t[0];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static void FormatTime(const FString& timeForm, int timeVal, FString* result)
|
||||
{
|
||||
FString error = CheckStrfString(timeForm);
|
||||
if (!error.IsEmpty())
|
||||
ThrowAbortException(X_FORMAT_ERROR, "'%s' is not a valid format specifier of SystemTime.Format()", error.GetChars());
|
||||
|
||||
time_t val = timeVal;
|
||||
struct tm* timeinfo = localtime(&val);
|
||||
if (timeinfo != nullptr)
|
||||
{
|
||||
char timeString[1024];
|
||||
if (strftime(timeString, sizeof(timeString), timeForm, timeinfo))
|
||||
*result = timeString;
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_SystemTime, Now, GetEpochTime)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
ACTION_RETURN_INT(GetEpochTime());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_SystemTime, Format, FormatTime)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(timeForm);
|
||||
PARAM_INT(timeVal);
|
||||
FString result;
|
||||
FormatTime(timeForm, timeVal, &result);
|
||||
ACTION_RETURN_STRING(result);
|
||||
}
|
||||
|
||||
|
||||
DEFINE_GLOBAL_NAMED(mus_playing, musplaying);
|
||||
DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, name);
|
||||
DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, baseorder);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue