LCOV - code coverage report
Current view: directory - js/src - jsdtoa.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 264 176 66.7 %
Date: 2012-06-02 Functions: 9 8 88.9 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code, released
      17                 :  * March 31, 1998.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Netscape Communications Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : /*
      41                 :  * Portable double to alphanumeric string and back converters.
      42                 :  */
      43                 : #include "jstypes.h"
      44                 : #include "jsdtoa.h"
      45                 : #include "jsprf.h"
      46                 : #include "jsapi.h"
      47                 : #include "jsprvtd.h"
      48                 : #include "jsnum.h"
      49                 : #include "jslibmath.h"
      50                 : #include "jscntxt.h"
      51                 : 
      52                 : #include "jsobjinlines.h"
      53                 : 
      54                 : using namespace js;
      55                 : 
      56                 : #ifdef IS_LITTLE_ENDIAN
      57                 : #define IEEE_8087
      58                 : #else
      59                 : #define IEEE_MC68k
      60                 : #endif
      61                 : 
      62                 : #ifndef Long
      63                 : #define Long int32_t
      64                 : #endif
      65                 : 
      66                 : #ifndef ULong
      67                 : #define ULong uint32_t
      68                 : #endif
      69                 : 
      70                 : /*
      71                 : #ifndef Llong
      72                 : #define Llong int64_t
      73                 : #endif
      74                 : 
      75                 : #ifndef ULlong
      76                 : #define ULlong uint64_t
      77                 : #endif
      78                 : */
      79                 : 
      80                 : /*
      81                 :  * MALLOC gets declared external, and that doesn't work for class members, so
      82                 :  * wrap.
      83                 :  */
      84           19910 : inline void* dtoa_malloc(size_t size) { return OffTheBooks::malloc_(size); }
      85           19908 : inline void dtoa_free(void* p) { return UnwantedForeground::free_(p); }
      86                 : 
      87                 : #define NO_GLOBAL_STATE
      88                 : #define MALLOC dtoa_malloc
      89                 : #define FREE dtoa_free
      90                 : #include "dtoa.c"
      91                 : 
      92                 : /* Mapping of JSDToStrMode -> js_dtoa mode */
      93                 : static const uint8_t dtoaModes[] = {
      94                 :     0,   /* DTOSTR_STANDARD */
      95                 :     0,   /* DTOSTR_STANDARD_EXPONENTIAL, */
      96                 :     3,   /* DTOSTR_FIXED, */
      97                 :     2,   /* DTOSTR_EXPONENTIAL, */
      98                 :     2};  /* DTOSTR_PRECISION */
      99                 : 
     100                 : double
     101          626563 : js_strtod_harder(DtoaState *state, const char *s00, char **se, int *err)
     102                 : {
     103                 :     double retval;
     104          626563 :     if (err)
     105          626563 :         *err = 0;
     106          626563 :     retval = _strtod(state, s00, se);
     107          626563 :     return retval;
     108                 : }
     109                 : 
     110                 : char *
     111           13739 : js_dtostr(DtoaState *state, char *buffer, size_t bufferSize, JSDToStrMode mode, int precision,
     112                 :           double dinput)
     113                 : {
     114                 :     U d;
     115                 :     int decPt;        /* Offset of decimal point from first digit */
     116                 :     int sign;         /* Nonzero if the sign bit was set in d */
     117                 :     int nDigits;      /* Number of significand digits returned by js_dtoa */
     118                 :     char *numBegin;   /* Pointer to the digits returned by js_dtoa */
     119           13739 :     char *numEnd = 0; /* Pointer past the digits returned by js_dtoa */
     120                 : 
     121               0 :     JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL
     122                 :                                     ? DTOSTR_STANDARD_BUFFER_SIZE
     123           13739 :                                     : DTOSTR_VARIABLE_BUFFER_SIZE(precision)));
     124                 : 
     125                 :     /*
     126                 :      * Change mode here rather than below because the buffer may not be large
     127                 :      * enough to hold a large integer.
     128                 :      */
     129           13739 :     if (mode == DTOSTR_FIXED && (dinput >= 1e21 || dinput <= -1e21))
     130               0 :         mode = DTOSTR_STANDARD;
     131                 : 
     132           13739 :     dval(d) = dinput;
     133           13739 :     numBegin = dtoa(PASS_STATE d, dtoaModes[mode], precision, &decPt, &sign, &numEnd);
     134           13739 :     if (!numBegin) {
     135               0 :         return NULL;
     136                 :     }
     137                 : 
     138           13739 :     nDigits = numEnd - numBegin;
     139           13739 :     JS_ASSERT((size_t) nDigits <= bufferSize - 2);
     140           13739 :     if ((size_t) nDigits > bufferSize - 2) {
     141               0 :         return NULL;
     142                 :     }
     143                 : 
     144           13739 :     js_memcpy(buffer + 2, numBegin, nDigits);
     145           13739 :     freedtoa(PASS_STATE numBegin);
     146           13739 :     numBegin = buffer + 2; /* +2 leaves space for sign and/or decimal point */
     147           13739 :     numEnd = numBegin + nDigits;
     148           13739 :     *numEnd = '\0';
     149                 : 
     150                 :     /* If Infinity, -Infinity, or NaN, return the string regardless of mode. */
     151           13739 :     if (decPt != 9999) {
     152           13739 :         JSBool exponentialNotation = JS_FALSE;
     153           13739 :         int minNDigits = 0;  /* Min number of significant digits required */
     154                 :         char *p;
     155                 :         char *q;
     156                 : 
     157           13739 :         switch (mode) {
     158                 :             case DTOSTR_STANDARD:
     159           13454 :                 if (decPt < -5 || decPt > 21)
     160           13014 :                     exponentialNotation = JS_TRUE;
     161                 :                 else
     162             440 :                     minNDigits = decPt;
     163           13454 :                 break;
     164                 : 
     165                 :             case DTOSTR_FIXED:
     166             258 :                 if (precision >= 0)
     167             258 :                     minNDigits = decPt + precision;
     168                 :                 else
     169               0 :                     minNDigits = decPt;
     170             258 :                 break;
     171                 : 
     172                 :             case DTOSTR_EXPONENTIAL:
     173               0 :                 JS_ASSERT(precision > 0);
     174               0 :                 minNDigits = precision;
     175                 :                 /* Fall through */
     176                 :             case DTOSTR_STANDARD_EXPONENTIAL:
     177              27 :                 exponentialNotation = JS_TRUE;
     178              27 :                 break;
     179                 : 
     180                 :             case DTOSTR_PRECISION:
     181               0 :                 JS_ASSERT(precision > 0);
     182               0 :                 minNDigits = precision;
     183               0 :                 if (decPt < -5 || decPt > precision)
     184               0 :                     exponentialNotation = JS_TRUE;
     185               0 :                 break;
     186                 :         }
     187                 : 
     188                 :         /* If the number has fewer than minNDigits, end-pad it with zeros. */
     189           13739 :         if (nDigits < minNDigits) {
     190              56 :             p = numBegin + minNDigits;
     191              56 :             nDigits = minNDigits;
     192             244 :             do {
     193             244 :                 *numEnd++ = '0';
     194                 :             } while (numEnd != p);
     195              56 :             *numEnd = '\0';
     196                 :         }
     197                 : 
     198           13739 :         if (exponentialNotation) {
     199                 :             /* Insert a decimal point if more than one significand digit */
     200           13041 :             if (nDigits != 1) {
     201           13014 :                 numBegin--;
     202           13014 :                 numBegin[0] = numBegin[1];
     203           13014 :                 numBegin[1] = '.';
     204                 :             }
     205           13041 :             JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1);
     206             698 :         } else if (decPt != nDigits) {
     207                 :             /* Some kind of a fraction in fixed notation */
     208             621 :             JS_ASSERT(decPt <= nDigits);
     209             621 :             if (decPt > 0) {
     210                 :                 /* dd...dd . dd...dd */
     211             269 :                 p = --numBegin;
     212             439 :                 do {
     213             439 :                     *p = p[1];
     214             439 :                     p++;
     215                 :                 } while (--decPt);
     216             269 :                 *p = '.';
     217                 :             } else {
     218                 :                 /* 0 . 00...00dd...dd */
     219             352 :                 p = numEnd;
     220             352 :                 numEnd += 1 - decPt;
     221             352 :                 q = numEnd;
     222             352 :                 JS_ASSERT(numEnd < buffer + bufferSize);
     223             352 :                 *numEnd = '\0';
     224            5804 :                 while (p != numBegin)
     225            5100 :                     *--q = *--p;
     226             352 :                 for (p = numBegin + 1; p != q; p++)
     227               0 :                     *p = '0';
     228             352 :                 *numBegin = '.';
     229             352 :                 *--numBegin = '0';
     230                 :             }
     231                 :         }
     232                 :     }
     233                 : 
     234                 :     /* If negative and neither -0.0 nor NaN, output a leading '-'. */
     235           26783 :     if (sign &&
     236            6522 :             !(word0(d) == Sign_bit && word1(d) == 0) &&
     237            6522 :             !((word0(d) & Exp_mask) == Exp_mask &&
     238            6522 :               (word1(d) || (word0(d) & Frac_mask)))) {
     239            6522 :         *--numBegin = '-';
     240                 :     }
     241           13739 :     return numBegin;
     242                 : }
     243                 : 
     244                 : 
     245                 : /* Let b = floor(b / divisor), and return the remainder.  b must be nonnegative.
     246                 :  * divisor must be between 1 and 65536.
     247                 :  * This function cannot run out of memory. */
     248                 : static uint32_t
     249               0 : divrem(Bigint *b, uint32_t divisor)
     250                 : {
     251               0 :     int32_t n = b->wds;
     252               0 :     uint32_t remainder = 0;
     253                 :     ULong *bx;
     254                 :     ULong *bp;
     255                 : 
     256               0 :     JS_ASSERT(divisor > 0 && divisor <= 65536);
     257                 : 
     258               0 :     if (!n)
     259               0 :         return 0; /* b is zero */
     260               0 :     bx = b->x;
     261               0 :     bp = bx + n;
     262               0 :     do {
     263               0 :         ULong a = *--bp;
     264               0 :         ULong dividend = remainder << 16 | a >> 16;
     265               0 :         ULong quotientHi = dividend / divisor;
     266                 :         ULong quotientLo;
     267                 : 
     268               0 :         remainder = dividend - quotientHi*divisor;
     269               0 :         JS_ASSERT(quotientHi <= 0xFFFF && remainder < divisor);
     270               0 :         dividend = remainder << 16 | (a & 0xFFFF);
     271               0 :         quotientLo = dividend / divisor;
     272               0 :         remainder = dividend - quotientLo*divisor;
     273               0 :         JS_ASSERT(quotientLo <= 0xFFFF && remainder < divisor);
     274               0 :         *bp = quotientHi << 16 | quotientLo;
     275                 :     } while (bp != bx);
     276                 :     /* Decrease the size of the number if its most significant word is now zero. */
     277               0 :     if (bx[n-1] == 0)
     278               0 :         b->wds--;
     279               0 :     return remainder;
     280                 : }
     281                 : 
     282                 : /* Return floor(b/2^k) and set b to be the remainder.  The returned quotient must be less than 2^32. */
     283            3178 : static uint32_t quorem2(Bigint *b, int32_t k)
     284                 : {
     285                 :     ULong mask;
     286                 :     ULong result;
     287                 :     ULong *bx, *bxe;
     288                 :     int32_t w;
     289            3178 :     int32_t n = k >> 5;
     290            3178 :     k &= 0x1F;
     291            3178 :     mask = (1<<k) - 1;
     292                 : 
     293            3178 :     w = b->wds - n;
     294            3178 :     if (w <= 0)
     295               0 :         return 0;
     296            3178 :     JS_ASSERT(w <= 2);
     297            3178 :     bx = b->x;
     298            3178 :     bxe = bx + n;
     299            3178 :     result = *bxe >> k;
     300            3178 :     *bxe &= mask;
     301            3178 :     if (w == 2) {
     302              34 :         JS_ASSERT(!(bxe[1] & ~mask));
     303              34 :         if (k)
     304              34 :             result |= bxe[1] << (32 - k);
     305                 :     }
     306            3178 :     n++;
     307            6356 :     while (!*bxe && bxe != bx) {
     308               0 :         n--;
     309               0 :         bxe--;
     310                 :     }
     311            3178 :     b->wds = n;
     312            3178 :     return result;
     313                 : }
     314                 : 
     315                 : 
     316                 : /* "-0.0000...(1073 zeros after decimal point)...0001\0" is the longest string that we could produce,
     317                 :  * which occurs when printing -5e-324 in binary.  We could compute a better estimate of the size of
     318                 :  * the output string and malloc fewer bytes depending on d and base, but why bother? */
     319                 : #define DTOBASESTR_BUFFER_SIZE 1078
     320                 : #define BASEDIGIT(digit) ((char)(((digit) >= 10) ? 'a' - 10 + (digit) : '0' + (digit)))
     321                 : 
     322                 : char *
     323             326 : js_dtobasestr(DtoaState *state, int base, double dinput)
     324                 : {
     325                 :     U d;
     326                 :     char *buffer;        /* The output string */
     327                 :     char *p;             /* Pointer to current position in the buffer */
     328                 :     char *pInt;          /* Pointer to the beginning of the integer part of the string */
     329                 :     char *q;
     330                 :     uint32_t digit;
     331                 :     U di;                /* d truncated to an integer */
     332                 :     U df;                /* The fractional part of d */
     333                 : 
     334             326 :     JS_ASSERT(base >= 2 && base <= 36);
     335                 : 
     336             326 :     dval(d) = dinput;
     337             326 :     buffer = (char*) OffTheBooks::malloc_(DTOBASESTR_BUFFER_SIZE);
     338             326 :     if (!buffer)
     339               0 :         return NULL;
     340             326 :     p = buffer;
     341                 : 
     342             326 :     if (dval(d) < 0.0
     343                 : #if defined(XP_WIN) || defined(XP_OS2)
     344                 :         && !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */
     345                 : #endif
     346                 :        ) {
     347               0 :         *p++ = '-';
     348               0 :         dval(d) = -dval(d);
     349                 :     }
     350                 : 
     351                 :     /* Check for Infinity and NaN */
     352             326 :     if ((word0(d) & Exp_mask) == Exp_mask) {
     353               0 :         strcpy(p, !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN");
     354               0 :         return buffer;
     355                 :     }
     356                 : 
     357                 :     /* Output the integer part of d with the digits in reverse order. */
     358             326 :     pInt = p;
     359             326 :     dval(di) = floor(dval(d));
     360             326 :     if (dval(di) <= 4294967295.0) {
     361             326 :         uint32_t n = (uint32_t)dval(di);
     362             326 :         if (n)
     363             240 :             do {
     364             240 :                 uint32_t m = n / base;
     365             240 :                 digit = n - m*base;
     366             240 :                 n = m;
     367             240 :                 JS_ASSERT(digit < (uint32_t)base);
     368             240 :                 *p++ = BASEDIGIT(digit);
     369                 :             } while (n);
     370             296 :         else *p++ = '0';
     371                 :     } else {
     372                 :         int e;
     373                 :         int bits;  /* Number of significant bits in di; not used. */
     374               0 :         Bigint *b = d2b(PASS_STATE di, &e, &bits);
     375               0 :         if (!b)
     376               0 :             goto nomem1;
     377               0 :         b = lshift(PASS_STATE b, e);
     378               0 :         if (!b) {
     379                 :           nomem1:
     380               0 :             Bfree(PASS_STATE b);
     381               0 :             UnwantedForeground::free_(buffer);
     382               0 :             return NULL;
     383                 :         }
     384               0 :         do {
     385               0 :             digit = divrem(b, base);
     386               0 :             JS_ASSERT(digit < (uint32_t)base);
     387               0 :             *p++ = BASEDIGIT(digit);
     388                 :         } while (b->wds);
     389               0 :         Bfree(PASS_STATE b);
     390                 :     }
     391                 :     /* Reverse the digits of the integer part of d. */
     392             326 :     q = p-1;
     393             772 :     while (q > pInt) {
     394             120 :         char ch = *pInt;
     395             120 :         *pInt++ = *q;
     396             120 :         *q-- = ch;
     397                 :     }
     398                 : 
     399             326 :     dval(df) = dval(d) - dval(di);
     400             326 :     if (dval(df) != 0.0) {
     401                 :         /* We have a fraction. */
     402                 :         int e, bbits;
     403                 :         int32_t s2, done;
     404                 :         Bigint *b, *s, *mlo, *mhi;
     405                 : 
     406             296 :         b = s = mlo = mhi = NULL;
     407                 : 
     408             296 :         *p++ = '.';
     409             296 :         b = d2b(PASS_STATE df, &e, &bbits);
     410             296 :         if (!b) {
     411                 :           nomem2:
     412               0 :             Bfree(PASS_STATE b);
     413               0 :             Bfree(PASS_STATE s);
     414               0 :             if (mlo != mhi)
     415               0 :                 Bfree(PASS_STATE mlo);
     416               0 :             Bfree(PASS_STATE mhi);
     417               0 :             UnwantedForeground::free_(buffer);
     418               0 :             return NULL;
     419                 :         }
     420             296 :         JS_ASSERT(e < 0);
     421                 :         /* At this point df = b * 2^e.  e must be less than zero because 0 < df < 1. */
     422                 : 
     423             296 :         s2 = -(int32_t)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);
     424                 : #ifndef Sudden_Underflow
     425             296 :         if (!s2)
     426               0 :             s2 = -1;
     427                 : #endif
     428             296 :         s2 += Bias + P;
     429                 :         /* 1/2^s2 = (nextDouble(d) - d)/2 */
     430             296 :         JS_ASSERT(-s2 < e);
     431             296 :         mlo = i2b(PASS_STATE 1);
     432             296 :         if (!mlo)
     433               0 :             goto nomem2;
     434             296 :         mhi = mlo;
     435             296 :         if (!word1(d) && !(word0(d) & Bndry_mask)
     436                 : #ifndef Sudden_Underflow
     437               0 :             && word0(d) & (Exp_mask & Exp_mask << 1)
     438                 : #endif
     439                 :             ) {
     440                 :             /* The special case.  Here we want to be within a quarter of the last input
     441                 :                significant digit instead of one half of it when the output string's value is less than d.  */
     442               0 :             s2 += Log2P;
     443               0 :             mhi = i2b(PASS_STATE 1<<Log2P);
     444               0 :             if (!mhi)
     445               0 :                 goto nomem2;
     446                 :         }
     447             296 :         b = lshift(PASS_STATE b, e + s2);
     448             296 :         if (!b)
     449               0 :             goto nomem2;
     450             296 :         s = i2b(PASS_STATE 1);
     451             296 :         if (!s)
     452               0 :             goto nomem2;
     453             296 :         s = lshift(PASS_STATE s, s2);
     454             296 :         if (!s)
     455               0 :             goto nomem2;
     456                 :         /* At this point we have the following:
     457                 :          *   s = 2^s2;
     458                 :          *   1 > df = b/2^s2 > 0;
     459                 :          *   (d - prevDouble(d))/2 = mlo/2^s2;
     460                 :          *   (nextDouble(d) - d)/2 = mhi/2^s2. */
     461                 : 
     462             296 :         done = JS_FALSE;
     463            3178 :         do {
     464                 :             int32_t j, j1;
     465                 :             Bigint *delta;
     466                 : 
     467            3178 :             b = multadd(PASS_STATE b, base, 0);
     468            3178 :             if (!b)
     469               0 :                 goto nomem2;
     470            3178 :             digit = quorem2(b, s2);
     471            3178 :             if (mlo == mhi) {
     472            3178 :                 mlo = mhi = multadd(PASS_STATE mlo, base, 0);
     473            3178 :                 if (!mhi)
     474               0 :                     goto nomem2;
     475                 :             }
     476                 :             else {
     477               0 :                 mlo = multadd(PASS_STATE mlo, base, 0);
     478               0 :                 if (!mlo)
     479               0 :                     goto nomem2;
     480               0 :                 mhi = multadd(PASS_STATE mhi, base, 0);
     481               0 :                 if (!mhi)
     482               0 :                     goto nomem2;
     483                 :             }
     484                 : 
     485                 :             /* Do we yet have the shortest string that will round to d? */
     486            3178 :             j = cmp(b, mlo);
     487                 :             /* j is b/2^s2 compared with mlo/2^s2. */
     488            3178 :             delta = diff(PASS_STATE s, mhi);
     489            3178 :             if (!delta)
     490               0 :                 goto nomem2;
     491            3178 :             j1 = delta->sign ? 1 : cmp(b, delta);
     492            3178 :             Bfree(PASS_STATE delta);
     493                 :             /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
     494                 : 
     495                 : #ifndef ROUND_BIASED
     496            3178 :             if (j1 == 0 && !(word1(d) & 1)) {
     497               0 :                 if (j > 0)
     498               0 :                     digit++;
     499               0 :                 done = JS_TRUE;
     500                 :             } else
     501                 : #endif
     502            3178 :             if (j < 0 || (j == 0
     503                 : #ifndef ROUND_BIASED
     504               0 :                 && !(word1(d) & 1)
     505                 : #endif
     506                 :                 )) {
     507             248 :                 if (j1 > 0) {
     508                 :                     /* Either dig or dig+1 would work here as the least significant digit.
     509                 :                        Use whichever would produce an output value closer to d. */
     510             197 :                     b = lshift(PASS_STATE b, 1);
     511             197 :                     if (!b)
     512               0 :                         goto nomem2;
     513             197 :                     j1 = cmp(b, s);
     514             197 :                     if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output
     515                 :                                  * such as 3.5 in base 3.  */
     516              95 :                         digit++;
     517                 :                 }
     518             248 :                 done = JS_TRUE;
     519            2930 :             } else if (j1 > 0) {
     520              48 :                 digit++;
     521              48 :                 done = JS_TRUE;
     522                 :             }
     523            3178 :             JS_ASSERT(digit < (uint32_t)base);
     524            3178 :             *p++ = BASEDIGIT(digit);
     525            3178 :         } while (!done);
     526             296 :         Bfree(PASS_STATE b);
     527             296 :         Bfree(PASS_STATE s);
     528             296 :         if (mlo != mhi)
     529               0 :             Bfree(PASS_STATE mlo);
     530             296 :         Bfree(PASS_STATE mhi);
     531                 :     }
     532             326 :     JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE);
     533             326 :     *p = '\0';
     534             326 :     return buffer;
     535                 : }
     536                 : 
     537                 : DtoaState *
     538           19910 : js_NewDtoaState()
     539                 : {
     540           19910 :     return newdtoa();
     541                 : }
     542                 : 
     543                 : void
     544           19908 : js_DestroyDtoaState(DtoaState *state)
     545                 : {
     546           19908 :     destroydtoa(state);
     547           19908 : }

Generated by: LCOV version 1.7