aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2009-04-26 14:57:08 +0200
committerGuido Günther <agx@sigxcpu.org>2009-04-26 15:26:25 +0200
commit3c8b9481088b546af3f0fd161a432ba0f0cb682e (patch)
treee6a83124f6becb94abc6dfbd03b8bd6400170f81 /common
parentd8a73fe012567565113419dc0c4678df5abe5bc5 (diff)
Move libc functions into a pseudo libc away from libarc
Diffstat (limited to 'common')
-rw-r--r--common/Makefile13
-rw-r--r--common/stddef.h11
-rw-r--r--common/stdio.c281
-rw-r--r--common/stdio.h30
-rw-r--r--common/stdlib.c116
-rw-r--r--common/stdlib.h15
-rw-r--r--common/string.c151
-rw-r--r--common/string.h26
8 files changed, 640 insertions, 3 deletions
diff --git a/common/Makefile b/common/Makefile
index f1f75ca..8a1b06a 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -1,11 +1,18 @@
SUBARCH ?= IP22
-CFLAGS += -Wall -O2 -I. -I../arclib -DSUBARCH=${SUBARCH}
+CFLAGS += -Wall -O2 -I../arclib -mno-abicalls -G 0 -fno-pic -fno-builtin -I. -DSUBARCH=${SUBARCH}
HOSTCC = $(CC)
HOSTCFLAGS += -Wall -O2 -DSUBARCH=$(SUBARCH)
-all:
+TARGETS = libc.a
+OBJECTS = stdlib.o stdio.o string.o
+
+all: $(TARGETS)
+
+libc.a: $(OBJECTS)
+ rm -f $@
+ $(AR) -crs $@ $(OBJECTS)
clean:
- rm -f *~ tags
+ rm -f $(OBJECTS) *~ tags
diff --git a/common/stddef.h b/common/stddef.h
new file mode 100644
index 0000000..97ee87f
--- /dev/null
+++ b/common/stddef.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef _STDDEF_H_
+#define _STDDEF_H_
+
+typedef unsigned int size_t;
+
+#define NULL ((void *) 0)
+
+#endif /* _STDDEF_H_ */
diff --git a/common/stdio.c b/common/stdio.c
new file mode 100644
index 0000000..2d94385
--- /dev/null
+++ b/common/stdio.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#include "string.h"
+#include "stdio.h"
+
+#include <arc.h>
+#include <stdarg.h>
+
+static FILE arc_stdin = ARC_STDIN;
+FILE *stdin = &arc_stdin;
+
+static FILE arc_stdout = ARC_STDOUT;
+FILE *stdout = &arc_stdout;
+
+
+int fputs(const char *s, FILE * stream)
+{
+ long status;
+ unsigned long count;
+
+ if (strlen(s) > 0) {
+ status = ArcWrite(*stream, (char *) s, strlen(s), &count);
+ if ((status != ESUCCESS) || (count != strlen(s)))
+ return EOF;
+ }
+ return 0;
+}
+
+
+int puts(const char *s)
+{
+ int status = fputs(s, stdout);
+
+ if (status != EOF)
+ status = fputs("\n\r", stdout);
+ return status;
+}
+
+
+int fgetc(FILE * stream)
+{
+ long status;
+ char ch;
+ unsigned long count;
+
+ status = ArcRead(*stream, &ch, sizeof(CHAR), &count);
+ if ((status != ESUCCESS) || (count != sizeof(CHAR)))
+ return EOF;
+ return (int) ch;
+}
+
+
+static const char *numtostr(unsigned int num, unsigned int base)
+{
+ static char str[33];
+ static char digits[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+ int pos = 32;
+
+ str[pos] = '\0';
+ do {
+ str[--pos] = digits[num % base];
+ num /= base;
+ } while (num > 0);
+
+ return &str[pos];
+}
+
+
+int vfprintf(FILE * stream, const char *format, va_list ap)
+{
+ int count = 0;
+ const char *str;
+ unsigned int uint;
+ char tmp[2];
+
+ if (format != NULL) {
+ while (*format != '\0') {
+ str = strchr(format, '%');
+ if (str == NULL) {
+ count += strlen(format);
+ fputs(format, stream);
+ break;
+ } else {
+ if (format < str) {
+ LONG status;
+ ULONG count;
+ ULONG len = str - format;
+
+ status =
+ ArcWrite(*stream,
+ (char *) format, len,
+ &count);
+ if ((status != ESUCCESS)
+ || (count != len))
+ return EOF;
+ count += len;
+ }
+
+ format = str + 1;
+ if(*format == 'l')
+ format = str + 2;
+
+ switch (*format) {
+ case 'd':
+ case 'u':
+ uint = va_arg(ap, unsigned int);
+ str = numtostr(uint, 10);
+ if (fputs(str, stream) == EOF)
+ return EOF;
+ count += strlen(str);
+ break;
+
+ case 'p':
+ case 'x':
+ uint = va_arg(ap, unsigned int);
+ str = numtostr(uint, 16);
+ if (fputs(str, stream) == EOF)
+ return EOF;
+ count += strlen(str);
+ break;
+
+ case 's':
+ str = va_arg(ap, const char *);
+ if( !str )
+ str = "(NULL)";
+ if (fputs(str, stream) == EOF)
+ return EOF;
+ count += strlen(str);
+ break;
+
+ case 'c':
+ tmp[0] = (char)va_arg(ap, int);
+ tmp[1] = '\0';
+ if (fputs(tmp, stream) == EOF)
+ return EOF;
+ count++;
+ break;
+
+ case '%':
+ if (fputs("%", stream) == EOF)
+ return EOF;
+ count += 1;
+ break;
+
+ case '\0': /* format error */
+ default:
+ return EOF;
+ }
+
+ format += 1;
+ }
+ }
+ }
+
+ return count;
+}
+
+
+int vprintf(const char *format, va_list ap)
+{
+ return vfprintf(stdout, format, ap);
+}
+
+
+int fprintf(FILE * stream, const char *format, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, format);
+ result = vfprintf(stream, format, ap);
+ va_end(ap);
+
+ return result;
+}
+
+
+int printf(const char *format, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, format);
+ result = vfprintf(stdout, format, ap);
+ va_end(ap);
+
+ return result;
+}
+
+int vsprintf(char* string, const char *format, va_list ap)
+{
+ int count = 0;
+ const char *str;
+ unsigned int uint;
+ char tmp[2];
+
+ if (format != NULL) {
+ while (*format != '\0') {
+ str = strchr(format, '%');
+ if (str == NULL) {
+ strcpy(&string[count], format);
+ count += strlen(format);
+ break;
+ } else {
+ if (format < str) {
+ ULONG len = str - format;
+
+ strncpy(&string[count],
+ (char *) format, len);
+ count += len;
+ }
+
+ format = str + 1;
+ if(*format == 'l')
+ format = str + 2;
+
+ switch (*format) {
+ case 'u':
+ uint = va_arg(ap, unsigned int);
+ str = numtostr(uint, 10);
+ strcpy(&string[count], str);
+ count += strlen(str);
+ break;
+
+ case 'p':
+ case 'x':
+ uint = va_arg(ap, unsigned int);
+ str = numtostr(uint, 16);
+ strcpy(&string[count], str);
+ count += strlen(str);
+ break;
+
+ case 's':
+ str = va_arg(ap, const char *);
+ if( !str )
+ str = "(NULL)";
+ strcpy(&string[count], str);
+ count += strlen(str);
+ break;
+
+ case 'c':
+ tmp[0] = (char)va_arg(ap, int);
+ tmp[1] = '\0';
+ strcpy(&string[count], tmp);
+ count++;
+ break;
+
+ case '%':
+ strcpy(&string[count], "%");
+ count++;
+ break;
+
+ case '\0': /* format error */
+ default:
+ return EOF;
+ }
+
+ format += 1;
+ }
+ }
+ }
+ string[count]='\0';
+ return count;
+}
+
+
+int sprintf(char* str, const char *format, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, format);
+ result = vsprintf(str, format, ap);
+ va_end(ap);
+
+ return result;
+}
diff --git a/common/stdio.h b/common/stdio.h
new file mode 100644
index 0000000..9ee52d3
--- /dev/null
+++ b/common/stdio.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef _STDIO_H_
+#define _STDIO_H_
+
+#include <stdarg.h>
+
+typedef unsigned long FILE;
+
+#define EOF (-1)
+
+extern FILE *stdin;
+extern FILE *stdout;
+
+extern int fputs(const char *s, FILE * stream);
+extern int puts(const char *s);
+
+extern int fgetc(FILE * stream);
+#define getc(stream) fgetc(stream)
+#define getchar() getc(stdin)
+
+extern int printf(const char *format, ...);
+extern int fprintf(FILE * stream, const char *format, ...);
+extern int sprintf(char* string, const char* format, ...);
+extern int vprintf(const char *format, va_list ap);
+extern int vfprintf(FILE * stream, const char *format, va_list ap);
+extern int vsprtinf(char* string, const char* format, va_list ap);
+
+#endif /* _STDIO_H_ */
diff --git a/common/stdlib.c b/common/stdlib.c
new file mode 100644
index 0000000..1d3355a
--- /dev/null
+++ b/common/stdlib.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#include "stdlib.h"
+#include "string.h"
+
+
+typedef struct _Node {
+ size_t size;
+ struct _Node *next;
+} Node;
+
+static Node *freeList = NULL;
+
+void *malloc(size_t size)
+{
+ Node **free, *mem;
+
+ size +=
+ /* header */ sizeof(Node) + /* round up */ (sizeof(Node) - 1);
+ size -= size % sizeof(Node);
+
+ free = &freeList;
+ while ((*free != NULL) && ((*free)->size < size))
+ free = &((*free)->next);
+
+ mem = *free;
+ if (mem != NULL) {
+ if (mem->size > size) {
+ Node *split = mem + (size / sizeof(Node));
+
+ split->size = mem->size - size;
+ split->next = mem->next;
+ mem->size = size;
+ mem->next = split;
+ }
+ *free = mem->next;
+ mem += 1;
+ }
+
+ return ((void *) mem);
+}
+
+
+void free(void *ptr)
+{
+ if (ptr != NULL) {
+ Node *mem = ((Node *) ptr) - 1;
+ Node **free = &freeList;
+
+ while ((*free != NULL) && (*free < mem)) {
+ if (mem ==
+ (*free + ((*free)->size / sizeof(Node)))) {
+ (*free)->size += mem->size;
+ mem = *free;
+ break;
+ }
+ free = &((*free)->next);
+ }
+
+ if (mem != *free) {
+ mem->next = *free;
+ *free = mem;
+ }
+
+ if (mem->next == (mem + (mem->size / sizeof(Node)))) {
+ mem->size += mem->next->size;
+ mem->next = mem->next->next;
+ }
+ }
+}
+
+
+void *realloc(void *ptr, size_t size)
+{
+ if (ptr == NULL) {
+ ptr = malloc(size);
+ } else {
+ Node *mem = ((Node *) ptr) - 1;
+
+ size +=
+ /* header */ sizeof(Node) +
+ /* round up */ (sizeof(Node) - 1);
+ size -= size % sizeof(Node);
+
+ if (size > mem->size) {
+ /* Should try to grow */
+ void *optr = ptr;
+
+ ptr = malloc(size);
+ if (ptr != NULL) {
+ memcpy(ptr, optr,
+ mem->size - sizeof(Node));
+ free(optr);
+ }
+ } else if (size < mem->size) {
+ Node *split = mem + (size / sizeof(Node));
+
+ split->size = mem->size - size;
+ split->next = mem->next;
+ mem->size = size;
+ free((void *) (split + 1));
+ }
+ }
+
+ return ptr;
+}
+
+
+void arclib_malloc_add(unsigned long start, unsigned long size)
+{
+ Node *node = (Node *) start;
+
+ node->size = size - (size % sizeof(Node));
+ free((void *) (node + 1));
+}
diff --git a/common/stdlib.h b/common/stdlib.h
new file mode 100644
index 0000000..8bd1e8b
--- /dev/null
+++ b/common/stdlib.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef _STDLIB_H_
+#define _STDLIB_H_
+
+#include "stddef.h"
+
+extern void *malloc(size_t size);
+extern void free(void *ptr);
+extern void *realloc(void *ptr, size_t size);
+
+extern void arclib_malloc_add(unsigned long start, unsigned long size);
+
+#endif /* _STDLIB_H_ */
diff --git a/common/string.c b/common/string.c
new file mode 100644
index 0000000..1c424c0
--- /dev/null
+++ b/common/string.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright 1999, 2001 Silicon Graphics, Inc.
+ * Copyright 2001 Ralf Baechle
+ * 2001 Guido Guenther <agx@sgixcpu.org>
+ * 2008 Florian Lohoff <flo@rfc822.org>
+ */
+#include "string.h"
+#include "stdlib.h"
+
+char *strcat(char *d, char *s) {
+ char *a;
+
+ for(a=d;*a;a++);
+ for(;*s;*a++=*s++);
+ *a=0x0;
+
+ return d;
+}
+
+size_t strlen(const char *s)
+{
+ size_t len = 0;
+
+ while (*(s++) != '\0')
+ len += 1;
+
+ return len;
+}
+
+
+int strncmp(const char *s1, const char *s2, size_t n)
+{
+ while (n-- > 0) {
+ if (*s1 < *s2)
+ return -1;
+ else if (*s1 > *s2)
+ return 1;
+ else if (*s1 == '\0')
+ return 0;
+ s1 += 1;
+ s2 += 1;
+ }
+
+ return 0;
+}
+
+/* from lib/string.c in the kernel sources */
+int strcmp(const char * cs,const char * ct)
+{
+ register signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+
+ return __res;
+}
+
+char *strchr(const char *s, int c)
+{
+ while ((*s != (char) c) && (*s != '\0'))
+ s += 1;
+ return (char *) ((*s == '\0') ? NULL : s);
+}
+
+
+char *strcpy(char *s1, const char *s2)
+{
+ char *s = s1;
+
+ do {
+ *(s1++) = *(s2);
+ } while(*s2++ != 0x0);
+
+ return s;
+}
+
+
+char *strncpy(char *s1, const char *s2, size_t n)
+{
+ char *s = s1;
+
+ while (n-- > 0) {
+ if ((*(s1++) = *(s2++)) == '\0')
+ break;
+ }
+
+ return s;
+}
+
+
+char *strdup(const char *s1)
+{
+ char *str = malloc(strlen(s1) + 1);
+
+ if (str != NULL)
+ strcpy(str, s1);
+ return str;
+}
+
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+ const unsigned char *su1, *su2;
+ signed char res = 0;
+
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+
+void *memcpy(void *s1, const void *s2, size_t n)
+{
+ char *c1 = (char *) s1;
+ const char *c2 = (const char *) s2;
+
+ while (n-- > 0)
+ *(c1++) = *(c2++);
+ return s1;
+}
+
+void *memmove(void *s1, const void *s2, size_t n)
+{
+ char *c1 = (char *) s1;
+ const char *c2 = (const char *) s2;
+
+ if (s1 < s2)
+ return memcpy(s1, s2, n);
+
+ c1+=n;
+ c2+=n;
+
+ while (n-- > 0)
+ *(--c1) = *(--c2);
+ return s1;
+}
+
+void *memset(void *s, int c, size_t n)
+{
+ char *mem = (char *) s;
+
+ while (n-- > 0)
+ *(mem++) = (char) c;
+ return s;
+}
+
+void __bzero(char *p, int len)
+{
+ memset(p, 0, len);
+}
diff --git a/common/string.h b/common/string.h
new file mode 100644
index 0000000..04cf123
--- /dev/null
+++ b/common/string.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ * 2001 Guido Guenther <agx@sigxcpu.org>
+ * 2008 Florian Lohoff <flo@rfc822.org>
+ */
+#ifndef _STRING_H_
+#define _STRING_H_
+
+#include "stddef.h"
+
+extern size_t strlen(const char *s);
+extern int strcmp(const char *s1,const char *s2);
+extern char *strcat(char *d, char *s);
+extern int strncmp(const char *s1, const char *s2, size_t n);
+extern char *strchr(const char *s, int c);
+extern char *strcpy(char *s1, const char *s2);
+extern char *strncpy(char *s1, const char *s2, size_t n);
+extern char *strdup(const char *s1);
+
+extern void *memcpy(void *s1, const void *s2, size_t n);
+extern void *memmove(void *s1, const void *s2, size_t n);
+extern void *memset(void *s, int c, size_t n);
+int memcmp(const void * cs,const void * ct,size_t count);
+extern void __bzero(char *p, int len);
+
+#endif /* _STRING_H_ */