Check-in [0ae4935331]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Corrections/improvements to use of C standard capabilities; TclNRAddCallback now requires non-NULL callback function, accepts variable number of data arguments
Timelines: family | ancestors | descendants | both | c-std-update
Files: files | file ages | folders
SHA3-256: 0ae4935331d668b80a7da33dede117eefabf37ea03c9b3ca5cbeed41c7474235
User & Date: dkf 2025-06-20 08:19:07.337
Context
2025-06-20
13:15
Give each TSD struct its own name as well as the standard ThreadSpecificData check-in: 8d695d0eb6 user: dkf tags: c-std-update
08:19
Corrections/improvements to use of C standard capabilities; TclNRAddCallback now requires non-NULL c... check-in: 0ae4935331 user: dkf tags: c-std-update
2025-06-19
14:08
Move general variable compiler to file where it makes sense check-in: 2996bce5c9 user: dkf tags: trunk, main
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/tclBasic.c.
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
     * this callback (that marks the end of the target command) and goes back
     * to the end of the source command.
     */

    if (iPtr->deferredCallbacks) {
	iPtr->deferredCallbacks = NULL;
    } else {
	TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
    }

    iPtr->numLevels++;
    TclNRAddCallback(interp, EvalObjvCore, cmdPtr, INT2PTR(flags),
	    INT2PTR(objc), objv);
    return TCL_OK;
}







|







4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
     * this callback (that marks the end of the target command) and goes back
     * to the end of the source command.
     */

    if (iPtr->deferredCallbacks) {
	iPtr->deferredCallbacks = NULL;
    } else {
	TclNRAddCallback(interp, NRCommand);
    }

    iPtr->numLevels++;
    TclNRAddCallback(interp, EvalObjvCore, cmdPtr, INT2PTR(flags),
	    INT2PTR(objc), objv);
    return TCL_OK;
}
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635

	TclDTraceInfo(info, a, i);
	TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]);
	TclDecrRefCount(info);
    }
    if ((TCL_DTRACE_CMD_RETURN_ENABLED() || TCL_DTRACE_CMD_RESULT_ENABLED())
	    && objc) {
	TclNRAddCallback(interp, DTraceCmdReturn, objv[0], NULL, NULL, NULL);
    }
    if (TCL_DTRACE_CMD_ENTRY_ENABLED() && objc) {
	TCL_DTRACE_CMD_ENTRY(TclGetString(objv[0]), objc - 1,
		(Tcl_Obj **)(objv + 1));
    }
#endif /* USE_DTRACE */








|







4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635

	TclDTraceInfo(info, a, i);
	TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]);
	TclDecrRefCount(info);
    }
    if ((TCL_DTRACE_CMD_RETURN_ENABLED() || TCL_DTRACE_CMD_RESULT_ENABLED())
	    && objc) {
	TclNRAddCallback(interp, DTraceCmdReturn, objv[0]);
    }
    if (TCL_DTRACE_CMD_ENTRY_ENABLED() && objc) {
	TCL_DTRACE_CMD_ENTRY(TclGetString(objv[0]), objc - 1,
		(Tcl_Obj **)(objv + 1));
    }
#endif /* USE_DTRACE */

4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
     * If there is a tailcall, schedule it next
     */

    if (data[1] && (data[1] != INT2PTR(1))) {
	listPtr = (Tcl_Obj *)data[1];
	data[1] = NULL;

	TclNRAddCallback(interp, TclNRTailcallEval, listPtr, NULL, NULL, NULL);
    }

    /* OPT ??
     * Do not interrupt a series of cleanups with async or limit checks:
     * just check at the end?
     */








|







4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
     * If there is a tailcall, schedule it next
     */

    if (data[1] && (data[1] != INT2PTR(1))) {
	listPtr = (Tcl_Obj *)data[1];
	data[1] = NULL;

	TclNRAddCallback(interp, TclNRTailcallEval, listPtr);
    }

    /* OPT ??
     * Do not interrupt a series of cleanups with async or limit checks:
     * just check at the end?
     */

4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
     */

    if (!(flags & TCL_EVAL_INVOKE)) {
	/*
	 * Error messages
	 */

	TclNRAddCallback(interp, TEOV_Error, INT2PTR(objc),
		objv, NULL, NULL);
    }

    if (iPtr->numLevels == 1) {
	/*
	 * No CONTINUE or BREAK at level 0, manage RETURN
	 */

	TclNRAddCallback(interp, TEOV_Exception, INT2PTR(iPtr->evalFlags),
		NULL, NULL, NULL);
    }
}

static void
TEOV_SwitchVarFrame(
    Tcl_Interp *interp)
{
    Interp *iPtr = (Interp *) interp;

    /*
     * Change the varFrame to be the rootVarFrame, and push a record to
     * restore things at the end.
     */

    TclNRAddCallback(interp, TEOV_RestoreVarFrame, iPtr->varFramePtr, NULL,
	    NULL, NULL);
    iPtr->varFramePtr = iPtr->rootFramePtr;
}

static int
TEOV_RestoreVarFrame(
    void *data[],
    Tcl_Interp *interp,







|
<







|
<














|
<







4726
4727
4728
4729
4730
4731
4732
4733

4734
4735
4736
4737
4738
4739
4740
4741

4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756

4757
4758
4759
4760
4761
4762
4763
     */

    if (!(flags & TCL_EVAL_INVOKE)) {
	/*
	 * Error messages
	 */

	TclNRAddCallback(interp, TEOV_Error, INT2PTR(objc), objv);

    }

    if (iPtr->numLevels == 1) {
	/*
	 * No CONTINUE or BREAK at level 0, manage RETURN
	 */

	TclNRAddCallback(interp, TEOV_Exception, INT2PTR(iPtr->evalFlags));

    }
}

static void
TEOV_SwitchVarFrame(
    Tcl_Interp *interp)
{
    Interp *iPtr = (Interp *) interp;

    /*
     * Change the varFrame to be the rootVarFrame, and push a record to
     * restore things at the end.
     */

    TclNRAddCallback(interp, TEOV_RestoreVarFrame, iPtr->varFramePtr);

    iPtr->varFramePtr = iPtr->rootFramePtr;
}

static int
TEOV_RestoreVarFrame(
    void *data[],
    Tcl_Interp *interp,
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931

    if (lookupNsPtr) {
	savedNsPtr = varFramePtr->nsPtr;
	varFramePtr->nsPtr = lookupNsPtr;
    }
    TclSkipTailcall(interp);
    TclNRAddCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc),
	    newObjv, savedNsPtr, NULL);
    return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL);
}

static int
TEOV_NotFoundCallback(
    void *data[],
    Tcl_Interp *interp,







|







4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928

    if (lookupNsPtr) {
	savedNsPtr = varFramePtr->nsPtr;
	varFramePtr->nsPtr = lookupNsPtr;
    }
    TclSkipTailcall(interp);
    TclNRAddCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc),
	    newObjv, savedNsPtr);
    return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL);
}

static int
TEOV_NotFoundCallback(
    void *data[],
    Tcl_Interp *interp,
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212

	    iPtr->cmdFramePtr = eoFramePtr;

	    flags |= TCL_EVAL_SOURCE_IN_FRAME;
	}

	TclMarkTailcall(interp);
	TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr,
		objPtr, NULL);

	TclListObjGetElements(NULL, listPtr, &objc, &objv);
	return TclNREvalObjv(interp, objc, objv, flags, NULL);
    }

    if (!(flags & TCL_EVAL_DIRECT)) {
	/*







|
<







6194
6195
6196
6197
6198
6199
6200
6201

6202
6203
6204
6205
6206
6207
6208

	    iPtr->cmdFramePtr = eoFramePtr;

	    flags |= TCL_EVAL_SOURCE_IN_FRAME;
	}

	TclMarkTailcall(interp);
	TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr, objPtr);


	TclListObjGetElements(NULL, listPtr, &objc, &objv);
	return TclNREvalObjv(interp, objc, objv, flags, NULL);
    }

    if (!(flags & TCL_EVAL_DIRECT)) {
	/*
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
	    savedVarFramePtr = iPtr->varFramePtr;
	    iPtr->varFramePtr = iPtr->rootFramePtr;
	}
	Tcl_IncrRefCount(objPtr);
	codePtr = TclCompileObj(interp, objPtr, invoker, word);

	TclNRAddCallback(interp, TEOEx_ByteCodeCallback, savedVarFramePtr,
		objPtr, INT2PTR(allowExceptions), NULL);
	return TclNRExecuteByteCode(interp, codePtr);
    }

    {
	/*
	 * We're not supposed to use the compiler or byte-code
	 * interpreter. Let Tcl_EvalEx evaluate the command directly (and







|







6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
	    savedVarFramePtr = iPtr->varFramePtr;
	    iPtr->varFramePtr = iPtr->rootFramePtr;
	}
	Tcl_IncrRefCount(objPtr);
	codePtr = TclCompileObj(interp, objPtr, invoker, word);

	TclNRAddCallback(interp, TEOEx_ByteCodeCallback, savedVarFramePtr,
		objPtr, INT2PTR(allowExceptions));
	return TclNRExecuteByteCode(interp, codePtr);
    }

    {
	/*
	 * We're not supposed to use the compiler or byte-code
	 * interpreter. Let Tcl_EvalEx evaluate the command directly (and
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
    cmdPtr = (Command *)Tcl_GetHashValue(hPtr);

    /*
     * Avoid the exception-handling brain damage when numLevels == 0
     */

    iPtr->numLevels++;
    Tcl_NRAddCallback(interp, NRPostInvoke, NULL, NULL, NULL, NULL);

    /*
     * Normal command resolution of objv[0] isn't going to find cmdPtr.
     * That's the whole point of **hidden** commands.  So tell the Eval core
     * machinery not to even try (and risk finding something wrong).
     */








|







6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
    cmdPtr = (Command *)Tcl_GetHashValue(hPtr);

    /*
     * Avoid the exception-handling brain damage when numLevels == 0
     */

    iPtr->numLevels++;
    TclNRAddCallback(interp, NRPostInvoke);

    /*
     * Normal command resolution of objv[0] isn't going to find cmdPtr.
     * That's the whole point of **hidden** commands.  So tell the Eval core
     * machinery not to even try (and risk finding something wrong).
     */

8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
void
TclMarkTailcall(
    Tcl_Interp *interp)
{
    Interp *iPtr = (Interp *) interp;

    if (iPtr->deferredCallbacks == NULL) {
	TclNRAddCallback(interp, NRCommand, NULL, NULL,
		NULL, NULL);
	iPtr->deferredCallbacks = TOP_CB(interp);
    }
}

void
TclSkipTailcall(
    Tcl_Interp *interp)
{
    Interp *iPtr = (Interp *) interp;

    TclMarkTailcall(interp);
    iPtr->deferredCallbacks->data[1] = INT2PTR(1);
}

void
TclPushTailcallPoint(
    Tcl_Interp *interp)
{
    TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
    ((Interp *) interp)->numLevels++;
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetTailcall --







|
<


















|







8683
8684
8685
8686
8687
8688
8689
8690

8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
void
TclMarkTailcall(
    Tcl_Interp *interp)
{
    Interp *iPtr = (Interp *) interp;

    if (iPtr->deferredCallbacks == NULL) {
	TclNRAddCallback(interp, NRCommand);

	iPtr->deferredCallbacks = TOP_CB(interp);
    }
}

void
TclSkipTailcall(
    Tcl_Interp *interp)
{
    Interp *iPtr = (Interp *) interp;

    TclMarkTailcall(interp);
    iPtr->deferredCallbacks->data[1] = INT2PTR(1);
}

void
TclPushTailcallPoint(
    Tcl_Interp *interp)
{
    TclNRAddCallback(interp, NRCommand);
    ((Interp *) interp)->numLevels++;
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetTailcall --
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
    }

    /*
     * Perform the tailcall
     */

    TclMarkTailcall(interp);
    TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
    iPtr->lookupNsPtr = (Namespace *) nsPtr;
    return TclNREvalObjv(interp, objc - 1, objv + 1, 0, NULL);
}

int
TclNRReleaseValues(
    void *data[],







|







8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
    }

    /*
     * Perform the tailcall
     */

    TclMarkTailcall(interp);
    TclNRAddCallback(interp, TclNRReleaseValues, listPtr);
    iPtr->lookupNsPtr = (Namespace *) nsPtr;
    return TclNREvalObjv(interp, objc - 1, objv + 1, 0, NULL);
}

