Tcl Source Code

Check-in [f727d678da]
Login

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

Overview
Comment:Merge to feature branch
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dkf-notifier-poll
Files: files | file ages | folders
SHA1: f727d678daa2b275b5f6a1da1354cfec656a2f73
User & Date: dkf 2011-04-19 08:19:03
Context
2011-04-23
12:24
Merge to feature branch check-in: 31660e19ea user: dkf tags: dkf-notifier-poll
2011-04-19
08:19
Merge to feature branch check-in: f727d678da user: dkf tags: dkf-notifier-poll
08:04
This time, I'll try to get it right! check-in: ef35e2c747 user: dkf tags: trunk
2011-04-16
14:21
Merge to feature branch check-in: 5a59a01655 user: dkf tags: dkf-notifier-poll
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.




















1
2
3
4
5
6
7



















2011-04-16  Donal K. Fellows  <[email protected]>

	* generic/tclFCmd.c (TclFileAttrsCmd): Add comments to make this code
	easier to understand. Added a panic to handle the case where the VFS
	layer does something odd.

2011-04-13  Don Porter  <[email protected]>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2011-04-18  Don Porter  <[email protected]>

	* generic/tclCmdIL.c:	Use ListRepPtr(.) and other cleanup.
	* generic/tclConfig.c:
	* generic/tclListObj.c:

	* generic/tclInt.h:	Define and use macros that test whether
	* generic/tclBasic.c:	a Tcl list value is canonical.
	* generic/tclUtil.c:

2011-04-18  Donal K. Fellows  <[email protected]>

	* doc/dict.n: [Bug 3288696]: Command summary was confusingly wrong
	when it came to [dict filter] with a 'value' filter.

2011-04-18  Jan Nijtmans  <[email protected]>

	* generic/tcl.h: [Bug 3288345]: Fix wrong Tcl_StatBuf used on MinGW.

2011-04-16  Donal K. Fellows  <[email protected]>

	* generic/tclFCmd.c (TclFileAttrsCmd): Add comments to make this code
	easier to understand. Added a panic to handle the case where the VFS
	layer does something odd.

2011-04-13  Don Porter  <[email protected]>

Changes to doc/dict.n.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
argument after the rule selection word is a two-element list.  If the
\fIscript\fR returns with a condition of \fBTCL_BREAK\fR, no further
key/value pairs are considered for inclusion in the resulting
dictionary, and a condition of \fBTCL_CONTINUE\fR is equivalent to a false
result. The key/value pairs are tested in the order in which the keys
were inserted into the dictionary.
.TP
\fBdict filter \fIdictionaryValue \fBvalue \fIglobPattern\fR
.VS 8.6
The value rule only matches those key/value pairs whose values match any
of the given patterns (in the style of \fBstring match\fR.)
.VE 8.6
.RE
.TP
\fBdict for {\fIkeyVar valueVar\fB} \fIdictionaryValue body\fR







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
argument after the rule selection word is a two-element list.  If the
\fIscript\fR returns with a condition of \fBTCL_BREAK\fR, no further
key/value pairs are considered for inclusion in the resulting
dictionary, and a condition of \fBTCL_CONTINUE\fR is equivalent to a false
result. The key/value pairs are tested in the order in which the keys
were inserted into the dictionary.
.TP
\fBdict filter \fIdictionaryValue \fBvalue \fR?\fIglobPattern ...\fR?
.VS 8.6
The value rule only matches those key/value pairs whose values match any
of the given patterns (in the style of \fBstring match\fR.)
.VE 8.6
.RE
.TP
\fBdict for {\fIkeyVar valueVar\fB} \fIdictionaryValue body\fR

Changes to generic/tcl.h.

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396




397
398
399
400
401
402
403
 *
 * Note on converting between Tcl_WideInt and strings. This implementation (in
 * tclObj.c) depends on the function
 * sprintf(...,"%" TCL_LL_MODIFIER "d",...).
 */

