From 3c8b9481088b546af3f0fd161a432ba0f0cb682e Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Sun, 26 Apr 2009 14:57:08 +0200 Subject: Move libc functions into a pseudo libc away from libarc --- common/Makefile | 13 ++- common/stddef.h | 11 +++ common/stdio.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/stdio.h | 30 ++++++ common/stdlib.c | 116 +++++++++++++++++++++++ common/stdlib.h | 15 +++ common/string.c | 151 ++++++++++++++++++++++++++++++ common/string.h | 26 ++++++ 8 files changed, 640 insertions(+), 3 deletions(-) create mode 100644 common/stddef.h create mode 100644 common/stdio.c create mode 100644 common/stdio.h create mode 100644 common/stdlib.c create mode 100644 common/stdlib.h create mode 100644 common/string.c create mode 100644 common/string.h (limited to 'common') 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 +#include + +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 + +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 + * 2008 Florian Lohoff + */ +#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 + * 2008 Florian Lohoff + */ +#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_ */ -- cgit v1.2.3