Tcl Source Code

Changes On Branch spjuth-listhole
Login

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

Changes In Branch spjuth-listhole Excluding Merge-Ins

This is equivalent to a diff from e9aa33ca4b to ae0b307a5a

2012-08-25
10:11
[Bug 3561330]: Use the correct full name of March in Ukrainian. check-in: 7fd43f120a user: dkf tags: trunk
2012-08-24
21:36
Merge from trunk check-in: 2ef46287b2 user: pspjuth tags: spjuth-macro (unpublished)
21:32
Fixed some minor stuff after merge. List-with-holes is no longer working after the massive core refa... Leaf check-in: ae0b307a5a user: pspjuth tags: spjuth-listhole (unpublished)
20:58
Merge from trunk check-in: 466b2dceb5 user: pspjuth tags: spjuth-listhole (unpublished)
06:33
make sure that extensions which might still use TclWinNToHS, now use ntohs directly. check-in: e9aa33ca4b user: jan.nijtmans tags: trunk
06:29
make sure that extensions which might still use TclWinNToHS, now use ntohs directly. check-in: f66713fc65 user: jan.nijtmans tags: core-8-5-branch
2012-08-23
20:18
small wrapper for TclWinNToHs, for change in calling convention check-in: 65be206be4 user: jan.nijtmans tags: trunk

Changes to generic/tclBasic.c.

233
234
235
236
237
238
239

240
241
242
243
244
245
246
    {"lrange",		Tcl_LrangeObjCmd,	TclCompileLrangeCmd,	NULL,	1},
    {"lrepeat",		Tcl_LrepeatObjCmd,	NULL,			NULL,	1},
    {"lreplace",	Tcl_LreplaceObjCmd,	TclCompileLreplaceCmd,	NULL,	1},
    {"lreverse",	Tcl_LreverseObjCmd,	NULL,			NULL,	1},
    {"lsearch",		Tcl_LsearchObjCmd,	NULL,			NULL,	1},
    {"lset",		Tcl_LsetObjCmd,		TclCompileLsetCmd,	NULL,	1},
    {"lsort",		Tcl_LsortObjCmd,	NULL,			NULL,	1},

    {"package",		Tcl_PackageObjCmd,	NULL,			NULL,	1},
    {"proc",		Tcl_ProcObjCmd,		NULL,			NULL,	1},
    {"regexp",		Tcl_RegexpObjCmd,	TclCompileRegexpCmd,	NULL,	1},
    {"regsub",		Tcl_RegsubObjCmd,	NULL,			NULL,	1},
    {"rename",		Tcl_RenameObjCmd,	NULL,			NULL,	1},
    {"return",		Tcl_ReturnObjCmd,	TclCompileReturnCmd,	NULL,	1},
    {"scan",		Tcl_ScanObjCmd,		NULL,			NULL,	1},







>







233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
    {"lrange",		Tcl_LrangeObjCmd,	TclCompileLrangeCmd,	NULL,	1},
    {"lrepeat",		Tcl_LrepeatObjCmd,	NULL,			NULL,	1},
    {"lreplace",	Tcl_LreplaceObjCmd,	TclCompileLreplaceCmd,	NULL,	1},
    {"lreverse",	Tcl_LreverseObjCmd,	NULL,			NULL,	1},
    {"lsearch",		Tcl_LsearchObjCmd,	NULL,			NULL,	1},
    {"lset",		Tcl_LsetObjCmd,		TclCompileLsetCmd,	NULL,	1},
    {"lsort",		Tcl_LsortObjCmd,	NULL,			NULL,	1},
    {"lunset",		Tcl_LunsetObjCmd,	NULL,			NULL,	1},
    {"package",		Tcl_PackageObjCmd,	NULL,			NULL,	1},
    {"proc",		Tcl_ProcObjCmd,		NULL,			NULL,	1},
    {"regexp",		Tcl_RegexpObjCmd,	TclCompileRegexpCmd,	NULL,	1},
    {"regsub",		Tcl_RegsubObjCmd,	NULL,			NULL,	1},
    {"rename",		Tcl_RenameObjCmd,	NULL,			NULL,	1},
    {"return",		Tcl_ReturnObjCmd,	TclCompileReturnCmd,	NULL,	1},
    {"scan",		Tcl_ScanObjCmd,		NULL,			NULL,	1},

Changes to generic/tclCmdIL.c.

