diff options
Diffstat (limited to 'roms/skiboot/libc')
72 files changed, 3281 insertions, 0 deletions
diff --git a/roms/skiboot/libc/Makefile.inc b/roms/skiboot/libc/Makefile.inc new file mode 100644 index 000000000..13f8034f4 --- /dev/null +++ b/roms/skiboot/libc/Makefile.inc @@ -0,0 +1,11 @@ +LIBCDIR = libc + +SUBDIRS += $(LIBCDIR) +LIBC = $(LIBCDIR)/built-in.a $(LIBCDIR)/time.o + +include $(SRC)/$(LIBCDIR)/string/Makefile.inc +include $(SRC)/$(LIBCDIR)/ctype/Makefile.inc +include $(SRC)/$(LIBCDIR)/stdlib/Makefile.inc +include $(SRC)/$(LIBCDIR)/stdio/Makefile.inc + +$(LIBC): $(STRING) $(CTYPE) $(STDLIB) $(STDIO) diff --git a/roms/skiboot/libc/README.txt b/roms/skiboot/libc/README.txt new file mode 100644 index 000000000..d6c3eb2c1 --- /dev/null +++ b/roms/skiboot/libc/README.txt @@ -0,0 +1,62 @@ + +skiboot changes: + + - Added malloc lock + - Added a few functions + - Malloc will always 4 byte align everything + - Added asserts, requires core to provide abort() + +WARNINGS: + + - don't use free() on the result of memalign() (should be fixable) + +Previous notes: + + Standard C library for the SLOF firmware project + ================================================ + +To use this library, link your target against the "libc.a" archive. + +However, there are some prerequisites before you can use certain parts of the +library: + +1) If you want to use malloc() and the like, you have to supply an implemen- + tation of sbrk() in your own code. malloc() uses sbrk() to get new, free + memory regions. + + Prototype: void *sbrk(int incr); + Description: sbrk() increments the available data space by incr bytes and + returns a pointer to the start of the new area. + + See the man-page of sbrk for details about this function. + +2) Before you can use the stdio output functions like printf(), puts() and the + like, you have to provide a standard write() function in your code. + printf() and the like use write() to print out the strings to the standard + output. + + Prototype: ssize_t write(int fd, const void *buf, size_t cnt); + Description: Write cnt byte from the buffer buf to the stream associated + with the file descriptor fd. + + The stdio functions will print their output to the stdout channel which is + assigned with the file descriptor 1 by default. Note that the stdio + functions will not use open() before calling write(), so if the stdout + cannel needs to be opened first, you should do that in your start-up code + before using the libc functions for the first time. + +3) Before you can use the stdio input functions like scanf() and the + like, you have to provide a standard read() function in your code. + scanf() and the like use read() to get the characters from the standard + input. + + Prototype: ssize_t read(int fd, void *buf, size_t cnt); + Description: Read cnt byte from the stream associated with the file + descriptor fd and put them into the buffer buf. + + The stdio functions will get their input from the stdin channel which is + assigned with the file descriptor 0 by default. Note that the stdio + functions will not use open() before calling read(), so if the stdin + cannel needs to be opened first, you should do that in your start-up code + before using the libc functions for the first time. + diff --git a/roms/skiboot/libc/ctype/Makefile.inc b/roms/skiboot/libc/ctype/Makefile.inc new file mode 100644 index 000000000..c183a54b8 --- /dev/null +++ b/roms/skiboot/libc/ctype/Makefile.inc @@ -0,0 +1,19 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +SUBDIRS += $(LIBCDIR)/ctype + +CTYPE_OBJS = isdigit.o isprint.o isspace.o isxdigit.o tolower.o toupper.o + +CTYPE = $(LIBCDIR)/ctype/built-in.a +$(CTYPE): $(CTYPE_OBJS:%=$(LIBCDIR)/ctype/%) + diff --git a/roms/skiboot/libc/ctype/isdigit.c b/roms/skiboot/libc/ctype/isdigit.c new file mode 100644 index 000000000..68cd4eb79 --- /dev/null +++ b/roms/skiboot/libc/ctype/isdigit.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <compiler.h> +#include <ctype.h> + +int __attrconst isdigit(int ch) +{ + switch (ch) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return 1; + + default: + return 0; + } +} diff --git a/roms/skiboot/libc/ctype/isprint.c b/roms/skiboot/libc/ctype/isprint.c new file mode 100644 index 000000000..0a7c94ce8 --- /dev/null +++ b/roms/skiboot/libc/ctype/isprint.c @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <compiler.h> +#include <ctype.h> + +int __attrconst isprint(int ch) +{ + return (ch >= 32 && ch < 127); +} diff --git a/roms/skiboot/libc/ctype/isspace.c b/roms/skiboot/libc/ctype/isspace.c new file mode 100644 index 000000000..f9fa36a3a --- /dev/null +++ b/roms/skiboot/libc/ctype/isspace.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <compiler.h> +#include <ctype.h> + +int __attrconst isspace(int ch) +{ + switch (ch) { + case ' ': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + return 1; + + default: + return 0; + } +} diff --git a/roms/skiboot/libc/ctype/isxdigit.c b/roms/skiboot/libc/ctype/isxdigit.c new file mode 100644 index 000000000..d3c73888e --- /dev/null +++ b/roms/skiboot/libc/ctype/isxdigit.c @@ -0,0 +1,22 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <compiler.h> +#include <ctype.h> + +int __attrconst isxdigit(int ch) +{ + return ( + (ch >= '0' && ch <= '9') | + (ch >= 'A' && ch <= 'F') | + (ch >= 'a' && ch <= 'f') ); +} diff --git a/roms/skiboot/libc/ctype/tolower.c b/roms/skiboot/libc/ctype/tolower.c new file mode 100644 index 000000000..398a1eb29 --- /dev/null +++ b/roms/skiboot/libc/ctype/tolower.c @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <compiler.h> +#include <ctype.h> + +int __attrconst tolower(int c) +{ + return (((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a' ) : c); +} diff --git a/roms/skiboot/libc/ctype/toupper.c b/roms/skiboot/libc/ctype/toupper.c new file mode 100644 index 000000000..6b52363d1 --- /dev/null +++ b/roms/skiboot/libc/ctype/toupper.c @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <compiler.h> +#include "ctype.h" + +int __attrconst toupper (int cha) +{ + if((cha >= 'a') && (cha <= 'z')) + return(cha - 'a' + 'A'); + return(cha); +} diff --git a/roms/skiboot/libc/include/assert.h b/roms/skiboot/libc/include/assert.h new file mode 100644 index 000000000..1e511fbe5 --- /dev/null +++ b/roms/skiboot/libc/include/assert.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008, 2012 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _ASSERT_H +#define _ASSERT_H + +struct trap_table_entry { + unsigned long address; + const char *message; +}; + +extern struct trap_table_entry __trap_table_start[]; +extern struct trap_table_entry __trap_table_end[]; + +#define stringify(expr) stringify_1(expr) +/* Double-indirection required to stringify expansions */ +#define stringify_1(expr) #expr + +void __attribute__((noreturn)) assert_fail(const char *msg, + const char *file, + unsigned int line, + const char *function); + +/* + * The 'nop' gets patched to 'trap' after skiboot takes over the exception + * vectors, then patched to 'nop' before booting the OS (see patch_traps). + * This makes assert fall through to assert_fail when we can't use the 0x700 + * interrupt. + */ +#define assert(cond) \ +do { \ + /* evaluate cond exactly once */ \ + const unsigned long __cond = (unsigned long)(cond); \ + asm volatile( \ + " cmpdi %0,0" "\n\t" \ + " bne 2f" "\n\t" \ + "1: nop # assert" "\n\t" \ + "2:" "\n\t" \ + ".section .rodata" "\n\t" \ + "3: .string \"assert failed at " __FILE__ ":" stringify(__LINE__) "\"" "\n\t" \ + ".previous" "\n\t" \ + ".section .trap_table,\"aw\"" "\n\t" \ + ".llong 1b" "\n\t" \ + ".llong 3b" "\n\t" \ + ".previous" "\n\t" \ + : : "r"(__cond) : "cr0"); \ + if (!__cond) \ + assert_fail(stringify(cond), __FILE__, __LINE__, __FUNCTION__); \ +} while (0) + +#endif diff --git a/roms/skiboot/libc/include/ctype.h b/roms/skiboot/libc/include/ctype.h new file mode 100644 index 000000000..60c98b059 --- /dev/null +++ b/roms/skiboot/libc/include/ctype.h @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _CTYPE_H +#define _CTYPE_H + +#include <compiler.h> + +int __attrconst isdigit(int c); +int __attrconst isxdigit(int c); +int __attrconst isprint(int c); +int __attrconst isspace(int c); + +int __attrconst tolower(int c); +int __attrconst toupper(int c); + +#endif diff --git a/roms/skiboot/libc/include/errno.h b/roms/skiboot/libc/include/errno.h new file mode 100644 index 000000000..c2bd98774 --- /dev/null +++ b/roms/skiboot/libc/include/errno.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _ERRNO_H +#define _ERRNO_H + +extern int errno; + +/* + * Error number definitions + */ +#define EPERM 1 /* not permitted */ +#define ENOENT 2 /* file or directory not found */ +#define EIO 5 /* input/output error */ +#define EBADF 9 /* Bad file number */ +#define ENOMEM 12 /* not enough space */ +#define EACCES 13 /* permission denied */ +#define EFAULT 14 /* bad address */ +#define EBUSY 16 /* resource busy */ +#define EEXIST 17 /* file already exists */ +#define ENODEV 19 /* device not found */ +#define EINVAL 22 /* invalid argument */ +#define EDOM 33 /* math argument out of domain of func */ +#define ERANGE 34 /* math result not representable */ +#define ENOSYS 38 /* Function not implemented */ + +#endif diff --git a/roms/skiboot/libc/include/getopt.h b/roms/skiboot/libc/include/getopt.h new file mode 100644 index 000000000..5956986a5 --- /dev/null +++ b/roms/skiboot/libc/include/getopt.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef GETOPT_H +#define GETOPT_H + +extern char *optarg; +extern int optind; +extern int opterr; +extern int optopt; + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +enum { + no_argument = 0, + required_argument, + optional_argument +}; + +int getopt(int argc, char **, const char *); +int getopt_long(int argc, char **, const char *, const struct option *, int *); + +#endif /* GETOPT_H */ diff --git a/roms/skiboot/libc/include/limits.h b/roms/skiboot/libc/include/limits.h new file mode 100644 index 000000000..bd67c7ecc --- /dev/null +++ b/roms/skiboot/libc/include/limits.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _LIMITS_H +#define _LIMITS_H + +#define UCHAR_MAX 255 +#define SCHAR_MAX 127 +#define SCHAR_MIN (-128) + +#define USHRT_MAX 65535 +#define SHRT_MAX 32767 +#define SHRT_MIN (-32768) + +#define UINT_MAX (4294967295U) +#define INT_MAX 2147483647 +#define INT_MIN (-2147483648) + +#define ULONG_MAX ((unsigned long)-1L) +#define LONG_MAX (ULONG_MAX/2) +#define LONG_MIN ((-LONG_MAX)-1) + +#define CHAR_BIT 8 + +#define UINT32_MAX UINT_MAX + +#endif diff --git a/roms/skiboot/libc/include/stdint.h b/roms/skiboot/libc/include/stdint.h new file mode 100644 index 000000000..2a2c1d916 --- /dev/null +++ b/roms/skiboot/libc/include/stdint.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDINT_H +#define _STDINT_H + +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +typedef unsigned long int uintptr_t; + +#endif diff --git a/roms/skiboot/libc/include/stdio.h b/roms/skiboot/libc/include/stdio.h new file mode 100644 index 000000000..5dc4502b0 --- /dev/null +++ b/roms/skiboot/libc/include/stdio.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDIO_H +#define _STDIO_H + +#include <stdarg.h> +#include "stddef.h" + +#define EOF (-1) + +#define _IONBF 0 +#define _IOLBF 1 +#define _IOFBF 2 +#define BUFSIZ 80 + +typedef struct { + int fd; + int mode; + int pos; + char *buf; + int bufsiz; +} FILE; + +extern FILE stdin_data; +extern FILE stdout_data; +extern FILE stderr_data; + +#define stdin (&stdin_data) +#define stdout (&stdout_data) +#define stderr (&stderr_data) + +int fileno(FILE *stream); + +int _printf(const char *format, ...) __attribute__((format (printf, 1, 2))); + +#ifndef pr_fmt +#define pr_fmt(fmt) fmt +#endif + +#define printf(f, ...) do { _printf(pr_fmt(f), ##__VA_ARGS__); } while(0) + +int fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3))); +int snprintf(char *str, size_t size, const char *format, ...) __attribute__((format (printf, 3, 4))); +int vfprintf(FILE *stream, const char *format, va_list); +int vsnprintf(char *str, size_t size, const char *format, va_list); +void setbuf(FILE *stream, char *buf); +int setvbuf(FILE *stream, char *buf, int mode , size_t size); + +int fputc(int ch, FILE *stream); +#define putc(ch, stream) fputc(ch, stream) +int putchar(int ch); +int puts(const char *str); +int fputs(const char *str, FILE *stream); + +int scanf(const char *format, ...) __attribute__((format (scanf, 1, 2))); +int fscanf(FILE *stream, const char *format, ...) __attribute__((format (scanf, 2, 3))); +int vfscanf(FILE *stream, const char *format, va_list); +int vsscanf(const char *str, const char *format, va_list); +int getc(FILE *stream); +int getchar(void); + +#endif diff --git a/roms/skiboot/libc/include/stdlib.h b/roms/skiboot/libc/include/stdlib.h new file mode 100644 index 000000000..43d5c24dd --- /dev/null +++ b/roms/skiboot/libc/include/stdlib.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDLIB_H +#define _STDLIB_H + +#include "stddef.h" + +#define RAND_MAX 32767 + +#include "mem_region-malloc.h" + +int atoi(const char *str); +long atol(const char *str); +unsigned long int strtoul(const char *nptr, char **endptr, int base); +long int strtol(const char *nptr, char **endptr, int base); + +int rand(void); +long int __attribute__((const)) labs(long int n); +#define abort() assert(0) + +#endif diff --git a/roms/skiboot/libc/include/string.h b/roms/skiboot/libc/include/string.h new file mode 100644 index 000000000..f3d6117fb --- /dev/null +++ b/roms/skiboot/libc/include/string.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * Copyright (c) 2004, 2016 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STRING_H +#define _STRING_H + +#include "stddef.h" + +#define strcpy __builtin_strcpy +#define strncpy __builtin_strncpy +#define strcat __builtin_strcat +#define strcmp __builtin_strcmp +#define strncmp __builtin_strncmp +#define strcasecmp __builtin_strcasecmp +#define strncasecmp __builtin_strncasecmp +#define strchr __builtin_strchr +#define strrchr __builtin_strrchr +#define strlen __builtin_strlen +#define strlen __builtin_strlen +size_t strnlen(const char *s, size_t maxlen); +#define strstr __builtin_strstr +#define strdup __builtin_strdup +char *strtok(char *src, const char *pattern); + +#define memset __builtin_memset +#define memchr __builtin_memchr +#define memcpy __builtin_memcpy +#define memmove __builtin_memmove +#define memcmp __builtin_memcmp +static inline void *memcpy_null(void *dest, const void *src, size_t n) +{ + asm("" : "+r"(dest)); + asm("" : "+r"(src)); + return memcpy(dest, src, n); +} +void *memcpy_from_ci(void *destpp, const void *srcpp, size_t len); + +static inline int ffs(unsigned long val) +{ + return __builtin_ffs(val); +} + +#endif diff --git a/roms/skiboot/libc/include/time.h b/roms/skiboot/libc/include/time.h new file mode 100644 index 000000000..8d34fdbab --- /dev/null +++ b/roms/skiboot/libc/include/time.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#ifndef _TIME_H +#define _TIME_H + +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; +}; + +typedef long time_t; + +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; + +struct tm *gmtime_r(const time_t *timep, struct tm *result); +time_t mktime(struct tm *tm); + +/* Not implemented by libc but by hosting environment, however + * this is where the prototype is expected + */ +int nanosleep(const struct timespec *req, struct timespec *rem); + +#endif /* _TIME_H */ diff --git a/roms/skiboot/libc/include/unistd.h b/roms/skiboot/libc/include/unistd.h new file mode 100644 index 000000000..bc53472dc --- /dev/null +++ b/roms/skiboot/libc/include/unistd.h @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include <stddef.h> + +typedef long ssize_t; + +extern int open(const char *name, int flags); +extern int close(int fd); +extern ssize_t read(int fd, void *buf, size_t count); +extern ssize_t write(int fd, const void *buf, size_t count); +extern ssize_t lseek(int fd, long offset, int whence); + +#endif diff --git a/roms/skiboot/libc/stdio/Makefile.inc b/roms/skiboot/libc/stdio/Makefile.inc new file mode 100644 index 000000000..a5436d734 --- /dev/null +++ b/roms/skiboot/libc/stdio/Makefile.inc @@ -0,0 +1,21 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + + +SUBDIRS += $(LIBCDIR)/stdio + +STDIO_OBJS = vfprintf.o vsnprintf.o fprintf.o \ + setvbuf.o fputc.o puts.o fputs.o putchar.o \ + stdchnls.o fileno.o snprintf.o + +STDIO = $(LIBCDIR)/stdio/built-in.a +$(STDIO): $(STDIO_OBJS:%=$(LIBCDIR)/stdio/%) diff --git a/roms/skiboot/libc/stdio/fileno.c b/roms/skiboot/libc/stdio/fileno.c new file mode 100644 index 000000000..6e239511d --- /dev/null +++ b/roms/skiboot/libc/stdio/fileno.c @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdio.h> + +int +fileno(FILE *stream) +{ + return stream->fd; +} diff --git a/roms/skiboot/libc/stdio/fprintf.c b/roms/skiboot/libc/stdio/fprintf.c new file mode 100644 index 000000000..866df3934 --- /dev/null +++ b/roms/skiboot/libc/stdio/fprintf.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" + + +int fprintf(FILE *stream, const char* fmt, ...) +{ + int count; + va_list ap; + + va_start(ap, fmt); + count = vfprintf(stream, fmt, ap); + va_end(ap); + + return count; +} diff --git a/roms/skiboot/libc/stdio/fputc.c b/roms/skiboot/libc/stdio/fputc.c new file mode 100644 index 000000000..6e9e7c9c0 --- /dev/null +++ b/roms/skiboot/libc/stdio/fputc.c @@ -0,0 +1,24 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" +#include "unistd.h" + +int fputc(int ch, FILE *stream) +{ + unsigned char outchar = ch; + + if (write(stream->fd, &outchar, 1) == 1) + return outchar; + else + return EOF; +} diff --git a/roms/skiboot/libc/stdio/fputs.c b/roms/skiboot/libc/stdio/fputs.c new file mode 100644 index 000000000..c22329c9c --- /dev/null +++ b/roms/skiboot/libc/stdio/fputs.c @@ -0,0 +1,23 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdio.h" +#include "string.h" +#include "unistd.h" + + +int fputs(const char *str, FILE *stream) +{ + return write(stream->fd, str, strlen(str)); +} + diff --git a/roms/skiboot/libc/stdio/putchar.c b/roms/skiboot/libc/stdio/putchar.c new file mode 100644 index 000000000..5c750d90a --- /dev/null +++ b/roms/skiboot/libc/stdio/putchar.c @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdio.h" + + +int +putchar(int ch) +{ + return putc(ch, stdout); +} diff --git a/roms/skiboot/libc/stdio/puts.c b/roms/skiboot/libc/stdio/puts.c new file mode 100644 index 000000000..85d9d3109 --- /dev/null +++ b/roms/skiboot/libc/stdio/puts.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdio.h" +#include "string.h" +#include "unistd.h" + + +int puts(const char *str) +{ + int ret; + + ret = write(stdout->fd, str, strlen(str)); + write(stdout->fd, "\n", 1); + + return ret + 1; +} diff --git a/roms/skiboot/libc/stdio/setvbuf.c b/roms/skiboot/libc/stdio/setvbuf.c new file mode 100644 index 000000000..9b62dd8ff --- /dev/null +++ b/roms/skiboot/libc/stdio/setvbuf.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdio.h> + +int setvbuf(FILE *stream, char *buf, int mode , size_t size) +{ + if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF) + return -1; + stream->buf = buf; + stream->mode = mode; + stream->bufsiz = size; + return 0; +} + +void setbuf(FILE *stream, char *buf) +{ + setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ); +} diff --git a/roms/skiboot/libc/stdio/snprintf.c b/roms/skiboot/libc/stdio/snprintf.c new file mode 100644 index 000000000..35b6f86ca --- /dev/null +++ b/roms/skiboot/libc/stdio/snprintf.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdio.h> + + +int snprintf(char *buff, size_t size, const char *format, ...) +{ + va_list ar; + int count; + + if (buff==NULL) + return(-1); + + va_start(ar, format); + count = vsnprintf(buff, size, format, ar); + va_end(ar); + + return(count); +} + diff --git a/roms/skiboot/libc/stdio/stdchnls.c b/roms/skiboot/libc/stdio/stdchnls.c new file mode 100644 index 000000000..41ed958bf --- /dev/null +++ b/roms/skiboot/libc/stdio/stdchnls.c @@ -0,0 +1,23 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdio.h" + +static char stdin_buffer[BUFSIZ], stdout_buffer[BUFSIZ]; + +FILE stdin_data = { .fd = 0, .mode = _IOLBF, .pos = 0, + .buf = stdin_buffer, .bufsiz = BUFSIZ }; +FILE stdout_data = { .fd = 1, .mode = _IOLBF, .pos = 0, + .buf = stdout_buffer, .bufsiz = BUFSIZ }; +FILE stderr_data = { .fd = 2, .mode = _IONBF, .pos = 0, + .buf = NULL, .bufsiz = 0 }; diff --git a/roms/skiboot/libc/stdio/vfprintf.c b/roms/skiboot/libc/stdio/vfprintf.c new file mode 100644 index 000000000..765feeace --- /dev/null +++ b/roms/skiboot/libc/stdio/vfprintf.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" +#include "unistd.h" + + +int vfprintf(FILE *stream, const char *fmt, va_list ap) +{ + int count; + char buffer[320]; + + count = vsnprintf(buffer, sizeof(buffer), fmt, ap); + write(stream->fd, buffer, count); + + return count; +} + diff --git a/roms/skiboot/libc/stdio/vsnprintf.c b/roms/skiboot/libc/stdio/vsnprintf.c new file mode 100644 index 000000000..410a806cb --- /dev/null +++ b/roms/skiboot/libc/stdio/vsnprintf.c @@ -0,0 +1,300 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdbool.h> +#include <compiler.h> +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "ctype.h" + +static const unsigned long long convert[] = { + 0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL +}; + +static int +print_str_fill(char **buffer, size_t bufsize, char *sizec, + const char *str, char c) +{ + size_t i, sizei, len; + char *bstart = *buffer; + + sizei = strtoul(sizec, NULL, 10); + len = strlen(str); + if (sizei > len) { + for (i = 0; + (i < (sizei - len)) && ((*buffer - bstart) < bufsize); + i++) { + **buffer = c; + *buffer += 1; + } + } + return 1; +} + +static int +print_str(char **buffer, size_t bufsize, const char *str) +{ + char *bstart = *buffer; + size_t i; + + for (i = 0; (i < strlen(str)) && ((*buffer - bstart) < bufsize); i++) { + **buffer = str[i]; + *buffer += 1; + } + return 1; +} + +static unsigned int __attrconst +print_intlen(unsigned long value, unsigned short int base) +{ + int i = 0; + + while (value > 0) { + value /= base; + i++; + } + if (i == 0) + i = 1; + return i; +} + +static int +print_itoa(char **buffer, size_t bufsize, unsigned long value, + unsigned short base, bool upper) +{ + const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + char c; + int i, len; + + if(base <= 2 || base > 16) + return 0; + + len = i = print_intlen(value, base); + + /* Don't print to buffer if bufsize is not enough. */ + if (len > bufsize) + return 0; + + do { + c = zeichen[value % base]; + if (upper) + c = toupper(c); + + (*buffer)[--i] = c; + value /= base; + } while(value); + + *buffer += len; + + return 1; +} + + + +static int +print_fill(char **buffer, size_t bufsize, char *sizec, unsigned long size, + unsigned short int base, char c, int optlen) +{ + int i, sizei, len; + char *bstart = *buffer; + + sizei = strtoul(sizec, NULL, 10); + len = print_intlen(size, base) + optlen; + if (sizei > len) { + for (i = 0; + (i < (sizei - len)) && ((*buffer - bstart) < bufsize); + i++) { + **buffer = c; + *buffer += 1; + } + } + + return 0; +} + + +static int +print_format(char **buffer, size_t bufsize, const char *format, void *var) +{ + char *start; + unsigned int i = 0, length_mod = sizeof(int); + unsigned long value = 0; + unsigned long signBit; + char *form, sizec[32]; + char sign = ' '; + bool upper = false; + + form = (char *) format; + start = *buffer; + + form++; + if(*form == '0' || *form == '.') { + sign = '0'; + form++; + } + + while ((*form != '\0') && ((*buffer - start) < bufsize)) { + switch(*form) { + case 'u': + case 'd': + case 'i': + sizec[i] = '\0'; + value = (unsigned long) var; + signBit = 0x1ULL << (length_mod * 8 - 1); + if ((*form != 'u') && (signBit & value)) { + **buffer = '-'; + *buffer += 1; + value = (-(unsigned long)value) & convert[length_mod]; + } + print_fill(buffer, bufsize - (*buffer - start), + sizec, value, 10, sign, 0); + print_itoa(buffer, bufsize - (*buffer - start), + value, 10, upper); + break; + case 'X': + upper = true; + /* fallthrough */ + case 'x': + sizec[i] = '\0'; + value = (unsigned long) var & convert[length_mod]; + print_fill(buffer, bufsize - (*buffer - start), + sizec, value, 16, sign, 0); + print_itoa(buffer, bufsize - (*buffer - start), + value, 16, upper); + break; + case 'O': + case 'o': + sizec[i] = '\0'; + value = (long int) var & convert[length_mod]; + print_fill(buffer, bufsize - (*buffer - start), + sizec, value, 8, sign, 0); + print_itoa(buffer, bufsize - (*buffer - start), + value, 8, upper); + break; + case 'p': + sizec[i] = '\0'; + print_fill(buffer, bufsize - (*buffer - start), + sizec, (unsigned long) var, 16, ' ', 2); + print_str(buffer, bufsize - (*buffer - start), + "0x"); + print_itoa(buffer, bufsize - (*buffer - start), + (unsigned long) var, 16, upper); + break; + case 'c': + sizec[i] = '\0'; + print_fill(buffer, bufsize - (*buffer - start), + sizec, 1, 10, ' ', 0); + **buffer = (unsigned long) var; + *buffer += 1; + break; + case 's': + sizec[i] = '\0'; + print_str_fill(buffer, + bufsize - (*buffer - start), sizec, + (char *) var, ' '); + + print_str(buffer, bufsize - (*buffer - start), + (char *) var); + break; + case 'l': + form++; + if(*form == 'l') { + length_mod = sizeof(long long int); + } else { + form--; + length_mod = sizeof(long int); + } + break; + case 'h': + form++; + if(*form == 'h') { + length_mod = sizeof(signed char); + } else { + form--; + length_mod = sizeof(short int); + } + break; + case 'z': + length_mod = sizeof(size_t); + break; + default: + if(*form >= '0' && *form <= '9') + sizec[i++] = *form; + } + form++; + } + + + return (long int) (*buffer - start); +} + + +/* + * The vsnprintf function prints a formatted strings into a buffer. + * BUG: buffer size checking does not fully work yet + */ +int +vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg) +{ + char *ptr, *bstart; + + bstart = buffer; + ptr = (char *) format; + + /* + * Return from here if size passed is zero, otherwise we would + * overrun buffer while setting NULL character at the end. + */ + if (!buffer || !bufsize) + return 0; + + /* Leave one space for NULL character */ + bufsize--; + + while(*ptr != '\0' && (buffer - bstart) < bufsize) + { + if(*ptr == '%') { + char formstr[20]; + int i=0; + + do { + formstr[i] = *ptr; + ptr++; + i++; + } while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X' + || *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%' + || *ptr == 'O' || *ptr == 'o' )); + formstr[i++] = *ptr; + formstr[i] = '\0'; + if(*ptr == '%') { + *buffer++ = '%'; + } else { + print_format(&buffer, + bufsize - (buffer - bstart), + formstr, va_arg(arg, void *)); + } + ptr++; + } else { + + *buffer = *ptr; + + buffer++; + ptr++; + } + } + + *buffer = '\0'; + + return (buffer - bstart); +} diff --git a/roms/skiboot/libc/stdlib/Makefile.inc b/roms/skiboot/libc/stdlib/Makefile.inc new file mode 100644 index 000000000..8a78d173c --- /dev/null +++ b/roms/skiboot/libc/stdlib/Makefile.inc @@ -0,0 +1,20 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +SUBDIRS += $(LIBCDIR)/stdlib + +STDLIB_OBJS = error.o atoi.o atol.o strtol.o strtoul.o \ + rand.o labs.o + +STDLIB = $(LIBCDIR)/stdlib/built-in.a +$(STDLIB): $(STDLIB_OBJS:%=$(LIBCDIR)/stdlib/%) + diff --git a/roms/skiboot/libc/stdlib/atoi.c b/roms/skiboot/libc/stdlib/atoi.c new file mode 100644 index 000000000..444c05a10 --- /dev/null +++ b/roms/skiboot/libc/stdlib/atoi.c @@ -0,0 +1,18 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + +int atoi(const char *str) +{ + return strtol(str, NULL, 10); +} diff --git a/roms/skiboot/libc/stdlib/atol.c b/roms/skiboot/libc/stdlib/atol.c new file mode 100644 index 000000000..e73c7d476 --- /dev/null +++ b/roms/skiboot/libc/stdlib/atol.c @@ -0,0 +1,18 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + +long atol(const char *str) +{ + return strtol(str, NULL, 10); +} diff --git a/roms/skiboot/libc/stdlib/error.c b/roms/skiboot/libc/stdlib/error.c new file mode 100644 index 000000000..1bec91b5d --- /dev/null +++ b/roms/skiboot/libc/stdlib/error.c @@ -0,0 +1,16 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <errno.h> + +int errno; + diff --git a/roms/skiboot/libc/stdlib/labs.c b/roms/skiboot/libc/stdlib/labs.c new file mode 100644 index 000000000..8bd15eab9 --- /dev/null +++ b/roms/skiboot/libc/stdlib/labs.c @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2017 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + +/** + * labs() - Computes the absolute value of long integer + * @n: long integer number + * + * Returns the absolute value of the long integer argument + */ + +long int __attribute__((const)) labs(long int n) +{ + return (n > 0) ? n : -n; +} diff --git a/roms/skiboot/libc/stdlib/rand.c b/roms/skiboot/libc/stdlib/rand.c new file mode 100644 index 000000000..e11702aa4 --- /dev/null +++ b/roms/skiboot/libc/stdlib/rand.c @@ -0,0 +1,24 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + + +static unsigned long _rand = 1; + +int +rand(void) +{ + _rand = _rand * 25364735 + 34563; + + return ((unsigned int) (_rand >> 16) & RAND_MAX); +} diff --git a/roms/skiboot/libc/stdlib/strtol.c b/roms/skiboot/libc/stdlib/strtol.c new file mode 100644 index 000000000..c7c52af01 --- /dev/null +++ b/roms/skiboot/libc/stdlib/strtol.c @@ -0,0 +1,113 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + +long int strtol(const char *S, char **PTR,int BASE) +{ + long rval = 0; + short int negative = 0; + short int digit; + // *PTR is S, unless PTR is NULL, in which case i override it with my own ptr + char* ptr; + if (PTR == NULL) + { + //override + PTR = &ptr; + } + // i use PTR to advance through the string + *PTR = (char *) S; + //check if BASE is ok + if ((BASE < 0) || BASE > 36) + { + return 0; + } + // ignore white space at beginning of S + while ((**PTR == ' ') + || (**PTR == '\t') + || (**PTR == '\n') + || (**PTR == '\r') + ) + { + (*PTR)++; + } + // check if S starts with "-" in which case the return value is negative + if (**PTR == '-') + { + negative = 1; + (*PTR)++; + } + // if BASE is 0... determine the base from the first chars... + if (BASE == 0) + { + // if S starts with "0x", BASE = 16, else 10 + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + BASE = 16; + } + else + { + BASE = 10; + } + } + if (BASE == 16) + { + // S may start with "0x" + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + (*PTR)++; + (*PTR)++; + } + } + //until end of string + while (**PTR) + { + if (((**PTR) >= '0') && ((**PTR) <= '9')) + { + //digit (0..9) + digit = **PTR - '0'; + } + else if (((**PTR) >= 'a') && ((**PTR) <='z')) + { + //alphanumeric digit lowercase(a (10) .. z (35) ) + digit = (**PTR - 'a') + 10; + } + else if (((**PTR) >= 'A') && ((**PTR) <='Z')) + { + //alphanumeric digit uppercase(a (10) .. z (35) ) + digit = (**PTR - 'A') + 10; + } + else + { + //end of parseable number reached... + break; + } + if (digit < BASE) + { + rval = (rval * BASE) + digit; + } + else + { + //digit found, but its too big for current base + //end of parseable number reached... + break; + } + //next... + (*PTR)++; + } + if (negative) + { + return rval * -1; + } + //else + return rval; +} diff --git a/roms/skiboot/libc/stdlib/strtoul.c b/roms/skiboot/libc/stdlib/strtoul.c new file mode 100644 index 000000000..e6e63aee7 --- /dev/null +++ b/roms/skiboot/libc/stdlib/strtoul.c @@ -0,0 +1,103 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + +unsigned long int strtoul(const char *S, char **PTR,int BASE) +{ + unsigned long rval = 0; + short int digit; + // *PTR is S, unless PTR is NULL, in which case i override it with my own ptr + char* ptr; + if (PTR == NULL) + { + //override + PTR = &ptr; + } + // i use PTR to advance through the string + *PTR = (char *) S; + //check if BASE is ok + if ((BASE < 0) || BASE > 36) + { + return 0; + } + // ignore white space at beginning of S + while ((**PTR == ' ') + || (**PTR == '\t') + || (**PTR == '\n') + || (**PTR == '\r') + ) + { + (*PTR)++; + } + // if BASE is 0... determine the base from the first chars... + if (BASE == 0) + { + // if S starts with "0x", BASE = 16, else 10 + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + BASE = 16; + } + else + { + BASE = 10; + } + } + if (BASE == 16) + { + // S may start with "0x" + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + (*PTR)++; + (*PTR)++; + } + } + //until end of string + while (**PTR) + { + if (((**PTR) >= '0') && ((**PTR) <='9')) + { + //digit (0..9) + digit = **PTR - '0'; + } + else if (((**PTR) >= 'a') && ((**PTR) <='z')) + { + //alphanumeric digit lowercase(a (10) .. z (35) ) + digit = (**PTR - 'a') + 10; + } + else if (((**PTR) >= 'A') && ((**PTR) <='Z')) + { + //alphanumeric digit uppercase(a (10) .. z (35) ) + digit = (**PTR - 'A') + 10; + } + else + { + //end of parseable number reached... + break; + } + if (digit < BASE) + { + rval = (rval * BASE) + digit; + } + else + { + //digit found, but its too big for current base + //end of parseable number reached... + break; + } + //next... + (*PTR)++; + } + //done + return rval; +} + diff --git a/roms/skiboot/libc/string/Makefile.inc b/roms/skiboot/libc/string/Makefile.inc new file mode 100644 index 000000000..2f038219f --- /dev/null +++ b/roms/skiboot/libc/string/Makefile.inc @@ -0,0 +1,23 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2016 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +SUBDIRS += $(LIBCDIR)/string + +STRING_OBJS = strcat.o strchr.o strrchr.o strcmp.o strcpy.o strlen.o \ + strncmp.o strncpy.o strstr.o memset.o memcpy.o memcpy_from_ci.o \ + memmove.o memchr.o memcmp.o strcasecmp.o strncasecmp.o \ + strtok.o strdup.o +STRING = $(LIBCDIR)/string/built-in.a +$(STRING): $(STRING_OBJS:%=$(LIBCDIR)/string/%) + +CFLAGS_SKIP_libc/string/ += -Os +CFLAGS_libc/string/ += -O2 diff --git a/roms/skiboot/libc/string/memchr.c b/roms/skiboot/libc/string/memchr.c new file mode 100644 index 000000000..db9a147c6 --- /dev/null +++ b/roms/skiboot/libc/string/memchr.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +void *memchr(const void *ptr, int c, size_t n); +void *memchr(const void *ptr, int c, size_t n) +{ + unsigned char ch = (unsigned char)c; + const unsigned char *p = ptr; + + while (n-- > 0) { + if (*p == ch) + return (void *)p; + p += 1; + } + + return NULL; +} diff --git a/roms/skiboot/libc/string/memcmp.c b/roms/skiboot/libc/string/memcmp.c new file mode 100644 index 000000000..b270b597b --- /dev/null +++ b/roms/skiboot/libc/string/memcmp.c @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +int memcmp(const void *ptr1, const void *ptr2, size_t n); +int memcmp(const void *ptr1, const void *ptr2, size_t n) +{ + const unsigned char *p1 = ptr1; + const unsigned char *p2 = ptr2; + + while (n-- > 0) { + if (*p1 != *p2) + return (*p1 - *p2); + p1 += 1; + p2 += 1; + } + + return 0; +} diff --git a/roms/skiboot/libc/string/memcpy.c b/roms/skiboot/libc/string/memcpy.c new file mode 100644 index 000000000..26f953d2e --- /dev/null +++ b/roms/skiboot/libc/string/memcpy.c @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> +#include <ccan/short_types/short_types.h> + +void *memcpy(void *dest, const void *src, size_t n); +void *memcpy(void *dest, const void *src, size_t n) +{ + void *ret = dest; + + while (n >= 8) { + *(uint64_t *)dest = *(uint64_t *)src; + dest += 8; + src += 8; + n -= 8; + } + + while (n > 0) { + *(uint8_t *)dest = *(uint8_t *)src; + dest += 1; + src += 1; + n -= 1; + } + + return ret; +} diff --git a/roms/skiboot/libc/string/memcpy_from_ci.c b/roms/skiboot/libc/string/memcpy_from_ci.c new file mode 100644 index 000000000..dd4d94e02 --- /dev/null +++ b/roms/skiboot/libc/string/memcpy_from_ci.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2016 IBM Corp + */ + +#include <ccan/short_types/short_types.h> +#include <io.h> +#include <string.h> + +void *memcpy_from_ci(void *destpp, const void *srcpp, size_t len) +{ + const size_t block = sizeof(uint64_t); + unsigned long int destp = (long int) destpp; + unsigned long int srcp = (long int) srcpp; + + /* Copy as many blocks as possible if srcp is block aligned */ + if ((srcp % block) == 0) { + while ((len - block) > -1) { + uint64_t v; + if (HAVE_BIG_ENDIAN) + v = in_be64((beint64_t*)srcp); + else + v = in_le64((leint64_t*)srcp); + *((uint64_t *) destp) = v; + srcp += block; + destp += block; + len -= block; + } + } + /* + * Byte-by-byte copy if srcp is not block aligned or len is/becomes + * less than one block + */ + while (len > 0) { + *((uint8_t*) destp) = in_8((uint8_t*)srcp); + srcp += 1; + destp += 1; + len--; + } + return destpp; +} diff --git a/roms/skiboot/libc/string/memmove.c b/roms/skiboot/libc/string/memmove.c new file mode 100644 index 000000000..76aef6c87 --- /dev/null +++ b/roms/skiboot/libc/string/memmove.c @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +void *memcpy(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n) +{ + /* Do the buffers overlap in a bad way? */ + if (src < dest && src + n >= dest) { + char *cdest; + const char *csrc; + int i; + + /* Copy from end to start */ + cdest = dest + n - 1; + csrc = src + n - 1; + for (i = 0; i < n; i++) { + *cdest-- = *csrc--; + } + return dest; + } else { + /* Normal copy is possible */ + return memcpy(dest, src, n); + } +} diff --git a/roms/skiboot/libc/string/memset.c b/roms/skiboot/libc/string/memset.c new file mode 100644 index 000000000..f96a0231f --- /dev/null +++ b/roms/skiboot/libc/string/memset.c @@ -0,0 +1,54 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#define CACHE_LINE_SIZE 128 + +#include <stddef.h> + +void *memset(void *dest, int c, size_t size); +void *memset(void *dest, int c, size_t size) +{ + unsigned char *d = (unsigned char *)dest; + unsigned long big_c = 0; + +#if defined(__powerpc__) || defined(__powerpc64__) + if (size > CACHE_LINE_SIZE && c==0) { + while ((unsigned long long)d % CACHE_LINE_SIZE) { + *d++ = (unsigned char)c; + size--; + } + while (size >= CACHE_LINE_SIZE) { + asm volatile ("dcbz 0,%0\n" : : "r"(d) : "memory"); + d+= CACHE_LINE_SIZE; + size-= CACHE_LINE_SIZE; + } + } +#endif + + if (c) { + big_c = c; + big_c |= (big_c << 8) | big_c; + big_c |= (big_c << 16) | big_c; + big_c |= (big_c << 32) | big_c; + } + while (size >= 8 && c == 0) { + *((unsigned long *)d) = big_c; + d+=8; + size-=8; + } + + while (size-- > 0) { + *d++ = (unsigned char)c; + } + + return dest; +} diff --git a/roms/skiboot/libc/string/strcasecmp.c b/roms/skiboot/libc/string/strcasecmp.c new file mode 100644 index 000000000..ba1aedb5f --- /dev/null +++ b/roms/skiboot/libc/string/strcasecmp.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <ctype.h> + +int strcasecmp(const char *s1, const char *s2); +int strcasecmp(const char *s1, const char *s2) +{ + while (*s1 != 0 && *s2 != 0) { + if (toupper(*s1) != toupper(*s2)) + break; + ++s1; + ++s2; + } + + return *s1 - *s2; +} + diff --git a/roms/skiboot/libc/string/strcat.c b/roms/skiboot/libc/string/strcat.c new file mode 100644 index 000000000..329cc88e1 --- /dev/null +++ b/roms/skiboot/libc/string/strcat.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +size_t strlen(const char *s); +char *strcpy(char *dst, const char *src); +char *strcat(char *dst, const char *src); +char *strcat(char *dst, const char *src) +{ + size_t p; + + p = strlen(dst); + strcpy(&dst[p], src); + + return dst; +} diff --git a/roms/skiboot/libc/string/strchr.c b/roms/skiboot/libc/string/strchr.c new file mode 100644 index 000000000..88f25f96b --- /dev/null +++ b/roms/skiboot/libc/string/strchr.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +char *strchr(const char *s, int c); +char *strchr(const char *s, int c) +{ + char cb = c; + + while (*s != 0) { + if (*s == cb) { + return (char *)s; + } + s += 1; + } + + return NULL; +} diff --git a/roms/skiboot/libc/string/strcmp.c b/roms/skiboot/libc/string/strcmp.c new file mode 100644 index 000000000..5afbae2a7 --- /dev/null +++ b/roms/skiboot/libc/string/strcmp.c @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +int strcmp(const char *s1, const char *s2); +int strcmp(const char *s1, const char *s2) +{ + while (*s1 != 0 && *s2 != 0) { + if (*s1 != *s2) + break; + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + diff --git a/roms/skiboot/libc/string/strcpy.c b/roms/skiboot/libc/string/strcpy.c new file mode 100644 index 000000000..514be1714 --- /dev/null +++ b/roms/skiboot/libc/string/strcpy.c @@ -0,0 +1,23 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +char *strcpy(char *dst, const char *src); +char *strcpy(char *dst, const char *src) +{ + char *ptr = dst; + + do { + *ptr++ = *src; + } while (*src++ != 0); + + return dst; +} diff --git a/roms/skiboot/libc/string/strdup.c b/roms/skiboot/libc/string/strdup.c new file mode 100644 index 000000000..b0a4b4d70 --- /dev/null +++ b/roms/skiboot/libc/string/strdup.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2012 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + +size_t strlen(const char *s); +void *memcpy(void *dest, const void *src, size_t n); +char *strdup(const char *src); +char *strdup(const char *src) +{ + size_t len = strlen(src) + 1; + char *ret; + + ret = malloc(len); + if (ret) + memcpy(ret, src, len); + return ret; +} diff --git a/roms/skiboot/libc/string/strlen.c b/roms/skiboot/libc/string/strlen.c new file mode 100644 index 000000000..f3c5a8362 --- /dev/null +++ b/roms/skiboot/libc/string/strlen.c @@ -0,0 +1,40 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +size_t strlen(const char *s); +size_t strlen(const char *s) +{ + size_t len = 0; + + while (*s != 0) { + len += 1; + s += 1; + } + + return len; +} + +size_t strnlen(const char *s, size_t n); +size_t strnlen(const char *s, size_t n) +{ + size_t len = 0; + + while (*s != 0 && n) { + len += 1; + s += 1; + n--; + } + + return len; +} diff --git a/roms/skiboot/libc/string/strncasecmp.c b/roms/skiboot/libc/string/strncasecmp.c new file mode 100644 index 000000000..c6b158e60 --- /dev/null +++ b/roms/skiboot/libc/string/strncasecmp.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <ctype.h> + +int strncasecmp(const char *s1, const char *s2, size_t n); +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n < 1) + return 0; + + while (*s1 != 0 && *s2 != 0 && --n > 0) { + if (toupper(*s1) != toupper(*s2)) + break; + ++s1; + ++s2; + } + + return toupper(*s1) - toupper(*s2); +} + diff --git a/roms/skiboot/libc/string/strncmp.c b/roms/skiboot/libc/string/strncmp.c new file mode 100644 index 000000000..a5422c0dc --- /dev/null +++ b/roms/skiboot/libc/string/strncmp.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +int strncmp(const char *s1, const char *s2, size_t n); +int strncmp(const char *s1, const char *s2, size_t n) +{ + if (n < 1) + return 0; + + while (*s1 != 0 && *s2 != 0 && --n > 0) { + if (*s1 != *s2) + break; + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + diff --git a/roms/skiboot/libc/string/strncpy.c b/roms/skiboot/libc/string/strncpy.c new file mode 100644 index 000000000..621c89b64 --- /dev/null +++ b/roms/skiboot/libc/string/strncpy.c @@ -0,0 +1,33 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +char *strncpy(char *dst, const char *src, size_t n); +char *strncpy(char *dst, const char *src, size_t n) +{ + char *ret = dst; + + /* Copy string */ + while (*src != 0 && n > 0) { + *dst++ = *src++; + n -= 1; + } + + /* strncpy always clears the rest of destination string... */ + while (n > 0) { + *dst++ = 0; + n -= 1; + } + + return ret; +} diff --git a/roms/skiboot/libc/string/strrchr.c b/roms/skiboot/libc/string/strrchr.c new file mode 100644 index 000000000..262a68287 --- /dev/null +++ b/roms/skiboot/libc/string/strrchr.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008, 2019 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +char *strrchr(const char *s, int c); +char *strrchr(const char *s, int c) +{ + char *last = NULL; + char cb = c; + + while (*s != 0) { + if (*s == cb) + last = (char *)s; + s += 1; + } + + return last; +} diff --git a/roms/skiboot/libc/string/strstr.c b/roms/skiboot/libc/string/strstr.c new file mode 100644 index 000000000..cd9ccae9a --- /dev/null +++ b/roms/skiboot/libc/string/strstr.c @@ -0,0 +1,39 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +size_t strlen(const char *s); +int strncmp(const char *s1, const char *s2, size_t n); +char *strstr(const char *hay, const char *needle); +char *strstr(const char *hay, const char *needle) +{ + char *pos; + size_t hlen, nlen; + + if (hay == NULL || needle == NULL) + return NULL; + + hlen = strlen(hay); + nlen = strlen(needle); + if (nlen < 1) + return (char *)hay; + + for (pos = (char *)hay; pos < hay + hlen; pos++) { + if (strncmp(pos, needle, nlen) == 0) { + return pos; + } + } + + return NULL; +} + diff --git a/roms/skiboot/libc/string/strtok.c b/roms/skiboot/libc/string/strtok.c new file mode 100644 index 000000000..fcc3fce32 --- /dev/null +++ b/roms/skiboot/libc/string/strtok.c @@ -0,0 +1,48 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stddef.h> + +char *strtok(char *src, const char *pattern); +char *strtok(char *src, const char *pattern) +{ + static char *nxtTok; + char *retVal = NULL; + + if (!src) { + src = nxtTok; + if (!src) + return retVal; + } + + while (*src) { + const char *pp = pattern; + while (*pp) { + if (*pp == *src) { + break; + } + pp++; + } + if (!*pp) { + if (!retVal) + retVal = src; + else if (!src[-1]) + break; + } else + *src = '\0'; + src++; + } + + nxtTok = src; + + return retVal; +} diff --git a/roms/skiboot/libc/test/.gitignore b/roms/skiboot/libc/test/.gitignore new file mode 100644 index 000000000..c1002af5b --- /dev/null +++ b/roms/skiboot/libc/test/.gitignore @@ -0,0 +1,10 @@ +gmon.out +run-ctype +run-ctype-gcov +run-memops +run-memops-gcov +run-snprintf +run-snprintf-gcov +run-stdlib +run-stdlib-gcov + diff --git a/roms/skiboot/libc/test/Makefile.check b/roms/skiboot/libc/test/Makefile.check new file mode 100644 index 000000000..a668334a1 --- /dev/null +++ b/roms/skiboot/libc/test/Makefile.check @@ -0,0 +1,74 @@ +# -*-Makefile-*- +LIBC_TEST := libc/test/run-time + +# We have some tricky tests that have system libc and skiboot libc, +# so that we can test parts of skiboot libc but in userspace. + +LIBC_DUALLIB_TEST := libc/test/run-snprintf \ + libc/test/run-memops \ + libc/test/run-stdlib \ + libc/test/run-ctype + +LCOV_EXCLUDE += $(LIBC_TEST:%=%.c) $(LIBC_DUALLIB_TEST:%=%.c) $(LIBC_DUALLIB_TEST:%=%-test.c) + +.PHONY : libc-check libc-coverage +libc-check: $(LIBC_TEST:%=%-check) $(LIBC_DUALLIB_TEST:%=%-check) +libc-coverage: $(LIBC_TEST:%=%-gcov-run) $(LIBC_DUALLIB_TEST:%=%-gcov-run) + +check: libc-check +coverage: libc-coverage + +$(LIBC_TEST:%=%-gcov-run) : %-run: % + $(call Q, TEST-COVERAGE ,$< , $<) + +$(LIBC_DUALLIB_TEST:%=%-gcov-run) : %-run: % + $(eval LCOV_DIRS += -d $(dir $<) ) + $(call Q, TEST-COVERAGE , (cd $(dir $<); GCOV_PREFIX_STRIP=`(c=0; while [ "\`pwd\`" != '/' ]; do cd ..; c=\`expr 1 + $$c\`; done; echo $$c)` ./$(notdir $<) ), $< ) + +$(LIBC_TEST:%=%-check) : %-check: % + $(call Q, RUN-TEST ,$(VALGRIND) $<, $<) + +$(LIBC_DUALLIB_TEST:%=%-check) : %-check: % + $(call Q, RUN-TEST ,$(VALGRIND) $<, $<) + +$(LIBC_TEST) : % : %.c + $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -I libc/include -o $@ $<, $<) + +$(LIBC_TEST:%=%-gcov): %-gcov : %.c % + $(call Q, HOSTCC ,(cd $(dir $<); $(HOSTCC) $(HOSTCFLAGS) $(HOSTGCOVCFLAGS) -I$(shell pwd)/include -I$(shell pwd) -I$(shell pwd)/libfdt -I$(shell pwd)/libc/include -o $(notdir $@) $(notdir $<)), $<) + +$(LIBC_DUALLIB_TEST) : % : %.o %-test.o + $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -o $@ $@-test.o $<, $<) + +$(LIBC_DUALLIB_TEST:%=%-gcov) : %-gcov : %-gcov.o %-gcov-test.o + $(call Q, HOSTCC ,(cd $(dir $<); $(HOSTCC) $(HOSTCFLAGS) $(HOSTGCOVCFLAGS) -I$(shell pwd)/include -I$(shell pwd)/. -I$(shell pwd)/libfdt -o $(notdir $@) $(notdir $@)-test.o $(notdir $<)), $<) + +$(LIBC_DUALLIB_TEST:%=%-test.o): %-test.o : %-test.c + $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -I libc/include -ffreestanding -o $@ -c $<, $<) + +$(LIBC_DUALLIB_TEST:%=%.o): %.o : %.c + $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -o $@ -c $<, $<) + +$(LIBC_DUALLIB_TEST:%=%-gcov.o): %-gcov.o : %.c + $(call Q, HOSTCC ,(cd $(dir $<); $(HOSTCC) $(HOSTCFLAGS) -fprofile-arcs -ftest-coverage -lgcov -pg -O0 -g -o $(notdir $@) -c $(notdir $<)), $<) + +$(LIBC_DUALLIB_TEST:%=%-gcov-test.o): %-gcov-test.o : %-test.c % + $(call Q, HOSTCC ,(cd $(dir $<); $(HOSTCC) $(HOSTCFLAGS) -fprofile-arcs -ftest-coverage -lgcov -pg -O0 -g -I$(shell pwd)/include -I$(shell pwd)/. -I$(shell pwd)/libfdt -I$(shell pwd)/libc/include -ffreestanding -o $(notdir $@) -c $(notdir $<) ), $<) + +-include $(wildcard libc/test/*.d) + +clean: libc-test-clean + +libc-test-clean: + $(RM) -f libc/test/*.[od] + $(RM) -f $(LIBC_TEST) \ + $(LIBC_TEST:%=%-gcov) \ + $(LIBC_TEST:%=%.gcda) \ + $(LIBC_TEST:%=%.gcno) + $(RM) -f $(LIBC_DUALLIB_TEST) \ + $(LIBC_DUALLIB_TEST:%=%-gcov) \ + $(LIBC_DUALLIB_TEST:%=%-gcov.gcda) \ + $(LIBC_DUALLIB_TEST:%=%-gcov.gcno) \ + $(LIBC_DUALLIB_TEST:%=%-gcov-test.gcda) \ + $(LIBC_DUALLIB_TEST:%=%-gcov-test.gcno) \ + $(LIBC_DUALLIB_TEST:%=%-test.o) diff --git a/roms/skiboot/libc/test/run-ctype-test.c b/roms/skiboot/libc/test/run-ctype-test.c new file mode 100644 index 000000000..d491b4942 --- /dev/null +++ b/roms/skiboot/libc/test/run-ctype-test.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2015 IBM Corp. + * + * This file is run with the skiboot libc files rather than system libc. + * This means we have a bit of "fun" with actually executing the tests on + * the host. + * Patches to make this less ugly are very welcome. + */ + +#include <config.h> +#include <stdarg.h> + +#include "../ctype/isdigit.c" +#include "../ctype/isprint.c" +#include "../ctype/isspace.c" +#include "../ctype/isxdigit.c" +#include "../ctype/tolower.c" +#include "../ctype/toupper.c" + +int skiboot_isdigit(int ch); +int skiboot_isprint(int ch); +int skiboot_isspace(int ch); +int skiboot_isxdigit(int ch); +int skiboot_tolower(int ch); +int skiboot_toupper(int ch); + +int skiboot_isdigit(int ch) +{ + return isdigit(ch); +} + +int skiboot_isprint(int ch) +{ + return isprint(ch); +} + +int skiboot_isspace(int ch) +{ + return isspace(ch); +} + +int skiboot_isxdigit(int ch) +{ + return isxdigit(ch); +} + +int skiboot_tolower(int ch) +{ + return tolower(ch); +} + +int skiboot_toupper(int ch) +{ + return toupper(ch); +} diff --git a/roms/skiboot/libc/test/run-ctype.c b/roms/skiboot/libc/test/run-ctype.c new file mode 100644 index 000000000..a43d37123 --- /dev/null +++ b/roms/skiboot/libc/test/run-ctype.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2015 IBM Corp. + */ + +#define BUFSZ 50 + +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include <ctype.h> + +int skiboot_isdigit(int ch); +int skiboot_isprint(int ch); +int skiboot_isspace(int ch); +int skiboot_isxdigit(int ch); +int skiboot_tolower(int ch); +int skiboot_toupper(int ch); + +int main(void) +{ + int i; + int r1, r2; + + for(i = '0'; i <= '9'; i++) + assert(skiboot_isdigit(i)); + assert(skiboot_isdigit('a') == 0); + assert(skiboot_isdigit('Z') == 0); + + for (i = 0; i < 257; i++) { + r1 = skiboot_isdigit(i); + r2 = isdigit(i); + if (r1) + assert(r2); + if (!r1) + assert(!r2); + } + + for(i = '0'; i <= '9'; i++) + assert(skiboot_isprint(i)); + assert(skiboot_isprint('\0') == 0); + assert(skiboot_isprint(4) == 0); + + for (i = 0; i < 257; i++) { + r1 = skiboot_isprint(i); + r2 = isprint(i); + if (r1) + assert(r2); + if (!r1) + assert(!r2); + } + + for(i = '0'; i <= '9'; i++) + assert(skiboot_isspace(i) == 0); + assert(skiboot_isspace('\f')); + assert(skiboot_isspace('\n')); + assert(skiboot_isspace(' ')); + + for (i = 0; i < 257; i++) { + r1 = skiboot_isspace(i); + r2 = isspace(i); + if (r1) + assert(r2); + if (!r1) + assert(!r2); + } + + for(i = '0'; i <= '9'; i++) + assert(skiboot_isxdigit(i)); + assert(skiboot_isxdigit('a')); + assert(skiboot_isxdigit('A')); + assert(skiboot_isxdigit('F')); + assert(skiboot_isxdigit('Z') == 0); + + for (i = 0; i < 257; i++) { + r1 = skiboot_isxdigit(i); + r2 = isxdigit(i); + if (r1) + assert(r2); + if (!r1) + assert(!r2); + } + + for (i = 0; i < 257; i++) { + assert(skiboot_tolower(i) == tolower(i)); + } + + for (i = 0; i < 257; i++) { + assert(skiboot_toupper(i) == toupper(i)); + } + + return 0; +} diff --git a/roms/skiboot/libc/test/run-memops-test.c b/roms/skiboot/libc/test/run-memops-test.c new file mode 100644 index 000000000..5be0d9ac1 --- /dev/null +++ b/roms/skiboot/libc/test/run-memops-test.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2015 IBM Corp. + * + * This file is run with the skiboot libc files rather than system libc. + * This means we have a bit of "fun" with actually executing the tests on + * the host. + * Patches to make this less ugly are very welcome. + */ + +#include <config.h> +#include <stdarg.h> + +#include "../string/memchr.c" +#include "../string/memcmp.c" +#include "../string/memcpy.c" +#include "../string/memmove.c" +#include "../string/memset.c" +#include "../string/strcasecmp.c" +#include "../string/strcat.c" +#include "../string/strchr.c" +#include "../string/strrchr.c" +#include "../string/strcmp.c" +#include "../string/strcpy.c" +/* #include "../string/strdup.c" */ +#include "../string/strlen.c" +#include "../string/strncasecmp.c" +#include "../string/strncmp.c" +#include "../string/strncpy.c" +#include "../string/strstr.c" +#include "../string/strtok.c" +#include <stdlib.h> + +int test_memset(char* buf, int c, size_t s); +int test_memchr(const void *ptr, int c, size_t n, void* expected); +int test_memcmp(const void *ptr1, const void *ptr2, size_t n, int expected); +int test_strcmp(const void *ptr1, const void *ptr2, int expected); +int test_strchr(const char *s, int c, char *expected); +int test_strrchr(const char *s, int c, char *expected); +int test_strcasecmp(const char *s1, const char *s2, int expected); +int test_strncasecmp(const char *s1, const char *s2, size_t n, int expected); +int test_memmove(void *dest, const void *src, size_t n, const void *r, const void *expected, size_t expected_n); + +int test_memset(char* buf, int c, size_t s) +{ + int i; + int r= 0; + + memset(buf, c, s); + for(i=0; i<s; i++) + if (buf[i] != c) + r = -1; + + return r; +} + +int test_memchr(const void *ptr, int c, size_t n, void* expected) +{ + return(expected == memchr(ptr, c, n)); +} + +int test_memcmp(const void *ptr1, const void *ptr2, size_t n, int expected) +{ + return(expected == memcmp(ptr1, ptr2, n)); +} + +int test_strcmp(const void *ptr1, const void *ptr2, int expected) +{ + return(expected == strcmp(ptr1, ptr2)); +} + +int test_strchr(const char *s, int c, char *expected) +{ + return(expected == strchr(s, c)); +} + +int test_strrchr(const char *s, int c, char *expected) +{ + return(expected == strrchr(s, c)); +} + +int test_strcasecmp(const char *s1, const char *s2, int expected) +{ + return(expected == strcasecmp(s1, s2)); +} + +int test_strncasecmp(const char *s1, const char *s2, size_t n, int expected) +{ + return(expected == strncasecmp(s1, s2, n)); +} + +int test_memmove(void *dest, const void *src, size_t n, const void *r, const void *expected, size_t expected_n) +{ + if (memmove(dest, src, n) != dest) + return -1; + return(memcmp(r, expected, expected_n) == 0); +} diff --git a/roms/skiboot/libc/test/run-memops.c b/roms/skiboot/libc/test/run-memops.c new file mode 100644 index 000000000..a00c2fb36 --- /dev/null +++ b/roms/skiboot/libc/test/run-memops.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2015 IBM Corp. + */ + +#define BUFSZ 50 + +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> + +int test_memset(char* buf, int c, size_t s); +int test_memchr(const void *ptr, int c, size_t n, void* expected); +int test_memcmp(const void *ptr1, const void *ptr2, size_t n, int expected); +int test_strcmp(const void *ptr1, const void *ptr2, int expected); +int test_strchr(const char *s, int c, char *expected); +int test_strrchr(const char *s, int c, char *expected); +int test_strcasecmp(const char *s1, const char *s2, int expected); +int test_strncasecmp(const char *s1, const char *s2, size_t n, int expected); +int test_memmove(void *dest, const void *src, size_t n, const void *r, const void *expected, size_t expected_n); + +int main(void) +{ + char *buf; + char *buf2; + + buf = malloc(100); + assert(test_memset(buf, 0x42, 100) == 0); + free(buf); + + buf = malloc(128); + assert(test_memset(buf, 0, 128) == 0); + assert(test_memset(buf+1, 0, 127) == 0); + free(buf); + + buf = malloc(1024); + assert(test_memset(buf, 0, 1024) == 0); + free(buf); + + buf = malloc(20); + strncpy(buf, "Hello World!", 20); + assert(test_memchr(buf, 'o', strlen(buf), buf+4)); + assert(test_memchr(buf, 'a', strlen(buf), NULL)); + + assert(test_memcmp(buf, "Hello World!", strlen(buf), 0)); + assert(test_memcmp(buf, "Hfllow World", strlen(buf), -1)); + + assert(test_strcmp(buf, "Hello World!", 0)); + assert(test_strcmp(buf, "Hfllow World", -1)); + + assert(test_strchr(buf, 'H', buf)); + assert(test_strchr(buf, 'e', buf+1)); + assert(test_strchr(buf, 'a', NULL)); + assert(test_strchr(buf, '!', buf+11)); + + assert(test_strrchr(buf, 'H', buf)); + assert(test_strrchr(buf, 'o', buf+7)); + assert(test_strrchr(buf, 'a', NULL)); + assert(test_strrchr(buf, 'l', buf+9)); + assert(test_strrchr(buf, '!', buf+11)); + + assert(test_strcasecmp(buf, "Hello World!", 0)); + assert(test_strcasecmp(buf, "HELLO WORLD!", 0)); + assert(test_strcasecmp(buf, "IELLO world!", -1)); + assert(test_strcasecmp(buf, "HeLLo WOrlc!", 1)); + + assert(test_strncasecmp(buf, "Hello World!", strlen(buf), 0)); + assert(test_strncasecmp(buf, "HELLO WORLD!", strlen(buf), 0)); + assert(test_strncasecmp(buf, "IELLO world!", strlen(buf), -1)); + assert(test_strncasecmp(buf, "HeLLo WOrlc!", strlen(buf), 1)); + + assert(test_strncasecmp(buf, "HeLLo WOrlc!", 0, 0)); + assert(test_strncasecmp(buf, "HeLLo WOrlc!", 1, 0)); + assert(test_strncasecmp(buf, "HeLLo WOrlc!", 2, 0)); + assert(test_strncasecmp(buf, "HeLLp WOrlc!", 5, -1)); + + free(buf); + + buf = malloc(20); + buf2 = malloc(20); + strncpy(buf, "Hello", 20); + strncpy(buf2, " World!", 20); + + assert(test_memmove(buf + 5, buf2, strlen(buf2), buf, + "Hello World!", strlen("Hello World!"))); + + strncpy(buf, "HHello World!", 20); + assert(test_memmove(buf, buf+1, strlen("Hello World!"), buf, "Hello World!", strlen("Hello World!"))); + + strncpy(buf, "0123456789", 20); + assert(test_memmove(buf+1, buf , strlen("0123456789"), buf, "00123456789", strlen("00123456789"))); + + free(buf); + free(buf2); + + return 0; +} diff --git a/roms/skiboot/libc/test/run-snprintf-test.c b/roms/skiboot/libc/test/run-snprintf-test.c new file mode 100644 index 000000000..a6ad02373 --- /dev/null +++ b/roms/skiboot/libc/test/run-snprintf-test.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2015 IBM Corp. + * + * This file is run with the skiboot libc files rather than system libc. + * This means we have a bit of "fun" with actually executing the tests on + * the host. + * Patches to make this less ugly are very welcome. + */ + +#include <config.h> +#include <stdarg.h> + +#include "../stdio/snprintf.c" +#include "../stdio/vsnprintf.c" + +int test1(void); + +int test1(void) +{ + return snprintf(NULL, 1, "Hello"); +} + +int skiboot_snprintf(char *buf, size_t bufsz, size_t l, const char* format, ...); + +int skiboot_snprintf(char *buf, size_t bufsz, size_t l, const char* format, ...) +{ + va_list ar; + int count; + + if (buf) + memset(buf, 0, bufsz); + + if ((buf==NULL) || (format==NULL)) + return(-1); + + va_start(ar, format); + count = vsnprintf(buf, l, format, ar); + va_end(ar); + + return(count); +} diff --git a/roms/skiboot/libc/test/run-snprintf.c b/roms/skiboot/libc/test/run-snprintf.c new file mode 100644 index 000000000..946d446fa --- /dev/null +++ b/roms/skiboot/libc/test/run-snprintf.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2015 IBM Corp. + */ + +#define BUFSZ 50 + +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> + +int test1(void); +int skiboot_snprintf(char *buf, size_t bufsz, size_t l, const char* format, ...); + +static void test_printf_0u(int n) +{ + char *buf, *buf2; + int blen; + unsigned int i; + + for(i=1; i<10; i++) + { + blen = i+1; + if (n<0) + blen++; + + buf = (char*)malloc(blen); + buf2 = (char*)malloc(blen); + skiboot_snprintf(buf, blen, blen, "%08u", n); + snprintf(buf2, blen, "%08u", n); + n = n * 10; + assert(0 == strncmp(buf, buf2, blen)); + free(buf); + free(buf2); + } +} + +static void test_printf_u(int n) +{ + char *buf, *buf2; + int blen; + unsigned int r; + unsigned int i; + + for(i=1; i<10; i++) + { + blen = i+1; + if (n<0) + blen++; + + buf = (char*)malloc(blen); + buf2 = (char*)malloc(blen); + r = skiboot_snprintf(buf, blen, blen, "%u", n); + snprintf(buf2, blen, "%u", n); + n = n * 10; + if (n<0) + assert(i+1 == r); + else + assert(i == r); + assert(0 == strncmp(buf, buf2, blen)); + free(buf); + free(buf2); + } +} + +static void test_printf_d(int n) +{ + char *buf, *buf2; + int blen; + int r; + int i; + + for(i=1; i<10; i++) + { + blen = i+1; + if (n<0) + blen++; + + buf = (char*)malloc(blen); + buf2 = (char*)malloc(blen); + r = skiboot_snprintf(buf, blen, blen, "%d", n); + snprintf(buf2, blen, "%d", n); + n = n * 10; + if (n<0) + assert(i+1 == r); + else + assert(i == r); + assert(0 == strncmp(buf, buf2, blen)); + free(buf); + free(buf2); + } +} + +static void test_printf_x(const char* f) +{ + char *buf, *buf2; + int blen; + int i, r; + unsigned int n=0x1; + + for (i=0; i<8; i++) + { + blen = i+2; + buf = (char*)malloc(blen); + buf2 = (char*)malloc(blen); + r = skiboot_snprintf(buf, blen, blen, f, n); + snprintf(buf2, blen, f, n); + assert(i+1 == r); + assert(0 == strncmp(buf, buf2, blen)); + free(buf); + free(buf2); + n = n << 4; + } +} + +static void test_printf_c(void) +{ + char *buf= (char*)malloc(2); + char buf2[2]; + unsigned char i= 0xff; + int r; + while(i) + { + r = skiboot_snprintf(buf, 2, 2, "%c", i); + snprintf(buf2, 2, "%c", i); + assert(r==1); + assert(0 == strncmp(buf, buf2, 2)); + i--; + } + free(buf); +} + +static void test_printf_p(void) +{ + char *buf= (char*)malloc(32); + char buf2[32]; + skiboot_snprintf(buf, 32, 32, "%p", buf); + snprintf(buf2, 32, "%p", buf); + assert(0 == strncmp(buf, buf2, 32)); + free(buf); +} + +static void test_printf_o(void) +{ + char *buf= (char*)malloc(32); + char buf2[32]; + skiboot_snprintf(buf, 32, 32, "%o", 0x12345678); + snprintf(buf2, 32, "%o", 0x12345678); + assert(0 == strncmp(buf, buf2, 32)); + free(buf); +} + +static void test_printf_h(short i) +{ + char *buf= (char*)malloc(32); + char buf2[32]; + skiboot_snprintf(buf, 32, 32, "%hd", i); + snprintf(buf2, 32, "%hd", i); + assert(0 == strncmp(buf, buf2, 32)); + free(buf); +} + +static void test_printf_z(size_t i) +{ + char *buf= (char*)malloc(32); + char buf2[32]; + skiboot_snprintf(buf, 32, 32, "%zu", i); + snprintf(buf2, 32, "%zu", i); + assert(0 == strncmp(buf, buf2, 32)); + free(buf); +} + +int main(void) +{ + char *buf; + int r; + + buf = (char*)malloc(BUFSZ); + memset(buf, 0, BUFSZ); + + assert(-1 == test1()); + + r = skiboot_snprintf(buf, BUFSZ, 2, "%%"); + assert(r==1); + assert(buf[0] == '%' && buf[1] == 0); + + r = skiboot_snprintf(buf, BUFSZ, 2, "%d", 137); + /* BUG/FIXME: + * skiboot libc does NOT return the length of the buffer you'd need + * Instead, it'll return something random, possibly zero (as here) + * but as you'll see in test_in_buf_len2, sometimes not. + * + * Basically, we're not POSIX printf and this is some day going to + * cause things to be awful. + */ + assert(0 == r); // BUG, should be 3 + assert(0 == strncmp(buf, "", 3)); + + r = skiboot_snprintf(buf, BUFSZ, 4, "%d", 137); + assert(3 == r); + assert(0 == strncmp(buf, "137", 3)); + assert(buf[3] == 0); + + /* Now we test the strange behaviour of our printf. + * For strings, we get partial prints going, but if we whack an + * integer on the end, we may or may not get that integer, depending + * on if we have enough size. We should test that though */ + + r = skiboot_snprintf(buf, BUFSZ, 4, "Hello %d", 137); + assert(3 == r); + assert(0 == strncmp(buf, "Hel", 3)); + assert(buf[3] == 0); + r = skiboot_snprintf(buf, BUFSZ, 7, "Hello %d", 137); + assert(6 == r); + assert(0 == strncmp(buf, "Hello ", 6)); + assert(buf[6] == 0); + r = skiboot_snprintf(buf, BUFSZ, 10, "Hello %d", 137); + assert(9 == r); + assert(0 == strncmp(buf, "Hello 137", 10)); + assert(buf[9] == 0); + free(buf); + + test_printf_u(1); + test_printf_0u(1); + test_printf_d(1); + test_printf_d(-1); + test_printf_x("%x"); + test_printf_x("%X"); + test_printf_c(); + test_printf_p(); + test_printf_o(); + test_printf_h(0); + test_printf_h(128); + test_printf_h(256); + test_printf_h(-1); + test_printf_h(32767); + test_printf_h(32768); + test_printf_h(65535); + test_printf_z(0); + test_printf_z(-1); + test_printf_z(12345); + test_printf_z(128000000); + + return 0; +} diff --git a/roms/skiboot/libc/test/run-stdlib-test.c b/roms/skiboot/libc/test/run-stdlib-test.c new file mode 100644 index 000000000..f7d7137c9 --- /dev/null +++ b/roms/skiboot/libc/test/run-stdlib-test.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2015 IBM Corp. + * + * This file is run with the skiboot libc files rather than system libc. + * This means we have a bit of "fun" with actually executing the tests on + * the host. + * Patches to make this less ugly are very welcome. + */ + +#include <config.h> +#include <stdarg.h> + +#include "../stdlib/atoi.c" +#include "../stdlib/atol.c" +#include "../stdlib/error.c" +#include "../stdlib/rand.c" +#include "../stdlib/strtol.c" +#include "../stdlib/strtoul.c" diff --git a/roms/skiboot/libc/test/run-stdlib.c b/roms/skiboot/libc/test/run-stdlib.c new file mode 100644 index 000000000..174920897 --- /dev/null +++ b/roms/skiboot/libc/test/run-stdlib.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2013-2015 IBM Corp. + */ + +#define BUFSZ 50 + +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> + +int main(void) +{ + char buf[] = "42, and stuff."; + char *ptr; + + /* atoi/strtol - general correct behavior */ + assert(atoi("0") == 0); + assert(atoi("1") == 1); + assert(atoi(" 123456") == 123456); + assert(atoi("-72") == -72); + assert(atoi(" -84") == -84); + assert(atoi("2147483647") == 2147483647); + + /* atoi/strtol - numbers before and after strings */ + assert(atoi("hello!123") == 0); + assert(atoi(buf) == 42); + assert(atoi("42isthemagicnumber") == 42); + + /* atoi is base 10 only */ + assert(atoi("0x800") == 0); + + /* atol - ensure it recognises longs */ + assert(atol("2147483648") == 2147483648); + assert(atol("-2147483649") == -2147483649); + + /* strtol detects hex */ + assert(strtol("0x800", NULL, 0) == 0x800); + /* But not with a duplicate prefix */ + assert(strtol("0x0x800", NULL, 0) == 0); + + /* strtol - invalid/weird bases */ + assert(strtol("z", NULL, -1) == 0); + assert(strtol("11111", NULL, 1) == 0); + assert(strtol("z", NULL, 37) == 0); + assert(strtol("z", NULL, 36) == 35); + assert(strtol("-Y", NULL, 36) == -34); + + /* strtol - ptr advanced correctly */ + ptr = buf; + assert(strtol(buf, &ptr, 10) == 42); + assert(ptr == buf + 2); + + /* strtoul - base 10 */ + assert(strtoul("0", NULL, 10) == 0); + assert(strtoul("1", NULL, 10) == 1); + assert(strtoul(" 123456", NULL, 10) == 123456); + assert(strtoul("-72", NULL, 10) == 0); + assert(strtoul("9999999999", NULL, 10) == 9999999999); + assert(strtoul("hello!123", NULL, 10) == 0); + assert(strtoul(buf, NULL, 10) == 42); + assert(strtoul("42isthemagicnumber", NULL, 10) == 42); + + /* strtoul - autodetection of base */ + assert(strtoul(" 123456", NULL, 0) == 123456); + assert(strtoul("0x800", NULL, 0) == 0x800); + assert(strtoul("0x0x800", NULL, 0) == 0); + + /* strtoul - weird/invalid bases */ + assert(strtoul("z", NULL, -1) == 0); + assert(strtoul("11111", NULL, 1) == 0); + assert(strtoul("z", NULL, 37) == 0); + assert(strtoul("z", NULL, 36) == 35); + assert(strtoul("Y", NULL, 36) == 34); + + /* labs - ensure it returns absolute value */ + assert(labs(0) == 0); + assert(labs(2147483647) == 2147483647); + assert(labs(-2147483647) == 2147483647); + assert(labs(9223372036854775807) == 9223372036854775807); + assert(labs(-9223372036854775807) == 9223372036854775807); + + return 0; +} diff --git a/roms/skiboot/libc/test/run-time.c b/roms/skiboot/libc/test/run-time.c new file mode 100644 index 000000000..95e83e5a9 --- /dev/null +++ b/roms/skiboot/libc/test/run-time.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Copyright 2014-2015 IBM Corp. + */ +#include "/usr/include/assert.h" +#include <stdio.h> +#include <libc/include/time.h> +#include <stdint.h> + +#include "../time.c" + +#define MKTIME_TEST(Y,M,D,h,m,s,t) \ + tm.tm_year = Y; \ + tm.tm_mon = M; \ + tm.tm_mday = D; \ + tm.tm_hour = h; \ + tm.tm_min = m; \ + tm.tm_sec = s; \ + assert(mktime(&tm) == t); \ + assert(tm.tm_year == Y); \ + assert(tm.tm_mon == M); \ + assert(tm.tm_mday == D); \ + assert(tm.tm_hour == h); \ + assert(tm.tm_min == m); \ + assert(tm.tm_sec == s) + +#define GMTIME_TEST(Y,M,D,h,m,s,tv) \ + t = tv; \ + gmtime_r(&t, &tm); \ + assert(tm.tm_year == Y); \ + assert(tm.tm_mon == M); \ + assert(tm.tm_mday == D); \ + assert(tm.tm_hour == h); \ + assert(tm.tm_min == m); \ + assert(tm.tm_sec == s) + +#define TIME_TEST(Y,M,D,h,m,s,tv) \ + MKTIME_TEST(Y,M,D,h,m,s,tv); \ + GMTIME_TEST(Y,M,D,h,m,s,tv) + +int main(void) +{ + struct tm tm; + time_t t = 0; + + TIME_TEST(1970, 0, 1, 0, 0, 0, 0); + TIME_TEST(1971, 0, 1, 0, 0, 0, 365*SECS_PER_DAY); + TIME_TEST(1972, 0, 1, 0, 0, 0, 2*365*SECS_PER_DAY); + TIME_TEST(1972, 11, 31, 0, 0, 0, 3*365*SECS_PER_DAY); + TIME_TEST(1973, 0, 1, 0, 0, 0, (3*365+1)*SECS_PER_DAY); + TIME_TEST(2000, 11, 31, 0, 0, 0, 978220800); + TIME_TEST(2001, 0, 1, 0, 0, 0, 978307200); + TIME_TEST(2003, 11, 31, 0, 0, 0, 1072828800); + TIME_TEST(2004, 0, 1, 0, 0, 0, 1072828800+SECS_PER_DAY); + TIME_TEST(2004, 11, 29, 0, 0, 0, 1072828800+364*SECS_PER_DAY); + TIME_TEST(2004, 11, 30, 0, 0, 0, 1072828800+365*SECS_PER_DAY); + TIME_TEST(2004, 11, 31, 0, 0, 0, 1072828800+366*SECS_PER_DAY); + TIME_TEST(2004, 11, 31, 23, 59, 59, 1072828800+367*SECS_PER_DAY-1); + TIME_TEST(2100, 11, 31, 0, 0, 0, 4133894400); + TIME_TEST(2101, 0, 1, 0, 0, 0, 4133980800); + + /* Test the normalisation functionality of mktime */ + tm.tm_year = 2000; + tm.tm_mon = 1; + tm.tm_mday = 10; + tm.tm_hour = 5; + tm.tm_min = 32; + tm.tm_sec = 105; + mktime(&tm); + assert(tm.tm_year == 2000); + assert(tm.tm_mon == 1); + assert(tm.tm_mday == 10); + assert(tm.tm_hour == 5); + assert(tm.tm_min == 33); + assert(tm.tm_sec == 45); + tm.tm_sec += 366*24*60*60; + mktime(&tm); + assert(tm.tm_year == 2001); + assert(tm.tm_mon == 1); + assert(tm.tm_mday == 10); + assert(tm.tm_hour == 5); + assert(tm.tm_min == 33); + assert(tm.tm_sec == 45); + + return 0; +} diff --git a/roms/skiboot/libc/time.c b/roms/skiboot/libc/time.c new file mode 100644 index 000000000..71bbdff64 --- /dev/null +++ b/roms/skiboot/libc/time.c @@ -0,0 +1,142 @@ +#include <stdbool.h> +#include <time.h> + +/* + * Returns the number of leap years prior to the given year. + */ +static int leap_years(int year) +{ + return (year-1)/4 + (year-1)/400 - (year-1)/100; +} + +static int is_leap_year(int year) +{ + return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); +} + +static int days_in_month(int month, int year) +{ + static char month_days[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, + }; + + /* we may need to update this in the year 4000, pending a + * decision on whether or not it's a leap year */ + if (month == 1) + return is_leap_year(year) ? 29 : 28; + + return month_days[month]; +} + +static const int days_per_month[2][13] = + {{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}}; + +#define SECS_PER_MIN 60 +#define SECS_PER_HOUR (SECS_PER_MIN*60) +#define SECS_PER_DAY (24*SECS_PER_HOUR) +#define DAYS_PER_YEAR 365 +struct tm *gmtime_r(const time_t *timep, struct tm *result) +{ + int i; + int Y; + int M; + int D; + int h; + int m; + int s; + + D = *timep / SECS_PER_DAY; + s = *timep % SECS_PER_DAY; + m = s / 60; + h = m / 60; + m %= 60; + s %= 60; + + /* + * Work out the year. We subtract one day for every four years + * and every 400 years after 1969. However as leap years don't + * occur every 100 years we add one day back to counteract the + * the subtraction for every 4 years. + */ + Y = (D - (1+D/365)/4 + (69+D/365)/100 - (369+D/365)/400)/365; + + /* + * Remember we're doing integer arithmetic here so + * leap_years(Y+1970) - leap_years(1970) != leap_years(Y) + */ + D = D - Y*365 - (leap_years(Y+1970) - leap_years(1970)) + 1; + Y += 1970; + + M = 0; + for (i = 0; i < 13; i++) + if (D <= days_per_month[is_leap_year(Y) ? 1 : 0][i]) { + M = i; + break; + } + + D -= days_per_month[is_leap_year(Y)][M-1]; + result->tm_year = Y; + result->tm_mon = M - 1; + result->tm_mday = D; + result->tm_hour = h; + result->tm_min = m; + result->tm_sec = s; + return result; +} + +time_t mktime(struct tm *tm) +{ + unsigned long year, month, mday, hour, minute, second, d; + static const unsigned long sec_in_400_years = + ((3903ul * 365) + (97 * 366)) * 24 * 60 * 60; + + second = tm->tm_sec; + minute = tm->tm_min; + hour = tm->tm_hour; + mday = tm->tm_mday; + month = tm->tm_mon; + year = tm->tm_year; + + /* There are the same number of seconds in any 400-year block; this + * limits the iterations in the loop below */ + year += 400 * (second / sec_in_400_years); + second = second % sec_in_400_years; + + if (second >= 60) { + minute += second / 60; + second = second % 60; + } + + if (minute >= 60) { + hour += minute / 60; + minute = minute % 60; + } + + if (hour >= 24) { + mday += hour / 24; + hour = hour % 24; + } + + for (d = days_in_month(month, year); mday > d; + d = days_in_month(month, year)) { + month++; + if (month > 11) { + month = 0; + year++; + } + mday -= d; + } + + tm->tm_year = year; + tm->tm_mon = month; + tm->tm_mday = mday; + tm->tm_hour = hour; + tm->tm_min = minute; + tm->tm_sec = second; + + d = mday; + d += days_per_month[is_leap_year(year)][month]; + d += (year-1970)*DAYS_PER_YEAR + leap_years(year) - leap_years(1970) - 1; + return d*SECS_PER_DAY + hour*SECS_PER_HOUR + minute*SECS_PER_MIN + second; +} |