Tcl Source Code

Check-in [63ec2ace6e]
Login

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

Overview
Comment:Replace TclCountSpaceRuns() with TclMaxListLength() which is the function we actually want.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-5-branch
Files: files | file ages | folders
SHA1: 63ec2ace6e71c3dc2cd421bd8585f2c23eab981c
User & Date: dgp 2011-05-02 15:38:31
Context
2011-05-02
17:36
Revised TclFindElement() interface. The final argument had been bracePtr, the address of a boolean v... check-in: 04d0ff20b9 user: dgp tags: core-8-5-branch, potential incompatibility
15:52
Replace TclCountSpaceRuns() with TclMaxListLength() which is the function we actually want. check-in: 056df6f608 user: dgp tags: dgp-switch-compile
15:44
Replace TclCountSpaceRuns() with TclMaxListLength() which is the function we actually want. check-in: 304fa3c29b user: dgp tags: trunk
15:38
Replace TclCountSpaceRuns() with TclMaxListLength() which is the function we actually want. check-in: 63ec2ace6e user: dgp tags: core-8-5-branch
2011-04-28
16:00
More isspace() callers. check-in: 88095bbde0 user: dgp tags: core-8-5-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.







1
2
3
4
5
6
7






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

	* generic/tclInt.h:	New utility routines:
	* generic/tclParse.c:	TclIsSpaceProc() and
	* generic/tclUtil.c:	TclCountSpaceRuns()

	* generic/tclCmdMZ.c:	Use new routines to replace calls to
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
2011-05-02  Don Porter  <[email protected]>

	* generic/tclInt.h:	Replace TclCountSpaceRuns() with
	* generic/tclListObj.c:	TclMaxListLength() which is the function we
	* generic/tclUtil.c:	actually want.

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

	* generic/tclInt.h:	New utility routines:
	* generic/tclParse.c:	TclIsSpaceProc() and
	* generic/tclUtil.c:	TclCountSpaceRuns()

	* generic/tclCmdMZ.c:	Use new routines to replace calls to

Changes to generic/tclInt.h.

2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
MODULE_SCOPE ContLineLoc* TclContinuationsEnter(Tcl_Obj *objPtr, int num,
			    int *loc);
MODULE_SCOPE void	TclContinuationsEnterDerived(Tcl_Obj *objPtr,
			    int start, int *clNext);
MODULE_SCOPE ContLineLoc* TclContinuationsGet(Tcl_Obj *objPtr);
MODULE_SCOPE void	TclContinuationsCopy(Tcl_Obj *objPtr,
			    Tcl_Obj *originObjPtr);
MODULE_SCOPE int	TclCountSpaceRuns(CONST char *bytes, int numBytes,
			    CONST char **endPtr);
MODULE_SCOPE void	TclDeleteNamespaceVars(Namespace *nsPtr);
/* TIP #280 - Modified token based evulation, with line information. */
MODULE_SCOPE int	TclEvalEx(Tcl_Interp *interp, const char *script,
			    int numBytes, int flags, int line,
			    int *clNextOuter, CONST char *outerScript);
MODULE_SCOPE int	TclFileAttrsCmd(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);







<
<







2569
2570
2571
2572
2573
2574
2575


2576
2577
2578
2579
2580
2581
2582
MODULE_SCOPE ContLineLoc* TclContinuationsEnter(Tcl_Obj *objPtr, int num,
			    int *loc);
MODULE_SCOPE void	TclContinuationsEnterDerived(Tcl_Obj *objPtr,
			    int start, int *clNext);
MODULE_SCOPE ContLineLoc* TclContinuationsGet(Tcl_Obj *objPtr);
MODULE_SCOPE void	TclContinuationsCopy(Tcl_Obj *objPtr,
			    Tcl_Obj *originObjPtr);


MODULE_SCOPE void	TclDeleteNamespaceVars(Namespace *nsPtr);
/* TIP #280 - Modified token based evulation, with line information. */
MODULE_SCOPE int	TclEvalEx(Tcl_Interp *interp, const char *script,
			    int numBytes, int flags, int line,
			    int *clNextOuter, CONST char *outerScript);
