VirtualBox

Changeset 44941 in vbox


Ignore:
Timestamp:
Mar 6, 2013 10:13:17 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
84147
Message:

Storage/testcase: More scripting language work

Location:
trunk/src/VBox/Storage/testcase
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/testcase/VDScript.cpp

    r44901 r44941  
     1/** $Id$ */
    12/** @file
    23 *
     
    370371    bool fNewline = true;
    371372
    372     if (   *pTokenizer->pszInput == '\r'
     373    if (   vdScriptTokenizerGetCh(pTokenizer) == '\r'
    373374        && vdScriptTokenizerPeekCh(pTokenizer) == '\n')
    374375        vdScriptTokenizerNewLine(pTokenizer, 2);
    375     else if (*pTokenizer->pszInput == '\n')
     376    else if (vdScriptTokenizerGetCh(pTokenizer) == '\n')
    376377        vdScriptTokenizerNewLine(pTokenizer, 1);
    377378    else
     
    390391{
    391392    while (   !vdScriptTokenizerIsEos(pTokenizer)
    392            && *pTokenizer->pszInput != '*'
    393            && vdScriptTokenizerPeekCh(pTokenizer) != '/')
     393           && (   vdScriptTokenizerGetCh(pTokenizer) != '*'
     394               || vdScriptTokenizerPeekCh(pTokenizer) != '/'))
    394395    {
    395396        if (!vdScriptTokenizerIsSkipNewLine(pTokenizer))
     
    504505    for (unsigned i = 0; i < cchNumber; i++)
    505506        vdScriptTokenizerSkipCh(pTokenizer);
     507
     508    /* Check for a supported suffix, supported are K|M|G. */
     509    if (vdScriptTokenizerGetCh(pTokenizer) == 'K')
     510    {
     511        pToken->Class.NumConst.u64 *= _1K;
     512        vdScriptTokenizerSkipCh(pTokenizer);
     513    }
     514    else if (vdScriptTokenizerGetCh(pTokenizer) == 'M')
     515    {
     516        pToken->Class.NumConst.u64 *= _1M;
     517        vdScriptTokenizerSkipCh(pTokenizer);
     518    }
     519    else if (vdScriptTokenizerGetCh(pTokenizer) == 'G')
     520    {
     521        pToken->Class.NumConst.u64 *= _1G;
     522        vdScriptTokenizerSkipCh(pTokenizer);
     523    }
    506524}
    507525
     
    931949                PCVDSCRIPTTOKEN pToken = vdScriptTokenizerGetToken(pThis->pTokenizer);
    932950                pExpr->enmType = VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST;
    933                 pExpr->pszStr = RTStrDup(pToken->Class.StringConst.pszString);
     951                pExpr->pszStr = RTStrDupN(pToken->Class.StringConst.pszString, pToken->Class.StringConst.cchString);
    934952                vdScriptTokenizerConsume(pThis->pTokenizer);
    935953
    936954                if (!pExpr->pszStr)
    937955                    rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating string\n");
     956            }
     957            else if (vdScriptTokenizerGetTokenClass(pThis->pTokenizer) == VDTOKENCLASS_KEYWORD)
     958            {
     959                PCVDSCRIPTTOKEN pToken = vdScriptTokenizerGetToken(pThis->pTokenizer);
     960                pExpr->enmType = VDSCRIPTEXPRTYPE_PRIMARY_BOOLEAN;
     961
     962                if (pToken->Class.Keyword.enmKeyword == VDSCRIPTTOKENKEYWORD_TRUE)
     963                    pExpr->f = true;
     964                else if (pToken->Class.Keyword.enmKeyword == VDSCRIPTTOKENKEYWORD_FALSE)
     965                    pExpr->f = false;
     966                else
     967                    rc = vdScriptParserError(pThis, VERR_INVALID_PARAMETER, RT_SRC_POS, "Parser: Unexpected keyword, expected true or false\n");
     968                vdScriptTokenizerConsume(pThis->pTokenizer);
    938969            }
    939970            else
     
    25052536                            pAstNodeFn->pCompoundStmts = pAstCompound;
    25062537                            RTListAppend(&pThis->ListAst, &pAstNodeFn->Core.ListNode);
     2538
     2539                            PVDSCRIPTFN pFn = (PVDSCRIPTFN)RTMemAllocZ(sizeof(VDSCRIPTFN));
     2540                            if (pFn)
     2541                            {
     2542                                pFn->Core.pszString = pAstNodeFn->pFnIde->aszIde;
     2543                                pFn->Core.cchString = strlen(pFn->Core.pszString);
     2544                                pFn->fExternal      = false;
     2545                                pFn->Type.Internal.pAstFn = pAstNodeFn;
     2546                                /** @todo: Parameters. */
     2547                                RTStrSpaceInsert(&pThis->hStrSpaceFn, &pFn->Core);
     2548                            }
     2549                            else
     2550                                rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory allocating memory for function\n");
    25072551                        }
    25082552                    }
     
    26002644}
    26012645
    2602 DECLHIDDEN(int) VDScriptCtxCallbacksRegister(VDSCRIPTCTX hScriptCtx, PVDSCRIPTCALLBACK paCallbacks,
     2646DECLHIDDEN(int) VDScriptCtxCallbacksRegister(VDSCRIPTCTX hScriptCtx, PCVDSCRIPTCALLBACK paCallbacks,
    26032647                                             unsigned cCallbacks, void *pvUser)
    26042648{
     
    26792723                                  PVDSCRIPTARG paArgs, unsigned cArgs)
    26802724{
    2681     return VERR_NOT_IMPLEMENTED;
    2682 }
     2725    PVDSCRIPTCTXINT pThis = hScriptCtx;
     2726    VDSCRIPTARG Ret;
     2727    return vdScriptCtxInterprete(pThis, pszFnCall, paArgs, cArgs, &Ret);
     2728}
  • trunk/src/VBox/Storage/testcase/VDScript.h

    r44891 r44941  
    4848/** Pointer to a type. */
    4949typedef VDSCRIPTTYPE *PVDSCRIPTTYPE;
     50/** Pointer to a const type. */
     51typedef const VDSCRIPTTYPE *PCVDSCRIPTTYPE;
    5052
    5153/**
     
    8890    /** The return type of the function. */
    8991    VDSCRIPTTYPE           enmTypeReturn;
     92    /** Pointer to the array of argument types. */
     93    PCVDSCRIPTTYPE         paArgs;
    9094    /** Number of arguments this method takes. */
    9195    unsigned               cArgs;
    92     /** Pointer to the array of argument types. */
    93     PVDSCRIPTTYPE          paArgs;
    9496    /** The callback handler. */
    9597    PFNVDSCRIPTCALLBACK    pfnCallback;
     
    9799/** Pointer to a callback register entry. */
    98100typedef VDSCRIPTCALLBACK *PVDSCRIPTCALLBACK;
     101/** Pointer to a const callback register entry. */
     102typedef const VDSCRIPTCALLBACK *PCVDSCRIPTCALLBACK;
    99103
    100104/**
     
    123127 * @param   pvUser         Opaque user data to pass on the callback invocation.
    124128 */
    125 DECLHIDDEN(int) VDScriptCtxCallbacksRegister(VDSCRIPTCTX hScriptCtx, PVDSCRIPTCALLBACK paCallbacks,
     129DECLHIDDEN(int) VDScriptCtxCallbacksRegister(VDSCRIPTCTX hScriptCtx, PCVDSCRIPTCALLBACK paCallbacks,
    126130                                             unsigned cCallbacks, void *pvUser);
    127131
  • trunk/src/VBox/Storage/testcase/VDScriptAst.cpp

    r44891 r44941  
     1/** $Id$ */
    12/** @file
    23 *
     
    4142    {
    4243        case VDSCRIPTEXPRTYPE_PRIMARY_NUMCONST:
     44        case VDSCRIPTEXPRTYPE_PRIMARY_BOOLEAN:
    4345            break;
    4446        case VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST:
     
    160162        case VDSCRIPTSTMTTYPE_EXPRESSION:
    161163        {
    162             RTListAppend(pList, &pStmt->pExpr->Core.ListNode);
     164            if (pStmt->pExpr)
     165                RTListAppend(pList, &pStmt->pExpr->Core.ListNode);
    163166            break;
    164167        }
     
    215218            AssertMsgFailedReturnVoid(("Invalid AST node statement type %d\n",
    216219                                       pStmt->enmStmtType));
    217     } 
     220    }
    218221}
    219222
  • trunk/src/VBox/Storage/testcase/VDScriptAst.h

    r44901 r44941  
    118118    /** String constant. */
    119119    VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST,
     120    /** Boolean constant. */
     121    VDSCRIPTEXPRTYPE_PRIMARY_BOOLEAN,
    120122    /** Identifier. */
    121123    VDSCRIPTEXPRTYPE_PRIMARY_IDENTIFIER,
     
    222224        /** String literal */
    223225        const char       *pszStr;
     226        /** Boolean constant. */
     227        bool              f;
    224228        /** List of expressions - VDSCRIPTASTEXPR. */
    225229        RTLISTANCHOR      ListExpr;
  • trunk/src/VBox/Storage/testcase/VDScriptChecker.cpp

    r44842 r44941  
     1/** $Id$ */
    12/** @file
    23 *
  • trunk/src/VBox/Storage/testcase/VDScriptInterp.cpp

    r44901 r44941  
     1/** $Id$ */
    12/** @file
    23 *
     
    2021#include <iprt/assert.h>
    2122#include <iprt/string.h>
     23#include <iprt/stream.h>
    2224
    2325#include <VBox/log.h>
     
    99101    /** If statement to evaluate now, the guard is on the stack. */
    100102    VDSCRIPTINTERPCTRLTYPE_IF,
     103    /** While statement. */
     104    VDSCRIPTINTERPCTRLTYPE_WHILE,
     105    /** for statement. */
     106    VDSCRIPTINTERPCTRLTYPE_FOR,
     107    /** switch statement. */
     108    VDSCRIPTINTERPCTRLTYPE_SWITCH,
     109    /** Compound statement. */
     110    VDSCRIPTINTERPCTRLTYPE_COMPOUND,
     111    /** 32bit blowup. */
    101112    VDSCRIPTINTERPCTRLTYPE_32BIT_HACK = 0x7fffffff
    102113} VDSCRIPTINTERPCTRLTYPE;
     
    125136            {
    126137                /** Function to call. */
    127                 PVDSCRIPTASTFN     pAstFn;
     138                PVDSCRIPTFN        pFn;
    128139            } FnCall;
     140            /** Compound statement. */
     141            struct
     142            {
     143                /** The compound statement node. */
     144                PVDSCRIPTASTSTMT   pStmtCompound;
     145                /** Current statement evaluated. */
     146                PVDSCRIPTASTSTMT   pStmtCurr;
     147            } Compound;
    129148        } Ctrl;
    130149    };
     
    144163static int vdScriptInterpreterError(PVDSCRIPTINTERPCTX pThis, int rc, RT_SRC_POS_DECL, const char *pszFmt, ...)
    145164{
     165    RTPrintf(pszFmt);
    146166    return rc;
    147167}
     
    168188DECLINLINE(int) vdScriptInterpreterPushValue(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTARG pVal)
    169189{
    170     PVDSCRIPTARG pValStack = (PVDSCRIPTARG)vdScriptStackGetUsed(&pThis->StackValues);
     190    PVDSCRIPTARG pValStack = (PVDSCRIPTARG)vdScriptStackGetUnused(&pThis->StackValues);
    171191    if (!pValStack)
    172192        return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory pushing a value on the value stack");
     
    202222
    203223/**
     224 * Pushes a compound statement control entry onto the stack.
     225 *
     226 * @returns VBox status code.
     227 * @param   pThis          The interpreter context.
     228 * @param   pStmtFirst     The first statement of the compound statement
     229 */
     230DECLINLINE(int) vdScriptInterpreterPushCompoundCtrlEntry(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTSTMT pStmt)
     231{
     232    PVDSCRIPTINTERPCTRL pCtrl = NULL;
     233
     234    pCtrl = (PVDSCRIPTINTERPCTRL)vdScriptStackGetUnused(&pThis->StackCtrl);
     235    if (pCtrl)
     236    {
     237        pCtrl->fEvalAst = false;
     238        pCtrl->Ctrl.enmCtrlType = VDSCRIPTINTERPCTRLTYPE_COMPOUND;
     239        pCtrl->Ctrl.Compound.pStmtCompound = pStmt;
     240        pCtrl->Ctrl.Compound.pStmtCurr = RTListGetFirst(&pStmt->Compound.ListStmts, VDSCRIPTASTSTMT, Core.ListNode);
     241        vdScriptStackPush(&pThis->StackCtrl);
     242        return VINF_SUCCESS;
     243    }
     244
     245    return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
     246}
     247
     248/**
    204249 * Pushes an AST node onto the control stack.
    205250 *
     
    227272
    228273/**
     274 * Destroy variable string space callback.
     275 */
     276static DECLCALLBACK(int) vdScriptInterpreterVarSpaceDestroy(PRTSTRSPACECORE pStr, void *pvUser)
     277{
     278    RTMemFree(pStr);
     279    return VINF_SUCCESS;
     280}
     281
     282/**
     283 * Setsup a new scope in the current function call.
     284 *
     285 * @returns VBox status code.
     286 * @param   pThis          The interpreter context.
     287 */
     288static int vdScriptInterpreterScopeCreate(PVDSCRIPTINTERPCTX pThis)
     289{
     290    int rc = VINF_SUCCESS;
     291    PVDSCRIPTINTERPSCOPE pScope = (PVDSCRIPTINTERPSCOPE)RTMemAllocZ(sizeof(VDSCRIPTINTERPSCOPE));
     292    if (pScope)
     293    {
     294        pScope->pParent = pThis->pFnCallCurr->pScopeCurr;
     295        pScope->hStrSpaceVar = NULL;
     296        pThis->pFnCallCurr->pScopeCurr = pScope;
     297    }
     298    else
     299        rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory allocating new scope");
     300
     301    return rc;
     302}
     303
     304/**
     305 * Destroys the current scope.
     306 *
     307 * @returns nothing.
     308 * @param   pThis          The interpreter context.
     309 */
     310static void vdScriptInterpreterScopeDestroyCurr(PVDSCRIPTINTERPCTX pThis)
     311{
     312    AssertMsgReturnVoid(pThis->pFnCallCurr->pScopeCurr != &pThis->pFnCallCurr->ScopeRoot,
     313                        ("Current scope is root scope of function call\n"));
     314
     315    PVDSCRIPTINTERPSCOPE pScope = pThis->pFnCallCurr->pScopeCurr;
     316    pThis->pFnCallCurr->pScopeCurr = pScope->pParent;
     317    RTStrSpaceDestroy(&pScope->hStrSpaceVar, vdScriptInterpreterVarSpaceDestroy, NULL);
     318    RTMemFree(pScope);
     319}
     320
     321/**
     322 * Get the content of the given variable identifier from the current or parent scope.
     323 */
     324static PVDSCRIPTINTERPVAR vdScriptInterpreterGetVar(PVDSCRIPTINTERPCTX pThis, const char *pszVar)
     325{
     326    PVDSCRIPTINTERPSCOPE pScopeCurr = pThis->pFnCallCurr->pScopeCurr;
     327    PVDSCRIPTINTERPVAR pVar = NULL;
     328
     329    while (   !pVar
     330           && pScopeCurr)
     331    {
     332        pVar = (PVDSCRIPTINTERPVAR)RTStrSpaceGet(&pScopeCurr->hStrSpaceVar, pszVar);
     333        if (pVar)
     334            break;
     335        pScopeCurr = pScopeCurr->pParent;
     336    }
     337
     338
     339    return pVar;
     340}
     341
     342/**
     343 * Evaluate an expression.
     344 *
     345 * @returns VBox status code.
     346 * @param   pThis      The interpreter context.
     347 * @param   pExpr      The expression to evaluate.
     348 */
     349static int vdScriptInterpreterEvaluateExpression(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTEXPR pExpr)
     350{
     351    int rc = VINF_SUCCESS;
     352
     353    switch (pExpr->enmType)
     354    {
     355        case VDSCRIPTEXPRTYPE_PRIMARY_NUMCONST:
     356        {
     357            /* Push the numerical constant on the value stack. */
     358            VDSCRIPTARG NumConst;
     359            NumConst.enmType = VDSCRIPTTYPE_UINT64;
     360            NumConst.u64     = pExpr->u64;
     361            rc = vdScriptInterpreterPushValue(pThis, &NumConst);
     362            break;
     363        }
     364        case VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST:
     365        {
     366            /* Push the string literal on the value stack. */
     367            VDSCRIPTARG StringConst;
     368            StringConst.enmType = VDSCRIPTTYPE_STRING;
     369            StringConst.psz     = pExpr->pszStr;
     370            rc = vdScriptInterpreterPushValue(pThis, &StringConst);
     371            break;
     372        }
     373        case VDSCRIPTEXPRTYPE_PRIMARY_BOOLEAN:
     374        {
     375            VDSCRIPTARG BoolConst;
     376            BoolConst.enmType = VDSCRIPTTYPE_BOOL;
     377            BoolConst.f       = pExpr->f;
     378            rc = vdScriptInterpreterPushValue(pThis, &BoolConst);
     379            break;
     380        }
     381        case VDSCRIPTEXPRTYPE_PRIMARY_IDENTIFIER:
     382        {
     383            /* Look it up and push the value onto the value stack. */
     384            PVDSCRIPTINTERPVAR pVar = vdScriptInterpreterGetVar(pThis, pExpr->pIde->aszIde);
     385
     386            AssertPtrReturn(pVar, VERR_IPE_UNINITIALIZED_STATUS);
     387            rc = vdScriptInterpreterPushValue(pThis, &pVar->Value);
     388            break;
     389        }
     390        case VDSCRIPTEXPRTYPE_POSTFIX_INCREMENT:
     391        case VDSCRIPTEXPRTYPE_POSTFIX_DECREMENT:
     392            AssertMsgFailed(("TODO\n"));
     393        case VDSCRIPTEXPRTYPE_POSTFIX_FNCALL:
     394        {
     395            PVDSCRIPTFN pFn = (PVDSCRIPTFN)RTStrSpaceGet(&pThis->pScriptCtx->hStrSpaceFn, pExpr->FnCall.pFnIde->pIde->aszIde);
     396            if (pFn)
     397            {
     398                /* Push a function call control entry on the stack. */
     399                PVDSCRIPTINTERPCTRL pCtrlFn = (PVDSCRIPTINTERPCTRL)vdScriptStackGetUnused(&pThis->StackCtrl);
     400                if (pCtrlFn)
     401                {
     402                    pCtrlFn->fEvalAst = false;
     403                    pCtrlFn->Ctrl.enmCtrlType = VDSCRIPTINTERPCTRLTYPE_FN_CALL;
     404                    pCtrlFn->Ctrl.FnCall.pFn = pFn;
     405                    vdScriptStackPush(&pThis->StackCtrl);
     406
     407                    /* Push parameter expressions on the stack. */
     408                    PVDSCRIPTASTEXPR pArg = RTListGetFirst(&pExpr->FnCall.ListArgs, VDSCRIPTASTEXPR, Core.ListNode);
     409                    while (pArg)
     410                    {
     411                        rc = vdScriptInterpreterPushAstEntry(pThis, &pArg->Core);
     412                        if (RT_FAILURE(rc))
     413                            break;
     414                        pArg = RTListGetNext(&pExpr->FnCall.ListArgs, pArg, VDSCRIPTASTEXPR, Core.ListNode);
     415                    }
     416                }
     417            }
     418            else
     419                AssertMsgFailed(("Invalid program given, unknown function: %s\n", pExpr->FnCall.pFnIde->pIde->aszIde));
     420            break;
     421        }
     422        case VDSCRIPTEXPRTYPE_UNARY_INCREMENT:
     423        case VDSCRIPTEXPRTYPE_UNARY_DECREMENT:
     424        case VDSCRIPTEXPRTYPE_UNARY_POSSIGN:
     425        case VDSCRIPTEXPRTYPE_UNARY_NEGSIGN:
     426        case VDSCRIPTEXPRTYPE_UNARY_INVERT:
     427        case VDSCRIPTEXPRTYPE_UNARY_NEGATE:
     428        case VDSCRIPTEXPRTYPE_MULTIPLICATION:
     429        case VDSCRIPTEXPRTYPE_DIVISION:
     430        case VDSCRIPTEXPRTYPE_MODULUS:
     431        case VDSCRIPTEXPRTYPE_ADDITION:
     432        case VDSCRIPTEXPRTYPE_SUBTRACTION:
     433        case VDSCRIPTEXPRTYPE_LSR:
     434        case VDSCRIPTEXPRTYPE_LSL:
     435        case VDSCRIPTEXPRTYPE_LOWER:
     436        case VDSCRIPTEXPRTYPE_HIGHER:
     437        case VDSCRIPTEXPRTYPE_LOWEREQUAL:
     438        case VDSCRIPTEXPRTYPE_HIGHEREQUAL:
     439        case VDSCRIPTEXPRTYPE_EQUAL:
     440        case VDSCRIPTEXPRTYPE_NOTEQUAL:
     441        case VDSCRIPTEXPRTYPE_BITWISE_AND:
     442        case VDSCRIPTEXPRTYPE_BITWISE_XOR:
     443        case VDSCRIPTEXPRTYPE_BITWISE_OR:
     444        case VDSCRIPTEXPRTYPE_LOGICAL_AND:
     445        case VDSCRIPTEXPRTYPE_LOGICAL_OR:
     446        case VDSCRIPTEXPRTYPE_ASSIGN:
     447        case VDSCRIPTEXPRTYPE_ASSIGN_MULT:
     448        case VDSCRIPTEXPRTYPE_ASSIGN_DIV:
     449        case VDSCRIPTEXPRTYPE_ASSIGN_MOD:
     450        case VDSCRIPTEXPRTYPE_ASSIGN_ADD:
     451        case VDSCRIPTEXPRTYPE_ASSIGN_SUB:
     452        case VDSCRIPTEXPRTYPE_ASSIGN_LSL:
     453        case VDSCRIPTEXPRTYPE_ASSIGN_LSR:
     454        case VDSCRIPTEXPRTYPE_ASSIGN_AND:
     455        case VDSCRIPTEXPRTYPE_ASSIGN_XOR:
     456        case VDSCRIPTEXPRTYPE_ASSIGN_OR:
     457        case VDSCRIPTEXPRTYPE_ASSIGNMENT_LIST:
     458            AssertMsgFailed(("TODO\n"));
     459        default:
     460            AssertMsgFailed(("Invalid expression type: %d\n", pExpr->enmType));
     461    }
     462    return rc;
     463}
     464
     465/**
    229466 * Evaluate a statement.
    230467 *
     
    235472static int vdScriptInterpreterEvaluateStatement(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTSTMT pStmt)
    236473{
    237     int rc = VERR_NOT_IMPLEMENTED;
    238     return rc;
    239 }
    240 
    241 /**
    242  * Evaluate an expression.
    243  *
    244  * @returns VBox status code.
    245  * @param   pThis      The interpreter context.
    246  * @param   pExpr      The expression to evaluate.
    247  */
    248 static int vdScriptInterpreterEvaluateExpression(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTEXPR pExpr)
    249 {
    250     int rc = VERR_NOT_IMPLEMENTED;
     474    int rc = VINF_SUCCESS;
     475
     476    switch (pStmt->enmStmtType)
     477    {
     478        case VDSCRIPTSTMTTYPE_COMPOUND:
     479        {
     480            /* Setup new scope. */
     481            rc = vdScriptInterpreterScopeCreate(pThis);
     482            if (RT_SUCCESS(rc))
     483            {
     484                /** @todo: Declarations */
     485                rc = vdScriptInterpreterPushCompoundCtrlEntry(pThis, pStmt);
     486            }
     487            break;
     488        }
     489        case VDSCRIPTSTMTTYPE_EXPRESSION:
     490        {
     491            rc = vdScriptInterpreterPushAstEntry(pThis, &pStmt->pExpr->Core);
     492            break;
     493        }
     494        case VDSCRIPTSTMTTYPE_IF:
     495        case VDSCRIPTSTMTTYPE_SWITCH:
     496        case VDSCRIPTSTMTTYPE_WHILE:
     497        case VDSCRIPTSTMTTYPE_FOR:
     498        case VDSCRIPTSTMTTYPE_CONTINUE:
     499        case VDSCRIPTSTMTTYPE_BREAK:
     500        case VDSCRIPTSTMTTYPE_RETURN:
     501        case VDSCRIPTSTMTTYPE_CASE:
     502        case VDSCRIPTSTMTTYPE_DEFAULT:
     503        default:
     504            AssertMsgFailed(("Invalid statement type: %d\n", pStmt->enmStmtType));
     505    }
     506
    251507    return rc;
    252508}
     
    267523        case VDSCRIPTASTCLASS_DECLARATION:
    268524        {
    269             break;
    270         }
     525            AssertMsgFailed(("TODO\n"));
     526            break;
     527        }
     528        case VDSCRIPTASTCLASS_STATEMENT:
     529        {
     530            rc = vdScriptInterpreterEvaluateStatement(pThis, (PVDSCRIPTASTSTMT)pAstNode);
     531            break;
     532        }
     533        case VDSCRIPTASTCLASS_EXPRESSION:
     534        {
     535            rc = vdScriptInterpreterEvaluateExpression(pThis, (PVDSCRIPTASTEXPR)pAstNode);
     536            break;
     537        }
     538        /* These should never ever appear here. */
    271539        case VDSCRIPTASTCLASS_IDENTIFIER:
    272         {
    273             /*
    274              * Identifiers are pushed only to the stack as an identifier for a variable.
    275              * Look it up and push the value onto the value stack.
    276              */
    277             PVDSCRIPTASTIDE pIde = (PVDSCRIPTASTIDE)pAstNode;
    278             PVDSCRIPTINTERPVAR pVar = (PVDSCRIPTINTERPVAR)RTStrSpaceGet(&pThis->pFnCallCurr->pScopeCurr->hStrSpaceVar, pIde->aszIde);
    279 
    280             AssertPtrReturn(pVar, VERR_IPE_UNINITIALIZED_STATUS);
    281             rc = vdScriptInterpreterPushValue(pThis, &pVar->Value);
    282             break;
    283         }
    284         case VDSCRIPTASTCLASS_STATEMENT:
    285         {
    286             rc = vdScriptInterpreterEvaluateStatement(pThis, (PVDSCRIPTASTSTMT)pAstNode);
    287             break;
    288         }
    289         case VDSCRIPTASTCLASS_EXPRESSION:
    290         {
    291             rc = vdScriptInterpreterEvaluateExpression(pThis, (PVDSCRIPTASTEXPR)pAstNode);
    292             break;
    293         }
    294         /* These should never ever appear here. */
    295540        case VDSCRIPTASTCLASS_FUNCTION:
    296541        case VDSCRIPTASTCLASS_FUNCTIONARG:
     
    304549
    305550/**
    306  * Destroy variable string space callback.
    307  */
    308 static DECLCALLBACK(int) vdScriptInterpreterVarSpaceDestroy(PRTSTRSPACECORE pStr, void *pvUser)
    309 {
    310     RTMemFree(pStr);
    311     return VINF_SUCCESS;
    312 }
    313 
    314 /**
    315551 * Evaluate a function call.
    316552 *
    317553 * @returns VBox status code.
    318554 * @param   pThis      The interpreter context.
    319  * @param
    320  */
    321 static int vdScriptInterpreterFnCall(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTFN pAstFn)
     555 * @param   pFn        The function execute.
     556 */
     557static int vdScriptInterpreterFnCall(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTFN pFn)
    322558{
    323559    int rc = VINF_SUCCESS;
    324560
    325     /* Add function call cleanup marker on the stack first. */
    326     rc = vdScriptInterpreterPushNonDataCtrlEntry(pThis, VDSCRIPTINTERPCTRLTYPE_FN_CALL_CLEANUP);
    327     if (RT_SUCCESS(rc))
    328     {
    329         /* Create function call frame and set it up. */
    330         PVDSCRIPTINTERPFNCALL pFnCall = (PVDSCRIPTINTERPFNCALL)RTMemAllocZ(sizeof(VDSCRIPTINTERPFNCALL));
    331         if (pFnCall)
    332         {
    333             pFnCall->pCaller = pThis->pFnCallCurr;
    334             pFnCall->ScopeRoot.pParent = NULL;
    335             pFnCall->ScopeRoot.hStrSpaceVar = NULL;
    336 
    337             /* Add the variables, remember order. The first variable in the argument has the value at the top of the value stack. */
    338             PVDSCRIPTASTFNARG pArg = RTListGetFirst(&pAstFn->ListArgs, VDSCRIPTASTFNARG, Core.ListNode);
    339             for (unsigned i = 0; i < pAstFn->cArgs; i++)
    340             {
    341                 PVDSCRIPTINTERPVAR pVar = (PVDSCRIPTINTERPVAR)RTMemAllocZ(sizeof(VDSCRIPTINTERPVAR));
    342                 if (pVar)
     561    if (!pFn->fExternal)
     562    {
     563        PVDSCRIPTASTFN pAstFn = pFn->Type.Internal.pAstFn;
     564
     565        /* Add function call cleanup marker on the stack first. */
     566        rc = vdScriptInterpreterPushNonDataCtrlEntry(pThis, VDSCRIPTINTERPCTRLTYPE_FN_CALL_CLEANUP);
     567        if (RT_SUCCESS(rc))
     568        {
     569            /* Create function call frame and set it up. */
     570            PVDSCRIPTINTERPFNCALL pFnCall = (PVDSCRIPTINTERPFNCALL)RTMemAllocZ(sizeof(VDSCRIPTINTERPFNCALL));
     571            if (pFnCall)
     572            {
     573                pFnCall->pCaller = pThis->pFnCallCurr;
     574                pFnCall->ScopeRoot.pParent = NULL;
     575                pFnCall->ScopeRoot.hStrSpaceVar = NULL;
     576                pFnCall->pScopeCurr = &pFnCall->ScopeRoot;
     577
     578                /* Add the variables, remember order. The first variable in the argument has the value at the top of the value stack. */
     579                PVDSCRIPTASTFNARG pArg = RTListGetFirst(&pAstFn->ListArgs, VDSCRIPTASTFNARG, Core.ListNode);
     580                for (unsigned i = 0; i < pAstFn->cArgs; i++)
    343581                {
    344                     pVar->Core.pszString = pArg->pArgIde->aszIde;
    345                     pVar->Core.cchString = pArg->pArgIde->cchIde;
    346                     vdScriptInterpreterPopValue(pThis, &pVar->Value);
    347                     bool fInserted = RTStrSpaceInsert(&pFnCall->ScopeRoot.hStrSpaceVar, &pVar->Core);
    348                     Assert(fInserted);
     582                    PVDSCRIPTINTERPVAR pVar = (PVDSCRIPTINTERPVAR)RTMemAllocZ(sizeof(VDSCRIPTINTERPVAR));
     583                    if (pVar)
     584                    {
     585                        pVar->Core.pszString = pArg->pArgIde->aszIde;
     586                        pVar->Core.cchString = pArg->pArgIde->cchIde;
     587                        vdScriptInterpreterPopValue(pThis, &pVar->Value);
     588                        bool fInserted = RTStrSpaceInsert(&pFnCall->ScopeRoot.hStrSpaceVar, &pVar->Core);
     589                        Assert(fInserted);
     590                    }
     591                    else
     592                    {
     593                        rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a variable");
     594                        break;
     595                    }
     596                    pArg = RTListGetNext(&pAstFn->ListArgs, pArg, VDSCRIPTASTFNARG, Core.ListNode);
    349597                }
    350                 else
     598
     599                if (RT_SUCCESS(rc))
    351600                {
    352                     rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a variable");
    353                     break;
     601                    /*
     602                     * Push compount statement on the control stack and make the newly created
     603                     * call frame the current one.
     604                     */
     605                    rc = vdScriptInterpreterPushAstEntry(pThis, &pAstFn->pCompoundStmts->Core);
     606                    if (RT_SUCCESS(rc))
     607                        pThis->pFnCallCurr = pFnCall;
    354608                }
    355                 pArg = RTListGetNext(&pAstFn->ListArgs, pArg, VDSCRIPTASTFNARG, Core.ListNode);
     609
     610                if (RT_FAILURE(rc))
     611                {
     612                    RTStrSpaceDestroy(&pFnCall->ScopeRoot.hStrSpaceVar, vdScriptInterpreterVarSpaceDestroy, NULL);
     613                    RTMemFree(pFnCall);
     614                }
    356615            }
    357 
    358             if (RT_SUCCESS(rc))
    359             {
    360                 /*
    361                  * Push compount statement on the control stack and make the newly created
    362                  * call frame the current one.
    363                  */
    364                 rc = vdScriptInterpreterPushAstEntry(pThis, &pAstFn->pCompoundStmts->Core);
     616            else
     617                rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a call frame");
     618        }
     619    }
     620    else
     621    {
     622        /* External function call, build the argument list. */
     623        if (pFn->cArgs)
     624        {
     625            PVDSCRIPTARG paArgs = (PVDSCRIPTARG)RTMemAllocZ(pFn->cArgs * sizeof(VDSCRIPTARG));
     626            if (paArgs)
     627            {
     628                for (unsigned i = 0; i < pFn->cArgs; i++)
     629                    vdScriptInterpreterPopValue(pThis, &paArgs[i]);
     630
     631                rc = pFn->Type.External.pfnCallback(paArgs, pFn->Type.External.pvUser);
     632                RTMemFree(paArgs);
     633            }
     634            else
     635                rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS,
     636                                              "Out of memory creating argument array for external function call");
     637        }
     638        else
     639            rc = pFn->Type.External.pfnCallback(NULL, pFn->Type.External.pvUser);
     640    }
     641
     642    return rc;
     643}
     644
     645/**
     646 * Evaluate interpreter control statement.
     647 *
     648 * @returns VBox status code.
     649 * @param   pThis      The interpreter context.
     650 * @param   pCtrl      The control entry to evaluate.
     651 */
     652static int vdScriptInterpreterEvaluateCtrlEntry(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTINTERPCTRL pCtrl)
     653{
     654    int rc = VINF_SUCCESS;
     655
     656    Assert(!pCtrl->fEvalAst);
     657    switch (pCtrl->Ctrl.enmCtrlType)
     658    {
     659        case VDSCRIPTINTERPCTRLTYPE_FN_CALL:
     660        {
     661            PVDSCRIPTFN pFn = pCtrl->Ctrl.FnCall.pFn;
     662
     663            vdScriptStackPop(&pThis->StackCtrl);
     664            rc = vdScriptInterpreterFnCall(pThis, pFn);
     665            break;
     666        }
     667        case VDSCRIPTINTERPCTRLTYPE_FN_CALL_CLEANUP:
     668        {
     669            vdScriptStackPop(&pThis->StackCtrl);
     670
     671            /* Delete function call entry. */
     672            AssertPtr(pThis->pFnCallCurr);
     673            PVDSCRIPTINTERPFNCALL pFnCallFree = pThis->pFnCallCurr;
     674
     675            pThis->pFnCallCurr = pFnCallFree->pCaller;
     676            Assert(pFnCallFree->pScopeCurr == &pFnCallFree->ScopeRoot);
     677            RTStrSpaceDestroy(&pFnCallFree->ScopeRoot.hStrSpaceVar, vdScriptInterpreterVarSpaceDestroy, NULL);
     678            RTMemFree(pFnCallFree);
     679            break;
     680        }
     681        case VDSCRIPTINTERPCTRLTYPE_COMPOUND:
     682        {
     683            if (!pCtrl->Ctrl.Compound.pStmtCurr)
     684            {
     685                /* Evaluated last statement, cleanup and remove the control statement from the stack. */
     686                vdScriptInterpreterScopeDestroyCurr(pThis);
     687                vdScriptStackPop(&pThis->StackCtrl);
     688            }
     689            else
     690            {
     691                /* Push the current statement onto the control stack and move on. */
     692                rc = vdScriptInterpreterPushAstEntry(pThis, &pCtrl->Ctrl.Compound.pStmtCurr->Core);
    365693                if (RT_SUCCESS(rc))
    366                     pThis->pFnCallCurr = pFnCall;
     694                {
     695                    pCtrl->Ctrl.Compound.pStmtCurr = RTListGetNext(&pCtrl->Ctrl.Compound.pStmtCompound->Compound.ListStmts,
     696                                                                   pCtrl->Ctrl.Compound.pStmtCurr, VDSCRIPTASTSTMT, Core.ListNode);
     697                }
    367698            }
    368 
    369             if (RT_FAILURE(rc))
    370             {
    371                 RTStrSpaceDestroy(&pFnCall->ScopeRoot.hStrSpaceVar, vdScriptInterpreterVarSpaceDestroy, NULL);
    372                 RTMemFree(pFnCall);
    373             }
    374         }
    375         else
    376             rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a call frame");
     699            break;
     700        }
     701        default:
     702            AssertMsgFailed(("Invalid evaluation control type on the stack: %d\n",
     703                             pCtrl->Ctrl.enmCtrlType));
    377704    }
    378705
     
    402729        }
    403730        else
    404         {
    405             switch (pCtrl->Ctrl.enmCtrlType)
    406             {
    407                 case VDSCRIPTINTERPCTRLTYPE_FN_CALL:
    408                 {
    409                     PVDSCRIPTASTFN pAstFn = pCtrl->Ctrl.FnCall.pAstFn;
    410 
    411                     vdScriptStackPop(&pThis->StackCtrl);
    412                     rc = vdScriptInterpreterFnCall(pThis, pAstFn);
    413                     break;
    414                 }
    415                 case VDSCRIPTINTERPCTRLTYPE_FN_CALL_CLEANUP:
    416                 {
    417                     vdScriptStackPop(&pThis->StackCtrl);
    418 
    419                     /* Delete function call entry. */
    420                     AssertPtr(pThis->pFnCallCurr);
    421                     PVDSCRIPTINTERPFNCALL pFnCallFree = pThis->pFnCallCurr;
    422 
    423                     pThis->pFnCallCurr = pFnCallFree->pCaller;
    424                     Assert(pFnCallFree->pScopeCurr == &pFnCallFree->ScopeRoot);
    425                     RTStrSpaceDestroy(&pFnCallFree->ScopeRoot.hStrSpaceVar, vdScriptInterpreterVarSpaceDestroy, NULL);
    426                     RTMemFree(pFnCallFree);
    427                     break;
    428                 }
    429                 default:
    430                     AssertMsgFailed(("Invalid evaluation control type on the stack: %d\n",
    431                                      pCtrl->Ctrl.enmCtrlType));
    432             }
    433         }
     731            rc = vdScriptInterpreterEvaluateCtrlEntry(pThis, pCtrl);
     732
    434733        pCtrl = (PVDSCRIPTINTERPCTRL)vdScriptStackGetUsed(&pThis->StackCtrl);
    435734    }
     
    472771            if (RT_SUCCESS(rc))
    473772            {
    474                 /* Push the AST onto the stack. */
    475                 PVDSCRIPTINTERPCTRL pCtrlFn = (PVDSCRIPTINTERPCTRL)vdScriptStackGetUnused(&InterpCtx.StackCtrl);
    476                 pCtrlFn->fEvalAst = false;
    477                 pCtrlFn->Ctrl.enmCtrlType = VDSCRIPTINTERPCTRLTYPE_FN_CALL;
    478                 pCtrlFn->Ctrl.FnCall.pAstFn = pFn->Type.Internal.pAstFn;
    479                 vdScriptStackPush(&InterpCtx.StackCtrl);
    480 
    481                 /* Run the interpreter. */
    482                 rc = vdScriptInterpreterEvaluate(&InterpCtx);
     773                /* Setup function call frame and parameters. */
     774                rc = vdScriptInterpreterFnCall(&InterpCtx, pFn);
     775                if (RT_SUCCESS(rc))
     776                {
     777                    /* Run the interpreter. */
     778                    rc = vdScriptInterpreterEvaluate(&InterpCtx);
     779                    vdScriptStackDestroy(&InterpCtx.StackValues);
     780                    vdScriptStackDestroy(&InterpCtx.StackCtrl);
     781                }
    483782            }
    484783        }
  • trunk/src/VBox/Storage/testcase/VDScriptStack.h

    r44901 r44941  
    5656
    5757/**
     58 * Destroys the given stack freeing all memory.
     59 *
     60 * @returns nothing.
     61 * @param   pStack         The stack to destroy.
     62 */
     63DECLINLINE(void) vdScriptStackDestroy(PVDSCRIPTSTACK pStack)
     64{
     65    if (pStack->pvStack)
     66        RTMemFree(pStack->pvStack);
     67    pStack->cbStackEntry = 0;
     68    pStack->pvStack      = NULL;
     69    pStack->cOnStack     = 0;
     70    pStack->cOnStackMax  = 0;
     71}
     72
     73/**
    5874 * Gets the topmost unused stack entry.
    5975 *
     
    8197    }
    8298
    83     if (pStack->cOnStack >= pStack->cOnStackMax)
     99    if (pStack->cOnStack < pStack->cOnStackMax)
    84100        pvElem = (char *)pStack->pvStack + pStack->cOnStack * pStack->cbStackEntry;
    85101
Note: See TracChangeset for help on using the changeset viewer.

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