summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2019-01-26 22:41:05 -0500
committerJakob Kaivo <jkk@ung.org>2019-01-26 22:41:05 -0500
commit8c6d4505329f94446084ca93eae10cd796d79a8d (patch)
treec00c6a990c81bd771ebcac72b38fd3ce2382c42e
new framework for building sources after gitlab migration
-rw-r--r--.gitignore5
-rw-r--r--.gitmodules9
-rw-r--r--Makefile90
-rw-r--r--nonstd/FILE.h46
-rw-r--r--nonstd/Makefile10
-rw-r--r--nonstd/__linux.h36
-rw-r--r--nonstd/addefs35
-rw-r--r--nonstd/assert.h67
-rw-r--r--nonstd/generated/confstr.h10
-rw-r--r--nonstd/generated/strerror.h247
-rw-r--r--nonstd/libc.c116
-rw-r--r--nonstd/man.h6
-rw-r--r--nonstd/public/setjmp.h7
-rw-r--r--nonstd/static/fopen.h12
-rw-r--r--nonstd/static/locale.h75
-rw-r--r--nonstd/static/printf.h318
-rw-r--r--nonstd/static/scanf.h7
-rw-r--r--nonstd/static/thread.h5
-rw-r--r--nonstd/static/wctrans.h5
-rw-r--r--nonstd/static/wctype.h15
-rw-r--r--nonstd/stubs/fcntl.h48
-rw-r--r--nonstd/stubs/inttypes.h6
-rw-r--r--nonstd/stubs/sys/mman.h13
-rw-r--r--nonstd/stubs/sys/stat.h0
-rw-r--r--nonstd/stubs/sys/types.h1
-rw-r--r--nonstd/stubs/unistd.h15
-rw-r--r--nonstd/stubs/wchar.h9
-rw-r--r--nonstd/syscall.h38
-rw-r--r--nonstd/tgmath.h31
-rw-r--r--nonstd/types.h117
-rw-r--r--nonstd/x86-32.s18
-rw-r--r--nonstd/x86-64.s19
m---------std/9899-19900
m---------std/POSIX.1-19880
m---------std/POSIX.1-19900
35 files changed, 1436 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..ca140b81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.dep
+.src
+include
+obj
+tags
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..b91aad6b
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,9 @@
+[submodule "9899-1990"]
+ path = std/9899-1990
+ url = git@gitlab.com:ung.org/lib/9899-1990.git
+[submodule "POSIX.1-1988"]
+ path = std/POSIX.1-1988
+ url = git@gitlab.com:ung.org/lib/POSIX.1-1988.git
+[submodule "POSIX.1-1990"]
+ path = std/POSIX.1-1990
+ url = git@gitlab.com:ung.org/lib/POSIX.1-1990.git
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..0e51f79d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,90 @@
+.POSIX:
+
+default: all
+
+#STANDARD=POSIX.1-1990
+STANDARD=9899-1990
+STDDIR=std/$(STANDARD)
+CC=c89
+
+CFLAGS=-g -fno-builtin -nostdinc -nostdlib -nodefaultlibs -Werror -Wall -Wextra -Wno-missing-field-initializers -fPIC -Iinclude -I. -Inonstd/stubs
+
+all: include .dep/$(STANDARD).mk
+ mkdir -p obj
+ $(MAKE) -f .dep/$(STANDARD).mk
+
+include: .dep/$(STANDARD)
+ sed -e 's#std/.[^/]*/##' -e 's#/.[^/]*$$##' .dep/$(STANDARD) | grep -v '.c$$' | sort -u > .dep/headers
+ for i in $$(cat .dep/headers); do $(MAKE) HEADER=$$i $$i; done
+ rm .dep/headers
+
+$(HEADER): include/$(HEADER).h
+
+## special case for assert.h, as it is *not* idempotent
+include/assert.h: std/9899-1990/assert/assert.c
+ head -n19 std/9899-1990/assert/assert.c | tail +3 > $@
+
+include/$(HEADER).h: .dep/$(STANDARD).defs .dep/$(STANDARD).types .dep/$(STANDARD).structs .dep/$(STANDARD).vars .dep/$(STANDARD).funcs
+ mkdir -p $$(dirname $@)
+ printf '#ifndef __%s_H__\n#define __%s_H__\n\n' "$$(echo $(HEADER) | tr a-z/ A-Z_)" "$$(echo $(HEADER) | tr a-z/ A-Z_)" > $@
+ printf '/* backwards compatibility */\n' >> $@
+ printf '#if !defined (__STDC_VERSION__) || (__STDC_VERSION__ < 199009L)\n' >> $@
+ printf '#define restrict\n' >> $@
+ printf '#endif\n' >> $@
+ printf '\n/* macros */\n' >> $@
+ for i in $$(grep '^std/.[^/]*/$(HEADER)/' .dep/$(STANDARD).defs); do sh nonstd/addefs $$i $@; done
+ printf '\n/* types */\n' >> $@
+ for i in $$(grep '^std/.[^/]*/$(HEADER)/' .dep/$(STANDARD).types); do sh nonstd/addefs $$i $@; done
+ printf '\n/* structs */\n' >> $@
+ for i in $$(grep '^std/.[^/]*/$(HEADER)/' .dep/$(STANDARD).structs); do sh nonstd/addefs $$i $@; done
+ printf '\n/* variables */\n' >> $@
+ for i in $$(grep '^std/.[^/]*/$(HEADER)/' .dep/$(STANDARD).vars); do sh nonstd/addefs $$i $@; done
+ printf '\n/* functions */\n' >> $@
+ for i in $$(grep '^std/.[^/]*/$(HEADER)/' .dep/$(STANDARD).funcs); do sh nonstd/addefs $$i $@; done
+ printf '\n#endif\n' >> $@
+
+.dep/$(STANDARD).defs: .dep/$(STANDARD)
+ grep -El '^#(un|)define' $$(cat .dep/$(STANDARD)) > $@
+
+.dep/$(STANDARD).types: .dep/$(STANDARD) .dep/$(STANDARD).defs
+ grep -El '^typedef.*$$' $$(grep -v -f .dep/$(STANDARD).defs .dep/$(STANDARD)) > $@
+
+.dep/$(STANDARD).structs: .dep/$(STANDARD) .dep/$(STANDARD).defs .dep/$(STANDARD).types
+ grep -El '^(struct|union).*{' $$(grep -v -f .dep/$(STANDARD).defs -f .dep/$(STANDARD).types .dep/$(STANDARD)) > $@
+
+.dep/$(STANDARD).vars: .dep/$(STANDARD) .dep/$(STANDARD).defs .dep/$(STANDARD).types .dep/$(STANDARD).structs
+ grep -El '^[a-zA-Z_].*;$$' $$(grep -v -f .dep/$(STANDARD).defs -f .dep/$(STANDARD).types -f .dep/$(STANDARD).structs .dep/$(STANDARD)) > $@
+
+.dep/$(STANDARD).funcs: .dep/$(STANDARD) .dep/$(STANDARD).defs .dep/$(STANDARD).types .dep/$(STANDARD).structs .dep/$(STANDARD).vars
+ grep -El '^[a-zA-Z_].*\)$$' $$(grep -v -f .dep/$(STANDARD).defs -f .dep/$(STANDARD).types -f .dep/$(STANDARD).structs -f .dep/$(STANDARD).vars .dep/$(STANDARD)) > $@
+
+
+.dep/$(STANDARD):
+ -for i in $$(cat $(STDDIR)/INCLUDE); do $(MAKE) STANDARD=$$i .dep/$$i; done
+ mkdir -p .dep
+ -cat .dep/* > $@
+ find $(STDDIR) -name \*.ref >> $@.refs
+ for i in $$(cat $@.refs); do ln -sf $$(grep ^REF $$i | m4 -DREFERENCE=$$(pwd)/std/'$$1') $$(dirname $$i)/$$(basename $$i .ref).c; done
+ find $(STDDIR) -name \*.c >> $@
+ mv $@ $@.tmp
+ sort -u $@.tmp > $@
+ rm $@.tmp
+
+
+
+deps: .dep/$(STANDARD).mk
+
+.dep/$(STANDARD).mk: .dep/$(STANDARD).vars .dep/$(STANDARD).funcs
+ mkdir -p $$(dirname $@)
+ printf 'CC=$(CC)\n' > $@
+ printf 'CFLAGS=$(CFLAGS)\n' >> $@
+ printf 'all: \\\n' >> $@
+ for i in $$(cat .dep/$(STANDARD).vars .dep/$(STANDARD).funcs); do if [ -f $$i ]; then printf '\tobj/%s.o \\\n' "$$(basename $$i .c)" >> $@; fi; done
+ printf '\n' >> $@
+ for i in $$(cat .dep/$(STANDARD).vars .dep/$(STANDARD).funcs); do if [ -f $$i ]; then printf 'obj/%s.o: %s\n\t$$(CC) $$(CFLAGS) -c %s -o $$@\n\n' "$$(basename $$i .c)" "$$i" "$$i" >> $@; fi; done
+
+clean:
+ rm -rf obj
+
+git-clean:
+ rm -rf include .dep
diff --git a/nonstd/FILE.h b/nonstd/FILE.h
new file mode 100644
index 00000000..263fe1ab
--- /dev/null
+++ b/nonstd/FILE.h
@@ -0,0 +1,46 @@
+#ifndef __NONSTD_FILE_H__
+#define __NONSTD_FILE_H__
+
+#include "stdio.h" /* for fpos_t */
+#include "sys/types.h" /* for pid_t */
+
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 199309L
+# define flockfile(x)
+# define ftrylockfile(x)
+# define funlockfile(x)
+#endif
+
+struct __FILE {
+ fpos_t pos;
+ char *buf;
+ enum { SUPPLIED, ALLOCED, UNSET } buftype;
+ int buffering;
+ int bsize;
+ int isopen;
+ int flags;
+ int lastop;
+
+ /* verified necessary */
+ int fd;
+ int oflag;
+ int orientation;
+ int eof;
+ int err;
+ int nlocks;
+ int thread;
+ pid_t pipe_pid;
+
+ struct {
+ char *buf;
+ size_t size;
+ int allocated;
+ } mem;
+
+ struct __FILE *prev;
+ struct __FILE *next;
+};
+
+int getc_unlocked(FILE *);
+int putc_unlocked(FILE *, int);
+
+#endif
diff --git a/nonstd/Makefile b/nonstd/Makefile
new file mode 100644
index 00000000..e1c54e66
--- /dev/null
+++ b/nonstd/Makefile
@@ -0,0 +1,10 @@
+.POSIX:
+
+CFLAGS=-nostdinc -I../include -I.. -Istubs
+
+default: libc.o
+
+libc.o: libc.c
+
+clean:
+ rm -f *.o
diff --git a/nonstd/__linux.h b/nonstd/__linux.h
new file mode 100644
index 00000000..4684b17f
--- /dev/null
+++ b/nonstd/__linux.h
@@ -0,0 +1,36 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef ENOSYS
+#define ENOSYS 62
+#endif
+
+extern long __syscall_x86_64(long, ...);
+#define __linux_syscall __syscall_x86_64
+#define __syscall __linux_syscall
+
+static long __syscall_lookup(const char *call)
+{
+ const char *__syscalls[] = {
+ [0] = "read",
+ [1] = "write",
+ [2] = "open",
+ [3] = "close",
+ [4] = "stat",
+ [5] = "fstat",
+ [6] = "lstat",
+ [9] = "mmap",
+ [60] = "exit",
+ [201] = "time",
+ };
+
+ size_t i;
+ for (i = 0; i < sizeof(__syscalls) / sizeof(__syscalls[0]); i++) {
+ if (__syscalls[i] && !strcmp(__syscalls[i], call)) {
+ return i;
+ }
+ }
+ return -1;
+}
diff --git a/nonstd/addefs b/nonstd/addefs
new file mode 100644
index 00000000..a6a5e2f4
--- /dev/null
+++ b/nonstd/addefs
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+#printf '/* %s */\n' "$1" >> $2
+
+if grep -q '^#define' $1; then
+ grep ' *extern.*;$' $1 >> $2
+ grep -E '^#(if|def|undef|el|end)' $1 >> $2
+
+elif grep -q '^typedef' $1; then
+ if grep -q '^#ifdef' $1; then
+ sed -ne '/#ifdef/,/#endif/p' $1 >> $2
+ elif grep -q '^typedef.*;$' $1; then
+ grep '^typedef' $1 >> $2
+ else
+ sed -ne '/^typedef/,/\}.*;$/p' $1 >> $2
+ fi
+
+elif grep -Eq '^(struct|union).*{$' $1; then
+ if grep -q '^struct' $1; then
+ sed -ne '/^struct/,/\};/p' $1 >> $2
+ else
+ sed -ne '/^union/,/\};/p' $1 >> $2
+ fi
+
+elif grep -q '^[a-zA-Z_].*;$' $1; then
+ printf 'extern %s' "$(grep '^[a-zA-Z_].*;$' $1)" >> $2
+
+elif grep -q 'TGFN' $1; then
+ printf '%s;\n' "$(sed -e "/{/q" $1 | tail -n2 | head -n1 | m4 '-DTGFN=$1' -DTYPE=double)" >> $2
+
+else
+ printf '%s;\n' "$(sed -e "/{/q" $1 | tail -n2 | head -n1)" >> $2
+fi
+
+#printf '\n' >> $2
diff --git a/nonstd/assert.h b/nonstd/assert.h
new file mode 100644
index 00000000..50614d5b
--- /dev/null
+++ b/nonstd/assert.h
@@ -0,0 +1,67 @@
+#ifndef __NONSTD_ASSERT_H__
+#define __NONSTD_ASSERT_H__
+#include "nonstd/types.h"
+
+#define __STDC_WANT_LIB_EXT1__ 1
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+
+typedef int errno_t;
+typedef void (*constraint_handler_t)(const char * restrict msg, void * restrict ptr, errno_t error);
+
+#ifndef EFAULT
+#define EFAULT 10
+#endif
+
+#ifndef NDEBUG
+
+# define ASSERT_NONNULL(_ptr) do { \
+ if (!_ptr) { \
+ struct __constraint_info _ci = {0}; \
+ _ci.func = __func__; \
+ __libc.stdlib.constraint_handler("Undefined behavior: " \
+ "Parameter " #_ptr " can not be NULL", &_ci, EFAULT); \
+ } \
+} while (0)
+
+# define ASSERT_NONZERO(_n) do { \
+ if (!_n) { \
+ struct __constraint_info _ci = {0}; \
+ _ci.func = __func__; \
+ __libc.stdlib.constraint_handler("Undefined behavior: " \
+ "Parameter " #_n " can not be 0", &_ci, ERANGE); \
+ } \
+} while (0)
+
+# define ASSERT_NOOVERLAP(x, y, s) do { \
+ /* TODO */ \
+} while (0)
+
+# define ASSERT_REPRESENTABLE(_n, _min, _max, _type, _sentinel) do { \
+ if (_sentinel && (_n != _sentinel && (_n < _min || _n > _max))) { \
+ struct __constraint_info _ci = {0}; \
+ _ci.func = __func__; \
+ __libc.stdlib.constraint_handler("Undefined behavior: " \
+ "Paramater " #_n " must be representable as a " #_type \
+ "or be equal to " #_sentinel, &_ci, ERANGE); \
+ } else if (_n < _min || _n > _max) { \
+ struct __constraint_info _ci = {0}; \
+ _ci.func = __func__; \
+ __libc.stdlib.constraint_handler("Undefined behavior: " \
+ "Parameter " #_n " must be representable as a " #_type, \
+ &_ci, ERANGE); \
+ } \
+} while (0)
+
+#else
+
+# define ASSERT_NONNULL(x) (void(0))
+# define ASSERT_NOOVERLAP(x, y, s) (void(0))
+# define ASSERT_REPRESENTABLE(n, min, max, type, sentinel) (void(0))
+# define ASSERT_NONZERO(n)
+
+#endif
+
+#endif
diff --git a/nonstd/generated/confstr.h b/nonstd/generated/confstr.h
new file mode 100644
index 00000000..72702d24
--- /dev/null
+++ b/nonstd/generated/confstr.h
@@ -0,0 +1,10 @@
+#ifdef _POSIX_SOURCE
+#include <unistd.h>
+#endif
+
+static const char *confstr[] = {
+ #ifdef _CS_PATH
+ [_CS_PATH] = "/bin",
+ #endif
+ 0
+};
diff --git a/nonstd/generated/strerror.h b/nonstd/generated/strerror.h
new file mode 100644
index 00000000..c5ada8a7
--- /dev/null
+++ b/nonstd/generated/strerror.h
@@ -0,0 +1,247 @@
+#include <errno.h>
+
+static const char *__strerror[] = {
+#ifdef EILSEQ
+ [EILSEQ] = "Illegal sequence / Illegal byte sequence",
+#endif
+#ifdef EDOM
+ [EDOM] = "Domain error: The argument is outside the defined input domain",
+#endif
+#ifdef ERANGE
+ [ERANGE] = "Out of range: The result of the operation is too large or too small",
+#endif
+#ifdef ECANCELED
+ [ECANCELED] = "Operation canceled",
+#endif
+#ifdef ENETRESET
+ [ENETRESET] = "Connection abored by network",
+#endif
+#ifdef ENOTRECOVERABLE
+ [ENOTRECOVERABLE] = "State not recoverable",
+#endif
+#ifdef EOWNERDEAD
+ [EOWNERDEAD] = "Previous owner died",
+#endif
+#ifdef E2BIG
+ [E2BIG] = "Argument list too long",
+#endif
+#ifdef EACCESS
+ [EACCESS] = "Permission denied",
+#endif
+#ifdef EAGAIN
+ [EAGAIN] = "Resource unavailable, try again",
+#endif
+#ifdef EBADF
+ [EBADF] = "Bad file descriptor",
+#endif
+#ifdef EBUSY
+ [EBUSY] = "Device or resource busy",
+#endif
+#ifdef ECHILD
+ [ECHILD] = "No child processes",
+#endif
+#ifdef EDEADLK
+ [EDEADLK] = "Resource deadlock would occur",
+#endif
+#ifdef EEXIST
+ [EEXIST] = "File exists",
+#endif
+#ifdef EFAULT
+ [EFAULT] = "Bad address",
+#endif
+#ifdef EFBIG
+ [EFBIG] = "File too large",
+#endif
+#ifdef EINTR
+ [EINTR] = "Interrupted function",
+#endif
+#ifdef EINVAL
+ [EINVAL] = "Invalid argument",
+#endif
+#ifdef EIO
+ [EIO] = "I/O error",
+#endif
+#ifdef EISDIR
+ [EISDIR] = "Is a directory",
+#endif
+#ifdef EMFILE
+ [EMFILE] = "File descriptor value too large",
+#endif
+#ifdef EMLINK
+ [EMLINK] = "Too many links",
+#endif
+#ifdef ENAMETOOLONG
+ [ENAMETOOLONG] = "Filename too long",
+#endif
+#ifdef ENFILE
+ [ENFILE] = "Too many files open in system",
+#endif
+#ifdef ENODEV
+ [ENODEV] = "No such device",
+#endif
+#ifdef ENOENT
+ [ENOENT] = "No such file or directory",
+#endif
+#ifdef ENOEXEC
+ [ENOEXEC] = "Executable file format error",
+#endif
+#ifdef ENOLCK
+ [ENOLCK] = "No locks available",
+#endif
+#ifdef ENOMEM
+ [ENOMEM] = "Not enough space",
+#endif
+#ifdef ENOSPC
+ [ENOSPC] = "No space left on device",
+#endif
+#ifdef ENOSYS
+ [ENOSYS] = "Function not supported",
+#endif
+#ifdef ENOTDIR
+ [ENOTDIR] = "Not a directory or a symbolic link to a directory",
+#endif
+#ifdef ENOTEMPTY
+ [ENOTEMPTY] = "Directory not empty",
+#endif
+#ifdef ENOTSUP
+ [ENOTSUP] = "Not supported",
+#endif
+#ifdef ENOTTY
+ [ENOTTY] = "Inappropriate I/O control operation",
+#endif
+#ifdef ENXIO
+ [ENXIO] = "No such device or address",
+#endif
+#ifdef EOVERFLOW
+ [EOVERFLOW] = "Value too large to be stored in data type",
+#endif
+#ifdef EPERM
+ [EPERM] = "Operation not permitted",
+#endif
+#ifdef EPIPE
+ [EPIPE] = "Broken pipe",
+#endif
+#ifdef EROFS
+ [EROFS] = "Read-only file system",
+#endif
+#ifdef ESPIPE
+ [ESPIPE] = "Invalid seek",
+#endif
+#ifdef ESRCH
+ [ESRCH] = "No such process",
+#endif
+#ifdef EXDEV
+ [EXDEV] = "Cross-device link",
+#endif
+#ifdef EADDRINUSE
+ [EADDRINUSE] = "Address in use",
+#endif
+#ifdef EADDRNOTAVAIL
+ [EADDRNOTAVAIL] = "Address not available",
+#endif
+#ifdef EAFNOSUPPORT
+ [EAFNOSUPPORT] = "Address family not supported",
+#endif
+#ifdef EALREADY
+ [EALREADY] = "Connection already in progress",
+#endif
+#ifdef EBADMSG
+ [EBADMSG] = "Bad message",
+#endif
+#ifdef ECONNABORTED
+ [ECONNABORTED] = "Connection aborted",
+#endif
+#ifdef ECONNREFUSED
+ [ECONNREFUSED] = "Connection refused",
+#endif
+#ifdef ECONNRESET
+ [ECONNRESET] = "Connection reset",
+#endif
+#ifdef EDESTADDRREQ
+ [EDESTADDRREQ] = "Destination address required",
+#endif
+#ifdef EDQUOT
+ [EDQUOT] = "Reserved",
+#endif
+#ifdef EHOSTUNREACH
+ [EHOSTUNREACH] = "Host is unreachable",
+#endif
+#ifdef EINPROGRESS
+ [EINPROGRESS] = "Operation in progress",
+#endif
+#ifdef EISCONN
+ [EISCONN] = "Socket is connected",
+#endif
+#ifdef ELOOP
+ [ELOOP] = "Too many levels of symbolic links",
+#endif
+#ifdef EMSGSIZE
+ [EMSGSIZE] = "Message too large",
+#endif
+#ifdef EMULTIHOP
+ [EMULTIHOP] = "Reserved",
+#endif
+#ifdef ENETDOWN
+ [ENETDOWN] = "Network is down",
+#endif
+#ifdef ENETUNREACH
+ [ENETUNREACH] = "Network unreachable",
+#endif
+#ifdef ENOBUFS
+ [ENOBUFS] = "No buffer space available",
+#endif
+#ifdef ENODATA
+ [ENODATA] = "No message is available on the STREAM head read queue",
+#endif
+#ifdef ENOLINK
+ [ENOLINK] = "Reserved",
+#endif
+#ifdef ENOMSG
+ [ENOMSG] = "No message of the desired type",
+#endif
+#ifdef ENOPROTOOPT
+ [ENOPROTOOPT] = "Protocol not available",
+#endif
+#ifdef ENOSR
+ [ENOSR] = "No STREAM resources",
+#endif
+#ifdef ENOSTR
+ [ENOSTR] = "Not a STREAM",
+#endif
+#ifdef ENOTCONN
+ [ENOTCONN] = "The socket is not connected",
+#endif
+#ifdef ENOTSOCK
+ [ENOTSOCK] = "Not a socket",
+#endif
+#ifdef EOPNOTSUPP
+ [EOPNOTSUPP] = "Operation not supported on socket",
+#endif
+#ifdef EPROTO
+ [EPROTO] = "Protocol error",
+#endif
+#ifdef EPROTONOSUPPORT
+ [EPROTONOSUPPORT] = "Protocol not supported",
+#endif
+#ifdef EPROTOTYPE
+ [EPROTOTYPE] = "Protocol wrong type for socket",
+#endif
+#ifdef ESTALE
+ [ESTALE] = "Reserved",
+#endif
+#ifdef ETIME
+ [ETIME] = "Stream ioctl() timeout",
+#endif
+#ifdef ETIMEDOUT
+ [ETIMEDOUT] = "Connection timed out",
+#endif
+#ifdef EWOULDBLOCK
+ [EWOULDBLOCK] = "Operation would block",
+#endif
+#ifdef EIDRM
+ [EIDRM] = "Identifier removed",
+#endif
+#ifdef ETXTBSY
+ [ETXTBSY] = "Text file busy",
+#endif
+};
diff --git a/nonstd/libc.c b/nonstd/libc.c
new file mode 100644
index 00000000..766f917f
--- /dev/null
+++ b/nonstd/libc.c
@@ -0,0 +1,116 @@
+#include <stddef.h>
+#include "nonstd/types.h"
+
+#include "nonstd/public/setjmp.h"
+
+#include "nonstd/static/locale.h"
+#include "nonstd/static/thread.h"
+/*
+#include "nonstd/static/wctype.h"
+#include "nonstd/static/wctrans.h"
+*/
+#include "nonstd/static/printf.h"
+#include "nonstd/static/scanf.h"
+#include "nonstd/static/fopen.h"
+
+#include "nonstd/syscall.h"
+
+#include "__linux.h"
+
+/*
+static int __syscall_byname(const char *name, ...)
+{
+ int ret = -1;
+ int sc = __libc.syscall_lookup(name);
+ va_list ap;
+ va_start(ap, name);
+ ret = __libc.syscall_arglist(sc, ap);
+ va_end(ap);
+ return ret;
+}
+
+static int __syscall_bynum(int call, ...)
+{
+ int ret = -1;
+ va_list ap;
+ va_start(ap, call);
+ ret = __libc.syscall_arglist(call, ap);
+ va_end(ap);
+ return ret;
+}
+*/
+
+struct libc __libc = {
+ .ctype = {
+ .ctattr = 0,
+ .ctolower = 1,
+ .ctoupper = 2,
+ .lower = 1 << 1,
+ .punct = 1 << 2,
+ .space = 1 << 3,
+ .upper = 1 << 4,
+ .xdigit = 1 << 5,
+ .getmap = __getmap,
+ },
+ .stdio.printf = __common_printf,
+ .stdio.scanf = __common_scanf,
+ .stdio.fopen = __common_fopen,
+ .stdlib.rand = 1,
+ .stdlib.atexit_max = 32,
+ /*
+ .wctype.wctype = __wctype,
+ .wctype.nwctype = sizeof(__wctype) / sizeof(__wctype[0]),
+ .wctype.wctrans = __wctrans,
+ .wctype.nwctrans = sizeof(__wctrans) / sizeof(__wctrans[0]),
+ .unistd.confstr = confstr,
+ .unistd.nconfstr = sizeof(confstr) / sizeof(confstr[0]),
+ */
+ .syscall_lookup = __syscall_lookup,
+ .syscall = __syscall,
+ /*
+ .syscall_byname = __syscall_byname,
+ .syscall_bynum = __syscall_bynum,
+ .syscall_arglist = __syscall_arglist,
+ */
+ .per_thread = per_thread,
+};
+
+extern int main();
+
+void __libc_start(int argc, char **argv)
+{
+ struct __fopen_options fo = {0};
+ fo.fd = 0;
+ stdin = __libc.stdio.fopen(&fo);
+ fo.fd = 1;
+ stdout = __libc.stdio.fopen(&fo);
+ fo.fd = 2;
+ stderr = __libc.stdio.fopen(&fo);
+ exit(main(argc, argv));
+}
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* TODO: i18n */
+
+void __assert(const char *expr, const char *file, int line, const char *func)
+{
+ if (func) {
+ fprintf(stderr, "Assertion failed: %s (%s:%d:%s())\n", expr,
+ file, line, func);
+ } else {
+ fprintf(stderr, "Assertion failed: %s (%s:%d)\n", expr, file,
+ line);
+ }
+ abort();
+}
+
+int *__errno(void)
+{
+ return &__libc.per_thread()->err;
+}
+
+
+FILE *stdin, *stdout, *stderr;
diff --git a/nonstd/man.h b/nonstd/man.h
new file mode 100644
index 00000000..f6edc35b
--- /dev/null
+++ b/nonstd/man.h
@@ -0,0 +1,6 @@
+#define RETURN_ALWAYS(x, ...)
+#define OBSOLETE(x, ...)
+#define RETURN(x, ...)
+#define RETURN_SUCCESS(x, ...)
+#define RETURN_FAILURE(x, ...)
+#define IMPLEMENTATION(x, ...)
diff --git a/nonstd/public/setjmp.h b/nonstd/public/setjmp.h
new file mode 100644
index 00000000..fb510bdc
--- /dev/null
+++ b/nonstd/public/setjmp.h
@@ -0,0 +1,7 @@
+#include <setjmp.h>
+
+int __setjmp(jmp_buf env)
+{
+ (void)env;
+ return 0;
+}
diff --git a/nonstd/static/fopen.h b/nonstd/static/fopen.h
new file mode 100644
index 00000000..64d30f1e
--- /dev/null
+++ b/nonstd/static/fopen.h
@@ -0,0 +1,12 @@
+#include "nonstd/FILE.h"
+
+static FILE *__common_fopen(struct __fopen_options *opt)
+{
+ FILE *f = NULL;
+ if (__libc.stdio.nopen < FOPEN_MAX) {
+ f = __libc.stdio.files + __libc.stdio.nopen;
+ __libc.stdio.nopen++;
+ }
+ f->fd = opt->fd;
+ return f;
+}
diff --git a/nonstd/static/locale.h b/nonstd/static/locale.h
new file mode 100644
index 00000000..e96b0376
--- /dev/null
+++ b/nonstd/static/locale.h
@@ -0,0 +1,75 @@
+#include <limits.h>
+#include "nonstd/types.h"
+
+#ifndef LC_GLOBAL_LOCALE
+typedef void * locale_t;
+#define LC_GLOBAL_LOCALE ((locale_t)(-1))
+#endif
+
+static unsigned char *__getmap(int map)
+{
+ static unsigned char c_attr[UCHAR_MAX + 1] = {0};
+ static unsigned char c_lower[UCHAR_MAX + 1] = {0};
+ static unsigned char c_upper[UCHAR_MAX + 1] = {0};
+ struct __locale_t c;
+ struct __locale_t *locale = __libc.per_thread()->locale;
+
+ if (!locale || locale == LC_GLOBAL_LOCALE || !locale->ctype) {
+ locale = __libc.locale.global;
+ }
+
+ if (!locale || !locale->ctype) {
+ unsigned char lower[] = "abcdefghijklmnopqrstuvwxyz";
+ unsigned char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ /* $@` are in ASCII but not 9899 */
+ unsigned char punct[] = "!\"#%&'()*+,-./:;<=>?[\\]^_{|}~$@`";
+ unsigned char space[] = " \f\n\r\t\v";
+ unsigned char xdigit[] = "0123456789abcdefABCDEF";
+
+ locale = &c;
+ c.ctattr = c_attr;
+ c.ctolower = c_lower;
+ c.ctoupper = c_upper;
+
+ if (c_attr['a'] == 0) {
+ unsigned int i;
+ for (i = 0; i <= UCHAR_MAX; i++) {
+ c_attr[i] = 0;
+ c_lower[i] = i;
+ c_upper[i] = i;
+ }
+
+ for (i = 0; i < sizeof(lower); i++) {
+ c_attr[lower[i]] = __libc.ctype.lower;
+ c_upper[lower[i]] = upper[i];
+ }
+
+ for (i = 0; i < sizeof(upper); i++) {
+ c_attr[upper[i]] = __libc.ctype.upper;
+ c_lower[upper[i]] = lower[i];
+ }
+
+ for (i = 0; i < sizeof(xdigit); i++) {
+ c_attr[xdigit[i]] |= __libc.ctype.xdigit;
+ }
+
+ for (i = 0; i < sizeof(punct); i++) {
+ c_attr[punct[i]] = __libc.ctype.punct;
+ }
+
+ for (i = 0; i < sizeof(space); i++) {
+ c_attr[space[i]] = __libc.ctype.space;
+ }
+
+ c_attr[0] = 0;
+ }
+ }
+
+ if (map == __libc.ctype.ctolower) {
+ return locale->ctolower;
+ } else if (map == __libc.ctype.ctoupper) {
+ return locale->ctoupper;
+ }
+
+ return locale->ctattr;
+}
diff --git a/nonstd/static/printf.h b/nonstd/static/printf.h
new file mode 100644
index 00000000..9ad3a76d
--- /dev/null
+++ b/nonstd/static/printf.h
@@ -0,0 +1,318 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include "nonstd/types.h"
+
+#include <unistd.h>
+
+#define NUMBUFLEN 64
+
+#define LEFT (1 << 0)
+#define SIGN (1 << 1)
+#define SPACE (1 << 2)
+#define ALT (1 << 3)
+#define ZERO (1 << 4)
+#define UPPER (1 << 5)
+#define UNSIGNED (1 << 6)
+
+/* TODO: remove this */
+uintmax_t strtoumax(const char *s, char **n, int base)
+{
+ (void)base;
+ *n = (char*)s;
+ return 0;
+}
+
+static int __append(char *s, char *argstring, int nout, size_t n)
+{
+ s += nout;
+ while (*argstring) {
+ if (nout < (int)n) {
+ *s++ = *argstring;
+ }
+ nout++;
+ argstring++;
+ }
+ return nout;
+}
+
+static void __itos(char *s, intmax_t n, int flags, int precision, int base)
+{
+ char digits[] = "0123456789abcdef";
+ char sign = n < 0 ? '-' : '+';
+ char buf[NUMBUFLEN];
+ char *out = buf + NUMBUFLEN;
+ if (flags & UPPER && base > 10) {
+ size_t i;
+ for (i = 0; i < sizeof(digits); i++) {
+ digits[i] = (char)toupper(digits[i]);
+ }
+ }
+ *out = '\0';
+ out--;
+ while (n > 0) {
+ precision--;
+ *out = digits[n % base];
+ n /= base;
+ out--;
+ }
+ if (flags & SIGN || sign == '-') {
+ *out = sign;
+ out--;
+ }
+ out++;
+ while ((*s++ = *out++) != 0) {
+ continue;
+ }
+}
+
+static int __common_printf(struct priscn_options *opt,
+ const char * restrict format, va_list arg)
+{
+ char buf[BUFSIZ];
+ int nout = 0;
+ int fd = -1;
+ FILE *f = NULL;
+
+ intmax_t argint = 0;
+ void *argptr = NULL;
+ char numbuf[NUMBUFLEN];
+
+ size_t i;
+ size_t n = 0;
+ char *s = NULL;
+
+ if (opt->stream) {
+ /* file based */
+ f = opt->stream;
+ s = buf;
+ n = BUFSIZ;
+ flockfile(f);
+ } else if (opt->string) {
+ /* memory buffer */
+ s = opt->string;
+ n = opt->maxlen;
+ } else {
+ /* file descriptor */
+ s = buf;
+ n = BUFSIZ;
+ fd = opt->fd;
+ }
+
+ for (i = 0; format[i] != 0; i++) {
+ if (format[i] != '%') {
+ if (nout < (int)n) {
+ s[nout] = format[i];
+ }
+ nout++;
+ continue;
+ }
+
+ /*
+ // zero of more flags "-+ #0"
+ // optional width "*" or decimal integer
+ // optional precision ".*" or ".[decimal]"
+ // optional length modifier "hh", "h", "l", "ll", "j",
+ // "z", "t", "L"
+ // conversion specifier "diouxXfFeEgGaAcspn%"
+ */
+ int flags = 0;
+ /* uintmax_t width = 0; */
+ int step = 0;
+ int precision = 0;
+ int base = 10;
+ enum { def, hh, h, l, ll, j, z, t, L } length = def;
+
+ while (step == 0) {
+ i++;
+ switch (format[i]) {
+ case '-': flags |= LEFT; break;
+ case '+': flags |= SIGN; break;
+ case ' ': flags |= SPACE; break;
+ case '#': flags |= ALT; break;
+ case '0': flags |= ZERO; break;
+ default: step = 1; break;
+ }
+ }
+
+ if (format[i] == '*') {
+ i++;
+ } else if (isdigit(format[i])) {
+ /*
+ char *end;
+ width = strtoumax(format + i, &end, 10);
+ i = end - format;
+ */
+ }
+
+ if (format[i] == '.') {
+ i++;
+ if (format[i] == '*') {
+ i++;
+ } else if (isdigit(format[i])) {
+ char *end;
+ precision = (int)strtoumax(format + i, &end, 10);
+ i = end - format;
+ } else {
+ /* invalid precision */
+ nout = -nout;
+ goto end;
+ }
+ }
+
+ if (format[i] == 'h') {
+ i++;
+ if (format[i] == 'h') {
+ i++;
+ length = hh;
+ } else {
+ length = h;
+ }
+ } else if (format[i] == 'l') {
+ i++;
+ if (format[i] == 'l') {
+ i++;
+ length = ll;
+ } else {
+ length = l;
+ }
+ } else if (format[i] == 'j') {
+ i++;
+ length = j;
+ } else if (format[i] == 'z') {
+ i++;
+ length = z;
+ } else if (format[i] == 't') {
+ i++;
+ length = t;
+ } else if (format[i] == 'L') {
+ i++;
+ length = L;
+ }
+
+ if (isupper(format[i])) {
+ flags |= UPPER;
+ }
+
+ switch (format[i]) {
+ case 'o': /* unsigned int */
+ case 'u':
+ case 'x':
+ case 'X':
+ flags |= UNSIGNED;
+
+ case 'd': /* int */
+ case 'i':
+ switch (length) {
+ case hh: argint = (signed char)va_arg(arg, int); break;
+ case h: argint = (short int)va_arg(arg, int); break;
+ case l: argint = va_arg(arg, long int); break;
+ case ll: argint = va_arg(arg, long long int); break;
+ case j: argint = va_arg(arg, intmax_t); break;
+ case z: argint = va_arg(arg, size_t); break;
+ case t: argint = va_arg(arg, ptrdiff_t); break;
+ case L: nout = -nout; goto end;
+ default: argint = va_arg(arg, int); break;
+ }
+ if (format[i] == 'o') {
+ base = 8;
+ } else if (format[i] == 'x') {
+ base = 16;
+ } else if (format[i] == 'X') {
+ base = 16;
+ flags |= UPPER;
+ } else {
+ base = 10;
+ }
+ __itos(numbuf, (long int)argint, flags, precision, base);
+ nout = __append(s, numbuf, nout, n);
+ break;
+
+
+ case 'f': /* double [-]ddd.ddd */
+ case 'F':
+ break;
+
+ case 'e': /* double [-]d.ddde+/-dd */
+ case 'E':
+ break;
+
+ case 'g': /* double f or e see docs */
+ case 'G':
+ break;
+
+ case 'a': /* double as hex */
+ case 'A':
+ break;
+
+ case 'c': /* char */
+ if (length == def) {
+ char c = va_arg(arg, int);
+ if (nout < (int)n) {
+ s[nout] = c;
+ }
+ nout++;
+ } else if (length == l) {
+ /* wint_t wc = va_arg(arg, wint_t); */
+ /* char mb[MB_CUR_MAX + 1] = "WC"; */
+ /* wctomb(mb, wc); */
+ /* nout = __append(s, mb, nout, n); */
+ } else {
+ nout = -nout;
+ goto end;
+ }
+ break;
+
+ case 's': /* string */
+ if (length == def) {
+ char *string = va_arg(arg, char *);
+ nout = __append(s, string, nout, n);
+ } else if (length == l) {
+ /*wchar_t *ws = va_arg(arg, wchar_t *); */
+ /*char *mbs = malloc(wcslen(ws) * MB_CUR_MAX + 1); */
+ /*wcstombs(mbs, ws, wcslen(ws) * MB_CUR_MAX + 1); */
+ /*nout = __append(s, mbs, nout, n); */
+ /*free(mbs); */
+ nout = __append(s, "WIDE STRING", nout, n);
+ } else {
+ nout = -nout;
+ goto end;
+ }
+
+ break;
+
+ case 'p': /* pointer */
+ argptr = va_arg(arg, void *);
+ nout = __append(s, "0x", nout, n);
+ __itos(numbuf, (intptr_t)argptr, ZERO, sizeof(argptr) * 2, 16);
+ nout = __append(s, numbuf, nout, n);
+ break;
+
+ case 'n': /* write-back */
+ break;
+
+ case '%': /* literal '%' */
+ if (nout < (int)n) {
+ s[nout] = '%';
+ }
+ nout++;
+ break;
+
+ default: /* undefined */
+ return -nout;
+ }
+ }
+
+ end:
+ if (f) {
+ fwrite(buf, 1, nout % BUFSIZ, f);
+ funlockfile(f);
+ } else if (fd != -1) {
+ write(fd, buf, nout % BUFSIZ);
+ }
+
+ return nout;
+}
diff --git a/nonstd/static/scanf.h b/nonstd/static/scanf.h
new file mode 100644
index 00000000..89622951
--- /dev/null
+++ b/nonstd/static/scanf.h
@@ -0,0 +1,7 @@
+#include "nonstd/types.h"
+
+static int __common_scanf(struct priscn_options *opt, const char *format, va_list arg)
+{
+ (void)opt; (void)format; (void)arg;
+ return 0;
+}
diff --git a/nonstd/static/thread.h b/nonstd/static/thread.h
new file mode 100644
index 00000000..00b40861
--- /dev/null
+++ b/nonstd/static/thread.h
@@ -0,0 +1,5 @@
+static struct per_thread *per_thread(void)
+{
+ static struct per_thread pt = {0};
+ return &pt;
+}
diff --git a/nonstd/static/wctrans.h b/nonstd/static/wctrans.h
new file mode 100644
index 00000000..5dcb7608
--- /dev/null
+++ b/nonstd/static/wctrans.h
@@ -0,0 +1,5 @@
+static const char *__wctrans[] = {
+ NULL, /* 0 is an invalid wctrans_t */
+ "tolower",
+ "toupper",
+};
diff --git a/nonstd/static/wctype.h b/nonstd/static/wctype.h
new file mode 100644
index 00000000..e0615096
--- /dev/null
+++ b/nonstd/static/wctype.h
@@ -0,0 +1,15 @@
+static const char *__wctype[] = {
+ 0, /* 0 is an invalid wctype_t */
+ "alnum",
+ "alpha",
+ "blank",
+ "cntrl",
+ "digit",
+ "graph",
+ "lower",
+ "print",
+ "punct",
+ "space",
+ "upper",
+ "xdigit",
+};
diff --git a/nonstd/stubs/fcntl.h b/nonstd/stubs/fcntl.h
new file mode 100644
index 00000000..2c737603
--- /dev/null
+++ b/nonstd/stubs/fcntl.h
@@ -0,0 +1,48 @@
+#ifndef __FCNTL_H__
+#define __FCNTL_H__
+#include "nonstd/types.h"
+
+#define F_DUPFD 1
+#define F_DUPFD_CLOEXEC 2
+#define F_GETFD 3
+#define F_SETFD 4
+#define F_GETFL 5
+#define F_SETFL 6
+#define F_GETLK 7
+#define F_SETLK 8
+#define F_SETLKW 9
+#define F_GETOWN 10
+#define F_SETOWN 11
+
+#define FD_CLOEXEC 1
+
+#define F_RDLCK 1
+#define F_UNLCK 2
+#define F_WRLCK 3
+
+#define O_CLOEXEC 02000000
+#define O_CREAT (1 << 1)
+#define O_DIRECTORY (1 << 2)
+#define O_EXCL (1 << 3)
+#define O_NCTTY (1 << 4)
+#define O_NOFOLLOW (1 << 5)
+#define O_TRUNC (1 << 6)
+#define O_TTY_INIT (1 << 7)
+
+#define O_APPEND (1 << 8)
+#define O_DSYNC (1 << 9)
+#define O_NONBLOCK (1 << 10)
+#define O_RSYNC (1 << 11)
+#define O_SYNC (1 << 12)
+
+#define O_EXEC (1 << 13)
+#define O_RDONLY (1 << 14)
+#define O_RDWR 02
+#define O_SEARCH (1 << 16)
+#define O_WRONLY (1 << 17)
+
+#define O_ACCMODE (O_EXEC|O_RDONLY|O_RDWR|O_SEARCH|O_WRONLY)
+
+#define open(path, mode, flags) __libc.syscall(__libc.syscall_lookup("open"), path, mode, flags)
+
+#endif
diff --git a/nonstd/stubs/inttypes.h b/nonstd/stubs/inttypes.h
new file mode 100644
index 00000000..acaa97af
--- /dev/null
+++ b/nonstd/stubs/inttypes.h
@@ -0,0 +1,6 @@
+#define SIZE_MAX 0xffffffff
+typedef long long int intmax_t;
+typedef unsigned long long int uintmax_t;
+typedef unsigned long int intptr_t;
+intmax_t strtoimax(const char *, char **, int);
+uintmax_t strtoumax(const char *, char **, int);
diff --git a/nonstd/stubs/sys/mman.h b/nonstd/stubs/sys/mman.h
new file mode 100644
index 00000000..01a201eb
--- /dev/null
+++ b/nonstd/stubs/sys/mman.h
@@ -0,0 +1,13 @@
+#include "nonstd/types.h"
+
+#ifndef PROT_READ
+# define PROT_READ 0x1
+#endif
+#ifndef PROT_WRITE
+# define PROT_WRITE 0x2
+#endif
+#ifndef MAP_PRIVATE
+# define MAP_PRIVATE 0x02
+#endif
+
+#define mmap(_a, _l, _p, _f, _d, _o) __libc.syscall(__libc.syscall_lookup("mmap"), _a, _l, _p, _f, _d, _o)
diff --git a/nonstd/stubs/sys/stat.h b/nonstd/stubs/sys/stat.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/nonstd/stubs/sys/stat.h
diff --git a/nonstd/stubs/sys/types.h b/nonstd/stubs/sys/types.h
new file mode 100644
index 00000000..5fe25895
--- /dev/null
+++ b/nonstd/stubs/sys/types.h
@@ -0,0 +1 @@
+typedef int pid_t;
diff --git a/nonstd/stubs/unistd.h b/nonstd/stubs/unistd.h
new file mode 100644
index 00000000..8e16c2e8
--- /dev/null
+++ b/nonstd/stubs/unistd.h
@@ -0,0 +1,15 @@
+#ifndef __UNISTD_H__
+#define __UNISTD_H__
+
+#include <stddef.h>
+#include "nonstd/syscall.h"
+
+#define open(path, mode, flags) __libc.syscall(__libc.syscall_lookup("open"), path, mode, flags)
+#define close(fd) __libc.syscall(__libc.syscall_lookup("close"), fd)
+#define write(fd, buf, nbyte) __libc.syscall(__libc.syscall_lookup("write"), fd, buf, nbyte)
+#define read(fd, buf, nbyte) __libc.syscall(__libc.syscall_lookup("read"), fd, buf, nbyte)
+#define kill(pid, sig) __libc.syscall(__libc.syscall_lookup("kill"), pid, sig)
+#define getpid() __libc.syscall(__libc.syscall_lookup("getpid"))
+#define _exit(status) __libc.syscall(__libc.syscall_lookup("exit"), status)
+
+#endif
diff --git a/nonstd/stubs/wchar.h b/nonstd/stubs/wchar.h
new file mode 100644
index 00000000..0bdc95cb
--- /dev/null
+++ b/nonstd/stubs/wchar.h
@@ -0,0 +1,9 @@
+#include <stddef.h>
+#define WEOF (-1L)
+typedef int mbstate_t;
+typedef int wint_t;
+size_t mbrlen(const char * restrict, size_t, mbstate_t * restrict);
+size_t mbsrtowcs(wchar_t * restrict, const char * restrict, size_t, mbstate_t * restrict);
+size_t mbrtowc(wchar_t * restrict, const char * restrict, size_t, mbstate_t * restrict);
+size_t wcrtomb(char * restrict, wchar_t, mbstate_t * restrict);
+wint_t btowc(int);
diff --git a/nonstd/syscall.h b/nonstd/syscall.h
new file mode 100644
index 00000000..e77ceeaa
--- /dev/null
+++ b/nonstd/syscall.h
@@ -0,0 +1,38 @@
+#ifndef __NONSTD_SYSCALL_H__
+#define __NONSTD_SYSCALL_H__
+
+#include <errno.h>
+#include "nonstd/types.h"
+
+#ifndef ENOSYS
+#define ENOSYS 10
+#endif
+
+#define SCNO(_var, _name, _notfound) static int _var = -2; do { \
+ if ((_var) == -2) { (_var) = __libc.syscall_lookup((_name)); } \
+ if ((_var) == -1) { errno = ENOSYS; return (_notfound); } \
+ } while (0)
+
+#define SCNOFAIL() static int _scno = -2; \
+ if (_scno == -2) { _scno = __libc.syscall_lookup(__func__); } \
+ return __libc.syscall(_scno)
+
+#define SC(_type, ...) static int _scno = -2; \
+ if (_scno == -2) { _scno = __libc.syscall_lookup(__func__); } \
+ _type _ret = __libc.syscall(_scno, __VA_ARGS__); \
+ if (_ret < 0) { \
+ errno = -_ret; \
+ return -1; \
+ } \
+ return _ret
+
+#define SC0(_type) static int _scno = -2; \
+ if (_scno == -2) { _scno = __libc.syscall_lookup(__func__); } \
+ _type __ret = __libc.syscall(_scno); \
+ if (_ret < 0) { \
+ errno = -_ret; \
+ return -1; \
+ } \
+ return _ret
+
+#endif
diff --git a/nonstd/tgmath.h b/nonstd/tgmath.h
new file mode 100644
index 00000000..01533baa
--- /dev/null
+++ b/nonstd/tgmath.h
@@ -0,0 +1,31 @@
+#ifndef __NONSTD_TGMATH_H__
+#define __NONSTD_TGMATH_H__
+#include <math.h>
+
+#ifdef TGSOURCE
+
+# if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+# define TGFN(x) x##f
+# define TYPE float
+# define TGHUGE HUGE_VALF
+# include TGSOURCE
+# undef TGFN
+# undef TYPE
+# undef TGHUGE
+
+# define TGFN(x) x##l
+# define TYPE long double
+# define TGHUGE HUGE_VALL
+# include TGSOURCE
+# undef TGFN
+# undef TYPE
+# undef TGHUGE
+# endif
+
+#endif
+
+#define TGFN(x) x
+#define TYPE double
+#define TGHUGE HUGE_VAL
+
+#endif
diff --git a/nonstd/types.h b/nonstd/types.h
new file mode 100644
index 00000000..0009c967
--- /dev/null
+++ b/nonstd/types.h
@@ -0,0 +1,117 @@
+#ifndef __NONSTD_TYPES_H__
+#define __NONSTD_TYPES_H__
+
+#include <stdio.h> /* for FILE */
+#include <stdarg.h> /* for va_list */
+
+#include "nonstd/FILE.h"
+
+typedef int errno_t;
+typedef void (*constraint_handler_t)(const char * restrict msg, void * restrict ptr, errno_t error);
+
+struct __constraint_info {
+ const char *func;
+};
+
+struct __locale_t {
+ int mask;
+ char *all;
+ char *collate;
+ char *ctype;
+ unsigned char *ctattr;
+ unsigned char *ctoupper;
+ unsigned char *ctolower;
+ char *message;
+ char *monetary;
+ char *numeric;
+ char *time;
+};
+
+struct priscn_options {
+ const char *fnname;
+ char *string;
+ FILE *stream;
+ size_t maxlen;
+ int fd;
+ int flags;
+};
+
+struct __fopen_options {
+ const char *fnname;
+ char *path;
+ int fd;
+ FILE *stream;
+};
+
+struct per_thread {
+ int id;
+ int err;
+ struct __locale_t *locale;
+};
+
+struct libc {
+ const struct {
+ int ctattr;
+ int ctoupper;
+ int ctolower;
+ int lower;
+ int punct;
+ int space;
+ int upper;
+ int xdigit;
+ unsigned char *(*getmap)(int);
+ } ctype;
+ struct {
+ struct __locale_t *global;
+ } locale;
+ struct {
+ FILE files[FOPEN_MAX];
+ FILE *lastfile;
+ int nopen;
+ int (*printf)(struct priscn_options *, const char *, va_list);
+ int (*scanf)(struct priscn_options *, const char *, va_list);
+ FILE *(*fopen)(struct __fopen_options *);
+ } stdio;
+ struct {
+ unsigned int rand;
+ struct atexit {
+ void (*fn)(void);
+ struct atexit *next;
+ struct atexit *prev;
+ } atexit[32], at_quick_exit[32];
+ struct atexit *atexit_tail;
+ struct atexit *at_quick_exit_tail;
+ int atexit_max;
+ int natexit;
+ int nat_quick_exit;
+ constraint_handler_t constraint_handler;
+ } stdlib;
+ struct {
+ const char **wctype;
+ const int nwctype;
+ const char **wctrans;
+ const int nwctrans;
+ } wctype;
+ struct {
+ int nopen;
+ struct fd {
+ int fd;
+ char *name;
+ char *dir;
+ } *fds;
+ const char **confstr;
+ const int nconfstr;
+ } unistd;
+ char* (*atpath)(int fd, const char *path);
+ long (*syscall_lookup)(const char *call);
+ long (*syscall)(long call, ...);
+ /*
+ int (*syscall_bynum)(int call, ...);
+ int (*syscall_byname)(const char *call, ...);
+ int (*syscall_arglist)(int call, va_list arg);
+ */
+ struct per_thread *(*per_thread)(void);
+};
+extern struct libc __libc;
+
+#endif
diff --git a/nonstd/x86-32.s b/nonstd/x86-32.s
new file mode 100644
index 00000000..dd7dbeff
--- /dev/null
+++ b/nonstd/x86-32.s
@@ -0,0 +1,18 @@
+.global __syscall_x86_32
+__syscall_x86_32:
+ mov 4(%esp), %eax
+ mov 8(%esp), %ebx
+ mov 12(%esp), %ecx
+ mov 16(%esp), %edx
+ mov 20(%esp), %esi
+ mov 24(%esp), %edi
+ mov 28(%esp), %ebp
+ sysenter
+ ret
+
+/* FIXME: this seems to be unpossible to put in a shared library */
+/* FIXME: it may be worthwhile to separate this into crt1.s */
+.global _start
+_start:
+ /* TODO */
+ call __libc_start
diff --git a/nonstd/x86-64.s b/nonstd/x86-64.s
new file mode 100644
index 00000000..92d6a2d1
--- /dev/null
+++ b/nonstd/x86-64.s
@@ -0,0 +1,19 @@
+.global __syscall_x86_64
+__syscall_x86_64:
+ mov %rdi, %rax
+ mov %rsi, %rdi
+ mov %rdx, %rsi
+ mov %rcx, %rdx
+ mov %r8, %r10
+ mov %r9, %r8
+ mov 8(%rsp), %r9
+ syscall
+ ret
+
+/* FIXME: this seems to be unpossible to put in a shared library */
+/* FIXME: it may be worthwhile to separate this into crt1.s */
+.global _start
+_start:
+ popq %rdi
+ movq %rsp, %rsi
+ call __libc_start
diff --git a/std/9899-1990 b/std/9899-1990
new file mode 160000
+Subproject b0afc09192e33e33b71102cb527a23d5e86b495
diff --git a/std/POSIX.1-1988 b/std/POSIX.1-1988
new file mode 160000
+Subproject db5ca1f21980781721e93d622eddddf1b07ca65
diff --git a/std/POSIX.1-1990 b/std/POSIX.1-1990
new file mode 160000
+Subproject 1f675ea7b2c93cb7369f55bdab97cbebdeb6d60