3566
3567
3568
3569
3570
3571
3572




















































































3573
3574
3575
3576
3577
3578
3579

    if (objc == 4) {
	finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]);
    } else {
	finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
		objv[objc-1]);
    }





















































































    /*
     * If substitution has failed, bail out.
     */

    if (finalValuePtr == NULL) {
	return TCL_ERROR;







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







3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663

    if (objc == 4) {
	finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]);
    } else {
	finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
		objv[objc-1]);
    }

    /*
     * If substitution has failed, bail out.
     */

    if (finalValuePtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Finally, update the variable so that traces fire.
     */

    listPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, finalValuePtr,
	    TCL_LEAVE_ERR_MSG);
    Tcl_DecrRefCount(finalValuePtr);
    if (listPtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Return the new value of the variable as the interpreter result.
     */

    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LunsetObjCmd --
 *
 *	This procedure is invoked to process the "lunset" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LunsetObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tcl_Obj *listPtr;		/* Pointer to the list being altered. */
    Tcl_Obj *finalValuePtr;	/* Value finally assigned to the variable. */

    /*
     * Check parameter count.
     */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "listVar index ?index...?");
	return TCL_ERROR;
    }

    /*
     * Look up the list variable's value.
     */

    listPtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL,
	    TCL_LEAVE_ERR_MSG);
    if (listPtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Substitute the value in the value. Return either the value or else an
     * unshared copy of it.
     */

    if (objc == 3) {
	finalValuePtr = TclLsetList(interp, listPtr, objv[2], NULL);
    } else {
	finalValuePtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);
    }

    /*
     * If substitution has failed, bail out.
     */

    if (finalValuePtr == NULL) {
	return TCL_ERROR;

Changes to generic/tclInt.h.

2433
2434
2435
2436
2437
2438
2439

2440
2441
2442
2443
2444
2445
2446
    int refCount;
    int maxElemCount;		/* Total number of element array slots. */
    int elemCount;		/* Current number of list elements. */
    int canonicalFlag;		/* Set if the string representation was
				 * derived from the list representation. May
				 * be ignored if there is no string rep at
				 * all.*/

    Tcl_Obj *elements;		/* First list element; the struct is grown to
				 * accomodate all elements. */
} List;

#define LIST_MAX \
	(1 + (int)(((size_t)UINT_MAX - sizeof(List))/sizeof(Tcl_Obj *)))
#define LIST_SIZE(numElems) \







>







2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
    int refCount;
    int maxElemCount;		/* Total number of element array slots. */
    int elemCount;		/* Current number of list elements. */
    int canonicalFlag;		/* Set if the string representation was
				 * derived from the list representation. May
				 * be ignored if there is no string rep at
				 * all.*/
    char *holes;
    Tcl_Obj *elements;		/* First list element; the struct is grown to
				 * accomodate all elements. */
} List;

#define LIST_MAX \
	(1 + (int)(((size_t)UINT_MAX - sizeof(List))/sizeof(Tcl_Obj *)))
#define LIST_SIZE(numElems) \
3361
3362
3363
3364
3365
3366
3367



3368
3369
3370
3371
3372
3373
3374
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsortObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,



			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitNamespaceCmd(Tcl_Interp *interp);
MODULE_SCOPE int	TclNamespaceEnsembleCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_OpenObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,







>
>
>







3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsortObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LunsetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitNamespaceCmd(Tcl_Interp *interp);
MODULE_SCOPE int	TclNamespaceEnsembleCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_OpenObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,

Changes to generic/tclListObj.c.

68
69
70
71
72
73
74
































75
76
77
78
79
80
81
 *
 * Side effects:
 *	The ref counts of the elements in objv are incremented since the
 *	resulting list now refers to them.
 *
 *----------------------------------------------------------------------
 */

































