summaryrefslogtreecommitdiffstats
path: root/src/VBox/Storage/testcase/VDScriptAst.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Storage/testcase/VDScriptAst.cpp')
-rw-r--r--src/VBox/Storage/testcase/VDScriptAst.cpp366
1 files changed, 366 insertions, 0 deletions
diff --git a/src/VBox/Storage/testcase/VDScriptAst.cpp b/src/VBox/Storage/testcase/VDScriptAst.cpp
new file mode 100644
index 00000000..c7fc01f6
--- /dev/null
+++ b/src/VBox/Storage/testcase/VDScriptAst.cpp
@@ -0,0 +1,366 @@
+/* $Id: VDScriptAst.cpp $ */
+/** @file
+ * VBox HDD container test utility - scripting engine AST node related functions.
+ */
+
+/*
+ * Copyright (C) 2013-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+#define LOGGROUP LOGGROUP_DEFAULT
+#include <iprt/list.h>
+#include <iprt/mem.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+#include <VBox/log.h>
+
+#include "VDScriptAst.h"
+
+/**
+ * Put all child nodes of the given expression AST node onto the given to free list.
+ *
+ * @param pList The free list to append everything to.
+ * @param pAstNode The expression node to free.
+ */
+static void vdScriptAstNodeExpressionPutOnFreeList(PRTLISTANCHOR pList, PVDSCRIPTASTCORE pAstNode)
+{
+ AssertMsgReturnVoid(pAstNode->enmClass == VDSCRIPTASTCLASS_EXPRESSION,
+ ("Given AST node is not a statement\n"));
+
+ PVDSCRIPTASTEXPR pExpr = (PVDSCRIPTASTEXPR)pAstNode;
+ switch (pExpr->enmType)
+ {
+ case VDSCRIPTEXPRTYPE_PRIMARY_NUMCONST:
+ case VDSCRIPTEXPRTYPE_PRIMARY_BOOLEAN:
+ break;
+ case VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST:
+ RTStrFree((char *)pExpr->pszStr);
+ break;
+ case VDSCRIPTEXPRTYPE_PRIMARY_IDENTIFIER:
+ {
+ RTListAppend(pList, &pExpr->pIde->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTEXPRTYPE_ASSIGNMENT_LIST:
+ {
+ while (!RTListIsEmpty(&pExpr->ListExpr))
+ {
+ PVDSCRIPTASTCORE pNode = RTListGetFirst(&pExpr->ListExpr, VDSCRIPTASTCORE, ListNode);
+ RTListNodeRemove(&pNode->ListNode);
+ RTListAppend(pList, &pNode->ListNode);
+ }
+ break;
+ }
+ case VDSCRIPTEXPRTYPE_POSTFIX_FNCALL:
+ {
+ RTListAppend(pList, &pExpr->FnCall.pFnIde->Core.ListNode);
+ while (!RTListIsEmpty(&pExpr->FnCall.ListArgs))
+ {
+ PVDSCRIPTASTCORE pNode = RTListGetFirst(&pExpr->FnCall.ListArgs, VDSCRIPTASTCORE, ListNode);
+ RTListNodeRemove(&pNode->ListNode);
+ RTListAppend(pList, &pNode->ListNode);
+ }
+ break;
+ }
+ case VDSCRIPTEXPRTYPE_POSTFIX_DEREFERENCE:
+ case VDSCRIPTEXPRTYPE_POSTFIX_DOT:
+ {
+ RTListAppend(pList, &pExpr->Deref.pIde->Core.ListNode);
+ RTListAppend(pList, &pExpr->Deref.pExpr->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTEXPRTYPE_POSTFIX_INCREMENT:
+ case VDSCRIPTEXPRTYPE_POSTFIX_DECREMENT:
+ case VDSCRIPTEXPRTYPE_UNARY_INCREMENT:
+ case VDSCRIPTEXPRTYPE_UNARY_DECREMENT:
+ case VDSCRIPTEXPRTYPE_UNARY_POSSIGN:
+ case VDSCRIPTEXPRTYPE_UNARY_NEGSIGN:
+ case VDSCRIPTEXPRTYPE_UNARY_INVERT:
+ case VDSCRIPTEXPRTYPE_UNARY_NEGATE:
+ case VDSCRIPTEXPRTYPE_UNARY_REFERENCE:
+ case VDSCRIPTEXPRTYPE_UNARY_DEREFERENCE:
+ {
+ RTListAppend(pList, &pExpr->pExpr->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTEXPRTYPE_MULTIPLICATION:
+ case VDSCRIPTEXPRTYPE_DIVISION:
+ case VDSCRIPTEXPRTYPE_MODULUS:
+ case VDSCRIPTEXPRTYPE_ADDITION:
+ case VDSCRIPTEXPRTYPE_SUBTRACTION:
+ case VDSCRIPTEXPRTYPE_LSR:
+ case VDSCRIPTEXPRTYPE_LSL:
+ case VDSCRIPTEXPRTYPE_LOWER:
+ case VDSCRIPTEXPRTYPE_HIGHER:
+ case VDSCRIPTEXPRTYPE_LOWEREQUAL:
+ case VDSCRIPTEXPRTYPE_HIGHEREQUAL:
+ case VDSCRIPTEXPRTYPE_EQUAL:
+ case VDSCRIPTEXPRTYPE_NOTEQUAL:
+ case VDSCRIPTEXPRTYPE_BITWISE_AND:
+ case VDSCRIPTEXPRTYPE_BITWISE_XOR:
+ case VDSCRIPTEXPRTYPE_BITWISE_OR:
+ case VDSCRIPTEXPRTYPE_LOGICAL_AND:
+ case VDSCRIPTEXPRTYPE_LOGICAL_OR:
+ case VDSCRIPTEXPRTYPE_ASSIGN:
+ case VDSCRIPTEXPRTYPE_ASSIGN_MULT:
+ case VDSCRIPTEXPRTYPE_ASSIGN_DIV:
+ case VDSCRIPTEXPRTYPE_ASSIGN_MOD:
+ case VDSCRIPTEXPRTYPE_ASSIGN_ADD:
+ case VDSCRIPTEXPRTYPE_ASSIGN_SUB:
+ case VDSCRIPTEXPRTYPE_ASSIGN_LSL:
+ case VDSCRIPTEXPRTYPE_ASSIGN_LSR:
+ case VDSCRIPTEXPRTYPE_ASSIGN_AND:
+ case VDSCRIPTEXPRTYPE_ASSIGN_XOR:
+ case VDSCRIPTEXPRTYPE_ASSIGN_OR:
+ {
+ RTListAppend(pList, &pExpr->BinaryOp.pLeftExpr->Core.ListNode);
+ RTListAppend(pList, &pExpr->BinaryOp.pRightExpr->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTEXPRTYPE_INVALID:
+ default:
+ AssertMsgFailedReturnVoid(("Invalid AST node expression type %d\n",
+ pExpr->enmType));
+ }
+}
+
+/**
+ * Free a given statement AST node and put everything on the given to free list.
+ *
+ * @param pList The free list to append everything to.
+ * @param pAstNode The statement node to free.
+ */
+static void vdScriptAstNodeStatmentPutOnFreeList(PRTLISTANCHOR pList, PVDSCRIPTASTCORE pAstNode)
+{
+ AssertMsgReturnVoid(pAstNode->enmClass == VDSCRIPTASTCLASS_STATEMENT,
+ ("Given AST node is not a statement\n"));
+
+ PVDSCRIPTASTSTMT pStmt = (PVDSCRIPTASTSTMT)pAstNode;
+ switch (pStmt->enmStmtType)
+ {
+ case VDSCRIPTSTMTTYPE_COMPOUND:
+ {
+ /* Put all declarations on the to free list. */
+ while (!RTListIsEmpty(&pStmt->Compound.ListDecls))
+ {
+ PVDSCRIPTASTCORE pNode = RTListGetFirst(&pStmt->Compound.ListDecls, VDSCRIPTASTCORE, ListNode);
+ RTListNodeRemove(&pNode->ListNode);
+ RTListAppend(pList, &pNode->ListNode);
+ }
+
+ /* Put all statements on the to free list. */
+ while (!RTListIsEmpty(&pStmt->Compound.ListStmts))
+ {
+ PVDSCRIPTASTCORE pNode = RTListGetFirst(&pStmt->Compound.ListStmts, VDSCRIPTASTCORE, ListNode);
+ RTListNodeRemove(&pNode->ListNode);
+ RTListAppend(pList, &pNode->ListNode);
+ }
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_EXPRESSION:
+ {
+ if (pStmt->pExpr)
+ RTListAppend(pList, &pStmt->pExpr->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_IF:
+ {
+ RTListAppend(pList, &pStmt->If.pCond->Core.ListNode);
+ RTListAppend(pList, &pStmt->If.pTrueStmt->Core.ListNode);
+ if (pStmt->If.pElseStmt)
+ RTListAppend(pList, &pStmt->If.pElseStmt->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_SWITCH:
+ {
+ RTListAppend(pList, &pStmt->Switch.pCond->Core.ListNode);
+ RTListAppend(pList, &pStmt->Switch.pStmt->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_WHILE:
+ {
+ RTListAppend(pList, &pStmt->While.pCond->Core.ListNode);
+ RTListAppend(pList, &pStmt->While.pStmt->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_FOR:
+ {
+ RTListAppend(pList, &pStmt->For.pExprStart->Core.ListNode);
+ RTListAppend(pList, &pStmt->For.pExprCond->Core.ListNode);
+ RTListAppend(pList, &pStmt->For.pExpr3->Core.ListNode);
+ RTListAppend(pList, &pStmt->For.pStmt->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_RETURN:
+ {
+ if (pStmt->pExpr)
+ RTListAppend(pList, &pStmt->pExpr->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_CASE:
+ {
+ RTListAppend(pList, &pStmt->Case.pExpr->Core.ListNode);
+ RTListAppend(pList, &pStmt->Case.pStmt->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_DEFAULT:
+ {
+ RTListAppend(pList, &pStmt->Case.pStmt->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTSTMTTYPE_CONTINUE:
+ case VDSCRIPTSTMTTYPE_BREAK:
+ break;
+ case VDSCRIPTSTMTTYPE_INVALID:
+ default:
+ AssertMsgFailedReturnVoid(("Invalid AST node statement type %d\n",
+ pStmt->enmStmtType));
+ }
+}
+
+DECLHIDDEN(void) vdScriptAstNodeFree(PVDSCRIPTASTCORE pAstNode)
+{
+ RTLISTANCHOR ListFree;
+
+ /*
+ * The node is not allowed to be part of a list because we need it
+ * for the nodes to free list.
+ */
+ Assert(RTListIsEmpty(&pAstNode->ListNode));
+ RTListInit(&ListFree);
+ RTListAppend(&ListFree, &pAstNode->ListNode);
+
+ do
+ {
+ pAstNode = RTListGetFirst(&ListFree, VDSCRIPTASTCORE, ListNode);
+ RTListNodeRemove(&pAstNode->ListNode);
+
+ switch (pAstNode->enmClass)
+ {
+ case VDSCRIPTASTCLASS_FUNCTION:
+ {
+ PVDSCRIPTASTFN pFn = (PVDSCRIPTASTFN)pAstNode;
+
+ if (pFn->pRetType)
+ RTListAppend(&ListFree, &pFn->pRetType->Core.ListNode);
+ if (pFn->pFnIde)
+ RTListAppend(&ListFree, &pFn->pFnIde->Core.ListNode);
+
+ /* Put argument list on the to free list. */
+ while (!RTListIsEmpty(&pFn->ListArgs))
+ {
+ PVDSCRIPTASTCORE pArg = RTListGetFirst(&pFn->ListArgs, VDSCRIPTASTCORE, ListNode);
+ RTListNodeRemove(&pArg->ListNode);
+ RTListAppend(&ListFree, &pArg->ListNode);
+ }
+
+ /* Put compound statement onto the list. */
+ RTListAppend(&ListFree, &pFn->pCompoundStmts->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTASTCLASS_FUNCTIONARG:
+ {
+ PVDSCRIPTASTFNARG pAstNodeArg = (PVDSCRIPTASTFNARG)pAstNode;
+ if (pAstNodeArg->pType)
+ RTListAppend(&ListFree, &pAstNodeArg->pType->Core.ListNode);
+ if (pAstNodeArg->pArgIde)
+ RTListAppend(&ListFree, &pAstNodeArg->pArgIde->Core.ListNode);
+ break;
+ }
+ case VDSCRIPTASTCLASS_IDENTIFIER:
+ break;
+ case VDSCRIPTASTCLASS_DECLARATION:
+ case VDSCRIPTASTCLASS_TYPENAME:
+ {
+ AssertMsgFailed(("TODO\n"));
+ break;
+ }
+ case VDSCRIPTASTCLASS_STATEMENT:
+ {
+ vdScriptAstNodeStatmentPutOnFreeList(&ListFree, pAstNode);
+ break;
+ }
+ case VDSCRIPTASTCLASS_EXPRESSION:
+ {
+ vdScriptAstNodeExpressionPutOnFreeList(&ListFree, pAstNode);
+ break;
+ }
+ case VDSCRIPTASTCLASS_INVALID:
+ default:
+ AssertMsgFailedReturnVoid(("Invalid AST node class given %d\n", pAstNode->enmClass));
+ }
+
+ RTMemFree(pAstNode);
+ } while (!RTListIsEmpty(&ListFree));
+
+}
+
+DECLHIDDEN(PVDSCRIPTASTCORE) vdScriptAstNodeAlloc(VDSCRIPTASTCLASS enmClass)
+{
+ size_t cbAlloc = 0;
+
+ switch (enmClass)
+ {
+ case VDSCRIPTASTCLASS_FUNCTION:
+ cbAlloc = sizeof(VDSCRIPTASTFN);
+ break;
+ case VDSCRIPTASTCLASS_FUNCTIONARG:
+ cbAlloc = sizeof(VDSCRIPTASTFNARG);
+ break;
+ case VDSCRIPTASTCLASS_DECLARATION:
+ cbAlloc = sizeof(VDSCRIPTASTDECL);
+ break;
+ case VDSCRIPTASTCLASS_STATEMENT:
+ cbAlloc = sizeof(VDSCRIPTASTSTMT);
+ break;
+ case VDSCRIPTASTCLASS_EXPRESSION:
+ cbAlloc = sizeof(VDSCRIPTASTEXPR);
+ break;
+ case VDSCRIPTASTCLASS_TYPENAME:
+ cbAlloc = sizeof(VDSCRIPTASTTYPENAME);
+ break;
+ case VDSCRIPTASTCLASS_IDENTIFIER:
+ case VDSCRIPTASTCLASS_INVALID:
+ default:
+ AssertMsgFailedReturn(("Invalid AST node class given %d\n", enmClass), NULL);
+ }
+
+ PVDSCRIPTASTCORE pAstNode = (PVDSCRIPTASTCORE)RTMemAllocZ(cbAlloc);
+ if (pAstNode)
+ {
+ pAstNode->enmClass = enmClass;
+ RTListInit(&pAstNode->ListNode);
+ }
+
+ return pAstNode;
+}
+
+DECLHIDDEN(PVDSCRIPTASTIDE) vdScriptAstNodeIdeAlloc(size_t cchIde)
+{
+ PVDSCRIPTASTIDE pAstNode = (PVDSCRIPTASTIDE)RTMemAllocZ(RT_UOFFSETOF_DYN(VDSCRIPTASTIDE, aszIde[cchIde + 1]));
+ if (pAstNode)
+ {
+ pAstNode->Core.enmClass = VDSCRIPTASTCLASS_IDENTIFIER;
+ RTListInit(&pAstNode->Core.ListNode);
+ }
+
+ return pAstNode;
+}