Coverage Report

Created: 2022-07-08 09:39

/home/mdboom/Work/builds/cpython/Python/pystrtod.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; c-file-style: "python" -*- */
2
3
#include <Python.h>
4
#include "pycore_dtoa.h"          // _Py_dg_strtod()
5
#include "pycore_pymath.h"        // _PY_SHORT_FLOAT_REPR
6
#include <locale.h>
7
8
/* Case-insensitive string match used for nan and inf detection; t should be
9
   lower-case.  Returns 1 for a successful match, 0 otherwise. */
10
11
static int
12
case_insensitive_match(const char *s, const char *t)
13
{
14
    while(*t && 
Py_TOLOWER42.6k
(*s) == *t42.6k
) {
  Branch (14:11): [True: 42.6k, False: 4.99k]
  Branch (14:17): [True: 15.2k, False: 27.4k]
15
        s++;
16
        t++;
17
    }
18
    return *t ? 
027.4k
:
14.99k
;
  Branch (18:12): [True: 27.4k, False: 4.99k]
19
}
20
21
/* _Py_parse_inf_or_nan: Attempt to parse a string of the form "nan", "inf" or
22
   "infinity", with an optional leading sign of "+" or "-".  On success,
23
   return the NaN or Infinity as a double and set *endptr to point just beyond
24
   the successfully parsed portion of the string.  On failure, return -1.0 and
25
   set *endptr to point to the start of the string. */
26
27
#if _PY_SHORT_FLOAT_REPR == 1
28
29
double
30
_Py_parse_inf_or_nan(const char *p, char **endptr)
31
{
32
    double retval;
33
    const char *s;
34
    int negate = 0;
35
36
    s = p;
37
    if (*s == '-') {
  Branch (37:9): [True: 6.55k, False: 9.64k]
38
        negate = 1;
39
        s++;
40
    }
41
    else if (*s == '+') {
  Branch (41:14): [True: 514, False: 9.13k]
42
        s++;
43
    }
44
    if (case_insensitive_match(s, "inf")) {
  Branch (44:9): [True: 2.90k, False: 13.2k]
45
        s += 3;
46
        if (case_insensitive_match(s, "inity"))
  Branch (46:13): [True: 108, False: 2.80k]
47
            s += 5;
48
        retval = _Py_dg_infinity(negate);
49
    }
50
    else if (case_insensitive_match(s, "nan")) {
  Branch (50:14): [True: 1.97k, False: 11.3k]
51
        s += 3;
52
        retval = _Py_dg_stdnan(negate);
53
    }
54
    else {
55
        s = p;
56
        retval = -1.0;
57
    }
58
    *endptr = (char *)s;
59
    return retval;
60
}
61
62
#else
63
64
double
65
_Py_parse_inf_or_nan(const char *p, char **endptr)
66
{
67
    double retval;
68
    const char *s;
69
    int negate = 0;
70
71
    s = p;
72
    if (*s == '-') {
73
        negate = 1;
74
        s++;
75
    }
76
    else if (*s == '+') {
77
        s++;
78
    }
79
    if (case_insensitive_match(s, "inf")) {
80
        s += 3;
81
        if (case_insensitive_match(s, "inity"))
82
            s += 5;
83
        retval = negate ? -Py_HUGE_VAL : Py_HUGE_VAL;
84
    }
85
    else if (case_insensitive_match(s, "nan")) {
86
        s += 3;
87
        retval = negate ? -Py_NAN : Py_NAN;
88
    }
89
    else {
90
        s = p;
91
        retval = -1.0;
92
    }
93
    *endptr = (char *)s;
94
    return retval;
95
}
96
97
#endif
98
99
/**
100
 * _PyOS_ascii_strtod:
101
 * @nptr:    the string to convert to a numeric value.
102
 * @endptr:  if non-%NULL, it returns the character after
103
 *           the last character used in the conversion.
104
 *
105
 * Converts a string to a #gdouble value.
106
 * This function behaves like the standard strtod() function
107
 * does in the C locale. It does this without actually
108
 * changing the current locale, since that would not be
109
 * thread-safe.
110
 *
111
 * This function is typically used when reading configuration
112
 * files or other non-user input that should be locale independent.
113
 * To handle input from the user you should normally use the
114
 * locale-sensitive system strtod() function.
115
 *
116
 * If the correct value would cause overflow, plus or minus %HUGE_VAL
117
 * is returned (according to the sign of the value), and %ERANGE is
118
 * stored in %errno. If the correct value would cause underflow,
119
 * zero is returned and %ERANGE is stored in %errno.
120
 * If memory allocation fails, %ENOMEM is stored in %errno.
121
 *
122
 * This function resets %errno before calling strtod() so that
123
 * you can reliably detect overflow and underflow.
124
 *
125
 * Return value: the #gdouble value.
126
 **/
