This is an automated email from the ASF dual-hosted git repository.

kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 79d699bc4 baselibc: Add strtof implementation
79d699bc4 is described below

commit 79d699bc42b0b40aeb74a9c9fefc6aa6405a0296
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Mon Jun 22 08:56:23 2026 +0200

    baselibc: Add strtof implementation
    
    While strtof has prototype in stdlib.h there was
    no implementation of this function, meaning compiler
    would search for this function in standard libraries.
    
    This would not be a problem for other functions
    mostly math functions do not have implementations
    in baselibc.
    
    However this function in libraries provided by arm
    gcc is really using _strtod_l which works on double
    precission numbers, moreover this _strtod_l forces
    inclusion of other code that baselibc already
    covers like malloc/free it can also lead to inclusion
    of other function and eventually conflicts during
    link time.
    
    This provide local strtof implemenation that does not
    depends on anything.
    
    For now hex string literals are not covered.
    
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 libc/baselibc/src/mynewt.c | 160 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 160 insertions(+)

diff --git a/libc/baselibc/src/mynewt.c b/libc/baselibc/src/mynewt.c
index a8f12ee7d..3c79a80dd 100644
--- a/libc/baselibc/src/mynewt.c
+++ b/libc/baselibc/src/mynewt.c
@@ -18,6 +18,8 @@
  */
 
 #include <stdio.h>
+#include <ctype.h>
+#include <math.h>
 #include <console/console.h>
 #include <os/os_time.h>
 #include <os/os_mutex.h>
@@ -54,6 +56,164 @@ fflush(FILE *stream)
     return 0;
 }
 
+static const char *
+eat_spaces(const char *p)
+{
+    while (isspace(*p)) {
+        ++p;
+    }
+
+    return p;
+}
+
+static const char *
+eat_sign(const char *p, int *sign)
+{
+    *sign = 1;
+
+    if (*p == '+' || *p == '-') {
+        *sign = ',' - *p;
+        ++p;
+    }
+
+    return p;
+}
+
+static const char *
+eat_base(const char *p, int *base)
+{
+    if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) {
+        *base = 16;
+        p += 2;
+    } else {
+        *base = 10;
+    }
+    return p;
+}
+
+static const char *
+eat_leading_zeros(const char *p)
+{
+    while (*p == '0') {
+        ++p;
+    }
+
+    return p;
+}
+
+static const char *
+eat_digits(const char *p, unsigned int *n, bool frac, int *exp)
+{
+    unsigned int val = *n;
+
+    while (isdigit(*p)) {
+        if (val < 429496729) {
+            val = val * 10 + *p - '0';
+            if (frac) {
+                --*exp;
+            }
+        } else if (!frac && exp) {
+            ++*exp;
+        }
+        ++p;
+    }
+    *n = val;
+
+    return p;
+}
+
+static float
+fexp10(int mant, int n)
+{
+    float result = (float)mant;
+    float mul = 10.0f;
+    bool plus = n >= 0;
+
+    n = abs(n);
+
+    for (; n != 0; n >>= 1) {
+        if (n & 1) {
+            if (plus) {
+                result *= mul;
+            } else {
+                result /= mul;
+            }
+        }
+        mul = mul * mul;
+    }
+    return result;
+}
+
+static bool
+eat_dot(const char **s)
+{
+    if (**s == '.') {
+        ++*s;
+        return true;
+    }
+    return false;
+}
+
+static bool
+eat_e(const char **s)
+{
+    if (**s == 'E' || **s == 'e') {
+        ++*s;
+        return true;
+    }
+    return false;
+}
+
+float
+strtof(const char *str, char **strend)
+{
+    const char *p = str;
+    int sign;
+    int base;
+    unsigned int mant = 0;
+    int exp = 0;
+    int exp_sign = 1;
+    float f = 0;
+
+    p = eat_spaces(p);
+    p = eat_sign(p, &sign);
+    p = eat_base(p, &base);
+    p = eat_leading_zeros(p);
+    if (base == 10) {
+        p = eat_digits(p, &mant, false, &exp);
+        if (eat_dot(&p)) {
+            if (mant == 0) {
+                const char *s = p;
+                p = eat_leading_zeros(p);
+                exp = s - p;
+            }
+            p = eat_digits(p, &mant, true, &exp);
+        }
+        if (eat_e(&p)) {
+            unsigned int exp1 = 0;
+
+            p = eat_sign(p, &exp_sign);
+            p = eat_leading_zeros(p);
+            p = eat_digits(p, &exp1, false, NULL);
+            exp += exp_sign * exp1;
+        }
+        if (exp > 45) {
+            f = exp_sign == 1 ? INFINITY : 0.0f;
+        } else if (exp == 0) {
+            f = (float)mant;
+        } else {
+            f = fexp10(mant, exp);
+        }
+        f *= sign;
+    } else if (base == 16) {
+        /* Not implemented */
+    }
+    if (strend) {
+        *strend = (char *)p;
+    }
+    return f;
+}
+
 #if MYNEWT_VAL(BASELIBC_THREAD_SAFE_HEAP_ALLOCATION)
 
 static struct os_mutex heap_mutex;

Reply via email to