summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/gen
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/gen
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/gen')
-rwxr-xr-xsys/src/ape/lib/ap/gen/_assert.c18
-rwxr-xr-xsys/src/ape/lib/ap/gen/abort.c9
-rwxr-xr-xsys/src/ape/lib/ap/gen/abs.c17
-rwxr-xr-xsys/src/ape/lib/ap/gen/atof.c7
-rwxr-xr-xsys/src/ape/lib/ap/gen/atoi.c7
-rwxr-xr-xsys/src/ape/lib/ap/gen/atol.c7
-rwxr-xr-xsys/src/ape/lib/ap/gen/atoll.c7
-rwxr-xr-xsys/src/ape/lib/ap/gen/bsearch.c24
-rwxr-xr-xsys/src/ape/lib/ap/gen/calloc.c13
-rwxr-xr-xsys/src/ape/lib/ap/gen/clock.c12
-rwxr-xr-xsys/src/ape/lib/ap/gen/ctype.c56
-rwxr-xr-xsys/src/ape/lib/ap/gen/difftime.c9
-rwxr-xr-xsys/src/ape/lib/ap/gen/div.c9
-rwxr-xr-xsys/src/ape/lib/ap/gen/getenv.c18
-rwxr-xr-xsys/src/ape/lib/ap/gen/isalnum.c24
-rwxr-xr-xsys/src/ape/lib/ap/gen/itoa.c7
-rwxr-xr-xsys/src/ape/lib/ap/gen/itol.c7
-rwxr-xr-xsys/src/ape/lib/ap/gen/ldiv.c9
-rwxr-xr-xsys/src/ape/lib/ap/gen/mbwc.c165
-rwxr-xr-xsys/src/ape/lib/ap/gen/memccpy.c17
-rwxr-xr-xsys/src/ape/lib/ap/gen/memchr.c16
-rwxr-xr-xsys/src/ape/lib/ap/gen/memcmp.c22
-rwxr-xr-xsys/src/ape/lib/ap/gen/memmove.c35
-rwxr-xr-xsys/src/ape/lib/ap/gen/memset.c14
-rwxr-xr-xsys/src/ape/lib/ap/gen/mkfile63
-rwxr-xr-xsys/src/ape/lib/ap/gen/mktime.c122
-rwxr-xr-xsys/src/ape/lib/ap/gen/qsort.c90
-rwxr-xr-xsys/src/ape/lib/ap/gen/raise.c11
-rwxr-xr-xsys/src/ape/lib/ap/gen/rand.c75
-rwxr-xr-xsys/src/ape/lib/ap/gen/reduce16
-rwxr-xr-xsys/src/ape/lib/ap/gen/strcat.c9
-rwxr-xr-xsys/src/ape/lib/ap/gen/strchr.c18
-rwxr-xr-xsys/src/ape/lib/ap/gen/strcmp.c19
-rwxr-xr-xsys/src/ape/lib/ap/gen/strcoll.c8
-rwxr-xr-xsys/src/ape/lib/ap/gen/strcpy.c30
-rwxr-xr-xsys/src/ape/lib/ap/gen/strcspn.c20
-rwxr-xr-xsys/src/ape/lib/ap/gen/strftime.c202
-rwxr-xr-xsys/src/ape/lib/ap/gen/strlen.c8
-rwxr-xr-xsys/src/ape/lib/ap/gen/strncat.c20
-rwxr-xr-xsys/src/ape/lib/ap/gen/strncmp.c23
-rwxr-xr-xsys/src/ape/lib/ap/gen/strncpy.c17
-rwxr-xr-xsys/src/ape/lib/ap/gen/strpbrk.c20
-rwxr-xr-xsys/src/ape/lib/ap/gen/strrchr.c14
-rwxr-xr-xsys/src/ape/lib/ap/gen/strspn.c17
-rwxr-xr-xsys/src/ape/lib/ap/gen/strstr.c27
-rwxr-xr-xsys/src/ape/lib/ap/gen/strtod.c91
-rwxr-xr-xsys/src/ape/lib/ap/gen/strtok.c36
-rwxr-xr-xsys/src/ape/lib/ap/gen/strtol.c94
-rwxr-xr-xsys/src/ape/lib/ap/gen/strtoll.c103
-rwxr-xr-xsys/src/ape/lib/ap/gen/strtoul.c92
-rwxr-xr-xsys/src/ape/lib/ap/gen/strtoull.c100
-rwxr-xr-xsys/src/ape/lib/ap/gen/strxfrm.c17
-rwxr-xr-xsys/src/ape/lib/ap/gen/toupper.c17
53 files changed, 1908 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/gen/_assert.c b/sys/src/ape/lib/ap/gen/_assert.c
new file mode 100755
index 000000000..e39e147a4
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/_assert.c
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+
+void
+_assert(char *f, unsigned line)
+{
+ char buf[20], *p, *s = &buf[20];
+ write(2, "assertion failed: file ", 23);
+ for(p = f; *p; p++) continue;
+ write(2, f, p-f);
+ write(2, ":", 7);
+ *--s = '\n';
+ do *--s = line%10 + '0'; while (line /= 10);
+ write(2, s, &buf[20] - s);
+ abort();
+
+}
diff --git a/sys/src/ape/lib/ap/gen/abort.c b/sys/src/ape/lib/ap/gen/abort.c
new file mode 100755
index 000000000..67b878541
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/abort.c
@@ -0,0 +1,9 @@
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+
+void
+abort(void)
+{
+ kill(getpid(), SIGABRT);
+}
diff --git a/sys/src/ape/lib/ap/gen/abs.c b/sys/src/ape/lib/ap/gen/abs.c
new file mode 100755
index 000000000..7d670ffb3
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/abs.c
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+abs(int a)
+{
+ if(a < 0)
+ return -a;
+ return a;
+}
+
+long
+labs(long a)
+{
+ if(a < 0)
+ return -a;
+ return a;
+}
diff --git a/sys/src/ape/lib/ap/gen/atof.c b/sys/src/ape/lib/ap/gen/atof.c
new file mode 100755
index 000000000..63b8bfea4
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/atof.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+double
+atof(const char *s)
+{
+ return(strtod(s, (char **)0));
+}
diff --git a/sys/src/ape/lib/ap/gen/atoi.c b/sys/src/ape/lib/ap/gen/atoi.c
new file mode 100755
index 000000000..8b9bddd41
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/atoi.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+int
+atoi(const char *s)
+{
+ return(strtol(s, (char **)0, 10));
+}
diff --git a/sys/src/ape/lib/ap/gen/atol.c b/sys/src/ape/lib/ap/gen/atol.c
new file mode 100755
index 000000000..41e6040fe
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/atol.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+long
+atol(const char *s)
+{
+ return(strtol(s, (char **)0, 10));
+}
diff --git a/sys/src/ape/lib/ap/gen/atoll.c b/sys/src/ape/lib/ap/gen/atoll.c
new file mode 100755
index 000000000..55f28000a
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/atoll.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+long long
+atoll(const char *s)
+{
+ return(strtoll(s, (char **)0, 10));
+}
diff --git a/sys/src/ape/lib/ap/gen/bsearch.c b/sys/src/ape/lib/ap/gen/bsearch.c
new file mode 100755
index 000000000..ae0342f99
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/bsearch.c
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include <stdio.h>
+void*
+bsearch(const void* key, const void* base, size_t nmemb, size_t size,
+ int (*compar)(const void*, const void*))
+{
+ long i, bot, top, new;
+ void *p;
+
+ bot = 0;
+ top = bot + nmemb - 1;
+ while(bot <= top){
+ new = (top + bot)/2;
+ p = (char *)base+new*size;
+ i = (*compar)(key, p);
+ if(i == 0)
+ return p;
+ if(i > 0)
+ bot = new + 1;
+ else
+ top = new - 1;
+ }
+ return 0;
+}
diff --git a/sys/src/ape/lib/ap/gen/calloc.c b/sys/src/ape/lib/ap/gen/calloc.c
new file mode 100755
index 000000000..e52210d84
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/calloc.c
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include <string.h>
+
+void *
+calloc(size_t nmemb, size_t size)
+{
+ void *mp;
+
+ nmemb = nmemb*size;
+ if(mp = malloc(nmemb))
+ memset(mp, 0, nmemb);
+ return(mp);
+}
diff --git a/sys/src/ape/lib/ap/gen/clock.c b/sys/src/ape/lib/ap/gen/clock.c
new file mode 100755
index 000000000..d7d5d4b67
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/clock.c
@@ -0,0 +1,12 @@
+#include <time.h>
+#include <sys/times.h>
+
+clock_t
+clock(void)
+{
+ struct tms t;
+
+ if(times(&t) == (clock_t)-1)
+ return (clock_t)-1;
+ return t.tms_utime+t.tms_stime;
+}
diff --git a/sys/src/ape/lib/ap/gen/ctype.c b/sys/src/ape/lib/ap/gen/ctype.c
new file mode 100755
index 000000000..3829a171a
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/ctype.c
@@ -0,0 +1,56 @@
+#include <ctype.h>
+
+unsigned char _ctype[] =
+{
+/* 0 1 2 3 */
+/* 4 5 6 7 */
+
+/* 0*/ _IScntrl, _IScntrl, _IScntrl, _IScntrl,
+ _IScntrl, _IScntrl, _IScntrl, _IScntrl,
+/* 10*/ _IScntrl, _ISspace|_IScntrl, _ISspace|_IScntrl, _ISspace|_IScntrl,
+ _ISspace|_IScntrl, _ISspace|_IScntrl, _IScntrl, _IScntrl,
+/* 20*/ _IScntrl, _IScntrl, _IScntrl, _IScntrl,
+ _IScntrl, _IScntrl, _IScntrl, _IScntrl,
+/* 30*/ _IScntrl, _IScntrl, _IScntrl, _IScntrl,
+ _IScntrl, _IScntrl, _IScntrl, _IScntrl,
+/* 40*/ _ISspace|_ISblank, _ISpunct, _ISpunct, _ISpunct,
+ _ISpunct, _ISpunct, _ISpunct, _ISpunct,
+/* 50*/ _ISpunct, _ISpunct, _ISpunct, _ISpunct,
+ _ISpunct, _ISpunct, _ISpunct, _ISpunct,
+/* 60*/ _ISdigit|_ISxdigit, _ISdigit|_ISxdigit, _ISdigit|_ISxdigit, _ISdigit|_ISxdigit,
+ _ISdigit|_ISxdigit, _ISdigit|_ISxdigit, _ISdigit|_ISxdigit, _ISdigit|_ISxdigit,
+/* 70*/ _ISdigit|_ISxdigit, _ISdigit|_ISxdigit, _ISpunct, _ISpunct,
+ _ISpunct, _ISpunct, _ISpunct, _ISpunct,
+/*100*/ _ISpunct, _ISupper|_ISxdigit, _ISupper|_ISxdigit, _ISupper|_ISxdigit,
+ _ISupper|_ISxdigit, _ISupper|_ISxdigit, _ISupper|_ISxdigit, _ISupper,
+/*110*/ _ISupper, _ISupper, _ISupper, _ISupper,
+ _ISupper, _ISupper, _ISupper, _ISupper,
+/*120*/ _ISupper, _ISupper, _ISupper, _ISupper,
+ _ISupper, _ISupper, _ISupper, _ISupper,
+/*130*/ _ISupper, _ISupper, _ISupper, _ISpunct,
+ _ISpunct, _ISpunct, _ISpunct, _ISpunct,
+/*140*/ _ISpunct, _ISlower|_ISxdigit, _ISlower|_ISxdigit, _ISlower|_ISxdigit,
+ _ISlower|_ISxdigit, _ISlower|_ISxdigit, _ISlower|_ISxdigit, _ISlower,
+/*150*/ _ISlower, _ISlower, _ISlower, _ISlower,
+ _ISlower, _ISlower, _ISlower, _ISlower,
+/*160*/ _ISlower, _ISlower, _ISlower, _ISlower,
+ _ISlower, _ISlower, _ISlower, _ISlower,
+/*170*/ _ISlower, _ISlower, _ISlower, _ISpunct,
+ _ISpunct, _ISpunct, _ISpunct, _IScntrl,
+/*200*/ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
diff --git a/sys/src/ape/lib/ap/gen/difftime.c b/sys/src/ape/lib/ap/gen/difftime.c
new file mode 100755
index 000000000..97ac3cee9
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/difftime.c
@@ -0,0 +1,9 @@
+#include <time.h>
+
+/* Difference in seconds between two calendar times */
+
+double
+difftime(time_t t1, time_t t0)
+{
+ return (double)t1-(double)t0;
+}
diff --git a/sys/src/ape/lib/ap/gen/div.c b/sys/src/ape/lib/ap/gen/div.c
new file mode 100755
index 000000000..10d92d97b
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/div.c
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+
+div_t div(int numer, int denom)
+{
+ div_t ans;
+ ans.quot=numer/denom; /* assumes division truncates */
+ ans.rem=numer-ans.quot*denom;
+ return ans;
+}
diff --git a/sys/src/ape/lib/ap/gen/getenv.c b/sys/src/ape/lib/ap/gen/getenv.c
new file mode 100755
index 000000000..e911d3298
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/getenv.c
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+
+extern char **environ;
+
+char *
+getenv(const char *name)
+{
+ char **p = environ;
+ char *v, *s1, *s2;
+
+ while (*p != NULL){
+ for(s1 = (char *)name, s2 = *p++; *s1 == *s2; s1++, s2++)
+ continue;
+ if(*s1 == '\0' && *s2 == '=')
+ return s2+1;
+ }
+ return NULL ;
+}
diff --git a/sys/src/ape/lib/ap/gen/isalnum.c b/sys/src/ape/lib/ap/gen/isalnum.c
new file mode 100755
index 000000000..e1ab47cde
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/isalnum.c
@@ -0,0 +1,24 @@
+#include <ctype.h>
+
+#undef isalnum
+#undef isalpha
+#undef iscntrl
+#undef isdigit
+#undef isgraph
+#undef islower
+#undef isprint
+#undef ispunct
+#undef isspace
+#undef isupper
+#undef isxdigit
+int isalnum(int c){ return (_ctype+1)[c]&(_ISupper|_ISlower|_ISdigit); }
+int isalpha(int c){ return (_ctype+1)[c]&(_ISupper|_ISlower); }
+int iscntrl(int c){ return (_ctype+1)[c]&_IScntrl; }
+int isdigit(int c){ return (_ctype+1)[c]&_ISdigit; }
+int isgraph(int c){ return (_ctype+1)[c]&(_ISpunct|_ISupper|_ISlower|_ISdigit); }
+int islower(int c){ return (_ctype+1)[c]&_ISlower; }
+int isprint(int c){ return (_ctype+1)[c]&(_ISpunct|_ISupper|_ISlower|_ISdigit|_ISblank); }
+int ispunct(int c){ return (_ctype+1)[c]&_ISpunct; }
+int isspace(int c){ return (_ctype+1)[c]&_ISspace; }
+int isupper(int c){ return (_ctype+1)[c]&_ISupper; }
+int isxdigit(int c){ return (_ctype+1)[c]&_ISxdigit; }
diff --git a/sys/src/ape/lib/ap/gen/itoa.c b/sys/src/ape/lib/ap/gen/itoa.c
new file mode 100755
index 000000000..9e686556b
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/itoa.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+int
+itoa(const char *s)
+{
+ return(strtol(s, (char **)0, 10));
+}
diff --git a/sys/src/ape/lib/ap/gen/itol.c b/sys/src/ape/lib/ap/gen/itol.c
new file mode 100755
index 000000000..a618acc8a
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/itol.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+long
+itol(const char *s)
+{
+ return(strtol(s, (char **)0, 10));
+}
diff --git a/sys/src/ape/lib/ap/gen/ldiv.c b/sys/src/ape/lib/ap/gen/ldiv.c
new file mode 100755
index 000000000..01313e6ac
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/ldiv.c
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+
+ldiv_t ldiv(long int numer, long int denom)
+{
+ ldiv_t ans;
+ ans.quot=numer/denom;
+ ans.rem=numer-ans.quot*denom;
+ return ans;
+}
diff --git a/sys/src/ape/lib/ap/gen/mbwc.c b/sys/src/ape/lib/ap/gen/mbwc.c
new file mode 100755
index 000000000..66a982193
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/mbwc.c
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+
+/*
+ * Use the FSS-UTF transformation proposed by posix.
+ * We define 7 byte types:
+ * T0 0xxxxxxx 7 free bits
+ * Tx 10xxxxxx 6 free bits
+ * T1 110xxxxx 5 free bits
+ * T2 1110xxxx 4 free bits
+ *
+ * Encoding is as follows.
+ * From hex Thru hex Sequence Bits
+ * 00000000 0000007F T0 7
+ * 00000080 000007FF T1 Tx 11
+ * 00000800 0000FFFF T2 Tx Tx 16
+ */
+
+int
+mblen(const char *s, size_t n)
+{
+
+ return mbtowc(0, s, n);
+}
+
+int
+mbtowc(wchar_t *pwc, const char *s, size_t n)
+{
+ int c, c1, c2;
+ long l;
+
+ if(!s)
+ return 0;
+
+ if(n < 1)
+ goto bad;
+ c = s[0] & 0xff;
+ if((c & 0x80) == 0x00) {
+ if(pwc)
+ *pwc = c;
+ if(c == 0)
+ return 0;
+ return 1;
+ }
+
+ if(n < 2)
+ goto bad;
+ c1 = (s[1] ^ 0x80) & 0xff;
+ if((c1 & 0xC0) != 0x00)
+ goto bad;
+ if((c & 0xE0) == 0xC0) {
+ l = ((c << 6) | c1) & 0x7FF;
+ if(l < 0x080)
+ goto bad;
+ if(pwc)
+ *pwc = l;
+ return 2;
+ }
+
+ if(n < 3)
+ goto bad;
+ c2 = (s[2] ^ 0x80) & 0xff;
+ if((c2 & 0xC0) != 0x00)
+ goto bad;
+ if((c & 0xF0) == 0xE0) {
+ l = ((((c << 6) | c1) << 6) | c2) & 0xFFFF;
+ if(l < 0x0800)
+ goto bad;
+ if(pwc)
+ *pwc = l;
+ return 3;
+ }
+
+ /*
+ * bad decoding
+ */
+bad:
+ return -1;
+
+}
+
+int
+wctomb(char *s, wchar_t wchar)
+{
+ long c;
+
+ if(!s)
+ return 0;
+
+ c = wchar & 0xFFFF;
+ if(c < 0x80) {
+ s[0] = c;
+ return 1;
+ }
+
+ if(c < 0x800) {
+ s[0] = 0xC0 | (c >> 6);
+ s[1] = 0x80 | (c & 0x3F);
+ return 2;
+ }
+
+ s[0] = 0xE0 | (c >> 12);
+ s[1] = 0x80 | ((c >> 6) & 0x3F);
+ s[2] = 0x80 | (c & 0x3F);
+ return 3;
+}
+
+size_t
+mbstowcs(wchar_t *pwcs, const char *s, size_t n)
+{
+ int i, d, c;
+
+ for(i=0; i < n; i++) {
+ c = *s & 0xff;
+ if(c < 0x80) {
+ *pwcs = c;
+ if(c == 0)
+ break;
+ s++;
+ } else {
+ d = mbtowc(pwcs, s, 3);
+ if(d <= 0)
+ return (size_t)((d<0) ? -1 : i);
+ s += d;
+ }
+ pwcs++;
+ }
+ return i;
+}
+
+size_t
+wcstombs(char *s, const wchar_t *pwcs, size_t n)
+{
+ int i, d;
+ long c;
+ char *p, *pe;
+ char buf[3];
+
+ p = s;
+ pe = p+n-3;
+ while(p < pe) {
+ c = *pwcs++;
+ if(c < 0x80)
+ *p++ = c;
+ else
+ p += wctomb(p, c);
+ if(c == 0)
+ return p-s;
+ }
+ while(p < pe+3) {
+ c = *pwcs++;
+ d = wctomb(buf, c);
+ if(p+d <= pe+3) {
+ *p++ = buf[0];
+ if(d > 1) {
+ *p++ = buf[2];
+ if(d > 2)
+ *p++ = buf[3];
+ }
+ }
+ if(c == 0)
+ break;
+ }
+ return p-s;
+}
+
diff --git a/sys/src/ape/lib/ap/gen/memccpy.c b/sys/src/ape/lib/ap/gen/memccpy.c
new file mode 100755
index 000000000..2f7b610d2
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/memccpy.c
@@ -0,0 +1,17 @@
+#include <string.h>
+
+void*
+memccpy(void *a1, void *a2, int c, size_t n)
+{
+ unsigned char *s1, *s2;
+
+ s1 = a1;
+ s2 = a2;
+ c &= 0xFF;
+ while(n > 0) {
+ if((*s1++ = *s2++) == c)
+ return s1;
+ n--;
+ }
+ return 0;
+}
diff --git a/sys/src/ape/lib/ap/gen/memchr.c b/sys/src/ape/lib/ap/gen/memchr.c
new file mode 100755
index 000000000..e63aefe8e
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/memchr.c
@@ -0,0 +1,16 @@
+#include <string.h>
+
+void*
+memchr(const void *ap, int c, size_t n)
+{
+ unsigned char *sp;
+
+ sp = ap;
+ c &= 0xFF;
+ while(n > 0) {
+ if(*sp++ == c)
+ return sp-1;
+ n--;
+ }
+ return 0;
+}
diff --git a/sys/src/ape/lib/ap/gen/memcmp.c b/sys/src/ape/lib/ap/gen/memcmp.c
new file mode 100755
index 000000000..c07fbd0e9
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/memcmp.c
@@ -0,0 +1,22 @@
+#include <string.h>
+
+int
+memcmp(const void *a1, const void *a2, size_t n)
+{
+ char *s1, *s2;
+ unsigned c1, c2;
+
+ s1 = a1;
+ s2 = a2;
+ while(n > 0) {
+ c1 = *s1++;
+ c2 = *s2++;
+ if(c1 != c2) {
+ if(c1 > c2)
+ return 1;
+ return -1;
+ }
+ n--;
+ }
+ return 0;
+}
diff --git a/sys/src/ape/lib/ap/gen/memmove.c b/sys/src/ape/lib/ap/gen/memmove.c
new file mode 100755
index 000000000..7eec93f68
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/memmove.c
@@ -0,0 +1,35 @@
+#include <string.h>
+
+void*
+memmove(void *a1, const void *a2, size_t n)
+{
+ char *s1, *s2;
+ extern void abort(void);
+
+ if((long)n < 0)
+ abort();
+ if(a1 > a2)
+ goto back;
+ s1 = a1;
+ s2 = a2;
+ while(n > 0) {
+ *s1++ = *s2++;
+ n--;
+ }
+ return a1;
+
+back:
+ s1 = (char*)a1 + n;
+ s2 = (char*)a2 + n;
+ while(n > 0) {
+ *--s1 = *--s2;
+ n--;
+ }
+ return a1;
+}
+
+void*
+memcpy(void *a1, const void *a2, size_t n)
+{
+ return memmove(a1, a2, n);
+}
diff --git a/sys/src/ape/lib/ap/gen/memset.c b/sys/src/ape/lib/ap/gen/memset.c
new file mode 100755
index 000000000..902874412
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/memset.c
@@ -0,0 +1,14 @@
+#include <string.h>
+
+void*
+memset(void *ap, int c, size_t n)
+{
+ char *p;
+
+ p = ap;
+ while(n > 0) {
+ *p++ = c;
+ n--;
+ }
+ return ap;
+}
diff --git a/sys/src/ape/lib/ap/gen/mkfile b/sys/src/ape/lib/ap/gen/mkfile
new file mode 100755
index 000000000..e9653bba1
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/mkfile
@@ -0,0 +1,63 @@
+APE=/sys/src/ape
+<$APE/config
+LIB=/$objtype/lib/ape/libap.a
+
+ALLOFILES=\
+ _assert.$O\
+ abort.$O\
+ abs.$O\
+ atof.$O\
+ atoi.$O\
+ atol.$O\
+ atoll.$O\
+ bsearch.$O\
+ calloc.$O\
+ clock.$O\
+ ctype.$O\
+ difftime.$O\
+ div.$O\
+ getenv.$O\
+ isalnum.$O\
+ itoa.$O\
+ itol.$O\
+ ldiv.$O\
+ mbwc.$O\
+ memccpy.$O\
+ memchr.$O\
+ memcmp.$O\
+ memmove.$O\
+ memset.$O\
+ mktime.$O\
+ qsort.$O\
+ raise.$O\
+ rand.$O\
+ strcat.$O\
+ strchr.$O\
+ strcmp.$O\
+ strcoll.$O\
+ strcpy.$O\
+ strcspn.$O\
+ strftime.$O\
+ strlen.$O\
+ strncat.$O\
+ strncmp.$O\
+ strncpy.$O\
+ strpbrk.$O\
+ strrchr.$O\
+ strspn.$O\
+ strstr.$O\
+ strtod.$O\
+ strtok.$O\
+ strtol.$O\
+ strtoll.$O\
+ strtoul.$O\
+ strtoull.$O\
+ strxfrm.$O\
+ toupper.$O\
+
+# cull things in the per-machine directories from this list
+OFILES= `{rc ./reduce $O $objtype $ALLOFILES}
+
+</sys/src/cmd/mksyslib
+
+CFLAGS=-c -D_POSIX_SOURCE
diff --git a/sys/src/ape/lib/ap/gen/mktime.c b/sys/src/ape/lib/ap/gen/mktime.c
new file mode 100755
index 000000000..2c8fa79fa
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/mktime.c
@@ -0,0 +1,122 @@
+#include <time.h>
+
+/*
+ * BUG: Doesn't do leap years in full glory,
+ * or calendar changes. In 2038 the sign bit
+ * will be needed in time_t, but we say it
+ * can't be represented.
+ */
+static int
+dysize(int y)
+{
+ y += 1900; /* arg is a tm_year, number of years since 1900 */
+ if((y%4) == 0 && ((y%100) !=0 || (y%400) == 0))
+ return 366;
+ return 365;
+}
+
+static int
+dmsize(int m, int y)
+{
+ static char sizes[12] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ if(m == 1)
+ return (dysize(y)==366)? 29 : 28;
+ else
+ return sizes[m];
+}
+
+/* Reduce *v to [0, mult), adding 1 to *next for every mult
+ * subtracted from *v, and return 1 if reduction worked (no overflow)
+ */
+static int
+reduce(int *v, int *next, int mult)
+{
+ int oldnext;
+
+ while(*v < 0){
+ *v += mult;
+ oldnext = *next;
+ --*next;
+ if(!(*next < oldnext))
+ return 0;
+ }
+ while(*v >= mult){
+ *v -= mult;
+ oldnext = *next;
+ ++*next;
+ if(!(*next > oldnext))
+ return 0;
+ }
+ return 1;
+}
+
+static int
+jan1(int yr)
+{
+ int y, d;
+
+ y = yr+1900;
+ d = (4+y+(y+3)/4-(y-1701)/100+(y-1601)/400+3)%7;
+ return d;
+}
+
+time_t
+mktime(struct tm *t)
+{
+ time_t a;
+ int i, d;
+ struct tm *ptm;
+
+ if(!(reduce(&t->tm_sec, &t->tm_min, 60) &&
+ reduce(&t->tm_min, &t->tm_hour, 60) &&
+ reduce(&t->tm_hour, &t->tm_mday, 24) &&
+ reduce(&t->tm_mon, &t->tm_year, 12)))
+ return -1;
+ while(t->tm_mday < 1){
+ if(--t->tm_mon == -1){
+ t->tm_mon = 11;
+ t->tm_year--;
+ }
+ t->tm_mday += dmsize(t->tm_mon, t->tm_year);
+ }
+ while(t->tm_mday > dmsize(t->tm_mon, t->tm_year)){
+ t->tm_mday -= dmsize(t->tm_mon, t->tm_year);
+ if(++t->tm_mon == 12){
+ t->tm_mon = 0;
+ t->tm_year++;
+ }
+ }
+ a = t->tm_sec + 60*t->tm_min + 3600*t->tm_hour;
+ t->tm_yday = t->tm_mday-1;
+ for(i=0; i<t->tm_mon; i++)
+ t->tm_yday += dmsize(i, t->tm_year);
+ a += t->tm_yday*86400L;
+ if(t->tm_year < 70){
+ for(i=t->tm_year; i<70; i++)
+ if((a -= dysize(i)*86400L) < 0)
+ return -1;
+ }else if(t->tm_year > 70){
+ for(i=70; i<t->tm_year; i++)
+ if((a += dysize(i)*86400L) < 0)
+ return -1;
+ }
+ /*
+ * Now a is number of seconds past Jan 1 1970.
+ * Convert to GMT.
+ */
+ ptm = gmtime(&a);
+ d = ptm->tm_hour;
+ ptm = localtime(&a);
+ d -= ptm->tm_hour;
+ if(d < 0)
+ d += 24;
+ if(t->tm_isdst == 0 && ptm->tm_isdst)
+ d--;
+ if(t->tm_isdst > 0 && !ptm->tm_isdst)
+ d++;
+ a += d*3600;
+ t->tm_wday = (jan1(t->tm_year)+t->tm_yday)%7;
+ return a;
+}
diff --git a/sys/src/ape/lib/ap/gen/qsort.c b/sys/src/ape/lib/ap/gen/qsort.c
new file mode 100755
index 000000000..e3fb9d12f
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/qsort.c
@@ -0,0 +1,90 @@
+/* qsort -- qsort interface implemented by faster quicksort */
+#include <stdlib.h>
+
+#define SWAPINIT(a, es) swaptype = \
+ (a - (char*) 0) % sizeof(long) || es % sizeof(long) ? 2 : \
+ es == sizeof(long) ? 0 : 1;
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / (int) sizeof(TYPE); \
+ register TYPE *pi = (TYPE *) (parmi); \
+ register TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ register TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+static void swapfunc(char *a, char *b, int n, int swaptype)
+{ if (swaptype <= 1) swapcode(long, a, b, n)
+ else swapcode(char, a, b, n)
+}
+#define swap(a, b) { \
+ if (swaptype == 0) { \
+ long t = * (long *) (a); \
+ * (long *) (a) = * (long *) (b); \
+ * (long *) (b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype); \
+}
+#define vecswap(a, b, n) { if (n > 0) swapfunc(a, b, n*es, swaptype); }
+
+static char *med3func(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
+{ return cmp(a, b) < 0 ?
+ (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ) )
+ : (cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ) );
+}
+#define med3(a, b, c) med3func(a, b, c, cmp)
+
+void qsort(void *va, size_t n, size_t es, int (*cmp)(const void *, const void *))
+{
+ char *a, *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int r, swaptype, na, nb, nc, nd, d;
+
+ a = va;
+ SWAPINIT(a, es);
+ if (n < 7) { /* Insertion sort on small arrays */
+ for (pm = a + es; pm < a + n*es; pm += es)
+ for (pl = pm; pl > a && cmp(pl-es, pl) > 0; pl -= es)
+ swap(pl, pl-es);
+ return;
+ }
+ pm = a + (n/2) * es;
+ if (n > 7) {
+ pl = a;
+ pn = a + (n-1) * es;
+ if (n > 40) { /* On big arrays, pseudomedian of 9 */
+ d = (n/8) * es;
+ pl = med3(pl, pl+d, pl+2*d);
+ pm = med3(pm-d, pm, pm+d);
+ pn = med3(pn-2*d, pn-d, pn);
+ }
+ pm = med3(pl, pm, pn); /* On medium arrays, median of 3 */
+ }
+ swap(a, pm); /* On tiny arrays, partition around middle */
+ pa = pb = a + es;
+ pc = pd = pn = a + (n-1)*es;
+ for (;;) {
+ while (pb <= pc && (r = cmp(pb, a)) <= 0) {
+ if (r == 0) { swap(pa, pb); pa += es; }
+ pb += es;
+ }
+ while (pb <= pc && (r = cmp(pc, a)) >= 0) {
+ if (r == 0) { swap(pc, pd); pd -= es; }
+ pc -= es;
+ }
+ if (pb > pc) break;
+ swap(pb, pc);
+ pb += es;
+ pc -= es;
+ }
+ na = (pa - a) / es;
+ nb = (pb - pa) / es;
+ nc = (pd - pc) / es;
+ nd = (pn - pd) / es;
+ if (na < nb) { vecswap(a, a + nb*es, na); }
+ else { vecswap(a, a + na*es, nb); }
+ if (nc < nd) { vecswap(pb, pb + nd*es, nc); }
+ else { vecswap(pb, pb + nc*es, nd); }
+ if (nb > 1) qsort(a, nb, es, cmp);
+ if (nc > 1) qsort(a + (n-nc) * es, nc, es, cmp);
+}
diff --git a/sys/src/ape/lib/ap/gen/raise.c b/sys/src/ape/lib/ap/gen/raise.c
new file mode 100755
index 000000000..f93b20d3a
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/raise.c
@@ -0,0 +1,11 @@
+/* not a posix function, but implemented with posix kill, getpid */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
+
+int
+raise(int sig)
+{
+ return kill(getpid(), sig);
+}
diff --git a/sys/src/ape/lib/ap/gen/rand.c b/sys/src/ape/lib/ap/gen/rand.c
new file mode 100755
index 000000000..c73ad826c
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/rand.c
@@ -0,0 +1,75 @@
+#include <stdlib.h>
+
+/*
+ * algorithm by
+ * D. P. Mitchell & J. A. Reeds
+ */
+#define LEN 607
+#define TAP 273
+#define MASK 0x7fffffffL
+#define A 48271
+#define M 2147483647
+#define Q 44488
+#define R 3399
+
+typedef unsigned long ulong;
+
+static ulong rng_vec[LEN];
+static ulong* rng_tap = rng_vec;
+static ulong* rng_feed = 0;
+
+void
+srand(unsigned int seed)
+{
+ long lo, hi, x;
+ int i;
+
+ rng_tap = rng_vec;
+ rng_feed = rng_vec+LEN-TAP;
+ seed = seed%M;
+ if(seed < 0)
+ seed += M;
+ if(seed == 0)
+ seed = 89482311;
+ x = seed;
+ /*
+ * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
+ */
+ for(i = -20; i < LEN; i++) {
+ hi = x / Q;
+ lo = x % Q;
+ x = A*lo - R*hi;
+ if(x < 0)
+ x += M;
+ if(i >= 0)
+ rng_vec[i] = x;
+ }
+}
+
+static long
+lrand(void)
+{
+ ulong x;
+
+ rng_tap--;
+ if(rng_tap < rng_vec) {
+ if(rng_feed == 0) {
+ srand(1);
+ rng_tap--;
+ }
+ rng_tap += LEN;
+ }
+ rng_feed--;
+ if(rng_feed < rng_vec)
+ rng_feed += LEN;
+ x = (*rng_feed + *rng_tap) & MASK;
+ *rng_feed = x;
+ return x;
+}
+
+int
+rand(void)
+{
+
+ return lrand() & 0x7fff;
+}
diff --git a/sys/src/ape/lib/ap/gen/reduce b/sys/src/ape/lib/ap/gen/reduce
new file mode 100755
index 000000000..584f8b9ab
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/reduce
@@ -0,0 +1,16 @@
+O=$1
+shift
+objtype=$1
+shift
+
+ls -p ../$objtype/*.[cs] >[2]/dev/null | sed 's/..$//;s/^/^/' > /tmp/reduce.$pid
+#
+# if empty directory, just return the input files
+#
+if (! ~ $status '|') {
+ echo $*
+ rm /tmp/reduce.$pid
+ exit 0
+}
+echo $* | tr ' ' \012 | grep -v -f /tmp/reduce.$pid | tr \012 ' '
+rm /tmp/reduce.$pid
diff --git a/sys/src/ape/lib/ap/gen/strcat.c b/sys/src/ape/lib/ap/gen/strcat.c
new file mode 100755
index 000000000..6aa75d109
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strcat.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+char*
+strcat(char *s1, const char *s2)
+{
+
+ strcpy(strchr(s1, 0), s2);
+ return s1;
+}
diff --git a/sys/src/ape/lib/ap/gen/strchr.c b/sys/src/ape/lib/ap/gen/strchr.c
new file mode 100755
index 000000000..b6d935f57
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strchr.c
@@ -0,0 +1,18 @@
+#include <string.h>
+
+char*
+strchr(const char *s, int c)
+{
+ char c1;
+
+ if(c == 0) {
+ while(*s++)
+ ;
+ return s-1;
+ }
+
+ while(c1 = *s++)
+ if(c1 == c)
+ return s-1;
+ return 0;
+}
diff --git a/sys/src/ape/lib/ap/gen/strcmp.c b/sys/src/ape/lib/ap/gen/strcmp.c
new file mode 100755
index 000000000..a9b4827e7
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strcmp.c
@@ -0,0 +1,19 @@
+#include <string.h>
+
+int
+strcmp(const char *s1, const char *s2)
+{
+ unsigned c1, c2;
+
+ for(;;) {
+ c1 = *s1++;
+ c2 = *s2++;
+ if(c1 != c2) {
+ if(c1 > c2)
+ return 1;
+ return -1;
+ }
+ if(c1 == 0)
+ return 0;
+ }
+}
diff --git a/sys/src/ape/lib/ap/gen/strcoll.c b/sys/src/ape/lib/ap/gen/strcoll.c
new file mode 100755
index 000000000..fda140945
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strcoll.c
@@ -0,0 +1,8 @@
+#include <string.h>
+
+int
+strcoll(const char *s1, const char *s2)
+{
+ /* BUG: supposed to pay attention to LC_COLLATE of current locale */
+ return strcmp(s1, s2);
+}
diff --git a/sys/src/ape/lib/ap/gen/strcpy.c b/sys/src/ape/lib/ap/gen/strcpy.c
new file mode 100755
index 000000000..6a294eee5
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strcpy.c
@@ -0,0 +1,30 @@
+#include <string.h>
+#define N 10000
+
+static void*
+memccpy(void *a1, void *a2, int c, unsigned long n)
+{
+ char *s1, *s2;
+
+ s1 = a1;
+ s2 = a2;
+ while(n > 0) {
+ if((*s1++ = *s2++) == c)
+ return s1;
+ n--;
+ }
+ return 0;
+}
+
+char*
+strcpy(char *s1, const char *s2)
+{
+ char *os1;
+
+ os1 = s1;
+ while(!memccpy(s1, s2, 0, N)) {
+ s1 += N;
+ s2 += N;
+ }
+ return os1;
+}
diff --git a/sys/src/ape/lib/ap/gen/strcspn.c b/sys/src/ape/lib/ap/gen/strcspn.c
new file mode 100755
index 000000000..f7628e8ae
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strcspn.c
@@ -0,0 +1,20 @@
+#include <string.h>
+
+#define N 256
+
+size_t
+strcspn(const char *s, const char *b)
+{
+ char map[N], *os;
+
+ memset(map, 0, N);
+ for(;;) {
+ map[*(unsigned char*)b] = 1;
+ if(*b++ == 0)
+ break;
+ }
+ os = s;
+ while(map[*(unsigned char*)s++] == 0)
+ ;
+ return s - os - 1;
+}
diff --git a/sys/src/ape/lib/ap/gen/strftime.c b/sys/src/ape/lib/ap/gen/strftime.c
new file mode 100755
index 000000000..f86606089
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strftime.c
@@ -0,0 +1,202 @@
+#include <time.h>
+#include <string.h>
+
+static char *awday[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+static char *wday[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday", "Saturday"};
+static char *amon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+static char *mon[12] = {"January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"};
+static char *ampm[2] = {"AM", "PM"};
+static char *tz[2] = {"EST", "EDT"};
+
+static int jan1(int);
+static char *strval(char *, char *, char **, int, int);
+static char *dval(char *, char *, int, int);
+
+size_t
+strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
+{
+ char *sp, *se, *fp;
+ int i;
+
+ sp = s;
+ se = s+maxsize;
+ for(fp=(char *)format; *fp && sp<se; fp++){
+ if(*fp != '%')
+ *sp++ = *fp;
+ else switch(*++fp){
+ case 'a':
+ sp = strval(sp, se, awday, t->tm_wday, 7);
+ break;
+ case 'A':
+ sp = strval(sp, se, wday, t->tm_wday, 7);
+ break;
+ case 'b':
+ sp = strval(sp, se, amon, t->tm_mon, 12);
+ break;
+ case 'B':
+ sp = strval(sp, se, mon, t->tm_mon, 12);
+ break;
+ case 'c':
+ sp += strftime(sp, se-sp, "%a %b %d %H:%M:%S %Y", t);
+ break;
+ case 'd':
+ sp = dval(sp, se, t->tm_mday, 2);
+ break;
+ case 'H':
+ sp = dval(sp, se, t->tm_hour, 2);
+ break;
+ case 'I':
+ i = t->tm_hour;
+ if(i == 0)
+ i = 12;
+ else if(i > 12)
+ i -= 12;
+ sp = dval(sp, se, i, 2);
+ break;
+ case 'j':
+ sp = dval(sp, se, t->tm_yday+1, 3);
+ break;
+ case 'm':
+ sp = dval(sp, se, t->tm_mon+1, 2);
+ break;
+ case 'M':
+ sp = dval(sp, se, t->tm_min, 2);
+ break;
+ case 'p':
+ i = (t->tm_hour < 12)? 0 : 1;
+ sp = strval(sp, se, ampm, i, 2);
+ break;
+ case 'S':
+ sp = dval(sp, se, t->tm_sec, 2);
+ break;
+ case 'U':
+ i = 7-jan1(t->tm_year);
+ if(i == 7)
+ i = 0;
+ /* Now i is yday number of first sunday in year */
+ if(t->tm_yday < i)
+ i = 0;
+ else
+ i = (t->tm_yday-i)/7 + 1;
+ sp = dval(sp, se, i, 2);
+ break;
+ case 'w':
+ sp = dval(sp, se, t->tm_wday, 1);
+ break;
+ case 'W':
+ i = 8-jan1(t->tm_year);
+ if(i >= 7)
+ i -= 7;
+ /* Now i is yday number of first monday in year */
+ if(t->tm_yday < i)
+ i = 0;
+ else
+ i = (t->tm_yday-i)/7 + 1;
+ sp = dval(sp, se, i, 2);
+ break;
+ case 'x':
+ sp += strftime(sp, se-sp, "%a %b %d, %Y", t);
+ break;
+ case 'X':
+ sp += strftime(sp, se-sp, "%H:%M:%S", t);
+ break;
+ case 'y':
+ sp = dval(sp, se, t->tm_year%100, 2);
+ break;
+ case 'Y':
+ sp = dval(sp, se, t->tm_year+1900, 4);
+ break;
+ case 'Z':
+ /* hack for now: assume eastern time zone */
+ i = t->tm_isdst? 1 : 0;
+ sp = strval(sp, se, tz, i, 2);
+ break;
+ case 0:
+ fp--; /* stop loop after next fp incr */
+ break;
+ default:
+ *sp++ = *fp;
+ }
+ }
+ if(*fp)
+ sp = s; /* format string didn't end: no room for conversion */
+ if(sp<se)
+ *sp = 0;
+ return sp-s;
+}
+
+static char *
+strval(char *start, char *end, char **array, int index, int alen)
+{
+ int n;
+
+ if(index<0 || index>=alen){
+ *start = '?';
+ return start+1;
+ }
+ n = strlen(array[index]);
+ if(n > end-start)
+ n = end-start;
+ memcpy(start, array[index], n);
+ return start+n;
+}
+
+static char *
+dval(char *start, char *end, int val, int width)
+{
+ char *p;
+
+ if(val<0 || end-start<width){
+ *start = '?';
+ return start+1;
+ }
+ p = start+width-1;
+ while(p>=start){
+ *p-- = val%10 + '0';
+ val /= 10;
+ }
+ if(val>0)
+ *start = '*';
+ return start+width;
+}
+
+/*
+ * return day of the week
+ * of jan 1 of given year
+ */
+static int
+jan1(int yr)
+{
+ int y, d;
+
+/*
+ * normal gregorian calendar
+ * one extra day per four years
+ */
+
+ y = yr+1900;
+ d = 4+y+(y+3)/4;
+
+/*
+ * julian calendar
+ * regular gregorian
+ * less three days per 400
+ */
+
+ if(y > 1800) {
+ d -= (y-1701)/100;
+ d += (y-1601)/400;
+ }
+
+/*
+ * great calendar changeover instant
+ */
+
+ if(y > 1752)
+ d += 3;
+
+ return(d%7);
+}
diff --git a/sys/src/ape/lib/ap/gen/strlen.c b/sys/src/ape/lib/ap/gen/strlen.c
new file mode 100755
index 000000000..e339cb16b
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strlen.c
@@ -0,0 +1,8 @@
+#include <string.h>
+
+size_t
+strlen(const char *s)
+{
+
+ return strchr(s, 0) - s;
+}
diff --git a/sys/src/ape/lib/ap/gen/strncat.c b/sys/src/ape/lib/ap/gen/strncat.c
new file mode 100755
index 000000000..8891724b4
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strncat.c
@@ -0,0 +1,20 @@
+#include <string.h>
+
+char*
+strncat(char *s1, const char *s2, size_t n)
+{
+ char *os1;
+ long nn;
+
+ os1 = s1;
+ nn = n;
+ while(*s1++)
+ ;
+ s1--;
+ while(*s1++ = *s2++)
+ if(--nn < 0) {
+ s1[-1] = 0;
+ break;
+ }
+ return os1;
+}
diff --git a/sys/src/ape/lib/ap/gen/strncmp.c b/sys/src/ape/lib/ap/gen/strncmp.c
new file mode 100755
index 000000000..e76b09b9d
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strncmp.c
@@ -0,0 +1,23 @@
+#include <string.h>
+
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+ unsigned c1, c2;
+ long nn;
+
+ nn = n;
+ while(nn > 0) {
+ c1 = *s1++;
+ c2 = *s2++;
+ nn--;
+ if(c1 != c2) {
+ if(c1 > c2)
+ return 1;
+ return -1;
+ }
+ if(c1 == 0)
+ break;
+ }
+ return 0;
+}
diff --git a/sys/src/ape/lib/ap/gen/strncpy.c b/sys/src/ape/lib/ap/gen/strncpy.c
new file mode 100755
index 000000000..28a5a522c
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strncpy.c
@@ -0,0 +1,17 @@
+#include <string.h>
+
+char*
+strncpy(char *s1, const char *s2, size_t n)
+{
+ int i;
+ char *os1;
+
+ os1 = s1;
+ for(i = 0; i < n; i++)
+ if((*s1++ = *s2++) == 0) {
+ while(++i < n)
+ *s1++ = 0;
+ return os1;
+ }
+ return os1;
+}
diff --git a/sys/src/ape/lib/ap/gen/strpbrk.c b/sys/src/ape/lib/ap/gen/strpbrk.c
new file mode 100755
index 000000000..407f1c266
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strpbrk.c
@@ -0,0 +1,20 @@
+#include <string.h>
+#define N 256
+
+char*
+strpbrk(const char *s, const char *b)
+{
+ char map[N];
+
+ memset(map, 0, N);
+ for(;;) {
+ map[*b] = 1;
+ if(*b++ == 0)
+ break;
+ }
+ while(map[*s++] == 0)
+ ;
+ if(*--s)
+ return s;
+ return 0;
+}
diff --git a/sys/src/ape/lib/ap/gen/strrchr.c b/sys/src/ape/lib/ap/gen/strrchr.c
new file mode 100755
index 000000000..038b06ad2
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strrchr.c
@@ -0,0 +1,14 @@
+#include <string.h>
+
+char*
+strrchr(const char *s, int c)
+{
+ char *r;
+
+ if(c == 0)
+ return strchr(s, 0);
+ r = 0;
+ while(s = strchr(s, c))
+ r = s++;
+ return r;
+}
diff --git a/sys/src/ape/lib/ap/gen/strspn.c b/sys/src/ape/lib/ap/gen/strspn.c
new file mode 100755
index 000000000..57ebfd1b5
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strspn.c
@@ -0,0 +1,17 @@
+#include <string.h>
+
+#define N 256
+
+size_t
+strspn(const char *s, const char *b)
+{
+ char map[N], *os;
+
+ memset(map, 0, N);
+ while(*b)
+ map[*(unsigned char *)b++] = 1;
+ os = s;
+ while(map[*(unsigned char *)s++])
+ ;
+ return s - os - 1;
+}
diff --git a/sys/src/ape/lib/ap/gen/strstr.c b/sys/src/ape/lib/ap/gen/strstr.c
new file mode 100755
index 000000000..4e6828571
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strstr.c
@@ -0,0 +1,27 @@
+#include <string.h>
+
+/* Return pointer to first occurrence of s2 in s1, NULL if none */
+
+char
+*strstr(const char *s1, const char *s2)
+{
+ char *p, *pa, *pb;
+ int c0, c;
+
+ c0 = *s2;
+ if(c0 == 0)
+ return s1;
+ s2++;
+ for(p=strchr(s1, c0); p; p=strchr(p+1, c0)) {
+ pa = p;
+ for(pb=s2;; pb++) {
+ c = *pb;
+ if(c == 0)
+ return p;
+ if(c != *++pa)
+ break;
+ }
+ }
+ return 0;
+}
+
diff --git a/sys/src/ape/lib/ap/gen/strtod.c b/sys/src/ape/lib/ap/gen/strtod.c
new file mode 100755
index 000000000..ca4939100
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strtod.c
@@ -0,0 +1,91 @@
+#include <math.h>
+#include <errno.h>
+
+/*
+ * bug: should detect overflow, set errno = ERANGE, and return +/- HUGE_VAL
+ */
+double
+strtod(const char *cp, char **endptr)
+{
+ double num, dem;
+ extern double pow10(int);
+ int neg, eneg, dig, predig, exp, c;
+ const char *p;
+
+ p = cp;
+ num = 0;
+ neg = 0;
+ dig = 0;
+ predig = 0;
+ exp = 0;
+ eneg = 0;
+
+ c = *p++;
+ while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' || c == '\r')
+ c = *p++;
+ if(c == '-' || c == '+'){
+ if(c == '-')
+ neg = 1;
+ c = *p++;
+ }
+ while(c >= '0' && c <= '9'){
+ num = num*10 + c-'0';
+ predig++;
+ c = *p++;
+ }
+ if(c == '.')
+ c = *p++;
+ while(c >= '0' && c <= '9'){
+ num = num*10 + c-'0';
+ dig++;
+ c = *p++;
+ }
+ if(dig+predig == 0){
+ if(endptr)
+ *endptr = (char *)cp;
+ return 0.0;
+ }
+ if(c == 'e' || c == 'E'){
+ c = *p++;
+ if(c == '-' || c == '+'){
+ if(c == '-'){
+ dig = -dig;
+ eneg = 1;
+ }
+ c = *p++;
+ }
+ while(c >= '0' && c <= '9'){
+ exp = exp*10 + c-'0';
+ c = *p++;
+ }
+ }
+ exp -= dig;
+ if(exp < 0){
+ exp = -exp;
+ eneg = !eneg;
+ }
+ dem = pow10(exp);
+ if(dem==HUGE_VAL)
+ num = eneg? 0.0 : HUGE_VAL;
+ else if(dem==0)
+ num = eneg? HUGE_VAL : 0.0;
+ else if(eneg)
+ num /= dem;
+ else
+ num *= dem;
+ if(neg)
+ num = -num;
+ if(endptr){
+ *endptr = (char *)--p;
+ /*
+ * Fix cases like 2.3e+
+ */
+ while(p > cp){
+ c = *--p;
+ if(c!='-' && c!='+' && c!='e' && c!='E')
+ break;
+ (*endptr)--;
+ }
+ }
+ return num;
+}
diff --git a/sys/src/ape/lib/ap/gen/strtok.c b/sys/src/ape/lib/ap/gen/strtok.c
new file mode 100755
index 000000000..24155782a
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strtok.c
@@ -0,0 +1,36 @@
+#include <string.h>
+
+#define N 256
+
+char*
+strtok_r(char *s, const char *b, char **last)
+{
+ char map[N], *os;
+
+ memset(map, 0, N);
+ while(*b)
+ map[*(unsigned char*)b++] = 1;
+ if(s == 0)
+ s = *last;
+ while(map[*(unsigned char*)s++])
+ ;
+ if(*--s == 0)
+ return 0;
+ os = s;
+ while(map[*(unsigned char*)s] == 0)
+ if(*s++ == 0) {
+ *last = s-1;
+ return os;
+ }
+ *s++ = 0;
+ *last = s;
+ return os;
+}
+
+char*
+strtok(char *s, const char *b)
+{
+ static char *under_rock;
+
+ return strtok_r(s, b, &under_rock);
+}
diff --git a/sys/src/ape/lib/ap/gen/strtol.c b/sys/src/ape/lib/ap/gen/strtol.c
new file mode 100755
index 000000000..1c5d99632
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strtol.c
@@ -0,0 +1,94 @@
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+
+long
+strtol(const char *nptr, char **endptr, int base)
+{
+ const char *p;
+ long n, nn;
+ int c, ovfl, v, neg, ndig;
+
+ p = nptr;
+ neg = 0;
+ n = 0;
+ ndig = 0;
+ ovfl = 0;
+
+ /*
+ * White space
+ */
+ for(;;p++){
+ switch(*p){
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case '\v':
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Sign
+ */
+ if(*p=='-' || *p=='+')
+ if(*p++ == '-')
+ neg = 1;
+
+ /*
+ * Base
+ */
+ if(base==0){
+ if(*p != '0')
+ base = 10;
+ else{
+ base = 8;
+ if(p[1]=='x' || p[1]=='X'){
+ p += 2;
+ base = 16;
+ }
+ }
+ }else if(base==16 && *p=='0'){
+ if(p[1]=='x' || p[1]=='X')
+ p += 2;
+ }else if(base<0 || 36<base)
+ goto Return;
+
+ /*
+ * Non-empty sequence of digits
+ */
+ for(;; p++,ndig++){
+ c = *p;
+ v = base;
+ if('0'<=c && c<='9')
+ v = c - '0';
+ else if('a'<=c && c<='z')
+ v = c - 'a' + 10;
+ else if('A'<=c && c<='Z')
+ v = c - 'A' + 10;
+ if(v >= base)
+ break;
+ nn = n*base + v;
+ if(nn < n)
+ ovfl = 1;
+ n = nn;
+ }
+
+ Return:
+ if(ndig == 0)
+ p = nptr;
+ if(endptr)
+ *endptr = (char *)p;
+ if(ovfl){
+ errno = ERANGE;
+ if(neg)
+ return LONG_MIN;
+ return LONG_MAX;
+ }
+ if(neg)
+ return -n;
+ return n;
+}
diff --git a/sys/src/ape/lib/ap/gen/strtoll.c b/sys/src/ape/lib/ap/gen/strtoll.c
new file mode 100755
index 000000000..e633d2d08
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strtoll.c
@@ -0,0 +1,103 @@
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+
+#define VLONG_MAX ~(1LL<<63)
+#define VLONG_MIN (1LL<<63)
+
+long long
+strtoll(char *nptr, char **endptr, int base)
+{
+ char *p;
+ long long n, nn, m;
+ int c, ovfl, v, neg, ndig;
+
+ p = nptr;
+ neg = 0;
+ n = 0;
+ ndig = 0;
+ ovfl = 0;
+
+ /*
+ * White space
+ */
+ for(;; p++) {
+ switch(*p) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case '\v':
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Sign
+ */
+ if(*p=='-' || *p=='+')
+ if(*p++ == '-')
+ neg = 1;
+
+ /*
+ * Base
+ */
+ if(base==0){
+ base = 10;
+ if(*p == '0') {
+ base = 8;
+ if(p[1]=='x' || p[1]=='X') {
+ p += 2;
+ base = 16;
+ }
+ }
+ } else
+ if(base==16 && *p=='0') {
+ if(p[1]=='x' || p[1]=='X')
+ p += 2;
+ } else
+ if(base<0 || 36<base)
+ goto Return;
+
+ /*
+ * Non-empty sequence of digits
+ */
+ m = VLONG_MAX/base;
+ for(;; p++,ndig++) {
+ c = *p;
+ v = base;
+ if('0'<=c && c<='9')
+ v = c - '0';
+ else
+ if('a'<=c && c<='z')
+ v = c - 'a' + 10;
+ else
+ if('A'<=c && c<='Z')
+ v = c - 'A' + 10;
+ if(v >= base)
+ break;
+ if(n > m)
+ ovfl = 1;
+ nn = n*base + v;
+ if(nn < n)
+ ovfl = 1;
+ n = nn;
+ }
+
+Return:
+ if(ndig == 0)
+ p = nptr;
+ if(endptr)
+ *endptr = p;
+ if(ovfl){
+ errno = ERANGE;
+ if(neg)
+ return VLONG_MIN;
+ return VLONG_MAX;
+ }
+ if(neg)
+ return -n;
+ return n;
+}
diff --git a/sys/src/ape/lib/ap/gen/strtoul.c b/sys/src/ape/lib/ap/gen/strtoul.c
new file mode 100755
index 000000000..bb7dce7ae
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strtoul.c
@@ -0,0 +1,92 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+
+unsigned long
+strtoul(const char *nptr, char **endptr, int base)
+{
+ const char *p;
+ unsigned long n, nn;
+ int c, ovfl, neg, v, ndig;
+
+ p = (char*)nptr;
+ neg = 0;
+ n = 0;
+ ndig = 0;
+ ovfl = 0;
+
+ /*
+ * White space
+ */
+ for(;;p++){
+ switch(*p){
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case '\v':
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Sign
+ */
+ if(*p=='-' || *p=='+')
+ if(*p++ == '-')
+ neg = 1;
+
+ /*
+ * Base
+ */
+ if(base==0){
+ if(*p != '0')
+ base = 10;
+ else{
+ base = 8;
+ if(p[1]=='x' || p[1]=='X'){
+ p += 2;
+ base = 16;
+ }
+ }
+ }else if(base==16 && *p=='0'){
+ if(p[1]=='x' || p[1]=='X')
+ p += 2;
+ }else if(base<0 || 36<base)
+ goto Return;
+
+ /*
+ * Non-empty sequence of digits
+ */
+ for(;; p++,ndig++){
+ c = *p;
+ v = base;
+ if('0'<=c && c<='9')
+ v = c - '0';
+ else if('a'<=c && c<='z')
+ v = c - 'a' + 10;
+ else if('A'<=c && c<='Z')
+ v = c - 'A' + 10;
+ if(v >= base)
+ break;
+ nn = n*base + v;
+ if(nn < n)
+ ovfl = 1;
+ n = nn;
+ }
+
+ Return:
+ if(ndig == 0)
+ p = nptr;
+ if(endptr)
+ *endptr = (char *)p;
+ if(ovfl){
+ errno = ERANGE;
+ return ULONG_MAX;
+ }
+ if(neg)
+ return -n;
+ return n;
+}
diff --git a/sys/src/ape/lib/ap/gen/strtoull.c b/sys/src/ape/lib/ap/gen/strtoull.c
new file mode 100755
index 000000000..76aa392a4
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strtoull.c
@@ -0,0 +1,100 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+
+#define UVLONG_MAX (1LL<<63)
+
+unsigned long long
+strtoull(char *nptr, char **endptr, int base)
+{
+ char *p;
+ unsigned long long n, nn, m;
+ int c, ovfl, v, neg, ndig;
+
+ p = nptr;
+ neg = 0;
+ n = 0;
+ ndig = 0;
+ ovfl = 0;
+
+ /*
+ * White space
+ */
+ for(;; p++) {
+ switch(*p) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case '\v':
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Sign
+ */
+ if(*p == '-' || *p == '+')
+ if(*p++ == '-')
+ neg = 1;
+
+ /*
+ * Base
+ */
+ if(base == 0) {
+ base = 10;
+ if(*p == '0') {
+ base = 8;
+ if(p[1] == 'x' || p[1] == 'X'){
+ p += 2;
+ base = 16;
+ }
+ }
+ } else
+ if(base == 16 && *p == '0') {
+ if(p[1] == 'x' || p[1] == 'X')
+ p += 2;
+ } else
+ if(base < 0 || 36 < base)
+ goto Return;
+
+ /*
+ * Non-empty sequence of digits
+ */
+ m = UVLONG_MAX/base;
+ for(;; p++,ndig++) {
+ c = *p;
+ v = base;
+ if('0' <= c && c <= '9')
+ v = c - '0';
+ else
+ if('a' <= c && c <= 'z')
+ v = c - 'a' + 10;
+ else
+ if('A' <= c && c <= 'Z')
+ v = c - 'A' + 10;
+ if(v >= base)
+ break;
+ if(n > m)
+ ovfl = 1;
+ nn = n*base + v;
+ if(nn < n)
+ ovfl = 1;
+ n = nn;
+ }
+
+Return:
+ if(ndig == 0)
+ p = nptr;
+ if(endptr)
+ *endptr = p;
+ if(ovfl){
+ errno = ERANGE;
+ return UVLONG_MAX;
+ }
+ if(neg)
+ return -n;
+ return n;
+}
diff --git a/sys/src/ape/lib/ap/gen/strxfrm.c b/sys/src/ape/lib/ap/gen/strxfrm.c
new file mode 100755
index 000000000..ecb095064
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/strxfrm.c
@@ -0,0 +1,17 @@
+#include <string.h>
+
+size_t
+strxfrm(char *s1, const char *s2, size_t n)
+{
+ /*
+ * BUG: supposed to transform s2 to a canonical form
+ * so that strcmp can be used instead of strcoll, but
+ * our strcoll just uses strcmp.
+ */
+
+ size_t xn = strlen(s2);
+ if(n > xn)
+ n = xn;
+ memcpy(s1, s2, n);
+ return xn;
+}
diff --git a/sys/src/ape/lib/ap/gen/toupper.c b/sys/src/ape/lib/ap/gen/toupper.c
new file mode 100755
index 000000000..eb1e8efd5
--- /dev/null
+++ b/sys/src/ape/lib/ap/gen/toupper.c
@@ -0,0 +1,17 @@
+#include <ctype.h>
+
+toupper(int c)
+{
+
+ if(c < 'a' || c > 'z')
+ return c;
+ return (c-'a'+'A');
+}
+
+tolower(int c)
+{
+
+ if(c < 'A' || c > 'Z')
+ return c;
+ return (c-'A'+'a');
+}