text:
#include <dirent.h>
#include <errno.h>
#include "__dirent.h"
#include "syscall.h"
#include "libc.h"

int __getdents(int, struct dirent *, size_t);

struct dirent *readdir(DIR *dir)
{
	struct dirent *de;

	if (dir->buf_pos >= dir->buf_end) {
		int len = __syscall(SYS_getdents, dir->fd, dir->buf, sizeof dir->buf);
		if (len <= 0) {
			if (len < 0 && len != -ENOENT) errno = -len;
			return 0;
		}
		dir->buf_end = len;
		dir->buf_pos = 0;
	}
	de = (void *)(dir->buf + dir->buf_pos);
	dir->buf_pos += de->d_reclen;
	dir->tell = de->d_off;
	return de;
}

LFS64(readdir);


text:
#include <dirent.h>
#include <unistd.h>
#include "__dirent.h"
#include "libc.h"

void rewinddir(DIR *dir)
{
	LOCK(dir->lock);
	lseek(dir->fd, 0, SEEK_SET);
	dir->buf_pos = dir->buf_end = 0;
	dir->tell = 0;
	UNLOCK(dir->lock);
}

repo_language: C

mime_type: text/x-c


text:
#define _GNU_SOURCE
#include <string.h>
#include <dirent.h>
#include "libc.h"

int versionsort(const struct dirent **a, const struct dirent **b)
{
	return strverscmp((*a)->d_name, (*b)->d_name);
}

#undef versionsort64
LFS64(versionsort);


text:
#include <string.h>
#include <dirent.h>
#include "libc.h"

int alphasort(const struct dirent **a, const struct dirent **b)
{
	return strcoll((*a)->d_name, (*b)->d_name);
}

LFS64(alphasort);


text:
#define _GNU_SOURCE
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include "__dirent.h"
#include "syscall.h"

DIR *opendir(const char *name)
{
	int fd;
	DIR *dir;

	if ((fd = open(name, O_RDONLY|O_DIRECTORY|O_CLOEXEC)) < 0)
		return 0;
	if (!(dir = calloc(1, sizeof *dir))) {
		__syscall(SYS_close, fd);
		return 0;
	}
	dir->fd = fd;
	return dir;
}


text:
#include <time.h>
#include <pthread.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int getdate_err;

struct tm *getdate(const char *s)
{
	static struct tm tmbuf;
	struct tm *ret = 0;
	char *datemsk = getenv("DATEMSK");
	FILE *f = 0;
	char fmt[100], *p;
	int cs;

	pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, &cs);

	if (!datemsk) {
		getdate_err = 1;
		goto out;
	}

	f = fopen(datemsk, "rbe");
	if (!f) {
		if (errno == ENOMEM) getdate_err = 6;
		else getdate_err = 2;
		goto out;
	}

	while (fgets(fmt, sizeof fmt, f)) {
		p = strptime(s, fmt, &tmbuf);
		if (p && !*p) {
			ret = &tmbuf;
			goto out;
		}
	}

	getdate_err = 7;
out:
	if (f) fclose(f);
	pthread_setcancelstate(cs, 0);
	return ret;
}


text:
#include <utime.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>

int utime(const char *path, const struct utimbuf *times)
{
	return utimensat(AT_FDCWD, path, times ? ((struct timespec [2]){
		{ .tv_sec = times->actime }, { .tv_sec = times->modtime }})
		: 0, 0);
}


text:
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include "syscall.h"

int clock_getcpuclockid(pid_t pid, clockid_t *clk)
{
	struct timespec ts;
	clockid_t id = (-pid-1)*8U + 2;
	int ret = __syscall(SYS_clock_getres, id, &ts);
	if (ret) return -ret;
	*clk = id;
	return 0;
}


text:
#include <time.h>
#include "syscall.h"
#include "libc.h"

int nanosleep(const struct timespec *req, struct timespec *rem)
{
	return syscall_cp(SYS_nanosleep, req, rem);
}


text:
#include <wchar.h>
#include <time.h>
#include <locale.h>
#include "locale_impl.h"
#include "libc.h"

const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc);

size_t __wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, const struct tm *restrict tm, locale_t loc)
{
	size_t l, k;
	char buf[100];
	wchar_t wbuf[100];
	wchar_t *p;
	const char *t_mb;
	const wchar_t *t;
	int plus;
	unsigned long width;
	for (l=0; l<n; f++) {
		if (!*f) {
			s[l] = 0;
			return l;
		}
		if (*f != '%') {
			s[l++] = *f;
			continue;
		}
		f++;
		if ((plus = (*f == '+'))) f++;
		width = wcstoul(f, &p, 10);
		if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') {
			if (!width && p!=f) width = 1;
		} else {
			width = 0;
		}
		f = p;
		if (*f == 'E' || *f == 'O') f++;
		t_mb = __strftime_fmt_1(&buf, &k, *f, tm, loc);
		if (!t_mb) break;
		k = mbstowcs(wbuf, t_mb, sizeof wbuf / sizeof *wbuf);
		if (k == (size_t)-1) return 0;
		t = wbuf;
		if (width) {
			for (; *t=='+' || *t=='-' || (*t=='0'&&t[1]); t++, k--);
			width--;
			if (plus && tm->tm_year >= 10000-1900)
				s[l++] = '+';
			else if (tm->tm_year < -1900)
				s[l++] = '-';
			else
				width++;
			for (; width > k && l < n; width--)
				s[l++] = '0';
		}
		if (k >= n-l) k = n-l;
		wmemcpy(s+l, t, k);
		l += k;
	}
	if (n) {
		if (l==n) l=n-1;
		s[l] = 0;
	}
	return 0;
}

size_t wcsftime(wchar_t *restrict wcs, size_t n, const wchar_t *restrict f, const struct tm *restrict tm)
{
	return __wcsftime_l(wcs, n, f, tm, CURRENT_LOCALE);
}

weak_alias(__wcsftime_l, wcsftime_l);


text:
#include <time.h>

char *ctime(const time_t *t)
{
	return asctime(localtime(t));
}


text:
#include <time.h>

int __clock_gettime(clockid_t, struct timespec *);

/* There is no other implemented value than TIME_UTC; all other values
 * are considered erroneous. */
int timespec_get(struct timespec * ts, int base)
{
	if (base != TIME_UTC) return 0;
	int ret = __clock_gettime(CLOCK_REALTIME, ts);
	return ret < 0 ? 0 : base;
}


text:
#include <time.h>
#include <setjmp.h>
#include "pthread_impl.h"

struct ksigevent {
	union sigval sigev_value;
	int sigev_signo;
	int sigev_notify;
	int sigev_tid;
};

struct start_args {
	pthread_barrier_t b;
	struct sigevent *sev;
};

static void dummy_1(pthread_t self)
{
}
weak_alias(dummy_1, __pthread_tsd_run_dtors);

void __reset_tls();

static void cleanup_fromsig(void *p)
{
	pthread_t self = __pthread_self();
	__pthread_tsd_run_dtors(self);
	self->cancel = 0;
	self->cancelbuf = 0;
	self->canceldisable = 0;
	self->cancelasync = 0;
	self->unblock_cancel = 0;
	__reset_tls();
	longjmp(p, 1);
}

static void timer_handler(int sig, siginfo_t *si, void *ctx)
{
	pthread_t self = __pthread_self();
	jmp_buf jb;
	void (*notify)(union sigval) = (void (*)(union sigval))self->start;
	union sigval val = { .sival_ptr = self->start_arg };

	if (!setjmp(jb) && si->si_code == SI_TIMER) {
		pthread_cleanup_push(cleanup_fromsig, jb);
		notify(val);
		pthread_cleanup_pop(1);
	}
}

static void install_handler()
{
	struct sigaction sa = {
		.sa_sigaction = timer_handler,
		.sa_flags = SA_SIGINFO | SA_RESTART
	};
	__libc_sigaction(SIGTIMER, &sa, 0);
}

static void *start(void *arg)
{
	pthread_t self = __pthread_self();
	struct start_args *args = arg;
	int id;

	/* Reuse no-longer-needed thread structure fields to avoid
	 * needing the timer address in the signal handler. */
	self->start = (void *(*)(void *))args->sev->sigev_notify_function;
	self->start_arg = args->sev->sigev_value.sival_ptr;

	pthread_barrier_wait(&args->b);
	if ((id = self->timer_id) >= 0) {
		__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
			SIGTIMER_SET, 0, _NSIG/8);
		__wait(&self->timer_id, 0, id, 1);
		__syscall(SYS_timer_delete, id);
	}
	return 0;
}

int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict res)
{
	static pthread_once_t once = PTHREAD_ONCE_INIT;
	pthread_t td;
	pthread_attr_t attr;
	int r;
	struct start_args args;
	struct ksigevent ksev, *ksevp=0;
	int timerid;
	sigset_t set;

	switch (evp ? evp->sigev_notify : SIGEV_SIGNAL) {
	case SIGEV_NONE:
	case SIGEV_SIGNAL:
		if (evp) {
			ksev.sigev_value = evp->sigev_value;
			ksev.sigev_signo = evp->sigev_signo;
			ksev.sigev_notify = evp->sigev_notify;
			ksev.sigev_tid = 0;
			ksevp = &ksev;
		}
		if (syscall(SYS_timer_create, clk, ksevp, &timerid) < 0)
			return -1;
		*res = (void *)(intptr_t)timerid;
		break;
	case SIGEV_THREAD:
		pthread_once(&once, install_handler);
		if (evp->sigev_notify_attributes)
			attr = *evp->sigev_notify_attributes;
		else
			pthread_attr_init(&attr);
		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
		pthread_barrier_init(&args.b, 0, 2);
		args.sev = evp;

		__block_app_sigs(&set);
		r = pthread_create(&td, &attr, start, &args);
		__restore_sigs(&set);
		if (r) {
			errno = r;
			return -1;
		}

		ksev.sigev_value.sival_ptr = 0;
		ksev.sigev_signo = SIGTIMER;
		ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */
		ksev.sigev_tid = td->tid;
		if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
			timerid = -1;
		td->timer_id = timerid;
		pthread_barrier_wait(&args.b);
		if (timerid < 0) return -1;
		*res = (void *)(INTPTR_MIN | (uintptr_t)td>>1);
		break;
	default:
		errno = EINVAL;
		return -1;
	}

	return 0;
}


text:
#include <time.h>

double difftime(time_t t1, time_t t0)
{
	return t1-t0;
}


text:
#include <time.h>
#include <limits.h>
#include "pthread_impl.h"

int timer_settime(timer_t t, int flags, const struct itimerspec *restrict val, struct itimerspec *restrict old)
{
	if ((intptr_t)t < 0) {
		pthread_t td = (void *)((uintptr_t)t << 1);
		t = (void *)(uintptr_t)(td->timer_id & INT_MAX);
	}
	return syscall(SYS_timer_settime, t, flags, val, old);
}


text:
#include "time_impl.h"

long long __tm_to_secs(const struct tm *tm)
{
	int is_leap;
	long long year = tm->tm_year;
	int month = tm->tm_mon;
	if (month >= 12 || month < 0) {
		int adj = month / 12;
		month %= 12;
		if (month < 0) {
			adj--;
			month += 12;
		}
		year += adj;
	}
	long long t = __year_to_secs(year, &is_leap);
	t += __month_to_secs(month, is_leap);
	t += 86400LL * (tm->tm_mday-1);
	t += 3600LL * tm->tm_hour;
	t += 60LL * tm->tm_min;
	t += tm->tm_sec;
	return t;
}


text:
#include "time_impl.h"

struct tm *__localtime_r(const time_t *restrict, struct tm *restrict);

struct tm *localtime(const time_t *t)
{
	static struct tm tm;
	return __localtime_r(t, &tm);
}


text:
#include <time.h>
#include "syscall.h"

int clock_settime(clockid_t clk, const struct timespec *ts)
{
	return syscall(SYS_clock_settime, clk, ts);
}


text:
#include "time_impl.h"
#include <errno.h>

struct tm *__gmtime_r(const time_t *restrict, struct tm *restrict);

struct tm *gmtime(const time_t *t)
{
	static struct tm tm;
	return __gmtime_r(t, &tm);
}


text:
#include <time.h>
#include "syscall.h"

int __clock_gettime(clockid_t, struct timespec *);

time_t time(time_t *t)
{
	struct timespec ts;
	__clock_gettime(CLOCK_REALTIME, &ts);
	if (t) *t = ts.tv_sec;
	return ts.tv_sec;
}


text:
#include <sys/timeb.h>
#include <time.h>

int ftime(struct timeb *tp)
{
	struct timespec ts;
	clock_gettime(CLOCK_REALTIME, &ts);
	tp->time = ts.tv_sec;
	tp->millitm = ts.tv_nsec / 1000000;
	tp->timezone = tp->dstflag = 0;
	return 0;
}


text:
#include "time_impl.h"
#include <errno.h>
#include "libc.h"

extern const char __gmt[];

struct tm *__gmtime_r(const time_t *restrict t, struct tm *restrict tm)
{
	if (__secs_to_tm(*t, tm) < 0) {
		errno = EOVERFLOW;
		return 0;
	}
	tm->tm_isdst = 0;
	tm->__tm_gmtoff = 0;
	tm->__tm_zone = __gmt;
	return tm;
}

weak_alias(__gmtime_r, gmtime_r);


text:
#include <time.h>

char *__asctime(const struct tm *restrict, char *restrict);

char *asctime_r(const struct tm *restrict tm, char *restrict buf)
{
	return __asctime(tm, buf);
}


text:
#include "time_impl.h"
#include <errno.h>
#include "libc.h"

struct tm *__localtime_r(const time_t *restrict t, struct tm *restrict tm)
{
	/* Reject time_t values whose year would overflow int because
	 * __secs_to_zone cannot safely handle them. */
	if (*t < INT_MIN * 31622400LL || *t > INT_MAX * 31622400LL) {
		errno = EOVERFLOW;
		return 0;
	}
	__secs_to_zone(*t, 0, &tm->tm_isdst, &tm->__tm_gmtoff, 0, &tm->__tm_zone);
	if (__secs_to_tm((long long)*t - tm->__tm_gmtoff, tm) < 0) {
		errno = EOVERFLOW;
		return 0;
	}
	return tm;
}

weak_alias(__localtime_r, localtime_r);


text:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <langinfo.h>
#include <locale.h>
#include <time.h>
#include <limits.h>
#include "locale_impl.h"
#include "libc.h"
#include "time_impl.h"

const char *__nl_langinfo_l(nl_item, locale_t);

