Diff
Not logged in

Differences From Artifact [41f158ed26]:

To Artifact [f646e98e52]:


10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24







-
+







 *	'double' and 'mp_int' types.
 *
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclStrToD.c,v 1.4.2.8 2005/12/02 18:42:08 dgp Exp $
 * RCS: @(#) $Id: tclStrToD.c,v 1.4.2.9 2006/01/25 18:38:31 dgp Exp $
 *
 *----------------------------------------------------------------------
 */

#include <tclInt.h>
#include <stdio.h>
#include <stdlib.h>
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187







-
+














+







 *	negative, the first NUL byte encountered will terminate the scan.
 *	If numBytes is non-negative, then no more than numBytes bytes will
 *	be scanned.  
 *
 *	The argument flags is an input that controls the numeric formats
 *	recognized by the parser.  The flag bits are:
 *
 *	 - TCL_PARSE_INTEGER_ONLY:	accept only integer values; reject
 *	- TCL_PARSE_INTEGER_ONLY:	accept only integer values; reject
 *		strings that denote floating point values (or accept only the
 *		leading portion of them that are integer values).
 *	- TCL_PARSE_SCAN_PREFIXES:	ignore the prefixes 0b and 0o that are
 *		not part of the [scan] command's vocabulary. Use only in
 *		combination with TCL_PARSE_INTEGER_ONLY.
 * 	- TCL_PARSE_OCTAL_ONLY:		parse only in the octal format, whether
 *		or not a prefix is present that would lead to octal parsing. Use
 *		only in combination with TCL_PARSE_INTEGER_ONLY.
 * 	- TCL_PARSE_HEXADECIMAL_ONLY:	parse only in the hexadecimal format,
 *		whether or not a prefix is present that would lead to
 *		hexadecimal parsing. Use only in combination with
 *		TCL_PARSE_INTEGER_ONLY.
 * 	- TCL_PARSE_DECIMAL_ONLY:	parse only in the decimal format, no
 *		matter whether a 0 prefix would normally force a different base.
 *	- TCL_PARSE_NO_WHITESPACE:	reject any leading/trailing whitespace
 *
 *	The arguments interp and expected are inputs that control error message
 * 	generation.  If interp is NULL, no error message will be generated.
 *	If interp is non-NULL, then expected must also be non-NULL.  When
 *	TCL_ERROR is returned, an error message will be left in the result
 *	of interp, and the expected argument will appear in the error message
 *	as the thing TclParseNumber expected, but failed to find in the string.
200
201
202
203
204
205
206
207

208
209
210
211
212
213


214
215
216
217
218




219
220
221
222
223
224
225
201
202
203
204
205
206
207

208
209





210
211
212




213
214
215
216
217
218
219
220
221
222
223







-
+

-
-
-
-
-
+
+

-
-
-
-
+
+
+
+







 *	then the internal rep and Tcl_ObjType of objPtr are set	to the
 *	"canonical" numeric value that matches the scanned string.  If
 *	endPtrPtr is non-NULL, a pointer to the end of the string will be
 *	written to *endPtrPtr (that is, either bytes+numBytes or a pointer
 *	to a terminating NUL byte).
 *
 *	When the parser determines that a partial string matches a format
 *	it is looking for, the value of endPtrPtr determines what happens.
 *	it is looking for, the value of endPtrPtr determines what happens:
 *
 *	If endPtrPtr is NULL, then the remainder of the string is scanned
 *	and if it consists entirely of trailing whitespace, then TCL_OK is
 *	returned and objPtr internals are set as above.  If any non-whitespace
 *	is encountered, TCL_ERROR is returned, with error message generation
 *	as above.
 *	- If endPtrPtr is NULL, then TCL_ERROR is returned, with error message
 *		generation as above.
 *
 *	When the parser detects a partial string match and endPtrPtr is
 *	non-NULL, then TCL_OK is returned and objPtr internals are set as
 *	above.  Also, a pointer to the first character following the parsed
 *	numeric string is written to *endPtrPtr.
 *	- If endPtrPtr is non-NULL, then TCL_OK is returned and objPtr
 *		internals are set as above.  Also, a pointer to the first
 *		character following the parsed numeric string is written
 *		to *endPtrPtr.
 *
 *	In some cases where the string being scanned is the string rep of
 *	objPtr, this routine can leave objPtr in an inconsistent state
 *	where its string rep and its internal rep do not agree.  In these
 *	cases the internal rep will be in agreement with only some substring
 *	of the string rep.  This might happen if the caller passes in a
 * 	non-NULL bytes value that points somewhere into the string rep.  It
331
332
333
334
335
336
337



338
339
340
341
342
343
344
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345







+
+
+







	case INITIAL:
	    /*
	     * Initial state. Acceptable characters are +, -, digits, period,
	     * I, N, and whitespace.
	     */

	    if (isspace(UCHAR(c))) {
		if (flags & TCL_PARSE_NO_WHITESPACE) {
		    goto endgame;
		}
		break;
	    } else if (c == '+') {
		state = SIGNUM;
		break;
	    } else if (c == '-') {
		signum = 1;
		state = SIGNUM;
889
890
891
892
893
894
895
896

897
898
899
900
901


902
903
904
905
906
907
908
890
891
892
893
894
895
896

897
898
899
900
901
902
903
904
905
906
907
908
909
910
911







-
+





+
+







	if (endPtrPtr != NULL) {
	    *endPtrPtr = p;
	}
    } else {
	/* Back up to the last accepting state in the lexer. */
	p = acceptPoint;
	len = acceptLen;
	if (endPtrPtr == NULL) {
	if (!(flags & TCL_PARSE_NO_WHITESPACE)) {
	    /* Accept trailing whitespace */
	    while (len != 0 && isspace(UCHAR(*p))) {
		++p;
		--len;
	    }
	}
	if (endPtrPtr == NULL) {
	    if ((len != 0) && ((numBytes > 0) || (*p != '\0'))) {
		status = TCL_ERROR;
	    }
	} else {
	    *endPtrPtr = p;
	}
    }
2207
2208
2209
2210
2211
2212
2213
2214

2215
2216
2217
2218
2219
2220
2221
2222
2223
2224


2225
2226
2227
2228
2229
2230

2231
2232
2233
2234
2235
2236
2237
2210
2211
2212
2213
2214
2215
2216

2217
2218
2219
2220
2221
2222
2223
2224
2225


2226
2227
2228
2229
2230
2231
2232

2233
2234
2235
2236
2237
2238
2239
2240







-
+








-
-
+
+





-
+







	mp_clear(pow5 + i);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitBignumFromDouble --
 * Tcl_InitBignumFromDouble --
 *
 *	Extracts the integer part of a double and converts it to an arbitrary
 *	precision integer.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Initializes the bignum supplied, and stores the converted number * in
 *	it.
 *	Initializes the bignum supplied, and stores the converted number 
 *      in it.
 *
 *----------------------------------------------------------------------
 */

int
TclInitBignumFromDouble(
Tcl_InitBignumFromDouble(
    Tcl_Interp *interp,		/* For error message */
    double d,			/* Number to convert */
    mp_int *b)			/* Place to store the result */
{
    double fract;
    int expt;