static List *
NewListIntRep(
    int objc,
    Tcl_Obj *const objv[],
    int p)
{







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







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 *
 * Side effects:
 *	The ref counts of the elements in objv are incremented since the
 *	resulting list now refers to them.
 *
 *----------------------------------------------------------------------
 */

static void
SetMaxElemCount(
    List *listRepPtr,
    int newSize)
{
    int t;

    if (listRepPtr->holes != NULL) {
	listRepPtr->holes =
		(char *) ckrealloc(listRepPtr->holes, sizeof(char) * newSize);
	for (t = listRepPtr->maxElemCount; t < newSize; t++) {
	    listRepPtr->holes[t] = 0;
	}
    }
    listRepPtr->maxElemCount = newSize;
}

static void
InitHoles(
    List *listRepPtr)
{
    int t;

    if (listRepPtr->holes == NULL) {
	listRepPtr->holes =
		(char *) ckalloc(sizeof(char) * listRepPtr->maxElemCount);
	for (t = 0; t < listRepPtr->maxElemCount; t++) {
	    listRepPtr->holes[t] = 0;
	}
    }
}

static List *
NewListIntRep(
    int objc,
    Tcl_Obj *const objv[],
    int p)
{
108
109
110
111
112
113
114

115
116
117
118
119
120
121
	}
	return NULL;
    }

    listRepPtr->canonicalFlag = 0;
    listRepPtr->refCount = 0;
    listRepPtr->maxElemCount = objc;


    if (objv) {
	Tcl_Obj **elemPtrs;
	int i;

	listRepPtr->elemCount = objc;
	elemPtrs = &listRepPtr->elements;







>







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
	}
	return NULL;
    }

    listRepPtr->canonicalFlag = 0;
    listRepPtr->refCount = 0;
    listRepPtr->maxElemCount = objc;
    listRepPtr->holes = NULL;

    if (objv) {
	Tcl_Obj **elemPtrs;
	int i;

	listRepPtr->elemCount = objc;
	elemPtrs = &listRepPtr->elements;
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

int
Tcl_ListObjAppendList(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    register Tcl_Obj *listPtr,	/* List object to append elements to. */
    Tcl_Obj *elemListPtr)	/* List obj with elements to append. */
{
    int objc;
    Tcl_Obj **objv;


    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList");
    }

    /*
     * Pull the elements to append from elemListPtr.
     */

    if (TCL_OK != TclListObjGetElements(interp, elemListPtr, &objc, &objv)) {
	return TCL_ERROR;
    }

    /*
     * Insert the new elements starting after the lists's last element.
     * Delete zero existing elements.
     */



    return Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, objc, objv);















}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjAppendElement --
 *







|

>


















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







539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591