static int is_leap(int y)
{
	/* Avoid overflow */
	if (y>INT_MAX-1900) y -= 2000;
	y += 1900;
	return !(y%4) && ((y%100) || !(y%400));
}

static int week_num(const struct tm *tm)
{
	int val = (tm->tm_yday + 7 - (tm->tm_wday+6)%7) / 7;
	/* If 1 Jan is just 1-3 days past Monday,
	 * the previous week is also in this year. */
	if ((tm->tm_wday - tm->tm_yday - 2 + 371) % 7 <= 2)
		val++;
	if (!val) {
		val = 52;
		/* If 31 December of prev year a Thursday,
		 * or Friday of a leap year, then the
		 * prev year has 53 weeks. */
		int dec31 = (tm->tm_wday - tm->tm_yday - 1 + 7) % 7;
		if (dec31 == 4 || (dec31 == 5 && is_leap(tm->tm_year%400-1)))
			val++;
	} else if (val == 53) {
		/* If 1 January is not a Thursday, and not
		 * a Wednesday of a leap year, then this
		 * year has only 52 weeks. */
		int jan1 = (tm->tm_wday - tm->tm_yday + 371) % 7;
		if (jan1 != 4 && (jan1 != 3 || !is_leap(tm->tm_year)))
			val = 1;
	}
	return val;
}

const char *__tm_to_tzname(const struct tm *);
size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);

const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc)
{
	nl_item item;
	long long val;
	const char *fmt;
	int width = 2;

	switch (f) {
	case 'a':
		item = ABDAY_1 + tm->tm_wday;
		goto nl_strcat;
	case 'A':
		item = DAY_1 + tm->tm_wday;
		goto nl_strcat;
	case 'h':
	case 'b':
		item = ABMON_1 + tm->tm_mon;
		goto nl_strcat;
	case 'B':
		item = MON_1 + tm->tm_mon;
		goto nl_strcat;
	case 'c':
		item = D_T_FMT;
		goto nl_strftime;
	case 'C':
		val = (1900LL+tm->tm_year) / 100;
		goto number;
	case 'd':
		val = tm->tm_mday;
		goto number;
	case 'D':
		fmt = "%m/%d/%y";
		goto recu_strftime;
	case 'e':
		*l = snprintf(*s, sizeof *s, "%2d", tm->tm_mday);
		return *s;
	case 'F':
		fmt = "%Y-%m-%d";
		goto recu_strftime;
	case 'g':
	case 'G':
		val = tm->tm_year + 1900LL;
		if (tm->tm_yday < 3 && week_num(tm) != 1) val--;
		else if (tm->tm_yday > 360 && week_num(tm) == 1) val++;
		if (f=='g') val %= 100;
		else width = 4;
		goto number;
	case 'H':
		val = tm->tm_hour;
		goto number;
	case 'I':
		val = tm->tm_hour;
		if (!val) val = 12;
		else if (val > 12) val -= 12;
		goto number;
	case 'j':
		val = tm->tm_yday+1;
		width = 3;
		goto number;
	case 'm':
		val = tm->tm_mon+1;
		goto number;
	case 'M':
		val = tm->tm_min;
		goto number;
	case 'n':
		*l = 1;
		return "\n";
	case 'p':
		item = tm->tm_hour >= 12 ? PM_STR : AM_STR;
		goto nl_strcat;
	case 'r':
		item = T_FMT_AMPM;
		goto nl_strftime;
	case 'R':
		fmt = "%H:%M";
		goto recu_strftime;
	case 's':
		val = __tm_to_secs(tm) + tm->__tm_gmtoff;
		width = 1;
		goto number;
	case 'S':
		val = tm->tm_sec;
		goto number;
	case 't':
		*l = 1;
		return "\t";
	case 'T':
		fmt = "%H:%M:%S";
		goto recu_strftime;
	case 'u':
		val = tm->tm_wday ? tm->tm_wday : 7;
		width = 1;
		goto number;
	case 'U':
		val = (tm->tm_yday + 7 - tm->tm_wday) / 7;
		goto number;
	case 'W':
		val = (tm->tm_yday + 7 - (tm->tm_wday+6)%7) / 7;
		goto number;
	case 'V':
		val = week_num(tm);
		goto number;
	case 'w':
		val = tm->tm_wday;
		width = 1;
		goto number;
	case 'x':
		item = D_FMT;
		goto nl_strftime;
	case 'X':
		item = T_FMT;
		goto nl_strftime;
	case 'y':
		val = tm->tm_year % 100;
		goto number;
	case 'Y':
		val = tm->tm_year + 1900;
		if (val >= 10000) {
			*l = snprintf(*s, sizeof *s, "+%lld", val);
			return *s;
		}
		width = 4;
		goto number;
	case 'z':
		if (tm->tm_isdst < 0) {
			*l = 0;
			return "";
		}
		*l = snprintf(*s, sizeof *s, "%+.2d%.2d",
			(-tm->__tm_gmtoff)/3600,
			abs(tm->__tm_gmtoff%3600)/60);
		return *s;
	case 'Z':
		if (tm->tm_isdst < 0) {
			*l = 0;
			return "";
		}
		fmt = __tm_to_tzname(tm);
		goto string;
	case '%':
		*l = 1;
		return "%";
	default:
		return 0;
	}
number:
	*l = snprintf(*s, sizeof *s, "%0*lld", width, val);
	return *s;
nl_strcat:
	fmt = __nl_langinfo_l(item, loc);
string:
	*l = strlen(fmt);
	return fmt;
nl_strftime:
	fmt = __nl_langinfo_l(item, loc);
recu_strftime:
	*l = __strftime_l(*s, sizeof *s, fmt, tm, loc);
	if (!*l) return 0;
	return *s;
}

size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm, locale_t loc)
{
	size_t l, k;
	char buf[100];
	char *p;
	const char *t;
	int plus;
	unsigned long width;
	for (l=0; l<n; f++) {
		if (!*f) {
			s[l] = 0;
			return l;
		}
		if (*f != '%') {
			s[l++] = *f;
			continue;
		}
		f++;
		if ((plus = (*f == '+'))) f++;
		width = strtoul(f, &p, 10);
		if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') {
			if (!width && p!=f) width = 1;
		} else {
			width = 0;
		}
		f = p;
		if (*f == 'E' || *f == 'O') f++;
		t = __strftime_fmt_1(&buf, &k, *f, tm, loc);
		if (!t) break;
		if (width) {
			for (; *t=='+' || *t=='-' || (*t=='0'&&t[1]); t++, k--);
			width--;
			if (plus && tm->tm_year >= 10000-1900)
				s[l++] = '+';
			else if (tm->tm_year < -1900)
				s[l++] = '-';
			else
				width++;
			for (; width > k && l < n; width--)
				s[l++] = '0';
		}
		if (k > n-l) k = n-l;
		memcpy(s+l, t, k);
		l += k;
	}
	if (n) {
		if (l==n) l=n-1;
		s[l] = 0;
	}
	return 0;
}

size_t strftime(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm)
{
	return __strftime_l(s, n, f, tm, CURRENT_LOCALE);
}

weak_alias(__strftime_l, strftime_l);


text:
#include "time_impl.h"
#include <limits.h>

/* 2000-03-01 (mod 400 year, immediately after feb29 */
#define LEAPOCH (946684800LL + 86400*(31+29))

#define DAYS_PER_400Y (365*400 + 97)
#define DAYS_PER_100Y (365*100 + 24)
#define DAYS_PER_4Y   (365*4   + 1)

int __secs_to_tm(long long t, struct tm *tm)
{
	long long days, secs;
	int remdays, remsecs, remyears;
	int qc_cycles, c_cycles, q_cycles;
	int years, months;
	int wday, yday, leap;
	static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29};

	/* Reject time_t values whose year would overflow int */
	if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL)
		return -1;

	secs = t - LEAPOCH;
	days = secs / 86400;
	remsecs = secs % 86400;
	if (remsecs < 0) {
		remsecs += 86400;
		days--;
	}

	wday = (3+days)%7;
	if (wday < 0) wday += 7;

	qc_cycles = days / DAYS_PER_400Y;
	remdays = days % DAYS_PER_400Y;
	if (remdays < 0) {
		remdays += DAYS_PER_400Y;
		qc_cycles--;
	}

	c_cycles = remdays / DAYS_PER_100Y;
	if (c_cycles == 4) c_cycles--;
	remdays -= c_cycles * DAYS_PER_100Y;

	q_cycles = remdays / DAYS_PER_4Y;
	if (q_cycles == 25) q_cycles--;
	remdays -= q_cycles * DAYS_PER_4Y;

	remyears = remdays / 365;
	if (remyears == 4) remyears--;
	remdays -= remyears * 365;

	leap = !remyears && (q_cycles || !c_cycles);
	yday = remdays + 31 + 28 + leap;
	if (yday >= 365+leap) yday -= 365+leap;

	years = remyears + 4*q_cycles + 100*c_cycles + 400*qc_cycles;

	for (months=0; days_in_month[months] <= remdays; months++)
		remdays -= days_in_month[months];

	if (years+100 > INT_MAX || years+100 < INT_MIN)
		return -1;

	tm->tm_year = years + 100;
	tm->tm_mon = months + 2;
	if (tm->tm_mon >= 12) {
		tm->tm_mon -=12;
		tm->tm_year++;
	}
	tm->tm_mday = remdays + 1;
	tm->tm_wday = wday;
	tm->tm_yday = yday;

	tm->tm_hour = remsecs / 3600;
	tm->tm_min = remsecs / 60 % 60;
	tm->tm_sec = remsecs % 60;

	return 0;
}


text:
#define _GNU_SOURCE
#include "time_impl.h"
#include <errno.h>

extern const char __gmt[];

time_t timegm(struct tm *tm)
{
	struct tm new;
	long long t = __tm_to_secs(tm);
	if (__secs_to_tm(t, &new) < 0) {
		errno = EOVERFLOW;
		return -1;
	}
	*tm = new;
	tm->tm_isdst = 0;
	tm->__tm_gmtoff = 0;
	tm->__tm_zone = __gmt;
	return t;
}


text:
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "syscall.h"

void *__mmap(void *, size_t, int, int, int, off_t);

const char unsigned *__map_file(const char *pathname, size_t *size)
{
	struct stat st;
	const unsigned char *map = MAP_FAILED;
	int fd = __sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
	if (fd < 0) return 0;
	if (!__syscall(SYS_fstat, fd, &st))
		map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
	__syscall(SYS_close, fd);
	*size = st.st_size;
	return map == MAP_FAILED ? 0 : map;
}


text:
#include <time.h>
#include <sys/time.h>
#include "syscall.h"

int gettimeofday(struct timeval *restrict tv, void *restrict tz)
{
	struct timespec ts;
	if (!tv) return 0;
	clock_gettime(CLOCK_REALTIME, &ts);
	tv->tv_sec = ts.tv_sec;
	tv->tv_usec = (int)ts.tv_nsec / 1000;
	return 0;
}


text:
#include <time.h>
#include <limits.h>
#include "pthread_impl.h"

int timer_getoverrun(timer_t t)
{
	if ((intptr_t)t < 0) {
		pthread_t td = (void *)((uintptr_t)t << 1);
		t = (void *)(uintptr_t)(td->timer_id & INT_MAX);
	}
	return syscall(SYS_timer_getoverrun, t);
}


text:
#include <time.h>
#include "syscall.h"

int clock_getres(clockid_t clk, struct timespec *ts)
{
	return syscall(SYS_clock_getres, clk, ts);
}


text:
long long __year_to_secs(long long year, int *is_leap)
{
	if (year-2ULL <= 136) {
		int y = year;
		int leaps = (y-68)>>2;
		if (!((y-68)&3)) {
			leaps--;
			if (is_leap) *is_leap = 1;
		} else if (is_leap) *is_leap = 0;
		return 31536000*(y-70) + 86400*leaps;
	}

	int cycles, centuries, leaps, rem;

	if (!is_leap) is_leap = &(int){0};
	cycles = (year-100) / 400;
	rem = (year-100) % 400;
	if (rem < 0) {
		cycles--;
		rem += 400;
	}
	if (!rem) {
		*is_leap = 1;
		centuries = 0;
		leaps = 0;
	} else {
		if (rem >= 200) {
			if (rem >= 300) centuries = 3, rem -= 300;
			else centuries = 2, rem -= 200;
		} else {
			if (rem >= 100) centuries = 1, rem -= 100;
			else centuries = 0;
		}
		if (!rem) {
			*is_leap = 0;
			leaps = 0;
		} else {
			leaps = rem / 4U;
			rem %= 4U;
			*is_leap = !rem;
		}
	}

	leaps += 97*cycles + 24*centuries - *is_leap;

	return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
}


text:
#include <time.h>
#include <limits.h>
#include "pthread_impl.h"

int timer_delete(timer_t t)
{
	if ((intptr_t)t < 0) {
		pthread_t td = (void *)((uintptr_t)t << 1);
		a_store(&td->timer_id, td->timer_id | INT_MIN);
		__wake(&td->timer_id, 1, 1);
		return 0;
	}
	return __syscall(SYS_timer_delete, t);
}


text:
#include <time.h>
#include <limits.h>

int __clock_gettime(clockid_t, struct timespec *);

clock_t clock()
{
	struct timespec ts;

	if (__clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts))
		return -1;

	if (ts.tv_sec > LONG_MAX/1000000
	 || ts.tv_nsec/1000 > LONG_MAX-1000000*ts.tv_sec)
		return -1;

	return ts.tv_sec*1000000 + ts.tv_nsec/1000;
}


text:
#include <sys/times.h>
#include "syscall.h"

clock_t times(struct tms *tms)
{
	return __syscall(SYS_times, tms);
}


text:
#include <stdlib.h>
#include <langinfo.h>
#include <time.h>
#include <ctype.h>
#include <stddef.h>
#include <string.h>
#include <strings.h>

