Tcl Source Code

Check-in [7eb94b8f21]
Login

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

Overview
Comment:merge novem
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dgp-refactor
Files: files | file ages | folders
SHA1: 7eb94b8f213c2f5ed4fcb13f82ce5eae794f9442
User & Date: dgp 2017-07-06 16:58:39
Context
2017-07-18
13:46
merge novem check-in: 56f00462f4 user: dgp tags: dgp-refactor
2017-07-06
16:58
merge novem check-in: 7eb94b8f21 user: dgp tags: dgp-refactor
16:52
merge trunk check-in: 4dc6e2e33e user: dgp tags: novem
2017-06-29
11:42
merge novem check-in: 76a8ebccd9 user: dgp tags: dgp-refactor
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

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.

1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
 *
 * 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;







|







1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
 *
 * 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;
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
 *
 * 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)) {







|







1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
 *
 * 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)) {
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
 *	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. */
{







|







2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
 *	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. */
{
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
 * 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;







|







2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
 * 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;
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
 * 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;








|







2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
 * 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;

2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
 * 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");







|







2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
 * 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");
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
 * 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) */







|







2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
 * 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) */
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
 *
 * 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. */
{
    /*







|







2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
 *
 * 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. */
{
    /*
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
 *	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. */







|







2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
 *	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. */
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
 *	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). */







|







2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
 *	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). */
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
 * 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') {







|







2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
 * 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') {
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
 * 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. */







|







2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
 * 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. */
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
 *
 * 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







|







2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
 *
 * 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
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
 *
 * 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







|







2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
 *
 * 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
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
 * 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. */







|







2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
 * 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. */
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
 *	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;







|







2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
 *	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;
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
 * 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. */







|







2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
 * 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. */
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
 * 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. */







|







3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
 * 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. */
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
 * 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);







|







3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
 * 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);
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
 * 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 */







|







3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
 * 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 */
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
 * 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. */







|







3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
 * 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. */
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
 * 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. */







|







3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
 * 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. */
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
 *
 * 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);







|







3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
 *
 * 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);
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
 *
 * 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







|







3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
 *
 * 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
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
 * 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. */







|







3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
 * 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. */
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
 * 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. */







|







3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
 * 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. */