int
Tcl_ListObjAppendList(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    register Tcl_Obj *listPtr,	/* List object to append elements to. */
    Tcl_Obj *elemListPtr)	/* List obj with elements to append. */
{
    int listLen, objc, result, i;
    Tcl_Obj **objv;
    List *listRepPtr, *elemListRepPtr;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList");
    }

    /*
     * Pull the elements to append from elemListPtr.
     */

    if (TCL_OK != TclListObjGetElements(interp, elemListPtr, &objc, &objv)) {
	return TCL_ERROR;
    }

    /*
     * Insert the new elements starting after the lists's last element.
     * Delete zero existing elements.
     */

    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    listLen = listRepPtr->maxElemCount;
    result = Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, objc, objv);
    if (result != TCL_OK) {
	return result;
    }

    
    elemListRepPtr = (List *) elemListPtr->internalRep.twoPtrValue.ptr1;
    if (elemListRepPtr->holes != NULL) {
	listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
	InitHoles(listRepPtr);
	for (i = 0; i < objc; i++) {
	    listRepPtr->holes[listLen + i] = elemListRepPtr->holes[i];
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjAppendElement --
 *
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
	}
	if (newPtr == NULL) {
	    attempt = numRequired;
	    newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt));
	}
	if (newPtr) {
	    listRepPtr = newPtr;
	    listRepPtr->maxElemCount = attempt;
	    needGrow = 0;
	}
    }
    if (isShared || needGrow) {
	Tcl_Obj **dst, **src = &listRepPtr->elements;

	/*







|







670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
	}
	if (newPtr == NULL) {
	    attempt = numRequired;
	    newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt));
	}
	if (newPtr) {
	    listRepPtr = newPtr;
	    SetMaxElemCount(listRepPtr, attempt);
	    needGrow = 0;
	}
    }
    if (isShared || needGrow) {
	Tcl_Obj **dst, **src = &listRepPtr->elements;

	/*
968
969
970
971
972
973
974















975
976
977
978
979
980
981
	    }
	}

	listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr;
	listRepPtr->refCount++;

	elemPtrs = &listRepPtr->elements;
















	if (isShared) {
	    /*
	     * The old struct will remain in place; need new refCounts for the
	     * new List struct references. Copy over only the surviving
	     * elements.
	     */







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







1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
	    }
	}

	listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr;
	listRepPtr->refCount++;

	elemPtrs = &listRepPtr->elements;

	if (oldListRepPtr->holes != NULL) {
	    listRepPtr->holes =
		    (char *) ckalloc(sizeof(char) * listRepPtr->maxElemCount);
	    for (i=0; i < first; i++) {
		listRepPtr->holes[i] = oldListRepPtr->holes[i];
	    }
	    for (i=first; i < first + objc; i++) {
		listRepPtr->holes[i] = 0;
	    }
	    for (i = first + count, j = first + objc;
		    j < numRequired; i++, j++) {
		listRepPtr->holes[j] = oldListRepPtr->holes[i];
	    }
	}

	if (isShared) {
	    /*
	     * The old struct will remain in place; need new refCounts for the
	     * new List struct references. Copy over only the surviving
	     * elements.
	     */
1366
1367
1368
1369
1370
1371
1372




1373
1374
1375
1376
1377
1378
1379

    /*
     * If there are no indices, simply return the new value.  (Without
     * indices, [lset] is a synonym for [set].
     */

    if (indexCount == 0) {




	Tcl_IncrRefCount(valuePtr);
	return valuePtr;
    }

    /*
     * If the list is shared, make a copy we can modify (copy-on-write).  We
     * use Tcl_DuplicateObj() instead of TclListObjCopy() for a few reasons:







>
>
>
>







1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449

    /*
     * If there are no indices, simply return the new value.  (Without
     * indices, [lset] is a synonym for [set].
     */

    if (indexCount == 0) {
	if (valuePtr == NULL) {
	    TclNewObj(valuePtr);
	}

	Tcl_IncrRefCount(valuePtr);
	return valuePtr;
    }

    /*
     * If the list is shared, make a copy we can modify (copy-on-write).  We
     * use Tcl_DuplicateObj() instead of TclListObjCopy() for a few reasons:
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
    Tcl_Obj *valuePtr)		/* Tcl object to store in the designated list
				 * element. */
{
    List *listRepPtr;		/* Internal representation of the list being
				 * modified. */
    Tcl_Obj **elemPtrs;		/* Pointers to elements of the list. */
    int elemCount;		/* Number of elements in the list. */


    /*
     * Ensure that the listPtr parameter designates an unshared list.
     */

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "TclListObjSetElement");







>







1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
    Tcl_Obj *valuePtr)		/* Tcl object to store in the designated list
				 * element. */
{
    List *listRepPtr;		/* Internal representation of the list being
				 * modified. */
    Tcl_Obj **elemPtrs;		/* Pointers to elements of the list. */
    int elemCount;		/* Number of elements in the list. */
    int hole = 0;

    /*
     * Ensure that the listPtr parameter designates an unshared list.
     */

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "TclListObjSetElement");
1666
1667
1668
1669
1670
1671
1672









1673
1674
1675
1676
1677
1678
1679
	}

	listRepPtr->refCount--;

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










    /*
     * Add a reference to the new list element.
     */

    Tcl_IncrRefCount(valuePtr);








>
>
>
>
>
>
>
>
>







1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
	}

	listRepPtr->refCount--;

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

    if (valuePtr == NULL) {
	hole = 1;
	TclNewObj(valuePtr);
    }
    if (hole || listRepPtr->holes != NULL) {
	InitHoles(listRepPtr);
	listRepPtr->holes[index] = hole;
    }

    /*
     * Add a reference to the new list element.
     */

    Tcl_IncrRefCount(valuePtr);

1720
1721
1722
1723
1724
1725
1726



1727
1728
1729
1730
1731
1732
1733
    if (--listRepPtr->refCount <= 0) {
	Tcl_Obj **elemPtrs = &listRepPtr->elements;
	int i, numElems = listRepPtr->elemCount;

	for (i = 0;  i < numElems;  i++) {
	    Tcl_DecrRefCount(elemPtrs[i]);
	}



	ckfree(listRepPtr);
    }

    listPtr->internalRep.twoPtrValue.ptr1 = NULL;
    listPtr->internalRep.twoPtrValue.ptr2 = NULL;
    listPtr->typePtr = NULL;
}







>
>
>







