Arduino stdlib Library Replacement

Excludes memory allocation functions. Compiled from various sources.

Just because.

ctype_.h

// ctype_ header.
#ifndef _CTYPE_H
#define _CTYPE_H

#ifdef __cplusplus
extern "C" {
#endif

inline int isalnum_(int c) { return ((c >= '0' && c <= '9') || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z')); }
inline int isalpha_(int c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); }
inline int iscntrl_(int c) { return ((c & ~0x1f) == 0 || c == 0x7f); }
inline int isdigit_(int c) { return c >= '0' && c <= '9'; }
inline int isgraph_(int c) { return (c >= '!' && c <= '~'); }
inline int islower_(int c) { return (c >= 'a' && c <= 'z'); }
inline int isprint_(int c) { return (c >= ' ' && c <= '~'); }
inline int ispunct_(int c) { return ((c >= '!' && c <= '~') && !((c >= '0' && c <= '9') || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z'))); }
inline int isspace_(int c) { return (c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'); }
inline int isupper_(int c) { return (c >= 'A' && c <= 'Z'); }
inline int isxdigit_(int c) { return ((c >= '0' && c <= '9') || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'F')); }

inline int tolower_(int const c)
{
    if (c >= 'A' && c <= 'Z')
        return c - ('A' - 'a');

    return c;
}

inline int toupper_(int const c)
{
    if (c >= 'a' && c <= 'z')
        return c - ('a' - 'A');

    return c;
}

inline int isascii_(int c) { return (c >= 0x00 && c <= 0x7f); }
inline int isblank_(int c) { return (c == ' ' || c == '\t'); }

#ifdef __cplusplus
}
#endif

#endif

stdio_.h

// stdio_ header.
#ifndef _STDIO_H
#define _STDIO_H

#ifdef __cplusplus
extern "C" {
#endif

#define NULL      (void *)0
#define size_t    int

#ifdef __cplusplus
}
#endif

#endif

stdlib_.h

// stdlib_ header.
#ifndef _STDLIB_H
#define _STDLIB_H

#include "stdio_.h"
#include "string_.h"
#include "ctype_.h"
#include <limits.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#define _RAND_MAX 32767
#define MAX_BUF   256 // chunk to copy on swap.

typedef struct 
{
  int quot;
  int rem;
} div_t;

typedef struct 
{
  long quot;
  long rem;
} ldiv_t;

typedef int compare(const void*, const void*);
// Example of compare function:
// int compare(const void* a, const void* b) {
//   const int* ia = (const int *)a; 
//   const int* ib = (const int *)b;
//   return *ia  - *ib; 
// }

int abs_(int);
long labs_(long);
int atoi_(const char*);
long atol_(const char*);
unsigned long atoul_(const char*);
double atof_(const char*);
div_t div_(int, int);
ldiv_t ldiv_(long, long);
void qsort_(void*, size_t, size_t, compare*);
int rand_(void);
void srand_(unsigned int);
char* itoa_(int, char*, int);
char* utoa_(unsigned, char*, int);
char* ltoa_(long, char*, int);
char* ultoa_(unsigned long, char*, int);

union int32_float_t 
{
  int32_t long_;
  float float_;
};

#ifndef FLT_MIN_EXP
#define FLT_MIN_EXP (-999)
#endif
#ifndef FLT_MAX_EXP
#define FLT_MAX_EXP (999)
#endif

#define _FTOA_TOO_LARGE -2  // |input| > 2147483520 
#define _FTOA_TOO_SMALL -1  // |input| < 0.0000001 

// precision 0-9
#define PRECISION 7

void ftoa_(float f, char *p, int *status);

#ifdef __cplusplus
}
#endif

#endif

stdlib_.c

#include "stdlib_.h"

#ifdef __cplusplus
extern "C" {
#endif

// the seed.
unsigned long _Randseed = 1;

// Compute absolute value of int argument.
int abs_(int i) { return ((i < 0) ? -i : i); }

// Compute absolute value of long argument.
long labs_(long i) { return ((i < 0) ? -i : i); }

// Convert a string to an unsigned long integer.  
unsigned long _Stoul(const char* nptr, char** endptr, register int base)
{
    register const char* s = nptr;
    register unsigned long acc;
    register int c;
    register unsigned long cutoff;
    register int neg = 0, any, cutlim;

    do {
        c = *s++;
    } while (isspace_(c));

    if (c == '-')
    {
        neg = 1;
        c = *s++;
    }
    else if (c == '+')
        c = *s++;

    if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X'))
    {
        c = s[1];
        s += 2;
        base = 16;
    }
    
    if (base == 0)
        base = c == '0' ? 8 : 10;
    
    cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
    cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;

    for (acc = 0, any = 0;; c = *s++)
    {
        if (isdigit_(c))
            c -= '0';
        else if (isalpha_(c))
            c -= isupper_(c) ? 'A' - 10 : 'a' - 10;
        else
            break;

        if (c >= base)
            break;

        if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
            any = -1;
        else
        {
            any = 1;
            acc *= base;
            acc += c;
        }
    }

    if (any < 0)
    {
        acc = ULONG_MAX;
        //errno = ERANGE;
    }
    else if (neg)
        acc = -(long)acc;

    if (endptr != 0)
        *endptr = (char*)(any ? s - 1 : nptr);

    return (acc);
}

// Convert string to int.
int atoi_(const char* s) { return ((int)_Stoul(s, NULL, 10)); }

// Convert string to long.
long atol_(const char* s) { return ((long)_Stoul(s, NULL, 10)); }

// Convert string to unsigned long.
unsigned long atoul_(const char* s) { return ((unsigned long)_Stoul(s, NULL, 10)); }

// Convert string to double.
double atof_(const char* s)
{
    double a = 0.0;
    int e = 0;
    int c;

    while ((c = *s++) != '\0' && isdigit_(c))
        a = a * 10.0 + (c - '0');

    if (c == '.')
    {
        while ((c = *s++) != '\0' && isdigit_(c))
        {
            a = a * 10.0 + (c - '0');
            e = e - 1;
        }
    }

    if (c == 'e' || c == 'E')
    {
        int sign = 1;
        int i = 0;

        c = *s++;
        if (c == '+')
            c = *s++;
        else if (c == '-')
        {
            c = *s++;
            sign = -1;
        }
    
        while (isdigit_(c))
        {
            i = i * 10 + (c - '0');
            c = *s++;
        }
        
        e += i * sign;
    }

    while (e > 0)
    {
        a *= 10.0;
        e--;
    }

    while (e < 0)
    {
        a *= 0.1;
        e++;
    }

    return a;
}

char* ltoa_(long value, char* string, int radix)
{
    char tmp[33];
    char* tp = tmp;
    long i;
    unsigned long v;
    int sign;
    char* sp;

    if (string == NULL)
        return 0;

    if (radix > 36 || radix <= 1)
        return 0;

    sign = (radix == 10 && value < 0);
    if (sign)
        v = -value;
    else
        v = (unsigned long)value;

    while (v || tp == tmp)
    {
        i = v % radix;
        v = v / radix;
        
        if (i < 10)
            *tp++ = (char)(i + '0');
        else
            *tp++ = (char)(i + 'a' - 10);
    }

    sp = string;

    if (sign)
        *sp++ = '-';
        
    while (tp > tmp)
        *sp++ = *--tp;
    
    *sp = 0;

    return string;
}

char* ultoa_(unsigned long value, char* string, int radix)
{
    char tmp[33];
    char* tp = tmp;
    long i;
    unsigned long v = value;
    char* sp;

    if (string == NULL)
        return 0;

    if (radix > 36 || radix <= 1)
        return 0;

    while (v || tp == tmp)
    {
        i = v % radix;
        v = v / radix;
        
        if (i < 10)
            *tp++ = (char)(i + '0');
        else
            *tp++ = (char)(i + 'a' - 10);
    }

    sp = string;

    while (tp > tmp)
        *sp++ = *--tp;
    
    *sp = 0;

    return string;
}

char* itoa_(int value, char* string, int radix) { return ltoa_(value, string, radix); }
char* utoa_(unsigned value, char* string, int radix) { return ultoa_(value, string, radix); }

// Sort (char base[size])[n] using quicksort.
void qsort_(void* base, size_t n, size_t size, compare* cmp)
{  
    while (1 < n)
    {
        // worth sorting.
        size_t i = 0;
        size_t j = n - 1;
        char* qi = (char*)base;
        char* qj = qi + size * j;
        char* qp = qj;

        while (i < j)
        {
            // partition about pivot.
            while (i < j && (*cmp)(qi, qp) <= 0)
                ++i, qi += size;
            
            while (i < j && (*cmp)(qp, qj) <= 0)
                --j, qj -= size;
            
            if (i < j)
            { 
                // swap elements i and j.
                char buf[MAX_BUF];
                char* q1 = qi;
                char* q2 = qj;
                size_t m, ms;

                for (ms = size; 0 < ms; ms -= m, q1 += m, q2 += m)
                { 
                    // swap as many as possible.
                    m = ms < sizeof(buf) ? ms : sizeof(buf);
                    memcpy_(buf, q1, m);
                    memcpy_(q1, q2, m);
                    memcpy_(q2, buf, m);
                }
                
                ++i, qi += size;
            }
        }

        if (qi != qp)
        { 
            // swap elements i and pivot.
            char buf[MAX_BUF];
            char* q1 = qi;
            char* q2 = qp;
            size_t m, ms;

            for (ms = size; 0 < ms; ms -= m, q1 += m, q2 += m)
            { 
                // swap as many as possible.
                m = ms < sizeof(buf) ? ms : sizeof(buf);
                memcpy_(buf, q1, m);
                memcpy_(q1, q2, m);
                memcpy_(q2, buf, m);
            }
        }

        j = n - i - 1, qi += size;
        
        if (j < i)
        { 
            // recurse on smaller partition.
            if (1 < j)
                qsort_(qi, j, size, cmp);
            
            n = i;
        }
        else
        { 
            // lower partition is smaller.
            if (1 < i)
                qsort_(base, i, size, cmp);

            base = qi;
            
            n = j;
        }
    }
}

// Compute pseudo-random value.
int rand_(void)
{ 
    _Randseed = _Randseed * 1103515245 + 12345;
    return ((unsigned int)(_Randseed >> 16) & _RAND_MAX);
}

// Alter the seed.
void srand_(unsigned int seed) { _Randseed = seed; }

// Compute int quotient and remainder.
div_t div_(int numer, int denom)
{ 
    div_t val;

    val.quot = numer / denom;
    val.rem = numer - denom * val.quot;
    if (val.quot < 0 && 0 < val.rem)
    { 
        // fix remainder with wrong sign.
        val.quot += 1;
        val.rem -= denom;
    }

    return (val);
}

// Compute long quotient and remainder.
ldiv_t ldiv_(long numer, long denom)
{
    ldiv_t val;

    val.quot = numer / denom;
    val.rem = numer - denom * val.quot;

    if (val.quot < 0 && 0 < val.rem)
    {
        // fix remainder with wrong sign.
        val.quot += 1;
        val.rem -= denom;
    }

    return (val);
}

void ftoa_(float f, char *p, int *status) 
{
  int32_t mantissa, intPart, fracPart;
  int16_t exp2;
  int32_float_t x;

  *status = 0;
  if (f == 0.0) 
  {
    *p++ = '0';
    *p++ = '.';
    *p++ = '0';
    *p = 0;
    return;
  }
  x.float_ = f;
  exp2 = (unsigned char)(x.long_ >> 23) - 127;
  mantissa = (x.long_ & 0xFFFFFF) | 0x800000;
  fracPart = 0;
  intPart = 0;

  if (exp2 >= 31) 
  {
    *status = _FTOA_TOO_LARGE;
    return;
  } 
  else if (exp2 < -23) 
  {
    *status = _FTOA_TOO_SMALL;
    return;
  }
  else if (exp2 >= 23) 
    intPart = mantissa << (exp2 - 23);
  else if (exp2 >= 0) 
  {
    intPart = mantissa >> (23 - exp2);
    fracPart = (mantissa << (exp2 + 1)) & 0xFFFFFF;
  } 
  else 
  {
    //if (exp2 < 0)
    fracPart = (mantissa & 0xFFFFFF) >> -(exp2 + 1);
  }

  if (x.long_ < 0)
      *p++ = '-';
  
  if (intPart == 0)
    *p++ = '0';
  else 
  {
    ltoa_(intPart, p, 10);
    while (*p)
      p++;
  }
  
  *p++ = '.';
  
  if (fracPart == 0)
    *p++ = '0';
  else 
  {
    char m;

    for (m=0; m<PRECISION; m++) 
    {
      //fracPart *= 10;
      fracPart = (fracPart << 3) + (fracPart << 1); 
      *p++ = (fracPart >> 24) + '0';
      fracPart &= 0xFFFFFF;
    }

    // Delete trailing zeroes.
    for (--p; p[0] == '0' && p[-1] != '.'; --p);
    ++p;
  }
  
  *p = 0;
}

#ifdef __cplusplus
}
#endif

About Jim Eli

µC experimenter
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a comment