char *strptime(const char *restrict s, const char *restrict f, struct tm *restrict tm)
{
	int i, w, neg, adj, min, range, *dest, dummy;
	const char *ex;
	size_t len;
	int want_century = 0, century = 0;
	while (*f) {
		if (*f != '%') {
			if (isspace(*f)) for (; *s && isspace(*s); s++);
			else if (*s != *f) return 0;
			else s++;
			f++;
			continue;
		}
		f++;
		if (*f == '+') f++;
		if (isdigit(*f)) w=strtoul(f, (void *)&f, 10);
		else w=-1;
		adj=0;
		switch (*f++) {
		case 'a': case 'A':
			dest = &tm->tm_wday;
			min = ABDAY_1;
			range = 7;
			goto symbolic_range;
		case 'b': case 'B': case 'h':
			dest = &tm->tm_mon;
			min = ABMON_1;
			range = 12;
			goto symbolic_range;
		case 'c':
			s = strptime(s, nl_langinfo(D_T_FMT), tm);
			if (!s) return 0;
			break;
		case 'C':
			dest = &century;
			if (w<0) w=2;
			want_century |= 2;
			goto numeric_digits;
		case 'd': case 'e':
			dest = &tm->tm_mday;
			min = 1;
			range = 31;
			goto numeric_range;
		case 'D':
			s = strptime(s, "%m/%d/%y", tm);
			if (!s) return 0;
			break;
		case 'H':
			dest = &tm->tm_hour;
			min = 0;
			range = 24;
			goto numeric_range;
		case 'I':
			dest = &tm->tm_hour;
			min = 1;
			range = 12;
			goto numeric_range;
		case 'j':
			dest = &tm->tm_yday;
			min = 1;
			range = 366;
			goto numeric_range;
		case 'm':
			dest = &tm->tm_mon;
			min = 1;
			range = 12;
			adj = 1;
			goto numeric_range;
		case 'M':
			dest = &tm->tm_min;
			min = 0;
			range = 60;
			goto numeric_range;
		case 'n': case 't':
			for (; *s && isspace(*s); s++);
			break;
		case 'p':
			ex = nl_langinfo(AM_STR);
			len = strlen(ex);
			if (!strncasecmp(s, ex, len)) {
				tm->tm_hour %= 12;
				break;
			}
			ex = nl_langinfo(PM_STR);
			len = strlen(ex);
			if (!strncasecmp(s, ex, len)) {
				tm->tm_hour %= 12;
				tm->tm_hour += 12;
				break;
			}
			return 0;
		case 'r':
			s = strptime(s, nl_langinfo(T_FMT_AMPM), tm);
			if (!s) return 0;
			break;
		case 'R':
			s = strptime(s, "%H:%M", tm);
			if (!s) return 0;
			break;
		case 'S':
			dest = &tm->tm_sec;
			min = 0;
			range = 61;
			goto numeric_range;
		case 'T':
			s = strptime(s, "%H:%M:%S", tm);
			if (!s) return 0;
			break;
		case 'U':
		case 'W':
			/* Throw away result, for now. (FIXME?) */
			dest = &dummy;
			min = 0;
			range = 54;
			goto numeric_range;
		case 'w':
			dest = &tm->tm_wday;
			min = 0;
			range = 7;
			goto numeric_range;
		case 'x':
			s = strptime(s, nl_langinfo(D_FMT), tm);
			if (!s) return 0;
			break;
		case 'X':
			s = strptime(s, nl_langinfo(T_FMT), tm);
			if (!s) return 0;
			break;
		case 'y':
			dest = &tm->tm_year;
			w = 2;
			want_century |= 1;
			goto numeric_digits;
		case 'Y':
			dest = &tm->tm_year;
			if (w<0) w=4;
			adj = 1900;
			want_century = 0;
			goto numeric_digits;
		case '%':
			if (*s++ != '%') return 0;
			break;
		default:
			return 0;
		numeric_range:
			if (!isdigit(*s)) return 0;
			*dest = 0;
			for (i=1; i<=min+range && isdigit(*s); i*=10)
				*dest = *dest * 10 + *s++ - '0';
			if (*dest - min >= (unsigned)range) return 0;
			*dest -= adj;
			switch((char *)dest - (char *)tm) {
			case offsetof(struct tm, tm_yday):
				;
			}
			goto update;
		numeric_digits:
			neg = 0;
			if (*s == '+') s++;
			else if (*s == '-') neg=1, s++;
			if (!isdigit(*s)) return 0;
			for (*dest=i=0; i<w && isdigit(*s); i++)
				*dest = *dest * 10 + *s++ - '0';
			if (neg) *dest = -*dest;
			*dest -= adj;
			goto update;
		symbolic_range:
			for (i=2*range-1; i>=0; i--) {
				ex = nl_langinfo(min+i);
				len = strlen(ex);
				if (strncasecmp(s, ex, len)) continue;
				s += len;
				*dest = i % range;
				break;
			}
			if (i<0) return 0;
			goto update;
		update:
			//FIXME
			;
		}
	}
	if (want_century) {
		if (want_century & 2) tm->tm_year += century * 100 - 1900;
		else if (tm->tm_year <= 68) tm->tm_year += 100;
	}
	return (char *)s;
}


text:
#include <time.h>
#include <errno.h>
#include <stdint.h>
#include "syscall.h"
#include "libc.h"
#include "atomic.h"

static int sc_clock_gettime(clockid_t clk, struct timespec *ts)
{
	int r = __syscall(SYS_clock_gettime, clk, ts);
	if (!r) return r;
	if (r == -ENOSYS) {
		if (clk == CLOCK_REALTIME) {
			__syscall(SYS_gettimeofday, ts, 0);
			ts->tv_nsec = (int)ts->tv_nsec * 1000;
			return 0;
		}
		r = -EINVAL;
	}
	errno = -r;
	return -1;
}

void *__vdsosym(const char *, const char *);

int __clock_gettime(clockid_t clk, struct timespec *ts)
{
#ifdef VDSO_CGT_SYM
	static int (*cgt)(clockid_t, struct timespec *);
	if (!cgt) {
		void *f = __vdsosym(VDSO_CGT_VER, VDSO_CGT_SYM);
		if (!f) f = (void *)sc_clock_gettime;
		a_cas_p(&cgt, 0, f);
	}
	return cgt(clk, ts);
#else
	return sc_clock_gettime(clk, ts);
#endif
}

weak_alias(__clock_gettime, clock_gettime);


text:
#include "time_impl.h"
#include <errno.h>

time_t mktime(struct tm *tm)
{
	struct tm new;
	long opp;
	long long t = __tm_to_secs(tm);

	__secs_to_zone(t, 1, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);

	if (tm->tm_isdst>=0 && new.tm_isdst!=tm->tm_isdst)
		t += opp - new.__tm_gmtoff;

	t += new.__tm_gmtoff;
	if ((time_t)t != t) goto error;

	__secs_to_zone(t, 0, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);

	if (__secs_to_tm(t - new.__tm_gmtoff, &new) < 0) goto error;

	*tm = new;
	return t;

error:
	errno = EOVERFLOW;
	return -1;
}


text:
#include "time_impl.h"
#include <stdint.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "libc.h"

long  __timezone = 0;
int   __daylight = 0;
char *__tzname[2] = { 0, 0 };

weak_alias(__timezone, timezone);
weak_alias(__daylight, daylight);
weak_alias(__tzname, tzname);

static char std_name[TZNAME_MAX+1];
static char dst_name[TZNAME_MAX+1];
const char __gmt[] = "GMT";

static int dst_off;
static int r0[5], r1[5];

static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end;
static size_t map_size;

static char old_tz_buf[32];
static char *old_tz = old_tz_buf;
static size_t old_tz_size = sizeof old_tz_buf;

static int lock[2];

static int getint(const char **p)
{
	unsigned x;
	for (x=0; **p-'0'<10U; (*p)++) x = **p-'0' + 10*x;
	return x;
}

static int getoff(const char **p)
{
	int neg = 0;
	if (**p == '-') {
		++*p;
		neg = 1;
	} else if (**p == '+') {
		++*p;
	}
	int off = 3600*getint(p);
	if (**p == ':') {
		++*p;
		off += 60*getint(p);
		if (**p == ':') {
			++*p;
			off += getint(p);
		}
	}
	return neg ? -off : off;
}

static void getrule(const char **p, int rule[5])
{
	int r = rule[0] = **p;

	if (r!='M') {
		if (r=='J') ++*p;
		else rule[0] = 0;
		rule[1] = getint(p);
	} else {
		++*p; rule[1] = getint(p);
		++*p; rule[2] = getint(p);
		++*p; rule[3] = getint(p);
	}

	if (**p=='/') {
		++*p;
		rule[4] = getoff(p);
	} else {
		rule[4] = 7200;
	}
}

static void getname(char *d, const char **p)
{
	int i;
	if (**p == '<') {
		++*p;
		for (i=0; **p!='>' && i<TZNAME_MAX; i++)
			d[i] = (*p)[i];
		++*p;
	} else {
		for (i=0; ((*p)[i]|32)-'a'<26U && i<TZNAME_MAX; i++)
			d[i] = (*p)[i];
	}
	*p += i;
	d[i] = 0;
}

#define VEC(...) ((const unsigned char[]){__VA_ARGS__})

static uint32_t zi_read32(const unsigned char *z)
{
	return (unsigned)z[0]<<24 | z[1]<<16 | z[2]<<8 | z[3];
}

static size_t zi_dotprod(const unsigned char *z, const unsigned char *v, size_t n)
{
	size_t y;
	uint32_t x;
	for (y=0; n; n--, z+=4, v++) {
		x = zi_read32(z);
		y += x * *v;
	}
	return y;
}

int __munmap(void *, size_t);

static void do_tzset()
{
	char buf[NAME_MAX+25], *pathname=buf+24;
	const char *try, *s, *p;
	const unsigned char *map = 0;
	size_t i;
	static const char search[] =
		"/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0";

	s = getenv("TZ");
	if (!s || !*s) s = "/etc/localtime";

	if (old_tz && !strcmp(s, old_tz)) return;

	if (zi) __munmap((void *)zi, map_size);

	/* Cache the old value of TZ to check if it has changed. Avoid
	 * free so as not to pull it into static programs. Growth
	 * strategy makes it so free would have minimal benefit anyway. */
	i = strlen(s);
	if (i > PATH_MAX+1) s = __gmt, i = 3;
	if (i >= old_tz_size) {
		old_tz_size *= 2;
		if (i >= old_tz_size) old_tz_size = i+1;
		if (old_tz_size > PATH_MAX+2) old_tz_size = PATH_MAX+2;
		old_tz = malloc(old_tz_size);
	}
	if (old_tz) memcpy(old_tz, s, i+1);

	/* Non-suid can use an absolute tzfile pathname or a relative
	 * pathame beginning with "."; in secure mode, only the
	 * standard path will be searched. */
	if (*s == ':' || ((p=strchr(s, '/')) && !memchr(s, ',', p-s))) {
		if (*s == ':') s++;
		if (*s == '/' || *s == '.') {
			if (!libc.secure || !strcmp(s, "/etc/localtime"))
				map = __map_file(s, &map_size);
		} else {
			size_t l = strlen(s);
			if (l <= NAME_MAX && !strchr(s, '.')) {
				memcpy(pathname, s, l+1);
				pathname[l] = 0;
				for (try=search; !map && *try; try+=l+1) {
					l = strlen(try);
					memcpy(pathname-l, try, l);
					map = __map_file(pathname-l, &map_size);
				}
			}
		}
		if (!map) s = __gmt;
	}
	if (map && (map_size < 44 || memcmp(map, "TZif", 4))) {
		__munmap((void *)map, map_size);
		map = 0;
		s = __gmt;
	}

	zi = map;
	if (map) {
		int scale = 2;
		if (sizeof(time_t) > 4 && map[4]=='2') {
			size_t skip = zi_dotprod(zi+20, VEC(1,1,8,5,6,1), 6);
			trans = zi+skip+44+44;
			scale++;
		} else {
			trans = zi+44;
		}
		index = trans + (zi_read32(trans-12) << scale);
		types = index + zi_read32(trans-12);
		abbrevs = types + 6*zi_read32(trans-8);
		abbrevs_end = abbrevs + zi_read32(trans-4);
		if (zi[map_size-1] == '\n') {
			for (s = (const char *)zi+map_size-2; *s!='\n'; s--);
			s++;
		} else {
			const unsigned char *p;
			__tzname[0] = __tzname[1] = 0;
			__daylight = __timezone = dst_off = 0;
			for (i=0; i<5; i++) r0[i] = r1[i] = 0;
			for (p=types; p<abbrevs; p+=6) {
				if (!p[4] && !__tzname[0]) {
					__tzname[0] = (char *)abbrevs + p[5];
					__timezone = -zi_read32(p);
				}
				if (p[4] && !__tzname[1]) {
					__tzname[1] = (char *)abbrevs + p[5];
					dst_off = -zi_read32(p);
					__daylight = 1;
				}
			}
			if (!__tzname[0]) __tzname[0] = __tzname[1];
			if (!__tzname[0]) __tzname[0] = (char *)__gmt;
			if (!__daylight) {
				__tzname[1] = __tzname[0];
				dst_off = __timezone;
			}
			return;
		}
	}

	if (!s) s = __gmt;
	getname(std_name, &s);
	__tzname[0] = std_name;
	__timezone = getoff(&s);
	getname(dst_name, &s);
	__tzname[1] = dst_name;
	if (dst_name[0]) {
		__daylight = 1;
		if (*s == '+' || *s=='-' || *s-'0'<10U)
			dst_off = getoff(&s);
		else
			dst_off = __timezone - 3600;
	} else {
		__daylight = 0;
		dst_off = 0;
	}

	if (*s == ',') s++, getrule(&s, r0);
	if (*s == ',') s++, getrule(&s, r1);
}

/* Search zoneinfo rules to find the one that applies to the given time,
 * and determine alternate opposite-DST-status rule that may be needed. */

static size_t scan_trans(long long t, int local, size_t *alt)
{
	int scale = 3 - (trans == zi+44);
	uint64_t x;
	int off = 0;

	size_t a = 0, n = (index-trans)>>scale, m;

	if (!n) {
		if (alt) *alt = 0;
		return 0;
	}

	/* Binary search for 'most-recent rule before t'. */
	while (n > 1) {
		m = a + n/2;
		x = zi_read32(trans + (m<<scale));
		if (scale == 3) x = x<<32 | zi_read32(trans + (m<<scale) + 4);
		else x = (int32_t)x;
		if (local) off = (int32_t)zi_read32(types + 6 * index[m-1]);
		if (t - off < (int64_t)x) {
			n /= 2;
		} else {
			a = m;
			n -= n/2;
		}
	}

	/* First and last entry are special. First means to use lowest-index
	 * non-DST type. Last means to apply POSIX-style rule if available. */
	n = (index-trans)>>scale;
	if (a == n-1) return -1;
	if (a == 0) {
		x = zi_read32(trans + (a<<scale));
		if (scale == 3) x = x<<32 | zi_read32(trans + (a<<scale) + 4);
		else x = (int32_t)x;
		if (local) off = (int32_t)zi_read32(types + 6 * index[a-1]);
		if (t - off < (int64_t)x) {
			for (a=0; a<(abbrevs-types)/6; a++) {
				if (types[6*a+4] != types[4]) break;
			}
			if (a == (abbrevs-types)/6) a = 0;
			if (types[6*a+4]) {
				*alt = a;
				return 0;
			} else {
				*alt = 0;
				return a;
			}
		}
	}

	/* Try to find a neighboring opposite-DST-status rule. */
	if (alt) {
		if (a && types[6*index[a-1]+4] != types[6*index[a]+4])
			*alt = index[a-1];
		else if (a+1<n && types[6*index[a+1]+4] != types[6*index[a]+4])
			*alt = index[a+1];
		else
			*alt = index[a];
	}

	return index[a];
}