int
TclNRReleaseValues(
    void *data[],
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
    void *data1,
    void *data2,
    void *data3)
{
    if (!(postProcPtr)) {
	Tcl_Panic("Adding a callback without an objProc?!");
    }
    TclNRAddCallback(interp, postProcPtr, data0, data1, data2, data3);
}

/*
 *----------------------------------------------------------------------
 *
 * TclNRCoroutineObjCmd -- (and friends)
 *







|







8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
    void *data1,
    void *data2,
    void *data3)
{
    if (!(postProcPtr)) {
	Tcl_Panic("Adding a callback without an objProc?!");
    }
    TclNRAddCallback_2(interp, postProcPtr, data0, data1, data2, data3);
}

/*
 *----------------------------------------------------------------------
 *
 * TclNRCoroutineObjCmd -- (and friends)
 *
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
    }

    if (objc == 2) {
	Tcl_SetObjResult(interp, objv[1]);
    }

    NRE_ASSERT(!COR_IS_SUSPENDED(corPtr));
    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
	    clientData, NULL, NULL);
    return TCL_OK;
}

int
TclNRYieldToObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,







|
<







8945
8946
8947
8948
8949
8950
8951
8952

8953
8954
8955
8956
8957
8958
8959
    }

    if (objc == 2) {
	Tcl_SetObjResult(interp, objv[1]);
    }

    NRE_ASSERT(!COR_IS_SUSPENDED(corPtr));
    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, clientData);

    return TCL_OK;
}

int
TclNRYieldToObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
    Tcl_InterpState state = Tcl_SaveInterpState(interp, result);

    NRE_ASSERT(COR_IS_SUSPENDED(corPtr));
    NRE_ASSERT(corPtr->eePtr != NULL);
    NRE_ASSERT(corPtr->eePtr != iPtr->execEnvPtr);

    corPtr->eePtr->rewind = 1;
    TclNRAddCallback(interp, RewindCoroutineCallback, state,
	    NULL, NULL, NULL);
    return TclNRInterpCoroutine(corPtr, interp, 0, NULL);
}

static void
DeleteCoroutine(
    void *clientData)
{







|
<







9024
9025
9026
9027
9028
9029
9030
9031

9032
9033
9034
9035
9036
9037
9038
    Tcl_InterpState state = Tcl_SaveInterpState(interp, result);

    NRE_ASSERT(COR_IS_SUSPENDED(corPtr));
    NRE_ASSERT(corPtr->eePtr != NULL);
    NRE_ASSERT(corPtr->eePtr != iPtr->execEnvPtr);

    corPtr->eePtr->rewind = 1;
    TclNRAddCallback(interp, RewindCoroutineCallback, state);

    return TclNRInterpCoroutine(corPtr, interp, 0, NULL);
}

static void
DeleteCoroutine(
    void *clientData)
{
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
    if (!corPtr->stackLevel) {
	/*
	 * -- Coroutine is suspended --
	 * Push the callback to restore the caller's context on yield or
	 * return.
	 */

	TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr,
		NULL, NULL, NULL);

	/*
	 * Record the stackLevel at which the resume is happening, then swap
	 * the interp's environment to make it suitable to run this coroutine.
	 */

	corPtr->stackLevel = stackLevel;







|
<







9168
9169
9170
9171
9172
9173
9174
9175

9176
9177
9178
9179
9180
9181
9182
    if (!corPtr->stackLevel) {
	/*
	 * -- Coroutine is suspended --
	 * Push the callback to restore the caller's context on yield or
	 * return.
	 */

	TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr);


	/*
	 * Record the stackLevel at which the resume is happening, then swap
	 * the interp's environment to make it suitable to run this coroutine.
	 */

	corPtr->stackLevel = stackLevel;
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395
     * Add the callback to the coro's execEnv, so that it is the first thing
     * to happen when the coro is resumed.
     */

    ExecEnv *savedEEPtr = iPtr->execEnvPtr;
    iPtr->execEnvPtr = corPtr->eePtr;
    TclNRAddCallback(interp, InjectHandler, corPtr,
	    Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), NULL);
    iPtr->execEnvPtr = savedEEPtr;

    return TCL_OK;
}

static int
TclNRCoroProbeObjCmd(







|







9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
     * Add the callback to the coro's execEnv, so that it is the first thing
     * to happen when the coro is resumed.
     */

    ExecEnv *savedEEPtr = iPtr->execEnvPtr;
    iPtr->execEnvPtr = corPtr->eePtr;
    TclNRAddCallback(interp, InjectHandler, corPtr,
	    Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs));
    iPtr->execEnvPtr = savedEEPtr;

    return TCL_OK;
}

static int
TclNRCoroProbeObjCmd(
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
    /*
     * Now we immediately transfer control to the coroutine to run our probe.
     * TRICKY STUFF copied from the [yield] implementation.
     *
     * Push the callback to restore the caller's context on yield back.
     */

    TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr,
	    NULL, NULL, NULL);

    /*
     * Record the stackLevel at which the resume is happening, then swap
     * the interp's environment to make it suitable to run this coroutine.
     */

    corPtr->stackLevel = &corPtr;







|
<







9429
9430
9431
9432
9433
9434
9435
9436

9437
9438
9439
9440
9441
9442
9443
    /*
     * Now we immediately transfer control to the coroutine to run our probe.
     * TRICKY STUFF copied from the [yield] implementation.
     *
     * Push the callback to restore the caller's context on yield back.
     */

    TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr);


    /*
     * Record the stackLevel at which the resume is happening, then swap
     * the interp's environment to make it suitable to run this coroutine.
     */

    corPtr->stackLevel = &corPtr;
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
    case COROUTINE_ARGUMENTS_ARBITRARY:
	if (objc > 1) {
	    Tcl_SetObjResult(interp, Tcl_NewListObj(objc - 1, objv + 1));
	}
	break;
    }

    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
	    NULL, NULL, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNRCoroutineObjCmd --







|
<







9607
9608
9609
9610
9611
9612
9613
9614

9615
9616
9617
9618
9619
9620
9621
    case COROUTINE_ARGUMENTS_ARBITRARY:
	if (objc > 1) {
	    Tcl_SetObjResult(interp, Tcl_NewListObj(objc - 1, objv + 1));
	}
	break;
    }

    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNRCoroutineObjCmd --
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
    corPtr->eePtr->corPtr = corPtr;

    SAVE_CONTEXT(corPtr->caller);
    corPtr->callerEEPtr = iPtr->execEnvPtr;
    RESTORE_CONTEXT(corPtr->running);
    iPtr->execEnvPtr = corPtr->eePtr;

    TclNRAddCallback(interp, NRCoroutineExitCallback, corPtr,
	    NULL, NULL, NULL);

    /*
     * Ensure that the command is looked up in the correct namespace.
     */

    iPtr->lookupNsPtr = lookupNsPtr;
    Tcl_NREvalObj(interp, Tcl_NewListObj(objc - 2, objv + 2), 0);
    iPtr->numLevels--;

    SAVE_CONTEXT(corPtr->running);
    RESTORE_CONTEXT(corPtr->caller);
    iPtr->execEnvPtr = corPtr->callerEEPtr;

    /*
     * Now just resume the coroutine.
     */

    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
	    NULL, NULL, NULL);
    return TCL_OK;
}

/*
 * This is used in the [info] ensemble
 */








|
<

















|
<







9727
9728
9729
9730
9731
9732
9733
9734

9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752

9753
9754
9755
9756
9757
9758
9759
    corPtr->eePtr->corPtr = corPtr;

    SAVE_CONTEXT(corPtr->caller);
    corPtr->callerEEPtr = iPtr->execEnvPtr;
    RESTORE_CONTEXT(corPtr->running);
    iPtr->execEnvPtr = corPtr->eePtr;

    TclNRAddCallback(interp, NRCoroutineExitCallback, corPtr);


    /*
     * Ensure that the command is looked up in the correct namespace.
     */

    iPtr->lookupNsPtr = lookupNsPtr;
    Tcl_NREvalObj(interp, Tcl_NewListObj(objc - 2, objv + 2), 0);
    iPtr->numLevels--;

    SAVE_CONTEXT(corPtr->running);
    RESTORE_CONTEXT(corPtr->caller);
    iPtr->execEnvPtr = corPtr->callerEEPtr;

    /*
     * Now just resume the coroutine.
     */

    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr);

    return TCL_OK;
}

/*
 * This is used in the [info] ensemble
 */

Changes to generic/tclCmdAH.c.
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
	varNamePtr = objv[2];
    }
    if (objc == 4) {
	optionVarNamePtr = objv[3];
    }

    TclNRAddCallback(interp, CatchObjCmdCallback, INT2PTR(objc),
	    varNamePtr, optionVarNamePtr, NULL);

    /*
     * TIP #280. Make invoking context available to caught script.
     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}







|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
	varNamePtr = objv[2];
    }
    if (objc == 4) {
	optionVarNamePtr = objv[3];
    }

    TclNRAddCallback(interp, CatchObjCmdCallback, INT2PTR(objc),
	    varNamePtr, optionVarNamePtr);

    /*
     * TIP #280. Make invoking context available to caught script.
     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
	 *
	 * TIP #280. Make invoking context available to eval'd script, done
	 * with the default values.
	 */

	objPtr = Tcl_ConcatObj(objc-1, objv+1);
    }
    TclNRAddCallback(interp, EvalCmdErrMsg, NULL, NULL, NULL, NULL);
    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ExitObjCmd --







|







983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
	 *
	 * TIP #280. Make invoking context available to eval'd script, done
	 * with the default values.
	 */

	objPtr = Tcl_ConcatObj(objc-1, objv+1);
    }
    TclNRAddCallback(interp, EvalCmdErrMsg);
    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ExitObjCmd --
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
	return TCL_ERROR;
    }

    TclNewObj(resultPtr);
    Tcl_IncrRefCount(resultPtr);
    if (objc == 2) {
	objPtr = objv[1];
	TclNRAddCallback(interp, ExprCallback, resultPtr, NULL, NULL, NULL);
    } else {
	objPtr = Tcl_ConcatObj(objc-1, objv+1);
	TclNRAddCallback(interp, ExprCallback, resultPtr, objPtr, NULL, NULL);
    }

    return Tcl_NRExprObj(interp, objPtr, resultPtr);
}

static int
ExprCallback(







|


|







1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
	return TCL_ERROR;
    }

    TclNewObj(resultPtr);
    Tcl_IncrRefCount(resultPtr);
    if (objc == 2) {
	objPtr = objv[1];
	TclNRAddCallback(interp, ExprCallback, resultPtr, NULL);
    } else {
	objPtr = Tcl_ConcatObj(objc-1, objv+1);
	TclNRAddCallback(interp, ExprCallback, resultPtr, objPtr);
    }

    return Tcl_NRExprObj(interp, objPtr, resultPtr);
}

static int
ExprCallback(
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
    TclSmallAllocEx(interp, sizeof(ForIterData), iterPtr);
    iterPtr->cond = objv[2];
    iterPtr->body = objv[4];
    iterPtr->next = objv[3];
    iterPtr->msg  = "\n    (\"for\" body line %d)";
    iterPtr->word = 4;

    TclNRAddCallback(interp, ForSetupCallback, iterPtr, NULL, NULL, NULL);

    /*
     * TIP #280. Make invoking context available to initial script.
     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}







|







2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
    TclSmallAllocEx(interp, sizeof(ForIterData), iterPtr);
    iterPtr->cond = objv[2];
    iterPtr->body = objv[4];
    iterPtr->next = objv[3];
    iterPtr->msg  = "\n    (\"for\" body line %d)";
    iterPtr->word = 4;

    TclNRAddCallback(interp, ForSetupCallback, iterPtr);

    /*
     * TIP #280. Make invoking context available to initial script.
     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
    if (result != TCL_OK) {
	if (result == TCL_ERROR) {
	    Tcl_AddErrorInfo(interp, "\n    (\"for\" initial command)");
	}
	TclSmallFreeEx(interp, iterPtr);
	return result;
    }
    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL);
    return TCL_OK;
}

int
TclNRForIterCallback(
    void *data[],
    Tcl_Interp *interp,







|







2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
    if (result != TCL_OK) {
	if (result == TCL_ERROR) {
	    Tcl_AddErrorInfo(interp, "\n    (\"for\" initial command)");
	}
	TclSmallFreeEx(interp, iterPtr);
	return result;
    }
    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr);
    return TCL_OK;
}

int
TclNRForIterCallback(
    void *data[],
    Tcl_Interp *interp,
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
	 * We need to reset the result before evaluating the expression.
	 * Otherwise, any error message will be appended to the result of the
	 * last evaluation.
	 */

	Tcl_ResetResult(interp);
	TclNewObj(boolObj);
	TclNRAddCallback(interp, ForCondCallback, iterPtr, boolObj, NULL,
		NULL);
	return Tcl_NRExprObj(interp, iterPtr->cond, boolObj);
    case TCL_BREAK:
	result = TCL_OK;
	Tcl_ResetResult(interp);
	break;
    case TCL_ERROR:
	Tcl_AppendObjToErrorInfo(interp,







|
<







2611
2612
2613
2614
2615
2616
2617
2618

2619
2620
2621
2622
2623
2624
2625
	 * We need to reset the result before evaluating the expression.
	 * Otherwise, any error message will be appended to the result of the
	 * last evaluation.
	 */

	Tcl_ResetResult(interp);
	TclNewObj(boolObj);
	TclNRAddCallback(interp, ForCondCallback, iterPtr, boolObj);

	return Tcl_NRExprObj(interp, iterPtr->cond, boolObj);
    case TCL_BREAK:
	result = TCL_OK;
	Tcl_ResetResult(interp);
	break;
    case TCL_ERROR:
	Tcl_AppendObjToErrorInfo(interp,
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
	return TCL_ERROR;
    }
    Tcl_DecrRefCount(boolObj);

    if (value) {
	/* TIP #280. */
	if (iterPtr->next) {
	    TclNRAddCallback(interp, ForNextCallback, iterPtr, NULL, NULL,
		    NULL);
	} else {
	    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL,
		    NULL, NULL);
	}
	return TclNREvalObjEx(interp, iterPtr->body, 0, iPtr->cmdFramePtr,
		iterPtr->word);
    }
    TclSmallFreeEx(interp, iterPtr);
    return result;
}

static int
ForNextCallback(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    ForIterData *iterPtr = (ForIterData *)data[0];
    Tcl_Obj *next = iterPtr->next;

    if ((result == TCL_OK) || (result == TCL_CONTINUE)) {
	TclNRAddCallback(interp, ForPostNextCallback, iterPtr, NULL, NULL,
		NULL);

	/*
	 * TIP #280. Make invoking context available to next script.
	 */

	return TclNREvalObjEx(interp, next, 0, iPtr->cmdFramePtr, 3);
    }

    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL);
    return result;
}

static int
ForPostNextCallback(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ForIterData *iterPtr = (ForIterData *)data[0];

    if ((result != TCL_BREAK) && (result != TCL_OK)) {
	if (result == TCL_ERROR) {
	    Tcl_AddErrorInfo(interp, "\n    (\"for\" loop-end command)");
	    TclSmallFreeEx(interp, iterPtr);
	}
	return result;
    }
    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ForeachObjCmd, TclNRForeachCmd, EachloopCmd --







|
<

|
<



















|
<








|


















|







2650
2651
2652
2653
2654
2655
2656
2657

2658
2659

2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679

2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
	return TCL_ERROR;
    }
    Tcl_DecrRefCount(boolObj);

    if (value) {
	/* TIP #280. */
	if (iterPtr->next) {
	    TclNRAddCallback(interp, ForNextCallback, iterPtr);

	} else {
	    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr);

	}
	return TclNREvalObjEx(interp, iterPtr->body, 0, iPtr->cmdFramePtr,
		iterPtr->word);
    }
    TclSmallFreeEx(interp, iterPtr);
    return result;
}

static int
ForNextCallback(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    ForIterData *iterPtr = (ForIterData *)data[0];
    Tcl_Obj *next = iterPtr->next;

    if ((result == TCL_OK) || (result == TCL_CONTINUE)) {
	TclNRAddCallback(interp, ForPostNextCallback, iterPtr);


	/*
	 * TIP #280. Make invoking context available to next script.
	 */

	return TclNREvalObjEx(interp, next, 0, iPtr->cmdFramePtr, 3);
    }

    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr);
    return result;
}

static int
ForPostNextCallback(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ForIterData *iterPtr = (ForIterData *)data[0];

    if ((result != TCL_BREAK) && (result != TCL_OK)) {
	if (result == TCL_ERROR) {
	    Tcl_AddErrorInfo(interp, "\n    (\"for\" loop-end command)");
	    TclSmallFreeEx(interp, iterPtr);
	}
	return result;
    }
    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ForeachObjCmd, TclNRForeachCmd, EachloopCmd --
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913

    if (statePtr->maxj > 0) {
	result = ForeachAssignments(interp, statePtr);
	if (result == TCL_ERROR) {
	    goto done;
	}

	TclNRAddCallback(interp, ForeachLoopStep, statePtr, NULL, NULL, NULL);
	return TclNREvalObjEx(interp, objv[objc-1], 0,
		((Interp *) interp)->cmdFramePtr, objc-1);
    }

    /*
     * This cleanup stage is only used when an error occurs during setup or if
     * there is no work to do.







|







2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909

    if (statePtr->maxj > 0) {
	result = ForeachAssignments(interp, statePtr);
	if (result == TCL_ERROR) {
	    goto done;
	}

	TclNRAddCallback(interp, ForeachLoopStep, statePtr);
	return TclNREvalObjEx(interp, objv[objc-1], 0,
		((Interp *) interp)->cmdFramePtr, objc-1);
    }

    /*
     * This cleanup stage is only used when an error occurs during setup or if
     * there is no work to do.
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984

    if (statePtr->maxj > ++statePtr->j) {
	result = ForeachAssignments(interp, statePtr);
	if (result == TCL_ERROR) {
	    goto done;
	}

	TclNRAddCallback(interp, ForeachLoopStep, statePtr, NULL, NULL, NULL);
	return TclNREvalObjEx(interp, statePtr->bodyPtr, 0,
		((Interp *) interp)->cmdFramePtr, statePtr->bodyIdx);
    }

    /*
     * We're done. Tidy up our work space and finish off.
     */







|







2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980

    if (statePtr->maxj > ++statePtr->j) {
	result = ForeachAssignments(interp, statePtr);
	if (result == TCL_ERROR) {
	    goto done;
	}

	TclNRAddCallback(interp, ForeachLoopStep, statePtr);
	return TclNREvalObjEx(interp, statePtr->bodyPtr, 0,
		((Interp *) interp)->cmdFramePtr, statePtr->bodyIdx);
    }

    /*
     * We're done. Tidy up our work space and finish off.
     */
Changes to generic/tclCmdIL.c.
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
    /*
     * At this point, objv[1] refers to the main expression to test. The
     * arguments after the expression must be "then" (optional) and a script
     * to execute if the expression is true.
     */

    TclNewObj(boolObj);
    Tcl_NRAddCallback(interp, IfConditionCallback, INT2PTR(objc),
	    (void *) objv, INT2PTR(1), boolObj);
    return Tcl_NRExprObj(interp, objv[1], boolObj);
}

static int
IfConditionCallback(
    void *data[],







|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
    /*
     * At this point, objv[1] refers to the main expression to test. The
     * arguments after the expression must be "then" (optional) and a script
     * to execute if the expression is true.
     */

    TclNewObj(boolObj);
    TclNRAddCallback(interp, IfConditionCallback, INT2PTR(objc),
	    (void *) objv, INT2PTR(1), boolObj);
    return Tcl_NRExprObj(interp, objv[1], boolObj);
}

static int
IfConditionCallback(
    void *data[],
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
		    "wrong # args: no expression after \"%s\" argument",
		    clause));
	    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
	    return TCL_ERROR;
	}
	if (!thenScriptIndex) {
	    TclNewObj(boolObj);
	    Tcl_NRAddCallback(interp, IfConditionCallback, data[0], data[1],
		    INT2PTR(i), boolObj);
	    return Tcl_NRExprObj(interp, objv[i], boolObj);
	}
    }

    /*
     * Couldn't find a "then" or "elseif" clause to execute. Check now for an







|







316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
		    "wrong # args: no expression after \"%s\" argument",
		    clause));
	    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
	    return TCL_ERROR;
	}
	if (!thenScriptIndex) {
	    TclNewObj(boolObj);
	    TclNRAddCallback(interp, IfConditionCallback, data[0], data[1],
		    INT2PTR(i), boolObj);
	    return Tcl_NRExprObj(interp, objv[i], boolObj);
	}
    }

    /*
     * Couldn't find a "then" or "elseif" clause to execute. Check now for an
Changes to generic/tclCmdMZ.c.
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
	}
    }

    /*
     * TIP #280: Make invoking context available to switch branch.
     */

    Tcl_NRAddCallback(interp, SwitchPostProc, INT2PTR(splitObjs), ctxPtr,
	    INT2PTR(pc), (void *)pattern);
    return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j);
}

static int
SwitchPostProc(
    void *data[],		/* Data passed from Tcl_NRAddCallback above */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int result)			/* Result to return*/
{
    /* Unpack the preserved data */

    int splitObjs = PTR2INT(data[0]);
    CmdFrame *ctxPtr = (CmdFrame *)data[1];







|
|





|







3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
	}
    }

    /*
     * TIP #280: Make invoking context available to switch branch.
     */

    TclNRAddCallback(interp, SwitchPostProc, INT2PTR(splitObjs), ctxPtr,
	    INT2PTR(pc), pattern);
    return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j);
}

static int
SwitchPostProc(
    void *data[],		/* Data passed from TclNRAddCallback above */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int result)			/* Result to return*/
{
    /* Unpack the preserved data */

    int splitObjs = PTR2INT(data[0]);
    CmdFrame *ctxPtr = (CmdFrame *)data[1];
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
	handlersObj = NULL;
    }

    /*
     * Execute the body.
     */

    Tcl_NRAddCallback(interp, TryPostBody, handlersObj, finallyObj,
	    (void *)objv, INT2PTR(objc));
    return TclNREvalObjEx(interp, bodyObj, 0,
	    ((Interp *) interp)->cmdFramePtr, 1);
}

/*
 *----------------------------------------------------------------------
 *







|
|







4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
	handlersObj = NULL;
    }

    /*
     * Execute the body.
     */

    TclNRAddCallback(interp, TryPostBody, handlersObj, finallyObj,
	    objv, INT2PTR(objc));
    return TclNREvalObjEx(interp, bodyObj, 0,
	    ((Interp *) interp)->cmdFramePtr, 1);
}

/*
 *----------------------------------------------------------------------
 *
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
	     * now because the info[] array is about to become invalid. There
	     * is very little refcount handling here however, since we know
	     * that the objects that we still want to refer to now were input
	     * arguments to [try] and so are still on the Tcl value stack.
	     */

	    handlerBodyObj = info[4];
	    Tcl_NRAddCallback(interp, TryPostHandler, objv, options, info[0],
		    INT2PTR((finallyObj == NULL) ? 0 : objc - 1));
	    Tcl_DecrRefCount(handlersObj);
	    return TclNREvalObjEx(interp, handlerBodyObj, 0,
		    ((Interp *) interp)->cmdFramePtr, 4*i + 5);

	handlerFailed:
	    resultObj = Tcl_GetObjResult(interp);







|







5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
	     * now because the info[] array is about to become invalid. There
	     * is very little refcount handling here however, since we know
	     * that the objects that we still want to refer to now were input
	     * arguments to [try] and so are still on the Tcl value stack.
	     */

	    handlerBodyObj = info[4];
	    TclNRAddCallback(interp, TryPostHandler, objv, options, info[0],
		    INT2PTR((finallyObj == NULL) ? 0 : objc - 1));
	    Tcl_DecrRefCount(handlersObj);
	    return TclNREvalObjEx(interp, handlerBodyObj, 0,
		    ((Interp *) interp)->cmdFramePtr, 4*i + 5);

	handlerFailed:
	    resultObj = Tcl_GetObjResult(interp);
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
    }

    /*
     * Process the finally clause.
     */

    if (finallyObj != NULL) {
	Tcl_NRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj,
		NULL);
	return TclNREvalObjEx(interp, finallyObj, 0,
		((Interp *) interp)->cmdFramePtr, objc - 1);
    }

    /*
     * Install the correct result/options into the interpreter and clean up
     * any temporary storage.







|
<







5121
5122
5123
5124
5125
5126
5127
5128

5129
5130
5131
5132
5133
5134
5135
    }

    /*
     * Process the finally clause.
     */

    if (finallyObj != NULL) {
	TclNRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj);

	return TclNREvalObjEx(interp, finallyObj, 0,
		((Interp *) interp)->cmdFramePtr, objc - 1);
    }

    /*
     * Install the correct result/options into the interpreter and clean up
     * any temporary storage.
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
    /*
     * Process the finally clause if it is present.
     */

    if (finallyObj != NULL) {
	Interp *iPtr = (Interp *) interp;

	Tcl_NRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj,
		NULL);

	/* The 'finally' script is always the last argument word. */
	return TclNREvalObjEx(interp, finallyObj, 0, iPtr->cmdFramePtr,
		finallyIndex);
    }

    /*







|
<







5204
5205
5206
5207
5208
5209
5210
5211

5212
5213
5214
5215
5216
5217
5218
    /*
     * Process the finally clause if it is present.
     */

    if (finallyObj != NULL) {
	Interp *iPtr = (Interp *) interp;

	TclNRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj);


	/* The 'finally' script is always the last argument word. */
	return TclNREvalObjEx(interp, finallyObj, 0, iPtr->cmdFramePtr,
		finallyIndex);
    }

    /*
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
    TclSmallAllocEx(interp, sizeof(ForIterData), iterPtr);
    iterPtr->cond = objv[1];
    iterPtr->body = objv[2];
    iterPtr->next = NULL;
    iterPtr->msg  = "\n    (\"while\" body line %d)";
    iterPtr->word = 2;

    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL,
	    NULL, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclListLines --







|
<







5336
5337
5338
5339
5340
5341
5342
5343

5344
5345
5346
5347
5348
5349
5350
    TclSmallAllocEx(interp, sizeof(ForIterData), iterPtr);
    iterPtr->cond = objv[1];
    iterPtr->body = objv[2];
    iterPtr->next = NULL;
    iterPtr->msg  = "\n    (\"while\" body line %d)";
    iterPtr->word = 2;

    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclListLines --
Changes to generic/tclDictObj.c.
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
    }
    TclDecrRefCount(valueObj);

    /*
     * Run the script.
     */

    TclNRAddCallback(interp, DictMapLoopCallback, storagePtr, NULL,NULL,NULL);
    return TclNREvalObjEx(interp, storagePtr->scriptObj, 0,
	    iPtr->cmdFramePtr, 3);

    /*
     * For unwinding everything on error.
     */








|







2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
    }
    TclDecrRefCount(valueObj);

    /*
     * Run the script.
     */

    TclNRAddCallback(interp, DictMapLoopCallback, storagePtr);
    return TclNREvalObjEx(interp, storagePtr->scriptObj, 0,
	    iPtr->cmdFramePtr, 3);

    /*
     * For unwinding everything on error.
     */

3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
    }
    TclDecrRefCount(valueObj);

    /*
     * Run the script.
     */

    TclNRAddCallback(interp, DictMapLoopCallback, storagePtr, NULL,NULL,NULL);
    return TclNREvalObjEx(interp, storagePtr->scriptObj, 0,
	    iPtr->cmdFramePtr, 3);

    /*
     * For unwinding everything once the iterating is done.
     */








|







3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
    }
    TclDecrRefCount(valueObj);

    /*
     * Run the script.
     */

    TclNRAddCallback(interp, DictMapLoopCallback, storagePtr);
    return TclNREvalObjEx(interp, storagePtr->scriptObj, 0,
	    iPtr->cmdFramePtr, 3);

    /*
     * For unwinding everything once the iterating is done.
     */

3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
     * Execute the body after setting up the NRE handler to process the
     * results.
     */

    objPtr = Tcl_NewListObj(objc-3, objv+2);
    Tcl_IncrRefCount(objPtr);
    Tcl_IncrRefCount(objv[1]);
    TclNRAddCallback(interp, FinalizeDictUpdate, objv[1], objPtr, NULL,NULL);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictUpdate(
    void *data[],







|







3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
     * Execute the body after setting up the NRE handler to process the
     * results.
     */

    objPtr = Tcl_NewListObj(objc-3, objv+2);
    Tcl_IncrRefCount(objPtr);
    Tcl_IncrRefCount(objv[1]);
    TclNRAddCallback(interp, FinalizeDictUpdate, objv[1], objPtr);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictUpdate(
    void *data[],
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701

    pathPtr = NULL;
    if (objc > 3) {
	pathPtr = Tcl_NewListObj(objc-3, objv+2);
	Tcl_IncrRefCount(pathPtr);
    }
    Tcl_IncrRefCount(objv[1]);
    TclNRAddCallback(interp, FinalizeDictWith, objv[1], keysPtr, pathPtr,
	    NULL);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictWith(
    void *data[],







|
<







3686
3687
3688
3689
3690
3691
3692
3693

3694
3695
3696
3697
3698
3699
3700

    pathPtr = NULL;
    if (objc > 3) {
	pathPtr = Tcl_NewListObj(objc-3, objv+2);
	Tcl_IncrRefCount(pathPtr);
    }
    Tcl_IncrRefCount(objv[1]);
    TclNRAddCallback(interp, FinalizeDictWith, objv[1], keysPtr, pathPtr);


    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictWith(
    void *data[],
Changes to generic/tclEnsemble.c.
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
	    Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
		    ensemblePtr->numParameters, objv + 1);
	    Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
		    objc - 2 - ensemblePtr->numParameters,
		    objv + 2 + ensemblePtr->numParameters);
	}
	Tcl_IncrRefCount(copyPtr);
	TclNRAddCallback(interp, TclNRReleaseValues, copyPtr, NULL, NULL, NULL);
	TclDecrRefCount(prefixObj);

	/*
	 * Record the words of the command as given so that routines like
	 * Tcl_WrongNumArgs can produce the correct error message. Parameters
	 * count both as inserted and removed arguments.
	 */

	if (TclInitRewriteEnsemble(interp, 2 + ensemblePtr->numParameters,
		prefixObjc + ensemblePtr->numParameters, objv)) {
	    TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL,
		    NULL);
	}

	/*
	 * Hand off to the target command.
	 */

	TclSkipTailcall(interp);







|










|
<







1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
	    Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
		    ensemblePtr->numParameters, objv + 1);
	    Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
		    objc - 2 - ensemblePtr->numParameters,
		    objv + 2 + ensemblePtr->numParameters);
	}
	Tcl_IncrRefCount(copyPtr);
	TclNRAddCallback(interp, TclNRReleaseValues, copyPtr);
	TclDecrRefCount(prefixObj);

	/*
	 * Record the words of the command as given so that routines like
	 * Tcl_WrongNumArgs can produce the correct error message. Parameters
	 * count both as inserted and removed arguments.
	 */

	if (TclInitRewriteEnsemble(interp, 2 + ensemblePtr->numParameters,
		prefixObjc + ensemblePtr->numParameters, objv)) {
	    TclNRAddCallback(interp, TclClearRootEnsemble);

	}

	/*
	 * Hand off to the target command.
	 */

	TclSkipTailcall(interp);
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
	 */

	tmp[0] = NULL;
	tmp[1] = (Tcl_Obj *) iPtr->ensembleRewrite.sourceObjs;
	tmp[2] = (Tcl_Obj *) store;
	iPtr->ensembleRewrite.sourceObjs = (Tcl_Obj *const *) tmp;

	TclNRAddCallback(interp, FreeER, tmp, store, NULL, NULL);
    }

    store[idx] = fix;
    Tcl_IncrRefCount(fix);
    TclNRAddCallback(interp, TclNRReleaseValues, fix, NULL, NULL, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclEnsembleGetRewriteValues --
 *







|




|







2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
	 */

	tmp[0] = NULL;
	tmp[1] = (Tcl_Obj *) iPtr->ensembleRewrite.sourceObjs;
	tmp[2] = (Tcl_Obj *) store;
	iPtr->ensembleRewrite.sourceObjs = (Tcl_Obj *const *) tmp;

	TclNRAddCallback(interp, FreeER, tmp, store);
    }

    store[idx] = fix;
    Tcl_IncrRefCount(fix);
    TclNRAddCallback(interp, TclNRReleaseValues, fix);
}

/*
 *----------------------------------------------------------------------
 *
 * TclEnsembleGetRewriteValues --
 *
Changes to generic/tclExecute.c.
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
				 * necessary */
} TEBCdata;

#define TEBC_YIELD() \
    do {								\
	esPtr->tosPtr = tosPtr;						\
	TclNRAddCallback(interp, TEBCresume,				\
		TD, pc, INT2PTR(cleanup), NULL);			\
    } while (0)

#define TEBC_DATA_DIG() \
    do {								\
	tosPtr = esPtr->tosPtr;						\
    } while (0)








|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
				 * necessary */
} TEBCdata;

#define TEBC_YIELD() \
    do {								\
	esPtr->tosPtr = tosPtr;						\
	TclNRAddCallback(interp, TEBCresume,				\
		TD, pc, INT2PTR(cleanup), INT2PTR(0));			\
    } while (0)

#define TEBC_DATA_DIG() \
    do {								\
	tosPtr = esPtr->tosPtr;						\
    } while (0)

1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
    Tcl_Obj **resultPtrPtr)	/* Where the Tcl_Obj* that is the expression
				 * result is stored if no errors occur. */
{
    NRE_callback *rootPtr = TOP_CB(interp);
    Tcl_Obj *resultPtr;

    TclNewObj(resultPtr);
    TclNRAddCallback(interp, CopyCallback, resultPtrPtr, resultPtr,
	    NULL, NULL);
    Tcl_NRExprObj(interp, objPtr, resultPtr);
    return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
}

static int
CopyCallback(
    void *data[],







|
<







1360
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
    Tcl_Obj **resultPtrPtr)	/* Where the Tcl_Obj* that is the expression
				 * result is stored if no errors occur. */
{
    NRE_callback *rootPtr = TOP_CB(interp);
    Tcl_Obj *resultPtr;

    TclNewObj(resultPtr);
    TclNRAddCallback(interp, CopyCallback, resultPtrPtr, resultPtr);

    Tcl_NRExprObj(interp, objPtr, resultPtr);
    return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
}

static int
CopyCallback(
    void *data[],
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
    Tcl_Obj *objPtr,
    Tcl_Obj *resultPtr)
{
    Tcl_InterpState state = Tcl_SaveInterpState(interp, TCL_OK);

    Tcl_ResetResult(interp);
    ByteCode *codePtr = CompileExprObj(interp, objPtr);
    Tcl_NRAddCallback(interp, ExprObjCallback, state, resultPtr,
	    NULL, NULL);
    return TclNRExecuteByteCode(interp, codePtr);
}

static int
ExprObjCallback(
    void *data[],
    Tcl_Interp *interp,







|
<







1416
1417
1418
1419
1420
1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
    Tcl_Obj *objPtr,
    Tcl_Obj *resultPtr)
{
    Tcl_InterpState state = Tcl_SaveInterpState(interp, TCL_OK);

    Tcl_ResetResult(interp);
    ByteCode *codePtr = CompileExprObj(interp, objPtr);
    TclNRAddCallback(interp, ExprObjCallback, state, resultPtr);

    return TclNRExecuteByteCode(interp, codePtr);
}

static int
ExprObjCallback(
    void *data[],
    Tcl_Interp *interp,
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
	    ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv);
	}

	pc++;
	cleanup = 1;
	TEBC_YIELD();
	TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
		yieldParameter, NULL, NULL);
	return TCL_OK;
    }

    {
	Tcl_Obj *listPtr;
	Tcl_Size i;








|







2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
	    ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv);
	}

	pc++;
	cleanup = 1;
	TEBC_YIELD();
	TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
		yieldParameter);
	return TCL_OK;
    }

    {
	Tcl_Obj *listPtr;
	Tcl_Size i;

3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
	}

	DECACHE_STACK_INFO();
	pc += 6;
	TEBC_YIELD();

	TclMarkTailcall(interp);
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
	TclListObjGetElements(NULL, objPtr, &objc, &objv);
	TclNRAddCallback(interp, TclNRReleaseValues, objPtr, NULL, NULL, NULL);
	return TclNREvalObjv(interp, objc, objv, TCL_EVAL_INVOKE, NULL);

    /*
     * -----------------------------------------------------------------
     *	   Start of INST_LOAD instructions.
     *
     * WARNING: more 'goto' here than your doctor recommended! The different







|

|







3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
	}

	DECACHE_STACK_INFO();
	pc += 6;
	TEBC_YIELD();

	TclMarkTailcall(interp);
	TclNRAddCallback(interp, TclClearRootEnsemble);
	TclListObjGetElements(NULL, objPtr, &objc, &objv);
	TclNRAddCallback(interp, TclNRReleaseValues, objPtr);
	return TclNREvalObjv(interp, objc, objv, TCL_EVAL_INVOKE, NULL);

    /*
     * -----------------------------------------------------------------
     *	   Start of INST_LOAD instructions.
     *
     * WARNING: more 'goto' here than your doctor recommended! The different
Changes to generic/tclIOUtil.c.
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
    Tcl_IncrRefCount(iPtr->scriptFile);

    /*
     * TIP #280:  Open a frame for the evaluated script.
     */

    iPtr->evalFlags |= TCL_EVAL_FILE;
    TclNRAddCallback(interp, EvalFileCallback, oldScriptFile, pathPtr, objPtr,
	    NULL);
    return TclNREvalObjEx(interp, objPtr, 0, NULL, INT_MIN);
}

static int
EvalFileCallback(
    void *data[],
    Tcl_Interp *interp,







|
<







1923
1924
1925
1926
1927
1928
1929
1930

1931
1932
1933
1934
1935
1936
1937
    Tcl_IncrRefCount(iPtr->scriptFile);

    /*
     * TIP #280:  Open a frame for the evaluated script.
     */

    iPtr->evalFlags |= TCL_EVAL_FILE;
    TclNRAddCallback(interp, EvalFileCallback, oldScriptFile, pathPtr, objPtr);

    return TclNREvalObjEx(interp, objPtr, 0, NULL, INT_MIN);
}

static int
EvalFileCallback(
    void *data[],
    Tcl_Interp *interp,
Changes to generic/tclInt.h.
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169


















170
171
172
173
174
175
176
#   define Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
#   undef  Tcl_ConditionFinalize
#   define Tcl_ConditionFinalize(condPtr)
#endif

// A way to mark a code path as unreachable.
#ifndef TCL_UNREACHABLE
#if defined(__STDC__) && __STDC__ >= 202311L
#include <stddef.h>
#define TCL_UNREACHABLE()	unreachable()
#elif defined(__GNUC__)
#define TCL_UNREACHABLE()	__builtin_unreachable()
#elif defined(_MSC_VER)
#include <stdbool.h>
#define TCL_UNREACHABLE()	__assume(false)
#else
#define TCL_UNREACHABLE()	((void) 0)
#endif
#endif // TCL_UNREACHABLE

#ifndef TCL_FALLTHROUGH
#if defined(__STDC__) && __STDC__ >= 202311L
#define TCL_FALLTHROUGH()	[[fallthrough]]
#elif defined(__GNUC__)
#define TCL_FALLTHROUGH()	__attribute__((fallthrough))
#else
// Nothing documented as an alternative to the standard [[fallthrough]].
#define TCL_FALLTHROUGH()	((void) 0)
#endif
#endif // TCL_FALLTHROUGH



















/*
 * The following procedures allow namespaces to be customized to support
 * special name resolution rules for commands/variables.
 */

struct Tcl_ResolvedVarInfo;








|













|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#   define Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
#   undef  Tcl_ConditionFinalize
#   define Tcl_ConditionFinalize(condPtr)
#endif

// A way to mark a code path as unreachable.
#ifndef TCL_UNREACHABLE
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
#include <stddef.h>
#define TCL_UNREACHABLE()	unreachable()
#elif defined(__GNUC__)
#define TCL_UNREACHABLE()	__builtin_unreachable()
#elif defined(_MSC_VER)
#include <stdbool.h>
#define TCL_UNREACHABLE()	__assume(false)
#else
#define TCL_UNREACHABLE()	((void) 0)
#endif
#endif // TCL_UNREACHABLE

#ifndef TCL_FALLTHROUGH
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
#define TCL_FALLTHROUGH()	[[fallthrough]]
#elif defined(__GNUC__)
#define TCL_FALLTHROUGH()	__attribute__((fallthrough))
#else
// Nothing documented as an alternative to the standard [[fallthrough]].
#define TCL_FALLTHROUGH()	((void) 0)
#endif
#endif // TCL_FALLTHROUGH

/*
 * Compile-time assertions: these produce a compile time error if the
 * expression is not known to be true at compile time. If the assertion is
 * known to be false, the compiler (or optimizer?) will error out with
 * "division by zero". If the assertion cannot be evaluated at compile time,
 * the compiler will error out with "non-static initializer".
 *
 * Adapted with permission from
 * http://www.pixelbeat.org/programming/gcc/static_assert.html
 */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
#define TCL_CT_ASSERT(e) \
    static_assert(e)
#else
#define TCL_CT_ASSERT(e) \
    {enum { ct_assert_value = 1/(!!(e)) };}
#endif

/*
 * The following procedures allow namespaces to be customized to support
 * special name resolution rules for commands/variables.
 */

struct Tcl_ResolvedVarInfo;

4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
	    ((limit).granularityTicker % (limit).cmdGranularity == 0)))	\
	    ? 1 :							\
    (((limit).active & TCL_LIMIT_TIME) &&				\
	    (((limit).timeGranularity == 1) ||				\
	    ((limit).granularityTicker % (limit).timeGranularity == 0)))\
	    ? 1 : 0)))

/*
 * Compile-time assertions: these produce a compile time error if the
 * expression is not known to be true at compile time. If the assertion is
 * known to be false, the compiler (or optimizer?) will error out with
 * "division by zero". If the assertion cannot be evaluated at compile time,
 * the compiler will error out with "non-static initializer".
 *
 * Adapted with permission from
 * http://www.pixelbeat.org/programming/gcc/static_assert.html
 */

#define TCL_CT_ASSERT(e) \
    {enum { ct_assert_value = 1/(!!(e)) };}

/*
 *----------------------------------------------------------------
 * Allocator for small structs (<=sizeof(Tcl_Obj)) using the Tcl_Obj pool.
 * Only checked at compile time.
 *
 * ONLY USE FOR CONSTANT nBytes.
 *







<
<
<
<
<
<
<
<
<
<
<
<
<
<







4972
4973
4974
4975
4976
4977
4978














4979
4980
4981
4982
4983
4984
4985
	    ((limit).granularityTicker % (limit).cmdGranularity == 0)))	\
	    ? 1 :							\
    (((limit).active & TCL_LIMIT_TIME) &&				\
	    (((limit).timeGranularity == 1) ||				\
	    ((limit).granularityTicker % (limit).timeGranularity == 0)))\
	    ? 1 : 0)))















/*
 *----------------------------------------------------------------
 * Allocator for small structs (<=sizeof(Tcl_Obj)) using the Tcl_Obj pool.
 * Only checked at compile time.
 *
 * ONLY USE FOR CONSTANT nBytes.
 *
5065
5066
5067
5068
5069
5070
5071





5072
5073





5074


5075
5076
5077
5078
5079
5080
5081
} NRE_callback;

#define TOP_CB(iPtr) \
    (((Interp *)(iPtr))->execEnvPtr->callbackPtr)

/*
 * Inline version of Tcl_NRAddCallback.





 */






#define TclNRAddCallback(interp,postProcPtr,data0,data1,data2,data3) \


    do {								\
	NRE_callback *_callbackPtr;					\
	TCLNR_ALLOC((interp), (_callbackPtr));				\
	_callbackPtr->procPtr = (postProcPtr);				\
	_callbackPtr->data[0] = (void *)(data0);			\
	_callbackPtr->data[1] = (void *)(data1);			\
	_callbackPtr->data[2] = (void *)(data2);			\







>
>
>
>
>

|
>
>
>
>
>
|
>
>







5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
} NRE_callback;

#define TOP_CB(iPtr) \
    (((Interp *)(iPtr))->execEnvPtr->callbackPtr)

/*
 * Inline version of Tcl_NRAddCallback.
 * This checks a non-NULL postProcPtr is present, and that there are between
 * zero and four data* arguments; unsupplied arguments will be NULL.
 *
 * If postProcPtr is non-constant, use Tcl_NRAddCallback to get a runtime check
 * for sanity.
 */
#define TclNRAddCallback(interp,...) \
	TclNRAddCallback_1(interp, __VA_ARGS__, NULL,NULL,NULL,NULL,NULL,NULL)
#define TclNRAddCallback_1(interp,postProcPtr,data0,data1,data2,data3,dummy,...) \
    do {								\
	TCL_CT_ASSERT((postProcPtr) != NULL);				\
	TCL_CT_ASSERT((dummy) == NULL);					\
	TclNRAddCallback_2(interp,postProcPtr,data0,data1,data2,data3);	\
    } while (0)
#define TclNRAddCallback_2(interp,postProcPtr,data0,data1,data2,data3) \
    do {								\
	NRE_callback *_callbackPtr;					\
	TCLNR_ALLOC((interp), (_callbackPtr));				\
	_callbackPtr->procPtr = (postProcPtr);				\
	_callbackPtr->data[0] = (void *)(data0);			\
	_callbackPtr->data[1] = (void *)(data1);			\
	_callbackPtr->data[2] = (void *)(data2);			\
Changes to generic/tclInterp.c.
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830

    /*
     * Use the ensemble rewriting machinery to ensure correct error messages:
     * only the source command should show, not the full target prefix.
     */

    if (TclInitRewriteEnsemble(interp, 1, prefc, objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
    }
    TclSkipTailcall(interp);
    return Tcl_NREvalObj(interp, listPtr, flags);
}

int
TclAliasObjCmd(







|







1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830

    /*
     * Use the ensemble rewriting machinery to ensure correct error messages:
     * only the source command should show, not the full target prefix.
     */

    if (TclInitRewriteEnsemble(interp, 1, prefc, objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble);
    }
    TclSkipTailcall(interp);
    return Tcl_NREvalObj(interp, listPtr, flags);
}

int
TclAliasObjCmd(
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126

    Tcl_Preserve(childInterp);
    Tcl_AllowExceptions(childInterp);

    if (namespaceName == NULL) {
	NRE_callback *rootPtr = TOP_CB(childInterp);

	Tcl_NRAddCallback(interp, NRPostInvokeHidden, childInterp,
		rootPtr, NULL, NULL);
	return TclNRInvoke(NULL, childInterp, objc, objv);
    } else {
	Namespace *nsPtr, *dummy1, *dummy2;
	const char *tail;

	result = TclGetNamespaceForQualName(childInterp, namespaceName, NULL,
		TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG







|
<







3111
3112
3113
3114
3115
3116
3117
3118

3119
3120
3121
3122
3123
3124
3125

    Tcl_Preserve(childInterp);
    Tcl_AllowExceptions(childInterp);

    if (namespaceName == NULL) {
	NRE_callback *rootPtr = TOP_CB(childInterp);

	TclNRAddCallback(interp, NRPostInvokeHidden, childInterp, rootPtr);

	return TclNRInvoke(NULL, childInterp, objc, objv);
    } else {
	Namespace *nsPtr, *dummy1, *dummy2;
	const char *tail;

	result = TclGetNamespaceForQualName(childInterp, namespaceName, NULL,
		TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG
Changes to generic/tclNamesp.c.
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
	word = 0;
    }

    /*
     * TIP #280: Make invoking context available to eval'd script.
     */

    TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "eval",
	    NULL, NULL);
    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

static int
NsEval_Callback(
    void *data[],
    Tcl_Interp *interp,







|
<







3538
3539
3540
3541
3542
3543
3544
3545

3546
3547
3548
3549
3550
3551
3552
	word = 0;
    }

    /*
     * TIP #280: Make invoking context available to eval'd script.
     */

    TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "eval");

    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

static int
NsEval_Callback(
    void *data[],
    Tcl_Interp *interp,
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979

	concatObjv[0] = objv[2];
	concatObjv[1] = Tcl_NewListObj(objc - 3, objv + 3);
	cmdObjPtr = Tcl_ConcatObj(2, concatObjv);
	Tcl_DecrRefCount(concatObjv[1]); /* We're done with the list object. */
    }

    TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "inscope",
	    NULL, NULL);
    return TclNREvalObjEx(interp, cmdObjPtr, 0, NULL, 0);
}

/*
 *----------------------------------------------------------------------
 *
 * NamespaceOriginCmd --







|
<







3963
3964
3965
3966
3967
3968
3969
3970

3971
3972
3973
3974
3975
3976
3977

	concatObjv[0] = objv[2];
	concatObjv[1] = Tcl_NewListObj(objc - 3, objv + 3);
	cmdObjPtr = Tcl_ConcatObj(2, concatObjv);
	Tcl_DecrRefCount(concatObjv[1]); /* We're done with the list object. */
    }

    TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "inscope");

    return TclNREvalObjEx(interp, cmdObjPtr, 0, NULL, 0);
}

/*
 *----------------------------------------------------------------------
 *
 * NamespaceOriginCmd --
Changes to generic/tclOO.c.
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
    contextPtr->skip = skip;

    /*
     * Adjust the ensemble tracking record if necessary. [Bug 3514761]
     */

    if (TclInitRewriteEnsemble(interp, skip, skip, objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
    }

    /*
     * Fire off the constructors non-recursively.
     */

    TclNRAddCallback(interp, FinalizeAlloc, contextPtr, oPtr, state,







|







1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
    contextPtr->skip = skip;

    /*
     * Adjust the ensemble tracking record if necessary. [Bug 3514761]
     */

    if (TclInitRewriteEnsemble(interp, skip, skip, objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble);
    }

    /*
     * Fire off the constructors non-recursively.
     */

    TclNRAddCallback(interp, FinalizeAlloc, contextPtr, oPtr, state,
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
    }

    /*
     * Invoke the call chain, locking the object structure against deletion
     * for the duration.
     */

    TclNRAddCallback(interp, FinalizeObjectCall, contextPtr, NULL,NULL,NULL);
    return TclOOInvokeContext(contextPtr, interp, objc, objv);
}

static int
FinalizeObjectCall(
    void *data[],
    TCL_UNUSED(Tcl_Interp *),







|







2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
    }

    /*
     * Invoke the call chain, locking the object structure against deletion
     * for the duration.
     */

    TclNRAddCallback(interp, FinalizeObjectCall, contextPtr);
    return TclOOInvokeContext(contextPtr, interp, objc, objv);
}

static int
FinalizeObjectCall(
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
     * arg (i.e., 'next') and not the variable amount that can happen because
     * method invocations (i.e., '$obj meth' and 'my meth'), constructors
     * (i.e., '$cls new' and '$cls create obj') and destructors (no args at
     * all) come through the same code.
     */

    TclNRAddCallback(interp, FinalizeNext, contextPtr,
	    INT2PTR(contextPtr->index), INT2PTR(contextPtr->skip), NULL);
    contextPtr->index++;
    contextPtr->skip = skip;

    /*
     * Invoke the (advanced) method call context in the caller context.
     */








|







2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
     * arg (i.e., 'next') and not the variable amount that can happen because
     * method invocations (i.e., '$obj meth' and 'my meth'), constructors
     * (i.e., '$cls new' and '$cls create obj') and destructors (no args at
     * all) come through the same code.
     */

    TclNRAddCallback(interp, FinalizeNext, contextPtr,
	    INT2PTR(contextPtr->index), INT2PTR(contextPtr->skip));
    contextPtr->index++;
    contextPtr->skip = skip;

    /*
     * Invoke the (advanced) method call context in the caller context.
     */

Changes to generic/tclOOBasic.c.
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 * ----------------------------------------------------------------------
 */

static inline Tcl_Object *
AddConstructionFinalizer(
    Tcl_Interp *interp)
{
    TclNRAddCallback(interp, FinalizeConstruction, NULL, NULL, NULL, NULL);
    return (Tcl_Object *) &(TOP_CB(interp)->data[0]);
}

static int
FinalizeConstruction(
    void *data[],
    Tcl_Interp *interp,







|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 * ----------------------------------------------------------------------
 */

static inline Tcl_Object *
AddConstructionFinalizer(
    Tcl_Interp *interp)
{
    TclNRAddCallback(interp, FinalizeConstruction, NULL);
    return (Tcl_Object *) &(TOP_CB(interp)->data[0]);
}

static int
FinalizeConstruction(
    void *data[],
    Tcl_Interp *interp,
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
     * Must add references or errors in configuration script will cause
     * trouble.
     */

    Tcl_IncrRefCount(invoke[0]);
    Tcl_IncrRefCount(invoke[1]);
    Tcl_IncrRefCount(invoke[2]);
    TclNRAddCallback(interp, DecrRefsPostClassConstructor,
	    invoke, oPtr, NULL, NULL);

    /*
     * Tricky point: do not want the extra reported level in the Tcl stack
     * trace, so use TCL_EVAL_NOERR.
     */

    return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);







|
<







128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
     * Must add references or errors in configuration script will cause
     * trouble.
     */

    Tcl_IncrRefCount(invoke[0]);
    Tcl_IncrRefCount(invoke[1]);
    Tcl_IncrRefCount(invoke[2]);
    TclNRAddCallback(interp, DecrRefsPostClassConstructor, invoke, oPtr);


    /*
     * Tricky point: do not want the extra reported level in the Tcl stack
     * trace, so use TCL_EVAL_NOERR.
     */

    return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    if (!(oPtr->flags & DESTRUCTOR_CALLED)) {
	oPtr->flags |= DESTRUCTOR_CALLED;
	contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL, NULL,
		NULL);
	if (contextPtr != NULL) {
	    contextPtr->callPtr->flags |= DESTRUCTOR;
	    contextPtr->skip = 0;
	    TclNRAddCallback(interp, AfterNRDestructor, contextPtr,
		    NULL, NULL, NULL);
	    TclPushTailcallPoint(interp);
	    return TclOOInvokeContext(contextPtr, interp, 0, NULL);
	}
    }
    if (oPtr->command) {
	Tcl_DeleteCommandFromToken(interp, oPtr->command);
    }







|
<







384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
    if (!(oPtr->flags & DESTRUCTOR_CALLED)) {
	oPtr->flags |= DESTRUCTOR_CALLED;
	contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL, NULL,
		NULL);
	if (contextPtr != NULL) {
	    contextPtr->callPtr->flags |= DESTRUCTOR;
	    contextPtr->skip = 0;
	    TclNRAddCallback(interp, AfterNRDestructor, contextPtr);

	    TclPushTailcallPoint(interp);
	    return TclOOInvokeContext(contextPtr, interp, 0, NULL);
	}
    }
    if (oPtr->command) {
	Tcl_DeleteCommandFromToken(interp, oPtr->command);
    }
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    }

    /*
     * Evaluate the script now, with FinalizeEval to do the processing after
     * the script completes.
     */

    TclNRAddCallback(interp, FinalizeEval, object, NULL, NULL, NULL);
    return TclNREvalObjEx(interp, scriptPtr, 0, invoker, skip);
}

static int
FinalizeEval(
    void *data[],
    Tcl_Interp *interp,







|







478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
    }

    /*
     * Evaluate the script now, with FinalizeEval to do the processing after
     * the script completes.
     */

    TclNRAddCallback(interp, FinalizeEval, object);
    return TclNREvalObjEx(interp, scriptPtr, 0, invoker, skip);
}

static int
FinalizeEval(
    void *data[],
    Tcl_Interp *interp,
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
    context = (Tcl_ObjectContext) framePtr->clientData;

    /*
     * Invoke the (advanced) method call context in the caller context. Note
     * that this is like [uplevel 1] and not [eval].
     */

    TclNRAddCallback(interp, NextRestoreFrame, framePtr, NULL,NULL,NULL);
    iPtr->varFramePtr = framePtr->callerVarPtr;
    return TclNRObjectContextInvokeNext(interp, context, objc, objv, 1);
}

int
TclOONextToObjCmd(
    TCL_UNUSED(void *),







|







938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
    context = (Tcl_ObjectContext) framePtr->clientData;

    /*
     * Invoke the (advanced) method call context in the caller context. Note
     * that this is like [uplevel 1] and not [eval].
     */

    TclNRAddCallback(interp, NextRestoreFrame, framePtr);
    iPtr->varFramePtr = framePtr->callerVarPtr;
    return TclNRObjectContextInvokeNext(interp, context, objc, objv, 1);
}

int
TclOONextToObjCmd(
    TCL_UNUSED(void *),
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
	if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) {
	    /*
	     * Invoke the (advanced) method call context in the caller
	     * context. Note that this is like [uplevel 1] and not [eval].
	     */

	    TclNRAddCallback(interp, NextRestoreFrame, framePtr,
		    contextPtr, INT2PTR(contextPtr->index), NULL);
	    contextPtr->index = i - 1;
	    iPtr->varFramePtr = framePtr->callerVarPtr;
	    return TclNRObjectContextInvokeNext(interp,
		    (Tcl_ObjectContext) contextPtr, objc, objv, 2);
	}
    }








|







998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
	if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) {
	    /*
	     * Invoke the (advanced) method call context in the caller
	     * context. Note that this is like [uplevel 1] and not [eval].
	     */

	    TclNRAddCallback(interp, NextRestoreFrame, framePtr,
		    contextPtr, INT2PTR(contextPtr->index));
	    contextPtr->index = i - 1;
	    iPtr->varFramePtr = framePtr->callerVarPtr;
	    return TclNRObjectContextInvokeNext(interp,
		    (Tcl_ObjectContext) contextPtr, objc, objv, 2);
	}
    }

Changes to generic/tclOOCall.c.
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
	}

	/*
	 * Add a callback to ensure that method references are dropped once
	 * this call is finished.
	 */

	TclNRAddCallback(interp, FinalizeMethodRefs, contextPtr, NULL, NULL,
		NULL);
    }

    /*
     * Save whether we were in a filter and set up whether we are now.
     */

    if (contextPtr->oPtr->flags & FILTER_HANDLING) {
	TclNRAddCallback(interp, SetFilterFlags, contextPtr, NULL,NULL,NULL);
    } else {
	TclNRAddCallback(interp, ResetFilterFlags,contextPtr,NULL,NULL,NULL);
    }
    if (isFilter || contextPtr->callPtr->flags & FILTER_HANDLING) {
	contextPtr->oPtr->flags |= FILTER_HANDLING;
    } else {
	contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    }








|
<







|

|







353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
	}

	/*
	 * Add a callback to ensure that method references are dropped once
	 * this call is finished.
	 */

	TclNRAddCallback(interp, FinalizeMethodRefs, contextPtr);

    }

    /*
     * Save whether we were in a filter and set up whether we are now.
     */

    if (contextPtr->oPtr->flags & FILTER_HANDLING) {
	TclNRAddCallback(interp, SetFilterFlags, contextPtr);
    } else {
	TclNRAddCallback(interp, ResetFilterFlags, contextPtr);
    }
    if (isFilter || contextPtr->callPtr->flags & FILTER_HANDLING) {
	contextPtr->oPtr->flags |= FILTER_HANDLING;
    } else {
	contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    }

Changes to generic/tclOOMethod.c.
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
	}
    }

    /*
     * Now invoke the body of the method.
     */

    TclNRAddCallback(interp, FinalizePMCall, pmPtr, context, fdPtr, NULL);
    return TclNRInterpProcCore(interp, fdPtr->nameObj,
	    Tcl_ObjectContextSkippedArgs(context), fdPtr->errProc);
}

static int
FinalizePMCall(
    void *data[],







|







882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
	}
    }

    /*
     * Now invoke the body of the method.
     */

    TclNRAddCallback(interp, FinalizePMCall, pmPtr, context, fdPtr);
    return TclNRInterpProcCore(interp, fdPtr->nameObj,
	    Tcl_ObjectContextSkippedArgs(context), fdPtr->errProc);
}

static int
FinalizePMCall(
    void *data[],
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
     * non-empty list, so there's a whole class of failures ("not a list") we
     * can ignore here.
     */

    TclListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs);
    argObjs = InitEnsembleRewrite(interp, objc, objv, skip,
	    numPrefixes, prefixObjs, &len);
    Tcl_NRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL);
    /*
     * NOTE: The combination of direct set of iPtr->lookupNsPtr and the use
     * of the TCL_EVAL_NOERR flag results in an evaluation configuration
     * very much like TCL_EVAL_INVOKE.
     */
    ((Interp *) interp)->lookupNsPtr = (Namespace *)
	    contextPtr->oPtr->namespacePtr;







|







1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
     * non-empty list, so there's a whole class of failures ("not a list") we
     * can ignore here.
     */

    TclListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs);
    argObjs = InitEnsembleRewrite(interp, objc, objv, skip,
	    numPrefixes, prefixObjs, &len);
    TclNRAddCallback(interp, FinalizeForwardCall, argObjs);
    /*
     * NOTE: The combination of direct set of iPtr->lookupNsPtr and the use
     * of the TCL_EVAL_NOERR flag results in an evaluation configuration
     * very much like TCL_EVAL_INVOKE.
     */
    ((Interp *) interp)->lookupNsPtr = (Namespace *)
	    contextPtr->oPtr->namespacePtr;
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
     * how to store the rewrite rules get complex solely because of the case
     * where an ensemble rewrites itself out of the picture; when that
     * happens, the quality of the error message rewrite falls drastically
     * (and unavoidably).
     */

    if (TclInitRewriteEnsemble(interp, toRewrite, rewriteLength, objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
    }
    *lengthPtr = len;
    return argObjs;
}

/*
 * ----------------------------------------------------------------------







|







1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
     * how to store the rewrite rules get complex solely because of the case
     * where an ensemble rewrites itself out of the picture; when that
     * happens, the quality of the error message rewrite falls drastically
     * (and unavoidably).
     */

    if (TclInitRewriteEnsemble(interp, toRewrite, rewriteLength, objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble);
    }
    *lengthPtr = len;
    return argObjs;
}