127
128
#if _PY_SHORT_FLOAT_REPR == 1
129
130
static double
131
_PyOS_ascii_strtod(const char *nptr, char **endptr)
132
{
133
    double result;
134
    _Py_SET_53BIT_PRECISION_HEADER;
135
136
    assert(nptr != NULL);
137
    /* Set errno to zero, so that we can distinguish zero results
138
       and underflows */
139
    errno = 0;
140
141
    _Py_SET_53BIT_PRECISION_START;
142
    result = _Py_dg_strtod(nptr, endptr);
143
    _Py_SET_53BIT_PRECISION_END;
144
145
    if (*endptr == nptr)
  Branch (145:9): [True: 5.99k, False: 58.2k]
146
        /* string might represent an inf or nan */
147
        result = _Py_parse_inf_or_nan(nptr, endptr);
148
149
    return result;
150
151
}
152
153
#else
154
155
/*
156
   Use system strtod;  since strtod is locale aware, we may
157
   have to first fix the decimal separator.
158
159
   Note that unlike _Py_dg_strtod, the system strtod may not always give
160
   correctly rounded results.
161
*/
162
163
static double
164
_PyOS_ascii_strtod(const char *nptr, char **endptr)
165
{
166
    char *fail_pos;
167
    double val;
168
    struct lconv *locale_data;
169
    const char *decimal_point;
170
    size_t decimal_point_len;
171
    const char *p, *decimal_point_pos;
172
    const char *end = NULL; /* Silence gcc */
173
    const char *digits_pos = NULL;
174
    int negate = 0;
175
176
    assert(nptr != NULL);
177
178
    fail_pos = NULL;
179
180
    locale_data = localeconv();
181
    decimal_point = locale_data->decimal_point;
182
    decimal_point_len = strlen(decimal_point);
183
184
    assert(decimal_point_len != 0);
185
186
    decimal_point_pos = NULL;
187
188
    /* Parse infinities and nans */
189
    val = _Py_parse_inf_or_nan(nptr, endptr);
190
    if (*endptr != nptr)
191
        return val;
192
193
    /* Set errno to zero, so that we can distinguish zero results
194
       and underflows */
195
    errno = 0;
196
197
    /* We process the optional sign manually, then pass the remainder to
198
       the system strtod.  This ensures that the result of an underflow
199
       has the correct sign. (bug #1725)  */
200
    p = nptr;
201
    /* Process leading sign, if present */
202
    if (*p == '-') {
203
        negate = 1;
204
        p++;
205
    }
206
    else if (*p == '+') {
207
        p++;
208
    }
209
210
    /* Some platform strtods accept hex floats; Python shouldn't (at the
211
       moment), so we check explicitly for strings starting with '0x'. */
212
    if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X'))
213
        goto invalid_string;
214
215
    /* Check that what's left begins with a digit or decimal point */
216
    if (!Py_ISDIGIT(*p) && *p != '.')
217
        goto invalid_string;
218
219
    digits_pos = p;
220
    if (decimal_point[0] != '.' ||
221
        decimal_point[1] != 0)
222
    {
223
        /* Look for a '.' in the input; if present, it'll need to be
224
           swapped for the current locale's decimal point before we
225
           call strtod.  On the other hand, if we find the current
226
           locale's decimal point then the input is invalid. */
227
        while (Py_ISDIGIT(*p))
228
            p++;
229
230
        if (*p == '.')
231
        {
232
            decimal_point_pos = p++;
233
234
            /* locate end of number */
235
            while (Py_ISDIGIT(*p))
236
                p++;
237
238
            if (*p == 'e' || *p == 'E')
239
                p++;
240
            if (*p == '+' || *p == '-')
241
                p++;
242
            while (Py_ISDIGIT(*p))
243
                p++;
244
            end = p;
245
        }
246
        else if (strncmp(p, decimal_point, decimal_point_len) == 0)
247
            /* Python bug #1417699 */
248
            goto invalid_string;
249
        /* For the other cases, we need not convert the decimal
250
           point */
251
    }
252
253
    if (decimal_point_pos) {
254
        char *copy, *c;
255
        /* Create a copy of the input, with the '.' converted to the
256
           locale-specific decimal point */
257
        copy = (char *)PyMem_Malloc(end - digits_pos +
258
                                    1 + decimal_point_len);
259
        if (copy == NULL) {
260
            *endptr = (char *)nptr;
261
            errno = ENOMEM;
262
            return val;
263
        }
264
265
        c = copy;
266
        memcpy(c, digits_pos, decimal_point_pos - digits_pos);
267
        c += decimal_point_pos - digits_pos;
268
        memcpy(c, decimal_point, decimal_point_len);
269
        c += decimal_point_len;
270
        memcpy(c, decimal_point_pos + 1,
271
               end - (decimal_point_pos + 1));
272
        c += end - (decimal_point_pos + 1);
273
        *c = 0;
274
275
        val = strtod(copy, &fail_pos);
276
277
        if (fail_pos)
278
        {
279
            if (fail_pos > decimal_point_pos)
280
                fail_pos = (char *)digits_pos +
281
                    (fail_pos - copy) -
282
                    (decimal_point_len - 1);
283
            else
284
                fail_pos = (char *)digits_pos +
285
                    (fail_pos - copy);
286
        }
287
288
        PyMem_Free(copy);
289
290
    }
291
    else {
292
        val = strtod(digits_pos, &fail_pos);
293
    }
294
295
    if (fail_pos == digits_pos)
296
        goto invalid_string;
297
298
    if (negate && fail_pos != nptr)
299
        val = -val;
300
    *endptr = fail_pos;
301
302
    return val;
303
304
  invalid_string:
305
    *endptr = (char*)nptr;
306
    errno = EINVAL;
307
    return -1.0;
308
}
309
310
#endif
311
312
/* PyOS_string_to_double converts a null-terminated byte string s (interpreted
313
   as a string of ASCII characters) to a float.  The string should not have
314
   leading or trailing whitespace.  The conversion is independent of the
315
   current locale.
316
317
   If endptr is NULL, try to convert the whole string.  Raise ValueError and
318
   return -1.0 if the string is not a valid representation of a floating-point
319
   number.
320
321
   If endptr is non-NULL, try to convert as much of the string as possible.
322
   If no initial segment of the string is the valid representation of a
323
   floating-point number then *endptr is set to point to the beginning of the
324
   string, -1.0 is returned and again ValueError is raised.
325
326
   On overflow (e.g., when trying to convert '1e500' on an IEEE 754 machine),
327
   if overflow_exception is NULL then +-Py_HUGE_VAL is returned, and no Python
328
   exception is raised.  Otherwise, overflow_exception should point to
329
   a Python exception, this exception will be raised, -1.0 will be returned,
330
   and *endptr will point just past the end of the converted value.
331
332
   If any other failure occurs (for example lack of memory), -1.0 is returned
333
   and the appropriate Python exception will have been set.
334
*/
335
336
double
337
PyOS_string_to_double(const char *s,
338
                      char **endptr,
339
                      PyObject *overflow_exception)
340
{
341
    double x, result=-1.0;
342
    char *fail_pos;
343
344
    errno = 0;
345
    x = _PyOS_ascii_strtod(s, &fail_pos);
346
347
    if (errno == ENOMEM) {
  Branch (347:9): [True: 0, False: 64.2k]
348
        PyErr_NoMemory();
349
        fail_pos = (char *)s;
350
    }
351
    else if (!endptr && 
(7.94k
fail_pos == s7.94k
||
*fail_pos != '\0'7.94k
))
  Branch (351:14): [True: 7.94k, False: 56.2k]
  Branch (351:26): [True: 2, False: 7.94k]
  Branch (351:43): [True: 3, False: 7.94k]
352
        PyErr_Format(PyExc_ValueError,
353
                      "could not convert string to float: "
354
                      "'%.200s'", s);
355
    else if (fail_pos == s)
  Branch (355:14): [True: 1.32k, False: 62.8k]
356
        PyErr_Format(PyExc_ValueError,
357
                      "could not convert string to float: "
358
                      "'%.200s'", s);
359
    else if (errno == ERANGE && 
fabs(x) >= 1.01.33k
&&
overflow_exception1.33k
)
  Branch (359:14): [True: 1.33k, False: 61.5k]
  Branch (359:33): [True: 1.33k, False: 0]
  Branch (359:51): [True: 0, False: 1.33k]
360
        PyErr_Format(overflow_exception,
361
                      "value too large to convert to float: "
362
                      "'%.200s'", s);
363
    else
364
        result = x;
365
366
    if (endptr != NULL)
  Branch (366:9): [True: 56.2k, False: 7.94k]
367
        *endptr = fail_pos;
368
    return result;
369
}
370
371
/* Remove underscores that follow the underscore placement rule from
372
   the string and then call the `innerfunc` function on the result.
373
   It should return a new object or NULL on exception.
374
375
   `what` is used for the error message emitted when underscores are detected
376
   that don't follow the rule. `arg` is an opaque pointer passed to the inner
377
   function.
378
379
   This is used to implement underscore-agnostic conversion for floats
380
   and complex numbers.
381
*/
382
PyObject *
383
_Py_string_to_number_with_underscores(
384
    const char *s, Py_ssize_t orig_len, const char *what, PyObject *obj, void *arg,
385
    PyObject *(*innerfunc)(const char *, Py_ssize_t, void *))