MODULE_SCOPE int	TclFileAttrsCmd(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
2681
2682
2683
2684
2685
2686
2687


2688
2689
2690
2691
2692
2693
2694
MODULE_SCOPE Tcl_Obj *	TclLsetList(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    Tcl_Obj *indexPtr, Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Obj *	TclLsetFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    int indexCount, Tcl_Obj *const indexArray[],
			    Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name,
			    const EnsembleImplMap map[]);


MODULE_SCOPE int	TclMergeReturnOptions(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr,
			    int *codePtr, int *levelPtr);
MODULE_SCOPE int	TclNokia770Doubles();
MODULE_SCOPE void	TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, const char *operation,
			    const char *reason, int index);







>
>







2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
MODULE_SCOPE Tcl_Obj *	TclLsetList(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    Tcl_Obj *indexPtr, Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Obj *	TclLsetFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    int indexCount, Tcl_Obj *const indexArray[],
			    Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name,
			    const EnsembleImplMap map[]);
MODULE_SCOPE int	TclMaxListLength(CONST char *bytes, int numBytes,
			    CONST char **endPtr);
MODULE_SCOPE int	TclMergeReturnOptions(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr,
			    int *codePtr, int *levelPtr);
MODULE_SCOPE int	TclNokia770Doubles();
MODULE_SCOPE void	TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, const char *operation,
			    const char *reason, int index);

Changes to generic/tclListObj.c.

1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776


1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
     * Get the string representation. Make it up-to-date if necessary.
     */

    string = TclGetStringFromObj(objPtr, &length);

    /*
     * Parse the string into separate string objects, and create a List
     * structure that points to the element string objects. We use a modified
     * version of Tcl_SplitList's implementation to avoid one malloc and a
     * string copy for each list element. First, estimate the number of
     * elements by counting the number of space characters in the list.
     */

    estCount = TclCountSpaceRuns(string, length, &limit) + 1;

    /*
     * Allocate a new List structure with enough room for "estCount" elements.
     * Each element is a pointer to a Tcl_Obj with the appropriate string rep.
     * The initial "estCount" elements are set using the corresponding "argv"
     * strings.
     */



    listRepPtr = AttemptNewList(interp, estCount, NULL);
    if (listRepPtr == NULL) {
	return TCL_ERROR;
    }
    elemPtrs = &listRepPtr->elements;


    for (p=string, lenRemain=length, i=0;
	    lenRemain > 0;
	    p=nextElem, lenRemain=limit-nextElem, i++) {
	result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem,
		&elemSize, &hasBrace);
	if (result != TCL_OK) {
	    for (j = 0;  j < i;  j++) {







|
<
<
<
<
|
<
|
<
<
<
<
|


>
>






>







1755
1756
1757
1758
1759
1760
1761
1762




1763

1764




1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
     * Get the string representation. Make it up-to-date if necessary.
     */

    string = TclGetStringFromObj(objPtr, &length);

    /*
     * Parse the string into separate string objects, and create a List
     * structure that points to the element string objects. 




     *

     * First, allocate enough space to hold a (Tcl_Obj *) for each




     * (possible) list element.
     */

    estCount = TclMaxListLength(string, length, &limit);
    estCount += (estCount == 0); /* Smallest List struct holds 1 element. */
    listRepPtr = AttemptNewList(interp, estCount, NULL);
    if (listRepPtr == NULL) {
	return TCL_ERROR;
    }
    elemPtrs = &listRepPtr->elements;

    /* Each iteration, parse and store a list element */
    for (p=string, lenRemain=length, i=0;
	    lenRemain > 0;
	    p=nextElem, lenRemain=limit-nextElem, i++) {
	result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem,
		&elemSize, &hasBrace);
	if (result != TCL_OK) {
	    for (j = 0;  j < i;  j++) {

Changes to generic/tclUtil.c.

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
114
115









116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134





135
136
137
138
139
140
141
    UpdateStringOfEndOffset,		/* updateStringProc */
    SetEndOffsetFromAny
};

/*
 *----------------------------------------------------------------------
 *
 * TclCountSpaceRuns --
 *
 *	Given 'bytes' pointing to 'numBytes' bytes, scan through them and
 *	count the number of whitespace runs that could be list element
 *	separators.  If 'numBytes' is -1, scan to the terminating '\0'.



 *
 * Results:

 *	Returns the count.  If 'endPtr' is not NULL, writes a pointer to
 *	the end of the string scanned there.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclCountSpaceRuns(
    CONST char *bytes,
    int numBytes,
    CONST char **endPtr)
{
    int count = 0;










    while (numBytes) {
	if ((numBytes == -1) && (*bytes == '\0')) {
	    break;
	}
	if (TclIsSpaceProc(*bytes)) {
	    /* Space run started; bump count */
	    count++;
	    do {
		bytes++;
		numBytes -= (numBytes != -1);
	    } while (numBytes && TclIsSpaceProc(*bytes));
	    if (numBytes == 0) {
		break;
	    }
	    /* (*bytes) is non-space; return to counting state */
	}
	bytes++;
	numBytes -= (numBytes != -1);
    }





    if (endPtr) {
	*endPtr = bytes;
    }
    return count;
}