static int days_in_month(int m, int is_leap)
{
	if (m==2) return 28+is_leap;
	else return 30+((0xad5>>(m-1))&1);
}

/* Convert a POSIX DST rule plus year to seconds since epoch. */

static long long rule_to_secs(const int *rule, int year)
{
	int is_leap;
	long long t = __year_to_secs(year, &is_leap);
	int x, m, n, d;
	if (rule[0]!='M') {
		x = rule[1];
		if (rule[0]=='J' && (x < 60 || !is_leap)) x--;
		t += 86400 * x;
	} else {
		m = rule[1];
		n = rule[2];
		d = rule[3];
		t += __month_to_secs(m-1, is_leap);
		int wday = (int)((t + 4*86400) % (7*86400)) / 86400;
		int days = d - wday;
		if (days < 0) days += 7;
		if (n == 5 && days+28 >= days_in_month(m, is_leap)) n = 4;
		t += 86400 * (days + 7*(n-1));
	}
	t += rule[4];
	return t;
}

/* Determine the time zone in effect for a given time in seconds since the
 * epoch. It can be given in local or universal time. The results will
 * indicate whether DST is in effect at the queried time, and will give both
 * the GMT offset for the active zone/DST rule and the opposite DST. This
 * enables a caller to efficiently adjust for the case where an explicit
 * DST specification mismatches what would be in effect at the time. */

void __secs_to_zone(long long t, int local, int *isdst, long *offset, long *oppoff, const char **zonename)
{
	LOCK(lock);

	do_tzset();

	if (zi) {
		size_t alt, i = scan_trans(t, local, &alt);
		if (i != -1) {
			*isdst = types[6*i+4];
			*offset = -(int32_t)zi_read32(types+6*i);
			*zonename = (const char *)abbrevs + types[6*i+5];
			if (oppoff) *oppoff = -(int32_t)zi_read32(types+6*alt);
			UNLOCK(lock);
			return;
		}
	}

	if (!__daylight) goto std;

	/* FIXME: may be broken if DST changes right at year boundary?
	 * Also, this could be more efficient.*/
	long long y = t / 31556952 + 70;
	while (__year_to_secs(y, 0) > t) y--;
	while (__year_to_secs(y+1, 0) < t) y++;

	long long t0 = rule_to_secs(r0, y);
	long long t1 = rule_to_secs(r1, y);

	if (t0 < t1) {
		if (!local) {
			t0 += __timezone;
			t1 += dst_off;
		}
		if (t >= t0 && t < t1) goto dst;
		goto std;
	} else {
		if (!local) {
			t1 += __timezone;
			t0 += dst_off;
		}
		if (t >= t1 && t < t0) goto std;
		goto dst;
	}
std:
	*isdst = 0;
	*offset = __timezone;
	if (oppoff) *oppoff = dst_off;
	*zonename = __tzname[0];
	UNLOCK(lock);
	return;
dst:
	*isdst = 1;
	*offset = dst_off;
	if (oppoff) *oppoff = __timezone;
	*zonename = __tzname[1];
	UNLOCK(lock);
}

void __tzset()
{
	LOCK(lock);
	do_tzset();
	UNLOCK(lock);
}

weak_alias(__tzset, tzset);

const char *__tm_to_tzname(const struct tm *tm)
{
	const void *p = tm->__tm_zone;
	LOCK(lock);
	do_tzset();
	if (p != __gmt && p != __tzname[0] && p != __tzname[1] &&
	    (!zi || (uintptr_t)p-(uintptr_t)abbrevs >= abbrevs_end - abbrevs))
		p = "";
	UNLOCK(lock);
	return p;
}


text:
#include <time.h>
#include <stdio.h>
#include <langinfo.h>
#include "atomic.h"

const char *__nl_langinfo(nl_item);

char *__asctime(const struct tm *restrict tm, char *restrict buf)
{
	/* FIXME: change __nl_langinfo to __nl_langinfo_l with explicit C
	 * locale once we have locales */
	if (snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
		__nl_langinfo(ABDAY_1+tm->tm_wday),
		__nl_langinfo(ABMON_1+tm->tm_mon),
		tm->tm_mday, tm->tm_hour,
		tm->tm_min, tm->tm_sec,
		1900 + tm->tm_year) >= 26)
	{
		/* ISO C requires us to use the above format string,
		 * even if it will not fit in the buffer. Thus asctime_r
		 * is _supposed_ to crash if the fields in tm are too large.
		 * We follow this behavior and crash "gracefully" to warn
		 * application developers that they may not be so lucky
		 * on other implementations (e.g. stack smashing..).
		 */
		a_crash();
	}
	return buf;
}


text:
#include <time.h>
#include <limits.h>
#include "pthread_impl.h"

int timer_gettime(timer_t t, struct itimerspec *val)
{
	if ((intptr_t)t < 0) {
		pthread_t td = (void *)((uintptr_t)t << 1);
		t = (void *)(uintptr_t)(td->timer_id & INT_MAX);
	}
	return syscall(SYS_timer_gettime, t, val);
}


text:
#include <time.h>

char *ctime_r(const time_t *t, char *buf)
{
	struct tm tm;
	localtime_r(t, &tm);
	return asctime_r(&tm, buf);
}


text:
int __month_to_secs(int month, int is_leap)
{
	static const int secs_through_month[] = {
		0, 31*86400, 59*86400, 90*86400,
		120*86400, 151*86400, 181*86400, 212*86400,
		243*86400, 273*86400, 304*86400, 334*86400 };
	int t = secs_through_month[month];
	if (is_leap && month >= 2) t+=86400;
	return t;
}


text:
#include <time.h>

int __days_in_month(int, int);
int __month_to_secs(int, int);
long long __year_to_secs(long long, int *);
long long __tm_to_secs(const struct tm *);
int __secs_to_tm(long long, struct tm *);
void __secs_to_zone(long long, int, int *, long *, long *, const char **);
const unsigned char *__map_file(const char *, size_t *);


text:
#include <time.h>

char *__asctime(const struct tm *, char *);

char *asctime(const struct tm *tm)
{
	static char buf[26];
	return __asctime(tm, buf);
}


text:
#include <time.h>
#include "syscall.h"
#include "libc.h"

int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct timespec *rem)
{
	return -__syscall_cp(SYS_clock_nanosleep, clk, flags, req, rem);
}


text:
#include <termios.h>
#include <sys/ioctl.h>
#include <errno.h>

int tcsetattr(int fd, int act, const struct termios *tio)
{
	if (act < 0 || act > 2) {
		errno = EINVAL;
		return -1;
	}
	return ioctl(fd, TCSETS+act, tio);
}


text:
#include <termios.h>
#include <sys/ioctl.h>

pid_t tcgetsid(int fd)
{
	int sid;
	if (ioctl(fd, TIOCGSID, &sid) < 0)
		return -1;
	return sid;
}


text:
#include <termios.h>
#include <sys/ioctl.h>
#include "libc.h"
#include "syscall.h"

int tcdrain(int fd)
{
	return syscall_cp(SYS_ioctl, fd, TCSBRK, 1);
}


text:
#include <termios.h>
#include <sys/ioctl.h>
#include <errno.h>
#include "libc.h"

int cfsetospeed(struct termios *tio, speed_t speed)
{
	if (speed & ~CBAUD) {
		errno = EINVAL;
		return -1;
	}
	tio->c_cflag &= ~CBAUD;
	tio->c_cflag |= speed;
	return 0;
}

int cfsetispeed(struct termios *tio, speed_t speed)
{
	return speed ? cfsetospeed(tio, speed) : 0;
}

weak_alias(cfsetospeed, cfsetspeed);


text:
#include <termios.h>
#include <sys/ioctl.h>

int tcflush(int fd, int queue)
{
	return ioctl(fd, TCFLSH, queue);
}


text:
#include <termios.h>
#include <sys/ioctl.h>

speed_t cfgetospeed(const struct termios *tio)
{
	return tio->c_cflag & CBAUD;
}

speed_t cfgetispeed(const struct termios *tio)
{
	return cfgetospeed(tio);
}


text:
#include <termios.h>
#include <sys/ioctl.h>

int tcgetattr(int fd, struct termios *tio)
{
	if (ioctl(fd, TCGETS, tio))
		return -1;
	return 0;
}


text:
#include <termios.h>
#include <sys/ioctl.h>

int tcsendbreak(int fd, int dur)
{
	/* nonzero duration is implementation-defined, so ignore it */
	return ioctl(fd, TCSBRK, 0);
}


text:
#include <termios.h>
#include <sys/ioctl.h>

int tcflow(int fd, int action)
{
	return ioctl(fd, TCXONC, action);
}


text:
#define _GNU_SOURCE
#include <termios.h>

void cfmakeraw(struct termios *t)
{
	t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
	t->c_oflag &= ~OPOST;
	t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
	t->c_cflag &= ~(CSIZE|PARENB);
	t->c_cflag |= CS8;
	t->c_cc[VMIN] = 1;
	t->c_cc[VTIME] = 0;
}


text:
#include <unistd.h>
#include <fcntl.h>
#include "syscall.h"

int rmdir(const char *path)
{
#ifdef SYS_rmdir
	return syscall(SYS_rmdir, path);
#else
	return syscall(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR);
#endif
}


