summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules27
-rw-r--r--config.ninja12
-rw-r--r--core/cparser/gen.rc15
m---------core/cparser/src0
-rw-r--r--core/file/gen.rc114
m---------core/file/src0
-rw-r--r--core/libfirm/gen.rc60
m---------core/libfirm/src0
-rw-r--r--core/loksh/gen.rc31
m---------core/loksh/src0
-rw-r--r--core/plan9port/gen.rc97
-rw-r--r--core/plan9port/patches/0001-Fix-build-with-musl.patch62
m---------core/plan9port/src0
-rw-r--r--core/sbase/gen.rc127
m---------core/sbase/src0
-rw-r--r--core/skeleton/gen.rc18
-rw-r--r--core/tz/gen.rc25
m---------core/tz/src0
-rw-r--r--core/ubase/gen.rc90
m---------core/ubase/src0
-rw-r--r--core/zlib/gen.rc25
m---------core/zlib/src0
-rw-r--r--gen.rc110
-rw-r--r--include/sys/queue.h533
-rw-r--r--rules.ninja35
-rw-r--r--scripts/hash.rc21
-rw-r--r--scripts/tree.rc19
-rwxr-xr-xsetup.rc117
29 files changed, 1539 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..a01ee289
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.*.swp
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..8046df4f
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,27 @@
+[submodule "core/cparser/src"]
+ path = core/cparser/src
+ url = http://pp.ipd.kit.edu/git/cparser.git
+[submodule "core/file/src"]
+ path = core/file/src
+ url = https://github.com/file/file
+[submodule "core/libfirm/src"]
+ path = core/libfirm/src
+ url = http://pp.ipd.kit.edu/git/libfirm.git
+[submodule "core/loksh/src"]
+ path = core/loksh/src
+ url = https://github.com/dimkr/loksh
+[submodule "core/plan9port/src"]
+ path = core/plan9port/src
+ url = https://github.com/9fans/plan9port
+[submodule "core/sbase/src"]
+ path = core/sbase/src
+ url = git://git.suckless.org/sbase
+[submodule "core/tz/src"]
+ path = core/tz/src
+ url = https://github.com/eggert/tz
+[submodule "core/ubase/src"]
+ path = core/ubase/src
+ url = git://git.suckless.org/ubase
+[submodule "core/zlib/src"]
+ path = core/zlib/src
+ url = https://github.com/madler/zlib
diff --git a/config.ninja b/config.ninja
new file mode 100644
index 00000000..522687bf
--- /dev/null
+++ b/config.ninja
@@ -0,0 +1,12 @@
+ar = ar
+cc = cc
+
+cflags = -O2 -march=native -pipe
+ldflags = -static
+
+zic = zic
+yacc = yacc
+python = python
+perl = perl
+
+repo = root.git
diff --git a/core/cparser/gen.rc b/core/cparser/gen.rc
new file mode 100644
index 00000000..ada89217
--- /dev/null
+++ b/core/cparser/gen.rc
@@ -0,0 +1,15 @@
+cflags\
+ -I '$root_srcdir'/core/libfirm/src/include\
+ -I '$root_outdir'/core/libfirm\
+ -I '$srcdir'/src/src\
+ -I '$outdir'
+
+rule revision_hdr 'echo ''#define cparser_REVISION ""'' >$out.tmp && mv $out.tmp $out'
+build '$outdir'/revision.h revision_hdr
+
+cd src
+srcs=src/^( main.c */*.c )
+for(src in $srcs) cc $src '|' '$outdir'/revision.h '||' '$root_outdir/core/libfirm/stamp'
+link cparser $srcs.o '$root_outdir'/core/libfirm/libfirm.a
+file bin/cparser '$outdir'/cparser 755
+file share/man/man1/cparser.1 '$srcdir'/src/cparser.1 644
diff --git a/core/cparser/src b/core/cparser/src
new file mode 160000
+Subproject d2a926c5f3b2c475650cb6d66eeed45ab7e31bd
diff --git a/core/file/gen.rc b/core/file/gen.rc
new file mode 100644
index 00000000..b5c16c8b
--- /dev/null
+++ b/core/file/gen.rc
@@ -0,0 +1,114 @@
+version=5.25
+cflags\
+ -DHAVE_ASCTIME_R'='1\
+ -DHAVE_CTIME_R'='1\
+ -DHAVE_FORK'='1\
+ -DHAVE_FREELOCALE'='1\
+ -DHAVE_GETLINE'='1\
+ -DHAVE_GETOPT_H'='1\
+ -DHAVE_GMTIME_R'='1\
+ -DHAVE_INTTYPES_H'='1\
+ -DHAVE_LIMITS_H'='1\
+ -DHAVE_LOCALE_H'='1\
+ -DHAVE_LOCALTIME_R'='1\
+ -DHAVE_MBRTOWC'='1\
+ -DHAVE_MBSTATE_T'='1\
+ -DHAVE_MKOSTEMP'='1\
+ -DHAVE_MKSTEMP'='1\
+ -DHAVE_MMAP'='1\
+ -DHAVE_NEWLOCALE'='1\
+ -DHAVE_PREAD'='1\
+ -DHAVE_SIGNAL_H'='1\
+ -DHAVE_STDDEF_H'='1\
+ -DHAVE_STDINT_H'='1\
+ -DHAVE_STDLIB_H'='1\
+ -DHAVE_STRERROR'='1\
+ -DHAVE_STRINGS_H'='1\
+ -DHAVE_STRING_H'='1\
+ -DHAVE_STRNDUP'='1\
+ -DHAVE_STRTOF'='1\
+ -DHAVE_STRTOUL'='1\
+ -DHAVE_STRUCT_OPTION'='1\
+ -DHAVE_STRUCT_STAT_ST_RDEV'='1\
+ -DHAVE_STRUCT_TM_TM_GMTOFF'='1\
+ -DHAVE_STRUCT_TM_TM_ZONE'='1\
+ -DHAVE_SYS_MMAN_H'='1\
+ -DHAVE_SYS_TIME_H'='1\
+ -DHAVE_SYS_WAIT_H'='1\
+ -DHAVE_UNISTD_H'='1\
+ -DHAVE_USELOCALE'='1\
+ -DHAVE_UTIME'='1\
+ -DHAVE_UTIMES'='1\
+ -DHAVE_UTIME_H'='1\
+ -DHAVE_WCHAR_H'='1\
+ -DHAVE_WCTYPE_H'='1\
+ -DHAVE_WCWIDTH'='1\
+ -DHAVE_ZLIB_H'='1\
+ \
+ -DHAVE_ASPRINTF'='1\
+ -DHAVE_GETOPT_LONG'='1\
+ -DHAVE_MEMORY_H'='1\
+ -DHAVE_SIG_T'='1\
+ -DHAVE_STRCASESTR'='1\
+ -DHAVE_STRLCAT'='1\
+ -DHAVE_STRLCPY'='1\
+ -DHAVE_VASPRINTF'='1\
+ -DHAVE_VISIBILITY'='1\
+ \
+ -DBUILTIN_ELF'='1\
+ -DELFCORE'='1\
+ -DVERSION'='\"$version\"\
+ -DMAGIC'='\"/share/file/magic\"\
+ -D_GNU_SOURCE\
+ -Wall\
+ -I core/zlib/include\
+ -I '$outdir'/include
+
+# TODO: check for visibility, xlocale.h, memory.h, vasprintf, asprintf,
+# strlcpy, strlcat, strcasestr, fmtcheck, getopt_long, sig_t, tm_zone,
+# tm_gmtoff
+
+cd src/magic
+magic_outs=magic/^( Header Localstuff )
+for(src in Header Localstuff) build '$outdir'/magic/$src copy '$srcdir'/src/magic/$src
+cd Magdir
+srcs=*
+magic_outs=( $magic_outs magic/$srcs )
+for(src in $srcs) build '$outdir'/magic/$src copy '$srcdir'/src/magic/Magdir/$src
+
+rule magic 'cd $outdir && file -C -m magic'
+build '$outdir'/magic.mgc magic '|' '$outdir'/$magic_outs
+
+ninja_vars='expr = s@X.YY@'`{echo $version | tr -d .}^@ \
+ build '$outdir'/include/magic.h sed '$srcdir'/src/src/magic.h.in
+ninja_vars='expr = -e s@__CSECTION__@1@g -e s@__FSECTION__@5@g -e s@__VERSION__@'$version'@g -e s@__MAGIC__@/share/file/magic@g' \
+ build '$outdir'/file.1 sed '$srcdir'/src/doc/file.man
+
+srcs=(\
+ src/magic.c\
+ src/apprentice.c\
+ src/softmagic.c\
+ src/ascmagic.c\
+ src/encoding.c\
+ src/compress.c\
+ src/is_tar.c\
+ src/readelf.c\
+ src/print.c\
+ src/fsmagic.c\
+ src/funcs.c\
+ src/apptype.c\
+ src/cdf.c\
+ src/cdf_time.c\
+ src/readcdf.c\
+ \
+ src/fmtcheck.c\
+) {
+ for(src in $srcs) cc $src '|' '$outdir/include/magic.h' '||' core/zlib/stamp
+ ar libmagic.a $srcs.o
+}
+
+exe file src/file.c libmagic.a
+
+file bin/file '$outdir'/file 755
+file share/man/man1/file.1 '$outdir'/file.1 644
+file share/file/magic.mgc '$outdir'/magic.mgc 644
diff --git a/core/file/src b/core/file/src
new file mode 160000
+Subproject f45db89ddc91692b662fffbabbdafc7bc4c00f5
diff --git a/core/libfirm/gen.rc b/core/libfirm/gen.rc
new file mode 100644
index 00000000..bbfcbee4
--- /dev/null
+++ b/core/libfirm/gen.rc
@@ -0,0 +1,60 @@
+cflags\
+ -I '$outdir' \
+ -I '$srcdir'/src/include/libfirm/adt\
+ -I '$srcdir'/src/include/libfirm\
+ -I '$srcdir'/src/ir/adt\
+ -I '$srcdir'/src/ir/ana\
+ -I '$srcdir'/src/ir/be/ia32\
+ -I '$srcdir'/src/ir/be\
+ -I '$srcdir'/src/ir/common\
+ -I '$srcdir'/src/ir/ident\
+ -I '$srcdir'/src/ir/ir\
+ -I '$srcdir'/src/ir/kaps\
+ -I '$srcdir'/src/ir/libcore\
+ -I '$srcdir'/src/ir/lower\
+ -I '$srcdir'/src/ir/lpp\
+ -I '$srcdir'/src/ir/opt\
+ -I '$srcdir'/src/ir/stat\
+ -I '$srcdir'/src/ir/tr\
+ -I '$srcdir'/src/ir/tv
+
+backends=( amd64 arm ia32 sparc TEMPLATE )
+
+rule irspec '$python $srcdir/src/scripts/gen_ir.py $srcdir/src/scripts/ir_spec.py $in >$out.tmp && mv $out.tmp $out'
+rule new_nodes '$perl $srcdir/src/ir/be/scripts/generate_new_opcodes.pl $in $outdir'
+rule regalloc_if '$perl $srcdir/src/ir/be/scripts/generate_regalloc_if.pl $in $outdir'
+rule emitter '$perl $srcdir/src/ir/be/scripts/generate_emitter.pl $in $outdir'
+
+cd src
+
+genhdrs=( nodes.h gen_irnode.h gen_proj_names.h )
+gensrcs=( gen_irnode.c gen_irio.c )
+for(gensrc in $genhdrs $gensrcs) {
+ build '$outdir'/$gensrc irspec '$srcdir'/src/scripts/templates/$gensrc
+}
+
+srcs=( ir/*/*.c '$outdir'/$gensrcs )
+objs=$srcs.o
+for(src in $srcs) cc $src '||' '$outdir/stamp'
+
+stampdeps=( $genhdrs )
+
+for(backend in $backends) {
+ types=( emitter regalloc_if new_nodes )
+ srcs=( ir/be/$backend/*.c '$outdir'/gen_$backend^_$types.c )
+ objs=( $objs $srcs.o )
+ stampdeps=( $stampdeps gen_$backend^_$types.h )
+ {
+ cflags -I '$srcdir'/src/ir/be/$backend
+ for(type in $types) {
+ outs=( '$outdir'/gen_$backend^_$type.^(c h) )\
+ build $"outs $type '$srcdir'/src/ir/be/$backend/$backend^_spec.pl
+ }
+ for(src in $srcs) cc $src '||' '$outdir/stamp'
+ } >$outdir/$backend.ninja
+ echo 'subninja $outdir'/$backend.ninja
+}
+
+ar libfirm.a $objs
+
+stamp $stampdeps
diff --git a/core/libfirm/src b/core/libfirm/src
new file mode 160000
+Subproject 03dcab7e4809422fd8c7ccf1802cd715242ef0b
diff --git a/core/loksh/gen.rc b/core/loksh/gen.rc
new file mode 100644
index 00000000..59e52b07
--- /dev/null
+++ b/core/loksh/gen.rc
@@ -0,0 +1,31 @@
+cflags -I '$root_srcdir/include' -D_GNU_SOURCE
+exe ksh\
+ alloc.c\
+ c_ksh.c\
+ c_sh.c\
+ c_test.c\
+ c_ulimit.c\
+ edit.c\
+ emacs.c\
+ eval.c \
+ exec.c\
+ expr.c\
+ history.c\
+ io.c\
+ jobs.c\
+ lex.c\
+ mail.c\
+ main.c\
+ misc.c\
+ path.c\
+ shf.c\
+ syn.c\
+ table.c\
+ trap.c\
+ tree.c\
+ tty.c\
+ var.c\
+ version.c\
+ vi.c
+file bin/ksh '$outdir'/ksh 755
+sym bin/sh ksh
diff --git a/core/loksh/src b/core/loksh/src
new file mode 160000
+Subproject d1eafa7917e3f109e4f69ceb8ab8ccc9754b2db
diff --git a/core/plan9port/gen.rc b/core/plan9port/gen.rc
new file mode 100644
index 00000000..635c6b9e
--- /dev/null
+++ b/core/plan9port/gen.rc
@@ -0,0 +1,97 @@
+cflags\
+ -I '$srcdir'/src/include\
+ -I '$srcdir'/src/src/cmd/rc\
+ -I '$srcdir'/src/src/lib9/fmt\
+ -I '$outdir'
+
+ninja_vars='yaccflags = -b x -d' outs=( '$outdir'/x.tab.^( c h ) )\
+ build $"outs yacc '$srcdir'/src/src/cmd/rc/syn.y
+
+static_lib lib9.a src/lib9/^(\
+ argv0.c\
+ atexit.c\
+ atoi.c\
+ await.c\
+ create.c\
+ dirfstat.c\
+ dirread.c\
+ dirstat.c\
+ dup.c\
+ errstr.c\
+ fmt/dofmt.c\
+ fmt/fltfmt.c\
+ fmt/fmt.c\
+ fmt/fmtfd.c\
+ fmt/fmtfdflush.c\
+ fmt/fmtlocale.c\
+ fmt/fmtstr.c\
+ fmt/fprint.c\
+ fmtlock2.c\
+ fmt/nan64.c\
+ fmt/runefmtstr.c\
+ fmt/smprint.c\
+ fmt/snprint.c\
+ fmt/sprint.c\
+ fmt/strtod.c\
+ fmt/vfprint.c\
+ fmt/vseprint.c\
+ fmt/vsmprint.c\
+ fmt/vsnprint.c\
+ get9root.c\
+ getcallerpc-x86_64.c\
+ getenv.c\
+ jmp.c\
+ main.c\
+ malloc.c\
+ mallocz.c\
+ notify.c\
+ open.c\
+ _p9dir.c\
+ pipe.c\
+ postnote.c\
+ qlock.c\
+ readn.c\
+ rfork.c\
+ seek.c\
+ strdup.c\
+ strecpy.c\
+ sysfatal.c\
+ tokenize.c\
+ unsharp.c\
+ utf/rune.c\
+ utf/utflen.c\
+ utf/utfnlen.c\
+ utf/utfrune.c\
+ wait.c\
+ write.c\
+)
+
+srcs=(\
+ code.c\
+ exec.c\
+ getflags.c\
+ glob.c\
+ here.c\
+ io.c\
+ lex.c\
+ pcmd.c\
+ pfnc.c\
+ simple.c\
+ subr.c\
+ trap.c\
+ tree.c\
+ unixcrap.c\
+ var.c\
+ plan9ish.c\
+ havefork.c\
+) {
+ for(src in $srcs) cc src/cmd/rc/$src '||' '$outdir/stamp'
+ cc '$outdir'/x.tab.c
+ link rc src/cmd/rc/$srcs.o x.tab.c.o lib9.a
+}
+
+file bin/rc '$outdir'/rc 755
+file share/man/man1/rc.1 '$srcdir'/src/man/man1/rc.1 644
+file lib/rcmain '$srcdir'/src/rcmain 644
+
+stamp x.tab.h
diff --git a/core/plan9port/patches/0001-Fix-build-with-musl.patch b/core/plan9port/patches/0001-Fix-build-with-musl.patch
new file mode 100644
index 00000000..2aff4071
--- /dev/null
+++ b/core/plan9port/patches/0001-Fix-build-with-musl.patch
@@ -0,0 +1,62 @@
+From 51ab047274d90b1c6b7a26b2b41992b176543d05 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 10 Apr 2016 02:50:03 -0700
+Subject: [PATCH] Fix build with musl
+
+---
+ src/lib9/dirread.c | 34 ----------------------------------
+ 1 file changed, 34 deletions(-)
+
+diff --git a/src/lib9/dirread.c b/src/lib9/dirread.c
+index 40fbe3c..345f49c 100644
+--- a/src/lib9/dirread.c
++++ b/src/lib9/dirread.c
+@@ -6,45 +6,11 @@
+
+ extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*);
+
+-#if defined(__linux__)
+-static int
+-mygetdents(int fd, struct dirent *buf, int n)
+-{
+- off_t off;
+- int nn;
+-
+- /* This doesn't match the man page, but it works in Debian with a 2.2 kernel */
+- off = p9seek(fd, 0, 1);
+- nn = getdirentries(fd, (void*)buf, n, &off);
+- return nn;
+-}
+-#elif defined(__APPLE__)
+-static int
+-mygetdents(int fd, struct dirent *buf, int n)
+-{
+- long off;
+- return getdirentries(fd, (void*)buf, n, &off);
+-}
+-#elif defined(__FreeBSD__) || defined(__DragonFly__)
+-static int
+-mygetdents(int fd, struct dirent *buf, int n)
+-{
+- off_t off;
+- return getdirentries(fd, (void*)buf, n, &off);
+-}
+-#elif defined(__sun__) || defined(__NetBSD__) || defined(__OpenBSD__)
+ static int
+ mygetdents(int fd, struct dirent *buf, int n)
+ {
+ return getdents(fd, (void*)buf, n);
+ }
+-#elif defined(__AIX__)
+-static int
+-mygetdents(int fd, struct dirent *buf, int n)
+-{
+- return getdirent(fd, (void*)buf, n);
+-}
+-#endif
+
+ #if defined(__DragonFly__)
+ static inline int d_reclen(struct dirent *de) { return _DIRENT_DIRSIZ(de); }
+--
+2.8.0
+
diff --git a/core/plan9port/src b/core/plan9port/src
new file mode 160000
+Subproject 51ab047274d90b1c6b7a26b2b41992b176543d0
diff --git a/core/sbase/gen.rc b/core/sbase/gen.rc
new file mode 100644
index 00000000..38b6ae36
--- /dev/null
+++ b/core/sbase/gen.rc
@@ -0,0 +1,127 @@
+cflags\
+ -D_DEFAULT_SOURCE\
+ -D_BSD_SOURCE\
+ -D_XOPEN_SOURCE'='700\
+ -D_FILE_OFFSET_BITS'='64\
+ -std'='c99 -Wall -pedantic\
+ -I '$outdir'
+
+cd src
+
+static_lib libutil.a libutil/*.c
+static_lib libutf.a libutf/*.c
+
+executables=(\
+ basename\
+ cal\
+ cat\
+ chgrp\
+ chmod\
+ chown\
+ chroot\
+ cksum\
+ cmp\
+ cols\
+ comm\
+ cp\
+ cron\
+ cut\
+ date\
+ dirname\
+ du\
+ echo\
+ ed\
+ env\
+ expand\
+ expr\
+ false\
+ find\
+ flock\
+ fold\
+ getconf\
+ grep\
+ head\
+ join\
+ hostname\
+ kill\
+ link\
+ ln\
+ logger\
+ logname\
+ ls\
+ md5sum\
+ mkdir\
+ mkfifo\
+ mktemp\
+ mv\
+ nice\
+ nl\
+ nohup\
+ od\
+ pathchk\
+ paste\
+ printenv\
+ printf\
+ pwd\
+ readlink\
+ renice\
+ rm\
+ rmdir\
+ sed\
+ seq\
+ setsid\
+ sha1sum\
+ sha224sum\
+ sha256sum\
+ sha384sum\
+ sha512sum\
+ sha512-224sum\
+ sha512-256sum\
+ sleep\
+ sort\
+ split\
+ sponge\
+ strings\
+ sync\
+ tail\
+ tar\
+ tee\
+ test\
+ tftp\
+ time\
+ touch\
+ tr\
+ true\
+ tsort\
+ tty\
+ uname\
+ unexpand\
+ uniq\
+ unlink\
+ uudecode\
+ uuencode\
+ wc\
+ which\
+ whoami\
+ xargs\
+ install\
+ yes\
+)
+
+getconf_hdrs=( confstr limits sysconf pathconf )^_l.h
+getconf_outs='$outdir'/$getconf_hdrs
+rule getconf_headers 'getconf=$$PWD/$srcdir/src/getconf.sh && cd $outdir && $$getconf'
+build $"getconf_outs getconf_headers '| $srcdir/src/getconf.sh'
+
+for(exe in $executables) {
+ if(~ $exe install) src=x$exe
+ if not src=$exe
+
+ cc $src.c '||' '$outdir/stamp'
+ link $exe $src.c.o libutil.a libutf.a
+
+ file bin/$exe '$outdir'/$exe 755
+ file share/man/man1/$exe.1 '$srcdir'/src/$src.1 644
+}
+
+stamp $getconf_hdrs
diff --git a/core/sbase/src b/core/sbase/src
new file mode 160000
+Subproject d89cd4811898a183f629323b855d1b5623c2da5
diff --git a/core/skeleton/gen.rc b/core/skeleton/gen.rc
new file mode 100644
index 00000000..05652d3e
--- /dev/null
+++ b/core/skeleton/gen.rc
@@ -0,0 +1,18 @@
+dir bin 755
+dir boot 755
+dir dev 755
+dir etc 755
+dir home 755
+dir lib 755
+dir libexec 755
+dir mnt 755
+dir proc 755
+dir root 755
+dir share 755
+dir share/man 755
+dir share/man/man1 755
+dir share/man/man8 755
+dir sys 755
+dir tmp 755
+dir var 755
+sym usr .
diff --git a/core/tz/gen.rc b/core/tz/gen.rc
new file mode 100644
index 00000000..59cb34d5
--- /dev/null
+++ b/core/tz/gen.rc
@@ -0,0 +1,25 @@
+tzdata=(\
+ africa\
+ antarctica\
+ asia\
+ australasia\
+ europe\
+ northamerica\
+ southamerica\
+ pacificnew\
+ etcetera\
+ backward\
+ systemv\
+ factory\
+)
+
+rule zic '$zic -d $outdir/zoneinfo $in'
+
+for(data in $tzdata) {
+ zones=`{awk '{if ($1 == "Zone") print $2}' src/$data}
+ if(! ~ $#zones 0) {
+ outs='$outdir'/zoneinfo/$zones
+ build $"outs zic $srcdir/src/$data
+ for(zone in $zones) file share/zoneinfo/$zone '$outdir'/zoneinfo/$zone 644
+ }
+}
diff --git a/core/tz/src b/core/tz/src
new file mode 160000
+Subproject 1284afb4bdc70f97f265ac2f49188217778413e
diff --git a/core/ubase/gen.rc b/core/ubase/gen.rc
new file mode 100644
index 00000000..43b0c50c
--- /dev/null
+++ b/core/ubase/gen.rc
@@ -0,0 +1,90 @@
+cflags\
+ -D_GNU_SOURCE\
+ -D_XOPEN_SOURCE'='700\
+ -D_FILE_OFFSET_BITS'='64\
+ -std'='c99 -Wall -Wextra\
+ -I '$outdir'
+
+build '$outdir/config.h' copy '$srcdir/src/config.def.h'
+
+static_lib libutil.a\
+ libutil/agetcwd.c\
+ libutil/agetline.c\
+ libutil/apathmax.c\
+ libutil/concat.c\
+ libutil/ealloc.c\
+ libutil/eprintf.c\
+ libutil/estrtol.c\
+ libutil/estrtoul.c\
+ libutil/explicit_bzero.c\
+ libutil/passwd.c\
+ libutil/proc.c\
+ libutil/putword.c\
+ libutil/recurse.c\
+ libutil/strlcat.c\
+ libutil/strlcpy.c\
+ libutil/strtonum.c\
+ libutil/tty.c
+
+fn myexe {
+ exe=$1
+ shift 1
+ cc $exe.c '||' '$outdir/stamp'
+ exe $exe '$outdir'/$exe.c.o '$outdir/libutil.a'
+ file bin/$exe '$outdir'/$exe 755
+ if(~ $#* 1) file share/man/man$1/$exe.$1 '$srcdir'/src/$exe.$1 644
+ true
+}
+
+myexe chvt 1
+myexe clear 1
+myexe ctrlaltdel 8
+myexe dd 1
+myexe df 1
+myexe dmesg 1
+myexe eject 1
+myexe fallocate 1
+myexe free 1
+myexe freeramdisk 8
+myexe fsfreeze 8
+myexe getty 8
+myexe halt 8
+myexe hwclock 8
+myexe id 1
+myexe insmod 8
+myexe killall5 8
+myexe last
+myexe lastlog 8
+myexe login 1
+myexe lsmod 8
+myexe lsusb 8
+myexe mesg 1
+myexe mknod 1
+myexe mkswap 8
+myexe mount 8
+myexe mountpoint 1
+myexe nologin 8
+myexe pagesize 1
+myexe passwd 1
+myexe pidof 1
+myexe pivot_root 8
+myexe ps 1
+myexe readahead 8
+myexe respawn 1
+myexe rmmod 8
+myexe stat 1
+myexe su 1
+myexe swaplabel 8
+myexe swapoff 8
+myexe swapon 8
+myexe switch_root 8
+myexe sysctl 8
+myexe truncate 1
+myexe umount 8
+myexe unshare 1
+myexe uptime 1
+myexe vtallow 1
+myexe watch 1
+myexe who 1
+
+stamp config.h
diff --git a/core/ubase/src b/core/ubase/src
new file mode 160000
+Subproject 28795cffe22ee6a645e4763f6b9bd0e422dddb2
diff --git a/core/zlib/gen.rc b/core/zlib/gen.rc
new file mode 100644
index 00000000..0cd8d1b6
--- /dev/null
+++ b/core/zlib/gen.rc
@@ -0,0 +1,25 @@
+cflags\
+ -DHAVE_HIDDEN\
+ -DHAVE_STDARG_H\
+ -DHAVE_UNISTD_H\
+ -D_LARGEFILE64_SOURCE
+
+static_lib libz.a\
+ adler32.c\
+ crc32.c\
+ deflate.c\
+ infback.c\
+ inffast.c\
+ inflate.c\
+ inftrees.c\
+ zutil.c\
+ \
+ compress.c\
+ uncompr.c\
+ gzclose.c\
+ gzlib.c\
+ gzread.c\
+ gzwrite.c
+
+build '$outdir'/include/zlib.h copy '$srcdir'/src/zlib.h
+stamp include/zlib.h
diff --git a/core/zlib/src b/core/zlib/src
new file mode 160000
+Subproject 50893291621658f355bc5b4d450a8d06a563053
diff --git a/gen.rc b/gen.rc
new file mode 100644
index 00000000..6617689f
--- /dev/null
+++ b/gen.rc
@@ -0,0 +1,110 @@
+fn stamp {
+ build '$outdir/stamp' stamp '$outdir'/$*
+}
+
+fn cflags {
+ set cflags '$cflags' $*
+}
+
+fn cc {
+ src=$1 obj=$src.o {
+ shift
+ if(! ~ $src '$'*) {
+ src='$srcdir'/src/$src
+ obj='$outdir'/$obj
+ }
+ build $obj cc $src $*
+ }
+}
+
+fn link {
+ out='$outdir'/$1 objs=() {
+ shift
+ for(obj in $*) {
+ if(! ~ $obj '$'*) obj='$outdir'/$obj
+ objs=( $objs $obj )
+ }
+ build $out link $objs
+ }
+}
+
+fn ar {
+ out='$outdir'/$1 objs=() {
+ shift
+ for(obj in $*) {
+ if(! ~ $obj '$'*) obj='$outdir'/$obj
+ objs=( $objs $obj )
+ }
+ build $out ar $objs
+ }
+}
+
+fn static_lib {
+ out=$1 {
+ shift
+ for(src) cc $src
+ ar $out $*.o
+ }
+}
+
+fn exe {
+ out=$1 objs=() {
+ shift
+ for(src) {
+ if(~ $src *.c) {
+ cc $src
+ obj=$src.o
+ }
+ if not obj=$src
+ objs=( $objs $obj )
+ }
+ link $out $objs
+ }
+}
+
+fn file {
+ out='$hash_root'/$1
+ ninja_vars='args = 100'$3' '$1 build $out githash $2 '| $repo.stamp'
+ root_inputs=( $root_inputs $out )
+
+ if(! ~ $3 755 644) root_perms=( $root_perms 100$3' '$1 )
+ true
+}
+
+fn dir {
+ root_perms=( $root_perms '010'$2' '$1 )
+}
+
+fn sym {
+ out='$hash_root'/$1
+ ninja_vars='args = 120000 '$1' '$2 build $out githash '| $repo.stamp'
+ root_inputs=( $root_inputs $out )
+}
+
+root_inputs=()
+root_perms=()
+
+packages=(\
+ cparser\
+ file\
+ libfirm\
+ loksh\
+ plan9port\
+ sbase\
+ skeleton\
+ tz\
+ ubase\
+ zlib\
+)
+
+set hash_root '$repo.hash'
+build '$repo.stamp' gitinit
+
+for(pkg in $packages) subgen core/$pkg
+
+printf '%s\n' $root_perms >$outdir/root_perms.txt
+file .perms '$outdir'/root_perms.txt 644
+
+build '$outdir'/root_tree.txt gittree $root_inputs '| $repo.stamp'
+
+for(pkg in $packages) subninja core/$pkg/local.ninja
diff --git a/include/sys/queue.h b/include/sys/queue.h
new file mode 100644
index 00000000..5e81fdd1
--- /dev/null
+++ b/include/sys/queue.h
@@ -0,0 +1,533 @@
+/* $OpenBSD: queue.h,v 1.43 2015/12/28 19:38:40 millert Exp $ */
+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues and XOR simple queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * An XOR simple queue is used in the same way as a regular simple queue.
+ * The difference is that the head structure also includes a "cookie" that
+ * is XOR'd with the queue pointer (first, last or next) to generate the
+ * real pointer value.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
+#define _Q_INVALIDATE(a) (a) = ((void *)-1)
+#else
+#define _Q_INVALIDATE(a)
+#endif
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_END(head) NULL
+#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = SLIST_FIRST(head); \
+ (var) != SLIST_END(head); \
+ (var) = SLIST_NEXT(var, field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST(head); \
+ (var) && ((tvar) = SLIST_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) { \
+ SLIST_FIRST(head) = SLIST_END(head); \
+}
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->slh_first; \
+ \
+ while (curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+ _Q_INVALIDATE((elm)->field.sle_next); \
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List access methods.
+ */
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_END(head) NULL
+#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field) \
+ for((var) = LIST_FIRST(head); \
+ (var)!= LIST_END(head); \
+ (var) = LIST_NEXT(var, field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST(head); \
+ (var) && ((tvar) = LIST_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ LIST_FIRST(head) = LIST_END(head); \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+ _Q_INVALIDATE((elm)->field.le_prev); \
+ _Q_INVALIDATE((elm)->field.le_next); \
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do { \
+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
+ (elm2)->field.le_next->field.le_prev = \
+ &(elm2)->field.le_next; \
+ (elm2)->field.le_prev = (elm)->field.le_prev; \
+ *(elm2)->field.le_prev = (elm2); \
+ _Q_INVALIDATE((elm)->field.le_prev); \
+ _Q_INVALIDATE((elm)->field.le_next); \
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for((var) = SIMPLEQ_FIRST(head); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = SIMPLEQ_NEXT(var, field))
+
+#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SIMPLEQ_FIRST(head); \
+ (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
+ == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_CONCAT(head1, head2) do { \
+ if (!SIMPLEQ_EMPTY((head2))) { \
+ *(head1)->sqh_last = (head2)->sqh_first; \
+ (head1)->sqh_last = (head2)->sqh_last; \
+ SIMPLEQ_INIT((head2)); \
+ } \
+} while (0)
+
+/*
+ * XOR Simple queue definitions.
+ */
+#define XSIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqx_first; /* first element */ \
+ struct type **sqx_last; /* addr of last next element */ \
+ unsigned long sqx_cookie; \
+}
+
+#define XSIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqx_next; /* next element */ \
+}
+
+/*
+ * XOR Simple queue access methods.
+ */
+#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \
+ (unsigned long)(ptr)))
+#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first))
+#define XSIMPLEQ_END(head) NULL
+#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
+#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
+
+
+#define XSIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = XSIMPLEQ_FIRST(head); \
+ (var) != XSIMPLEQ_END(head); \
+ (var) = XSIMPLEQ_NEXT(head, var, field))
+
+#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = XSIMPLEQ_FIRST(head); \
+ (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * XOR Simple queue functions.
+ */
+#define XSIMPLEQ_INIT(head) do { \
+ arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
+ (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqx_next = (head)->sqx_first) == \
+ XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+ (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \
+ *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \
+ XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+ (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \
+} while (0)
+
+#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqx_first = XSIMPLEQ_XOR(head, \
+ (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
+} while (0)
+
+#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \
+ (elm)->field.sqx_next)->field.sqx_next) \
+ == XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = \
+ XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+} while (0)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_END(head) NULL
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define TAILQ_EMPTY(head) \
+ (TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field) \
+ for((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head) && \
+ ((tvar) = TAILQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_PREV(var, headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head) && \
+ ((tvar) = TAILQ_PREV(var, headname, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+ _Q_INVALIDATE((elm)->field.tqe_prev); \
+ _Q_INVALIDATE((elm)->field.tqe_next); \
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+ _Q_INVALIDATE((elm)->field.tqe_prev); \
+ _Q_INVALIDATE((elm)->field.tqe_next); \
+} while (0)
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/rules.ninja b/rules.ninja
new file mode 100644
index 00000000..c49bc90b
--- /dev/null
+++ b/rules.ninja
@@ -0,0 +1,35 @@
+rule gen
+ command = rc $in -d $root_srcdir $$PWD
+ generator = 1
+
+# toolchain
+rule cc
+ command = $cc $cflags -c -o $out $in
+
+rule link
+ command = $cc $ldflags -o $out $in
+
+rule ar
+ command = $ar crsD $out $in
+
+rule stamp
+ command = touch $out
+
+rule copy
+ command = ln -f $in $out
+
+# misc tools
+rule yacc
+ command = oldpwd=$$PWD && cd $outdir && $yacc $yaccflags $$oldpwd/$in
+
+rule sed
+ command = sed $expr >$out.tmp $in && mv $out.tmp $out
+
+rule githash
+ command = rc $root_srcdir/scripts/hash.rc $repo $out $args $in
+
+rule gittree
+ command = rc $root_srcdir/scripts/tree.rc $repo $out $in
+
+rule gitinit
+ command = mkdir -p $repo && git -C $repo init --bare && touch $out
diff --git a/scripts/hash.rc b/scripts/hash.rc
new file mode 100644
index 00000000..9b715308
--- /dev/null
+++ b/scripts/hash.rc
@@ -0,0 +1,21 @@
+#!/bin/rc
+
+flag e +
+
+repo=$1
+out=$2
+mode=$3
+name=$4
+shift 4
+
+hash=`{
+ switch($mode) {
+ case 120???
+ printf %s $1 | git -C $repo hash-object -w --stdin
+ case 100???
+ git -C $repo hash-object -w --stdin <$1
+ }
+}
+
+printf '%s %s\t%s\n' $mode $hash $name >$out.tmp
+mv $out.tmp $out
diff --git a/scripts/tree.rc b/scripts/tree.rc
new file mode 100644
index 00000000..8d71ffe2
--- /dev/null
+++ b/scripts/tree.rc
@@ -0,0 +1,19 @@
+#!/bin/rc
+
+flag e +
+
+repo=$1
+out=$2
+shift 2
+
+ifs=() { oldpwd=`{pwd | head -c -1} }
+cd $repo
+
+git read-tree --empty
+cat $oldpwd/$* | git update-index --index-info
+tree=`{git write-tree}
+git update-ref refs/tags/tree $tree
+
+cd $oldpwd
+echo $tree >$out.tmp
+mv $out.tmp $out
diff --git a/setup.rc b/setup.rc
new file mode 100755
index 00000000..590a8d72
--- /dev/null
+++ b/setup.rc
@@ -0,0 +1,117 @@
+#!/bin/rc
+
+flag e +
+
+while(~ $1 -*) switch($1) {
+case -d
+ cd $2
+ shift 2
+}
+if(~ $#* 0) outdir=out
+if not outdir=$1
+
+mkdir -p $outdir
+
+ifs=() {
+ abs_srcdir=`{readlink -f . | head -c -1}
+ abs_outdir=`{readlink -f $outdir | head -c -1}
+}
+
+# find relative path from outdir to srcdir
+ifs=/ {
+ srcdir=`{printf %s $abs_srcdir}
+ outdir=`{printf %s $abs_outdir}
+}
+
+if(~ $#outdir 0) ifs=() { rel_srcdir=`{ifs=() pwd | head -c -1} }
+if not n=() {
+ for(i in `{awk 'BEGIN {for (i = 1; i <= '$#outdir'; i++) print i}'}) {
+ if(~$#n 0 && ! ~ $srcdir($i) $outdir($i)) {
+ ifs=() { rel_srcdir=`{printf /%s $srcdir($i-) | tail -c +2} }
+ n=$i
+ }
+ if(~ $#n 1) {
+ if(~ $#rel_srcdir 0) rel_srcdir=..
+ if not rel_srcdir=../$rel_srcdir
+ }
+ }
+}
+
+root_srcdir=$abs_srcdir
+root_outdir=$abs_outdir
+setup_outs=( build.ninja )
+setup_ins=()
+
+fn set {
+ var=$1 {
+ shift
+ printf '%s = %s\n' $var $"*
+ }
+}
+
+fn subninja {
+ echo subninja $*
+}
+
+fn include {
+ echo include $*
+}
+
+fn rule {
+ name=$1 {
+ shift
+ echo rule $name
+ for(var in 'command = '$* $ninja_vars) {
+ echo ' '$var
+ }
+ }
+}
+
+fn build {
+ out=$1 rule=$2 {
+ shift 2
+ echo build $out: $rule $*
+ }
+ for(var in $ninja_vars) echo ' '$var
+}
+
+fn subgen {
+ olddir=$dir
+ dir=$1
+ srcdir=$root_srcdir/$dir
+ outdir=$root_outdir/$dir
+
+ printf 'generating in %s\n' $dir >[1=2]
+
+ setup_outs=( $setup_outs $dir/local.ninja )
+ setup_ins=( $setup_ins '$root_srcdir'/$dir/gen.rc )
+
+ mkdir -p $outdir
+ cd $srcdir
+ {
+ echo 'outdir = '$dir
+ echo 'srcdir = $root_srcdir/'$dir
+ . ./gen.rc
+ } >$outdir/local.ninja
+ cd $root_srcdir
+
+ dir=$olddir
+ srcdir=$root_srcdir/$dir
+ outdir=$root_outdir/$dir
+}
+
+subgen .
+
+{
+ set root_srcdir $rel_srcdir
+ set root_outdir .
+
+ include '$root_srcdir/config.ninja'
+ include '$root_srcdir/rules.ninja'
+
+ ninja_vars='generator = 1' build $"setup_outs gen '$root_srcdir/setup.rc' '|' $setup_ins
+
+ subninja local.ninja
+} >$root_outdir/build.ninja.tmp
+
+mv $root_outdir/^( build.ninja.tmp build.ninja )