mirror of
https://github.com/ZDoom/Raze.git
synced 2024-12-02 09:02:18 +00:00
84173ee09b
The main bulk of this is the new start screen code. To make this work in Raze some more work on the startup procedure is needed. What this does provide is support for the DOS end-of-game text screens in Duke and SW on non-Windows systems.
1395 lines
No EOL
39 KiB
C++
1395 lines
No EOL
39 KiB
C++
/*
|
|
** zcc_expr.cpp
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright -2016 Randy Heit
|
|
** All rights reserved.
|
|
**
|
|
** Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions
|
|
** are met:
|
|
**
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
** notice, this list of conditions and the following disclaimer.
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
** documentation and/or other materials provided with the distribution.
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
** derived from this software without specific prior written permission.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
**---------------------------------------------------------------------------
|
|
**
|
|
*/
|
|
|
|
#include "dobject.h"
|
|
#include "sc_man.h"
|
|
#include "filesystem.h"
|
|
#include "cmdlib.h"
|
|
#include "m_argv.h"
|
|
#include "v_text.h"
|
|
#include "version.h"
|
|
#include "zcc_parser.h"
|
|
#include "zcc_compile.h"
|
|
|
|
|
|
TArray<FString> Includes;
|
|
TArray<FScriptPosition> IncludeLocs;
|
|
|
|
static FString ZCCTokenName(int terminal);
|
|
void AddInclude(ZCC_ExprConstant *node)
|
|
{
|
|
assert(node->Type == TypeString);
|
|
if (Includes.Find(*node->StringVal) >= Includes.Size())
|
|
{
|
|
Includes.Push(*node->StringVal);
|
|
IncludeLocs.Push(*node);
|
|
}
|
|
}
|
|
|
|
#include "zcc-parse.h"
|
|
#include "zcc-parse.c"
|
|
|
|
struct TokenMapEntry
|
|
{
|
|
int16_t TokenType;
|
|
uint16_t TokenName;
|
|
TokenMapEntry(int16_t a, uint16_t b)
|
|
: TokenType(a), TokenName(b)
|
|
{ }
|
|
};
|
|
static TMap<int16_t, TokenMapEntry> TokenMap;
|
|
static int16_t BackTokenMap[YYERRORSYMBOL]; // YYERRORSYMBOL immediately follows the terminals described by the grammar
|
|
|
|
#define TOKENDEF2(sc, zcc, name) { TokenMapEntry tme(zcc, name); TokenMap.Insert(sc, tme); } BackTokenMap[zcc] = sc
|
|
#define TOKENDEF(sc, zcc) TOKENDEF2(sc, zcc, NAME_None)
|
|
|
|
static void InitTokenMap()
|
|
{
|
|
TOKENDEF ('=', ZCC_EQ);
|
|
TOKENDEF (TK_MulEq, ZCC_MULEQ);
|
|
TOKENDEF (TK_DivEq, ZCC_DIVEQ);
|
|
TOKENDEF (TK_ModEq, ZCC_MODEQ);
|
|
TOKENDEF (TK_AddEq, ZCC_ADDEQ);
|
|
TOKENDEF (TK_SubEq, ZCC_SUBEQ);
|
|
TOKENDEF (TK_LShiftEq, ZCC_LSHEQ);
|
|
TOKENDEF (TK_RShiftEq, ZCC_RSHEQ);
|
|
TOKENDEF (TK_URShiftEq, ZCC_URSHEQ);
|
|
TOKENDEF (TK_AndEq, ZCC_ANDEQ);
|
|
TOKENDEF (TK_OrEq, ZCC_OREQ);
|
|
TOKENDEF (TK_XorEq, ZCC_XOREQ);
|
|
TOKENDEF ('?', ZCC_QUESTION);
|
|
TOKENDEF (':', ZCC_COLON);
|
|
TOKENDEF ('@', ZCC_ATSIGN);
|
|
TOKENDEF (TK_OrOr, ZCC_OROR);
|
|
TOKENDEF (TK_AndAnd, ZCC_ANDAND);
|
|
TOKENDEF (TK_Eq, ZCC_EQEQ);
|
|
TOKENDEF (TK_Neq, ZCC_NEQ);
|
|
TOKENDEF (TK_ApproxEq, ZCC_APPROXEQ);
|
|
TOKENDEF ('<', ZCC_LT);
|
|
TOKENDEF ('>', ZCC_GT);
|
|
TOKENDEF (TK_Leq, ZCC_LTEQ);
|
|
TOKENDEF (TK_Geq, ZCC_GTEQ);
|
|
TOKENDEF (TK_LtGtEq, ZCC_LTGTEQ);
|
|
TOKENDEF (TK_Is, ZCC_IS);
|
|
TOKENDEF (TK_DotDot, ZCC_DOTDOT);
|
|
TOKENDEF (TK_Ellipsis, ZCC_ELLIPSIS);
|
|
TOKENDEF ('|', ZCC_OR);
|
|
TOKENDEF ('^', ZCC_XOR);
|
|
TOKENDEF ('&', ZCC_AND);
|
|
TOKENDEF (TK_LShift, ZCC_LSH);
|
|
TOKENDEF (TK_RShift, ZCC_RSH);
|
|
TOKENDEF (TK_URShift, ZCC_URSH);
|
|
TOKENDEF ('-', ZCC_SUB);
|
|
TOKENDEF ('+', ZCC_ADD);
|
|
TOKENDEF ('*', ZCC_MUL);
|
|
TOKENDEF ('/', ZCC_DIV);
|
|
TOKENDEF ('%', ZCC_MOD);
|
|
TOKENDEF (TK_Cross, ZCC_CROSSPROD);
|
|
TOKENDEF (TK_Dot, ZCC_DOTPROD);
|
|
TOKENDEF (TK_MulMul, ZCC_POW);
|
|
TOKENDEF (TK_Incr, ZCC_ADDADD);
|
|
TOKENDEF (TK_Decr, ZCC_SUBSUB);
|
|
TOKENDEF ('.', ZCC_DOT);
|
|
TOKENDEF ('(', ZCC_LPAREN);
|
|
TOKENDEF (')', ZCC_RPAREN);
|
|
TOKENDEF (TK_ColonColon, ZCC_SCOPE);
|
|
TOKENDEF (';', ZCC_SEMICOLON);
|
|
TOKENDEF (',', ZCC_COMMA);
|
|
TOKENDEF (TK_Class, ZCC_CLASS);
|
|
TOKENDEF (TK_Abstract, ZCC_ABSTRACT);
|
|
TOKENDEF (TK_Native, ZCC_NATIVE);
|
|
TOKENDEF (TK_Action, ZCC_ACTION);
|
|
TOKENDEF (TK_Replaces, ZCC_REPLACES);
|
|
TOKENDEF (TK_Static, ZCC_STATIC);
|
|
TOKENDEF (TK_Private, ZCC_PRIVATE);
|
|
TOKENDEF (TK_Protected, ZCC_PROTECTED);
|
|
TOKENDEF (TK_Latent, ZCC_LATENT);
|
|
TOKENDEF (TK_Virtual, ZCC_VIRTUAL);
|
|
TOKENDEF (TK_VarArg, ZCC_VARARG);
|
|
TOKENDEF (TK_UI, ZCC_UI);
|
|
TOKENDEF (TK_Play, ZCC_PLAY);
|
|
TOKENDEF (TK_ClearScope, ZCC_CLEARSCOPE);
|
|
TOKENDEF (TK_VirtualScope, ZCC_VIRTUALSCOPE);
|
|
TOKENDEF (TK_Override, ZCC_OVERRIDE);
|
|
TOKENDEF (TK_Final, ZCC_FINAL);
|
|
TOKENDEF (TK_Meta, ZCC_META);
|
|
TOKENDEF (TK_Deprecated, ZCC_DEPRECATED);
|
|
TOKENDEF (TK_Version, ZCC_VERSION);
|
|
TOKENDEF (TK_ReadOnly, ZCC_READONLY);
|
|
TOKENDEF (TK_Internal, ZCC_INTERNAL);
|
|
TOKENDEF ('{', ZCC_LBRACE);
|
|
TOKENDEF ('}', ZCC_RBRACE);
|
|
TOKENDEF (TK_Struct, ZCC_STRUCT);
|
|
TOKENDEF (TK_Property, ZCC_PROPERTY);
|
|
TOKENDEF (TK_FlagDef, ZCC_FLAGDEF);
|
|
TOKENDEF (TK_Mixin, ZCC_MIXIN);
|
|
TOKENDEF (TK_Transient, ZCC_TRANSIENT);
|
|
TOKENDEF (TK_Enum, ZCC_ENUM);
|
|
TOKENDEF2(TK_SByte, ZCC_SBYTE, NAME_sByte);
|
|
TOKENDEF2(TK_Byte, ZCC_BYTE, NAME_Byte);
|
|
TOKENDEF2(TK_Short, ZCC_SHORT, NAME_Short);
|
|
TOKENDEF2(TK_UShort, ZCC_USHORT, NAME_uShort);
|
|
TOKENDEF2(TK_Int8, ZCC_SBYTE, NAME_int8);
|
|
TOKENDEF2(TK_UInt8, ZCC_BYTE, NAME_uint8);
|
|
TOKENDEF2(TK_Int16, ZCC_SHORT, NAME_int16);
|
|
TOKENDEF2(TK_UInt16, ZCC_USHORT, NAME_uint16);
|
|
TOKENDEF2(TK_Int, ZCC_INT, NAME_Int);
|
|
TOKENDEF2(TK_UInt, ZCC_UINT, NAME_uInt);
|
|
TOKENDEF2(TK_Bool, ZCC_BOOL, NAME_Bool);
|
|
TOKENDEF2(TK_Float, ZCC_FLOAT, NAME_Float);
|
|
TOKENDEF2(TK_Double, ZCC_DOUBLE, NAME_Double);
|
|
TOKENDEF2(TK_String, ZCC_STRING, NAME_String);
|
|
TOKENDEF2(TK_Vector2, ZCC_VECTOR2, NAME_Vector2);
|
|
TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3);
|
|
TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name);
|
|
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
|
|
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
|
|
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
|
|
TOKENDEF (TK_Void, ZCC_VOID);
|
|
TOKENDEF (TK_True, ZCC_TRUE);
|
|
TOKENDEF (TK_False, ZCC_FALSE);
|
|
TOKENDEF ('[', ZCC_LBRACKET);
|
|
TOKENDEF (']', ZCC_RBRACKET);
|
|
TOKENDEF (TK_In, ZCC_IN);
|
|
TOKENDEF (TK_Out, ZCC_OUT);
|
|
TOKENDEF (TK_Super, ZCC_SUPER);
|
|
TOKENDEF (TK_Null, ZCC_NULLPTR);
|
|
TOKENDEF ('~', ZCC_TILDE);
|
|
TOKENDEF ('!', ZCC_BANG);
|
|
TOKENDEF (TK_SizeOf, ZCC_SIZEOF);
|
|
TOKENDEF (TK_AlignOf, ZCC_ALIGNOF);
|
|
TOKENDEF (TK_Continue, ZCC_CONTINUE);
|
|
TOKENDEF (TK_Break, ZCC_BREAK);
|
|
TOKENDEF (TK_Return, ZCC_RETURN);
|
|
TOKENDEF (TK_Do, ZCC_DO);
|
|
TOKENDEF (TK_For, ZCC_FOR);
|
|
TOKENDEF (TK_While, ZCC_WHILE);
|
|
TOKENDEF (TK_Until, ZCC_UNTIL);
|
|
TOKENDEF (TK_If, ZCC_IF);
|
|
TOKENDEF (TK_Else, ZCC_ELSE);
|
|
TOKENDEF (TK_Switch, ZCC_SWITCH);
|
|
TOKENDEF (TK_Case, ZCC_CASE);
|
|
TOKENDEF2(TK_Default, ZCC_DEFAULT, NAME_Default);
|
|
TOKENDEF (TK_Const, ZCC_CONST);
|
|
TOKENDEF (TK_Stop, ZCC_STOP);
|
|
TOKENDEF (TK_Wait, ZCC_WAIT);
|
|
TOKENDEF (TK_Fail, ZCC_FAIL);
|
|
TOKENDEF (TK_Loop, ZCC_LOOP);
|
|
TOKENDEF (TK_Goto, ZCC_GOTO);
|
|
TOKENDEF (TK_States, ZCC_STATES);
|
|
TOKENDEF2(TK_State, ZCC_STATE, NAME_State);
|
|
TOKENDEF2(TK_Color, ZCC_COLOR, NAME_Color);
|
|
TOKENDEF2(TK_Sound, ZCC_SOUND, NAME_Sound);
|
|
TOKENDEF2(TK_Let, ZCC_LET, NAME_let);
|
|
TOKENDEF2(TK_StaticConst, ZCC_STATICCONST,NAME_Staticconst);
|
|
|
|
TOKENDEF (TK_Identifier, ZCC_IDENTIFIER);
|
|
TOKENDEF (TK_StringConst, ZCC_STRCONST);
|
|
TOKENDEF (TK_NameConst, ZCC_NAMECONST);
|
|
TOKENDEF (TK_IntConst, ZCC_INTCONST);
|
|
TOKENDEF (TK_UIntConst, ZCC_UINTCONST);
|
|
TOKENDEF (TK_FloatConst, ZCC_FLOATCONST);
|
|
TOKENDEF (TK_NonWhitespace, ZCC_NWS);
|
|
|
|
TOKENDEF (TK_Bright, ZCC_BRIGHT);
|
|
TOKENDEF (TK_Slow, ZCC_SLOW);
|
|
TOKENDEF (TK_Fast, ZCC_FAST);
|
|
TOKENDEF (TK_NoDelay, ZCC_NODELAY);
|
|
TOKENDEF (TK_Offset, ZCC_OFFSET);
|
|
TOKENDEF (TK_CanRaise, ZCC_CANRAISE);
|
|
TOKENDEF (TK_Light, ZCC_LIGHT);
|
|
TOKENDEF (TK_Extend, ZCC_EXTEND);
|
|
}
|
|
#undef TOKENDEF
|
|
#undef TOKENDEF2
|
|
|
|
//**--------------------------------------------------------------------------
|
|
|
|
static void ParseSingleFile(FScanner *pSC, const char *filename, int lump, void *parser, ZCCParseState &state)
|
|
{
|
|
int tokentype;
|
|
//bool failed;
|
|
ZCCToken value;
|
|
FScanner lsc;
|
|
|
|
if (pSC == nullptr)
|
|
{
|
|
if (filename != nullptr)
|
|
{
|
|
lump = fileSystem.CheckNumForFullName(filename, true);
|
|
if (lump >= 0)
|
|
{
|
|
lsc.OpenLumpNum(lump);
|
|
}
|
|
else
|
|
{
|
|
Printf("Could not find script lump '%s'\n", filename);
|
|
return;
|
|
}
|
|
}
|
|
else lsc.OpenLumpNum(lump);
|
|
|
|
pSC = &lsc;
|
|
}
|
|
FScanner &sc = *pSC;
|
|
sc.SetParseVersion(state.ParseVersion);
|
|
state.sc = ≻
|
|
|
|
while (sc.GetToken())
|
|
{
|
|
value.Largest = 0;
|
|
value.SourceLoc = sc.GetMessageLine();
|
|
switch (sc.TokenType)
|
|
{
|
|
case TK_StringConst:
|
|
value.String = state.Strings.Alloc(sc.String, sc.StringLen);
|
|
tokentype = ZCC_STRCONST;
|
|
break;
|
|
|
|
case TK_NameConst:
|
|
value.Int = FName(sc.String).GetIndex();
|
|
tokentype = ZCC_NAMECONST;
|
|
break;
|
|
|
|
case TK_IntConst:
|
|
value.Int = sc.Number;
|
|
tokentype = ZCC_INTCONST;
|
|
break;
|
|
|
|
case TK_UIntConst:
|
|
value.Int = sc.Number;
|
|
tokentype = ZCC_UINTCONST;
|
|
break;
|
|
|
|
case TK_FloatConst:
|
|
value.Float = sc.Float;
|
|
tokentype = ZCC_FLOATCONST;
|
|
break;
|
|
|
|
case TK_None: // 'NONE' is a token for SBARINFO but not here.
|
|
case TK_Identifier:
|
|
value.Int = FName(sc.String).GetIndex();
|
|
tokentype = ZCC_IDENTIFIER;
|
|
break;
|
|
|
|
case TK_NonWhitespace:
|
|
value.Int = FName(sc.String).GetIndex();
|
|
tokentype = ZCC_NWS;
|
|
break;
|
|
|
|
case TK_Static:
|
|
sc.MustGetAnyToken();
|
|
// The oh so wonderful grammar has problems with the 'const' token thanks to the overly broad rule for constants,
|
|
// which effectively prevents use of this token nearly anywhere else. So in order to get 'static const' through
|
|
// on the class/struct level we have to muck around with the token type here so that both words get combined into
|
|
// a single token that doesn't make the grammar throw a fit.
|
|
if (sc.TokenType == TK_Const)
|
|
{
|
|
tokentype = ZCC_STATICCONST;
|
|
value.Int = NAME_Staticconst;
|
|
}
|
|
else
|
|
{
|
|
tokentype = ZCC_STATIC;
|
|
value.Int = NAME_Static;
|
|
sc.UnGet();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
TokenMapEntry *zcctoken = TokenMap.CheckKey(sc.TokenType);
|
|
if (zcctoken != nullptr)
|
|
{
|
|
tokentype = zcctoken->TokenType;
|
|
value.Int = zcctoken->TokenName;
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptMessage("Unexpected token %s.\n", sc.TokenName(sc.TokenType).GetChars());
|
|
goto parse_end;
|
|
}
|
|
break;
|
|
}
|
|
ZCCParse(parser, tokentype, value, &state);
|
|
}
|
|
parse_end:
|
|
value.Int = -1;
|
|
ZCCParse(parser, ZCC_EOF, value, &state);
|
|
state.sc = nullptr;
|
|
}
|
|
|
|
//**--------------------------------------------------------------------------
|
|
|
|
PNamespace *ParseOneScript(const int baselump, ZCCParseState &state)
|
|
{
|
|
FScanner sc;
|
|
void *parser;
|
|
ZCCToken value;
|
|
int lumpnum = baselump;
|
|
auto fileno = fileSystem.GetFileContainer(lumpnum);
|
|
|
|
if (TokenMap.CountUsed() == 0)
|
|
{
|
|
InitTokenMap();
|
|
}
|
|
|
|
parser = ZCCParseAlloc(malloc);
|
|
|
|
#ifndef NDEBUG
|
|
FILE *f = nullptr;
|
|
const char *tracefile = Args->CheckValue("-tracefile");
|
|
if (tracefile != nullptr)
|
|
{
|
|
f = fopen(tracefile, "w");
|
|
char prompt = '\0';
|
|
ZCCParseTrace(f, &prompt);
|
|
}
|
|
#endif
|
|
|
|
sc.OpenLumpNum(lumpnum);
|
|
sc.SetParseVersion({ 2, 4 }); // To get 'version' we need parse version 2.4 for the initial test
|
|
auto saved = sc.SavePos();
|
|
|
|
if (sc.GetToken())
|
|
{
|
|
if (sc.TokenType == TK_Version)
|
|
{
|
|
char *endp;
|
|
sc.MustGetString();
|
|
state.ParseVersion.major = (int16_t)clamp<unsigned long long>(strtoull(sc.String, &endp, 10), 0, USHRT_MAX);
|
|
if (*endp != '.')
|
|
{
|
|
sc.ScriptError("Bad version directive");
|
|
}
|
|
state.ParseVersion.minor = (int16_t)clamp<unsigned long long>(strtoll(endp + 1, &endp, 10), 0, USHRT_MAX);
|
|
if (*endp == '.')
|
|
{
|
|
state.ParseVersion.revision = (int16_t)clamp<unsigned long long>(strtoll(endp + 1, &endp, 10), 0, USHRT_MAX);
|
|
}
|
|
else state.ParseVersion.revision = 0;
|
|
if (*endp != 0)
|
|
{
|
|
sc.ScriptError("Bad version directive");
|
|
}
|
|
if (state.ParseVersion.major == USHRT_MAX || state.ParseVersion.minor == USHRT_MAX || state.ParseVersion.revision == USHRT_MAX)
|
|
{
|
|
sc.ScriptError("Bad version directive");
|
|
}
|
|
if (state.ParseVersion > MakeVersion(VER_MAJOR, VER_MINOR, VER_REVISION))
|
|
{
|
|
sc.ScriptError("The file you are attempting to run requires a newer version of " GAMENAME ".\n\nA version with ZScript version %d.%d.%d is required, but your copy of " GAMENAME " only supports %d.%d.%d. Please upgrade!", state.ParseVersion.major, state.ParseVersion.minor, state.ParseVersion.revision, VER_MAJOR, VER_MINOR, VER_REVISION);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
state.ParseVersion = MakeVersion(2, 3); // 2.3 is the first version of ZScript.
|
|
sc.RestorePos(saved);
|
|
}
|
|
}
|
|
|
|
ParseSingleFile(&sc, nullptr, lumpnum, parser, state);
|
|
for (unsigned i = 0; i < Includes.Size(); i++)
|
|
{
|
|
lumpnum = fileSystem.CheckNumForFullName(Includes[i], true);
|
|
if (lumpnum == -1 && ( Includes[i].IndexOf("./") == 0 || Includes[i].IndexOf("../") == 0 ) ) // relative path resolving
|
|
{
|
|
FString fullPath = IncludeLocs[i].FileName.GetChars(); // get full path, format 'wad:filepath/filename'
|
|
|
|
long start = fullPath.IndexOf(":"); // find first ':'
|
|
|
|
long end = fullPath.LastIndexOf("/"); // find last '/'
|
|
|
|
if (start!=-1&&end!=-1)
|
|
{
|
|
FString resolvedPath = fullPath.Mid(start + 1, end - start - 1); // extract filepath from string
|
|
FString relativePath = Includes[i];
|
|
if ( relativePath.IndexOf("./") == 0 ) // strip initial marker
|
|
{
|
|
relativePath = relativePath.Mid(2);
|
|
}
|
|
|
|
bool pathOk = true;
|
|
|
|
while (relativePath.IndexOf("../") == 0) // go back one folder for each '..'
|
|
{
|
|
relativePath = relativePath.Mid(3);
|
|
long slash_index = resolvedPath.LastIndexOf("/");
|
|
if (slash_index != -1) {
|
|
resolvedPath = resolvedPath.Mid(0,slash_index);
|
|
} else {
|
|
pathOk = false;
|
|
break;
|
|
}
|
|
}
|
|
if ( pathOk ) // if '..' parsing was successful
|
|
{
|
|
resolvedPath += "/" + relativePath; // add relative path
|
|
|
|
lumpnum = fileSystem.CheckNumForFullName(resolvedPath, true); // check for relative include
|
|
}
|
|
}
|
|
|
|
}
|
|
if (lumpnum == -1)
|
|
{
|
|
IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars());
|
|
}
|
|
else
|
|
{
|
|
auto fileno2 = fileSystem.GetFileContainer(lumpnum);
|
|
if (fileno == 0 && fileno2 != 0)
|
|
{
|
|
I_FatalError("File %s is overriding core lump %s.",
|
|
fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(lumpnum)), Includes[i].GetChars());
|
|
}
|
|
|
|
ParseSingleFile(nullptr, nullptr, lumpnum, parser, state);
|
|
}
|
|
}
|
|
Includes.Clear();
|
|
Includes.ShrinkToFit();
|
|
IncludeLocs.Clear();
|
|
IncludeLocs.ShrinkToFit();
|
|
|
|
value.Int = -1;
|
|
value.SourceLoc = sc.GetMessageLine();
|
|
ZCCParse(parser, 0, value, &state);
|
|
ZCCParseFree(parser, free);
|
|
|
|
// If the parser fails, there is no point starting the compiler, because it'd only flood the output with endless errors.
|
|
if (FScriptPosition::ErrorCounter > 0)
|
|
{
|
|
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, fileSystem.GetFileFullPath(baselump).GetChars());
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
if (f != nullptr)
|
|
{
|
|
fclose(f);
|
|
}
|
|
#endif
|
|
|
|
// Make a dump of the AST before running the compiler for diagnostic purposes.
|
|
if (Args->CheckParm("-dumpast"))
|
|
{
|
|
FString ast = ZCC_PrintAST(state.TopNode);
|
|
FString filename = fileSystem.GetFileFullPath(baselump);
|
|
filename.ReplaceChars(":\\/?|", '.');
|
|
filename << ".ast";
|
|
FileWriter *ff = FileWriter::Open(filename);
|
|
if (ff != NULL)
|
|
{
|
|
ff->Write(ast.GetChars(), ast.Len());
|
|
delete ff;
|
|
}
|
|
}
|
|
|
|
auto newns = fileSystem.GetFileContainer(baselump) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(fileSystem.GetFileContainer(baselump));
|
|
return newns;
|
|
}
|
|
|
|
static FString ZCCTokenName(int terminal)
|
|
{
|
|
if (terminal == ZCC_EOF)
|
|
{
|
|
return "end of file";
|
|
}
|
|
int sc_token;
|
|
if (terminal > 0 && terminal < (int)countof(BackTokenMap))
|
|
{
|
|
sc_token = BackTokenMap[terminal];
|
|
if (sc_token == 0)
|
|
{ // This token was not initialized. Whoops!
|
|
sc_token = -terminal;
|
|
}
|
|
}
|
|
else
|
|
{ // This should never happen.
|
|
sc_token = -terminal;
|
|
}
|
|
return FScanner::TokenName(sc_token);
|
|
}
|
|
|
|
ZCC_TreeNode *ZCC_AST::InitNode(size_t size, EZCCTreeNodeType type, ZCC_TreeNode *basis)
|
|
{
|
|
ZCC_TreeNode *node = (ZCC_TreeNode *)SyntaxArena.Alloc(size);
|
|
node->SiblingNext = node;
|
|
node->SiblingPrev = node;
|
|
node->NodeType = type;
|
|
if (basis != NULL)
|
|
{
|
|
node->SourceName = basis->SourceName;
|
|
node->SourceLump = basis->SourceLump;
|
|
node->SourceLoc = basis->SourceLoc;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ZCC_TreeNode *ZCCParseState::InitNode(size_t size, EZCCTreeNodeType type)
|
|
{
|
|
ZCC_TreeNode *node = ZCC_AST::InitNode(size, type, NULL);
|
|
node->SourceName = Strings.Alloc(sc->ScriptName);
|
|
node->SourceLump = sc->LumpNum;
|
|
return node;
|
|
}
|
|
|
|
// Appends a sibling to this node's sibling list.
|
|
void AppendTreeNodeSibling(ZCC_TreeNode *thisnode, ZCC_TreeNode *sibling)
|
|
{
|
|
if (thisnode == nullptr)
|
|
{
|
|
// Some bad syntax can actually get here, so better abort so that the user can see the error which caused this.
|
|
I_FatalError("Internal script compiler error. Execution aborted.");
|
|
}
|
|
if (sibling == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ZCC_TreeNode *&SiblingPrev = thisnode->SiblingPrev;
|
|
ZCC_TreeNode *&SiblingNext = thisnode->SiblingNext;
|
|
|
|
// Check integrity of our sibling list.
|
|
assert(SiblingPrev->SiblingNext == thisnode);
|
|
assert(SiblingNext->SiblingPrev == thisnode);
|
|
|
|
// Check integrity of new sibling list.
|
|
assert(sibling->SiblingPrev->SiblingNext == sibling);
|
|
assert(sibling->SiblingNext->SiblingPrev == sibling);
|
|
|
|
ZCC_TreeNode *siblingend = sibling->SiblingPrev;
|
|
SiblingPrev->SiblingNext = sibling;
|
|
sibling->SiblingPrev = SiblingPrev;
|
|
SiblingPrev = siblingend;
|
|
siblingend->SiblingNext = thisnode;
|
|
}
|
|
|
|
//**--------------------------------------------------------------------------
|
|
|
|
const char *GetMixinTypeString(EZCCMixinType type) {
|
|
switch (type) {
|
|
case ZCC_Mixin_Class:
|
|
return "class";
|
|
|
|
default:
|
|
assert(0 && "Unhandled mixin type");
|
|
return "invalid type";
|
|
}
|
|
}
|
|
|
|
//**--------------------------------------------------------------------------
|
|
|
|
ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings, TMap<ZCC_TreeNode *, ZCC_TreeNode *> *copiedNodesList);
|
|
void TreeNodeDeepCopy_Base(ZCC_AST *ast, ZCC_TreeNode *orig, ZCC_TreeNode *copy, bool copySiblings, TMap<ZCC_TreeNode *, ZCC_TreeNode *> *copiedNodesList)
|
|
{
|
|
copy->SourceName = orig->SourceName;
|
|
copy->SourceLump = orig->SourceLump;
|
|
copy->SourceLoc = orig->SourceLoc;
|
|
copy->NodeType = orig->NodeType;
|
|
|
|
if (copySiblings)
|
|
{
|
|
auto node = orig->SiblingNext;
|
|
while (node != orig)
|
|
{
|
|
auto nextNode = TreeNodeDeepCopy_Internal(ast, node, false, copiedNodesList);
|
|
auto newLast = nextNode->SiblingPrev;
|
|
|
|
auto firstNode = copy;
|
|
auto lastNode = firstNode->SiblingPrev;
|
|
|
|
lastNode->SiblingNext = nextNode;
|
|
firstNode->SiblingPrev = newLast;
|
|
|
|
nextNode->SiblingPrev = lastNode;
|
|
newLast->SiblingNext = firstNode;
|
|
|
|
node = node->SiblingNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
#define GetTreeNode(type) static_cast<ZCC_##type *>(ast->InitNode(sizeof(ZCC_##type), AST_##type, nullptr));
|
|
#define TreeNodeDeepCopy_Start(type) \
|
|
auto copy = GetTreeNode(type); \
|
|
auto origCasted = static_cast<ZCC_##type *>(orig); \
|
|
ret = copy; \
|
|
copiedNodesList->Insert(orig, ret);
|
|
|
|
ZCC_TreeNode *TreeNodeDeepCopy(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings)
|
|
{
|
|
TMap<ZCC_TreeNode *, ZCC_TreeNode *> copiedNodesList;
|
|
copiedNodesList.Clear();
|
|
|
|
return TreeNodeDeepCopy_Internal(ast, orig, copySiblings, &copiedNodesList);
|
|
}
|
|
|
|
ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings, TMap<ZCC_TreeNode *, ZCC_TreeNode *> *copiedNodesList)
|
|
{
|
|
// [pbeta] This is a legitimate case as otherwise this function would need
|
|
// an excessive amount of "if" statements, so just return null.
|
|
if (orig == nullptr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
// [pbeta] We need to keep and check a list of already copied nodes, because
|
|
// some are supposed to be the same, and it can cause infinite loops.
|
|
auto existingCopy = copiedNodesList->CheckKey(orig);
|
|
if (existingCopy != nullptr)
|
|
{
|
|
return *existingCopy;
|
|
}
|
|
|
|
ZCC_TreeNode *ret = nullptr;
|
|
|
|
switch (orig->NodeType)
|
|
{
|
|
case AST_Identifier:
|
|
{
|
|
TreeNodeDeepCopy_Start(Identifier);
|
|
|
|
// ZCC_Identifier
|
|
copy->Id = origCasted->Id;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Struct:
|
|
{
|
|
TreeNodeDeepCopy_Start(Struct);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_Struct
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList);
|
|
copy->Type = origCasted->Type;
|
|
copy->Version = origCasted->Version;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Class:
|
|
{
|
|
TreeNodeDeepCopy_Start(Class);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_Struct
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList);
|
|
copy->Type = origCasted->Type;
|
|
copy->Version = origCasted->Version;
|
|
// ZCC_Class
|
|
copy->ParentName = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->ParentName, true, copiedNodesList));
|
|
copy->Replaces = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Replaces, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Enum:
|
|
{
|
|
TreeNodeDeepCopy_Start(Enum);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_Enum
|
|
copy->EnumType = origCasted->EnumType;
|
|
copy->Elements = static_cast<ZCC_ConstantDef *>(TreeNodeDeepCopy_Internal(ast, origCasted->Elements, false, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_EnumTerminator:
|
|
{
|
|
TreeNodeDeepCopy_Start (EnumTerminator);
|
|
break;
|
|
}
|
|
|
|
case AST_States:
|
|
{
|
|
TreeNodeDeepCopy_Start(States);
|
|
|
|
// ZCC_States
|
|
copy->Body = static_cast<ZCC_StatePart *>(TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList));
|
|
copy->Flags = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Flags, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_StatePart:
|
|
{
|
|
TreeNodeDeepCopy_Start (StatePart);
|
|
break;
|
|
}
|
|
|
|
case AST_StateLabel:
|
|
{
|
|
TreeNodeDeepCopy_Start(StateLabel);
|
|
|
|
// ZCC_StateLabel
|
|
copy->Label = origCasted->Label;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_StateStop:
|
|
{
|
|
TreeNodeDeepCopy_Start (StateStop);
|
|
break;
|
|
}
|
|
|
|
case AST_StateWait:
|
|
{
|
|
TreeNodeDeepCopy_Start (StateWait);
|
|
break;
|
|
}
|
|
|
|
case AST_StateFail:
|
|
{
|
|
TreeNodeDeepCopy_Start (StateFail);
|
|
break;
|
|
}
|
|
|
|
case AST_StateLoop:
|
|
{
|
|
TreeNodeDeepCopy_Start (StateLoop);
|
|
break;
|
|
}
|
|
|
|
case AST_StateGoto:
|
|
{
|
|
TreeNodeDeepCopy_Start(StateGoto);
|
|
|
|
// ZCC_StateGoto
|
|
copy->Qualifier = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Qualifier, true, copiedNodesList));
|
|
copy->Label = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Label, true, copiedNodesList));
|
|
copy->Offset = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Offset, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_StateLine:
|
|
{
|
|
TreeNodeDeepCopy_Start(StateLine);
|
|
|
|
// ZCC_StateLine
|
|
copy->Sprite = origCasted->Sprite;
|
|
|
|
copy->bBright = origCasted->bBright;
|
|
copy->bFast = origCasted->bFast;
|
|
copy->bSlow = origCasted->bSlow;
|
|
copy->bNoDelay = origCasted->bNoDelay;
|
|
copy->bCanRaise = origCasted->bCanRaise;
|
|
|
|
copy->Frames = origCasted->Frames;
|
|
copy->Duration = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Duration, true, copiedNodesList));
|
|
copy->Offset = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Offset, true, copiedNodesList));
|
|
copy->Lights = static_cast<ZCC_ExprConstant *>(TreeNodeDeepCopy_Internal(ast, origCasted->Lights, true, copiedNodesList));
|
|
copy->Action = TreeNodeDeepCopy_Internal(ast, origCasted->Action, true, copiedNodesList);
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_VarName:
|
|
{
|
|
TreeNodeDeepCopy_Start(VarName);
|
|
|
|
// ZCC_VarName
|
|
copy->Name = origCasted->Name;
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_VarInit:
|
|
{
|
|
TreeNodeDeepCopy_Start(VarInit);
|
|
|
|
// ZCC_VarName
|
|
copy->Name = origCasted->Name;
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_VarInit
|
|
copy->Init = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Init, true, copiedNodesList));
|
|
copy->InitIsArray = origCasted->InitIsArray;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Type:
|
|
{
|
|
TreeNodeDeepCopy_Start(Type);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_BasicType:
|
|
{
|
|
TreeNodeDeepCopy_Start(BasicType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_BasicType
|
|
copy->Type = origCasted->Type;
|
|
copy->UserType = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->UserType, true, copiedNodesList));
|
|
copy->isconst = origCasted->isconst;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_MapType:
|
|
{
|
|
TreeNodeDeepCopy_Start(MapType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_MapType
|
|
copy->KeyType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->KeyType, true, copiedNodesList));
|
|
copy->ValueType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->ValueType, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_DynArrayType:
|
|
{
|
|
TreeNodeDeepCopy_Start(DynArrayType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_DynArrayType
|
|
copy->ElementType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->ElementType, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ClassType:
|
|
{
|
|
TreeNodeDeepCopy_Start(ClassType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_ClassType
|
|
copy->Restriction = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Restriction, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Expression:
|
|
{
|
|
TreeNodeDeepCopy_Start(Expression);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprID:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprID);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprID
|
|
copy->Identifier = origCasted->Identifier;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprTypeRef:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprTypeRef);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprTypeRef
|
|
copy->RefType = origCasted->RefType;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprConstant:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprConstant);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprConstant
|
|
// Currently handled: StringVal, IntVal and DoubleVal. (UIntVal appears to be completely unused.)
|
|
if (origCasted->Type == TypeString)
|
|
{
|
|
copy->StringVal = origCasted->StringVal;
|
|
}
|
|
else if (origCasted->Type == TypeFloat64 || origCasted->Type == TypeFloat32)
|
|
{
|
|
copy->DoubleVal = origCasted->DoubleVal;
|
|
}
|
|
else if (origCasted->Type == TypeName || origCasted->Type->isIntCompatible())
|
|
{
|
|
copy->IntVal = origCasted->IntVal;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprFuncCall:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprFuncCall);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprFuncCall
|
|
copy->Function = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Function, true, copiedNodesList));
|
|
copy->Parameters = static_cast<ZCC_FuncParm *>(TreeNodeDeepCopy_Internal(ast, origCasted->Parameters, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprMemberAccess:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprMemberAccess);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprMemberAccess
|
|
copy->Left = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList));
|
|
copy->Right = origCasted->Right;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprUnary:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprUnary);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprUnary
|
|
copy->Operand = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Operand, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprBinary:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprBinary);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprBinary
|
|
copy->Left = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList));
|
|
copy->Right = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Right, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprTrinary:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprTrinary);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprTrinary
|
|
copy->Test = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Test, true, copiedNodesList));
|
|
copy->Left = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList));
|
|
copy->Right = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Right, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FuncParm:
|
|
{
|
|
TreeNodeDeepCopy_Start(FuncParm);
|
|
|
|
// ZCC_FuncParm
|
|
copy->Value = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Value, true, copiedNodesList));
|
|
copy->Label = origCasted->Label;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Statement:
|
|
{
|
|
TreeNodeDeepCopy_Start (Statement);
|
|
break;
|
|
}
|
|
|
|
case AST_CompoundStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(CompoundStmt);
|
|
|
|
// ZCC_CompoundStmt
|
|
copy->Content = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ContinueStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start (ContinueStmt);
|
|
break;
|
|
}
|
|
|
|
case AST_BreakStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start (BreakStmt);
|
|
break;
|
|
}
|
|
|
|
case AST_ReturnStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(ReturnStmt);
|
|
|
|
// ZCC_ReturnStmt
|
|
copy->Values = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExpressionStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExpressionStmt);
|
|
|
|
// ZCC_ExpressionStmt
|
|
copy->Expression = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Expression, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_IterationStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(IterationStmt);
|
|
|
|
// ZCC_IterationStmt
|
|
copy->LoopCondition = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopCondition, true, copiedNodesList));
|
|
copy->LoopStatement = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList));
|
|
copy->LoopBumper = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopBumper, true, copiedNodesList));
|
|
copy->CheckAt = origCasted->CheckAt;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_IfStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(IfStmt);
|
|
|
|
// ZCC_IfStmt
|
|
copy->Condition = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList));
|
|
copy->TruePath = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->TruePath, true, copiedNodesList));
|
|
copy->FalsePath = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->FalsePath, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_SwitchStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(SwitchStmt);
|
|
|
|
// ZCC_SwitchStmt
|
|
copy->Condition = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList));
|
|
copy->Content = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_CaseStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(CaseStmt);
|
|
|
|
// ZCC_CaseStmt
|
|
copy->Condition = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_AssignStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(AssignStmt);
|
|
|
|
// ZCC_AssignStmt
|
|
copy->Dests = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Dests, true, copiedNodesList));
|
|
copy->Sources = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Sources, true, copiedNodesList));
|
|
copy->AssignOp = origCasted->AssignOp;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_LocalVarStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(LocalVarStmt);
|
|
|
|
// ZCC_LocalVarStmt
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Vars = static_cast<ZCC_VarInit *>(TreeNodeDeepCopy_Internal(ast, origCasted->Vars, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FuncParamDecl:
|
|
{
|
|
TreeNodeDeepCopy_Start(FuncParamDecl);
|
|
|
|
// ZCC_FuncParamDecl
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Default = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Default, true, copiedNodesList));
|
|
copy->Name = origCasted->Name;
|
|
copy->Flags = origCasted->Flags;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ConstantDef:
|
|
{
|
|
TreeNodeDeepCopy_Start(ConstantDef);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_ConstantDef
|
|
copy->Value = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Value, true, copiedNodesList));
|
|
copy->Symbol = origCasted->Symbol;
|
|
if (copy->Symbol != nullptr)
|
|
{
|
|
copy->Type = static_cast<ZCC_Enum *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Declarator:
|
|
{
|
|
TreeNodeDeepCopy_Start(Declarator);
|
|
|
|
// ZCC_Declarator
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Version = origCasted->Version;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_VarDeclarator:
|
|
{
|
|
TreeNodeDeepCopy_Start(VarDeclarator);
|
|
|
|
// ZCC_Declarator
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Version = origCasted->Version;
|
|
// ZCC_VarDeclarator
|
|
copy->Names = static_cast<ZCC_VarName *>(TreeNodeDeepCopy_Internal(ast, origCasted->Names, true, copiedNodesList));
|
|
copy->DeprecationMessage = origCasted->DeprecationMessage;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FuncDeclarator:
|
|
{
|
|
TreeNodeDeepCopy_Start(FuncDeclarator);
|
|
|
|
// ZCC_Declarator
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Version = origCasted->Version;
|
|
// ZCC_FuncDeclarator
|
|
copy->Params = static_cast<ZCC_FuncParamDecl *>(TreeNodeDeepCopy_Internal(ast, origCasted->Params, true, copiedNodesList));
|
|
copy->Name = origCasted->Name;
|
|
copy->Body = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList));
|
|
copy->UseFlags = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->UseFlags, true, copiedNodesList));
|
|
copy->DeprecationMessage = origCasted->DeprecationMessage;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Default:
|
|
{
|
|
TreeNodeDeepCopy_Start(Default);
|
|
|
|
// ZCC_CompoundStmt
|
|
copy->Content = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FlagStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(FlagStmt);
|
|
|
|
// ZCC_FlagStmt
|
|
copy->name = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->name, true, copiedNodesList));
|
|
copy->set = origCasted->set;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_PropertyStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(PropertyStmt);
|
|
|
|
// ZCC_PropertyStmt
|
|
copy->Prop = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Prop, true, copiedNodesList));
|
|
copy->Values = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_VectorValue:
|
|
{
|
|
TreeNodeDeepCopy_Start(VectorValue);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_VectorValue
|
|
copy->X = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->X, true, copiedNodesList));
|
|
copy->Y = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Y, true, copiedNodesList));
|
|
copy->Z = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Z, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_DeclFlags:
|
|
{
|
|
TreeNodeDeepCopy_Start(DeclFlags);
|
|
|
|
// ZCC_DeclFlags
|
|
copy->Id = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Id, true, copiedNodesList));
|
|
copy->DeprecationMessage = origCasted->DeprecationMessage;
|
|
copy->Version = origCasted->Version;
|
|
copy->Flags = origCasted->Flags;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ClassCast:
|
|
{
|
|
TreeNodeDeepCopy_Start(ClassCast);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ClassCast
|
|
copy->ClassName = origCasted->ClassName;
|
|
copy->Parameters = static_cast<ZCC_FuncParm *>(TreeNodeDeepCopy_Internal(ast, origCasted->Parameters, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_StaticArrayStatement:
|
|
{
|
|
TreeNodeDeepCopy_Start(StaticArrayStatement);
|
|
|
|
// ZCC_StaticArrayStatement
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Id = origCasted->Id;
|
|
copy->Values = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Property:
|
|
{
|
|
TreeNodeDeepCopy_Start(Property);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_Property
|
|
copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList);
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FlagDef:
|
|
{
|
|
TreeNodeDeepCopy_Start(FlagDef);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_FlagDef
|
|
copy->RefName = origCasted->RefName;
|
|
copy->BitValue = origCasted->BitValue;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_MixinDef:
|
|
{
|
|
TreeNodeDeepCopy_Start(MixinDef);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_MixinDef
|
|
copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList);
|
|
copy->MixinType = origCasted->MixinType;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_MixinStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(MixinStmt);
|
|
|
|
// ZCC_MixinStmt
|
|
copy->MixinName = origCasted->MixinName;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
assert(0 && "Unimplemented node type");
|
|
break;
|
|
}
|
|
|
|
TreeNodeDeepCopy_Base(ast, orig, ret, copySiblings, copiedNodesList);
|
|
|
|
return ret;
|
|
} |