386
{
387
    char prev;
388
    const char *p, *last;
389
    char *dup, *end;
390
    PyObject *result;
391
392
    assert(s[orig_len] == '\0');
393
394
    if (strchr(s, '_') == NULL) {
  Branch (394:9): [True: 54.4k, False: 96]
395
        return innerfunc(s, orig_len, arg);
396
    }
397
398
    dup = PyMem_Malloc(orig_len + 1);
399
    if (dup == NULL) {
  Branch (399:9): [True: 0, False: 96]
400
        return PyErr_NoMemory();
401
    }
402
    end = dup;
403
    prev = '\0';
404
    last = s + orig_len;
405
    for (p = s; *p; 
p++524
) {
  Branch (405:17): [True: 567, False: 53]
406
        if (*p == '_') {
  Branch (406:13): [True: 138, False: 429]
407
            /* Underscores are only allowed after digits. */
408
            if (!(prev >= '0' && 
prev <= '9'127
)) {
  Branch (408:19): [True: 127, False: 11]
  Branch (408:34): [True: 110, False: 17]
409
                goto error;
410
            }
411
        }
412
        else {
413
            *end++ = *p;
414
            /* Underscores are only allowed before digits. */
415
            if (prev == '_' && 
!(98
*p >= '0'98
&&
*p <= '9'94
)) {
  Branch (415:17): [True: 98, False: 331]
  Branch (415:34): [True: 94, False: 4]
  Branch (415:47): [True: 83, False: 11]
416
                goto error;
417
            }
418
        }
419
        prev = *p;
420
    }
421
    /* Underscores are not allowed at the end. */
422
    if (prev == '_') {
  Branch (422:9): [True: 4, False: 49]
423
        goto error;
424
    }
425
    /* No embedded NULs allowed. */
426
    if (p != last) {
  Branch (426:9): [True: 1, False: 48]
427
        goto error;
428
    }
429
    *end = '\0';
430
    result = innerfunc(dup, end - dup, arg);
431
    PyMem_Free(dup);
432
    return result;
433
434
  error:
435
    PyMem_Free(dup);
436
    PyErr_Format(PyExc_ValueError,
437
                 "could not convert string to %s: "
438
                 "%R", what, obj);
439
    return NULL;
440
}
441
442
#if _PY_SHORT_FLOAT_REPR == 0
443
444
/* Given a string that may have a decimal point in the current
445
   locale, change it back to a dot.  Since the string cannot get
446
   longer, no need for a maximum buffer size parameter. */
447
Py_LOCAL_INLINE(void)
448
change_decimal_from_locale_to_dot(char* buffer)
449
{
450
    struct lconv *locale_data = localeconv();
451
    const char *decimal_point = locale_data->decimal_point;
452
453
    if (decimal_point[0] != '.' || decimal_point[1] != 0) {
454
        size_t decimal_point_len = strlen(decimal_point);
455
456
        if (*buffer == '+' || *buffer == '-')
457
            buffer++;
458
        while (Py_ISDIGIT(*buffer))
459
            buffer++;
460
        if (strncmp(buffer, decimal_point, decimal_point_len) == 0) {
461
            *buffer = '.';
462
            buffer++;
463
            if (decimal_point_len > 1) {
464
                /* buffer needs to get smaller */
465
                size_t rest_len = strlen(buffer +
466
                                     (decimal_point_len - 1));
467
                memmove(buffer,
468
                    buffer + (decimal_point_len - 1),
469
                    rest_len);
470
                buffer[rest_len] = 0;
471
            }
472
        }
473
    }
474
}
475
476
477
/* From the C99 standard, section 7.19.6:
478
The exponent always contains at least two digits, and only as many more digits
479
as necessary to represent the exponent.
480
*/
481
#define MIN_EXPONENT_DIGITS 2
482
483
/* Ensure that any exponent, if present, is at least MIN_EXPONENT_DIGITS
484
   in length. */
485
Py_LOCAL_INLINE(void)
486
ensure_minimum_exponent_length(char* buffer, size_t buf_size)
487
{
488
    char *p = strpbrk(buffer, "eE");
489
    if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {
490
        char *start = p + 2;
491
        int exponent_digit_cnt = 0;
492
        int leading_zero_cnt = 0;
493
        int in_leading_zeros = 1;
494
        int significant_digit_cnt;
495
496
        /* Skip over the exponent and the sign. */
497
        p += 2;
498
499
        /* Find the end of the exponent, keeping track of leading
500
           zeros. */
501
        while (*p && Py_ISDIGIT(*p)) {
502
            if (in_leading_zeros && *p == '0')
503
                ++leading_zero_cnt;
504
            if (*p != '0')
505
                in_leading_zeros = 0;
506
            ++p;
507
            ++exponent_digit_cnt;
508
        }
509
510
        significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;
511
        if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {
512
            /* If there are 2 exactly digits, we're done,
513
               regardless of what they contain */
514
        }
515
        else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {
516
            int extra_zeros_cnt;
517
518
            /* There are more than 2 digits in the exponent.  See
519
               if we can delete some of the leading zeros */
520
            if (significant_digit_cnt < MIN_EXPONENT_DIGITS)
521
                significant_digit_cnt = MIN_EXPONENT_DIGITS;
522
            extra_zeros_cnt = exponent_digit_cnt -
523
                significant_digit_cnt;
524
525
            /* Delete extra_zeros_cnt worth of characters from the
526
               front of the exponent */
527
            assert(extra_zeros_cnt >= 0);
528
529
            /* Add one to significant_digit_cnt to copy the
530
               trailing 0 byte, thus setting the length */
531
            memmove(start,
532
                start + extra_zeros_cnt,
533
                significant_digit_cnt + 1);
534
        }
535
        else {
536
            /* If there are fewer than 2 digits, add zeros
537
               until there are 2, if there's enough room */
538
            int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;
539
            if (start + zeros + exponent_digit_cnt + 1
540
                  < buffer + buf_size) {
541
                memmove(start + zeros, start,
542
                    exponent_digit_cnt + 1);
543
                memset(start, '0', zeros);
544
            }
545
        }
546
    }
547
}
548
549
/* Remove trailing zeros after the decimal point from a numeric string; also
550
   remove the decimal point if all digits following it are zero.  The numeric
551
   string must end in '\0', and should not have any leading or trailing
552
   whitespace.  Assumes that the decimal point is '.'. */
