6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * VBox HDD container test utility - scripting engine, interpreter.
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * Copyright (C) 2013 Oracle Corporation
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * This file is part of VirtualBox Open Source Edition (OSE), as
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * available from http://www.virtualbox.org. This file is free software;
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * you can redistribute it and/or modify it under the terms of the GNU
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * General Public License (GPL) as published by the Free Software
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * Foundation, in version 2 as it comes in the "COPYING" file of the
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * Interpreter variable.
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest /** String space core. */
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest /** Value. */
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest/** Pointer to an interpreter variable. */
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forresttypedef VDSCRIPTINTERPVAR *PVDSCRIPTINTERPVAR;
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * Block scope.
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest /** Pointer to the enclosing scope if available. */
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest /** String space of declared variables in this scope. */
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest/** Pointer to a scope block. */
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forresttypedef VDSCRIPTINTERPSCOPE *PVDSCRIPTINTERPSCOPE;
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest * Function call.
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest /** Pointer to the caller of this function. */
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest /** Root scope of this function. */
6b2668dc101d6c62adc8c13810988a006e2ba666Andrew Forrest /** Current scope in this function. */
static int vdScriptInterpreterError(PVDSCRIPTINTERPCTX pThis, int rc, RT_SRC_POS_DECL, const char *pszFmt, ...)
return rc;
if (!pValStack)
if (!pValStack)
return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory pushing a value on the value stack");
return VINF_SUCCESS;
if (pCtrl)
return VINF_SUCCESS;
return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
if (pCtrl)
return VINF_SUCCESS;
return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
DECLINLINE(int) vdScriptInterpreterPushCompoundCtrlEntry(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTSTMT pStmt)
if (pCtrl)
pCtrl->Ctrl.Compound.pStmtCurr = RTListGetFirst(&pStmt->Compound.ListStmts, VDSCRIPTASTSTMT, Core.ListNode);
return VINF_SUCCESS;
return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
DECLINLINE(int) vdScriptInterpreterPushWhileCtrlEntry(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTSTMT pStmt)
if (pCtrl)
rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
return rc;
if (pCtrl)
rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
return rc;
DECLINLINE(int) vdScriptInterpreterPushForCtrlEntry(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTSTMT pStmt)
if (pCtrl)
rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
return rc;
return VINF_SUCCESS;
if (pScope)
rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory allocating new scope");
return rc;
while ( !pVar
&& pScopeCurr)
if (pVar)
return pVar;
PVDSCRIPTFN pFn = (PVDSCRIPTFN)RTStrSpaceGet(&pThis->pScriptCtx->hStrSpaceFn, pExpr->FnCall.pFnIde->pIde->aszIde);
if (pFn)
if (pCtrlFn)
while (pArg)
AssertMsgFailed(("Invalid program given, unknown function: %s\n", pExpr->FnCall.pFnIde->pIde->aszIde));
case VDSCRIPTEXPRTYPE_MODULUS:
case VDSCRIPTEXPRTYPE_LSR:
case VDSCRIPTEXPRTYPE_LSL:
case VDSCRIPTEXPRTYPE_LOWER:
case VDSCRIPTEXPRTYPE_HIGHER:
case VDSCRIPTEXPRTYPE_EQUAL:
case VDSCRIPTEXPRTYPE_ASSIGN:
return rc;
case VDSCRIPTSTMTTYPE_IF:
case VDSCRIPTSTMTTYPE_SWITCH:
case VDSCRIPTSTMTTYPE_WHILE:
case VDSCRIPTSTMTTYPE_RETURN:
while ( pCtrl
case VDSCRIPTSTMTTYPE_FOR:
while ( pCtrl
case VDSCRIPTSTMTTYPE_BREAK:
while ( pCtrl
case VDSCRIPTSTMTTYPE_CASE:
case VDSCRIPTSTMTTYPE_DEFAULT:
return rc;
case VDSCRIPTASTCLASS_INVALID:
return rc;
if (pFnCall)
/* Add the variables, remember order. The first variable in the argument has the value at the top of the value stack. */
if (pVar)
rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a variable");
rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a call frame");
if (paArgs)
return rc;
static int vdScriptInterpreterEvaluateCtrlEntry(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTINTERPCTRL pCtrl)
pCtrl->Ctrl.Compound.pStmtCurr = RTListGetNext(&pCtrl->Ctrl.Compound.pStmtCompound->Compound.ListStmts,
if (Cond.f)
if (Cond.f)
return rc;
while (pCtrl)
return rc;
if (pFn)
for (unsigned i = 0; i < cArgs; i++)
rc = vdScriptInterpreterError(&InterpCtx, VERR_INVALID_PARAMETER, RT_SRC_POS, "Invalid number of parameters, expected %d got %d", pFn->cArgs, cArgs);
rc = vdScriptInterpreterError(&InterpCtx, VERR_NOT_FOUND, RT_SRC_POS, "Function with identifier \"%s\" not found", pszFn);
return rc;