#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
#   if defined(__GNUC__)
#      define TCL_WIDE_INT_TYPE long long
#      if defined(__WIN32__) && !defined(__CYGWIN__)
#         define TCL_LL_MODIFIER        "I64"
#      else
#         define TCL_LL_MODIFIER	"ll"
#      endif
typedef struct stat	Tcl_StatBuf;
#   elif defined(__WIN32__)
#      define TCL_WIDE_INT_TYPE __int64
#      ifdef __BORLANDC__
typedef struct stati64 Tcl_StatBuf;
#         define TCL_LL_MODIFIER	"L"
#      else /* __BORLANDC__ */
#         if _MSC_VER < 1400 || !defined(_M_IX86)
typedef struct _stati64	Tcl_StatBuf;
#         else
typedef struct _stat64	Tcl_StatBuf;
#         endif /* _MSC_VER < 1400 */
#         define TCL_LL_MODIFIER	"I64"
#      endif /* __BORLANDC__ */




#   else /* __WIN32__ */
/*
 * Don't know what platform it is and configure hasn't discovered what is
 * going on for us. Try to guess...
 */
#      ifdef NO_LIMITS_H
#	  error please define either TCL_WIDE_INT_TYPE or TCL_WIDE_INT_IS_LONG







|
<
<
<
<
<
<
<
<





|






>
>
>
>







369
370
371
372
373
374
375
376








377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
 *
 * Note on converting between Tcl_WideInt and strings. This implementation (in
 * tclObj.c) depends on the function
 * sprintf(...,"%" TCL_LL_MODIFIER "d",...).
 */

#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
#   if defined(__WIN32__)








#      define TCL_WIDE_INT_TYPE __int64
#      ifdef __BORLANDC__
typedef struct stati64 Tcl_StatBuf;
#         define TCL_LL_MODIFIER	"L"
#      else /* __BORLANDC__ */
#         if (defined(_MSC_VER) && (_MSC_VER < 1400)) || !defined(_M_IX86) || defined(__GNUC__)
typedef struct _stati64	Tcl_StatBuf;
#         else
typedef struct _stat64	Tcl_StatBuf;
#         endif /* _MSC_VER < 1400 */
#         define TCL_LL_MODIFIER	"I64"
#      endif /* __BORLANDC__ */
#   elif defined(__GNUC__)
#      define TCL_WIDE_INT_TYPE long long
#      define TCL_LL_MODIFIER	"ll"
typedef struct stat	Tcl_StatBuf;
#   else /* __WIN32__ */
/*
 * Don't know what platform it is and configure hasn't discovered what is
 * going on for us. Try to guess...
 */
#      ifdef NO_LIMITS_H
#	  error please define either TCL_WIDE_INT_TYPE or TCL_WIDE_INT_IS_LONG

Changes to generic/tclBasic.c.

5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
    /*
     * An object which either has no string rep or else is a canonical list is
     * guaranteed to have been generated dynamically: bail out, this cannot
     * have a usable absolute location. _Do not touch_ the information the set
     * up by the caller. It knows better than us.
     */

    if ((!obj->bytes) || ((obj->typePtr == &tclListType) &&
	    ((List *) obj->internalRep.twoPtrValue.ptr1)->canonicalFlag)) {
	return;
    }

    /*
     * First look for location information recorded in the argument
     * stack. That is nearest.
     */







|
<







5713
5714
5715
5716
5717
5718
5719
5720