553
Py_LOCAL_INLINE(void)
554
remove_trailing_zeros(char *buffer)
555
{
556
    char *old_fraction_end, *new_fraction_end, *end, *p;
557
558
    p = buffer;
559
    if (*p == '-' || *p == '+')
560
        /* Skip leading sign, if present */
561
        ++p;
562
    while (Py_ISDIGIT(*p))
563
        ++p;
564
565
    /* if there's no decimal point there's nothing to do */
566
    if (*p++ != '.')
567
        return;
568
569
    /* scan any digits after the point */
570
    while (Py_ISDIGIT(*p))
571
        ++p;
572
    old_fraction_end = p;
573
574
    /* scan up to ending '\0' */
575
    while (*p != '\0')
576
        p++;
577
    /* +1 to make sure that we move the null byte as well */
578
    end = p+1;
579
580
    /* scan back from fraction_end, looking for removable zeros */
581
    p = old_fraction_end;
582
    while (*(p-1) == '0')
583
        --p;
584
    /* and remove point if we've got that far */
585
    if (*(p-1) == '.')
586
        --p;
587
    new_fraction_end = p;
588
589
    memmove(new_fraction_end, old_fraction_end, end-old_fraction_end);
590
}
591
592
/* Ensure that buffer has a decimal point in it.  The decimal point will not
593
   be in the current locale, it will always be '.'. Don't add a decimal point
594
   if an exponent is present.  Also, convert to exponential notation where
595
   adding a '.0' would produce too many significant digits (see issue 5864).
596
597
   Returns a pointer to the fixed buffer, or NULL on failure.
598
*/
599
Py_LOCAL_INLINE(char *)
600
ensure_decimal_point(char* buffer, size_t buf_size, int precision)
601
{
602
    int digit_count, insert_count = 0, convert_to_exp = 0;
603
    const char *chars_to_insert;
604
    char *digits_start;
605
606
    /* search for the first non-digit character */
607
    char *p = buffer;
608
    if (*p == '-' || *p == '+')
609
        /* Skip leading sign, if present.  I think this could only
610
           ever be '-', but it can't hurt to check for both. */
611
        ++p;
612
    digits_start = p;
613
    while (*p && Py_ISDIGIT(*p))
614
        ++p;
615
    digit_count = Py_SAFE_DOWNCAST(p - digits_start, Py_ssize_t, int);
616
617
    if (*p == '.') {
618
        if (Py_ISDIGIT(*(p+1))) {
619
            /* Nothing to do, we already have a decimal
620
               point and a digit after it */
621
        }
622
        else {
623
            /* We have a decimal point, but no following
624
               digit.  Insert a zero after the decimal. */
625
            /* can't ever get here via PyOS_double_to_string */
626
            assert(precision == -1);
627
            ++p;
628
            chars_to_insert = "0";
629
            insert_count = 1;
630
        }
631
    }
632
    else if (!(*p == 'e' || *p == 'E')) {
633
        /* Don't add ".0" if we have an exponent. */
634
        if (digit_count == precision) {
635
            /* issue 5864: don't add a trailing .0 in the case
636
               where the '%g'-formatted result already has as many
637
               significant digits as were requested.  Switch to
638
               exponential notation instead. */
639
            convert_to_exp = 1;
640
            /* no exponent, no point, and we shouldn't land here
641
               for infs and nans, so we must be at the end of the
642
               string. */
643
            assert(*p == '\0');
644
        }
645
        else {
646
            assert(precision == -1 || digit_count < precision);
647
            chars_to_insert = ".0";
648
            insert_count = 2;
649
        }
650
    }
651
    if (insert_count) {
652
        size_t buf_len = strlen(buffer);
653
        if (buf_len + insert_count + 1 >= buf_size) {
654
            /* If there is not enough room in the buffer
655
               for the additional text, just skip it.  It's
656
               not worth generating an error over. */
657
        }
658
        else {
659
            memmove(p + insert_count, p,
660
                buffer + strlen(buffer) - p + 1);
661
            memcpy(p, chars_to_insert, insert_count);
662
        }
663
    }
664
    if (convert_to_exp) {
665
        int written;
666
        size_t buf_avail;
667
        p = digits_start;
668
        /* insert decimal point */
669
        assert(digit_count >= 1);
670
        memmove(p+2, p+1, digit_count); /* safe, but overwrites nul */
671
        p[1] = '.';
672
        p += digit_count+1;
673
        assert(p <= buf_size+buffer);
674
        buf_avail = buf_size+buffer-p;
675
        if (buf_avail == 0)
676
            return NULL;
677
        /* Add exponent.  It's okay to use lower case 'e': we only
678
           arrive here as a result of using the empty format code or
679
           repr/str builtins and those never want an upper case 'E' */
680
        written = PyOS_snprintf(p, buf_avail, "e%+.02d", digit_count-1);
681
        if (!(0 <= written &&
682
              written < Py_SAFE_DOWNCAST(buf_avail, size_t, int)))
683
            /* output truncated, or something else bad happened */
684
            return NULL;
685
        remove_trailing_zeros(buffer);
686
    }
687
    return buffer;
688
}
689
690
/* see FORMATBUFLEN in unicodeobject.c */
691
#define FLOAT_FORMATBUFLEN 120
692
693
/**
694
 * _PyOS_ascii_formatd:
695
 * @buffer: A buffer to place the resulting string in
696
 * @buf_size: The length of the buffer.
697
 * @format: The printf()-style format to use for the
698
 *          code to use for converting.
699
 * @d: The #gdouble to convert
700
 * @precision: The precision to use when formatting.
701
 *
702
 * Converts a #gdouble to a string, using the '.' as
703
 * decimal point. To format the number you pass in
704
 * a printf()-style format string. Allowed conversion
705
 * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'Z'.
706
 *
707
 * 'Z' is the same as 'g', except it always has a decimal and
708
 *     at least one digit after the decimal.
709
 *
710
 * Return value: The pointer to the buffer with the converted string.
711
 * On failure returns NULL but does not set any Python exception.
712
 **/
713
static char *
714
_PyOS_ascii_formatd(char       *buffer,
715
                   size_t      buf_size,
716
                   const char *format,
717
                   double      d,
718
                   int         precision)
