diff options
author | Jakob Kaivo <jkk@ung.org> | 2019-01-26 22:41:05 -0500 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2019-01-26 22:41:05 -0500 |
commit | 8c6d4505329f94446084ca93eae10cd796d79a8d (patch) | |
tree | c00c6a990c81bd771ebcac72b38fd3ce2382c42e |
new framework for building sources after gitlab migration
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 |