Tcl Source Code

Check-in [50bd973657]
Login

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

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-439 | semver
Files: files | file ages | folders
SHA1: 50bd97365724cf8356d345f6623f1b7b7a0f9f6a
User & Date: jan.nijtmans 2017-07-14 14:21:06
Context
2017-08-30
12:01
merge trunk check-in: ddda318c41 user: jan.nijtmans tags: tip-439, semver
2017-07-14
14:21
merge trunk check-in: 50bd973657 user: jan.nijtmans tags: tip-439, semver
2017-07-13
15:07
merge core-8-6-branch check-in: a3919af766 user: jan.nijtmans tags: trunk
2017-06-26
11:37
merge trunk check-in: 0705d03cdf user: jan.nijtmans tags: tip-439, semver
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclInt.h.

4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
 *
 * MODULE_SCOPE int	TclUtfToUniChar(const char *string, Tcl_UniChar *ch);
 *----------------------------------------------------------------
 */

#define TclUtfToUniChar(str, chPtr) \
	((((unsigned char) *(str)) < 0xC0) ?		\
	    ((*(chPtr) = (Tcl_UniChar) *(str)), 1)	\
	    : Tcl_UtfToUniChar(str, chPtr))

/*
 *----------------------------------------------------------------
 * Macro counterpart of the Tcl_NumUtfChars() function. To be used in speed-
 * -sensitive points where it pays to avoid a function call in the common case
 * of counting along a string of all one-byte characters.  The ANSI C







|







4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
 *
 * MODULE_SCOPE int	TclUtfToUniChar(const char *string, Tcl_UniChar *ch);
 *----------------------------------------------------------------
 */

#define TclUtfToUniChar(str, chPtr) \
	((((unsigned char) *(str)) < 0xC0) ?		\
	    ((*(chPtr) = (unsigned char) *(str)), 1)	\
	    : Tcl_UtfToUniChar(str, chPtr))

/*
 *----------------------------------------------------------------
 * Macro counterpart of the Tcl_NumUtfChars() function. To be used in speed-
 * -sensitive points where it pays to avoid a function call in the common case
 * of counting along a string of all one-byte characters.  The ANSI C

Changes to generic/tclOO.h.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 *
 * tests/oo.test
 * tests/ooNext2.test
 * unix/tclooConfig.sh
 * win/tclooConfig.sh
 */

#define TCLOO_VERSION "1.0.4"
#define TCLOO_PATCHLEVEL TCLOO_VERSION

#include "tcl.h"

/*
 * For C++ compilers, use extern "C"
 */







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 *
 * tests/oo.test
 * tests/ooNext2.test
 * unix/tclooConfig.sh
 * win/tclooConfig.sh
 */

#define TCLOO_VERSION "1.2.0"
#define TCLOO_PATCHLEVEL TCLOO_VERSION

#include "tcl.h"

/*
 * For C++ compilers, use extern "C"
 */

Changes to generic/tclPathObj.c.

9
10
11
12
13
14
15

16
17
18
19
20
21
22
 *
 * 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 "tclFileSystem.h"


/*
 * Prototypes for functions defined later in this file.
 */