719
{
720
    char format_char;
721
    size_t format_len = strlen(format);
722
723
    /* Issue 2264: code 'Z' requires copying the format.  'Z' is 'g', but
724
       also with at least one character past the decimal. */
725
    char tmp_format[FLOAT_FORMATBUFLEN];
726
727
    /* The last character in the format string must be the format char */
728
    format_char = format[format_len - 1];
729
730
    if (format[0] != '%')
731
        return NULL;
732
733
    /* I'm not sure why this test is here.  It's ensuring that the format
734
       string after the first character doesn't have a single quote, a
735
       lowercase l, or a percent. This is the reverse of the commented-out
736
       test about 10 lines ago. */
737
    if (strpbrk(format + 1, "'l%"))
738
        return NULL;
739
740
    /* Also curious about this function is that it accepts format strings
741
       like "%xg", which are invalid for floats.  In general, the
742
       interface to this function is not very good, but changing it is
743
       difficult because it's a public API. */
744
745
    if (!(format_char == 'e' || format_char == 'E' ||
746
          format_char == 'f' || format_char == 'F' ||
747
          format_char == 'g' || format_char == 'G' ||
748
          format_char == 'Z'))
749
        return NULL;
750
751
    /* Map 'Z' format_char to 'g', by copying the format string and
752
       replacing the final char with a 'g' */
753
    if (format_char == 'Z') {
754
        if (format_len + 1 >= sizeof(tmp_format)) {
755
            /* The format won't fit in our copy.  Error out.  In
756
               practice, this will never happen and will be
757
               detected by returning NULL */
758
            return NULL;
759
        }
760
        strcpy(tmp_format, format);
761
        tmp_format[format_len - 1] = 'g';
762
        format = tmp_format;
763
    }
764
765
766
    /* Have PyOS_snprintf do the hard work */
767
    PyOS_snprintf(buffer, buf_size, format, d);
768
769
    /* Do various fixups on the return string */
770
771
    /* Get the current locale, and find the decimal point string.
772
       Convert that string back to a dot. */
773
    change_decimal_from_locale_to_dot(buffer);
774
775
    /* If an exponent exists, ensure that the exponent is at least
776
       MIN_EXPONENT_DIGITS digits, providing the buffer is large enough
777
       for the extra zeros.  Also, if there are more than
778
       MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get
779
       back to MIN_EXPONENT_DIGITS */
780
    ensure_minimum_exponent_length(buffer, buf_size);
781
782
    /* If format_char is 'Z', make sure we have at least one character
783
       after the decimal point (and make sure we have a decimal point);
784
       also switch to exponential notation in some edge cases where the
785
       extra character would produce more significant digits that we
786
       really want. */
787
    if (format_char == 'Z')
788
        buffer = ensure_decimal_point(buffer, buf_size, precision);
789
790
    return buffer;
791
}
792
793
/* The fallback code to use if _Py_dg_dtoa is not available. */
794
795
char * PyOS_double_to_string(double val,
796
                                         char format_code,
797
                                         int precision,
798
                                         int flags,
799
                                         int *type)
800
{
801
    char format[32];
802
    Py_ssize_t bufsize;
803
    char *buf;
804
    int t, exp;
805
    int upper = 0;
806
807
    /* Validate format_code, and map upper and lower case */
808
    switch (format_code) {
809
    case 'e':          /* exponent */
810
    case 'f':          /* fixed */
811
    case 'g':          /* general */
812
        break;
813
    case 'E':
814
        upper = 1;
815
        format_code = 'e';
816
        break;
817
    case 'F':
818
        upper = 1;
819
        format_code = 'f';
820
        break;
821
    case 'G':
822
        upper = 1;
823
        format_code = 'g';
824
        break;
825
    case 'r':          /* repr format */
826
        /* Supplied precision is unused, must be 0. */
827
        if (precision != 0) {
828
            PyErr_BadInternalCall();
829
            return NULL;
830
        }
831
        /* The repr() precision (17 significant decimal digits) is the
832
           minimal number that is guaranteed to have enough precision
833
           so that if the number is read back in the exact same binary
834
           value is recreated.  This is true for IEEE floating point
835
           by design, and also happens to work for all other modern
836
           hardware. */
837
        precision = 17;
838
        format_code = 'g';
839
        break;
840
    default:
841
        PyErr_BadInternalCall();
842
        return NULL;
843
    }
844
845
    /* Here's a quick-and-dirty calculation to figure out how big a buffer
846
       we need.  In general, for a finite float we need:
847
848
         1 byte for each digit of the decimal significand, and
849
850
         1 for a possible sign
851
         1 for a possible decimal point
852
         2 for a possible [eE][+-]
853
         1 for each digit of the exponent;  if we allow 19 digits
854
           total then we're safe up to exponents of 2**63.
855
         1 for the trailing nul byte
856
857
       This gives a total of 24 + the number of digits in the significand,
858
       and the number of digits in the significand is:
859
860
         for 'g' format: at most precision, except possibly
861
           when precision == 0, when it's 1.
862
         for 'e' format: precision+1
863
         for 'f' format: precision digits after the point, at least 1
864
           before.  To figure out how many digits appear before the point
865
           we have to examine the size of the number.  If fabs(val) < 1.0
866
           then there will be only one digit before the point.  If
867
           fabs(val) >= 1.0, then there are at most
868
869
         1+floor(log10(ceiling(fabs(val))))
870
871
           digits before the point (where the 'ceiling' allows for the
872
           possibility that the rounding rounds the integer part of val
873
           up).  A safe upper bound for the above quantity is
874
           1+floor(exp/3), where exp is the unique integer such that 0.5
875
           <= fabs(val)/2**exp < 1.0.  This exp can be obtained from
876
           frexp.
877
878
       So we allow room for precision+1 digits for all formats, plus an
879
       extra floor(exp/3) digits for 'f' format.
880
881
    */
882
883
    if (Py_IS_NAN(val) || Py_IS_INFINITY(val))
884
        /* 3 for 'inf'/'nan', 1 for sign, 1 for '\0' */
885
        bufsize = 5;
886
    else {
887
        bufsize = 25 + precision;
888
        if (format_code == 'f' && fabs(val) >= 1.0) {
889
            frexp(val, &exp);
890
            bufsize += exp/3;
891
        }
892
    }
893
894
    buf = PyMem_Malloc(bufsize);
895
    if (buf == NULL) {
896
        PyErr_NoMemory();
897
        return NULL;
898
    }
899
900
    /* Handle nan and inf. */
901
    if (Py_IS_NAN(val)) {
902
        strcpy(buf, "nan");
903
        t = Py_DTST_NAN;
904
    } else if (Py_IS_INFINITY(val)) {
905
        if (copysign(1., val) == 1.)
906
            strcpy(buf, "inf");
907
        else
908
            strcpy(buf, "-inf");
909
        t = Py_DTST_INFINITE;
910
    } else {
911
        t = Py_DTST_FINITE;
912
        if (flags & Py_DTSF_ADD_DOT_0)
913
            format_code = 'Z';
914
915
        PyOS_snprintf(format, sizeof(format), "%%%s.%i%c",
916
                      (flags & Py_DTSF_ALT ? "#" : ""), precision,
917
                      format_code);
918
        _PyOS_ascii_formatd(buf, bufsize, format, val, precision);
919
920
        if (flags & Py_DTSF_NO_NEG_0 && buf[0] == '-') {
921
            char *buf2 = buf + 1;
922
            while (*buf2 == '0' || *buf2 == '.') {
923
                ++buf2;
924
            }
925
            if (*buf2 == 0 || *buf2 == 'e') {
926
                size_t len = buf2 - buf + strlen(buf2);
927
                assert(buf[len] == 0);
928
                memmove(buf, buf+1, len);
929
            }
930
        }
931
    }
932
933
    /* Add sign when requested.  It's convenient (esp. when formatting
934
     complex numbers) to include a sign even for inf and nan. */
935
    if (flags & Py_DTSF_SIGN && buf[0] != '-') {
936
        size_t len = strlen(buf);
937
        /* the bufsize calculations above should ensure that we've got
938
           space to add a sign */
939
        assert((size_t)bufsize >= len+2);
940
        memmove(buf+1, buf, len+1);
941
        buf[0] = '+';
942
    }
943
    if (upper) {
944
        /* Convert to upper case. */
945
        char *p1;
946
        for (p1 = buf; *p1; p1++)
947
            *p1 = Py_TOUPPER(*p1);
948
    }
949
950
    if (type)
951
        *type = t;
952
    return buf;
953
}
954
955
#else  // _PY_SHORT_FLOAT_REPR == 1
956
957
/* _Py_dg_dtoa is available. */
958
959
/* I'm using a lookup table here so that I don't have to invent a non-locale
960
   specific way to convert to uppercase */
