aboutsummaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/include/stdlib.h4
-rw-r--r--libc/stdlib.c93
2 files changed, 94 insertions, 3 deletions
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index a6e27f2..49116df 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -1,6 +1,8 @@
#ifndef _STDLIB_H_
#define _STDLIB_H_
+#include <stddef.h>
+
/* this is by no means standards-compliant... but who cares? :P */
/* NOT reentrant! */
@@ -14,5 +16,7 @@ char* itoa(int val, int base);
unsigned int rand(void);
void srand(unsigned int);
int abs(int);
+void *malloc(size_t);
+int snprintf(char*, int, const char*, ...);
#endif
diff --git a/libc/stdlib.c b/libc/stdlib.c
index bea3b65..c6a9c3d 100644
--- a/libc/stdlib.c
+++ b/libc/stdlib.c
@@ -1,3 +1,6 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
/* adapted from <http://www.strudel.org.uk/itoa/> */
@@ -54,12 +57,96 @@ void srand(unsigned int seed)
rand_s2 = seed++;
rand_s3 = seed++;
/* "warm it up" */
- rand();
- rand();
- rand();
+ for(int i=0;i<10;++i)
+ rand();
}
int abs(int val)
{
return (val<0?-val:val);
}
+
+void *malloc(size_t sz)
+{
+ static uint8_t mallocbuf[1024*1024*16];
+ static uint8_t *next_ptr = mallocbuf;
+ static int bytes_left = sizeof(mallocbuf);
+ bytes_left -= sz;
+ if(bytes_left < 0)
+ return NULL;
+ else
+ {
+ void *ret = next_ptr;
+ next_ptr += sz;
+ return ret;
+ }
+}
+
+static inline int snputs(char *buf, int idx, int sz, const char *str)
+{
+ while(idx < sz && *str)
+ {
+ buf[idx++] = *str++;
+ }
+ return idx;
+}
+
+static char hex_table[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+static inline int snprint_hex(char *buf, int idx, int sz, unsigned int n)
+{
+ unsigned mask = 0xF0000000;
+ unsigned shift = 28;
+ while(mask && idx < sz)
+ {
+ buf[idx++] = hex_table[(n & mask) >> shift];
+ mask >>= 4;
+ shift -= 4;
+ }
+ return idx;
+}
+
+int snprintf(char *buf, int sz, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int i = 0;
+ /* leave room for the null! */
+ sz--;
+ while(*fmt && i < sz)
+ {
+ char ch = *fmt++;
+ switch(ch)
+ {
+ case '%':
+ {
+ switch(*fmt++)
+ {
+ case 'c':
+ buf[i++] = va_arg(ap, int);
+ break;
+ case 's':
+ i = snputs(buf, i, sz, va_arg(ap, const char*));
+ break;
+ case 'x':
+ i = snprint_hex(buf, i, sz, va_arg(ap, unsigned));
+ break;
+ case 'd':
+ i = snputs(buf, i, sz, itoa(va_arg(ap, unsigned), 10));
+ break;
+ default:
+ i = snputs(buf, i, sz, "snprintf: unknown format\n");
+ break;
+ }
+ break;
+ }
+ default:
+ buf[i++] = ch;
+ break;
+ }
+ }
+ buf[i] = '\0';
+ va_end(ap);
+ return 0;
+}