text:
#define _GNU_SOURCE
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
{
	return __setxid(SYS_setresgid, rgid, egid, sgid);
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

off_t lseek(int fd, off_t offset, int whence)
{
#ifdef SYS__llseek
	off_t result;
	return syscall(SYS__llseek, fd, offset>>32, offset, &result, whence) ? -1 : result;
#else
	return syscall(SYS_lseek, fd, offset, whence);
#endif
}

LFS64(lseek);


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

ssize_t write(int fd, const void *buf, size_t count)
{
	return syscall_cp(SYS_write, fd, buf, count);
}


text:
#include <unistd.h>
#include <errno.h>

void __procfdname(char *, unsigned);

int ttyname_r(int fd, char *name, size_t size)
{
	char procname[sizeof "/proc/self/fd/" + 3*sizeof(int) + 2];
	ssize_t l;

	if (!isatty(fd)) return ENOTTY;

	__procfdname(procname, fd);
	l = readlink(procname, name, size);

	if (l < 0) return errno;
	else if (l == size) return ERANGE;
	else {
		name[l] = 0;
		return 0;
	}
}


text:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include "syscall.h"

char *ctermid(char *s)
{
	static char s2[L_ctermid];
	int fd;
	if (!s) s = s2;
	*s = 0;
	fd = open("/dev/tty", O_WRONLY | O_NOCTTY | O_CLOEXEC);
	if (fd >= 0) {
		ttyname_r(fd, s, L_ctermid);
		__syscall(SYS_close, fd);
	}
	return s;
}


text:
#include <unistd.h>
#include "syscall.h"

int fsync(int fd)
{
	return syscall(SYS_fsync, fd);
}


text:
#include <unistd.h>
#include "syscall.h"

int setpgid(pid_t pid, pid_t pgid)
{
	return syscall(SYS_setpgid, pid, pgid);
}


text:
#include <unistd.h>
#include <errno.h>
#include "syscall.h"
#include "libc.h"

int close(int fd)
{
	int r = __syscall_cp(SYS_close, fd);
	if (r == -EINTR) r = -EINPROGRESS;
	return __syscall_ret(r);
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int setreuid(uid_t ruid, uid_t euid)
{
	return __setxid(SYS_setreuid, ruid, euid, 0);
}


text:
#include <unistd.h>

int posix_close(int fd, int flags)
{
	return close(fd);
}


text:
#include <unistd.h>
#include "syscall.h"

void sync(void)
{
	__syscall(SYS_sync);
}


text:
#define _GNU_SOURCE
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int acct(const char *filename)
{
	return syscall(SYS_acct, filename);
}


text:
#define _BSD_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

ssize_t preadv(int fd, const struct iovec *iov, int count, off_t ofs)
{
	return syscall_cp(SYS_preadv, fd, iov, count,
		(long)(ofs), (long)(ofs>>32));
}

LFS64(preadv);


text:
#include <unistd.h>
#include "syscall.h"

pid_t getpgid(pid_t pid)
{
	return syscall(SYS_getpgid, pid);
}


text:
#define _GNU_SOURCE
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "syscall.h"
#include "libc.h"

int __dup3(int old, int new, int flags)
{
	int r;
#ifdef SYS_dup2
	if (old==new) return __syscall_ret(-EINVAL);
	if (flags & O_CLOEXEC) {
		while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
		if (r!=-ENOSYS) return __syscall_ret(r);
	}
	while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
	if (flags & O_CLOEXEC) __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC);
#else
	while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
#endif
	return __syscall_ret(r);
}

weak_alias(__dup3, dup3);


text:
#include <unistd.h>
#include "syscall.h"

int getgroups(int count, gid_t list[])
{
	return syscall(SYS_getgroups, count, list);
}


text:
#include <unistd.h>
#include "syscall.h"

gid_t getegid(void)
{
	return __syscall(SYS_getegid);
}


text:
#include <unistd.h>
#include <fcntl.h>
#include "syscall.h"

int lchown(const char *path, uid_t uid, gid_t gid)
{
#ifdef SYS_lchown
	return syscall(SYS_lchown, path, uid, gid);
#else
	return syscall(SYS_fchownat, AT_FDCWD, path, uid, gid, AT_SYMLINK_NOFOLLOW);
#endif
}


text:
#include <unistd.h>
#include <sys/time.h>
#include "syscall.h"

unsigned alarm(unsigned seconds)
{
	struct itimerval it = { .it_value.tv_sec = seconds };
	__syscall(SYS_setitimer, ITIMER_REAL, &it, &it);
	return it.it_value.tv_sec + !!it.it_value.tv_usec;
}


text:
#define _BSD_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

ssize_t pwritev(int fd, const struct iovec *iov, int count, off_t ofs)
{
	return syscall_cp(SYS_pwritev, fd, iov, count,
		(long)(ofs), (long)(ofs>>32));
}

LFS64(pwritev);


text:
#include <unistd.h>
#include "syscall.h"

int fchownat(int fd, const char *path, uid_t uid, gid_t gid, int flag)
{
	return syscall(SYS_fchownat, fd, path, uid, gid, flag);
}


text:
#include <unistd.h>
#include <fcntl.h>
#include "syscall.h"

int symlink(const char *existing, const char *new)
{
#ifdef SYS_symlink
	return syscall(SYS_symlink, existing, new);
#else
	return syscall(SYS_symlinkat, existing, AT_FDCWD, new);
#endif
}


text:
#include <unistd.h>
#include <fcntl.h>
#include "syscall.h"

int chown(const char *path, uid_t uid, gid_t gid)
{
#ifdef SYS_chown
	return syscall(SYS_chown, path, uid, gid);
#else
	return syscall(SYS_fchownat, AT_FDCWD, path, uid, gid, 0);
#endif
}


text:
#include <unistd.h>
#include "syscall.h"

int symlinkat(const char *existing, int fd, const char *new)
{
	return syscall(SYS_symlinkat, existing, fd, new);
}


text:
#include <unistd.h>
#include "syscall.h"

pid_t getpid(void)
{
	return __syscall(SYS_getpid);
}


text:
#include <unistd.h>
#include "syscall.h"

pid_t setsid(void)
{
	return syscall(SYS_setsid);
}


text:
#include <stdio.h>
#include "syscall.h"

int renameat(int oldfd, const char *old, int newfd, const char *new)
{
	return syscall(SYS_renameat, oldfd, old, newfd, new);
}


text:
#include <unistd.h>
#include "syscall.h"

pid_t getpgrp(void)
{
	return __syscall(SYS_getpgid, 0);
}


text:
#include <unistd.h>
#include <fcntl.h>
#include "syscall.h"

int access(const char *filename, int amode)
{
#ifdef SYS_access
	return syscall(SYS_access, filename, amode);
#else
	return syscall(SYS_faccessat, AT_FDCWD, filename, amode, 0);
#endif
}


text:
#include <unistd.h>
#include "syscall.h"

pid_t getppid(void)
{
	return __syscall(SYS_getppid);
}


text:
#include <unistd.h>
#include <stdlib.h>

char *getlogin(void)
{
	return getenv("LOGNAME");
}


text:
#include <sys/uio.h>
#include "syscall.h"
#include "libc.h"

ssize_t readv(int fd, const struct iovec *iov, int count)
{
	return syscall_cp(SYS_readv, fd, iov, count);
}


text:
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include "syscall.h"

char *getcwd(char *buf, size_t size)
{
	char tmp[PATH_MAX];
	if (!buf) {
		buf = tmp;
		size = PATH_MAX;
	} else if (!size) {
		errno = EINVAL;
		return 0;
	}
	if (syscall(SYS_getcwd, buf, size) < 0) return 0;
	return buf == tmp ? strdup(buf) : buf;
}


text:
#include <unistd.h>
#include "syscall.h"

gid_t getgid(void)
{
	return __syscall(SYS_getgid);
}


text:
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "syscall.h"

int dup2(int old, int new)
{
	int r;
#ifdef SYS_dup2
	while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
#else
	if (old==new) {
		r = __syscall(SYS_fcntl, old, F_GETFD);
		if (r >= 0) return old;
	} else {
		while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY);
	}
#endif
	return __syscall_ret(r);
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

ssize_t read(int fd, void *buf, size_t count)
{
	return syscall_cp(SYS_read, fd, buf, count);
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int seteuid(uid_t euid)
{
	return __setxid(SYS_setresuid, -1, euid, -1);
}


text:
#include <unistd.h>

pid_t setpgrp(void)
{
	return setpgid(0, 0);
}


text:
#define _GNU_SOURCE
#include <unistd.h>
#include <time.h>

int usleep(unsigned useconds)
{
	struct timespec tv = {
		.tv_sec = useconds/1000000,
		.tv_nsec = (useconds%1000000)*1000
	};
	return nanosleep(&tv, &tv);
}


text:
#include <unistd.h>
#include "syscall.h"

int pipe(int fd[2])
{
#ifdef SYS_pipe
	return syscall(SYS_pipe, fd);
#else
	return syscall(SYS_pipe2, fd, 0);
#endif
}


text:
#include <unistd.h>
#include "syscall.h"

pid_t getsid(pid_t pid)
{
	return syscall(SYS_getsid, pid);
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
{
	return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL_O(ofs));
}

LFS64(pread);


text:
#include <unistd.h>
#include <string.h>
#include <errno.h>

int getlogin_r(char *name, size_t size)
{
	char *logname = getlogin();
	if (!logname) return ENXIO; /* or...? */
	if (strlen(logname) >= size) return ERANGE;
	strcpy(name, logname);
	return 0;
}


text:
#include <unistd.h>
#include "syscall.h"

ssize_t readlinkat(int fd, const char *restrict path, char *restrict buf, size_t bufsize)
{
	return syscall(SYS_readlinkat, fd, path, buf, bufsize);
}


text:
#include <sys/uio.h>
#include "syscall.h"
#include "libc.h"

ssize_t writev(int fd, const struct iovec *iov, int count)
{
	return syscall_cp(SYS_writev, fd, iov, count);
}


text:
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include "syscall.h"
#include "pthread_impl.h"

struct ctx {
	int fd;
	const char *filename;
	int amode;
};

static const int errors[] = {
	0, -EACCES, -ELOOP, -ENAMETOOLONG, -ENOENT, -ENOTDIR,
	-EROFS, -EBADF, -EINVAL, -ETXTBSY,
	-EFAULT, -EIO, -ENOMEM,
	-EBUSY
};

static int checker(void *p)
{
	struct ctx *c = p;
	int ret;
	int i;
	if (__syscall(SYS_setregid, __syscall(SYS_getegid), -1)
	    || __syscall(SYS_setreuid, __syscall(SYS_geteuid), -1))
		__syscall(SYS_exit, 1);
	ret = __syscall(SYS_faccessat, c->fd, c->filename, c->amode, 0);
	for (i=0; i < sizeof errors/sizeof *errors - 1 && ret!=errors[i]; i++);
	return i;
}

int faccessat(int fd, const char *filename, int amode, int flag)
{
	if (!flag || (flag==AT_EACCESS && getuid()==geteuid() && getgid()==getegid()))
		return syscall(SYS_faccessat, fd, filename, amode, flag);

	if (flag != AT_EACCESS)
		return __syscall_ret(-EINVAL);

	char stack[1024];
	sigset_t set;
	pid_t pid;
	int ret = -EBUSY;
	struct ctx c = { .fd = fd, .filename = filename, .amode = amode };

	__block_all_sigs(&set);

	pid = __clone(checker, stack+sizeof stack, 0, &c);
	if (pid > 0) {
		int status;
		do {
			__syscall(SYS_wait4, pid, &status, __WCLONE, 0);
		} while (!WIFEXITED(status) && !WIFSIGNALED(status));
		if (WIFEXITED(status))
			ret = errors[WEXITSTATUS(status)];
	}

	__restore_sigs(&set);

	return __syscall_ret(ret);
}


text:
#include <unistd.h>
#include <sys/utsname.h>

int gethostname(char *name, size_t len)
{
	size_t i;
	struct utsname uts;
	if (uname(&uts)) return -1;
	if (len > sizeof uts.nodename) len = sizeof uts.nodename;
	for (i=0; i<len && (name[i] = uts.nodename[i]); i++);
	if (i==len) name[i-1] = 0;
	return 0;
}


text:
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "syscall.h"

void __procfdname(char *, unsigned);

int fchown(int fd, uid_t uid, gid_t gid)
{
	int ret = __syscall(SYS_fchown, fd, uid, gid);
	if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0)
		return __syscall_ret(ret);

	char buf[15+3*sizeof(int)];
	__procfdname(buf, fd);
#ifdef SYS_chown
	return syscall(SYS_chown, buf, uid, gid);
#else
	return syscall(SYS_fchownat, AT_FDCWD, buf, uid, gid);
#endif

}


text:
#define _GNU_SOURCE
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int setresuid(uid_t ruid, uid_t euid, uid_t suid)
{
	return __setxid(SYS_setresuid, ruid, euid, suid);
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int setuid(uid_t uid)
{
	return __setxid(SYS_setuid, uid, 0, 0);
}


text:
#include <unistd.h>
#include "syscall.h"

uid_t geteuid(void)
{
	return __syscall(SYS_geteuid);
}


text:
#include <unistd.h>
#include <fcntl.h>
#include "syscall.h"

int unlink(const char *path)
{
#ifdef SYS_unlink
	return syscall(SYS_unlink, path);
#else
	return syscall(SYS_unlinkat, AT_FDCWD, path, 0);
#endif
}


text:
#include <unistd.h>
#include <fcntl.h>
#include "syscall.h"

ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize)
{
#ifdef SYS_readlink
	return syscall(SYS_readlink, path, buf, bufsize);
#else
	return syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize);
#endif
}


text:
#include <unistd.h>
#include "syscall.h"

uid_t getuid(void)
{
	return __syscall(SYS_getuid);
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)
{
	return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL_O(ofs));
}

LFS64(pwrite);


text:
#include <unistd.h>
#include "syscall.h"

int chdir(const char *path)
{
	return syscall(SYS_chdir, path);
}


text:
#include <unistd.h>
#include "syscall.h"

int fdatasync(int fd)
{
	return syscall(SYS_fdatasync, fd);
}


text:
#include <unistd.h>
#include <termios.h>

int isatty(int fd)
{
	struct termios t;
	return tcgetattr(fd, &t) == 0;
}


text:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/time.h>

unsigned ualarm(unsigned value, unsigned interval)
{
	struct itimerval it = {
		.it_interval.tv_usec = interval,
		.it_value.tv_usec = value
	};
	setitimer(ITIMER_REAL, &it, &it);
	return it.it_value.tv_sec*1000000 + it.it_value.tv_usec;
}


text:
#include <unistd.h>
#include "syscall.h"

int unlinkat(int fd, const char *path, int flag)
{
	return syscall(SYS_unlinkat, fd, path, flag);
}


text:
#include <unistd.h>
#include "libc.h"
#include "syscall.h"

int setegid(gid_t egid)
{
	return __setxid(SYS_setresgid, -1, egid, -1);
}


text:
#include <unistd.h>
#include <time.h>

unsigned sleep(unsigned seconds)
{
	struct timespec tv = { .tv_sec = seconds, .tv_nsec = 0 };
	if (nanosleep(&tv, &tv))
		return tv.tv_sec;
	return 0;
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int setregid(gid_t rgid, gid_t egid)
{
	return __setxid(SYS_setregid, rgid, egid, 0);
}


text:
#include <unistd.h>
#include <stdlib.h>

_Noreturn void _exit(int status)
{
	_Exit(status);
}


text:
#include <unistd.h>
#include <sys/resource.h>
#include "syscall.h"

int nice(int inc)
{
#ifdef SYS_nice
	return syscall(SYS_nice, inc);
#else
	return setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS, 0)+inc);
#endif
}


text:
#include <unistd.h>
#include <errno.h>
#include <sys/resource.h>
#include "syscall.h"
#include "libc.h"

struct ctx {
	int id, eid, sid;
	int nr, rlim, err;
};

/* We jump through hoops to eliminate the possibility of partial failures. */

int __setrlimit(int, const struct rlimit *);

static void do_setxid(void *p)
{
	struct ctx *c = p;
	if (c->err) return;
	if (c->rlim && c->id >= 0 && c->id != getuid()) {
		struct rlimit inf = { RLIM_INFINITY, RLIM_INFINITY }, old;
		getrlimit(RLIMIT_NPROC, &old);
		if ((c->err = -__setrlimit(RLIMIT_NPROC, &inf)) && libc.threads_minus_1)
			return;
		c->err = -__syscall(c->nr, c->id, c->eid, c->sid);
		__setrlimit(RLIMIT_NPROC, &old);
		return;
	}
	c->err = -__syscall(c->nr, c->id, c->eid, c->sid);
}

int __setxid(int nr, int id, int eid, int sid)
{
	struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid };
	switch (nr) {
	case SYS_setuid:
	case SYS_setreuid:
	case SYS_setresuid:
		c.rlim = 1;
	}
	__synccall(do_setxid, &c);
	if (c.err) {
		errno = c.err;
		return -1;
	}
	return 0;
}


text:
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "syscall.h"