961
#define OFS_INF 0
962
#define OFS_NAN 1
963
#define OFS_E 2
964
965
/* The lengths of these are known to the code below, so don't change them */
966
static const char * const lc_float_strings[] = {
967
    "inf",
968
    "nan",
969
    "e",
970
};
971
static const char * const uc_float_strings[] = {
972
    "INF",
973
    "NAN",
974
    "E",
975
};
976
977
978
/* Convert a double d to a string, and return a PyMem_Malloc'd block of
979
   memory contain the resulting string.
980
981
   Arguments:
982
     d is the double to be converted
983
     format_code is one of 'e', 'f', 'g', 'r'.  'e', 'f' and 'g'
984
       correspond to '%e', '%f' and '%g';  'r' corresponds to repr.
985
     mode is one of '0', '2' or '3', and is completely determined by
986
       format_code: 'e' and 'g' use mode 2; 'f' mode 3, 'r' mode 0.
987
     precision is the desired precision
988
     always_add_sign is nonzero if a '+' sign should be included for positive
989
       numbers
990
     add_dot_0_if_integer is nonzero if integers in non-exponential form
991
       should have ".0" added.  Only applies to format codes 'r' and 'g'.
992
     use_alt_formatting is nonzero if alternative formatting should be
993
       used.  Only applies to format codes 'e', 'f' and 'g'.  For code 'g',
994
       at most one of use_alt_formatting and add_dot_0_if_integer should
995
       be nonzero.
996
     type, if non-NULL, will be set to one of these constants to identify
997
       the type of the 'd' argument:
998
     Py_DTST_FINITE
999
     Py_DTST_INFINITE
1000
     Py_DTST_NAN
1001
1002
   Returns a PyMem_Malloc'd block of memory containing the resulting string,
1003
    or NULL on error. If NULL is returned, the Python error has been set.
1004
 */
1005
1006
static char *
1007
format_float_short(double d, char format_code,
1008
                   int mode, int precision,
1009
                   int always_add_sign, int add_dot_0_if_integer,
1010
                   int use_alt_formatting, int no_negative_zero,
1011
                   const char * const *float_strings, int *type)
