diff --git a/ChangeLog b/ChangeLog index e69b87635d..823440068e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6225,4 +6225,5 @@ (2013-12-13). * fs/procfs/procfs_utils.c: Move some re-usable functions out of fs_procfsproc.c into a utility file (2013-12-14). + * fs/procfs/fs_procfsuptime.c: Supports /proc/uptime (2013-12-14). diff --git a/fs/procfs/Kconfig b/fs/procfs/Kconfig index 6c1c34bf08..84df4a620d 100644 --- a/fs/procfs/Kconfig +++ b/fs/procfs/Kconfig @@ -35,6 +35,10 @@ config FS_PROCFS_EXCLUDE_PROCESS This will reduce code space, but then giving access to process info was kinda the whole point of procfs, but hey, whatever. +config FS_PROCFS_EXCLUDE_UPTIME + bool "Exclude uptime" + default n + config FS_PROCFS_EXCLUDE_PARTITIONS bool "Exclude partitions" depends on MTD_PARTITION diff --git a/fs/procfs/Make.defs b/fs/procfs/Make.defs index c29dce37c3..8b05cbb176 100644 --- a/fs/procfs/Make.defs +++ b/fs/procfs/Make.defs @@ -37,7 +37,7 @@ ifeq ($(CONFIG_FS_PROCFS),y) # Files required for procfs file system support ASRCS += -CSRCS += fs_procfs.c fs_procfsproc.c fs_procfsutil.c +CSRCS += fs_procfs.c fs_procfsutil.c fs_procfsproc.c fs_procfsuptime.c # Include procfs build support diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index a44d00f93b..c547bf17f2 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -76,6 +76,7 @@ ****************************************************************************/ extern const struct procfs_operations process_operations; +extern const struct procfs_operations uptime_operations; extern const struct procfs_operations mtd_procfsoperations; extern const struct procfs_operations part_procfsoperations; extern const struct procfs_operations smartfs_procfsoperations; @@ -101,6 +102,9 @@ static const struct procfs_entry_s g_procfsentries[] = #if defined(CONFIG_MTD_PARTITION) && !defined(CONFIG_FS_PROCFS_EXCLUDE_PARTITON) { "partitions", &part_procfsoperations }, #endif +#if !defined(CONFIG_FS_PROCFS_EXCLUDE_UPTIME) + { "uptime", &uptime_operations }, +#endif }; static const uint8_t g_procfsentrycount = sizeof(g_procfsentries) / diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index 8721ce07e3..119eaf466a 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -68,6 +68,9 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Determines the size of an intermeidate buffer that must be large enough + * to handle the longest line generated by this logic. + */ #define STATUS_LINELEN 32 @@ -344,7 +347,7 @@ static ssize_t process_status(FAR struct process_file_s *attr, return totalsize; } - /* Show the signal mast */ + /* Show the signal mask */ #ifndef CONFIG_DISABLE_SIGNALS linesize = snprintf(attr->line, STATUS_LINELEN, "%-12s%08x\n", "SigMask:", diff --git a/fs/procfs/fs_procfsuptime.c b/fs/procfs/fs_procfsuptime.c new file mode 100644 index 0000000000..642e8e4768 --- /dev/null +++ b/fs/procfs/fs_procfsuptime.c @@ -0,0 +1,359 @@ +/**************************************************************************** + * fs/procfs/fs_procfsuptime.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) +#ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Determines the size of an intermeidate buffer that must be large enough + * to handle the longest line generated by this logic. + */ + +#define UPTIME_LINELEN 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes one open "file" */ + +struct uptime_file_s +{ + struct procfs_file_s base; /* Base open file structure */ + char line[UPTIME_LINELEN]; /* Pre-allocated buffer for formatted lines */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* File system methods */ + +static int uptime_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +static int uptime_close(FAR struct file *filep); +static ssize_t uptime_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); + +static int uptime_dup(FAR const struct file *oldp, + FAR struct file *newp); + +static int uptime_stat(FAR const char *relpath, FAR struct stat *buf); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct procfs_operations uptime_operations = +{ + uptime_open, /* open */ + uptime_close, /* close */ + uptime_read, /* read */ + NULL, /* write */ + + uptime_dup, /* dup */ + + NULL, /* opendir */ + NULL, /* closedir */ + NULL, /* readdir */ + NULL, /* rewinddir */ + + uptime_stat /* stat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uptime_open + ****************************************************************************/ + +static int uptime_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + FAR struct uptime_file_s *attr; + + fvdbg("Open '%s'\n", relpath); + + /* PROCFS is read-only. Any attempt to open with any kind of write + * access is not permitted. + * + * REVISIT: Write-able proc files could be quite useful. + */ + + if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) + { + fdbg("ERROR: Only O_RDONLY supported\n"); + return -EACCES; + } + + /* "uptime" is the only acceptable value for the relpath */ + + if (strcmp(relpath, "uptime") != 0) + { + fdbg("ERROR: relpath is '%s'\n", relpath); + return -ENOENT; + } + + /* Allocate a container to hold the file attributes */ + + attr = (FAR struct uptime_file_s *)kzalloc(sizeof(struct uptime_file_s)); + if (!attr) + { + fdbg("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* Save the attributes as the open-specific state in filep->f_priv */ + + filep->f_priv = (FAR void *)attr; + return OK; +} + +/**************************************************************************** + * Name: uptime_close + ****************************************************************************/ + +static int uptime_close(FAR struct file *filep) +{ + FAR struct uptime_file_s *attr; + + /* Recover our private data from the struct file instance */ + + attr = (FAR struct uptime_file_s *)filep->f_priv; + DEBUGASSERT(attr); + + /* Release the file attributes structure */ + + kfree(attr); + filep->f_priv = NULL; + return OK; +} + +/**************************************************************************** + * Name: uptime_read + ****************************************************************************/ + +static ssize_t uptime_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct uptime_file_s *attr; + size_t linesize; + off_t offset; + ssize_t ret; + +#ifdef CONFIG_SYSTEM_TIME64 + /* 32-bit timer */ + + uint64_t upticks = clock_systimer64(); + +#if defined(CONFIG_HAVE_DOUBLE) && defined(CONFIG_LIBC_FLOATINGPOINT) + double now = (double)upticks / (double)CLOCKS_PER_SEC; + +#else + uint64_t sec = upticks / CLOCKS_PER_SEC; + unsigned int remainder = (unsigned int)(upticks % CLOCKS_PER_SEC); + unsigned int csec = (100 * remainder + (CLOCKS_PER_SEC / 2)) / CLOCKS_PER_SEC; + +#endif +#else + /* 32-bit timer */ + + uint32_t upticks = clock_systimer(); + +#if defined(CONFIG_HAVE_DOUBLE) && defined(CONFIG_LIBC_FLOATINGPOINT) + double now = (double)upticks / (double)CLOCKS_PER_SEC; + +#else + uint32_t sec = upticks / CLOCKS_PER_SEC; + unsigned int remainder = (unsigned int)(upticks % CLOCKS_PER_SEC); + unsigned int csec = (100 * remainder + (CLOCKS_PER_SEC / 2)) / CLOCKS_PER_SEC; + +#endif +#endif + + fvdbg("buffer=%p buflen=%d\n", buffer, (int)buflen); + + /* Recover our private data from the struct file instance */ + + attr = (FAR struct uptime_file_s *)filep->f_priv; + DEBUGASSERT(attr); + +#if defined(CONFIG_HAVE_DOUBLE) && defined(CONFIG_LIBC_FLOATINGPOINT) + /* Convert the system up time to seconds + hundredths of seconds */ + + linesize = snprintf(attr->line, UPTIME_LINELEN, "%10.2f\n", now); + +#else + /* Make sure that rounding did not force the hundredths of a second above 99 */ + + if (csec > 99) + { + sec++; + csec -= 100; + } + + /* Convert the system up time to seconds + hundredths of seconds */ + + linesize = snprintf(attr->line, UPTIME_LINELEN, "%7lu.%02u\n", sec, csec); + +#endif + + /* Transfer the system up time to user receive buffer */ + + offset = filep->f_pos; + ret = procfs_memcpy(attr->line, linesize, buffer, buflen, &offset); + + /* Update the file offset */ + + if (ret > 0) + { + filep->f_pos += ret; + } + + return ret; +} + +/**************************************************************************** + * Name: uptime_dup + * + * Description: + * Duplicate open file data in the new file structure. + * + ****************************************************************************/ + +static int uptime_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + FAR struct uptime_file_s *oldattr; + FAR struct uptime_file_s *newattr; + + fvdbg("Dup %p->%p\n", oldp, newp); + + /* Recover our private data from the old struct file instance */ + + oldattr = (FAR struct uptime_file_s *)oldp->f_priv; + DEBUGASSERT(oldattr); + + /* Allocate a new container to hold the task and attribute selection */ + + newattr = (FAR struct uptime_file_s *)kzalloc(sizeof(struct uptime_file_s)); + if (!newattr) + { + fdbg("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* The copy the file attribtes from the old attributes to the new */ + + memcpy(&newattr->base, &oldattr->base, sizeof(struct procfs_file_s)); + + /* Save the new attributes in the new file structure */ + + newp->f_priv = (FAR void *)newattr; + return OK; +} + +/**************************************************************************** + * Name: uptime_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +static int uptime_stat(const char *relpath, struct stat *buf) +{ + int ret; + + /* "uptime" is the only acceptable value for the relpath */ + + if (strcmp(relpath, "uptime") != 0) + { + fdbg("ERROR: relpath is '%s'\n", relpath); + return -ENOENT; + } + + /* "uptime" is the name for a read-only file */ + + buf->st_mode = S_IFREG|S_IROTH|S_IRGRP|S_IRUSR; + buf->st_size = 0; + buf->st_blksize = 0; + buf->st_blocks = 0; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* CONFIG_FS_PROCFS_EXCLUDE_PROCESS */ +#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */ diff --git a/libc/stdio/lib_dtoa.c b/libc/stdio/lib_dtoa.c index 44290ae328..6241a486b4 100644 --- a/libc/stdio/lib_dtoa.c +++ b/libc/stdio/lib_dtoa.c @@ -147,6 +147,7 @@ static Bigint *Balloc(int k) rv->k = k; rv->maxwds = x; } + rv->sign = rv->wds = 0; return rv; } @@ -189,6 +190,7 @@ static Bigint *multadd(Bigint * b, int m, int a) #endif } while (++i < wds); + if (a) { if (wds >= b->maxwds) @@ -201,6 +203,7 @@ static Bigint *multadd(Bigint * b, int m, int a) b->x[wds++] = a; b->wds = wds; } + return b; } @@ -240,6 +243,7 @@ static int hi0bits(unsigned long x) return 32; } } + return k; } @@ -254,11 +258,13 @@ static int lo0bits(unsigned long *y) { return 0; } + if (x & 2) { *y = x >> 1; return 1; } + *y = x >> 2; return 2; } @@ -297,6 +303,7 @@ static int lo0bits(unsigned long *y) return 32; } } + *y = x; return k; } @@ -336,11 +343,13 @@ static Bigint *mult(Bigint * a, Bigint * b) { k++; } + c = Balloc(k); for (x = c->x, xa = x + wc; x < xa; x++) { *x = 0; } + xa = a->x; xae = xa + wa; xb = b->x; @@ -363,8 +372,10 @@ static Bigint *mult(Bigint * a, Bigint * b) Storeinc(xc, z2, z); } while (x < xae); + *xc = carry; } + if ((y = *xb >> 16)) { x = xa; @@ -380,6 +391,7 @@ static Bigint *mult(Bigint * a, Bigint * b) carry = z2 >> 16; } while (x < xae); + *xc = z2; } } @@ -398,10 +410,12 @@ static Bigint *mult(Bigint * a, Bigint * b) *xc++ = z & 0xffff; } while (x < xae); + *xc = carry; } } #endif + for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc); c->wds = wc; return c; @@ -438,6 +452,7 @@ static Bigint *pow5mult(Bigint * b, int k) Bfree(b); b = b1; } + if (!(k >>= 1)) { break; @@ -448,8 +463,10 @@ static Bigint *pow5mult(Bigint * b, int k) p51 = p5->next = mult(p5, p5); p51->next = 0; } + p5 = p51; } + return b; } @@ -470,12 +487,14 @@ static Bigint *lshift(Bigint * b, int k) { k1++; } + b1 = Balloc(k1); x1 = b1->x; for (i = 0; i < n; i++) { *x1++ = 0; } + x = b->x; xe = x + b->wds; #ifdef Pack_32 @@ -489,6 +508,7 @@ static Bigint *lshift(Bigint * b, int k) z = *x++ >> k1; } while (x < xe); + if ((*x1 = z)) { ++n1; @@ -505,6 +525,7 @@ static Bigint *lshift(Bigint * b, int k) z = *x++ >> k1; } while (x < xe); + if ((*x1 = z)) { ++n1; @@ -512,11 +533,14 @@ static Bigint *lshift(Bigint * b, int k) } #endif else - do - { - *x1++ = *x++; - } - while (x < xe); + { + do + { + *x1++ = *x++; + } + while (x < xe); + } + b1->wds = n1 - 1; Bfree(b); return b1; @@ -534,13 +558,18 @@ static int cmp(Bigint * a, Bigint * b) { ldbg("cmp called with a->x[a->wds-1] == 0\n"); } + if (j > 1 && !b->x[j - 1]) { ldbg("cmp called with b->x[b->wds-1] == 0\n"); } #endif + if (i -= j) - return i; + { + return i; + } + xa0 = a->x; xa = xa0 + j; xb0 = b->x; @@ -548,9 +577,14 @@ static int cmp(Bigint * a, Bigint * b) for (;;) { if (*--xa != *--xb) - return *xa < *xb ? -1 : 1; + { + return *xa < *xb ? -1 : 1; + } + if (xa <= xa0) - break; + { + break; + } } return 0; } @@ -573,6 +607,7 @@ static Bigint *diff(Bigint * a, Bigint * b) c->x[0] = 0; return c; } + if (i < 0) { c = a; @@ -581,7 +616,10 @@ static Bigint *diff(Bigint * a, Bigint * b) i = 1; } else - i = 0; + { + i = 0; + } + c = Balloc(a->k); c->sign = i; wa = a->wds; @@ -604,6 +642,7 @@ static Bigint *diff(Bigint * a, Bigint * b) Storeinc(xc, z, y); } while (xb < xbe); + while (xa < xae) { y = (*xa & 0xffff) + borrow; @@ -623,6 +662,7 @@ static Bigint *diff(Bigint * a, Bigint * b) *xc++ = y & 0xffff; } while (xb < xbe); + while (xa < xae) { y = *xa++ + borrow; @@ -631,8 +671,12 @@ static Bigint *diff(Bigint * a, Bigint * b) *xc++ = y & 0xffff; } #endif + while (!*--xc) - wa--; + { + wa--; + } + c->wds = wa; return c; } @@ -663,7 +707,10 @@ static Bigint *d2b(double d, int *e, int *bits) z >>= k; } else - x[0] = y; + { + x[0] = y; + } + i = b->wds = (x[1] = z) ? 2 : 1; } else @@ -727,6 +774,7 @@ static Bigint *d2b(double d, int *e, int *bits) x[1] = z >> 16; i = 1; } + k += 32; } while (!x[i]) @@ -747,10 +795,12 @@ static Bigint *d2b(double d, int *e, int *bits) *bits = (i + 2) * 16 - hi0bits(x[i]); #endif } + return b; } -static const double tens[] = { +static const double tens[] = +{ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 @@ -790,6 +840,7 @@ static int quorem(Bigint * b, Bigint * S) { return 0; } + sx = S->x; sxe = sx + --n; bx = b->x; @@ -801,6 +852,7 @@ static int quorem(Bigint * b, Bigint * S) ldbg("oversized quotient in quorem\n"); } #endif + if (q) { borrow = 0; @@ -829,11 +881,15 @@ static int quorem(Bigint * b, Bigint * S) #endif } while (sx <= sxe); + if (!*bxe) { bx = b->x; while (--bxe > bx && !*bxe) - --n; + { + --n; + } + b->wds = n; } } @@ -877,6 +933,7 @@ static int quorem(Bigint * b, Bigint * S) b->wds = n; } } + return q; } @@ -921,14 +978,14 @@ static int quorem(Bigint * b, Bigint * S) char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) { /* Arguments ndigits, decpt, sign are similar to those of ecvt and fcvt; - * trailing zeros are suppressed from the returned string. If not null, *rve + * trailing zeros are suppressed from the returned string. If not null, *rve * is set to point to the end of the return value. If d is +-Infinity or * NaN, then *decpt is set to 9999. - * + * * mode: 0 ==> shortest string that yields d when read in and rounded to * nearest. 1 ==> like 0, but with Steele & White stopping rule; e.g. with * IEEE P754 arithmetic , mode 0 gives 1e23 whereas mode 1 gives - * 9.999999999999999e22. 2 ==> max(1,ndigits) significant digits. This gives + * 9.999999999999999e22. 2 ==> max(1,ndigits) significant digits. This gives * a return value similar to that of ecvt, except that trailing zeros are * suppressed. 3 ==> through ndigits past the decimal point. This gives a * return value similar to that from fcvt, except that trailing zeros are @@ -938,9 +995,9 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) * sometimes faster than modes 2-3. 4,5,8,9 ==> left-to-right digit * generation. 6-9 ==> don't try fast floating-point estimate (if * applicable). - * + * * Values of mode other than 0-9 are treated as mode 0. - * + * * Sufficient space is allocated to the return value to hold the suppressed * trailing zeros. */ @@ -989,11 +1046,14 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) #endif "NaN"; if (rve) - *rve = + { + *rve = #ifdef IEEE_Arith - s[3] ? s + 8 : + s[3] ? s + 8 : #endif - s + 3; + s + 3; + } + return s; } #endif @@ -1002,7 +1062,10 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) *decpt = 1; s = "0"; if (rve) - *rve = s + 1; + { + *rve = s + 1; + } + return s; } @@ -1017,10 +1080,10 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) * log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) log10(d) = * (i-Bias)*log(2)/log(10) + log10(d2) This suggests computing an * approximation k to log10(d) by k = (i - Bias)*0.301029995663981 + ( - * (d2-1.5)*0.289529654602168 + 0.176091259055681 ); We want k to be too + * (d2-1.5)*0.289529654602168 + 0.176091259055681 ); We want k to be too * large rather than too small. The error in the first-order Taylor - * series approximation is in our favor, so we just round up the constant - * enough to compensate for any error in the multiplication of (i - Bias) + * series approximation is in our favor, so we just round up the constant + * enough to compensate for any error in the multiplication of (i - Bias) * by 0.301029995663981; since |i - Bias| <= 1077, and 1077 * 0.30103 * * 2^-52 ~=~ 7.2e-14, adding 1e-13 to the constant term more than * suffices. Hence we adjust the constant term to 0.1760912590558. (We @@ -1049,6 +1112,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) { k--; /* want k = floor(ds) */ } + k_check = 1; if (k >= 0 && k <= Ten_pmax) @@ -1226,11 +1290,20 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) d -= L; *s++ = '0' + (int)L; if (d < eps) - goto ret1; + { + goto ret1; + } + if (1. - d < eps) - goto bump_up; + { + goto bump_up; + } + if (++i >= ilim) - break; + { + break; + } + eps *= 10.; d *= 10.; } @@ -1239,7 +1312,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) { #endif /* Generate ilim digits, then fix them up. */ - + eps *= tens[ilim - 1]; for (i = 1;; i++, d *= 10.) { @@ -1249,13 +1322,16 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) if (i == ilim) { if (d > 0.5 + eps) - goto bump_up; + { + goto bump_up; + } else if (d < 0.5 - eps) { while (*--s == '0'); s++; goto ret1; } + break; } } @@ -1280,7 +1356,10 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) { S = mhi = 0; if (ilim < 0 || d <= 5 * ds) - goto no_digits; + { + goto no_digits; + } + goto one_digit; } @@ -1310,10 +1389,12 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) *s = '0'; break; } + ++*s++; } break; } + if (!(d *= 10.)) { break; @@ -1343,6 +1424,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) b5 += j; m5 = 0; } + if ((i = ilim) < 0) { m2 -= i; @@ -1374,8 +1456,11 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) Bfree(b); b = b1; } + if ((j = b5 - m5)) - b = pow5mult(b, j); + { + b = pow5mult(b, j); + } } else { @@ -1471,10 +1556,12 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) if (ilim < 0 || cmp(b, S = multadd(S, 5, 0)) <= 0) { /* no digits, fcvt style */ + no_digits: k = -1 - ndigits; goto ret; } + one_digit: *s++ = '1'; k++; @@ -1603,6 +1690,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) *s++ = '1'; goto ret; } + ++*s++; } else @@ -1625,7 +1713,7 @@ ret: ret1: Bfree(b); if (s == s0) - { /* don't return empty string */ + { /* Don't return empty string */ *s++ = '0'; k = 0; } diff --git a/libc/stdio/lib_libdtoa.c b/libc/stdio/lib_libdtoa.c index 7f39701271..7fc8369bce 100644 --- a/libc/stdio/lib_libdtoa.c +++ b/libc/stdio/lib_libdtoa.c @@ -160,7 +160,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, /* Special handling for NaN and Infinity */ - if (isnan(value)) + if (isnan(value)) { lib_dtoa_string(obj, "NaN"); return; @@ -168,7 +168,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, if (isinf(value)) { - if (value < 0.0d) + if (value < 0.0) { obj->put(obj, '-'); } @@ -340,4 +340,3 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, /**************************************************************************** * Public Functions ****************************************************************************/ -