1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
    if (--listRepPtr->refCount <= 0) {
	Tcl_Obj **elemPtrs = &listRepPtr->elements;
	int i, numElems = listRepPtr->elemCount;

	for (i = 0;  i < numElems;  i++) {
	    Tcl_DecrRefCount(elemPtrs[i]);
	}
	if (listRepPtr->holes != NULL) {
	    ckfree((char *) listRepPtr->holes);
	}
	ckfree(listRepPtr);
    }

    listPtr->internalRep.twoPtrValue.ptr1 = NULL;
    listPtr->internalRep.twoPtrValue.ptr2 = NULL;
    listPtr->typePtr = NULL;
}
1958
1959
1960
1961
1962
1963
1964



1965

1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984




1985


1986
1987
1988
1989
1990
1991
1992

	flagPtr = ckalloc(numElems * sizeof(int));
    }
    elemPtrs = &listRepPtr->elements;
    for (i = 0; i < numElems; i++) {
	flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0);
	elem = TclGetStringFromObj(elemPtrs[i], &length);



	bytesNeeded += TclScanElement(elem, length, flagPtr+i);

	if (bytesNeeded < 0) {
	    Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
	}
    }
    if (bytesNeeded > INT_MAX - numElems + 1) {
	Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
    }
    bytesNeeded += numElems;

    /*
     * Pass 2: copy into string rep buffer.
     */

    listPtr->length = bytesNeeded - 1;
    listPtr->bytes = ckalloc(bytesNeeded);
    dst = listPtr->bytes;
    for (i = 0; i < numElems; i++) {
	flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0);
	elem = TclGetStringFromObj(elemPtrs[i], &length);




	dst += TclConvertElement(elem, length, dst, flagPtr[i]);


	*dst++ = ' ';
    }
    listPtr->bytes[listPtr->length] = '\0';

    if (flagPtr != localFlags) {
	ckfree(flagPtr);
    }







>
>
>
|
>



















>
>
>
>
|
>
>







2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085

	flagPtr = ckalloc(numElems * sizeof(int));
    }
    elemPtrs = &listRepPtr->elements;
    for (i = 0; i < numElems; i++) {
	flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0);
	elem = TclGetStringFromObj(elemPtrs[i], &length);
	if (listRepPtr->holes != NULL && listRepPtr->holes[i] != 0) {
	    listPtr->length += 8;
	} else {
	    bytesNeeded += TclScanElement(elem, length, flagPtr+i);
	}
	if (bytesNeeded < 0) {
	    Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
	}
    }
    if (bytesNeeded > INT_MAX - numElems + 1) {
	Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
    }
    bytesNeeded += numElems;

    /*
     * Pass 2: copy into string rep buffer.
     */

    listPtr->length = bytesNeeded - 1;
    listPtr->bytes = ckalloc(bytesNeeded);
    dst = listPtr->bytes;
    for (i = 0; i < numElems; i++) {
	flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0);
	elem = TclGetStringFromObj(elemPtrs[i], &length);
	if (listRepPtr->holes != NULL && listRepPtr->holes[i] != 0) {
	    strcpy(dst, "{*}{{}}");
	    dst += 7;
	} else {
	    dst += TclConvertElement(elem, length, dst,
		    flagPtr[i] | (i==0 ? 0 : TCL_DONT_QUOTE_HASH));
	}
	*dst++ = ' ';
    }
    listPtr->bytes[listPtr->length] = '\0';

    if (flagPtr != localFlags) {
	ckfree(flagPtr);
    }

Changes to generic/tclUtil.c.

533
534
535
536
537
538
539