1012
{
1013
    char *buf = NULL;
1014
    char *p = NULL;
1015
    Py_ssize_t bufsize = 0;
1016
    char *digits, *digits_end;
1017
    int decpt_as_int, sign, exp_len, exp = 0, use_exp = 0;
1018
    Py_ssize_t decpt, digits_len, vdigits_start, vdigits_end;
1019
    _Py_SET_53BIT_PRECISION_HEADER;
1020
1021
    /* _Py_dg_dtoa returns a digit string (no decimal point or exponent).
1022
       Must be matched by a call to _Py_dg_freedtoa. */
1023
    _Py_SET_53BIT_PRECISION_START;
1024
    digits = _Py_dg_dtoa(d, mode, precision, &decpt_as_int, &sign,
1025
                         &digits_end);
1026
    _Py_SET_53BIT_PRECISION_END;
1027
1028
    decpt = (Py_ssize_t)decpt_as_int;
1029
    if (digits == NULL) {
  Branch (1029:9): [True: 0, False: 202k]
1030
        /* The only failure mode is no memory. */
1031
        PyErr_NoMemory();
1032
        goto exit;
1033
    }
1034
    assert(digits_end != NULL && digits_end >= digits);
1035
    digits_len = digits_end - digits;
1036
1037
    if (no_negative_zero && 
sign == 143
&&
  Branch (1037:9): [True: 43, False: 202k]
  Branch (1037:29): [True: 30, False: 13]
1038
            
(30
digits_len == 030
||
(25
digits_len == 125
&&
digits[0] == '0'25
))) {
  Branch (1038:14): [True: 5, False: 25]
  Branch (1038:34): [True: 25, False: 0]
  Branch (1038:53): [True: 17, False: 8]
1039
        sign = 0;
1040
    }
1041
1042
    if (digits_len && 
!201k
Py_ISDIGIT201k
(digits[0])) {
  Branch (1042:9): [True: 201k, False: 1.24k]
  Branch (1042:23): [True: 15.3k, False: 186k]
1043
        /* Infinities and nans here; adapt Gay's output,
1044
           so convert Infinity to inf and NaN to nan, and
1045
           ignore sign of nan. Then return. */
1046
1047
        /* ignore the actual sign of a nan */
1048
        if (digits[0] == 'n' || digits[0] == 'N')
  Branch (1048:13): [True: 0, False: 15.3k]
  Branch (1048:33): [True: 1.53k, False: 13.8k]
1049
            sign = 0;
1050
1051
        /* We only need 5 bytes to hold the result "+inf\0" . */
1052
        bufsize = 5; /* Used later in an assert. */
1053
        buf = (char *)PyMem_Malloc(bufsize);
1054
        if (buf == NULL) {
  Branch (1054:13): [True: 0, False: 15.3k]
1055
            PyErr_NoMemory();
1056
            goto exit;
1057
        }
1058
        p = buf;
1059
1060
        if (sign == 1) {
  Branch (1060:13): [True: 6.27k, False: 9.11k]
1061
            *p++ = '-';
1062
        }
1063
        else if (always_add_sign) {
  Branch (1063:18): [True: 192, False: 8.92k]
1064
            *p++ = '+';
1065
        }
1066
        if (digits[0] == 'i' || digits[0] == 'I') {
  Branch (1066:13): [True: 0, False: 15.3k]
  Branch (1066:33): [True: 13.8k, False: 1.53k]
1067
            strncpy(p, float_strings[OFS_INF], 3);
1068
            p += 3;
1069
1070
            if (type)
  Branch (1070:17): [True: 84, False: 13.7k]
1071
                *type = Py_DTST_INFINITE;
1072
        }
1073
        else if (digits[0] == 'n' || digits[0] == 'N') {
  Branch (1073:18): [True: 0, False: 1.53k]
  Branch (1073:38): [True: 1.53k, False: 0]
1074
            strncpy(p, float_strings[OFS_NAN], 3);
1075
            p += 3;
1076
1077
            if (type)
  Branch (1077:17): [True: 84, False: 1.45k]
1078
                *type = Py_DTST_NAN;
1079
        }
1080
        else {
1081
            /* shouldn't get here: Gay's code should always return
1082
               something starting with a digit, an 'I',  or 'N' */
1083
            Py_UNREACHABLE();
1084
        }
1085
        goto exit;
1086
    }
1087
1088
    /* The result must be finite (not inf or nan). */
1089
    if (type)
  Branch (1089:9): [True: 7.33k, False: 180k]
1090
        *type = Py_DTST_FINITE;
1091
1092
1093
    /* We got digits back, format them.  We may need to pad 'digits'
1094
       either on the left or right (or both) with extra zeros, so in
1095
       general the resulting string has the form
1096
1097
         [<sign>]<zeros><digits><zeros>[<exponent>]
1098
1099
       where either of the <zeros> pieces could be empty, and there's a
1100
       decimal point that could appear either in <digits> or in the
1101
       leading or trailing <zeros>.
1102
1103
       Imagine an infinite 'virtual' string vdigits, consisting of the
1104
       string 'digits' (starting at index 0) padded on both the left and
1105
       right with infinite strings of zeros.  We want to output a slice
1106
1107
         vdigits[vdigits_start : vdigits_end]
1108
1109
       of this virtual string.  Thus if vdigits_start < 0 then we'll end
1110
       up producing some leading zeros; if vdigits_end > digits_len there
1111
       will be trailing zeros in the output.  The next section of code
1112
       determines whether to use an exponent or not, figures out the
1113
       position 'decpt' of the decimal point, and computes 'vdigits_start'
1114
       and 'vdigits_end'. */
1115
    vdigits_end = digits_len;
1116
    switch (format_code) {
1117
    case 'e':
  Branch (1117:5): [True: 4.30k, False: 183k]
1118
        use_exp = 1;
1119
        vdigits_end = precision;
1120
        break;
1121
    case 'f':
  Branch (1121:5): [True: 29.6k, False: 157k]
1122
        vdigits_end = decpt + precision;
1123
        break;
1124
    case 'g':
  Branch (1124:5): [True: 4.53k, False: 183k]
1125
        if (decpt <= -4 || decpt >
  Branch (1125:13): [True: 425, False: 4.11k]
  Branch (1125:28): [True: 2.42k, False: 1.68k]
1126
            (add_dot_0_if_integer ? 
precision-19
:
precision4.10k
))
  Branch (1126:14): [True: 9, False: 4.10k]
1127
            use_exp = 1;
1128
        if (use_alt_formatting)
  Branch (1128:13): [True: 1.87k, False: 2.65k]
1129
            vdigits_end = precision;
1130
        break;
1131
    case 'r':
  Branch (1131:5): [True: 149k, False: 38.4k]
1132
        /* convert to exponential format at 1e16.  We used to convert
1133
           at 1e17, but that gives odd-looking results for some values
1134
           when a 16-digit 'shortest' repr is padded with bogus zeros.
1135
           For example, repr(2e16+8) would give 20000000000000010.0;
1136
           the true value is 20000000000000008.0. */
1137
        if (decpt <= -4 || 
decpt > 16106k
)
  Branch (1137:13): [True: 42.1k, False: 106k]
  Branch (1137:28): [True: 46.3k, False: 60.5k]
1138
            use_exp = 1;
1139
        break;
1140
    default:
  Branch (1140:5): [True: 0, False: 187k]
1141
        PyErr_BadInternalCall();
1142
        goto exit;
1143
    }
1144
1145
    /* if using an exponent, reset decimal point position to 1 and adjust
1146
       exponent accordingly.*/
1147
    if (use_exp) {
  Branch (1147:9): [True: 95.6k, False: 91.8k]
1148
        exp = (int)decpt - 1;
1149
        decpt = 1;
1150
    }
1151
    /* ensure vdigits_start < decpt <= vdigits_end, or vdigits_start <
1152
       decpt < vdigits_end if add_dot_0_if_integer and no exponent */
1153
    vdigits_start = decpt <= 0 ? 
decpt-132.6k
:
0154k
;
  Branch (1153:21): [True: 32.6k, False: 154k]
1154
    if (!use_exp && 
add_dot_0_if_integer91.8k
)
  Branch (1154:9): [True: 91.8k, False: 95.6k]
  Branch (1154:21): [True: 59.1k, False: 32.7k]
1155
        vdigits_end = vdigits_end > decpt ? 
vdigits_end43.1k
:
decpt + 116.0k
;
  Branch (1155:23): [True: 43.1k, False: 16.0k]
1156
    else
1157
        vdigits_end = vdigits_end > decpt ? 
vdigits_end118k
:
decpt9.41k
;
  Branch (1157:23): [True: 118k, False: 9.41k]
1158
1159
    /* double check inequalities */
1160
    assert(vdigits_start <= 0 &&
1161
           0 <= digits_len &&
1162
           digits_len <= vdigits_end);
1163
    /* decimal point should be in (vdigits_start, vdigits_end] */
1164
    assert(vdigits_start < decpt && decpt <= vdigits_end);
1165
1166
    /* Compute an upper bound how much memory we need. This might be a few
1167
       chars too long, but no big deal. */
1168
    bufsize =
1169
        /* sign, decimal point and trailing 0 byte */
1170
        3 +
1171
1172
        /* total digit count (including zero padding on both sides) */
1173
        (vdigits_end - vdigits_start) +
1174
1175
        /* exponent "e+100", max 3 numerical digits */
1176
        (use_exp ? 
595.6k
:
091.8k
);
  Branch (1176:10): [True: 95.6k, False: 91.8k]
1177
1178
    /* Now allocate the memory and initialize p to point to the start of
1179
       it. */
1180
    buf = (char *)PyMem_Malloc(bufsize);
1181
    if (buf == NULL) {
  Branch (1181:9): [True: 0, False: 187k]
1182
        PyErr_NoMemory();
1183
        goto exit;
1184
    }
1185
    p = buf;
1186
1187
    /* Add a negative sign if negative, and a plus sign if non-negative
1188
       and always_add_sign is true. */
1189
    if (sign == 1)
  Branch (1189:9): [True: 69.2k, False: 118k]
1190
        *p++ = '-';
1191
    else if (always_add_sign)
  Branch (1191:14): [True: 506, False: 117k]
1192
        *p++ = '+';
1193
1194
    /* note that exactly one of the three 'if' conditions is true,
1195
       so we include exactly one decimal point */
1196
    /* Zero padding on left of digit string */
1197
    if (decpt <= 0) {
  Branch (1197:9): [True: 32.6k, False: 154k]
1198
        memset(p, '0', decpt-vdigits_start);
1199
        p += decpt - vdigits_start;
1200
        *p++ = '.';
1201
        memset(p, '0', 0-decpt);
1202
        p += 0-decpt;
1203
    }
1204
    else {
1205
        memset(p, '0', 0-vdigits_start);
1206
        p += 0 - vdigits_start;
1207
    }
1208
1209
    /* Digits, with included decimal point */
1210
    if (0 < decpt && 
decpt <= digits_len154k
) {
  Branch (1210:9): [True: 154k, False: 32.6k]
  Branch (1210:22): [True: 149k, False: 5.71k]
1211
        strncpy(p, digits, decpt-0);
1212
        p += decpt-0;
1213
        *p++ = '.';
1214
        strncpy(p, digits+decpt, digits_len-decpt);
1215
        p += digits_len-decpt;
1216
    }
1217
    else {
1218
        strncpy(p, digits, digits_len);
1219
        p += digits_len;
1220
    }
1221
1222
    /* And zeros on the right */
1223
    if (digits_len < decpt) {
  Branch (1223:9): [True: 5.71k, False: 181k]
1224
        memset(p, '0', decpt-digits_len);
1225
        p += decpt-digits_len;
1226
        *p++ = '.';
1227
        memset(p, '0', vdigits_end-decpt);
1228
        p += vdigits_end-decpt;
1229
    }
1230
    else {
1231
        memset(p, '0', vdigits_end-digits_len);
1232
        p += vdigits_end-digits_len;
1233
    }
1234
1235
    /* Delete a trailing decimal pt unless using alternative formatting. */
1236
    if (p[-1] == '.' && 
!use_alt_formatting9.41k
)
  Branch (1236:9): [True: 9.41k, False: 178k]
  Branch (1236:25): [True: 7.00k, False: 2.41k]
1237
        p--;
1238
1239
    /* Now that we've done zero padding, add an exponent if needed. */
1240
    if (use_exp) {
  Branch (1240:9): [True: 95.6k, False: 91.8k]
1241
        *p++ = float_strings[OFS_E][0];
1242
        exp_len = sprintf(p, "%+.02d", exp);
1243
        p += exp_len;
1244
    }
1245
  exit:
1246
    if (buf) {
  Branch (1246:9): [True: 202k, False: 0]
1247
        *p = '\0';
1248
        /* It's too late if this fails, as we've already stepped on
1249
           memory that isn't ours. But it's an okay debugging test. */
1250
        assert(p-buf < bufsize);
1251
    }
1252
    if (digits)
  Branch (1252:9): [True: 202k, False: 0]
1253
        _Py_dg_freedtoa(digits);
1254
1255
    return buf;
1256
}
1257
1258
1259
char * PyOS_double_to_string(double val,
1260
                                         char format_code,
1261
                                         int precision,
1262
                                         int flags,
1263
                                         int *type)
