VirtualBox

source: vbox/trunk/src/VBox/Storage/testcase/VDScriptAst.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/* $Id: VDScriptAst.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox HDD container test utility - scripting engine AST node related functions.
4 */
5
6/*
7 * Copyright (C) 2013-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27#define LOGGROUP LOGGROUP_DEFAULT
28#include <iprt/list.h>
29#include <iprt/mem.h>
30#include <iprt/assert.h>
31#include <iprt/string.h>
32
33#include <VBox/log.h>
34
35#include "VDScriptAst.h"
36
37/**
38 * Put all child nodes of the given expression AST node onto the given to free list.
39 *
40 * @returns nothing.
41 * @param pList The free list to append everything to.
42 * @param pAstNode The expression node to free.
43 */
44static void vdScriptAstNodeExpressionPutOnFreeList(PRTLISTANCHOR pList, PVDSCRIPTASTCORE pAstNode)
45{
46 AssertMsgReturnVoid(pAstNode->enmClass == VDSCRIPTASTCLASS_EXPRESSION,
47 ("Given AST node is not a statement\n"));
48
49 PVDSCRIPTASTEXPR pExpr = (PVDSCRIPTASTEXPR)pAstNode;
50 switch (pExpr->enmType)
51 {
52 case VDSCRIPTEXPRTYPE_PRIMARY_NUMCONST:
53 case VDSCRIPTEXPRTYPE_PRIMARY_BOOLEAN:
54 break;
55 case VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST:
56 RTStrFree((char *)pExpr->pszStr);
57 break;
58 case VDSCRIPTEXPRTYPE_PRIMARY_IDENTIFIER:
59 {
60 RTListAppend(pList, &pExpr->pIde->Core.ListNode);
61 break;
62 }
63 case VDSCRIPTEXPRTYPE_ASSIGNMENT_LIST:
64 {
65 while (!RTListIsEmpty(&pExpr->ListExpr))
66 {
67 PVDSCRIPTASTCORE pNode = RTListGetFirst(&pExpr->ListExpr, VDSCRIPTASTCORE, ListNode);
68 RTListNodeRemove(&pNode->ListNode);
69 RTListAppend(pList, &pNode->ListNode);
70 }
71 break;
72 }
73 case VDSCRIPTEXPRTYPE_POSTFIX_FNCALL:
74 {
75 RTListAppend(pList, &pExpr->FnCall.pFnIde->Core.ListNode);
76 while (!RTListIsEmpty(&pExpr->FnCall.ListArgs))
77 {
78 PVDSCRIPTASTCORE pNode = RTListGetFirst(&pExpr->FnCall.ListArgs, VDSCRIPTASTCORE, ListNode);
79 RTListNodeRemove(&pNode->ListNode);
80 RTListAppend(pList, &pNode->ListNode);
81 }
82 break;
83 }
84 case VDSCRIPTEXPRTYPE_POSTFIX_DEREFERENCE:
85 case VDSCRIPTEXPRTYPE_POSTFIX_DOT:
86 {
87 RTListAppend(pList, &pExpr->Deref.pIde->Core.ListNode);
88 RTListAppend(pList, &pExpr->Deref.pExpr->Core.ListNode);
89 break;
90 }
91 case VDSCRIPTEXPRTYPE_POSTFIX_INCREMENT:
92 case VDSCRIPTEXPRTYPE_POSTFIX_DECREMENT:
93 case VDSCRIPTEXPRTYPE_UNARY_INCREMENT:
94 case VDSCRIPTEXPRTYPE_UNARY_DECREMENT:
95 case VDSCRIPTEXPRTYPE_UNARY_POSSIGN:
96 case VDSCRIPTEXPRTYPE_UNARY_NEGSIGN:
97 case VDSCRIPTEXPRTYPE_UNARY_INVERT:
98 case VDSCRIPTEXPRTYPE_UNARY_NEGATE:
99 case VDSCRIPTEXPRTYPE_UNARY_REFERENCE:
100 case VDSCRIPTEXPRTYPE_UNARY_DEREFERENCE:
101 {
102 RTListAppend(pList, &pExpr->pExpr->Core.ListNode);
103 break;
104 }
105 case VDSCRIPTEXPRTYPE_MULTIPLICATION:
106 case VDSCRIPTEXPRTYPE_DIVISION:
107 case VDSCRIPTEXPRTYPE_MODULUS:
108 case VDSCRIPTEXPRTYPE_ADDITION:
109 case VDSCRIPTEXPRTYPE_SUBTRACTION:
110 case VDSCRIPTEXPRTYPE_LSR:
111 case VDSCRIPTEXPRTYPE_LSL:
112 case VDSCRIPTEXPRTYPE_LOWER:
113 case VDSCRIPTEXPRTYPE_HIGHER:
114 case VDSCRIPTEXPRTYPE_LOWEREQUAL:
115 case VDSCRIPTEXPRTYPE_HIGHEREQUAL:
116 case VDSCRIPTEXPRTYPE_EQUAL:
117 case VDSCRIPTEXPRTYPE_NOTEQUAL:
118 case VDSCRIPTEXPRTYPE_BITWISE_AND:
119 case VDSCRIPTEXPRTYPE_BITWISE_XOR:
120 case VDSCRIPTEXPRTYPE_BITWISE_OR:
121 case VDSCRIPTEXPRTYPE_LOGICAL_AND:
122 case VDSCRIPTEXPRTYPE_LOGICAL_OR:
123 case VDSCRIPTEXPRTYPE_ASSIGN:
124 case VDSCRIPTEXPRTYPE_ASSIGN_MULT:
125 case VDSCRIPTEXPRTYPE_ASSIGN_DIV:
126 case VDSCRIPTEXPRTYPE_ASSIGN_MOD:
127 case VDSCRIPTEXPRTYPE_ASSIGN_ADD:
128 case VDSCRIPTEXPRTYPE_ASSIGN_SUB:
129 case VDSCRIPTEXPRTYPE_ASSIGN_LSL:
130 case VDSCRIPTEXPRTYPE_ASSIGN_LSR:
131 case VDSCRIPTEXPRTYPE_ASSIGN_AND:
132 case VDSCRIPTEXPRTYPE_ASSIGN_XOR:
133 case VDSCRIPTEXPRTYPE_ASSIGN_OR:
134 {
135 RTListAppend(pList, &pExpr->BinaryOp.pLeftExpr->Core.ListNode);
136 RTListAppend(pList, &pExpr->BinaryOp.pRightExpr->Core.ListNode);
137 break;
138 }
139 case VDSCRIPTEXPRTYPE_INVALID:
140 default:
141 AssertMsgFailedReturnVoid(("Invalid AST node expression type %d\n",
142 pExpr->enmType));
143 }
144}
145
146/**
147 * Free a given statement AST node and put everything on the given to free list.
148 *
149 * @returns nothing.
150 * @param pList The free list to append everything to.
151 * @param pAstNode The statement node to free.
152 */
153static void vdScriptAstNodeStatmentPutOnFreeList(PRTLISTANCHOR pList, PVDSCRIPTASTCORE pAstNode)
154{
155 AssertMsgReturnVoid(pAstNode->enmClass == VDSCRIPTASTCLASS_STATEMENT,
156 ("Given AST node is not a statement\n"));
157
158 PVDSCRIPTASTSTMT pStmt = (PVDSCRIPTASTSTMT)pAstNode;
159 switch (pStmt->enmStmtType)
160 {
161 case VDSCRIPTSTMTTYPE_COMPOUND:
162 {
163 /* Put all declarations on the to free list. */
164 while (!RTListIsEmpty(&pStmt->Compound.ListDecls))
165 {
166 PVDSCRIPTASTCORE pNode = RTListGetFirst(&pStmt->Compound.ListDecls, VDSCRIPTASTCORE, ListNode);
167 RTListNodeRemove(&pNode->ListNode);
168 RTListAppend(pList, &pNode->ListNode);
169 }
170
171 /* Put all statements on the to free list. */
172 while (!RTListIsEmpty(&pStmt->Compound.ListStmts))
173 {
174 PVDSCRIPTASTCORE pNode = RTListGetFirst(&pStmt->Compound.ListStmts, VDSCRIPTASTCORE, ListNode);
175 RTListNodeRemove(&pNode->ListNode);
176 RTListAppend(pList, &pNode->ListNode);
177 }
178 break;
179 }
180 case VDSCRIPTSTMTTYPE_EXPRESSION:
181 {
182 if (pStmt->pExpr)
183 RTListAppend(pList, &pStmt->pExpr->Core.ListNode);
184 break;
185 }
186 case VDSCRIPTSTMTTYPE_IF:
187 {
188 RTListAppend(pList, &pStmt->If.pCond->Core.ListNode);
189 RTListAppend(pList, &pStmt->If.pTrueStmt->Core.ListNode);
190 if (pStmt->If.pElseStmt)
191 RTListAppend(pList, &pStmt->If.pElseStmt->Core.ListNode);
192 break;
193 }
194 case VDSCRIPTSTMTTYPE_SWITCH:
195 {
196 RTListAppend(pList, &pStmt->Switch.pCond->Core.ListNode);
197 RTListAppend(pList, &pStmt->Switch.pStmt->Core.ListNode);
198 break;
199 }
200 case VDSCRIPTSTMTTYPE_WHILE:
201 {
202 RTListAppend(pList, &pStmt->While.pCond->Core.ListNode);
203 RTListAppend(pList, &pStmt->While.pStmt->Core.ListNode);
204 break;
205 }
206 case VDSCRIPTSTMTTYPE_FOR:
207 {
208 RTListAppend(pList, &pStmt->For.pExprStart->Core.ListNode);
209 RTListAppend(pList, &pStmt->For.pExprCond->Core.ListNode);
210 RTListAppend(pList, &pStmt->For.pExpr3->Core.ListNode);
211 RTListAppend(pList, &pStmt->For.pStmt->Core.ListNode);
212 break;
213 }
214 case VDSCRIPTSTMTTYPE_RETURN:
215 {
216 if (pStmt->pExpr)
217 RTListAppend(pList, &pStmt->pExpr->Core.ListNode);
218 break;
219 }
220 case VDSCRIPTSTMTTYPE_CASE:
221 {
222 RTListAppend(pList, &pStmt->Case.pExpr->Core.ListNode);
223 RTListAppend(pList, &pStmt->Case.pStmt->Core.ListNode);
224 break;
225 }
226 case VDSCRIPTSTMTTYPE_DEFAULT:
227 {
228 RTListAppend(pList, &pStmt->Case.pStmt->Core.ListNode);
229 break;
230 }
231 case VDSCRIPTSTMTTYPE_CONTINUE:
232 case VDSCRIPTSTMTTYPE_BREAK:
233 break;
234 case VDSCRIPTSTMTTYPE_INVALID:
235 default:
236 AssertMsgFailedReturnVoid(("Invalid AST node statement type %d\n",
237 pStmt->enmStmtType));
238 }
239}
240
241DECLHIDDEN(void) vdScriptAstNodeFree(PVDSCRIPTASTCORE pAstNode)
242{
243 RTLISTANCHOR ListFree;
244
245 /*
246 * The node is not allowed to be part of a list because we need it
247 * for the nodes to free list.
248 */
249 Assert(RTListIsEmpty(&pAstNode->ListNode));
250 RTListInit(&ListFree);
251 RTListAppend(&ListFree, &pAstNode->ListNode);
252
253 do
254 {
255 pAstNode = RTListGetFirst(&ListFree, VDSCRIPTASTCORE, ListNode);
256 RTListNodeRemove(&pAstNode->ListNode);
257
258 switch (pAstNode->enmClass)
259 {
260 case VDSCRIPTASTCLASS_FUNCTION:
261 {
262 PVDSCRIPTASTFN pFn = (PVDSCRIPTASTFN)pAstNode;
263
264 if (pFn->pRetType)
265 RTListAppend(&ListFree, &pFn->pRetType->Core.ListNode);
266 if (pFn->pFnIde)
267 RTListAppend(&ListFree, &pFn->pFnIde->Core.ListNode);
268
269 /* Put argument list on the to free list. */
270 while (!RTListIsEmpty(&pFn->ListArgs))
271 {
272 PVDSCRIPTASTCORE pArg = RTListGetFirst(&pFn->ListArgs, VDSCRIPTASTCORE, ListNode);
273 RTListNodeRemove(&pArg->ListNode);
274 RTListAppend(&ListFree, &pArg->ListNode);
275 }
276
277 /* Put compound statement onto the list. */
278 RTListAppend(&ListFree, &pFn->pCompoundStmts->Core.ListNode);
279 break;
280 }
281 case VDSCRIPTASTCLASS_FUNCTIONARG:
282 {
283 PVDSCRIPTASTFNARG pAstNodeArg = (PVDSCRIPTASTFNARG)pAstNode;
284 if (pAstNodeArg->pType)
285 RTListAppend(&ListFree, &pAstNodeArg->pType->Core.ListNode);
286 if (pAstNodeArg->pArgIde)
287 RTListAppend(&ListFree, &pAstNodeArg->pArgIde->Core.ListNode);
288 break;
289 }
290 case VDSCRIPTASTCLASS_IDENTIFIER:
291 break;
292 case VDSCRIPTASTCLASS_DECLARATION:
293 case VDSCRIPTASTCLASS_TYPENAME:
294 {
295 AssertMsgFailed(("TODO\n"));
296 break;
297 }
298 case VDSCRIPTASTCLASS_STATEMENT:
299 {
300 vdScriptAstNodeStatmentPutOnFreeList(&ListFree, pAstNode);
301 break;
302 }
303 case VDSCRIPTASTCLASS_EXPRESSION:
304 {
305 vdScriptAstNodeExpressionPutOnFreeList(&ListFree, pAstNode);
306 break;
307 }
308 case VDSCRIPTASTCLASS_INVALID:
309 default:
310 AssertMsgFailedReturnVoid(("Invalid AST node class given %d\n", pAstNode->enmClass));
311 }
312
313 RTMemFree(pAstNode);
314 } while (!RTListIsEmpty(&ListFree));
315
316}
317
318DECLHIDDEN(PVDSCRIPTASTCORE) vdScriptAstNodeAlloc(VDSCRIPTASTCLASS enmClass)
319{
320 size_t cbAlloc = 0;
321
322 switch (enmClass)
323 {
324 case VDSCRIPTASTCLASS_FUNCTION:
325 cbAlloc = sizeof(VDSCRIPTASTFN);
326 break;
327 case VDSCRIPTASTCLASS_FUNCTIONARG:
328 cbAlloc = sizeof(VDSCRIPTASTFNARG);
329 break;
330 case VDSCRIPTASTCLASS_DECLARATION:
331 cbAlloc = sizeof(VDSCRIPTASTDECL);
332 break;
333 case VDSCRIPTASTCLASS_STATEMENT:
334 cbAlloc = sizeof(VDSCRIPTASTSTMT);
335 break;
336 case VDSCRIPTASTCLASS_EXPRESSION:
337 cbAlloc = sizeof(VDSCRIPTASTEXPR);
338 break;
339 case VDSCRIPTASTCLASS_TYPENAME:
340 cbAlloc = sizeof(VDSCRIPTASTTYPENAME);
341 break;
342 case VDSCRIPTASTCLASS_IDENTIFIER:
343 case VDSCRIPTASTCLASS_INVALID:
344 default:
345 AssertMsgFailedReturn(("Invalid AST node class given %d\n", enmClass), NULL);
346 }
347
348 PVDSCRIPTASTCORE pAstNode = (PVDSCRIPTASTCORE)RTMemAllocZ(cbAlloc);
349 if (pAstNode)
350 {
351 pAstNode->enmClass = enmClass;
352 RTListInit(&pAstNode->ListNode);
353 }
354
355 return pAstNode;
356}
357
358DECLHIDDEN(PVDSCRIPTASTIDE) vdScriptAstNodeIdeAlloc(size_t cchIde)
359{
360 PVDSCRIPTASTIDE pAstNode = (PVDSCRIPTASTIDE)RTMemAllocZ(RT_UOFFSETOF_DYN(VDSCRIPTASTIDE, aszIde[cchIde + 1]));
361 if (pAstNode)
362 {
363 pAstNode->Core.enmClass = VDSCRIPTASTCLASS_IDENTIFIER;
364 RTListInit(&pAstNode->Core.ListNode);
365 }
366
367 return pAstNode;
368}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use