static Tcl_Obj *	AppendPath(Tcl_Obj *head, Tcl_Obj *tail);
static void		DupFsPathInternalRep(Tcl_Obj *srcPtr,







>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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 "tclFileSystem.h"
#include <assert.h>

/*
 * Prototypes for functions defined later in this file.
 */

static Tcl_Obj *	AppendPath(Tcl_Obj *head, Tcl_Obj *tail);
static void		DupFsPathInternalRep(Tcl_Obj *srcPtr,
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860

861

862

863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
}

Tcl_Obj *
TclJoinPath(
    int elements,
    Tcl_Obj * const objv[])
{
    Tcl_Obj *res;
    int i;
    const Tcl_Filesystem *fsPtr = NULL;

    res = NULL;

    for (i = 0; i < elements; i++) {
	int driveNameLength, strEltLen, length;
	Tcl_PathType type;

	char *strElt, *ptr;

	Tcl_Obj *driveName = NULL;

	Tcl_Obj *elt = objv[i];

	/*
	 * This is a special case where we can be much more efficient, where
	 * we are joining a single relative path onto an object that is
	 * already of path type. The 'TclNewFSPathObj' call below creates an
	 * object which can be normalized more efficiently. Currently we only
	 * use the special case when we have exactly two elements, but we
	 * could expand that in the future.
         *
         * Bugfix [a47641a0]. TclNewFSPathObj requires first argument
         * to be an absolute path. Added a check for that elt is absolute.
	 */

	if ((i == (elements-2)) && (i == 0)
                && (elt->typePtr == &tclFsPathType)
		&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
                && TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
            Tcl_Obj *tailObj = objv[i+1];


	    type = TclGetPathType(tailObj, NULL, NULL, NULL);
	    if (type == TCL_PATH_RELATIVE) {
		const char *str;
		int len;

		str = TclGetStringFromObj(tailObj, &len);
		if (len == 0) {
		    /*
		     * This happens if we try to handle the root volume '/'.
		     * There's no need to return a special path object, when
		     * the base itself is just fine!
		     */

		    if (res != NULL) {
			TclDecrRefCount(res);
		    }
		    return elt;
		}

		/*
		 * If it doesn't begin with '.' and is a unix path or it a
		 * windows path without backslashes, then we can be very
		 * efficient here. (In fact even a windows path with







|



|

|
<
|
>
|
>
|
>
|








|
|
|


<
|


|
>

<












<
<
<







846
847
848
849
850
851
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879

880
881
882
883
884
885

886
887
888
889
890
891
892
893
894
895
896
897



898
899
900
901
902
903
904
}

Tcl_Obj *
TclJoinPath(
    int elements,
    Tcl_Obj * const objv[])
{
    Tcl_Obj *res = NULL;
    int i;
    const Tcl_Filesystem *fsPtr = NULL;

    assert ( elements >= 0 );

    if (elements == 0) {

	return Tcl_NewObj();
    }

    assert ( elements > 0 );

    if (elements == 2) {
	Tcl_Obj *elt = objv[0];

	/*
	 * This is a special case where we can be much more efficient, where
	 * we are joining a single relative path onto an object that is
	 * already of path type. The 'TclNewFSPathObj' call below creates an
	 * object which can be normalized more efficiently. Currently we only
	 * use the special case when we have exactly two elements, but we
	 * could expand that in the future.
	 *
	 * Bugfix [a47641a0]. TclNewFSPathObj requires first argument
	 * to be an absolute path. Added a check for that elt is absolute.
	 */


	if ((elt->typePtr == &tclFsPathType)
		&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
                && TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
            Tcl_Obj *tailObj = objv[1];
	    Tcl_PathType type = TclGetPathType(tailObj, NULL, NULL, NULL);


	    if (type == TCL_PATH_RELATIVE) {
		const char *str;
		int len;

		str = TclGetStringFromObj(tailObj, &len);
		if (len == 0) {
		    /*
		     * This happens if we try to handle the root volume '/'.
		     * There's no need to return a special path object, when
		     * the base itself is just fine!
		     */




		    return elt;
		}

		/*
		 * If it doesn't begin with '.' and is a unix path or it a
		 * windows path without backslashes, then we can be very
		 * efficient here. (In fact even a windows path with
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959











960
961
962
963
964
965
966
		     * Finally, on Windows, 'file join' is defined to convert
		     * all backslashes to forward slashes, so the base part
		     * cannot have backslashes either.
		     */

		    if ((tclPlatform != TCL_PLATFORM_WINDOWS)
			    || (strchr(Tcl_GetString(elt), '\\') == NULL)) {
			if (res != NULL) {
			    TclDecrRefCount(res);
			}

			if (PATHFLAGS(elt)) {
			    return TclNewFSPathObj(elt, str, len);
			}
			if (TCL_PATH_ABSOLUTE != Tcl_FSGetPathType(elt)) {
			    return TclNewFSPathObj(elt, str, len);
			}
			(void) Tcl_FSGetNormalizedPath(NULL, elt);
			if (elt == PATHOBJ(elt)->normPathPtr) {
			    return TclNewFSPathObj(elt, str, len);
			}
		    }
		}

		/*
		 * Otherwise we don't have an easy join, and we must let the
		 * more general code below handle things.
		 */
	    } else if (tclPlatform == TCL_PLATFORM_UNIX) {
		if (res != NULL) {
		    TclDecrRefCount(res);
		}
		return tailObj;
	    } else {
		const char *str = TclGetString(tailObj);

		if (tclPlatform == TCL_PLATFORM_WINDOWS) {
		    if (strchr(str, '\\') == NULL) {
			if (res != NULL) {
			    TclDecrRefCount(res);
			}
			return tailObj;
		    }
		}
	    }
	}











	strElt = TclGetStringFromObj(elt, &strEltLen);
	driveNameLength = 0;
	type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
	if (type != TCL_PATH_RELATIVE) {
	    /*
	     * Zero out the current result.
	     */







<
<
<



















<
<
<






<
<
<





>
>
>
>
>
>
>
>
>
>
>







913
914
915
916
917
918
919



920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938



939
940
941
942
943
944



945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
		     * Finally, on Windows, 'file join' is defined to convert
		     * all backslashes to forward slashes, so the base part
		     * cannot have backslashes either.
		     */

		    if ((tclPlatform != TCL_PLATFORM_WINDOWS)
			    || (strchr(Tcl_GetString(elt), '\\') == NULL)) {




			if (PATHFLAGS(elt)) {
			    return TclNewFSPathObj(elt, str, len);
			}
			if (TCL_PATH_ABSOLUTE != Tcl_FSGetPathType(elt)) {
			    return TclNewFSPathObj(elt, str, len);
			}
			(void) Tcl_FSGetNormalizedPath(NULL, elt);
			if (elt == PATHOBJ(elt)->normPathPtr) {
			    return TclNewFSPathObj(elt, str, len);
			}
		    }
		}

		/*
		 * Otherwise we don't have an easy join, and we must let the
		 * more general code below handle things.
		 */
	    } else if (tclPlatform == TCL_PLATFORM_UNIX) {



		return tailObj;
	    } else {
		const char *str = TclGetString(tailObj);

		if (tclPlatform == TCL_PLATFORM_WINDOWS) {
		    if (strchr(str, '\\') == NULL) {



			return tailObj;
		    }
		}
	    }
	}
    }

    assert ( res == NULL );

    for (i = 0; i < elements; i++) {
	int driveNameLength, strEltLen, length;
	Tcl_PathType type;
	char *strElt, *ptr;
	Tcl_Obj *driveName = NULL;
	Tcl_Obj *elt = objv[i];

	strElt = TclGetStringFromObj(elt, &strEltLen);
	driveNameLength = 0;
	type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
	if (type != TCL_PATH_RELATIVE) {
	    /*
	     * Zero out the current result.
	     */
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
	 * The path element was not of a suitable form to be returned as is.
	 * We need to perform a more complex operation here.
	 */

    noQuickReturn:
	if (res == NULL) {
	    res = Tcl_NewObj();
	    ptr = TclGetStringFromObj(res, &length);
	} else {
	    ptr = TclGetStringFromObj(res, &length);
	}


	/*
	 * Strip off any './' before a tilde, unless this is the beginning of
	 * the path.
	 */

	if (length > 0 && strEltLen > 0 && (strElt[0] == '.') &&







<
<
<

>







1048
1049
1050
1051
1052
1053
1054



1055
1056
1057
1058
1059
1060
1061
1062
1063
	 * The path element was not of a suitable form to be returned as is.
	 * We need to perform a more complex operation here.
	 */

    noQuickReturn:
	if (res == NULL) {
	    res = Tcl_NewObj();



	}
	ptr = TclGetStringFromObj(res, &length);

	/*
	 * Strip off any './' before a tilde, unless this is the beginning of
	 * the path.
	 */

	if (length > 0 && strEltLen > 0 && (strElt[0] == '.') &&
1083
1084
1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
	    int needsSep = 0;

	    if (fsPtr->filesystemSeparatorProc != NULL) {
		Tcl_Obj *sep = fsPtr->filesystemSeparatorProc(res);

		if (sep != NULL) {
		    separator = TclGetString(sep)[0];

		}
		/* Safety check in case the VFS driver caused sharing */
		if (Tcl_IsShared(res)) {
		    TclDecrRefCount(res);
		    res = Tcl_DuplicateObj(res);
		    Tcl_IncrRefCount(res);
		}







>







1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
	    int needsSep = 0;

	    if (fsPtr->filesystemSeparatorProc != NULL) {
		Tcl_Obj *sep = fsPtr->filesystemSeparatorProc(res);

		if (sep != NULL) {
		    separator = TclGetString(sep)[0];
		    TclDecrRefCount(sep);
		}
		/* Safety check in case the VFS driver caused sharing */
		if (Tcl_IsShared(res)) {
		    TclDecrRefCount(res);
		    res = Tcl_DuplicateObj(res);
		    Tcl_IncrRefCount(res);
		}
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
		    needsSep = 1;
		}
	    }
	    length = ptr - TclGetString(res);
	    Tcl_SetObjLength(res, length);
	}
    }
    if (res == NULL) {
	res = Tcl_NewObj();
    }
    return res;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSConvertToPathType --







|
<
<







1118
1119
1120
1121
1122
1123
1124
1125


1126
1127
1128
1129
1130
1131
1132
		    needsSep = 1;
		}
	    }
	    length = ptr - TclGetString(res);
	    Tcl_SetObjLength(res, length);
	}
    }
    assert ( res != NULL );


    return res;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSConvertToPathType --

Changes to generic/tclStrToD.c.

1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
 *
 * Side effects:
 *	Stores base*5**n in result.
 *
 *----------------------------------------------------------------------
 */

inline static void
MulPow5(
    mp_int *base, 		/* Number to multiply. */
    unsigned n,			/* Power of 5 to multiply by. */
    mp_int *result)		/* Place to store the result. */
{
    mp_int *p = base;
    int n13 = n / 13;







|







1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
 *
 * Side effects:
 *	Stores base*5**n in result.
 *
 *----------------------------------------------------------------------
 */

static inline void
MulPow5(
    mp_int *base, 		/* Number to multiply. */
    unsigned n,			/* Power of 5 to multiply by. */
    mp_int *result)		/* Place to store the result. */
{
    mp_int *p = base;
    int n13 = n / 13;
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
 *
 * Side effects:
 *	Shifts the number in place; *wPtr is replaced by the shifted number.
 *
 *----------------------------------------------------------------------
 */

inline static int
NormalizeRightward(
    Tcl_WideUInt *wPtr)		/* INOUT: Number to shift. */
{
    int rv = 0;
    Tcl_WideUInt w = *wPtr;

    if (!(w & (Tcl_WideUInt) 0xffffffff)) {







|







2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
 *
 * Side effects:
 *	Shifts the number in place; *wPtr is replaced by the shifted number.
 *
 *----------------------------------------------------------------------
 */

static inline int
NormalizeRightward(
    Tcl_WideUInt *wPtr)		/* INOUT: Number to shift. */
{
    int rv = 0;
    Tcl_WideUInt w = *wPtr;

    if (!(w & (Tcl_WideUInt) 0xffffffff)) {
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
 *	Stores the significand in '*significand' and the exponent in '*expon'
 *	so that dv == significand * 2.0**expon, and significand is odd.  Also
 *	stores the position of the leftmost 1-bit in 'significand' in 'bits'.
 *
 *----------------------------------------------------------------------
 */

inline static void
DoubleToExpAndSig(
    double dv,			/* Number to convert. */
    Tcl_WideUInt *significand,	/* OUTPUT: Significand of the number. */
    int *expon,			/* OUTPUT: Exponent to multiply the number
				 * by. */
    int *bits)			/* OUTPUT: Number of significant bits. */
{







|







2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
 *	Stores the significand in '*significand' and the exponent in '*expon'
 *	so that dv == significand * 2.0**expon, and significand is odd.  Also
 *	stores the position of the leftmost 1-bit in 'significand' in 'bits'.
 *
 *----------------------------------------------------------------------
 */

static inline void
DoubleToExpAndSig(
    double dv,			/* Number to convert. */
    Tcl_WideUInt *significand,	/* OUTPUT: Significand of the number. */
    int *expon,			/* OUTPUT: Exponent to multiply the number
				 * by. */
    int *bits)			/* OUTPUT: Number of significant bits. */
{
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
 * Side effects:
 *	The 'double' in *d is replaced with its absolute value. The signum is
 *	stored in 'sign': 1 for negative, 0 for nonnegative.
 *
 *----------------------------------------------------------------------
 */

inline static void
TakeAbsoluteValue(
    Double *d,			/* Number to replace with absolute value. */
    int *sign)			/* Place to put the signum. */
{
    if (d->w.word0 & SIGN_BIT) {
	*sign = 1;
	d->w.word0 &= ~SIGN_BIT;







|







2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
 * Side effects:
 *	The 'double' in *d is replaced with its absolute value. The signum is
 *	stored in 'sign': 1 for negative, 0 for nonnegative.
 *
 *----------------------------------------------------------------------
 */

static inline void
TakeAbsoluteValue(
    Double *d,			/* Number to replace with absolute value. */
    int *sign)			/* Place to put the signum. */
{
    if (d->w.word0 & SIGN_BIT) {
	*sign = 1;
	d->w.word0 &= ~SIGN_BIT;
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
 * Side effects:
 *	Stores 9999 in *decpt, and sets '*endPtr' to designate the terminating
 *	NUL byte of the string if 'endPtr' is not NULL.
 *
 *----------------------------------------------------------------------
 */

inline static char *
FormatInfAndNaN(
    Double *d,			/* Exceptional number to format. */
    int *decpt,			/* Decimal point to set to a bogus value. */
    char **endPtr)		/* Pointer to the end of the formatted data */
{
    char *retval;








|







2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
 * Side effects:
 *	Stores 9999 in *decpt, and sets '*endPtr' to designate the terminating
 *	NUL byte of the string if 'endPtr' is not NULL.
 *
 *----------------------------------------------------------------------
 */

static inline char *
FormatInfAndNaN(
    Double *d,			/* Exceptional number to format. */
    int *decpt,			/* Decimal point to set to a bogus value. */
    char **endPtr)		/* Pointer to the end of the formatted data */
{
    char *retval;

2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
 * Side effects:
 *	Stores 1 in '*decpt' and puts a pointer to the NUL byte terminating
 *	the string in '*endPtr' if 'endPtr' is not NULL.
 *
 *----------------------------------------------------------------------
 */

inline static char *
FormatZero(
    int *decpt,			/* Location of the decimal point. */
    char **endPtr)		/* Pointer to the end of the formatted data */
{
    char *retval = ckalloc(2);

    strcpy(retval, "0");







|







2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
 * Side effects:
 *	Stores 1 in '*decpt' and puts a pointer to the NUL byte terminating
 *	the string in '*endPtr' if 'endPtr' is not NULL.
 *
 *----------------------------------------------------------------------
 */

static inline char *
FormatZero(
    int *decpt,			/* Location of the decimal point. */
    char **endPtr)		/* Pointer to the end of the formatted data */
{
    char *retval = ckalloc(2);

    strcpy(retval, "0");
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
 * Results:
 *	Return an approximation to floor(log10(bw*2**be)) that is either exact
 *	or 1 too high.
 *
 *----------------------------------------------------------------------
 */

inline static int
ApproximateLog10(
    Tcl_WideUInt bw,		/* Integer significand of the number. */
    int be,			/* Power of two to scale bw. */
    int bbits)			/* Number of bits of precision in bw. */
{
    int i;			/* Log base 2 of the number. */
    int k;			/* Floor(Log base 10 of the number) */







|







2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
 * Results:
 *	Return an approximation to floor(log10(bw*2**be)) that is either exact
 *	or 1 too high.
 *
 *----------------------------------------------------------------------
 */

static inline int
ApproximateLog10(
    Tcl_WideUInt bw,		/* Integer significand of the number. */
    int be,			/* Power of two to scale bw. */
    int bbits)			/* Number of bits of precision in bw. */
{
    int i;			/* Log base 2 of the number. */
    int k;			/* Floor(Log base 10 of the number) */
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
 *
 * Results:
 *	Returns the improved approximation to log10(d).
 *
 *----------------------------------------------------------------------
 */

inline static int
BetterLog10(
    double d,			/* Original number to format. */
    int k,			/* Characteristic(Log base 10) of the
				 * number. */
    int *k_check)		/* Flag == 1 if k is inexact. */
{
    /*







|







2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
 *
 * Results:
 *	Returns the improved approximation to log10(d).
 *
 *----------------------------------------------------------------------
 */

static inline int
BetterLog10(
    double d,			/* Original number to format. */
    int k,			/* Characteristic(Log base 10) of the
				 * number. */
    int *k_check)		/* Flag == 1 if k is inexact. */
{
    /*
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
 *	exactly represents the value of the x/10**k. This value will lie in
 *	the range [1 .. 10), and allows for computing successive digits by
 *	multiplying sig%10 by 10.
 *
 *----------------------------------------------------------------------
 */

inline static void
ComputeScale(
    int be,			/* Exponent part of number: d = bw * 2**be. */
    int k,			/* Characteristic of log10(number). */
    int *b2,			/* OUTPUT: Power of 2 in the numerator. */
    int *b5,			/* OUTPUT: Power of 5 in the numerator. */
    int *s2,			/* OUTPUT: Power of 2 in the denominator. */
    int *s5)			/* OUTPUT: Power of 5 in the denominator. */







|







2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
 *	exactly represents the value of the x/10**k. This value will lie in
 *	the range [1 .. 10), and allows for computing successive digits by
 *	multiplying sig%10 by 10.
 *
 *----------------------------------------------------------------------
 */

static inline void
ComputeScale(
    int be,			/* Exponent part of number: d = bw * 2**be. */
    int k,			/* Characteristic of log10(number). */
    int *b2,			/* OUTPUT: Power of 2 in the numerator. */
    int *b5,			/* OUTPUT: Power of 5 in the numerator. */
    int *s2,			/* OUTPUT: Power of 2 in the denominator. */
    int *s5)			/* OUTPUT: Power of 5 in the denominator. */
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
 *	digits to convert if k has been guessed correctly, and '*iLim1Ptr' to
 *	the limiting number of digits to convert if k has been guessed to be
 *	one too high.
 *
 *----------------------------------------------------------------------
 */

inline static void
SetPrecisionLimits(
    int convType,		/* Type of conversion: TCL_DD_SHORTEST,
				 * TCL_DD_STEELE0, TCL_DD_E_FMT,
				 * TCL_DD_F_FMT. */
    int k,			/* Floor(log10(number to convert)) */
    int *ndigitsPtr,		/* IN/OUT: Number of digits requested (will be
				 *         adjusted if needed). */







|







2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
 *	digits to convert if k has been guessed correctly, and '*iLim1Ptr' to
 *	the limiting number of digits to convert if k has been guessed to be
 *	one too high.
 *
 *----------------------------------------------------------------------
 */

static inline void
SetPrecisionLimits(
    int convType,		/* Type of conversion: TCL_DD_SHORTEST,
				 * TCL_DD_STEELE0, TCL_DD_E_FMT,
				 * TCL_DD_F_FMT. */
    int k,			/* Floor(log10(number to convert)) */
    int *ndigitsPtr,		/* IN/OUT: Number of digits requested (will be
				 *         adjusted if needed). */
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
 * Side effects:
 *	In the case that the string consists solely of '999999', sets it to
 *	"1" and moves the decimal point (*kPtr) one place to the right.
 *
 *----------------------------------------------------------------------
 */

inline static char *
BumpUp(
    char *s,		    	/* Cursor pointing one past the end of the
				 * string. */
    char *retval,		/* Start of the string of digits. */
    int *kPtr)			/* Position of the decimal point. */
{
    while (*--s == '9') {







|







2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
 * Side effects:
 *	In the case that the string consists solely of '999999', sets it to
 *	"1" and moves the decimal point (*kPtr) one place to the right.
 *
 *----------------------------------------------------------------------
 */

static inline char *
BumpUp(
    char *s,		    	/* Cursor pointing one past the end of the
				 * string. */
    char *retval,		/* Start of the string of digits. */
    int *kPtr)			/* Position of the decimal point. */
{
    while (*--s == '9') {
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
 * Results:
 *	Returns the precision that has been lost in the prescaling as a count
 *	of units in the least significant place.
 *
 *----------------------------------------------------------------------
 */

inline static int
AdjustRange(
    double *dPtr,		/* INOUT: Number to adjust. */
    int k)			/* IN: floor(log10(d)) */
{
    int ieps;			/* Number of roundoff errors that have
				 * accumulated. */
    double d = *dPtr;		/* Number to adjust. */







|







2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
 * Results:
 *	Returns the precision that has been lost in the prescaling as a count
 *	of units in the least significant place.
 *
 *----------------------------------------------------------------------
 */

static inline int
AdjustRange(
    double *dPtr,		/* INOUT: Number to adjust. */
    int k)			/* IN: floor(log10(d)) */
{
    int ieps;			/* Number of roundoff errors that have
				 * accumulated. */
    double d = *dPtr;		/* Number to adjust. */
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
 *
 * Side effects:
 *	Stores the position of the decimal point at '*kPtr'.
 *
 *----------------------------------------------------------------------
 */

inline static char *
ShorteningQuickFormat(
    double d,			/* Number to convert. */
    int k,			/* floor(log10(d)) */
    int ilim,			/* Number of significant digits to return. */
    double eps,			/* Estimated roundoff error. */
    char *retval,		/* Buffer to receive the digit string. */
    int *kPtr)			/* Pointer to stash the position of the







|







2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
 *
 * Side effects:
 *	Stores the position of the decimal point at '*kPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
ShorteningQuickFormat(
    double d,			/* Number to convert. */
    int k,			/* floor(log10(d)) */
    int ilim,			/* Number of significant digits to return. */
    double eps,			/* Estimated roundoff error. */
    char *retval,		/* Buffer to receive the digit string. */
    int *kPtr)			/* Pointer to stash the position of the
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
 *
 * Side effects:
 *	Stores the position of the decimal point in '*kPtr'.
 *
 *----------------------------------------------------------------------
 */

inline static char *
StrictQuickFormat(
    double d,			/* Number to convert. */
    int k,			/* floor(log10(d)) */
    int ilim,			/* Number of significant digits to return. */
    double eps,			/* Estimated roundoff error. */
    char *retval,		/* Start of the digit string. */
    int *kPtr)			/* Pointer to stash the position of the







|







2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
 *
 * Side effects:
 *	Stores the position of the decimal point in '*kPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
StrictQuickFormat(
    double d,			/* Number to convert. */
    int k,			/* floor(log10(d)) */
    int ilim,			/* Number of significant digits to return. */
    double eps,			/* Estimated roundoff error. */
    char *retval,		/* Start of the digit string. */
    int *kPtr)			/* Pointer to stash the position of the
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
 * Results:
 *	Returns the converted string, or NULL if the bignum method must be
 *	used.
 *
 *----------------------------------------------------------------------
 */

inline static char *
QuickConversion(
    double e,			/* Number to format. */
    int k,			/* floor(log10(d)), approximately. */
    int k_check,		/* 0 if k is exact, 1 if it may be too high */
    int flags,			/* Flags passed to dtoa:
				 *    TCL_DD_SHORTEN_FLAG */
    int len,			/* Length of the return value. */







|







2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
 * Results:
 *	Returns the converted string, or NULL if the bignum method must be
 *	used.
 *
 *----------------------------------------------------------------------
 */

static inline char *
QuickConversion(
    double e,			/* Number to format. */
    int k,			/* floor(log10(d)), approximately. */
    int k_check,		/* 0 if k is exact, 1 if it may be too high */
    int flags,			/* Flags passed to dtoa:
				 *    TCL_DD_SHORTEN_FLAG */
    int len,			/* Length of the return value. */
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
 *	Adjust the factors 'b2', 'm2', and 's2' to cast out common powers of 2
 *	from numerator and denominator in preparation for the 'bignum' method
 *	of floating point conversion.
 *
 *----------------------------------------------------------------------
 */

inline static void
CastOutPowersOf2(
    int *b2,			/* Power of 2 to multiply the significand. */
    int *m2,			/* Power of 2 to multiply 1/2 ulp. */
    int *s2)			/* Power of 2 to multiply the common
				 * denominator. */
{
    int i;







|







2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
 *	Adjust the factors 'b2', 'm2', and 's2' to cast out common powers of 2
 *	from numerator and denominator in preparation for the 'bignum' method
 *	of floating point conversion.
 *
 *----------------------------------------------------------------------
 */

static inline void
CastOutPowersOf2(
    int *b2,			/* Power of 2 to multiply the significand. */
    int *m2,			/* Power of 2 to multiply 1/2 ulp. */
    int *s2)			/* Power of 2 to multiply the common
				 * denominator. */
{
    int i;
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

inline static char *
ShorteningInt64Conversion(
    Double *dPtr,		/* Original number to convert. */
    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */
    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */







|







2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
ShorteningInt64Conversion(
    Double *dPtr,		/* Original number to convert. */
    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */
    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

inline static char *
StrictInt64Conversion(
    Double *dPtr,		/* Original number to convert. */
    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */
    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */







|







3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
StrictInt64Conversion(
    Double *dPtr,		/* Original number to convert. */
    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */
    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
 * Results:
 *	Returns 1 iff the fraction is more than 1/2, or if the fraction is
 *	exactly 1/2 and the digit is odd.
 *
 *----------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUpPowD(
    mp_int *b,			/* Numerator of the fraction. */
    int sd,			/* Denominator is 2**(sd*DIGIT_BIT). */
    int isodd)			/* 1 if the digit is odd, 0 if even. */
{
    int i;
    static const mp_digit topbit = 1 << (DIGIT_BIT - 1);







|







3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
 * Results:
 *	Returns 1 iff the fraction is more than 1/2, or if the fraction is
 *	exactly 1/2 and the digit is odd.
 *
 *----------------------------------------------------------------------
 */

static inline int
ShouldBankerRoundUpPowD(
    mp_int *b,			/* Numerator of the fraction. */
    int sd,			/* Denominator is 2**(sd*DIGIT_BIT). */
    int isodd)			/* 1 if the digit is odd, 0 if even. */
{
    int i;
    static const mp_digit topbit = 1 << (DIGIT_BIT - 1);
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
 * Results:
 *	Returns 1 if the rounding will be performed - which increases the
 *	digit by one - and 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUpToNextPowD(
    mp_int *b,			/* Numerator of the fraction. */
    mp_int *m,			/* Numerator of the rounding tolerance. */
    int sd,			/* Common denominator is 2**(sd*DIGIT_BIT). */
    int convType,		/* Conversion type: STEELE defeats
				 * round-to-even (not sure why one wants to do
				 * this; I copied it from Gay). FIXME */







|







3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
 * Results:
 *	Returns 1 if the rounding will be performed - which increases the
 *	digit by one - and 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

static inline int
ShouldBankerRoundUpToNextPowD(
    mp_int *b,			/* Numerator of the fraction. */
    mp_int *m,			/* Numerator of the rounding tolerance. */
    int sd,			/* Common denominator is 2**(sd*DIGIT_BIT). */
    int convType,		/* Conversion type: STEELE defeats
				 * round-to-even (not sure why one wants to do
				 * this; I copied it from Gay). FIXME */
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

inline static char *
ShorteningBignumConversionPowD(
    Double *dPtr,		/* Original number to convert. */
    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */
    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */







|







3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
ShorteningBignumConversionPowD(
    Double *dPtr,		/* Original number to convert. */
    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */
    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

inline static char *
StrictBignumConversionPowD(
    Double *dPtr,		/* Original number to convert. */
    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */
    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */







|







3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
StrictBignumConversionPowD(
    Double *dPtr,		/* Original number to convert. */
    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */
    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
 *
 * Results:
 *	Returns 1 if the number needs to be rounded up, 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUp(
    mp_int *twor,		/* 2x the remainder from thd division that
				 * produced the last digit. */
    mp_int *S,			/* Denominator. */
    int isodd)			/* Flag == 1 if the last digit is odd. */
{
    int r = mp_cmp_mag(twor, S);







|







3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
 *
 * Results:
 *	Returns 1 if the number needs to be rounded up, 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

static inline int
ShouldBankerRoundUp(
    mp_int *twor,		/* 2x the remainder from thd division that
				 * produced the last digit. */
    mp_int *S,			/* Denominator. */
    int isodd)			/* Flag == 1 if the last digit is odd. */
{
    int r = mp_cmp_mag(twor, S);
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
 *
 * Results:
 *	Returns 1 if the number should be rounded up, 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUpToNext(
    mp_int *b,			/* Remainder from the division that produced
				 * the last digit. */
    mp_int *m,			/* Numerator of the rounding tolerance. */
    mp_int *S,			/* Denominator. */
    int convType,		/* Conversion type: STEELE0 defeats
				 * round-to-even. (Not sure why one would want







|







3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
 *
 * Results:
 *	Returns 1 if the number should be rounded up, 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

static inline int
ShouldBankerRoundUpToNext(
    mp_int *b,			/* Remainder from the division that produced
				 * the last digit. */
    mp_int *m,			/* Numerator of the rounding tolerance. */
    mp_int *S,			/* Denominator. */
    int convType,		/* Conversion type: STEELE0 defeats
				 * round-to-even. (Not sure why one would want
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
 * Side effects:
 *	Stores the position of the decimal point in *decpt.  Stores a pointer
 *	to the end of the number in *endPtr.
 *
 *----------------------------------------------------------------------
 */

inline static char *
ShorteningBignumConversion(
    Double *dPtr,		/* Original number being converted. */
    int convType,		/* Conversion type. */
    Tcl_WideUInt bw,		/* Integer significand and exponent. */
    int b2,			/* Scale factor for the significand. */
    int m2plus, int m2minus,	/* Scale factors for 1/2 ulp in numerator. */
    int s2, int s5,		/* Scale factors for denominator. */







|







3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
 * Side effects:
 *	Stores the position of the decimal point in *decpt.  Stores a pointer
 *	to the end of the number in *endPtr.
 *
 *----------------------------------------------------------------------
 */

static inline char *
ShorteningBignumConversion(
    Double *dPtr,		/* Original number being converted. */
    int convType,		/* Conversion type. */
    Tcl_WideUInt bw,		/* Integer significand and exponent. */
    int b2,			/* Scale factor for the significand. */
    int m2plus, int m2minus,	/* Scale factors for 1/2 ulp in numerator. */
    int s2, int s5,		/* Scale factors for denominator. */
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
 * Side effects:
 *	Stores the position of the decimal point in *decpt.  Stores a pointer
 *	to the end of the number in *endPtr.
 *
 *----------------------------------------------------------------------
 */

inline static char *
StrictBignumConversion(
    Double *dPtr,		/* Original number being converted. */
    int convType,		/* Conversion type. */
    Tcl_WideUInt bw,		/* Integer significand and exponent. */
    int b2,			/* Scale factor for the significand. */
    int s2, int s5,		/* Scale factors for denominator. */
    int k,			/* Guessed position of the decimal point. */







|







3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
 * Side effects:
 *	Stores the position of the decimal point in *decpt.  Stores a pointer
 *	to the end of the number in *endPtr.
 *
 *----------------------------------------------------------------------
 */

static inline char *
StrictBignumConversion(
    Double *dPtr,		/* Original number being converted. */
    int convType,		/* Conversion type. */
    Tcl_WideUInt bw,		/* Integer significand and exponent. */
    int b2,			/* Scale factor for the significand. */
    int s2, int s5,		/* Scale factors for denominator. */
    int k,			/* Guessed position of the decimal point. */

Changes to generic/tclStringObj.c.

2025
2026
2027
2028
2029
2030
2031
2032



2033
2034
2035
2036
2037
2038
2039
2040
2041
	    if (gotHash || (ch == 'p')) {
		switch (ch) {
		case 'o':
		    Tcl_AppendToObj(segment, "0", 1);
		    segmentLimit -= 1;
		    precision--;
		    break;
		case 'p':



		case 'x':
		case 'X':
		    Tcl_AppendToObj(segment, "0x", 2);
		    segmentLimit -= 2;
		    break;
		case 'b':
		    Tcl_AppendToObj(segment, "0b", 2);
		    segmentLimit -= 2;
		    break;







|
>
>
>
|
|







2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
	    if (gotHash || (ch == 'p')) {
		switch (ch) {
		case 'o':
		    Tcl_AppendToObj(segment, "0", 1);
		    segmentLimit -= 1;
		    precision--;
		    break;
		case 'X':
		    Tcl_AppendToObj(segment, "0X", 2);
		    segmentLimit -= 2;
		    break;
		case 'p':
		case 'x':
		    Tcl_AppendToObj(segment, "0x", 2);
		    segmentLimit -= 2;
		    break;
		case 'b':
		    Tcl_AppendToObj(segment, "0b", 2);
		    segmentLimit -= 2;
		    break;
2196
2197
2198
2199
2200
2201
2202



2203

2204
2205
2206
2207
2208
2209
2210
			    bits |= ((Tcl_WideUInt) big.dp[index++]) << shift;
			    shift += DIGIT_BIT;
			}
			shift -= numBits;
		    }
		    digitOffset = (int) (bits % base);
		    if (digitOffset > 9) {



			bytes[numDigits] = 'a' + digitOffset - 10;

		    } else {
			bytes[numDigits] = '0' + digitOffset;
		    }
		    bits /= base;
		}
		if (useBig) {
		    mp_clear(&big);







>
>
>
|
>







2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
			    bits |= ((Tcl_WideUInt) big.dp[index++]) << shift;
			    shift += DIGIT_BIT;
			}
			shift -= numBits;
		    }
		    digitOffset = (int) (bits % base);
		    if (digitOffset > 9) {
			if (ch == 'X') {
			    bytes[numDigits] = 'A' + digitOffset - 10;
			} else {
			    bytes[numDigits] = 'a' + digitOffset - 10;
			}
		    } else {
			bytes[numDigits] = '0' + digitOffset;
		    }
		    bits /= base;
		}
		if (useBig) {
		    mp_clear(&big);
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
	default:
	    if (interp != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_ObjPrintf("bad field specifier \"%c\"", ch));
		Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL);
	    }
	    goto error;
	}

	switch (ch) {
	case 'E':
	case 'G':
	case 'X': {
	    Tcl_SetObjLength(segment, Tcl_UtfToUpper(TclGetString(segment)));
	}
	}

	if (width>0 && numChars<0) {
	    numChars = Tcl_GetCharLength(segment);
	}
	if (!gotMinus && width>0) {
	    if (numChars < width) {







<
<
<
<
<
<
<
<







2323
2324
2325
2326
2327
2328
2329








2330
2331
2332
2333
2334
2335
2336
	default:
	    if (interp != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_ObjPrintf("bad field specifier \"%c\"", ch));
		Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL);
	    }
	    goto error;








	}

	if (width>0 && numChars<0) {
	    numChars = Tcl_GetCharLength(segment);
	}
	if (!gotMinus && width>0) {
	    if (numChars < width) {

Changes to library/init.tcl.

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

317

318
319
320


321
322
323





324
325
326



327
328


329
330
331
332
333
334
335
		if {[string bytelength $cinfo] > 150} {
		    set cinfo [string range $cinfo 0 150]
		    while {[string bytelength $cinfo] > 150} {
			set cinfo [string range $cinfo 0 end-1]
		    }
		    append cinfo ...
		}
		append cinfo "\"\n    (\"uplevel\" body line 1)"
		append cinfo "\n    invoked from within"
		append cinfo "\n\"uplevel 1 \$args\""
		#
		# Try each possible form of the stack trace
		# and trim the extra contribution from the matching case
		#
		set expect "$msg\n    while executing\n\"$cinfo"
		if {$errInfo eq $expect} {
		    #
		    # The stack has only the eval from the expanded command
		    # Do not generate any stack trace here.
		    #
		    dict unset opts -errorinfo
		    dict incr opts -level
		    return -options $opts $msg
		}
		#
		# Stack trace is nested, trim off just the contribution
		# from the extra "eval" of $args due to the "catch" above.
		#
		set expect "\n    invoked from within\n\"$cinfo"
		set exlen [string length $expect]
		set eilen [string length $errInfo]

		set i [expr {$eilen - $exlen - 1}]

		set einfo [string range $errInfo 0 $i]
		#
		# For now verify that $errInfo consists of what we are about


		# to return plus what we expected to trim off.
		#
		if {$errInfo ne "$einfo$expect"} {





		    error "Tcl bug: unexpected stack trace in \"unknown\"" {} \
			[list CORE UNKNOWN BADTRACE $einfo $expect $errInfo]
		}



		return -code error -errorcode $errCode \
			-errorinfo $einfo $msg


	    } else {
		dict incr opts -level
		return -options $opts $msg
	    }
	}
    }








|
<
|
<
<
<
<
|













<
|
|
>
|
>
|
<
|
>
>
|
<
|
>
>
>
>
>
|
|

>
>
>
|
|
>
>







286
287
288
289
290
291
292
293

294




295
296
297
298
299
300
301
302
303
304
305
306
307
308

309
310
311
312
313
314

315
316
317
318

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
		if {[string bytelength $cinfo] > 150} {
		    set cinfo [string range $cinfo 0 150]
		    while {[string bytelength $cinfo] > 150} {
			set cinfo [string range $cinfo 0 end-1]
		    }
		    append cinfo ...
		}
		set tail "\n    (\"uplevel\" body line 1)\n    invoked\

			from within\n\"uplevel 1 \$args\""




		set expect "$msg\n    while executing\n\"$cinfo\"$tail"
		if {$errInfo eq $expect} {
		    #
		    # The stack has only the eval from the expanded command
		    # Do not generate any stack trace here.
		    #
		    dict unset opts -errorinfo
		    dict incr opts -level
		    return -options $opts $msg
		}
		#
		# Stack trace is nested, trim off just the contribution
		# from the extra "eval" of $args due to the "catch" above.
		#

		set last [string last $tail $errInfo]
		if {$last + [string length $tail] != [string length $errInfo]} {
		    # Very likely cannot happen
		    return -options $opts $msg
		}
		set errInfo [string range $errInfo 0 $last-1]

		set tail "\"$cinfo\""
		set last [string last $tail $errInfo]
		if {$last + [string length $tail] != [string length $errInfo]} {
		    return -code error -errorcode $errCode \

			    -errorinfo $errInfo $msg
		}
		set errInfo [string range $errInfo 0 $last-1]
		set tail "\n    invoked from within\n"
		set last [string last $tail $errInfo]
		if {$last + [string length $tail] == [string length $errInfo]} {
		    return -code error -errorcode $errCode \
			    -errorinfo [string range $errInfo 0 $last-1] $msg
		}
		set tail "\n    while executing\n"
		set last [string last $tail $errInfo]
		if {$last + [string length $tail] == [string length $errInfo]} {
		    return -code error -errorcode $errCode \
			    -errorinfo [string range $errInfo 0 $last-1] $msg
		}
		return -options $opts $msg
	    } else {
		dict incr opts -level
		return -options $opts $msg
	    }
	}
    }

Changes to tests/init.test.

163
164
165
166
167
168
169










170
171
172
173
174
175
176
	set first $::errorInfo
	catch {parray ::junk::$arg}
	list $first $::errorInfo
    } -match pairwise -result equal

    incr count
}











test init-5.0 {return options passed through ::unknown} -setup {
    catch {rename xxx {}}
    set ::auto_index(::xxx) {proc ::xxx {} {
	return -code error -level 2 xxx
    }}
} -body {







>
>
>
>
>
>
>
>
>
>







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
	set first $::errorInfo
	catch {parray ::junk::$arg}
	list $first $::errorInfo
    } -match pairwise -result equal

    incr count
}

test init-4.$count {[Bug 46f801ed5a]} -setup {
    auto_reset
    array set auto_index {demo {proc demo {} {tailcall error foo}}}
} -body {
    demo
} -cleanup {
    array unset auto_index demo
    rename demo {}
} -returnCodes error -result foo

test init-5.0 {return options passed through ::unknown} -setup {
    catch {rename xxx {}}
    set ::auto_index(::xxx) {proc ::xxx {} {
	return -code error -level 2 xxx
    }}
} -body {

Changes to unix/tclooConfig.sh.

12
13
14
15
16
17
18
19
# These are mostly empty because no special steps are ever needed from Tcl 8.6
# onwards; all libraries and include files are just part of Tcl.
TCLOO_LIB_SPEC=""
TCLOO_STUB_LIB_SPEC=""
TCLOO_INCLUDE_SPEC=""
TCLOO_PRIVATE_INCLUDE_SPEC=""
TCLOO_CFLAGS=""
TCLOO_VERSION=1.0.4







|
12
13
14
15
16
17
18
19
# These are mostly empty because no special steps are ever needed from Tcl 8.6
# onwards; all libraries and include files are just part of Tcl.
TCLOO_LIB_SPEC=""
TCLOO_STUB_LIB_SPEC=""
TCLOO_INCLUDE_SPEC=""
TCLOO_PRIVATE_INCLUDE_SPEC=""
TCLOO_CFLAGS=""
TCLOO_VERSION=1.2.0

Changes to win/tclooConfig.sh.

12
13
14
15
16
17
18
19
# These are mostly empty because no special steps are ever needed from Tcl 8.6
# onwards; all libraries and include files are just part of Tcl.
TCLOO_LIB_SPEC=""
TCLOO_STUB_LIB_SPEC=""
TCLOO_INCLUDE_SPEC=""
TCLOO_PRIVATE_INCLUDE_SPEC=""
TCLOO_CFLAGS=""
TCLOO_VERSION=1.0.4







|
12
13
14
15
16
17
18
19
# These are mostly empty because no special steps are ever needed from Tcl 8.6
# onwards; all libraries and include files are just part of Tcl.
TCLOO_LIB_SPEC=""
TCLOO_STUB_LIB_SPEC=""
TCLOO_INCLUDE_SPEC=""
TCLOO_PRIVATE_INCLUDE_SPEC=""
TCLOO_CFLAGS=""
TCLOO_VERSION=1.2.0