1264
{
1265
    const char * const *float_strings = lc_float_strings;
1266
    int mode;
1267
1268
    /* Validate format_code, and map upper and lower case. Compute the
1269
       mode and make any adjustments as needed. */
1270
    switch (format_code) {
1271
    /* exponent */
1272
    case 'E':
  Branch (1272:5): [True: 3.62k, False: 199k]
1273
        float_strings = uc_float_strings;
1274
        format_code = 'e';
1275
        /* Fall through. */
1276
    case 'e':
  Branch (1276:5): [True: 4.36k, False: 198k]
1277
        mode = 2;
1278
        precision++;
1279
        break;
1280
1281
    /* fixed */
1282
    case 'F':
  Branch (1282:5): [True: 3.64k, False: 199k]
1283
        float_strings = uc_float_strings;
1284
        format_code = 'f';
1285
        /* Fall through. */
1286
    case 'f':
  Branch (1286:5): [True: 29.7k, False: 173k]
1287
        mode = 3;
1288
        break;
1289
1290
    /* general */
1291
    case 'G':
  Branch (1291:5): [True: 3.61k, False: 199k]
1292
        float_strings = uc_float_strings;
1293
        format_code = 'g';
1294
        /* Fall through. */
1295
    case 'g':
  Branch (1295:5): [True: 4.59k, False: 198k]
1296
        mode = 2;
1297
        /* precision 0 makes no sense for 'g' format; interpret as 1 */
1298
        if (precision == 0)
  Branch (1298:13): [True: 3.12k, False: 5.08k]
1299
            precision = 1;
1300
        break;
1301
1302
    /* repr format */
1303
    case 'r':
  Branch (1303:5): [True: 153k, False: 49.5k]
1304
        mode = 0;
1305
        /* Supplied precision is unused, must be 0. */
1306
        if (precision != 0) {
  Branch (1306:13): [True: 0, False: 153k]
1307
            PyErr_BadInternalCall();
1308
            return NULL;
1309
        }
1310
        break;
1311
1312
    default:
  Branch (1312:5): [True: 0, False: 202k]
1313
        PyErr_BadInternalCall();
1314
        return NULL;
1315
    }
1316
1317
    return format_float_short(val, format_code, mode, precision,
1318
                              flags & Py_DTSF_SIGN,
1319
                              flags & Py_DTSF_ADD_DOT_0,
1320
                              flags & Py_DTSF_ALT,
1321
                              flags & Py_DTSF_NO_NEG_0,
1322
                              float_strings, type);
1323
}
1324
#endif  // _PY_SHORT_FLOAT_REPR == 1