VirtualBox

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

Last change on this file since 55747 was 52371, checked in by vboxsync, 10 years ago

Storage/tstVDIo: Plug leaks, modifications and start turning it into a proper testcase for unit tests

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette