Tcl Source Code

Check-in [a96d145418]
Login

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

Overview
Comment:Backdoor kludge to let traced ensemble subcommands gain access to the string command of the original, avoiding expensive reconstruction from the parsed words.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | bug-3485833
Files: files | file ages | folders
SHA1: a96d1454188b6567bd29e1e95b124741a067ab02
User & Date: dgp 2012-03-05 19:11:48
Context
2012-03-05
20:47
Better conform to Tcl style guidelines. check-in: ffd6477611 user: dgp tags: bug-3485833
19:11
Backdoor kludge to let traced ensemble subcommands gain access to the string command of the original... check-in: a96d145418 user: dgp tags: bug-3485833
2012-03-04
16:38
Patch from the cygwin folks check-in: 8dafecc06c user: jan.nijtmans tags: core-8-5-branch
2012-03-01
09:29
clarify and review code check-in: cda4203920 user: sebres tags: dgp-scan-element
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclBasic.c.

3001
3002
3003
3004
3005
3006
3007



3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024



3025
3026
3027
3028
3029
3030
3031
 *----------------------------------------------------------------------
 *
 * GetCommandSource --
 *
 *	This function returns a Tcl_Obj with the full source string for the
 *	command. This insures that traces get a correct NUL-terminated command
 *	string.



 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
GetCommandSource(
    Interp *iPtr,
    const char *command,
    int numChars,
    int objc,
    Tcl_Obj *const objv[])
{
    if (!command) {
	return Tcl_NewListObj(objc, objv);
    }
    if (command == (char *) -1) {
	command = TclGetSrcInfoForCmd(iPtr, &numChars);



    }
    return Tcl_NewStringObj(command, numChars);
}

/*
 *----------------------------------------------------------------------
 *







>
>
>

















>
>
>







3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
 *----------------------------------------------------------------------
 *
 * GetCommandSource --
 *
 *	This function returns a Tcl_Obj with the full source string for the
 *	command. This insures that traces get a correct NUL-terminated command
 *	string.
 *	If parameter 'command' is (char*)-1 it returns a pointer to the command's 
 *	source using TclGetSrcInfoForCmd. As parameter 'numChars' could be used 
 *	an ENSEMBLE_PSEUDO_COMMAND to advise call of the ensemble command.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
GetCommandSource(
    Interp *iPtr,
    const char *command,
    int numChars,
    int objc,
    Tcl_Obj *const objv[])
{
    if (!command) {
	return Tcl_NewListObj(objc, objv);
    }
    if (command == (char *) -1) {
	command = TclGetSrcInfoForCmd(iPtr, &numChars);
	if (!command) {
	    return Tcl_NewListObj(objc, objv);
	}
    }
    return Tcl_NewStringObj(command, numChars);
}

/*
 *----------------------------------------------------------------------
 *
3529
3530
3531
3532
3533
3534
3535
3536


3537
3538
3539
3540
3541
3542
3543
3544
    Tcl_Obj *const objv[],	/* An array of pointers to objects that are
				 * the words that make up the command. */
    const char *command,	/* Points to the beginning of the string
				 * representation of the command; this is used
				 * for traces. NULL if the string
				 * representation of the command is unknown is
				 * to be generated from (objc,objv), -1 if it
				 * is to be generated from bytecode


				 * source. This is only needed the traces. */
    int length,			/* Number of bytes in command; if -1, all
				 * characters up to the first null byte are
				 * used. */
    int flags)			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Only
				 * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are
				 * currently supported. */







|
>
>
|







3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
    Tcl_Obj *const objv[],	/* An array of pointers to objects that are
				 * the words that make up the command. */
    const char *command,	/* Points to the beginning of the string
				 * representation of the command; this is used
				 * for traces. NULL if the string
				 * representation of the command is unknown is
				 * to be generated from (objc,objv), -1 if it
				 * is to be generated from bytecode source,
				 * with length ENSEMBLE_PSEUDO_COMMAND it is 
				 * to be determined from the ensemble context. 
				 * This is only needed the traces. */
    int length,			/* Number of bytes in command; if -1, all
				 * characters up to the first null byte are
				 * used. */
    int flags)			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Only
				 * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are
				 * currently supported. */

Changes to generic/tclCompile.h.

839
840
841
842
843
844
845








846
847
848
849
850
851
852
    const char *op;   /* Do not call it 'operator': C++ reserved */
    const char *expected;
    union {
	int numArgs;
	int identity;
    } i;
} TclOpCmdClientData;









/*
 *----------------------------------------------------------------
 * Procedures exported by tclBasic.c to be used within the engine.
 *----------------------------------------------------------------
 */








>
>
>
>
>
>
>
>







839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
    const char *op;   /* Do not call it 'operator': C++ reserved */
    const char *expected;
    union {
	int numArgs;
	int identity;
    } i;
} TclOpCmdClientData;

/*
 * Special sentinel value for TclEvalObjvInternal's 'length' parameter to
 * cause it to retrieve command information for an ensemble from the
 * containing command (parameter 'command' is (char *)-1).
 */

#define ENSEMBLE_PSEUDO_COMMAND -2

/*
 *----------------------------------------------------------------
 * Procedures exported by tclBasic.c to be used within the engine.
 *----------------------------------------------------------------
 */

Changes to generic/tclExecute.c.

7753
7754
7755
7756
7757
7758
7759


7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772






7773




7774
7775
7776


















7777
7778
7779
7780
7781
7782
7783
 * Results:
 *	If a command is found that encloses the program counter value, a
 *	pointer to the command's source is returned and the length of the
 *	source is stored at *lengthPtr. If multiple commands resulted in code
 *	at pc, information about the closest enclosing command is returned. If
 *	no matching command is found, NULL is returned and *lengthPtr is
 *	unchanged.


 *
 * Side effects:
 *	The CmdFrame at *cfPtr is updated.
 *
 *----------------------------------------------------------------------
 */

const char *
TclGetSrcInfoForCmd(
    Interp *iPtr,
    int *lenPtr)
{
    CmdFrame *cfPtr = iPtr->cmdFramePtr;






    ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;





    return GetSrcInfoForPc((unsigned char *) cfPtr->data.tebc.pc,
	    codePtr, lenPtr);


















}

void
TclGetSrcInfoForPc(
    CmdFrame *cfPtr)
{
    ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;







>
>













>
>
>
>
>
>
|
>
>
>
>

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
 * Results:
 *	If a command is found that encloses the program counter value, a
 *	pointer to the command's source is returned and the length of the
 *	source is stored at *lengthPtr. If multiple commands resulted in code
 *	at pc, information about the closest enclosing command is returned. If
 *	no matching command is found, NULL is returned and *lengthPtr is
 *	unchanged.
 *	As input parameter '*lengthPtr' could be used an ENSEMBLE_PSEUDO_COMMAND 
 *	to advise call of the ensemble command.
 *
 * Side effects:
 *	The CmdFrame at *cfPtr is updated.
 *
 *----------------------------------------------------------------------
 */

const char *
TclGetSrcInfoForCmd(
    Interp *iPtr,
    int *lenPtr)
{
    CmdFrame *cfPtr = iPtr->cmdFramePtr;
    const char *command;
    ByteCode *codePtr;
    int len;

    if (!cfPtr)
	return NULL;
    codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;
    if (!codePtr)
	return NULL;
    if (!cfPtr->data.tebc.pc)
	return NULL;

    command = GetSrcInfoForPc((unsigned char *) cfPtr->data.tebc.pc,
	    codePtr, &len);

    /*
     * [sebres]: If ensemble call (sentinel length == ENSEMBLE_PSEUDO_COMMAND), 
     * shift string ptr to subcommand (string range -> range).
     */

    if (command && len && (lenPtr && *lenPtr == ENSEMBLE_PSEUDO_COMMAND) && codePtr->objArrayPtr) {
	Tcl_Obj *objPtr = codePtr->objArrayPtr[0];

	if (len > objPtr->length) {
	    command += objPtr->length + 1;
	    len -= objPtr->length + 1;
	}
    }

    if (lenPtr != NULL)
	*lenPtr = len;
    return command;
}

void
TclGetSrcInfoForPc(
    CmdFrame *cfPtr)
{
    ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;

Changes to generic/tclNamesp.c.

21
22
23
24
25
26
27

28
29
30
31
32
33
34
 *   [email protected]
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"


/*
 * Thread-local storage used to avoid having a global lock on data that is not
 * limited to a single interpreter.
 */

typedef struct ThreadSpecificData {







>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 *   [email protected]
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"

/*
 * Thread-local storage used to avoid having a global lock on data that is not
 * limited to a single interpreter.
 */

typedef struct ThreadSpecificData {
6225
6226
6227
6228
6229
6230
6231


6232
6233
6234

6235
6236
6237
6238
6239
6240
6241
6242
	tempObjv = (Tcl_Obj **) TclStackAlloc(interp,
		(int) sizeof(Tcl_Obj *) * (objc - 2 + prefixObjc));
	memcpy(tempObjv, prefixObjv, sizeof(Tcl_Obj *) * prefixObjc);
	memcpy(tempObjv+prefixObjc, objv+2, sizeof(Tcl_Obj *) * (objc-2));

	/*
	 * Hand off to the target command.


	 */

	result = Tcl_EvalObjv(interp, objc-2+prefixObjc, tempObjv,

		TCL_EVAL_INVOKE);

	/*
	 * Clean up.
	 */

	TclStackFree(interp, tempObjv);
	Tcl_DecrRefCount(copyObj);







>
>


|
>
|







6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
	tempObjv = (Tcl_Obj **) TclStackAlloc(interp,
		(int) sizeof(Tcl_Obj *) * (objc - 2 + prefixObjc));
	memcpy(tempObjv, prefixObjv, sizeof(Tcl_Obj *) * prefixObjc);
	memcpy(tempObjv+prefixObjc, objv+2, sizeof(Tcl_Obj *) * (objc-2));

	/*
	 * Hand off to the target command.
	 * [sebres] call from ensemble using ENSEMBLE_PSEUDO_COMMAND to
	 * retrive subcommand from main ensemble.
	 */

	result = TclEvalObjvInternal(interp, objc-2+prefixObjc, tempObjv,
		/* call from TEBC, TclGetSrcInfoForCmd sentinel */(char *) -1, 
		ENSEMBLE_PSEUDO_COMMAND, TCL_EVAL_INVOKE);

	/*
	 * Clean up.
	 */

	TclStackFree(interp, tempObjv);
	Tcl_DecrRefCount(copyObj);