540
541
542
543
544
545
546
	openBraces = 1;
	p++;
    } else if (*p == '"') {
	inQuotes = 1;
	p++;
    }
    elemStart = p;














    /*
     * Find element's end (a space, close brace, or the end of the string).
     */

    while (p < limit) {
	switch (*p) {







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







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
	openBraces = 1;
	p++;
    } else if (*p == '"') {
	inQuotes = 1;
	p++;
    }
    elemStart = p;

    /* Special case for special NULL token */
    if (openBraces && *p == '*' && strncmp(p, "*}{{}}", 6) == 0) {
	if (((p+6) >= limit) || isspace(UCHAR(*(p+6)))) {/* INTL: ISO space. */
	    elemStart = p + 4;
	    size = 0;
	    p += 6;
	    /* if (bracePtr != 0) { */
	    /*     *bracePtr = 2; */
	    /* } */
	    goto done;
	}
    }

    /*
     * Find element's end (a space, close brace, or the end of the string).
     */

    while (p < limit) {
	switch (*p) {
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
Tcl_ConcatObj(
    int objc,			/* Number of objects to concatenate. */
    Tcl_Obj *const objv[])	/* Array of objects to concatenate. */
{
    int i, elemLength, needSpace = 0, bytesNeeded = 0;
    const char *element;
    Tcl_Obj *objPtr, *resPtr;


    /*
     * 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.
     */








>







1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
Tcl_ConcatObj(
    int objc,			/* Number of objects to concatenate. */
    Tcl_Obj *const objv[])	/* Array of objects to concatenate. */
{
    int i, elemLength, needSpace = 0, bytesNeeded = 0;
    const char *element;
    Tcl_Obj *objPtr, *resPtr;
    List *listRepPtr;

    /*
     * 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.
     */

Changes to tests/list.test.

124
125
126
127
128
129
130




131



















































































132
133
134
test list-3.1 {SetListFromAny and lrange/concat results} {
    slowsort {fred julie alex carol bill annie}
} {alex annie bill carol fred julie}

test list-4.1 {Bug 3173086} {
    string is list "{[list \\\\\}]}"
} 1
























































































# cleanup
::tcltest::cleanupTests
return







>
>
>
>

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



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
test list-3.1 {SetListFromAny and lrange/concat results} {
    slowsort {fred julie alex carol bill annie}
} {alex annie bill carol fred julie}

test list-4.1 {Bug 3173086} {
    string is list "{[list \\\\\}]}"
} 1
test list-4.1 {null elements, parse literal} {
    set apa {a b {*}{{}} d}
    lindex $apa 2
} {}

test list-4.2 {null elements, parse literal} {
    set apa {a b {*}{{}} d}
    lindex $apa 3
} {d}

test list-4.3 {null elements, lappend preserves} {
    set apa {a b {*}{{}} d}
    lappend apa x
} {a b {*}{{}} d x}

test list-4.4 {null elements, lappend preserves} {
    set apa {a b {*}{{}} d}
    lappend apa x y z
    lindex $apa 2
} {}

test list-4.5 {null elements, lrange destroys} {
    set apa {a b {*}{{}} d}
    lrange $apa 0 end
} {a b {} d}

test list-4.6 {null elements, eval safe, pure list} {
    set apa {list b {*}{{}} d}
    lappend apa e
    eval $apa
} {b {} d e}

test list-4.7 {null elements, eval safe, string} {
    set apa {list b {*}{{}} d}
    lappend apa e
    eval " $apa x"
} {b {} d e x}

test list-4.8 {null elements, concat safe, pure list} {
    set apa {a b {*}{{}} d}
    lappend apa e
    set bepa {f {*}{{}} g}
    lappend bepa h
    concat $apa $bepa
} {a b {*}{{}} d e f {*}{{}} g h}

test list-4.9 {null elements, concat safe, string} {
    set apa {a b {*}{{}} d}
    set bepa {f {*}{{}} g}
    concat $apa $bepa
} {a b {*}{{}} d f {*}{{}} g}

test list-4.10 {null elements, lset preserves} {
    set apa {a b {*}{{}} d e}
    lset apa 3 x
    list $apa [lindex $apa 2]
} {{a b {*}{{}} x e} {}}

test list-4.11 {null elements, lset overwrites} {
    set apa {a b {*}{{}} d e}
    lset apa 2 x
    list $apa [lindex $apa 2]
} {{a b x d e} x}

test list-4.12 {null elements, nested lset overwrites} {
    set apa {g h {*}{{}} {a b {*}{{}} d e}}
    lset apa 3 2 x
    list $apa [lindex $apa 3 2]
} {{g h {*}{{}} {a b x d e}} x}

test list-4.13 {null elements, nested lset preserves} {
    set apa {g h {*}{{}} {a b {*}{{}} d e}}
    lset apa 3 3 x
    list $apa [lindex $apa 3 3]
} {{g h {*}{{}} {a b {*}{{}} x e}} x}

test list-5.1 {lunset} {
    set apa {a b c d e}
    lunset apa 3
    list $apa [lindex $apa 3]
} {{a b c {*}{{}} e} {}}

test list-5.2 {lunset, nested} {
    set apa {a b c {d e f g} h}
    lunset apa 3 2
    list $apa [lindex $apa 3 2]
} {{a b c {d e {*}{{}} g} h} {}}

# cleanup
::tcltest::cleanupTests
return