5721
5722
5723
5724
5725
5726
5727
    /*
     * An object which either has no string rep or else is a canonical list is
     * guaranteed to have been generated dynamically: bail out, this cannot
     * have a usable absolute location. _Do not touch_ the information the set
     * up by the caller. It knows better than us.
     */

    if ((obj->bytes == NULL) || TclListObjIsCanonical(obj)) {

	return;
    }

    /*
     * First look for location information recorded in the argument
     * stack. That is nearest.
     */
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
				 * evaluation of the script. Supported values
				 * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
    const CmdFrame *invoker,	/* Frame of the command doing the eval. */
    int word)			/* Index of the word which is in objPtr. */
{
    Interp *iPtr = (Interp *) interp;
    int result;
    List *listRepPtr = objPtr->internalRep.twoPtrValue.ptr1;

    /*
     * This function consists of three independent blocks for: direct
     * evaluation of canonical lists, compileation and bytecode execution and
     * finally direct evaluation. Precisely one of these blocks will be run.
     */

    if ((objPtr->typePtr == &tclListType) &&		/* is a list */
	    ((objPtr->bytes == NULL ||			/* no string rep */
		    listRepPtr->canonicalFlag))) {	/* or is canonical */
	Tcl_Obj *listPtr = objPtr;
	CmdFrame *eoFramePtr = NULL;
	int objc;
	Tcl_Obj **objv;

	/*
	 * Pure List Optimization (no string representation). In this case, we







<







<
<
|







5892
5893
5894
5895
5896
5897
5898

5899
5900
5901
5902
5903
5904
5905


5906
5907
5908
5909
5910
5911
5912
5913
				 * evaluation of the script. Supported values
				 * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
    const CmdFrame *invoker,	/* Frame of the command doing the eval. */
    int word)			/* Index of the word which is in objPtr. */
{
    Interp *iPtr = (Interp *) interp;
    int result;


    /*
     * This function consists of three independent blocks for: direct
     * evaluation of canonical lists, compileation and bytecode execution and
     * finally direct evaluation. Precisely one of these blocks will be run.
     */



    if (TclListObjIsCanonical(objPtr)) {
	Tcl_Obj *listPtr = objPtr;
	CmdFrame *eoFramePtr = NULL;
	int objc;
	Tcl_Obj **objv;

	/*
	 * Pure List Optimization (no string representation). In this case, we

Changes to generic/tclCmdIL.c.

1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
InfoLoadedCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *interpName;
    int result;

    if ((objc != 1) && (objc != 2)) {
	Tcl_WrongNumArgs(interp, 1, objv, "?interp?");
	return TCL_ERROR;
    }

    if (objc == 1) {		/* Get loaded pkgs in all interpreters. */
	interpName = NULL;
    } else {			/* Get pkgs just in specified interp. */
	interpName = TclGetString(objv[1]);
    }
    result = TclGetLoadedPackages(interp, interpName);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoNameOfExecutableCmd --
 *







<











|
<







1662
1663
1664
1665
1666
1667
1668

1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680

1681
1682
1683
1684
1685
1686
1687
InfoLoadedCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *interpName;


    if ((objc != 1) && (objc != 2)) {
	Tcl_WrongNumArgs(interp, 1, objv, "?interp?");
	return TCL_ERROR;
    }

    if (objc == 1) {		/* Get loaded pkgs in all interpreters. */
	interpName = NULL;
    } else {			/* Get pkgs just in specified interp. */
	interpName = TclGetString(objv[1]);
    }
    return TclGetLoadedPackages(interp, interpName);

}

/*
 *----------------------------------------------------------------------
 *
 * InfoNameOfExecutableCmd --
 *
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512

    result = TclListObjGetElements(interp, objv[1], &listLen, &elemPtrs);
    if (result != TCL_OK) {
	return result;
    }

    if (Tcl_IsShared(objv[1]) ||
	    (((List *) objv[1]->internalRep.twoPtrValue.ptr1)->refCount > 1)) {
	Tcl_SetObjResult(interp, Tcl_NewListObj(last - first + 1,
		&elemPtrs[first]));
    } else {
	/*
	 * In-place is possible.
	 */








|







2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510

    result = TclListObjGetElements(interp, objv[1], &listLen, &elemPtrs);
    if (result != TCL_OK) {
	return result;
    }

    if (Tcl_IsShared(objv[1]) ||
	    ((ListRepPtr(objv[1])->refCount > 1))) {
	Tcl_SetObjResult(interp, Tcl_NewListObj(last - first + 1,
		&elemPtrs[first]));
    } else {
	/*
	 * In-place is possible.
	 */

2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
    /*
     * Get an empty list object that is allocated large enough to hold each
     * init value elementCount times.
     */

    listPtr = Tcl_NewListObj(totalElems, NULL);
    if (totalElems) {
	List *listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;

	listRepPtr->elemCount = elementCount*objc;
	dataArray = &listRepPtr->elements;
    }

    /*
     * Set the elements. Note that we handle the common degenerate case of a







|







2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
    /*
     * Get an empty list object that is allocated large enough to hold each
     * init value elementCount times.
     */

    listPtr = Tcl_NewListObj(totalElems, NULL);
    if (totalElems) {
	List *listRepPtr = ListRepPtr(listPtr);

	listRepPtr->elemCount = elementCount*objc;
	dataArray = &listRepPtr->elements;
    }

    /*
     * Set the elements. Note that we handle the common degenerate case of a
2792
2793
2794
2795
2796
2797
2798
2799

2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
     */

    if (!elemc) {
	Tcl_SetObjResult(interp, objv[1]);
	return TCL_OK;
    }

    if (Tcl_IsShared(objv[1])) {

	Tcl_Obj *resultObj, **dataArray;
	List *listPtr;

    makeNewReversedList:
	resultObj = Tcl_NewListObj(elemc, NULL);
	listPtr = resultObj->internalRep.twoPtrValue.ptr1;
	listPtr->elemCount = elemc;
	dataArray = &listPtr->elements;

	for (i=0,j=elemc-1 ; i<elemc ; i++,j--) {
	    dataArray[j] = elemv[i];
	    Tcl_IncrRefCount(elemv[i]);
	}

	Tcl_SetObjResult(interp, resultObj);
    } else {
	/*
	 * It is theoretically possible for a list object to have a shared
	 * internal representation, but be an unshared object. Check for this
	 * and use the "shared" code if we have that problem. [Bug 1675044]
	 */

	if (((List *) objv[1]->internalRep.twoPtrValue.ptr1)->refCount > 1) {
	    goto makeNewReversedList;
	}

	/*
	 * Not shared, so swap "in place". This relies on Tcl_LOGE above
	 * returning a pointer to the live array of Tcl_Obj values.
	 */

	for (i=0,j=elemc-1 ; i<j ; i++,j--) {







|
>

|

<

|
|
|








<
<
<
<
<
<
<
<
<







2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801

2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813









2814
2815
2816
2817
2818
2819
2820
     */

    if (!elemc) {
	Tcl_SetObjResult(interp, objv[1]);
	return TCL_OK;
    }

    if (Tcl_IsShared(objv[1])
	    || (ListRepPtr(objv[1])->refCount > 1)) {	/* Bug 1675044 */
	Tcl_Obj *resultObj, **dataArray;
	List *listRepPtr;


	resultObj = Tcl_NewListObj(elemc, NULL);
	listRepPtr = ListRepPtr(resultObj);
	listRepPtr->elemCount = elemc;
	dataArray = &listRepPtr->elements;

	for (i=0,j=elemc-1 ; i<elemc ; i++,j--) {
	    dataArray[j] = elemv[i];
	    Tcl_IncrRefCount(elemv[i]);
	}

	Tcl_SetObjResult(interp, resultObj);
    } else {










	/*
	 * Not shared, so swap "in place". This relies on Tcl_LOGE above
	 * returning a pointer to the live array of Tcl_Obj values.
	 */

	for (i=0,j=elemc-1 ; i<j ; i++,j--) {
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
     */

    if (sortInfo.resultCode == TCL_OK) {
	List *listRepPtr;
	Tcl_Obj **newArray, *objPtr;

	resultPtr = Tcl_NewListObj(sortInfo.numElements * groupSize, NULL);
	listRepPtr = resultPtr->internalRep.twoPtrValue.ptr1;
	newArray = &listRepPtr->elements;
	if (group) {
	    for (i=0; elementPtr!=NULL ; elementPtr=elementPtr->nextPtr) {
		idx = elementPtr->payload.index;
		for (j = 0; j < groupSize; j++) {
		    if (indices) {
			objPtr = Tcl_NewIntObj(idx + j - groupOffset);







|







3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
     */

    if (sortInfo.resultCode == TCL_OK) {
	List *listRepPtr;
	Tcl_Obj **newArray, *objPtr;

	resultPtr = Tcl_NewListObj(sortInfo.numElements * groupSize, NULL);
	listRepPtr = ListRepPtr(resultPtr);
	newArray = &listRepPtr->elements;
	if (group) {
	    for (i=0; elementPtr!=NULL ; elementPtr=elementPtr->nextPtr) {
		idx = elementPtr->payload.index;
		for (j = 0; j < groupSize; j++) {
		    if (indices) {
			objPtr = Tcl_NewIntObj(idx + j - groupOffset);

Changes to generic/tclConfig.c.

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
	    Tcl_SetResult(interp, "insufficient memory to create list",
		    TCL_STATIC);
	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	    return TCL_ERROR;
	}

	if (n) {
	    List *listRepPtr = (List *)
		    listPtr->internalRep.twoPtrValue.ptr1;
	    Tcl_DictSearch s;
	    Tcl_Obj *key, **vals;
	    int done, i = 0;

	    listRepPtr->elemCount = n;
	    vals = &listRepPtr->elements;








|
<







273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
	    Tcl_SetResult(interp, "insufficient memory to create list",
		    TCL_STATIC);
	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	    return TCL_ERROR;
	}

	if (n) {
	    List *listRepPtr = ListRepPtr(listPtr);

	    Tcl_DictSearch s;
	    Tcl_Obj *key, **vals;
	    int done, i = 0;

	    listRepPtr->elemCount = n;
	    vals = &listRepPtr->elements;

Changes to generic/tclInt.h.

2451
2452
2453
2454
2455
2456
2457



2458
2459
2460
2461
2462
2463
2464
2465
2466
2467



2468
2469
2470
2471
2472
2473
2474
#define ListObjGetElements(listPtr, objc, objv) \
    ((objv) = &(ListRepPtr(listPtr)->elements), \
     (objc) = ListRepPtr(listPtr)->elemCount)

#define ListObjLength(listPtr, len) \
    ((len) = ListRepPtr(listPtr)->elemCount)




#define TclListObjGetElements(interp, listPtr, objcPtr, objvPtr) \
    (((listPtr)->typePtr == &tclListType) \
	    ? ((ListObjGetElements((listPtr), *(objcPtr), *(objvPtr))), TCL_OK)\
	    : Tcl_ListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)))

#define TclListObjLength(interp, listPtr, lenPtr) \
    (((listPtr)->typePtr == &tclListType) \
	    ? ((ListObjLength((listPtr), *(lenPtr))), TCL_OK)\
	    : Tcl_ListObjLength((interp), (listPtr), (lenPtr)))




/*
 * Macros providing a faster path to integers: Tcl_GetLongFromObj everywhere,
 * Tcl_GetIntFromObj and TclGetIntForIndex on platforms where longs are ints.
 *
 * WARNING: these macros eval their args more than once.
 */








>
>
>










>
>
>







2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
#define ListObjGetElements(listPtr, objc, objv) \
    ((objv) = &(ListRepPtr(listPtr)->elements), \
     (objc) = ListRepPtr(listPtr)->elemCount)

#define ListObjLength(listPtr, len) \
    ((len) = ListRepPtr(listPtr)->elemCount)

#define ListObjIsCanonical(listPtr) \
    (((listPtr)->bytes == NULL) || ListRepPtr(listPtr)->canonicalFlag)

#define TclListObjGetElements(interp, listPtr, objcPtr, objvPtr) \
    (((listPtr)->typePtr == &tclListType) \
	    ? ((ListObjGetElements((listPtr), *(objcPtr), *(objvPtr))), TCL_OK)\
	    : Tcl_ListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)))

#define TclListObjLength(interp, listPtr, lenPtr) \
    (((listPtr)->typePtr == &tclListType) \
	    ? ((ListObjLength((listPtr), *(lenPtr))), TCL_OK)\
	    : Tcl_ListObjLength((interp), (listPtr), (lenPtr)))

#define TclListObjIsCanonical(listPtr) \
    (((listPtr)->typePtr == &tclListType) ? ListObjIsCanonical((listPtr)) : 0)

/*
 * Macros providing a faster path to integers: Tcl_GetLongFromObj everywhere,
 * Tcl_GetIntFromObj and TclGetIntForIndex on platforms where longs are ints.
 *
 * WARNING: these macros eval their args more than once.
 */

Changes to generic/tclListObj.c.

442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
	}

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }
    listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
    *objcPtr = listRepPtr->elemCount;
    *objvPtr = &listRepPtr->elements;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
	}

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }
    listRepPtr = ListRepPtr(listPtr);
    *objcPtr = listRepPtr->elemCount;
    *objvPtr = &listRepPtr->elements;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
    numElems = listRepPtr->elemCount;
    numRequired = numElems + 1 ;

    /*
     * If there is no room in the current array of element pointers, allocate
     * a new, larger array and copy the pointers to it. If the List struct is
     * shared, allocate a new one.







|







560
561
562
563
564
565
566
567
568
569
570
571
572
573
574

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);
    numElems = listRepPtr->elemCount;
    numRequired = numElems + 1 ;

    /*
     * If there is no room in the current array of element pointers, allocate
     * a new, larger array and copy the pointers to it. If the List struct is
     * shared, allocate a new one.
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
    if ((index < 0) || (index >= listRepPtr->elemCount)) {
	*objPtrPtr = NULL;
    } else {
	*objPtrPtr = (&listRepPtr->elements)[index];
    }

    return TCL_OK;







|







670
671
672
673
674
675
676
677
678
679
680
681
682
683
684

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);
    if ((index < 0) || (index >= listRepPtr->elemCount)) {
	*objPtrPtr = NULL;
    } else {
	*objPtrPtr = (&listRepPtr->elements)[index];
    }

    return TCL_OK;
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
    *intPtr = listRepPtr->elemCount;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|







725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);
    *intPtr = listRepPtr->elemCount;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
     * Note that when count == 0 and objc == 0, this routine is logically a
     * no-op, removing and adding no elements to the list. However, by flowing
     * through this routine anyway, we get the important side effect that the
     * resulting listPtr is a list in canoncial form. This is important.
     * Resist any temptation to optimize this case.
     */

    listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
    elemPtrs = &listRepPtr->elements;
    numElems = listRepPtr->elemCount;

    if (first < 0) {
	first = 0;
    }
    if (first >= numElems) {







|







812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
     * Note that when count == 0 and objc == 0, this routine is logically a
     * no-op, removing and adding no elements to the list. However, by flowing
     * through this routine anyway, we get the important side effect that the
     * resulting listPtr is a list in canoncial form. This is important.
     * Resist any temptation to optimize this case.
     */

    listRepPtr = ListRepPtr(listPtr);
    elemPtrs = &listRepPtr->elements;
    numElems = listRepPtr->elemCount;

    if (first < 0) {
	first = 0;
    }
    if (first >= numElems) {
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
	}
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
    elemCount = listRepPtr->elemCount;
    elemPtrs = &listRepPtr->elements;

    /*
     * Ensure that the index is in bounds.
     */








|







1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
	}
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);
    elemCount = listRepPtr->elemCount;
    elemPtrs = &listRepPtr->elements;

    /*
     * Ensure that the index is in bounds.
     */

1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
 *----------------------------------------------------------------------
 */

static void
FreeListInternalRep(
    Tcl_Obj *listPtr)		/* List object with internal rep to free. */
{
    register List *listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
    register Tcl_Obj **elemPtrs = &listRepPtr->elements;
    register Tcl_Obj *objPtr;
    int numElems = listRepPtr->elemCount;
    int i;

    if (--listRepPtr->refCount <= 0) {
	for (i = 0;  i < numElems;  i++) {







|







1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
 *----------------------------------------------------------------------
 */

static void
FreeListInternalRep(
    Tcl_Obj *listPtr)		/* List object with internal rep to free. */
{
    register List *listRepPtr = ListRepPtr(listPtr);
    register Tcl_Obj **elemPtrs = &listRepPtr->elements;
    register Tcl_Obj *objPtr;
    int numElems = listRepPtr->elemCount;
    int i;

    if (--listRepPtr->refCount <= 0) {
	for (i = 0;  i < numElems;  i++) {
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
 */

static void
DupListInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    List *listRepPtr = srcPtr->internalRep.twoPtrValue.ptr1;

    listRepPtr->refCount++;
    copyPtr->internalRep.twoPtrValue.ptr1 = listRepPtr;
    copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
    copyPtr->typePtr = &tclListType;
}








|







1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
 */

static void
DupListInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    List *listRepPtr = ListRepPtr(srcPtr);

    listRepPtr->refCount++;
    copyPtr->internalRep.twoPtrValue.ptr1 = listRepPtr;
    copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
    copyPtr->typePtr = &tclListType;
}

1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883

static void
UpdateStringOfList(
    Tcl_Obj *listPtr)		/* List object with string rep to update. */
{
#   define LOCAL_SIZE 20
    int localFlags[LOCAL_SIZE], *flagPtr;
    List *listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
    int numElems = listRepPtr->elemCount;
    register int i;
    const char *elem;
    char *dst;
    int length;
    Tcl_Obj **elemPtrs;








|







1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883

static void
UpdateStringOfList(
    Tcl_Obj *listPtr)		/* List object with string rep to update. */
{
#   define LOCAL_SIZE 20
    int localFlags[LOCAL_SIZE], *flagPtr;
    List *listRepPtr = ListRepPtr(listPtr);
    int numElems = listRepPtr->elemCount;
    register int i;
    const char *elem;
    char *dst;
    int length;
    Tcl_Obj **elemPtrs;

Changes to generic/tclUtil.c.

1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
    /*
     * Check first to see if all the items are of list type or empty. If so,
     * we will concat them together as lists, and return a list object. This
     * is only valid when the lists are in canonical form.
     */

    for (i = 0;  i < objc;  i++) {
	List *listRepPtr;

	objPtr = objv[i];
	if (objPtr->typePtr != &tclListType) {
	    TclGetString(objPtr);
	    if (objPtr->length) {
		break;
	    } else {
		continue;
	    }
	}
	listRepPtr = objPtr->internalRep.twoPtrValue.ptr1;
	if (objPtr->bytes != NULL && !listRepPtr->canonicalFlag) {

	    break;
	}
    }
    if (i == objc) {
	Tcl_Obj **listv;
	int listc;

	resPtr = NULL;
	for (i = 0;  i < objc;  i++) {
	    /*
	     * Tcl_ListObjAppendList could be used here, but this saves us a
	     * bit of type checking (since we've already done it). Use of
	     * INT_MAX tells us to always put the new stuff on the end. It
	     * will be set right in Tcl_ListObjReplace.
	     * Note that all objs at this point are either lists or have an
	     * empty string rep.
	     */

	    objPtr = objv[i];
	    if (objPtr->bytes && !objPtr->length) {
		continue;
	    }
	    TclListObjGetElements(NULL, objPtr, &listc, &listv);
	    if (listc) {
		if (resPtr) {
		    Tcl_ListObjReplace(NULL, resPtr, INT_MAX, 0, listc, listv);
		} else {







|


|
<
<
<
<
|
|
<
<
|
>



















|







1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210




1211
1212


1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
    /*
     * Check first to see if all the items are of list type or empty. If so,
     * we will concat them together as lists, and return a list object. This
     * is only valid when the lists are in canonical form.
     */

    for (i = 0;  i < objc;  i++) {
	int length;

	objPtr = objv[i];
	if (TclListObjIsCanonical(objPtr)) {




	    continue;
	}


	Tcl_GetStringFromObj(objPtr, &length);
	if (length > 0) {
	    break;
	}
    }
    if (i == objc) {
	Tcl_Obj **listv;
	int listc;

	resPtr = NULL;
	for (i = 0;  i < objc;  i++) {
	    /*
	     * Tcl_ListObjAppendList could be used here, but this saves us a
	     * bit of type checking (since we've already done it). Use of
	     * INT_MAX tells us to always put the new stuff on the end. It
	     * will be set right in Tcl_ListObjReplace.
	     * Note that all objs at this point are either lists or have an
	     * empty string rep.
	     */

	    objPtr = objv[i];
	    if (objPtr->bytes && objPtr->length == 0) {
		continue;
	    }
	    TclListObjGetElements(NULL, objPtr, &listc, &listv);
	    if (listc) {
		if (resPtr) {
		    Tcl_ListObjReplace(NULL, resPtr, INT_MAX, 0, listc, listv);
		} else {