int pipe2(int fd[2], int flag)
{
	if (!flag) return pipe(fd);
	int ret = __syscall(SYS_pipe2, fd, flag);
	if (ret != -ENOSYS) return __syscall_ret(ret);
	ret = pipe(fd);
	if (ret) return ret;
	if (flag & O_CLOEXEC) {
		__syscall(SYS_fcntl, fd[0], F_SETFD, FD_CLOEXEC);
		__syscall(SYS_fcntl, fd[1], F_SETFD, FD_CLOEXEC);
	}
	if (flag & O_NONBLOCK) {
		__syscall(SYS_fcntl, fd[0], F_SETFL, O_NONBLOCK);
		__syscall(SYS_fcntl, fd[1], F_SETFL, O_NONBLOCK);
	}
	return 0;
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int truncate(const char *path, off_t length)
{
	return syscall(SYS_truncate, path, __SYSCALL_LL_O(length));
}

LFS64(truncate);


text:
#include <unistd.h>
#include <errno.h>
#include <limits.h>

char *ttyname(int fd)
{
	static char buf[TTY_NAME_MAX];
	int result;
	if ((result = ttyname_r(fd, buf, sizeof buf))) {
		errno = result;
		return NULL;
	}
	return buf;
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int ftruncate(int fd, off_t length)
{
	return syscall(SYS_ftruncate, fd, __SYSCALL_LL_O(length));
}

LFS64(ftruncate);


text:
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "syscall.h"

void __procfdname(char *, unsigned);

int fchdir(int fd)
{
	int ret = __syscall(SYS_fchdir, fd);
	if (ret != -EBADF || __syscall(SYS_fcntl, fd, F_GETFD) < 0)
		return __syscall_ret(ret);

	char buf[15+3*sizeof(int)];
	__procfdname(buf, fd);
	return syscall(SYS_chdir, buf);
}


text:
#include <unistd.h>
#include "syscall.h"
#include "libc.h"

int setgid(gid_t gid)
{
	return __setxid(SYS_setgid, gid, 0, 0);
}


text:
#include <unistd.h>
#include "syscall.h"

int dup(int fd)
{
	return syscall(SYS_dup, fd);
}


text:
#include <unistd.h>
#include "syscall.h"

int linkat(int fd1, const char *existing, int fd2, const char *new, int flag)
{
	return syscall(SYS_linkat, fd1, existing, fd2, new, flag);
}


text:
#include <unistd.h>
#include <signal.h>
#include "syscall.h"
#include "libc.h"

int pause(void)
{
#ifdef SYS_pause
	return syscall_cp(SYS_pause);
#else
	return syscall_cp(SYS_ppoll, 0, 0, 0, 0);
#endif
}


text:
#include <unistd.h>
#include <fcntl.h>
#include "syscall.h"

int link(const char *existing, const char *new)
{
#ifdef SYS_link
	return syscall(SYS_link, existing, new);
#else
	return syscall(SYS_linkat, AT_FDCWD, existing, AT_FDCWD, new, 0);
#endif
}


text:
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>

int tcsetpgrp(int fd, pid_t pgrp)
{
	int pgrp_int = pgrp;
	return ioctl(fd, TIOCSPGRP, &pgrp_int);
}


text:
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>

pid_t tcgetpgrp(int fd)
{
	int pgrp;
	if (ioctl(fd, TIOCGPGRP, &pgrp) < 0)
		return -1;
	return pgrp;
}


text:
.global pipe
.type   pipe, @function
pipe:
	mov    #42, r3
	trapa  #17

	! work around hardware bug
	or     r0, r0
	or     r0, r0
	or     r0, r0
	or     r0, r0
	or     r0, r0

	cmp/pz r0
	bt     1f

	mov.l  L1, r1
	braf   r1
	 mov   r0, r4

1:	mov.l  r0, @(0,r4)
	mov.l  r1, @(4,r4)
	rts
	 mov   #0, r0

.align 2
L1:	.long __syscall_ret@PLT-(1b-.)


text:
.set noreorder

.global pipe
.type   pipe,@function
pipe:
	lui $gp, %hi(_gp_disp)
	addiu $gp, %lo(_gp_disp)
	addu $gp, $gp, $25
	li $2, 4042
	syscall
	beq $7, $0, 1f
	nop
	lw $25, %call16(__syscall_ret)($gp)
	jr $25
	subu $4, $0, $2
1:	sw $2, 0($4)
	sw $3, 4($4)
	move $2, $0
	jr $ra
	nop


text:
#define _GNU_SOURCE
#include <unistd.h>
#include "syscall.h"

int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
{
	return syscall(SYS_getresgid, rgid, egid, sgid);
}


text:
#define _GNU_SOURCE
#include <stddef.h>
#include <getopt.h>
#include <stdio.h>

extern int __optpos, __optreset;

static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
{
	if (!optind || __optreset) {
		__optreset = 0;
		__optpos = 0;
		optind = 1;
	}
	if (optind >= argc || !argv[optind] || argv[optind][0] != '-') return -1;
	if ((longonly && argv[optind][1]) ||
		(argv[optind][1] == '-' && argv[optind][2]))
	{
		int i;
		for (i=0; longopts[i].name; i++) {
			const char *name = longopts[i].name;
			char *opt = argv[optind]+1;
			if (*opt == '-') opt++;
			for (; *name && *name == *opt; name++, opt++);
			if (*name || (*opt && *opt != '=')) continue;
			if (*opt == '=') {
				if (!longopts[i].has_arg) continue;
				optarg = opt+1;
			} else {
				if (longopts[i].has_arg == required_argument) {
					if (!(optarg = argv[++optind]))
						return ':';
				} else optarg = NULL;
			}
			optind++;
			if (idx) *idx = i;
			if (longopts[i].flag) {
				*longopts[i].flag = longopts[i].val;
				return 0;
			}
			return longopts[i].val;
		}
		if (argv[optind][1] == '-') {
			optind++;
			return '?';
		}
	}
	return getopt(argc, argv, optstring);
}

int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
{
	return __getopt_long(argc, argv, optstring, longopts, idx, 0);
}

int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
{
	return __getopt_long(argc, argv, optstring, longopts, idx, 1);
}


text:
#include <strings.h>
#include "atomic.h"

int ffsll(long long i)
{
	return i ? a_ctz_64(i)+1 : 0;
}


text:
#define _GNU_SOURCE
#include <unistd.h>
#include "syscall.h"

int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
{
	return syscall(SYS_getresuid, ruid, euid, suid);
}


text:
#include <sys/resource.h>
#include "syscall.h"

int setpriority(int which, id_t who, int prio)
{
	return syscall(SYS_setpriority, which, who, prio);
}


text:
#include <sys/utsname.h>
#include "syscall.h"

int uname(struct utsname *uts)
{
	return syscall(SYS_uname, uts);
}


text:
#include <pty.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>

int forkpty(int *m, char *name, const struct termios *tio, const struct winsize *ws)
{
	int s, t, i, istmp[3]={0};
	pid_t pid;

	if (openpty(m, &s, name, tio, ws) < 0) return -1;

	/* Ensure before forking that we don't exceed fd limit */
	for (i=0; i<3; i++) {
		if (fcntl(i, F_GETFL) < 0) {
			t = fcntl(s, F_DUPFD, i);
			if (t<0) break;
			else if (t!=i) close(t);
			else istmp[i] = 1;
		}
	}
	pid = i==3 ? fork() : -1;
	if (!pid) {
		close(*m);
		setsid();
		ioctl(s, TIOCSCTTY, (char *)0);
		dup2(s, 0);
		dup2(s, 1);
		dup2(s, 2);
		if (s>2) close(s);
		return 0;
	}
	for (i=0; i<3; i++)
		if (istmp[i]) close(i);
	close(s);
	if (pid < 0) close(*m);
	return pid;
}


text:
#include <strings.h>
#include "atomic.h"

int ffsl(long i)
{
	return i ? a_ctz_l(i)+1 : 0;
}


text:
#include <strings.h>
#include "atomic.h"

int ffs(int i)
{
	return i ? a_ctz_l(i)+1 : 0;
}


text:
#include <string.h>
#include <libgen.h>

char *dirname(char *s)
{
	size_t i;
	if (!s || !*s) return ".";
	i = strlen(s)-1;
	for (; s[i]=='/'; i--) if (!i) return "/";
	for (; s[i]!='/'; i--) if (!i) return ".";
	for (; s[i]=='/'; i--) if (!i) return "/";
	s[i+1] = 0;
	return s;
}


text:
#include <stdarg.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <syslog.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <fcntl.h>
#include "libc.h"
#include "atomic.h"

static int lock[2];
static char log_ident[32];
static int log_opt;
static int log_facility = LOG_USER;
static int log_mask = 0xff;
static int log_fd = -1;

int setlogmask(int maskpri)
{
	if (maskpri) return a_swap(&log_mask, maskpri);
	else return log_mask;
}

static const struct {
	short sun_family;
	char sun_path[9];
} log_addr = {
	AF_UNIX,
	"/dev/log"
};

void closelog(void)
{
	int cs;
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
	LOCK(lock);
	close(log_fd);
	log_fd = -1;
	UNLOCK(lock);
	pthread_setcancelstate(cs, 0);
}

static void __openlog()
{
	log_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
	if (log_fd >= 0) connect(log_fd, (void *)&log_addr, sizeof log_addr);
}

void openlog(const char *ident, int opt, int facility)
{
	int cs;
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
	LOCK(lock);

	if (ident) {
		size_t n = strnlen(ident, sizeof log_ident - 1);
		memcpy(log_ident, ident, n);
		log_ident[n] = 0;
	} else {
		log_ident[0] = 0;
	}
	log_opt = opt;
	log_facility = facility;

	if ((opt & LOG_NDELAY) && log_fd<0) __openlog();

	UNLOCK(lock);
	pthread_setcancelstate(cs, 0);
}

static void _vsyslog(int priority, const char *message, va_list ap)
{
	char timebuf[16];
	time_t now;
	struct tm tm;
	char buf[256];
	int errno_save = errno;
	int pid;
	int l, l2;
	int hlen;
	int fd;

	if (log_fd < 0) __openlog();

	if (!(priority & LOG_FACMASK)) priority |= log_facility;

	now = time(NULL);
	gmtime_r(&now, &tm);
	strftime(timebuf, sizeof timebuf, "%b %e %T", &tm);

	pid = (log_opt & LOG_PID) ? getpid() : 0;
	l = snprintf(buf, sizeof buf, "<%d>%s %n%s%s%.0d%s: ",
		priority, timebuf, &hlen, log_ident, "["+!pid, pid, "]"+!pid);
	errno = errno_save;
	l2 = vsnprintf(buf+l, sizeof buf - l, message, ap);
	if (l2 >= 0) {
		if (l2 >= sizeof buf - l) l = sizeof buf - 1;
		else l += l2;
		if (buf[l-1] != '\n') buf[l++] = '\n';
		if (send(log_fd, buf, l, 0) < 0 && (log_opt & LOG_CONS)) {
			fd = open("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
			if (fd >= 0) {
				dprintf(fd, "%.*s", l-hlen, buf+hlen);
				close(fd);
			}
		}
		if (log_opt & LOG_PERROR) dprintf(2, "%.*s", l-hlen, buf+hlen);
	}
}

void __vsyslog(int priority, const char *message, va_list ap)
{
	int cs;
	if (!(log_mask & LOG_MASK(priority&7)) || (priority&~0x3ff)) return;
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
	LOCK(lock);
	_vsyslog(priority, message, ap);
	UNLOCK(lock);
	pthread_setcancelstate(cs, 0);
}

void syslog(int priority, const char *message, ...)
{
	va_list ap;
	va_start(ap, message);
	__vsyslog(priority, message, ap);
	va_end(ap);
}

weak_alias(__vsyslog, vsyslog);


text:
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pty.h>
#include <stdio.h>

/* Nonstandard, but vastly superior to the standard functions */

int openpty(int *m, int *s, char *name, const struct termios *tio, const struct winsize *ws)
{
	int n=0;
	char buf[20];

	*m = open("/dev/ptmx", O_RDWR|O_NOCTTY);
	if (*m < 0) return -1;

	if (ioctl(*m, TIOCSPTLCK, &n) || ioctl (*m, TIOCGPTN, &n)) {
		close(*m);
		return -1;
	}

	if (!name) name = buf;
	snprintf(name, sizeof buf, "/dev/pts/%d", n);
	if ((*s = open(name, O_RDWR|O_NOCTTY)) < 0) {
		close(*m);
		return -1;
	}

	if (tio) tcsetattr(*s, TCSANOW, tio);
	if (ws) ioctl(*s, TIOCSWINSZ, ws);

	return 0;
}


text:
#include <unistd.h>
#include "libc.h"

int issetugid(void)
{
	return libc.secure;
}


text:
#include <sys/auxv.h>
#include <errno.h>
#include "libc.h"

unsigned long getauxval(unsigned long item)
{
	size_t *auxv = libc.auxv;
	if (item == AT_SECURE) return libc.secure;
	for (; *auxv; auxv+=2)
		if (*auxv==item) return auxv[1];
	errno = ENOENT;
	return 0;
}


text:
#define _GNU_SOURCE
#include <grp.h>
#include <limits.h>

int initgroups(const char *user, gid_t gid)
{
	gid_t groups[NGROUPS_MAX];
	int count = NGROUPS_MAX;
	if (getgrouplist(user, gid, groups, &count) < 0) return -1;
	return setgroups(count, groups);
}


text:
#include "syscall.h"
#include <stdarg.h>

#undef syscall

long syscall(long n, ...)
{
	va_list ap;
	syscall_arg_t a,b,c,d,e,f;
	va_start(ap, n);
	a=va_arg(ap, syscall_arg_t);
	b=va_arg(ap, syscall_arg_t);
	c=va_arg(ap, syscall_arg_t);
	d=va_arg(ap, syscall_arg_t);
	e=va_arg(ap, syscall_arg_t);
	f=va_arg(ap, syscall_arg_t);
	va_end(ap);
	return __syscall_ret(__syscall(n,a,b,c,d,e,f));
}


text:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/utsname.h>
#include <string.h>
#include <errno.h>

int getdomainname(char *name, size_t len)
{
	struct utsname temp;
	uname(&temp);
	if (!len || strlen(temp.domainname) >= len) {
		errno = EINVAL;
		return -1;
	}
	strcpy(name, temp.domainname);
	return 0;
}


text:
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

static const char digits[] =
	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

long a64l(const char *s)
{
	int e;
	uint32_t x = 0;
	for (e=0; e<36 && *s; e+=6, s++)
		x |= (strchr(digits, *s)-digits)<<e;
	return x;
}

char *l64a(long x0)
{
	static char s[7];
	char *p;
	uint32_t x = x0;
	for (p=s; x; p++, x>>=6)
		*p = digits[x&63];
	*p = 0;
	return s;
}


text:
#include <stdlib.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include "libc.h"
#include "syscall.h"

int posix_openpt(int flags)
{
	return open("/dev/ptmx", flags);
}

int grantpt(int fd)
{
	return 0;
}

int unlockpt(int fd)
{
	int unlock = 0;
	return ioctl(fd, TIOCSPTLCK, &unlock);
}

int __ptsname_r(int fd, char *buf, size_t len)
{
	int pty, err;
	if (!buf) len = 0;
	if ((err = __syscall(SYS_ioctl, fd, TIOCGPTN, &pty))) return -err;
	if (snprintf(buf, len, "/dev/pts/%d", pty) >= len) return ERANGE;
	return 0;
}

weak_alias(__ptsname_r, ptsname_r);


text:
#include <stdio.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>

FILE *setmntent(const char *name, const char *mode)
{
	return fopen(name, mode);
}

int endmntent(FILE *f)
{
	if (f) fclose(f);
	return 1;
}

struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen)
{
	int cnt, n[8];

	mnt->mnt_freq = 0;
	mnt->mnt_passno = 0;

	do {
		fgets(linebuf, buflen, f);
		if (feof(f) || ferror(f)) return 0;
		if (!strchr(linebuf, '\n')) {
			fscanf(f, "%*[^\n]%*[\n]");
			errno = ERANGE;
			return 0;
		}
		cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
			n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
			&mnt->mnt_freq, &mnt->mnt_passno);
	} while (cnt < 2 || linebuf[n[0]] == '#');

	linebuf[n[1]] = 0;
	linebuf[n[3]] = 0;
	linebuf[n[5]] = 0;
	linebuf[n[7]] = 0;

	mnt->mnt_fsname = linebuf+n[0];
	mnt->mnt_dir = linebuf+n[2];
	mnt->mnt_type = linebuf+n[4];
	mnt->mnt_opts = linebuf+n[6];

	return mnt;
}

struct mntent *getmntent(FILE *f)
{
	static char linebuf[256];
	static struct mntent mnt;
	return getmntent_r(f, &mnt, linebuf, sizeof linebuf);
}

int addmntent(FILE *f, const struct mntent *mnt)
{
	if (fseek(f, 0, SEEK_END)) return 1;
	return fprintf(f, "%s\t%s\t%s\t%s\t%d\t%d\n",
		mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts,
		mnt->mnt_freq, mnt->mnt_passno) < 0;
}

char *hasmntopt(const struct mntent *mnt, const char *opt)
{
	return strstr(mnt->mnt_opts, opt);
}


text:
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <sys/stat.h>

char *get_current_dir_name(void) {
	struct stat a, b;
	char *res = getenv("PWD");
	if (res && *res && !stat(res, &a) && !stat(".", &b)
	    && (a.st_dev == b.st_dev) && (a.st_ino == b.st_ino))
		return strdup(res);
	return getcwd(0, 0);
}


text:
#include <stdlib.h>
#include <limits.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include "syscall.h"

void __procfdname(char *, unsigned);

char *realpath(const char *restrict filename, char *restrict resolved)
{
	int fd;
	ssize_t r;
	struct stat st1, st2;
	char buf[15+3*sizeof(int)];
	char tmp[PATH_MAX];

	if (!filename) {
		errno = EINVAL;
		return 0;
	}

	fd = sys_open(filename, O_PATH|O_NONBLOCK|O_CLOEXEC);
	if (fd < 0) return 0;
	__procfdname(buf, fd);

	r = readlink(buf, tmp, sizeof tmp - 1);
	if (r < 0) goto err;
	tmp[r] = 0;

	fstat(fd, &st1);
	r = stat(tmp, &st2);
	if (r<0 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
		if (!r) errno = ELOOP;
		goto err;
	}

	__syscall(SYS_close, fd);
	return resolved ? strcpy(resolved, tmp) : strdup(tmp);
err:
	__syscall(SYS_close, fd);
	return 0;
}


text:
/* Public domain fmtmsg()
 * Written by Isaac Dunham, 2014
 */
#include <fmtmsg.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>

/*
 * If lstr is the first part of bstr, check that the next char in bstr
 * is either \0 or :
 */
static int _strcolcmp(const char *lstr, const char *bstr)
{
	size_t i = 0;
	while (lstr[i] && bstr[i] && (bstr[i] == lstr[i])) i++;
	if ( lstr[i] || (bstr[i] && bstr[i] != ':')) return 1;
	return 0;
}

int fmtmsg(long classification, const char *label, int severity,
           const char *text, const char *action, const char *tag)
{
	int ret = 0, i, consolefd, verb = 0;
	char *errstring = MM_NULLSEV, *cmsg = getenv("MSGVERB");
	char *const msgs[] = {
		"label", "severity", "text", "action", "tag", NULL
	};
	int cs;

	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);

	if (severity == MM_HALT) errstring = "HALT: ";
	else if (severity == MM_ERROR) errstring = "ERROR: ";
	else if (severity == MM_WARNING) errstring = "WARNING: ";
	else if (severity == MM_INFO) errstring = "INFO: ";

	if (classification & MM_CONSOLE) {
		consolefd = open("/dev/console", O_WRONLY);
		if (consolefd < 0) {
			ret = MM_NOCON;
		} else {
			if (dprintf(consolefd, "%s%s%s%s%s%s%s%s\n",
			            label?label:"", label?": ":"",
			            severity?errstring:"", text?text:"",
			            action?"\nTO FIX: ":"",
			            action?action:"", action?" ":"",
			            tag?tag:"" )<1)
				ret = MM_NOCON;
			close(consolefd);
		}
	}

	if (classification & MM_PRINT) {
		while (cmsg && cmsg[0]) {
			for(i=0; msgs[i]; i++) {
				if (!_strcolcmp(msgs[i], cmsg)) break;
			}
			if (msgs[i] == NULL) {
				//ignore MSGVERB-unrecognized component
				verb = 0xFF;
				break;
			} else {
				verb |= (1 << i);
				cmsg = strchr(cmsg, ':');
				if (cmsg) cmsg++;
			}
		}
		if (!verb) verb = 0xFF;
		if (dprintf(2, "%s%s%s%s%s%s%s%s\n",
		            (verb&1 && label) ? label : "",
		            (verb&1 && label) ? ": " : "",
		            (verb&2 && severity) ? errstring : "",
		            (verb&4 && text) ? text : "",
		            (verb&8 && action) ? "\nTO FIX: " : "",
		            (verb&8 && action) ? action : "",
		            (verb&8 && action) ? " " : "",
		            (verb&16 && tag) ? tag : "" ) < 1)
			ret |= MM_NOMSG;
	}
	if ((ret & (MM_NOCON|MM_NOMSG)) == (MM_NOCON|MM_NOMSG))
		ret = MM_NOTOK;

	pthread_setcancelstate(cs, 0);

	return ret;
}


text:
#include <unistd.h>
#include <wchar.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include "libc.h"

char *optarg;
int optind=1, opterr=1, optopt, __optpos, __optreset=0;

#define optpos __optpos
weak_alias(__optreset, optreset);

int getopt(int argc, char * const argv[], const char *optstring)
{
	int i;
	wchar_t c, d;
	int k, l;
	char *optchar;

	if (!optind || __optreset) {
		__optreset = 0;
		__optpos = 0;
		optind = 1;
	}

	if (optind >= argc || !argv[optind] || argv[optind][0] != '-' || !argv[optind][1])
		return -1;
	if (argv[optind][1] == '-' && !argv[optind][2])
		return optind++, -1;

	if (!optpos) optpos++;
	if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
		k = 1;
		c = 0xfffd; /* replacement char */
	}
	optchar = argv[optind]+optpos;
	optopt = c;
	optpos += k;

	if (!argv[optind][optpos]) {
		optind++;
		optpos = 0;
	}

	for (i=0; (l = mbtowc(&d, optstring+i, MB_LEN_MAX)) && d!=c; i+=l>0?l:1);

	if (d != c) {
		if (optstring[0] != ':' && opterr) {
			write(2, argv[0], strlen(argv[0]));
			write(2, ": illegal option: ", 18);
			write(2, optchar, k);
			write(2, "\n", 1);
		}
		return '?';
	}
	if (optstring[i+1] == ':') {
		if (optind >= argc) {
			if (optstring[0] == ':') return ':';
			if (opterr) {
				write(2, argv[0], strlen(argv[0]));
				write(2, ": option requires an argument: ", 31);
				write(2, optchar, k);
				write(2, "\n", 1);
			}
			return '?';
		}
		if (optstring[i+2] == ':') optarg = 0;
		if (optstring[i+2] != ':' || optpos) {
			optarg = argv[optind++] + optpos;
			optpos = 0;
		}
	}
	return c;
}

weak_alias(getopt, __posix_getopt);


text:
#include <sys/resource.h>
#include "syscall.h"

int getpriority(int which, id_t who)
{
	int ret = syscall(SYS_getpriority, which, who);
	if (ret < 0) return ret;
	return 20-ret;
}


text:
#include <sys/resource.h>
#include <errno.h>
#include "syscall.h"
#include "libc.h"

#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0)

int getrlimit(int resource, struct rlimit *rlim)
{
	unsigned long k_rlim[2];
	int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim);
	if (!ret) {
		FIX(rlim->rlim_cur);
		FIX(rlim->rlim_max);
	}
	if (!ret || errno != ENOSYS)
		return ret;
	if (syscall(SYS_getrlimit, resource, k_rlim) < 0)
		return -1;
	rlim->rlim_cur = k_rlim[0] == -1UL ? RLIM_INFINITY : k_rlim[0];
	rlim->rlim_max = k_rlim[1] == -1UL ? RLIM_INFINITY : k_rlim[1];
	FIX(rlim->rlim_cur);
	FIX(rlim->rlim_max);
	return 0;
}

LFS64(getrlimit);


text:
#include <stdlib.h>
#include <errno.h>

int __ptsname_r(int, char *, size_t);

char *ptsname(int fd)
{
	static char buf[9 + sizeof(int)*3 + 1];
	int err = __ptsname_r(fd, buf, sizeof buf);
	if (err) {
		errno = err;
		return 0;
	}
	return buf;
}


text:
#include <wordexp.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include "pthread_impl.h"

static void reap(pid_t pid)
{
	int status;
	for (;;) {
		if (waitpid(pid, &status, 0) < 0) {
			if (errno != EINTR) return;
		} else {
			if (WIFEXITED(status)) return;
		}
	}
}

static char *getword(FILE *f)
{
	char *s = 0;
	return getdelim(&s, (size_t [1]){0}, 0, f) < 0 ? 0 : s;
}

static int do_wordexp(const char *s, wordexp_t *we, int flags)
{
	size_t i, l;
	int sq=0, dq=0;
	size_t np=0;
	char *w, **tmp;
	char *redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null";
	int err = 0;
	FILE *f;
	size_t wc = 0;
	char **wv = 0;
	int p[2];
	pid_t pid;
	sigset_t set;

	if (flags & WRDE_REUSE) wordfree(we);

	if (flags & WRDE_NOCMD) for (i=0; s[i]; i++) switch (s[i]) {
	case '\\':
		if (!sq) i++;
		break;
	case '\'':
		if (!dq) sq^=1;
		break;
	case '"':
		if (!sq) dq^=1;
		break;
	case '(':
		if (np) {
			np++;
			break;
		}
	case ')':
		if (np) {
			np--;
			break;
		}
	case '\n':
	case '|':
	case '&':
	case ';':
	case '<':
	case '>':
	case '{':
	case '}':
		if (!(sq|dq|np)) return WRDE_BADCHAR;
		break;
	case '$':
		if (s[i+1]=='(' && s[i+2]=='(') {
			i += 2;
			np += 2;
			break;
		} else if (s[i+1] != '(') break;
	case '`':
		if (sq) break;
		return WRDE_CMDSUB;
	}

	if (flags & WRDE_APPEND) {
		wc = we->we_wordc;
		wv = we->we_wordv;
	}

	i = wc;
	if (flags & WRDE_DOOFFS) {
		if (we->we_offs > SIZE_MAX/sizeof(void *)/4)
			goto nospace;
		i += we->we_offs;
	} else {
		we->we_offs = 0;
	}

	if (pipe2(p, O_CLOEXEC) < 0) goto nospace;
	__block_all_sigs(&set);
	pid = fork();
	__restore_sigs(&set);
	if (pid < 0) {
		close(p[0]);
		close(p[1]);
		goto nospace;
	}
	if (!pid) {
		if (p[1] == 1) fcntl(1, F_SETFD, 0);
		else dup2(p[1], 1);
		execl("/bin/sh", "sh", "-c",
			"eval \"printf %s\\\\\\\\0 x $1 $2\"",
			"sh", s, redir, (char *)0);
		_exit(1);
	}
	close(p[1]);

	f = fdopen(p[0], "r");
	if (!f) {
		close(p[0]);
		kill(pid, SIGKILL);
		reap(pid);
		goto nospace;
	}

	l = wv ? i+1 : 0;

	free(getword(f));
	if (feof(f)) {
		fclose(f);
		reap(pid);
		return WRDE_SYNTAX;
	}

	while ((w = getword(f))) {
		if (i+1 >= l) {
			l += l/2+10;
			tmp = realloc(wv, l*sizeof(char *));
			if (!tmp) break;
			wv = tmp;
		}
		wv[i++] = w;
		wv[i] = 0;
	}
	if (!feof(f)) err = WRDE_NOSPACE;

	fclose(f);
	reap(pid);

	if (!wv) wv = calloc(i+1, sizeof *wv);

	we->we_wordv = wv;
	we->we_wordc = i;

	if (flags & WRDE_DOOFFS) {
		if (wv) for (i=we->we_offs; i; i--)
			we->we_wordv[i-1] = 0;
		we->we_wordc -= we->we_offs;
	}
	return err;

nospace:
	if (!(flags & WRDE_APPEND)) {
		we->we_wordc = 0;
		we->we_wordv = 0;
	}
	return WRDE_NOSPACE;
}

int wordexp(const char *restrict s, wordexp_t *restrict we, int flags)
{
	int r, cs;
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
	r = do_wordexp(s, we, flags);
	pthread_setcancelstate(cs, 0);
	return r;
}

void wordfree(wordexp_t *we)
{
	size_t i;
	if (!we->we_wordv) return;
	for (i=0; i<we->we_wordc; i++) free(we->we_wordv[we->we_offs+i]);
	free(we->we_wordv);
	we->we_wordv = 0;
	we->we_wordc = 0;
}


text:
#include <stdlib.h>
#include <string.h>

int getsubopt(char **opt, char *const *keys, char **val)
{
	char *s = *opt;
	int i;

	*val = NULL;
	*opt = strchr(s, ',');
	if (*opt) *(*opt)++ = 0;
	else *opt = s + strlen(s);

	for (i=0; keys[i]; i++) {
		size_t l = strlen(keys[i]);
		if (strncmp(keys[i], s, l)) continue;
		if (s[l] == '=')
			*val = s + l;
		else if (s[l]) continue;
		return i;
	}
	return -1;
}


text:
#include <sys/resource.h>
#include <errno.h>
#include "syscall.h"
#include "libc.h"

#define MIN(a, b) ((a)<(b) ? (a) : (b))
#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0)

int __setrlimit(int resource, const struct rlimit *rlim)
{
	unsigned long k_rlim[2];
	struct rlimit tmp;
	if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
		tmp = *rlim;
		FIX(tmp.rlim_cur);
		FIX(tmp.rlim_max);
		rlim = &tmp;
	}
	int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
	if (ret != -ENOSYS) return ret;
	k_rlim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY));
	k_rlim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY));
	return __syscall(SYS_setrlimit, resource, k_rlim);
}

struct ctx {
	const struct rlimit *rlim;
	int res;
	int err;
};

static void do_setrlimit(void *p)
{
	struct ctx *c = p;
	if (c->err) return;
	c->err = -__setrlimit(c->res, c->rlim);
}

int setrlimit(int resource, const struct rlimit *rlim)
{
	struct ctx c = { .res = resource, .rlim = rlim };
	__synccall(do_setrlimit, &c);
	if (c.err) {
		errno = c.err;
		return -1;
	}
	return 0;
}

LFS64(setrlimit);


