libc: Introduce files from SCC

Taken from http://git.simple-cc.org/scc/ from the following commit:

67508ad14af314cea2229783d3c084f28c41daf0

Permission has been granted from the author to use them under the
license BSD-3-Clause instead of ISC.

Change-Id: I65c0ce3ab60c49d34a57533af12a74bd7bde88e5
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 65f39b0..de7b5db 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2982,32 +2982,13 @@
 more functionality is required, the needed library functions will need to be
 added to the local implementation.
 
-Versions of `FreeBSD`_ headers can be found in ``include/lib/stdlib``. Some of
-these headers have been cut down in order to simplify the implementation. In
-order to minimize changes to the header files, the `FreeBSD`_ layout has been
-maintained. The generic C library definitions can be found in
-``include/lib/stdlib`` with more system and machine specific declarations in
-``include/lib/stdlib/sys`` and ``include/lib/stdlib/machine``.
+Some C headers have been obtained from `FreeBSD`_ and `SCC`_, while others have
+been written specifically for TF-A. Fome implementation files have been obtained
+from `FreeBSD`_, others have been written specifically for TF-A as well. The
+files can be found in ``include/lib/libc`` and ``lib/libc``.
 
-The local C library implementations can be found in ``lib/stdlib``. In order to
-extend the C library these files may need to be modified. It is recommended to
-use a release version of `FreeBSD`_ as a starting point.
-
-The C library header files in the `FreeBSD`_ source tree are located in the
-``include`` and ``sys/sys`` directories. `FreeBSD`_ machine specific definitions
-can be found in the ``sys/<machine-type>`` directories. These files define things
-like 'the size of a pointer' and 'the range of an integer'. Since an AArch64
-port for `FreeBSD`_ does not yet exist, the machine specific definitions are
-based on existing machine types with similar properties (for example SPARC64).
-
-Where possible, C library function implementations were taken from `FreeBSD`_
-as found in the ``lib/libc`` directory.
-
-A copy of the `FreeBSD`_ sources can be downloaded with ``git``.
-
-::
-
-    git clone git://github.com/freebsd/freebsd.git -b origin/release/9.2.0
+SCC can be found in `http://www.simple-cc.org/`_. A copy of the `FreeBSD`_
+sources can be obtained from `http://github.com/freebsd/freebsd`_.
 
 Storage abstraction layer
 -------------------------
@@ -3082,3 +3063,4 @@
 .. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html
 .. _3.0 (GICv3): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0069b/index.html
 .. _FreeBSD: http://www.freebsd.org