/*
 * ----------------------------------------------------------------------
Changes to generic/tclPkg.c.
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    void *clientData,
    Tcl_Interp *interp,
    int reqc,
    Tcl_Obj *const reqv[])
{
    RequireProcArgs *args = (RequireProcArgs *)clientData;

    Tcl_NRAddCallback(interp,
	    PkgRequireCore, (void *) args->name, INT2PTR(reqc), (void *) reqv,
	    args->clientDataPtr);
    return TCL_OK;
}

static int
PkgRequireCore(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    const char *name = (const char *)data[0];
    int reqc = (int)PTR2INT(data[1]);
    Tcl_Obj **reqv = (Tcl_Obj **)data[2];
    int code = CheckAllRequirements(interp, reqc, reqv);
    Require *reqPtr;

    if (code != TCL_OK) {
	return code;
    }
    reqPtr = (Require *)Tcl_Alloc(sizeof(Require));
    Tcl_NRAddCallback(interp, PkgRequireCoreCleanup, reqPtr, NULL, NULL, NULL);
    reqPtr->clientDataPtr = data[3];
    reqPtr->name = name;
    reqPtr->pkgPtr = FindPackage(interp, name);
    if (reqPtr->pkgPtr->version == NULL) {
	Tcl_NRAddCallback(interp,
		SelectPackage, reqPtr, INT2PTR(reqc), reqv,
		(void *)PkgRequireCoreStep1);
    } else {
	Tcl_NRAddCallback(interp,
		PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), reqv, NULL);
    }
    return TCL_OK;
}

static int
PkgRequireCoreStep1(
    void *data[],







|
|
<



















|




|
|
<

|
|







448
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
490
491
492
    void *clientData,
    Tcl_Interp *interp,
    int reqc,
    Tcl_Obj *const reqv[])
{
    RequireProcArgs *args = (RequireProcArgs *)clientData;

    TclNRAddCallback(interp, PkgRequireCore,
	    args->name, INT2PTR(reqc), reqv, args->clientDataPtr);

    return TCL_OK;
}

static int
PkgRequireCore(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    const char *name = (const char *)data[0];
    int reqc = (int)PTR2INT(data[1]);
    Tcl_Obj **reqv = (Tcl_Obj **)data[2];
    int code = CheckAllRequirements(interp, reqc, reqv);
    Require *reqPtr;

    if (code != TCL_OK) {
	return code;
    }
    reqPtr = (Require *)Tcl_Alloc(sizeof(Require));
    TclNRAddCallback(interp, PkgRequireCoreCleanup, reqPtr);
    reqPtr->clientDataPtr = data[3];
    reqPtr->name = name;
    reqPtr->pkgPtr = FindPackage(interp, name);
    if (reqPtr->pkgPtr->version == NULL) {
	TclNRAddCallback(interp, SelectPackage,
		reqPtr, INT2PTR(reqc), reqv, PkgRequireCoreStep1);

    } else {
	TclNRAddCallback(interp, PkgRequireCoreFinal,
		reqPtr, INT2PTR(reqc), reqv);
    }
    return TCL_OK;
}

static int
PkgRequireCoreStep1(
    void *data[],
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549

    /*
     * If we've got the package in the DB already, go on to actually loading
     * it.
     */

    if (reqPtr->pkgPtr->version != NULL) {
	Tcl_NRAddCallback(interp,
		PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
	return TCL_OK;
    }

    /*
     * The package is not in the database. If there is a "package unknown"
     * command, invoke it.
     */

    script = ((Interp *) interp)->packageUnknown;
    if (script == NULL) {
	/*
	 * No package unknown script. Move on to finalizing.
	 */

	Tcl_NRAddCallback(interp,
		PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
	return TCL_OK;
    }

    /*
     * Invoke the "package unknown" script synchronously.
     */

    Tcl_DStringInit(&command);
    Tcl_DStringAppend(&command, script, -1);
    Tcl_DStringAppendElement(&command, name);
    AddRequirementsToDString(&command, reqc, reqv);

    Tcl_NRAddCallback(interp,
	    PkgRequireCoreStep2, reqPtr, INT2PTR(reqc), (void *) reqv, NULL);
    Tcl_NREvalObj(interp, Tcl_DStringToObj(&command), TCL_EVAL_GLOBAL);
    return TCL_OK;
}

static int
PkgRequireCoreStep2(
    void *data[],







|
|














|
|












|
|







502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547

    /*
     * If we've got the package in the DB already, go on to actually loading
     * it.
     */

    if (reqPtr->pkgPtr->version != NULL) {
	TclNRAddCallback(interp, PkgRequireCoreFinal,
		reqPtr, INT2PTR(reqc), reqv);
	return TCL_OK;
    }

    /*
     * The package is not in the database. If there is a "package unknown"
     * command, invoke it.
     */

    script = ((Interp *) interp)->packageUnknown;
    if (script == NULL) {
	/*
	 * No package unknown script. Move on to finalizing.
	 */

	TclNRAddCallback(interp, PkgRequireCoreFinal,
		reqPtr, INT2PTR(reqc), reqv);
	return TCL_OK;
    }

    /*
     * Invoke the "package unknown" script synchronously.
     */

    Tcl_DStringInit(&command);
    Tcl_DStringAppend(&command, script, -1);
    Tcl_DStringAppendElement(&command, name);
    AddRequirementsToDString(&command, reqc, reqv);

    TclNRAddCallback(interp, PkgRequireCoreStep2,
	    reqPtr, INT2PTR(reqc), reqv);
    Tcl_NREvalObj(interp, Tcl_DStringToObj(&command), TCL_EVAL_GLOBAL);
    return TCL_OK;
}

static int
PkgRequireCoreStep2(
    void *data[],
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
    Tcl_ResetResult(interp);

    /*
     * pkgPtr may now be invalid, so refresh it.
     */

    reqPtr->pkgPtr = FindPackage(interp, name);
    Tcl_NRAddCallback(interp,
	    SelectPackage, reqPtr, INT2PTR(reqc), reqv,
	    (void *)PkgRequireCoreFinal);
    return TCL_OK;
}

static int
PkgRequireCoreFinal(
    void *data[],
    Tcl_Interp *interp,







|
|
<







567
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
    Tcl_ResetResult(interp);

    /*
     * pkgPtr may now be invalid, so refresh it.
     */

    reqPtr->pkgPtr = FindPackage(interp, name);
    TclNRAddCallback(interp, SelectPackage,
	    reqPtr, INT2PTR(reqc), reqv, PkgRequireCoreFinal);

    return TCL_OK;
}

static int
PkgRequireCoreFinal(
    void *data[],
    Tcl_Interp *interp,
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

    if ((iPtr->packagePrefer == PKG_PREFER_STABLE)
	    && (bestStablePtr != NULL)) {
	bestPtr = bestStablePtr;
    }

    if (bestPtr == NULL) {
	Tcl_NRAddCallback(interp,
		(Tcl_NRPostProc *)data[3], reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
    } else {
	/*
	 * We found an ifneeded script for the package. Be careful while
	 * executing it: this could cause reentrancy, so (a) protect the
	 * script itself from deletion and (b) don't assume that bestPtr will
	 * still exist when the script completes.
	 */







|
|







797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812

    if ((iPtr->packagePrefer == PKG_PREFER_STABLE)
	    && (bestStablePtr != NULL)) {
	bestPtr = bestStablePtr;
    }

    if (bestPtr == NULL) {
	Tcl_NRAddCallback(interp, (Tcl_NRPostProc *)data[3],
		reqPtr, INT2PTR(reqc), (void *)reqv, NULL);
    } else {
	/*
	 * We found an ifneeded script for the package. Be careful while
	 * executing it: this could cause reentrancy, so (a) protect the
	 * script itself from deletion and (b) don't assume that bestPtr will
	 * still exist when the script completes.
	 */
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
	pkgName->nextPtr = pkgFiles->names;
	strcpy(pkgName->name, name);
	pkgFiles->names = pkgName;
	if (bestPtr->pkgIndex) {
	    TclPkgFileSeen(interp, bestPtr->pkgIndex);
	}
	reqPtr->versionToProvide = versionToProvide;
	Tcl_NRAddCallback(interp,
		SelectPackageFinal, reqPtr, INT2PTR(reqc), (void *)reqv,
		data[3]);
	Tcl_NREvalObj(interp, Tcl_NewStringObj(bestPtr->script, -1),
		TCL_EVAL_GLOBAL);
    }
    return TCL_OK;
}

static int







|
|
<







828
829
830
831
832
833
834
835
836

837
838
839
840
841
842
843
	pkgName->nextPtr = pkgFiles->names;
	strcpy(pkgName->name, name);
	pkgFiles->names = pkgName;
	if (bestPtr->pkgIndex) {
	    TclPkgFileSeen(interp, bestPtr->pkgIndex);
	}
	reqPtr->versionToProvide = versionToProvide;
	TclNRAddCallback(interp, SelectPackageFinal,
		reqPtr, INT2PTR(reqc), reqv, data[3]);

	Tcl_NREvalObj(interp, Tcl_NewStringObj(bestPtr->script, -1),
		TCL_EVAL_GLOBAL);
    }
    return TCL_OK;
}

static int
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
	    Tcl_DecrRefCount(reqPtr->pkgPtr->version);
	    reqPtr->pkgPtr->version = NULL;
	}
	reqPtr->pkgPtr->clientData = NULL;
	return result;
    }

    Tcl_NRAddCallback(interp,
	    (Tcl_NRPostProc *)data[3], reqPtr, INT2PTR(reqc), (void *) reqv, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PkgPresent / Tcl_PkgPresentEx --







|
|







934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
	    Tcl_DecrRefCount(reqPtr->pkgPtr->version);
	    reqPtr->pkgPtr->version = NULL;
	}
	reqPtr->pkgPtr->clientData = NULL;
	return result;
    }

    Tcl_NRAddCallback(interp, (Tcl_NRPostProc *)data[3],
	    reqPtr, INT2PTR(reqc), (void *) reqv, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PkgPresent / Tcl_PkgPresentEx --
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
	    Tcl_IncrRefCount(objv[3]);

	    objvListPtr = Tcl_NewListObj(0, NULL);
	    Tcl_IncrRefCount(objvListPtr);
	    Tcl_ListObjAppendElement(interp, objvListPtr, ov);
	    TclListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);

	    Tcl_NRAddCallback(interp,
		    TclNRPackageObjCmdCleanup, objv[3], objvListPtr, NULL,NULL);
	    Tcl_NRAddCallback(interp,
		    PkgRequireCore, (void *) argv3, INT2PTR(newobjc),
		    newObjvPtr, NULL);
	    return TCL_OK;
	} else {
	    Tcl_Obj *const *newobjv = objv + 3;

	    newobjc = objc - 3;
	    if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
		return TCL_ERROR;







|
|
|
|
<







1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
	    Tcl_IncrRefCount(objv[3]);

	    objvListPtr = Tcl_NewListObj(0, NULL);
	    Tcl_IncrRefCount(objvListPtr);
	    Tcl_ListObjAppendElement(interp, objvListPtr, ov);
	    TclListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);

	    TclNRAddCallback(interp, TclNRPackageObjCmdCleanup,
		    objv[3], objvListPtr);
	    TclNRAddCallback(interp, PkgRequireCore,
		    argv3, INT2PTR(newobjc), newObjvPtr);

	    return TCL_OK;
	} else {
	    Tcl_Obj *const *newobjv = objv + 3;

	    newobjc = objc - 3;
	    if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
		return TCL_ERROR;
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
		 * so duplicate them.
		 */

		Tcl_ListObjAppendElement(interp, objvListPtr,
			Tcl_DuplicateObj(newobjv[i]));
	    }
	    TclListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
	    Tcl_NRAddCallback(interp,
		    TclNRPackageObjCmdCleanup, objv[2], objvListPtr, NULL,NULL);
	    Tcl_NRAddCallback(interp,
		    PkgRequireCore, (void *) argv2, INT2PTR(newobjc),
		    newObjvPtr, NULL);
	    return TCL_OK;
	}
	break;
    case PKG_UNKNOWN:
	if (objc == 2) {
	    if (iPtr->packageUnknown != NULL) {
		Tcl_SetObjResult(interp,







|
|
|
|
<







1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388

1389
1390
1391
1392
1393
1394
1395
		 * so duplicate them.
		 */

		Tcl_ListObjAppendElement(interp, objvListPtr,
			Tcl_DuplicateObj(newobjv[i]));
	    }
	    TclListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
	    TclNRAddCallback(interp, TclNRPackageObjCmdCleanup,
		    objv[2], objvListPtr);
	    TclNRAddCallback(interp, PkgRequireCore,
		    argv2, INT2PTR(newobjc), newObjvPtr);

	    return TCL_OK;
	}
	break;
    case PKG_UNKNOWN:
	if (objc == 2) {
	    if (iPtr->packageUnknown != NULL) {
		Tcl_SetObjResult(interp,
Changes to generic/tclProc.c.
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
	 * between, then evaluate the result. Tcl_EvalObjEx will delete the
	 * object when it decrements its refcount after eval'ing it.
	 */

	objPtr = Tcl_ConcatObj(objc, objv);
    }

    TclNRAddCallback(interp, Uplevel_Callback, savedVarFramePtr, NULL, NULL,
	    NULL);
    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

/*
 *----------------------------------------------------------------------
 *
 * TclFindProc --







|
<







993
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
	 * between, then evaluate the result. Tcl_EvalObjEx will delete the
	 * object when it decrements its refcount after eval'ing it.
	 */

	objPtr = Tcl_ConcatObj(objc, objv);
    }

    TclNRAddCallback(interp, Uplevel_Callback, savedVarFramePtr);

    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

/*
 *----------------------------------------------------------------------
 *
 * TclFindProc --
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
    /*
     * Initialise all compiled locals to avoid problems at DeleteLocalVars.
     */

  incorrectArgs:
    if ((skip != 1) &&
	    TclInitRewriteEnsemble(interp, skip-1, 0, framePtr->objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
    }
    memset(varPtr, 0,
	    ((framePtr->compiledLocals + localCt)-varPtr) * sizeof(Var));
    return ProcWrongNumArgs(interp, skip);
}

/*







|







1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
    /*
     * Initialise all compiled locals to avoid problems at DeleteLocalVars.
     */

  incorrectArgs:
    if ((skip != 1) &&
	    TclInitRewriteEnsemble(interp, skip-1, 0, framePtr->objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble);
    }
    memset(varPtr, 0,
	    ((framePtr->compiledLocals + localCt)-varPtr) * sizeof(Var));
    return ProcWrongNumArgs(interp, skip);
}

/*
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
    /*
     * Invoke the commands in the procedure's body.
     */

    procPtr->refCount++;
    ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);

    TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc,
	    NULL, NULL);
    return TclNRExecuteByteCode(interp, codePtr);
}

static int
InterpProcNR2(
    void *data[],
    Tcl_Interp *interp,







|
<







1789
1790
1791
1792
1793
1794
1795
1796

1797
1798
1799
1800
1801
1802
1803
    /*
     * Invoke the commands in the procedure's body.
     */

    procPtr->refCount++;
    ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);

    TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc);

    return TclNRExecuteByteCode(interp, codePtr);
}

static int
InterpProcNR2(
    void *data[],
    Tcl_Interp *interp,
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
    extraPtr->efi.fields[0].name = "lambda";
    extraPtr->efi.fields[0].proc = NULL;
    extraPtr->efi.fields[0].clientData = lambdaPtr;
    extraPtr->cmd.clientData = &extraPtr->efi;

    result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1);
    if (result == TCL_OK) {
	TclNRAddCallback(interp, ApplyNR2, extraPtr, NULL, NULL, NULL);
	result = TclNRInterpProcCore(interp, objv[1], 2, &MakeLambdaError);
    }
    return result;
}

static int
ApplyNR2(







|







2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
    extraPtr->efi.fields[0].name = "lambda";
    extraPtr->efi.fields[0].proc = NULL;
    extraPtr->efi.fields[0].clientData = lambdaPtr;
    extraPtr->cmd.clientData = &extraPtr->efi;

    result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1);
    if (result == TCL_OK) {
	TclNRAddCallback(interp, ApplyNR2, extraPtr);
	result = TclNRInterpProcCore(interp, objv[1], 2, &MakeLambdaError);
    }
    return result;
}

static int
ApplyNR2(