text:
long gethostid()
{
	return 0;
}


text:
#include <sys/ioctl.h>
#include <stdarg.h>
#include "syscall.h"

int ioctl(int fd, int req, ...)
{
	void *arg;
	va_list ap;
	va_start(ap, req);
	arg = va_arg(ap, void *);
	va_end(ap);
	return syscall(SYS_ioctl, fd, req, arg);
}


text:
#include <ftw.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <pthread.h>
#include "libc.h"

struct history
{
	struct history *chain;
	dev_t dev;
	ino_t ino;
	int level;
	int base;
};

#undef dirfd
#define dirfd(d) (*(int *)d)

static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags, struct history *h)
{
	size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
	struct stat st;
	struct history new;
	int type;
	int r;
	struct FTW lev;
	char *name;

	if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
		if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
			type = FTW_SLN;
		else if (errno != EACCES) return -1;
		else type = FTW_NS;
	} else if (S_ISDIR(st.st_mode)) {
		if (access(path, R_OK) < 0) type = FTW_DNR;
		else if (flags & FTW_DEPTH) type = FTW_DP;
		else type = FTW_D;
	} else if (S_ISLNK(st.st_mode)) {
		if (flags & FTW_PHYS) type = FTW_SL;
		else type = FTW_SLN;
	} else {
		type = FTW_F;
	}

	if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
		return 0;

	new.chain = h;
	new.dev = st.st_dev;
	new.ino = st.st_ino;
	new.level = h ? h->level+1 : 0;
	new.base = l+1;

	lev.level = new.level;
	lev.base = h ? h->base : (name=strrchr(path, '/')) ? name-path : 0;

	if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
		return r;

	for (; h; h = h->chain)
		if (h->dev == st.st_dev && h->ino == st.st_ino)
			return 0;

	if ((type == FTW_D || type == FTW_DP) && fd_limit) {
		DIR *d = opendir(path);
		if (d) {
			struct dirent *de;
			while ((de = readdir(d))) {
				if (de->d_name[0] == '.'
				 && (!de->d_name[1]
				  || (de->d_name[1]=='.'
				   && !de->d_name[2]))) continue;
				if (strlen(de->d_name) >= PATH_MAX-l) {
					errno = ENAMETOOLONG;
					closedir(d);
					return -1;
				}
				path[j]='/';
				strcpy(path+j+1, de->d_name);
				if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
					closedir(d);
					return r;
				}
			}
			closedir(d);
		} else if (errno != EACCES) {
			return -1;
		}
	}

	path[l] = 0;
	if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
		return r;

	return 0;
}

int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags)
{
	int r, cs;
	size_t l;
	char pathbuf[PATH_MAX+1];

	if (fd_limit <= 0) return 0;

	l = strlen(path);
	if (l > PATH_MAX) {
		errno = ENAMETOOLONG;
		return -1;
	}
	memcpy(pathbuf, path, l+1);

	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
	r = do_nftw(pathbuf, fn, fd_limit, flags, NULL);
	pthread_setcancelstate(cs, 0);
	return r;
}

LFS64(nftw);


text:
#define _GNU_SOURCE
#include <unistd.h>
#include "syscall.h"

int setdomainname(const char *name, size_t len)
{
	return syscall(SYS_setdomainname, name, len);
}


text:
#include <string.h>
#include <libgen.h>
#include "libc.h"

char *basename(char *s)
{
	size_t i;
	if (!s || !*s) return ".";
	i = strlen(s)-1;
	for (; i&&s[i]=='/'; i--) s[i] = 0;
	for (; i&&s[i-1]!='/'; i--);
	return s+i;
}

weak_alias(basename, __xpg_basename);


text:
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "libc.h"

int lockf(int fd, int op, off_t size)
{
	struct flock l = {
		.l_type = F_WRLCK,
		.l_whence = SEEK_CUR,
		.l_len = size,
	};
	switch (op) {
	case F_TEST:
		l.l_type = F_RDLCK;
		if (fcntl(fd, F_GETLK, &l) < 0)
			return -1;
		if (l.l_type == F_UNLCK || l.l_pid == getpid())
			return 0;
		errno = EACCES;
		return -1;
	case F_ULOCK:
		l.l_type = F_UNLCK;
	case F_TLOCK:
		return fcntl(fd, F_SETLK, &l);
	case F_LOCK:
		return fcntl(fd, F_SETLKW, &l);
	}
	errno = EINVAL;
	return -1;
}

LFS64(lockf);


text:
#include <sys/resource.h>
#include "syscall.h"

int getrusage(int who, struct rusage *ru)
{
	return syscall(SYS_getrusage, who, ru);
}


text:
#define _GNU_SOURCE
#include <grp.h>
#include <string.h>
#include <limits.h>

int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
{
	size_t n, i;
	struct group *gr;
	if (*ngroups<1) return -1;
	n = *ngroups;
	*groups++ = gid;
	*ngroups = 1;

	setgrent();
	while ((gr = getgrent()) && *ngroups < INT_MAX) {
		for (i=0; gr->gr_mem[i] && strcmp(user, gr->gr_mem[i]); i++);
		if (!gr->gr_mem[i]) continue;
		if (++*ngroups <= n) *groups++ = gr->gr_gid;
	}
	endgrent();

	return *ngroups > n ? -1 : *ngroups;
}


text:
static inline struct pthread *__pthread_self()
{
#ifdef __clang__
	char *tp;
	__asm__ __volatile__ ("mr %0, 2" : "=r"(tp) : : );
#else
	register char *tp __asm__("r2");
#endif
	return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
}

#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)

// offset of the PC register in mcontext_t, divided by the system wordsize
// the kernel calls the ip "nip", it's the first saved value after the 32
// GPRs.
#define CANCEL_REG_IP 32


text:
#include <string.h>
#include <elf.h>

#define LDSO_ARCH "powerpc"

#define TPOFF_K (-0x7000)

static int remap_rel(int type)
{
	switch(type) {
	case R_PPC_ADDR32:
		return REL_SYMBOLIC;
	case R_PPC_GLOB_DAT:
		return REL_GOT;
	case R_PPC_JMP_SLOT:
		return REL_PLT;
	case R_PPC_RELATIVE:
		return REL_RELATIVE;
	case R_PPC_COPY:
		return REL_COPY;
	case R_PPC_DTPMOD32:
		return REL_DTPMOD;
	case R_PPC_DTPREL32:
		return REL_DTPOFF;
	case R_PPC_TPREL32:
		return REL_TPOFF;
	}
	return 0;
}

void __reloc_self(int c, size_t *a, size_t *dynv)
{
	char *base;
	size_t t[20], n;
	for (a+=c+1; *a; a++);
	for (a++; *a; a+=2) if (*a<20) t[*a] = a[1];
	base = (char *)t[AT_BASE];
	if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]);
	for (a=dynv; *a; a+=2) if (*a<20) t[*a] = a[1];
	n = t[DT_RELASZ];
	for (a=(void *)(base+t[DT_RELA]); n; a+=3, n-=12)
		if (a[1]%256 == R_PPC_RELATIVE)
			*(size_t *)(base+a[0]) = (size_t)base + a[2];
}


text:
#ifndef _INTERNAL_ATOMIC_H
#define _INTERNAL_ATOMIC_H

#include <stdint.h>
#include <endian.h>

static inline int a_ctz_l(unsigned long x)
{
	static const char debruijn32[32] = {
		0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
		31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
	};
	return debruijn32[(x&-x)*0x076be629 >> 27];
}

static inline int a_ctz_64(uint64_t x)
{
	uint32_t y = x;
	if (!y) {
		y = x>>32;
		return 32 + a_ctz_l(y);
	}
	return a_ctz_l(y);
}

static inline int a_cas(volatile int *p, int t, int s)
{
	__asm__("\n"
		"	sync\n"
		"1:	lwarx %0, 0, %4\n"
		"	cmpw %0, %2\n"
		"	bne 1f\n"
		"	stwcx. %3, 0, %4\n"
		"	bne- 1b\n"
		"	isync\n"
		"1:	\n"
		: "=&r"(t), "+m"(*p) : "r"(t), "r"(s), "r"(p) : "cc", "memory" );
        return t;
}

static inline void *a_cas_p(volatile void *p, void *t, void *s)
{
	return (void *)a_cas(p, (int)t, (int)s);
}

static inline int a_swap(volatile int *x, int v)
{
	int old;
	do old = *x;
	while (a_cas(x, old, v) != old);
	return old;
}

static inline int a_fetch_add(volatile int *x, int v)
{
	int old;
	do old = *x;
	while (a_cas(x, old, old+v) != old);
	return old;
}

static inline void a_inc(volatile int *x)
{
	a_fetch_add(x, 1);
}

static inline void a_dec(volatile int *x)
{
	a_fetch_add(x, -1);
}

static inline void a_store(volatile int *p, int x)
{
	__asm__ __volatile__ ("\n"
		"	sync\n"
		"	stw %1, %0\n"
		"	isync\n"
		: "=m"(*p) : "r"(x) : "memory" );
}

#define a_spin a_barrier

static inline void a_barrier()
{
	a_cas(&(int){0}, 0, 0);
}

static inline void a_crash()
{
	*(volatile char *)0=0;
}

static inline void a_and(volatile int *p, int v)
{
	int old;
	do old = *p;
	while (a_cas(p, old, old&v) != old);
}

static inline void a_or(volatile int *p, int v)
{
	int old;
	do old = *p;
	while (a_cas(p, old, old|v) != old);
}

static inline void a_or_l(volatile void *p, long v)
{
	a_or(p, v);
}

static inline void a_and_64(volatile uint64_t *p, uint64_t v)
{
	union { uint64_t v; uint32_t r[2]; } u = { v };
	a_and((int *)p, u.r[0]);
	a_and((int *)p+1, u.r[1]);
}

static inline void a_or_64(volatile uint64_t *p, uint64_t v)
{
	union { uint64_t v; uint32_t r[2]; } u = { v };
	a_or((int *)p, u.r[0]);
	a_or((int *)p+1, u.r[1]);
}

#endif


text:
#define __SYSCALL_LL_E(x) \
((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
((union { long long ll; long l[2]; }){ .ll = x }).l[1]
#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))

long (__syscall)(long, ...);

static inline long __syscall0(long n)
{
	return (__syscall)(n, 0, 0, 0, 0, 0, 0);
}

static inline long __syscall1(long n, long a)
{
	return (__syscall)(n, a, 0, 0, 0, 0, 0);
}

static inline long __syscall2(long n, long a, long b)
{
	return (__syscall)(n, a, b, 0, 0, 0, 0);
}

static inline long __syscall3(long n, long a, long b, long c)
{
	return (__syscall)(n, a, b, c, 0, 0, 0);
}

static inline long __syscall4(long n, long a, long b, long c, long d)
{
	return (__syscall)(n, a, b, c, d, 0, 0);
}

static inline long __syscall5(long n, long a, long b, long c, long d, long e)
{
	return (__syscall)(n, a, b, c, d, e, 0);
}

static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
{
	return (__syscall)(n, a, b, c, d, e, f);
}


text:
__asm__("\
.global _start \n\
.type   _start, %function \n\
_start: \n\
	mr 3, 1 \n\
	clrrwi 1, 1, 4 \n\
	li 0, 0 \n\
	stwu 1, -16(1) \n\
	mtlr 0 \n\
	stw 0, 0(1) \n\
	bl __cstart \n\
");


text:
struct pt_regs {
	unsigned long gpr[32], nip, msr, orig_gpr3, ctr, link, xer, ccr, mq;
	unsigned long trap, dar, dsisr, result;
};

struct user {
	struct pt_regs regs;
	unsigned long u_tsize, u_dsize, u_ssize;
	unsigned long start_code, start_data, start_stack;
	long signal;
	void *u_ar0;
	unsigned long magic;
	char u_comm[32];
};

#define ELF_NGREG 48
#define ELF_NFPREG 33
#define ELF_NVRREG 33
typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
typedef double elf_fpreg_t, elf_fpregset_t[ELF_NFPREG];
typedef struct { unsigned u[4]; }
#ifdef __GNUC__
__attribute__((__aligned__(16)))
#endif
	elf_vrreg_t, elf_vrregset_t[ELF_NVRREG];


text:
#ifdef __BIG_ENDIAN__
  #if __BIG_ENDIAN__
    #define __BYTE_ORDER __BIG_ENDIAN
  #endif
#endif /* __BIG_ENDIAN__ */

#ifdef __LITTLE_ENDIAN__
  #if __LITTLE_ENDIAN__
    #define __BYTE_ORDER __LITTLE_ENDIAN
  #endif
#endif /* __LITTLE_ENDIAN__ */

#ifndef __BYTE_ORDER
  #define __BYTE_ORDER __BIG_ENDIAN
#endif


text:
#define FLT_ROUNDS 1
#define FLT_EVAL_METHOD 0

#define LDBL_TRUE_MIN 4.94065645841246544177e-324L
#define LDBL_MIN 2.22507385850720138309e-308L
#define LDBL_MAX 1.79769313486231570815e+308L
#define LDBL_EPSILON 2.22044604925031308085e-16L

#define LDBL_MANT_DIG 53
#define LDBL_MIN_EXP (-1021)
#define LDBL_MAX_EXP 1024

#define LDBL_DIG 15
#define LDBL_MIN_10_EXP (-307)
#define LDBL_MAX_10_EXP 308

#define DECIMAL_DIG 17


text:
#define FE_TONEAREST	0
#define FE_TOWARDZERO	1
#define FE_UPWARD	2
#define FE_DOWNWARD	3

#define FE_INEXACT	0x02000000
#define FE_DIVBYZERO	0x04000000
#define FE_UNDERFLOW	0x08000000
#define FE_OVERFLOW	0x10000000
#define FE_INVALID	0x20000000

#define FE_ALL_EXCEPT	0x3e000000

#ifdef _GNU_SOURCE
#define FE_INVALID_SNAN		0x01000000
#define FE_INVALID_ISI		0x00800000
#define FE_INVALID_IDI		0x00400000
#define FE_INVALID_ZDZ		0x00200000
#define FE_INVALID_IMZ		0x00100000
#define FE_INVALID_COMPARE	0x00080000
#define FE_INVALID_SOFTWARE	0x00000400
#define FE_INVALID_SQRT		0x00000200
#define FE_INVALID_INTEGER_CONVERSION	0x00000100

#define FE_ALL_INVALID		0x01f80700
#endif

typedef unsigned fexcept_t;
typedef double fenv_t;

#define FE_DFL_ENV ((const fenv_t *)-1)