/**
 * @callback_method_impl{FNRTSTRSPACECALLBACK, Destroys RTMANIFESTENTRY.}
 */
static DECLCALLBACK(int) rtManifestDestroyEntry(PRTSTRSPACECORE pStr, void *pvUser)
{
    PRTMANIFESTENTRY pEntry = RT_FROM_MEMBER(pStr, RTMANIFESTENTRY, StrCore);
    RTStrSpaceDestroy(&pEntry->Attributes, rtManifestDestroyAttribute, pvUser);
    RTMemFree(pEntry);
    return 0;
}
示例#2
0
/**
 * Destroys the current scope.
 *
 * @returns nothing.
 * @param   pThis          The interpreter context.
 */
static void vdScriptInterpreterScopeDestroyCurr(PVDSCRIPTINTERPCTX pThis)
{
    AssertMsgReturnVoid(pThis->pFnCallCurr->pScopeCurr != &pThis->pFnCallCurr->ScopeRoot,
                        ("Current scope is root scope of function call\n"));

    PVDSCRIPTINTERPSCOPE pScope = pThis->pFnCallCurr->pScopeCurr;
    pThis->pFnCallCurr->pScopeCurr = pScope->pParent;
    RTStrSpaceDestroy(&pScope->hStrSpaceVar, vdScriptInterpreterVarSpaceDestroy, NULL);
    RTMemFree(pScope);
}
/**
 * Releases a reference to the manifest handle.
 *
 * @returns The new reference count, 0 if free. UINT32_MAX is returned if the
 *          handle is invalid.
 * @param   hManifest           The handle to release.
 *                              NIL is quietly ignored (returns 0).
 */
RTDECL(uint32_t) RTManifestRelease(RTMANIFEST hManifest)
{
    RTMANIFESTINT *pThis = hManifest;
    if (pThis == NIL_RTMANIFEST)
        return 0;
    AssertPtrReturn(pThis, UINT32_MAX);
    AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, UINT32_MAX);

    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
    Assert(cRefs < _1M);
    if (!cRefs)
    {
        ASMAtomicWriteU32(&pThis->u32Magic, ~RTMANIFEST_MAGIC);
        RTStrSpaceDestroy(&pThis->Entries, rtManifestDestroyEntry,pThis);
        RTStrSpaceDestroy(&pThis->SelfEntry.Attributes, rtManifestDestroyAttribute, pThis);
        RTMemFree(pThis);
    }

    return cRefs;
}
示例#4
0
/**
 * Evaluate interpreter control statement.
 *
 * @returns VBox status code.
 * @param   pThis      The interpreter context.
 * @param   pCtrl      The control entry to evaluate.
 */