/*







|




>
>
>


>
|
|








|






>
>
>
>
>
>
>
>
>



















>
>
>
>
>







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
114
115
116
117
118
119
120
121
122
123
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
    UpdateStringOfEndOffset,		/* updateStringProc */
    SetEndOffsetFromAny
};

/*
 *----------------------------------------------------------------------
 *
 * TclMaxListLength --
 *
 *	Given 'bytes' pointing to 'numBytes' bytes, scan through them and
 *	count the number of whitespace runs that could be list element
 *	separators.  If 'numBytes' is -1, scan to the terminating '\0'.
 *	Not a full list parser.  Typically used to get a quick and dirty
 *	overestimate of length size in order to allocate space for an
 *	actual list parser to operate with.
 *
 * Results:
 *	Returns the largest number of list elements that could possibly
 *	be in this string, interpreted as a Tcl list.  If 'endPtr' is not
 *	NULL, writes a pointer to the end of the string scanned there.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclMaxListLength(
    CONST char *bytes,
    int numBytes,
    CONST char **endPtr)
{
    int count = 0;

    if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) {
	/* Empty string case - quick exit */
	goto done;
    }

    /* No list element before leading white space */
    count += 1 - TclIsSpaceProc(*bytes); 

    /* Count white space runs as potential element separators */
    while (numBytes) {
	if ((numBytes == -1) && (*bytes == '\0')) {
	    break;
	}
	if (TclIsSpaceProc(*bytes)) {
	    /* Space run started; bump count */
	    count++;
	    do {
		bytes++;
		numBytes -= (numBytes != -1);
	    } while (numBytes && TclIsSpaceProc(*bytes));
	    if (numBytes == 0) {
		break;
	    }
	    /* (*bytes) is non-space; return to counting state */
	}
	bytes++;
	numBytes -= (numBytes != -1);
    }

    /* No list element following trailing white space */
    count -= TclIsSpaceProc(bytes[-1]); 

    done:
    if (endPtr) {
	*endPtr = bytes;
    }
    return count;
}

/*
458
459
460
461
462
463
464
465
466



467
468
469
470
471
472
473
474

475
476
477
478
479
480
481
				 * of pointers to list elements. */
{
    CONST char **argv, *end, *element;
    char *p;
    int length, size, i, result, elSize, brace;

    /*
     * Figure out how much space to allocate. There must be enough space for
     * both the array of pointers and also for a copy of the list. To estimate



     * the number of pointers needed, count the number of space characters in
     * the list.
     */

    size = TclCountSpaceRuns(list, -1, &end) + 2;
    length = end - list;
    argv = (CONST char **) ckalloc((unsigned)
	    ((size * sizeof(char *)) + length + 1));

    for (i = 0, p = ((char *) argv) + size*sizeof(char *);
	    *list != 0;  i++) {
	CONST char *prevList = list;

	result = TclFindElement(interp, list, length, &element, &list,
		&elSize, &brace);
	length -= (list - prevList);







|
|
>
>
>
|
<


|



>







476
477
478
479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496
497
498
499
500
501
502
				 * of pointers to list elements. */
{
    CONST char **argv, *end, *element;
    char *p;
    int length, size, i, result, elSize, brace;

    /*
     * Allocate enough space to work in. A (CONST char *) for each
     * (possible) list element plus one more for terminating NULL,
     * plus as many bytes as in the original string value, plus one
     * more for a terminating '\0'.  Space used to hold element separating
     * white space in the original string gets re-purposed to hold '\0'
     * characters in the argv array.

     */

    size = TclMaxListLength(list, -1, &end) + 1;
    length = end - list;
    argv = (CONST char **) ckalloc((unsigned)
	    ((size * sizeof(char *)) + length + 1));

    for (i = 0, p = ((char *) argv) + size*sizeof(char *);
	    *list != 0;  i++) {
	CONST char *prevList = list;

	result = TclFindElement(interp, list, length, &element, &list,
		&elSize, &brace);
	length -= (list - prevList);