+.. _SCC: http://www.simple-cc.org/
diff --git a/include/lib/libc/limits.h b/include/lib/libc/limits.h
new file mode 100644
index 0000000..df1a963
--- /dev/null
+++ b/include/lib/libc/limits.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _LIMITS_H
+#define _LIMITS_H
+
+#include <arch/limits.h>
+
+#define CHAR_BIT   8
+#define MB_LEN_MAX 1
+
+#endif
diff --git a/include/lib/libc/stdarg.h b/include/lib/libc/stdarg.h
new file mode 100644
index 0000000..3c20788
--- /dev/null
+++ b/include/lib/libc/stdarg.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _STDARG_H
+#define _STDARG_H
+
+#define va_list __builtin_va_list
+#define va_start(ap, last) __builtin_va_start(ap, last)
+#define va_end(ap) __builtin_va_end(ap)
+#define va_copy(to, from) __builtin_va_copy(to, from)
+#define va_arg(to, type) __builtin_va_arg(to, type)
+
+#endif
diff --git a/include/lib/libc/stddef.h b/include/lib/libc/stddef.h
new file mode 100644
index 0000000..1150650
--- /dev/null
+++ b/include/lib/libc/stddef.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+#include <arch/stddef.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define offsetof(st, m) ((size_t)&(((st *)0)->m))
+
+#endif
diff --git a/include/lib/libc/stdint.h b/include/lib/libc/stdint.h
new file mode 100644
index 0000000..cd24d1f
--- /dev/null
+++ b/include/lib/libc/stdint.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _STDINT_H_
+#define _STDINT_H_
+
+#include <arch/stdint.h>
+
+#endif
diff --git a/include/lib/libc/stdio.h b/include/lib/libc/stdio.h
new file mode 100644
index 0000000..a876f6c
--- /dev/null
+++ b/include/lib/libc/stdio.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _STDIO_H
+#define _STDIO_H
+
+#include <arch/stdio.h>
+
+#ifndef FOPEN_MAX
+#define FOPEN_MAX 12
+#endif
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define EOF            -1
+#define SEEK_CUR        0
+#define SEEK_END        1
+#define SEEK_SET        2
+
+
+#define _IOWRITE        (1 << 0)
+#define _IOREAD         (1 << 1)
+#define _IORW           (1 << 2)
+#define _IOEOF          (1 << 3)
+#define _IOERR          (1 << 4)
+#define _IOSTRG         (1 << 5)
+#define _IOTXT          (1 << 6)
+#define _IOFBF          (1 << 7)
+#define _IOLBF          (1 << 8)
+#define _IONBF          (1 << 9)
+#define _IOALLOC        (1 <<10)
+
+typedef struct {
+	int fd;        	        /* file descriptor */
+	unsigned char *buf;     /* pointer to i/o buffer */
+	unsigned char *rp;      /* read pointer */
+	unsigned char *wp;      /* write pointer */
+	unsigned char *lp;      /* write pointer used when line-buffering */
+	size_t len;             /* actual length of buffer */
+	unsigned short flags;
+	unsigned char unbuf[1];  /* tiny buffer for unbuffered io */
+} FILE;
+
+extern FILE __iob[FOPEN_MAX];
+
+#define	stdin	(&__iob[0])
+#define	stdout	(&__iob[1])
+#define	stderr	(&__iob[2])
+
+extern int remove(const char *filename);
+extern int rename(const char *old, const char *new);
+extern FILE *tmpfile(void);
+extern char *tmpnam(char *s);
+extern int fclose(FILE *fp);
+extern int fflush(FILE *fp);
+extern FILE *fopen(const char * restrict fname, const char * restrict mode);
+extern FILE *freopen(const char * restrict fname, const char * restrict mode,
+                     FILE * restrict fp);
+extern void setbuf(FILE * restrict fp, char * restrict buf);
+extern int setvbuf(FILE * restrict fp,
+                   char * restrict buf, int mode, size_t size);
+extern int fprintf(FILE * restrict fp, const char * restrict fmt, ...);
+extern int fscanf(FILE * restrict fp, const char * restrict fmt, ...);
+extern int printf(const char * restrict fmt, ...);
+extern int scanf(const char * restrict fmt, ...);
+extern int snprintf(char * restrict s,
+                    size_t n, const char * restrict fmt, ...);
+extern int sprintf(char * restrict s, const char * restrict fmt, ...);
+extern int sscanf(const char * restrict s, const char * restrict fmt, ...);
+
+#ifdef _STDARG_H
+extern int vfprintf(FILE * restrict fp,
+                    const char * restrict fmt, va_list arg);
+extern int vfscanf(FILE * restrict fp,
+                   const char * restrict fmt, va_list arg);
+extern int vprintf(const char * restrict fmt, va_list arg);
+extern int vscanf(const char * restrict fmt, va_list arg);
+extern int vsnprintf(char * restrict s, size_t n, const char * restrict fmt,
+                     va_list arg);
+extern int vsprintf(char * restrict s,
+                    const char * restrict fmt, va_list arg);
+extern int vsscanf(const char * restrict s,
+                   const char * restrict fmt, va_list arg);
+#endif
+
+extern int fgetc(FILE *fp);
+extern char *fgets(char * restrict s, int n, FILE * restrict fp);
+extern int fputc(int c, FILE *fp);
+extern int fputs(const char * restrict s, FILE * restrict fp);
+extern int getc(FILE *fp);
+extern int getchar(void);
+extern char *gets(char *s);
+extern int putc(int c, FILE *fp);
+extern int putchar(int c);
+extern int puts(const char *s);
+extern int ungetc(int c, FILE *fp);
+extern size_t fread(void * restrict ptr, size_t size, size_t nmemb,
+             FILE * restrict fp);
+extern size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb,
+              FILE * restrict fp);
+extern int fgetpos(FILE * restrict fp, fpos_t * restrict pos);
+extern int fseek(FILE *fp, long int offset, int whence);
+extern int fsetpos(FILE *fp, const fpos_t *pos);
+extern long int ftell(FILE *fp);
+extern void rewind(FILE *fp);
+extern void clearerr(FILE *fp);
+extern int feof(FILE *fp);
+extern int ferror(FILE *fp);
+extern void perror(const char *s);
+
+extern int __getc(FILE *fp);
+extern int __putc(int, FILE *fp);
+
+#ifdef __USE_MACROS
+#ifdef __UNIX_FILES
+#define getc(fp)     ((fp)->rp >= (fp)->wp ?  __getc(fp) : *(fp)->rp++)
+#define putc(c, fp)  ((fp)->wp >= (fp)->rp ? __putc(c,fp) : (*(fp)->wp++ = c))
+#endif
+
+#define ferror(fp)          ((fp)->flags & _IOERR)
+#define feof(fp)            ((fp)->flags & _IOEOF)
+#define clearerr(fp)        (void) ((fp)->flags &= ~(_IOERR|_IOEOF))
+#define getchar()           getc(stdin)
+#define putchar(c)          putc((c), stdout)
+#define setbuf(fp, b)       (void) setvbuf(fp, b, b ? _IOFBF:_IONBF, BUFSIZ)
+#endif
+
+#endif
diff --git a/include/lib/libc/stdlib.h b/include/lib/libc/stdlib.h
new file mode 100644
index 0000000..6aec2b3
--- /dev/null
+++ b/include/lib/libc/stdlib.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+#include <arch/stdlib.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define _ATEXIT_MAX 32
+
+#define MB_CUR_MAX 1
+#define RAND_MAX 32767
+
+typedef struct {
+	int quot, rem;
+} div_t;
+
+typedef struct {
+	long quot, rem;
+} ldiv_t;
+
+typedef struct {
+	long long quot, rem;
+} lldiv_t;
+
+extern double atof(const char *nptr);
+extern int atoi(const char *nptr);
+extern long int atol(const char *nptr);
+extern long long int atoll(const char *nptr);
+extern double strtod(const char * restrict nptr, char ** restrict endptr);
+extern float strtof(const char * restrict nptr, char ** restrict endptr);
+extern long double strtold(const char * restrict nptr, char ** restrict endptr);
+extern long int strtol(const char * restrict nptr, char ** restrict endptr, int base);
+extern long long int strtoll(const char * restrict nptr, char ** restrict endptr,
+                             int base);
+extern unsigned long int strtoul(const char * restrict nptr, char ** restrict endptr,
+                                 int base);
+extern unsigned long long int strtoull(const char * restrict nptr,
+                                       char ** restrict endptr, int base);
+extern int rand(void);
+extern void srand(unsigned int seed);
+extern void *calloc(size_t nmemb, size_t size);
+extern void free(void *ptr);
+extern void *malloc(size_t size);
+extern void *realloc(void *ptr, size_t size);
+extern void abort(void);
+extern int atexit(void (*func)(void));
+extern void exit(int status);
+extern void _Exit(int status);
+extern char *getenv(const char *name);
+extern int system(const char *string);
+extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size,
+                     int (*compar)(const void *, const void *));
+extern void qsort(void *base, size_t nmemb, size_t size,
+                  int (*compar)(const void *, const void *));
+extern int abs(int j);
+extern long int labs(long int j);
+extern long long int llabs(long long int j);
+extern div_t div(int numer, int denom);
+extern ldiv_t ldiv(long int numer, long int denom);
+extern lldiv_t lldiv(long long int numer, long long int denom);
+extern int mblen(const char *s, size_t n);
+extern int mbtowc(wchar_t * restrict pwc, const char * restrict s, size_t n);
+extern int wctomb(char *s, wchar_t wchar);
+extern size_t mbstowcs(wchar_t * restrict pwcs, const char * restrict s, size_t n);
+extern size_t wcstombs(char * restrict s, const wchar_t * restrict pwcs, size_t n);
+
+#ifdef __USE_MACROS
+extern int __abs;
+extern long __labs;
+extern long long __llabs;
+
+#define abs(x)   (__abs = (x), (__abs) < 0 ? -__abs :  __abs)
+#define labs(x)  (__labs = (x), (__labs) < 0 ? -__labs :  __labs)
+#define llabs(x) (__llabs = (x), (__llabs) < 0 ? -__llabs :  __llabs)
+#endif
+
+#endif
diff --git a/include/lib/libc/string.h b/include/lib/libc/string.h
new file mode 100644
index 0000000..72ba769
--- /dev/null
+++ b/include/lib/libc/string.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _STRING_H
+#define _STRING_H
+
+#include <arch/string.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+extern void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
+extern void *memmove(void *s1, const void *s2, size_t n);
+extern char *strcpy(char * restrict s1, const char * restrict s2);
+extern char *strncpy(char * restrict s1, const char * restrict s2, size_t n);
+extern char *strcat(char * restrict s1, const char * restrict s2);
+extern char *strncat(char * restrict s1, const char * restrict s2, size_t n);
+extern int memcmp(const void *s1, const void *s2, size_t n);
+extern int strcmp(const char *s1, const char *s2);
+extern int strcoll(const char *s1, const char *s2);
+extern int strncmp(const char *s1, const char *s2, size_t n);
+extern size_t strxfrm(char * restrict s1, const char * restrict s2, size_t n);
+extern void *memchr(const void *s, int c, size_t n);
+extern char *strchr(const char *s, int c);
+extern size_t strcspn(const char *s1, const char *s2);
+extern char *strpbrk(const char *s1, const char *s2);
+extern char *strrchr(const char *s, int c);
+extern size_t strspn(const char *s1, const char *s2);
+extern char *strstr(const char *s1, const char *s2);
+extern char *strtok(char * restrict s1, const char * restrict s2);
+extern void *memset(void *s, int c, size_t n);
+extern char *strerror(int errnum);
+extern size_t strlen(const char *s);
+
+#endif
diff --git a/include/lib/libc/time.h b/include/lib/libc/time.h
new file mode 100644
index 0000000..846ec21
--- /dev/null
+++ b/include/lib/libc/time.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _TIME_H
+#define _TIME_H
+
+#include <arch/time.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define CLOCKS_PER_SEC 1000000
+
+typedef long int clock_t;
+
+struct tm {
+	int tm_sec;
+	int tm_min;
+	int tm_hour;
+	int tm_mday;
+	int tm_mon;
+	int tm_year;
+	int tm_wday;
+	int tm_yday;
+	int tm_isdst;
+};
+
+extern clock_t clock(void);
+extern double difftime(time_t time1, time_t time0);
+extern time_t mktime(struct tm *timeptr);
+extern time_t time(time_t *timer);
+extern char *asctime(const struct tm *timeptr);
+extern char *ctime(const time_t *timer);
+extern struct tm *gmtime(const time_t *timer);
+extern struct tm *localtime(const time_t *timer);
+extern size_t strftime(char * restrict s, size_t maxsize,
+                       const char * restrict format,
+                       const struct tm * restrict timeptr);
+
+#endif
diff --git a/readme.rst b/readme.rst
index 4897f36..26e1fde 100644
--- a/readme.rst
+++ b/readme.rst
@@ -30,8 +30,9 @@
 This project contains code from other projects as listed below. The original
 license text is included in those source files.
 
--  The stdlib source code is derived from FreeBSD code, which uses various
-   BSD licenses, including BSD-3-Clause and BSD-2-Clause.
+-  The libc source code is derived from `FreeBSD`_ and `SCC`_. FreeBSD uses
+   various BSD licenses, including BSD-3-Clause and BSD-2-Clause. The SCC code
+   is used under the BSD-3-Clause license with the author's permission.
 
 -  The libfdt source code is disjunctively dual licensed
    (GPL-2.0+ OR BSD-2-Clause). It is used by this project under the terms of
@@ -275,3 +276,5 @@
 .. _Change Log: ./docs/change-log.rst
 .. _User Guide: ./docs/user-guide.rst
 .. _Porting Guide: ./docs/porting-guide.rst
+.. _FreeBSD: http://www.freebsd.org
+.. _SCC: http://www.simple-cc.org/