static int vdScriptInterpreterEvaluateCtrlEntry(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTINTERPCTRL pCtrl)
{
    int rc = VINF_SUCCESS;

    Assert(!pCtrl->fEvalAst);
    switch (pCtrl->Ctrl.enmCtrlType)
    {
        case VDSCRIPTINTERPCTRLTYPE_FN_CALL:
        {
            PVDSCRIPTFN pFn = pCtrl->Ctrl.FnCall.pFn;

            vdScriptStackPop(&pThis->StackCtrl);
            rc = vdScriptInterpreterFnCall(pThis, pFn);
            break;
        }
        case VDSCRIPTINTERPCTRLTYPE_FN_CALL_CLEANUP:
        {
            vdScriptStackPop(&pThis->StackCtrl);

            /* Delete function call entry. */
            AssertPtr(pThis->pFnCallCurr);
            PVDSCRIPTINTERPFNCALL pFnCallFree = pThis->pFnCallCurr;

            pThis->pFnCallCurr = pFnCallFree->pCaller;
            Assert(pFnCallFree->pScopeCurr == &pFnCallFree->ScopeRoot);
            RTStrSpaceDestroy(&pFnCallFree->ScopeRoot.hStrSpaceVar, vdScriptInterpreterVarSpaceDestroy, NULL);
            RTMemFree(pFnCallFree);
            break;
        }
        case VDSCRIPTINTERPCTRLTYPE_COMPOUND:
        {
            if (!pCtrl->Ctrl.Compound.pStmtCurr)
            {
                /* Evaluated last statement, cleanup and remove the control statement from the stack. */
                vdScriptInterpreterScopeDestroyCurr(pThis);
                vdScriptStackPop(&pThis->StackCtrl);
            }
            else
            {
                /* Push the current statement onto the control stack and move on. */
                rc = vdScriptInterpreterPushAstEntry(pThis, &pCtrl->Ctrl.Compound.pStmtCurr->Core);
                if (RT_SUCCESS(rc))
                {
                    pCtrl->Ctrl.Compound.pStmtCurr = RTListGetNext(&pCtrl->Ctrl.Compound.pStmtCompound->Compound.ListStmts,
                                                                   pCtrl->Ctrl.Compound.pStmtCurr, VDSCRIPTASTSTMT, Core.ListNode);
                }
            }
            break;
        }
        case VDSCRIPTINTERPCTRLTYPE_LOOP:
        {
            PVDSCRIPTASTSTMT pLoopStmt = (PVDSCRIPTASTSTMT)pCtrl->Ctrl.pAstNode;

            /* Check whether the condition passed. */
            VDSCRIPTARG Cond;
            vdScriptInterpreterPopValue(pThis, &Cond);
            AssertMsg(Cond.enmType == VDSCRIPTTYPE_BOOL,
                      ("Value on stack is not of boolean type\n"));

            if (Cond.f)
            {
                /* Execute the loop another round. */
                if (pLoopStmt->enmStmtType == VDSCRIPTSTMTTYPE_WHILE)
                {
                    rc = vdScriptInterpreterPushAstEntry(pThis, &pLoopStmt->While.pCond->Core);
                    if (RT_SUCCESS(rc))
                    {
                        rc = vdScriptInterpreterPushAstEntry(pThis, &pLoopStmt->While.pStmt->Core);
                        if (RT_FAILURE(rc))
                            vdScriptStackPop(&pThis->StackCtrl);
                    }
                }
                else
                {
                    AssertMsg(pLoopStmt->enmStmtType == VDSCRIPTSTMTTYPE_FOR,
                              ("Not a for statement\n"));

                    rc = vdScriptInterpreterPushAstEntry(pThis, &pLoopStmt->For.pExprCond->Core);
                    if (RT_SUCCESS(rc))
                    {
                        rc = vdScriptInterpreterPushAstEntry(pThis, &pLoopStmt->For.pExpr3->Core);
                        if (RT_SUCCESS(rc))
                        {
                            rc = vdScriptInterpreterPushAstEntry(pThis, &pLoopStmt->For.pStmt->Core);
                            if (RT_FAILURE(rc))
                                vdScriptStackPop(&pThis->StackCtrl);
                        }

                        if (RT_FAILURE(rc))
                            vdScriptStackPop(&pThis->StackCtrl);
                    }
                }
            }
            else
                vdScriptStackPop(&pThis->StackCtrl); /* Remove loop control statement. */
            break;
        }
        case VDSCRIPTINTERPCTRLTYPE_IF:
        {
            PVDSCRIPTASTSTMT pIfStmt = (PVDSCRIPTASTSTMT)pCtrl->Ctrl.pAstNode;

            vdScriptStackPop(&pThis->StackCtrl); /* Remove if control statement. */

            /* Check whether the condition passed. */
            VDSCRIPTARG Cond;
            vdScriptInterpreterPopValue(pThis, &Cond);
            AssertMsg(Cond.enmType == VDSCRIPTTYPE_BOOL,
                      ("Value on stack is not of boolean type\n"));

            if (Cond.f)
            {
                /* Execute the true branch. */
                rc = vdScriptInterpreterPushAstEntry(pThis, &pIfStmt->If.pTrueStmt->Core);
            }
            else if (pIfStmt->If.pElseStmt)
                rc = vdScriptInterpreterPushAstEntry(pThis, &pIfStmt->If.pElseStmt->Core);

            break;
        }
        default:
            AssertMsgFailed(("Invalid evaluation control type on the stack: %d\n",
                             pCtrl->Ctrl.enmCtrlType));
    }

    return rc;
}
示例#5
0
/**
 * Evaluate a function call.
 *
 * @returns VBox status code.
 * @param   pThis      The interpreter context.
 * @param   pFn        The function execute.
 */
static int vdScriptInterpreterFnCall(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTFN pFn)
{
    int rc = VINF_SUCCESS;

    if (!pFn->fExternal)
    {
        PVDSCRIPTASTFN pAstFn = pFn->Type.Internal.pAstFn;

        /* Add function call cleanup marker on the stack first. */
        rc = vdScriptInterpreterPushNonDataCtrlEntry(pThis, VDSCRIPTINTERPCTRLTYPE_FN_CALL_CLEANUP);
        if (RT_SUCCESS(rc))
        {
            /* Create function call frame and set it up. */
            PVDSCRIPTINTERPFNCALL pFnCall = (PVDSCRIPTINTERPFNCALL)RTMemAllocZ(sizeof(VDSCRIPTINTERPFNCALL));
            if (pFnCall)
            {
                pFnCall->pCaller = pThis->pFnCallCurr;
                pFnCall->ScopeRoot.pParent = NULL;
                pFnCall->ScopeRoot.hStrSpaceVar = NULL;
                pFnCall->pScopeCurr = &pFnCall->ScopeRoot;

                /* Add the variables, remember order. The first variable in the argument has the value at the top of the value stack. */
                PVDSCRIPTASTFNARG pArg = RTListGetFirst(&pAstFn->ListArgs, VDSCRIPTASTFNARG, Core.ListNode);
                for (unsigned i = 0; i < pAstFn->cArgs; i++)
                {
                    PVDSCRIPTINTERPVAR pVar = (PVDSCRIPTINTERPVAR)RTMemAllocZ(sizeof(VDSCRIPTINTERPVAR));
                    if (pVar)
                    {
                        pVar->Core.pszString = pArg->pArgIde->aszIde;
                        pVar->Core.cchString = pArg->pArgIde->cchIde;
                        vdScriptInterpreterPopValue(pThis, &pVar->Value);
                        bool fInserted = RTStrSpaceInsert(&pFnCall->ScopeRoot.hStrSpaceVar, &pVar->Core);
                        Assert(fInserted);
                    }
                    else
                    {
                        rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a variable");
                        break;
                    }
                    pArg = RTListGetNext(&pAstFn->ListArgs, pArg, VDSCRIPTASTFNARG, Core.ListNode);
                }

                if (RT_SUCCESS(rc))
                {
                    /*
                     * Push compount statement on the control stack and make the newly created
                     * call frame the current one.
                     */
                    rc = vdScriptInterpreterPushAstEntry(pThis, &pAstFn->pCompoundStmts->Core);
                    if (RT_SUCCESS(rc))
                        pThis->pFnCallCurr = pFnCall;
                }

                if (RT_FAILURE(rc))
                {
                    RTStrSpaceDestroy(&pFnCall->ScopeRoot.hStrSpaceVar, vdScriptInterpreterVarSpaceDestroy, NULL);
                    RTMemFree(pFnCall);
                }
            }
            else
                rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a call frame");
        }
    }
    else
    {
        /* External function call, build the argument list. */
        if (pFn->cArgs)
        {
            PVDSCRIPTARG paArgs = (PVDSCRIPTARG)RTMemAllocZ(pFn->cArgs * sizeof(VDSCRIPTARG));
            if (paArgs)
            {
                for (unsigned i = 0; i < pFn->cArgs; i++)
                    vdScriptInterpreterPopValue(pThis, &paArgs[i]);

                rc = pFn->Type.External.pfnCallback(paArgs, pFn->Type.External.pvUser);
                RTMemFree(paArgs);
            }
            else
                rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS,
                                              "Out of memory creating argument array for external function call");
        }
        else
            rc = pFn->Type.External.pfnCallback(NULL, pFn->Type.External.pvUser);
    }

    return rc;
}