aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNicholas <nbnoll@eml.cc>2021-11-12 09:22:01 -0800
committerNicholas <nbnoll@eml.cc>2021-11-12 09:22:01 -0800
commitce05175372a9ddca1a225db0765ace1127a39293 (patch)
tree5988b4d4f6b402e4953945886fc90aae11203df6 /sys
parentb375f3cdedb5b0e08745d100b40e38d2f8396a58 (diff)
chore: simplified organizational structurelaptop
Diffstat (limited to 'sys')
-rw-r--r--sys/base/arg.c71
-rw-r--r--sys/base/bufio/dump.c66
-rw-r--r--sys/base/bufio/get.c17
-rw-r--r--sys/base/bufio/internal.h4
-rw-r--r--sys/base/bufio/read.c36
-rw-r--r--sys/base/bufio/reader.c28
-rw-r--r--sys/base/bufio/refill.h28
-rw-r--r--sys/base/bufio/rules.mk5
-rw-r--r--sys/base/bufio/unget.c18
-rw-r--r--sys/base/coro/coro.c43
-rw-r--r--sys/base/coro/internal.h15
-rw-r--r--sys/base/coro/rules.mk3
-rw-r--r--sys/base/coro/unix_x64.s113
-rw-r--r--sys/base/error/errorf.c13
-rw-r--r--sys/base/error/exits.c11
-rw-r--r--sys/base/error/internal.h3
-rw-r--r--sys/base/error/panicf.c16
-rw-r--r--sys/base/error/rules.mk6
-rw-r--r--sys/base/error/verrorf.c9
-rw-r--r--sys/base/error/vpanicf.c11
-rw-r--r--sys/base/flate/internal.h39
-rw-r--r--sys/base/flate/read.c41
-rw-r--r--sys/base/flate/reader.c59
-rw-r--r--sys/base/flate/rules.mk6
-rw-r--r--sys/base/flate/write.c48
-rw-r--r--sys/base/flate/writer.c57
-rw-r--r--sys/base/fs/internal.h18
-rw-r--r--sys/base/fs/rules.mk3
-rw-r--r--sys/base/fs/walk.c119
-rw-r--r--sys/base/fs/walker.c39
-rw-r--r--sys/base/gz/flush.c7
-rw-r--r--sys/base/gz/get.c17
-rw-r--r--sys/base/gz/interface.c12
-rw-r--r--sys/base/gz/internal.h6
-rw-r--r--sys/base/gz/open.c13
-rw-r--r--sys/base/gz/printf.c15
-rw-r--r--sys/base/gz/put.c7
-rw-r--r--sys/base/gz/putstring.c8
-rw-r--r--sys/base/gz/read.c16
-rw-r--r--sys/base/gz/rules.mk11
-rw-r--r--sys/base/gz/seek.c7
-rw-r--r--sys/base/gz/write.c7
-rw-r--r--sys/base/io/fd.c7
-rw-r--r--sys/base/io/flush.c7
-rw-r--r--sys/base/io/get.c7
-rw-r--r--sys/base/io/interface.c70
-rw-r--r--sys/base/io/internal.h4
-rw-r--r--sys/base/io/open.c13
-rw-r--r--sys/base/io/putbyte.c7
-rw-r--r--sys/base/io/putstring.c7
-rw-r--r--sys/base/io/read.c7
-rw-r--r--sys/base/io/readln.c12
-rw-r--r--sys/base/io/rules.mk14
-rw-r--r--sys/base/io/seek.c7
-rw-r--r--sys/base/io/stat.c7
-rw-r--r--sys/base/io/tell.c7
-rw-r--r--sys/base/io/unget.c7
-rw-r--r--sys/base/io/write.c7
-rw-r--r--sys/base/mem/arena.c119
-rw-r--r--sys/base/mem/buffer.c45
-rw-r--r--sys/base/mem/interface.c36
-rw-r--r--sys/base/mem/internal.h4
-rw-r--r--sys/base/mem/rules.mk5
-rw-r--r--sys/base/mem/set64.c13
-rw-r--r--sys/base/mmap/internal.h5
-rw-r--r--sys/base/mmap/mmap.c39
-rw-r--r--sys/base/mmap/rules.mk2
-rw-r--r--sys/base/os/basename.c10
-rw-r--r--sys/base/os/exists.c7
-rw-r--r--sys/base/os/internal.h4
-rw-r--r--sys/base/os/rules.mk4
-rw-r--r--sys/base/os/sep.c14
-rw-r--r--sys/base/rng/base.c24
-rw-r--r--sys/base/rng/bernoulli.c7
-rw-r--r--sys/base/rng/exponential.c11
-rw-r--r--sys/base/rng/internal.h19
-rw-r--r--sys/base/rng/normal.c77
-rw-r--r--sys/base/rng/poisson.c126
-rw-r--r--sys/base/rng/random.c33
-rw-r--r--sys/base/rng/rules.mk7
-rw-r--r--sys/base/rules.mk36
-rw-r--r--sys/base/sort/double.c12
-rw-r--r--sys/base/sort/float.c12
-rw-r--r--sys/base/sort/int.c12
-rw-r--r--sys/base/sort/int16.c12
-rw-r--r--sys/base/sort/int32.c12
-rw-r--r--sys/base/sort/int64.c12
-rw-r--r--sys/base/sort/int8.c12
-rw-r--r--sys/base/sort/internal.h5
-rw-r--r--sys/base/sort/rules.mk14
-rw-r--r--sys/base/sort/string.c12
-rw-r--r--sys/base/sort/uint.c12
-rw-r--r--sys/base/sort/uint16.c12
-rw-r--r--sys/base/sort/uint32.c12
-rw-r--r--sys/base/sort/uint64.c12
-rw-r--r--sys/base/sort/uint8.c12
-rw-r--r--sys/base/string/append.c53
-rw-r--r--sys/base/string/appendf.c31
-rw-r--r--sys/base/string/clear.c9
-rw-r--r--sys/base/string/copyn.c11
-rw-r--r--sys/base/string/equals.c12
-rw-r--r--sys/base/string/find.c11
-rw-r--r--sys/base/string/fit.c20
-rw-r--r--sys/base/string/free.c8
-rw-r--r--sys/base/string/grow.c33
-rw-r--r--sys/base/string/internal.h12
-rw-r--r--sys/base/string/join.c16
-rw-r--r--sys/base/string/len.c17
-rw-r--r--sys/base/string/lower.c12
-rw-r--r--sys/base/string/make.c53
-rw-r--r--sys/base/string/makef.c25
-rw-r--r--sys/base/string/read.c12
-rw-r--r--sys/base/string/replace.c26
-rw-r--r--sys/base/string/rules.mk19
-rw-r--r--sys/base/string/split.c39
-rw-r--r--sys/base/string/upper.c12
-rw-r--r--sys/base/test.c170
-rw-r--r--sys/cmd/cc/ast.c2139
-rw-r--r--sys/cmd/cc/bits.c114
-rw-r--r--sys/cmd/cc/cc.c409
-rw-r--r--sys/cmd/cc/cc.h806
-rw-r--r--sys/cmd/cc/lex.c873
-rw-r--r--sys/cmd/cc/pp.c1125
-rw-r--r--sys/cmd/cc/rules.mk23
-rw-r--r--sys/cmd/cc/scratch.c7
-rw-r--r--sys/cmd/cc/util.c21
-rw-r--r--sys/cmd/dwm/LICENSE37
-rw-r--r--sys/cmd/dwm/client.c657
-rw-r--r--sys/cmd/dwm/config.h141
-rw-r--r--sys/cmd/dwm/drw.c376
-rw-r--r--sys/cmd/dwm/dwm.c1185
-rw-r--r--sys/cmd/dwm/dwm.h384
-rw-r--r--sys/cmd/dwm/hook.c489
-rw-r--r--sys/cmd/dwm/rules.mk28
-rw-r--r--sys/cmd/dwm/util.c66
-rw-r--r--sys/cmd/filter/filter.c104
-rw-r--r--sys/cmd/filter/rules.mk13
-rw-r--r--sys/cmd/ic/LICENSE23
-rw-r--r--sys/cmd/ic/ic.1100
-rw-r--r--sys/cmd/ic/ic.c878
-rw-r--r--sys/cmd/ic/rules.mk14
-rw-r--r--sys/cmd/ic/strlcpy.c32
-rw-r--r--sys/cmd/menu/LICENSE30
-rw-r--r--sys/cmd/menu/config.h25
-rw-r--r--sys/cmd/menu/drw.c428
-rw-r--r--sys/cmd/menu/drw.h57
-rw-r--r--sys/cmd/menu/menu.c765
-rw-r--r--sys/cmd/menu/menu.h40
-rw-r--r--sys/cmd/menu/rules.mk25
-rw-r--r--sys/cmd/menu/util.c30
-rw-r--r--sys/cmd/rc/code.c277
-rw-r--r--sys/cmd/rc/exec.c1267
-rw-r--r--sys/cmd/rc/exec.h47
-rw-r--r--sys/cmd/rc/input.c1679
-rw-r--r--sys/cmd/rc/io.c437
-rw-r--r--sys/cmd/rc/job.c91
-rw-r--r--sys/cmd/rc/lex.c394
-rw-r--r--sys/cmd/rc/main.c66
-rw-r--r--sys/cmd/rc/parse.c2059
-rw-r--r--sys/cmd/rc/parse.h141
-rw-r--r--sys/cmd/rc/prompt.c36
-rw-r--r--sys/cmd/rc/rc.h263
-rw-r--r--sys/cmd/rc/rules.mk31
-rw-r--r--sys/cmd/rc/syntax.y147
-rw-r--r--sys/cmd/rc/sys.c137
-rw-r--r--sys/cmd/rc/tree.c111
-rw-r--r--sys/cmd/rc/util.c65
-rw-r--r--sys/cmd/rc/var.c336
-rw-r--r--sys/cmd/rc/wait.c247
-rw-r--r--sys/cmd/rules.mk38
-rw-r--r--sys/cmd/term/LICENSE34
-rw-r--r--sys/cmd/term/config.h474
-rw-r--r--sys/cmd/term/hb.c147
-rw-r--r--sys/cmd/term/nonspacing.h89
-rw-r--r--sys/cmd/term/rules.mk24
-rw-r--r--sys/cmd/term/term.c2417
-rw-r--r--sys/cmd/term/term.h316
-rw-r--r--sys/cmd/term/term.info250
-rw-r--r--sys/cmd/term/util.c30
-rw-r--r--sys/cmd/term/wide.h65
-rw-r--r--sys/cmd/term/x.c2070
-rw-r--r--sys/cmd/walk/rules.mk13
-rw-r--r--sys/cmd/walk/walk.c84
-rw-r--r--sys/cmd/wm/arg.c0
-rw-r--r--sys/cmd/wm/client.c274
-rw-r--r--sys/cmd/wm/config.h70
-rw-r--r--sys/cmd/wm/input.c316
-rw-r--r--sys/cmd/wm/layer.c107
-rw-r--r--sys/cmd/wm/main.c177
-rw-r--r--sys/cmd/wm/monitor.c386
-rwxr-xr-xsys/cmd/wm/protocol/sync6
-rw-r--r--sys/cmd/wm/render.c160
-rw-r--r--sys/cmd/wm/rules.mk61
-rw-r--r--sys/cmd/wm/util.c99
-rw-r--r--sys/cmd/wm/wm.h350
-rw-r--r--sys/cmd/wm/xdg.c118
-rw-r--r--sys/libbio/align.c178
-rw-r--r--sys/libbio/fasta.c393
-rw-r--r--sys/libbio/newick.c414
-rw-r--r--sys/libbio/phylo.c427
-rw-r--r--sys/libbio/rules.mk28
-rw-r--r--sys/libbio/simulate.c120
-rw-r--r--sys/libbio/test.c283
-rw-r--r--sys/libc/rules.mk23
-rw-r--r--sys/libc/stdio.c59
-rw-r--r--sys/libc/string.c80
-rw-r--r--sys/libfmt/buffer.c60
-rw-r--r--sys/libfmt/do.c730
-rw-r--r--sys/libfmt/esprint.c14
-rw-r--r--sys/libfmt/float.c1077
-rw-r--r--sys/libfmt/fprint.c14
-rw-r--r--sys/libfmt/internal.h17
-rw-r--r--sys/libfmt/locale.c16
-rw-r--r--sys/libfmt/nsprint.c14
-rw-r--r--sys/libfmt/open.c34
-rw-r--r--sys/libfmt/print.c13
-rw-r--r--sys/libfmt/rules.mk36
-rw-r--r--sys/libfmt/sprint.c19
-rw-r--r--sys/libfmt/test.c72
-rw-r--r--sys/libfmt/vesprint.c26
-rw-r--r--sys/libfmt/vfprint.c19
-rw-r--r--sys/libfmt/vnsprint.c26
-rw-r--r--sys/libfmt/vprint.c19
-rw-r--r--sys/libfmt/vwrite.c26
-rw-r--r--sys/libfmt/write.c22
-rw-r--r--sys/libmath/basic.c531
-rw-r--r--sys/libmath/blas.c63
-rw-r--r--sys/libmath/blas1.c58
-rw-r--r--sys/libmath/blas1body215
-rw-r--r--sys/libmath/blas2.c222
-rw-r--r--sys/libmath/blas2body256
-rw-r--r--sys/libmath/blas3.c279
-rw-r--r--sys/libmath/lapack.c0
-rw-r--r--sys/libmath/linalg.c63
-rw-r--r--sys/libmath/loop.h114
-rw-r--r--sys/libmath/matrix.c176
-rw-r--r--sys/libmath/rules.mk24
-rw-r--r--sys/libmath/test.c471
-rw-r--r--sys/libsre/lex.c246
-rw-r--r--sys/libsre/sre.h93
-rw-r--r--sys/libterm/term.c489
-rw-r--r--sys/libterm/term.h270
-rw-r--r--sys/libterm/window.c408
-rw-r--r--sys/libutf/canfit.c23
-rw-r--r--sys/libutf/decode.c98
-rw-r--r--sys/libutf/decodeprev.c60
-rw-r--r--sys/libutf/encode.c69
-rw-r--r--sys/libutf/find.c31
-rw-r--r--sys/libutf/findlast.c32
-rw-r--r--sys/libutf/internal.h38
-rw-r--r--sys/libutf/len.c21
-rw-r--r--sys/libutf/rules.mk76
-rw-r--r--sys/libutf/runelen.c8
-rw-r--r--sys/libutf/vendor/common.c220
-rw-r--r--sys/libutf/vendor/common.h46
-rw-r--r--sys/libutf/vendor/mkgraphemedata.c24
-rw-r--r--sys/libutf/vendor/mkrunetype.c388
-rw-r--r--sys/libutf/vendor/mkrunewidth.c325
-rw-r--r--sys/nixos/rules.mk0
-rw-r--r--sys/rules.mk41
260 files changed, 0 insertions, 39871 deletions
diff --git a/sys/base/arg.c b/sys/base/arg.c
deleted file mode 100644
index 269043e..0000000
--- a/sys/base/arg.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <u.h>
-#include <base.h>
-
-// NOTE: this utf8 bit is copied from libunicode to remove the hard dependency just for ARG_BEGIN.
-
-#define UTFmax 4
-#define RuneSync 0x80u
-#define RuneSelf 0x80u
-#define RuneErr 0xFFFDu
-#define RuneMax 0x10FFFFu
-#define RuneMask 0x1FFFFFu
-
-#define Bit(i) (7-(i))
-/* N 0's preceded by i 1's e.g. T(Bit(2)) is 1100 0000 */
-#define Tbyte(i) (((1 << (Bit(i)+1))-1) ^ 0xFF)
-/* 0000 0000 0000 0111 1111 1111 */
-#define RuneX(i) ((1 << (Bit(i) + ((i)-1)*Bitx))-1)
-enum
-{
- Bitx = Bit(1),
- Tx = Tbyte(1),
- Rune1 = (1 << (Bit(0)+0*Bitx)) - 1,
-
- Maskx = (1 << Bitx) - 1, /* 0011 1111 */
- Testx = Maskx ^ 0xff, /* 1100 0000 */
-
- SurrogateMin = 0xD800,
- SurrogateMax = 0xDFFF,
- Bad = RuneErr,
-};
-
-
-int
-arg·bytetorune(uint32* r, byte* s)
-{
- int c[4], i;
- uint32 l;
-
- c[0] = *(ubyte*)(s);
- if(c[0] < Tx) {
- *r = c[0];
- return 1;
- }
-
- l = c[0];
- for(i = 1; i < UTFmax; i++) {
- c[i] = *(ubyte*)(s+i);
- c[i] ^= Tx;
- if (c[i] & Testx) goto bad;
-
- l = (l << Bitx) | c[i];
- if(c[0] < Tbyte(i + 2)) {
- l &= RuneX(i + 1);
- if (i == 1) {
- if (c[0] < Tbyte(2) || l <= Rune1)
- goto bad;
- } else if (l <= RuneX(i) || l > RuneMax)
- goto bad;
- if (i == 2 && SurrogateMin <= l && l <= SurrogateMax)
- goto bad;
-
- *r = l;
- return i + 1;
- }
- }
-bad:
- *r = RuneErr;
- return 1;
-}
-
-char *argv0;
diff --git a/sys/base/bufio/dump.c b/sys/base/bufio/dump.c
deleted file mode 100644
index 0b527e2..0000000
--- a/sys/base/bufio/dump.c
+++ /dev/null
@@ -1,66 +0,0 @@
-// -----------------------------------------------------------------------
-// reader
-
-#if 0
-rune
-bufio·getrune(io·Buffer *buf)
-{
- ubyte b;
- int i;
- byte str[UTFmax+1];
- rune r;
-
- // NOTE: I'm worried about the sign here...
- b = bufio·getbyte(buf);
- if (b < RuneSelf) {
- buf->runesize = 1;
- return b;
- }
-
- i = 0;
- str[i++] = b;
-
-nextbyte:
- b = bufio·getbyte(buf);
- if (b < 0) return b;
- if (i >= arrlen(str)) return RuneErr;
- str[i++] = b;
- if (!utf8·fullrune(str, i))
- goto nextbyte;
-
- buf->runesize = utf8·bytetorune(&r, str);
- if (r == RuneErr && b == 1) {
- errorf("illegal UTF-8 sequence");
- for (; i >= 0; i--)
- errorf("%s%.2x", i > 0 ? " " : "", *(ubyte*)(str+i));
- errorf("\n");
-
- buf->runesize = 0;
- } else
- for (; i > buf->runesize; i--)
- bufio·ungetbyte(buf, str[i]);
-
- return r;
-}
-
-// TODO: Check that we are given the correct rune!
-error
-bufio·ungetrune(io·Buffer *buf, rune r)
-{
- if (buf->state & bufio·rdr) {
- errorf("attempted to unget on non-active reader");
- return bufio·err;
- }
-
- if (buf->pos == buf->buf) {
- errorf("attempted to unget past end of buffer");
- return bufio·err;
- }
-
- buf->pos -= buf->runesize;
- return 0;
-}
-#endif
-
-// -----------------------------------------------------------------------
-// writer
diff --git a/sys/base/bufio/get.c b/sys/base/bufio/get.c
deleted file mode 100644
index 9f10c88..0000000
--- a/sys/base/bufio/get.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "internal.h"
-#include "refill.h"
-
-int
-bufio·getbyte(io·Buffer *buf)
-{
-getbyte:
- if(buf->pos < buf->end)
- return *buf->pos++;
-
- memmove(buf->buf, buf->end - bufio·ungets, bufio·ungets);
-
- if(refill(buf) <= 0)
- return bufio·eof;
-
- goto getbyte;
-}
diff --git a/sys/base/bufio/internal.h b/sys/base/bufio/internal.h
deleted file mode 100644
index 302c035..0000000
--- a/sys/base/bufio/internal.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
diff --git a/sys/base/bufio/read.c b/sys/base/bufio/read.c
deleted file mode 100644
index 09a9f83..0000000
--- a/sys/base/bufio/read.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "internal.h"
-#include "refill.h"
-
-int
-bufio·read(io·Buffer *buf, int sz, int n, void *out)
-{
- byte *wtr;
- int nr, rem, diff;
-
- if(n == 0 || buf->state & bufio·end)
- return bufio·err;
-
- assert(buf->state & bufio·rdr);
-
- wtr = out;
- rem = n*sz;
-
- while(rem > 0){
- diff = buf->end - buf->pos;
- nr = MIN(diff, rem);
- if(!nr){
- if(buf->state & bufio·end)
- break;
- if(refill(buf) <= 0)
- break;
-
- continue;
- }
- memmove(wtr, buf->pos, nr);
- wtr += nr;
- buf->pos += nr;
- rem -= nr;
- }
-
- return n - rem/sz;
-}
diff --git a/sys/base/bufio/reader.c b/sys/base/bufio/reader.c
deleted file mode 100644
index afdaf60..0000000
--- a/sys/base/bufio/reader.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "internal.h"
-
-error
-bufio·initreader(io·Buffer *buf, io·Reader rdr, void *h)
-{
- if (buf->state) {
- errorf("attemped to initialize an active buffer, state is '%d'", buf->state);
- return bufio·err;
- }
- buf->state = bufio·rdr;
- buf->runesize = 0;
- buf->h = h;
- buf->rdr = rdr;
- buf->beg = buf->buf + bufio·ungets;
- buf->pos = buf->beg;
- buf->end = buf->pos;
- buf->size = bufio·size - bufio·ungets;
-
- return 0;
-}
-
-void
-bufio·finireader(io·Buffer *buf)
-{
- buf->state = bufio·nil;
- buf->runesize = 0;
- buf->rdr = (io·Reader){ .read = nil };
-}
diff --git a/sys/base/bufio/refill.h b/sys/base/bufio/refill.h
deleted file mode 100644
index 41e357e..0000000
--- a/sys/base/bufio/refill.h
+++ /dev/null
@@ -1,28 +0,0 @@
-int
-refill(io·Buffer *buf)
-{
- int n;
-
- if(buf->state & bufio·end)
- return bufio·err;
-
- memcpy(buf->buf, buf->pos - bufio·ungets, bufio·ungets);
-
- n = buf->rdr.read(buf->h, 1, buf->size, buf->beg);
- if(n < 0)
- return bufio·err;
- if(n == 0){
- buf->state |= bufio·end;
- return 0;
- }
-
- buf->pos = buf->beg;
- buf->end = buf->pos + n;
-
- // TEST: put a physical EOF byte at the end
- // this would allow for an unget operation
- if(n < buf->size)
- *buf->end++ = EOF;
-
- return n;
-}
diff --git a/sys/base/bufio/rules.mk b/sys/base/bufio/rules.mk
deleted file mode 100644
index 84f283f..0000000
--- a/sys/base/bufio/rules.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-SRCS_$(d)+=\
- $(d)/bufio/get.c\
- $(d)/bufio/read.c\
- $(d)/bufio/reader.c\
- $(d)/bufio/unget.c\
diff --git a/sys/base/bufio/unget.c b/sys/base/bufio/unget.c
deleted file mode 100644
index 3fd16de..0000000
--- a/sys/base/bufio/unget.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "internal.h"
-
-error
-bufio·ungetbyte(io·Buffer *buf, byte c)
-{
- if(!(buf->state & bufio·rdr)) {
- errorf("attempted to unget on non-active reader");
- return bufio·err;
- }
-
- if(buf->pos == buf->buf) {
- errorf("attempted to unget past end of buffer");
- return bufio·err;
- }
-
- buf->pos--;
- return 0;
-}
diff --git a/sys/base/coro/coro.c b/sys/base/coro/coro.c
deleted file mode 100644
index 2255c99..0000000
--- a/sys/base/coro/coro.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "internal.h"
-
-/* Co-routine context */
-Coro*
-coro·make(uintptr stk, uintptr (*func)(Coro*, uintptr))
-{
- if (!func) return nil;
- if (stk == 0) stk = 8192;
-
- byte *block = malloc(stk);
- Coro *co = (Coro*)&block[stk - sizeof(Coro)];
- co->bp = block;
- co->size = stk;
-
- _newcoro(co, func, co);
- return co;
-}
-
-error
-coro·free(Coro *co)
-{
- enum
- {
- NIL,
- GOOD,
- EMPTY,
- LOST,
- };
-
- if (!co) return NIL;
- if (!co->bp) return LOST;
- if (co->size == 0) return EMPTY;
-
- free(co->bp);
-
- return GOOD;
-}
-
-uintptr
-coro·yield(Coro *c, uintptr arg)
-{
- return _coroyield(c, arg);
-}
diff --git a/sys/base/coro/internal.h b/sys/base/coro/internal.h
deleted file mode 100644
index f57d27b..0000000
--- a/sys/base/coro/internal.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-
-extern void _newcoro(Coro *co, uintptr (*func)(Coro*, uintptr), void *stk);
-extern uintptr _coroyield(Coro *co, uintptr arg);
-
-struct Coro
-{
- void *sp;
- void *bp;
- uintptr size;
- void *user;
-};
diff --git a/sys/base/coro/rules.mk b/sys/base/coro/rules.mk
deleted file mode 100644
index c2ee89f..0000000
--- a/sys/base/coro/rules.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-SRCS_$(d)+=\
- $(d)/coro/coro.c\
- $(d)/coro/unix_x64.s\
diff --git a/sys/base/coro/unix_x64.s b/sys/base/coro/unix_x64.s
deleted file mode 100644
index d7de2a2..0000000
--- a/sys/base/coro/unix_x64.s
+++ /dev/null
@@ -1,113 +0,0 @@
-; Nicholas Noll 2019
-;
-; ===================================================================
-%use altreg
-
- bits 64
- default rel
- global _newcoro
- global _coroyield
-
-; ===================================================================
- section .text
-; -------------------------------------------------------------------
-
-%assign L.coro -8
-%assign L.func -16
-
-coroinit:
- mov R7, [RBP + L.coro]
- mov R6, R0
- call [RBP + L.func]
-
-rerun:
- mov R7, [RBP + L.coro]
- mov R6, R0
- call _coroyield
- jmp rerun
-
-; -------------------------------------------------------------------
-; # Register Mapping
-;
-; R0 R1 R2 R3 R4 R5 R6 R7 R8 ...
-; RAX RCX RDX RBX RSP RBP RSI RDI R8 ...
-;
-; # Sys V calling convention
-; func(R7, R6, R2, R1, R8, R9, Z0-7): R0
-;
-; # Stack layout of an in-flight coro
-; *coro
-; *func
-; *bp (base pointer of stack)
-; ....... STACK .........
-; Saved Clobbers
-;
-; ###
-; Stack layout of an init coro
-; Stores the func pointer to init
-; Stores the clobber registers.
-;
-; L.coro [8]
-; L.func [7]
-; coroinit [6]
-; RBP [5]
-; R3 [4]
-; R12 [3]
-; R13 [2]
-; R14 [1]
-; R15 [0]
-
-%define WORDSZ 8
-%define NSAVES 9
-
-; coro *coro·new(co *coro, fn func, bp *stack)
-_newcoro:
- lea R0, [coroinit] ; Store address of init function
- lea R1, [R2 - NSAVES*WORDSZ] ; Store offset address of stack
-
- mov [R1 + 8*WORDSZ], R7 ; Store context pointer
- mov [R1 + 7*WORDSZ], R6 ; Store function pointer
- mov [R1 + 6*WORDSZ], R0 ; Store initializer pointer
- mov [R1 + 5*WORDSZ], R2 ; Store stack base pointer
-
- xor R0, R0
-
- ; Start of mutable stack
- ; Blank out the clobbers
- mov [R1 + 4*WORDSZ], R0 ; R3
- mov [R1 + 3*WORDSZ], R0 ; R12
- mov [R1 + 2*WORDSZ], R0 ; R13
- mov [R1 + 1*WORDSZ], R0 ; R14
- mov [R1 + 0*WORDSZ], R0 ; R15
-
- mov [R7], R1
- ret
-
-; Saves register state
-%macro pushclobs 0
- push RBP
- push R3
- push R12
- push R13
- push R14
- push R15
-%endmacro
-
-; Restores register state
-%macro popclobs 0
- pop R15
- pop R14
- pop R13
- pop R12
- pop R3
- pop RBP
-%endmacro
-
-; uintptr coro.yield(co *coro, data uintptr)
-_coroyield:
- pushclobs
- mov R0, R6 ; Move return value into return register.
- xchg RSP, [R7] ; Atomically swap the stack pointer with the yieldee.
- popclobs
-
- ret
diff --git a/sys/base/error/errorf.c b/sys/base/error/errorf.c
deleted file mode 100644
index 193dd9d..0000000
--- a/sys/base/error/errorf.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "internal.h"
-
-void
-errorf(byte* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- fprintf(stderr, "error: ");
- vfprintf(stderr, fmt, args);
-
- va_end(args);
-}
diff --git a/sys/base/error/exits.c b/sys/base/error/exits.c
deleted file mode 100644
index 6be7d3b..0000000
--- a/sys/base/error/exits.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "internal.h"
-
-void
-exits(char *s)
-{
- if(s == nil || *s == 0)
- exit(0);
-
- fputs(s, stderr);
- exit(1);
-}
diff --git a/sys/base/error/internal.h b/sys/base/error/internal.h
deleted file mode 100644
index 88a8895..0000000
--- a/sys/base/error/internal.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <u.h>
-#include <base.h>
-
diff --git a/sys/base/error/panicf.c b/sys/base/error/panicf.c
deleted file mode 100644
index d698576..0000000
--- a/sys/base/error/panicf.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "internal.h"
-
-void
-panicf(byte* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- printf("panic: ");
- vprintf(fmt, args);
- printf("\n");
-
- va_end(args);
-
- exit(1);
-}
diff --git a/sys/base/error/rules.mk b/sys/base/error/rules.mk
deleted file mode 100644
index e3a9ce0..0000000
--- a/sys/base/error/rules.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-SRCS_$(d)+=\
- $(d)/error/exits.c \
- $(d)/error/errorf.c \
- $(d)/error/panicf.c \
- $(d)/error/verrorf.c \
- $(d)/error/vpanicf.c \
diff --git a/sys/base/error/verrorf.c b/sys/base/error/verrorf.c
deleted file mode 100644
index 15af064..0000000
--- a/sys/base/error/verrorf.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "internal.h"
-
-void
-verrorf(byte* fmt, va_list args)
-{
- printf("error: ");
- vprintf(fmt, args);
- printf("\n");
-}
diff --git a/sys/base/error/vpanicf.c b/sys/base/error/vpanicf.c
deleted file mode 100644
index bea97ac..0000000
--- a/sys/base/error/vpanicf.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "internal.h"
-
-void
-vpanicf(byte* fmt, va_list args)
-{
- printf("panic: ");
- vprintf(fmt, args);
- printf("\n");
-
- exit(1);
-}
diff --git a/sys/base/flate/internal.h b/sys/base/flate/internal.h
deleted file mode 100644
index 794c7c2..0000000
--- a/sys/base/flate/internal.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-
-#include <zlib.h>
-
-typedef struct buffer
-{
- union {
- struct z_stream_s;
- z_stream z;
- };
-
- ubyte buf[4098];
-} buffer;
-
-typedef struct flate·Reader
-{
- io·Reader rdr;
- void* impl;
-
- union {
- struct buffer;
- buffer b;
- };
-} flate·Reader;
-
-typedef struct flate·Writer
-{
- io·Writer wtr;
- void* impl;
-
- union {
- struct buffer;
- buffer b;
- };
-} flate·Writer;
-
diff --git a/sys/base/flate/read.c b/sys/base/flate/read.c
deleted file mode 100644
index 9a42070..0000000
--- a/sys/base/flate/read.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include "internal.h"
-
-int
-flate·read(flate·Reader *rdr, int sz, int n, void *buf)
-{
- int r;
- int err;
- flate·Reader zrdr;
-
- zrdr = *rdr;
- zrdr.next_out = buf;
- zrdr.avail_out = n*sz;
-
-READ:
- err = inflate(&zrdr.b.z, Z_STREAM_END);
- switch (err) {
- case Z_OK:
- return n;
-
- case Z_STREAM_END:
- r = zrdr.next_out - (ubyte*)buf;
- n -= r;
- zrdr.avail_in = zrdr.rdr.read(zrdr.impl, 1, arrlen(zrdr.buf), zrdr.buf);
- if (!zrdr.avail_in) {
- return r;
- }
- zrdr.next_in = zrdr.buf;
- goto READ;
-
- case Z_NEED_DICT:
- errorf("zlib: need input dictionary");
- goto ERROR;
-
- case Z_STREAM_ERROR:
- errorf("zlib: inconsistent stream structure");
- goto ERROR;
- }
-ERROR:
- flate·closereader(rdr);
- return -1;
-}
diff --git a/sys/base/flate/reader.c b/sys/base/flate/reader.c
deleted file mode 100644
index 84f0d80..0000000
--- a/sys/base/flate/reader.c
+++ /dev/null
@@ -1,59 +0,0 @@
-#include "internal.h"
-
-flate·Reader*
-flate·openreader(io·Reader rdr, void* r, mem·Allocator mem, void* m)
-{
- error err;
- flate·Reader *zrdr;
-
- zrdr = mem.alloc(m, 1, sizeof(*zrdr));
-
- zrdr->zalloc = (void *(*)(void *, unsigned int, unsigned int))mem.alloc;
- zrdr->zfree = mem.free;
- zrdr->opaque = m;
- zrdr->avail_in = rdr.read(r, 1, arrlen(zrdr->buf), zrdr->buf);
- zrdr->next_in = zrdr->buf;
-
- err = inflateInit(&zrdr->b.z);
-
- switch (err) {
- case Z_OK:
- return zrdr;
-
- case Z_MEM_ERROR:
- errorf("zlib: not enough memory");
- goto ERROR;
-
- case Z_VERSION_ERROR:
- errorf("zlib: incompatible version");
- goto ERROR;
-
- case Z_STREAM_ERROR:
- errorf("zlib: incorrect input parameters");
- goto ERROR;
-
- default:
- errorf("zlib: unrecognized error code");
- }
-ERROR:
- errorf("zlib: msg: %s", zrdr->msg);
- mem.free(m, zrdr);
- return nil;
-}
-
-error
-flate·closereader(flate·Reader *rdr)
-{
- int err;
- flate·Reader zrdr;
-
- zrdr = *rdr;
- err = inflateEnd(&zrdr.b.z);
- if (err != Z_OK) {
- errorf("zlib: failed to cleanup");
- return err;
- }
- rdr->zfree(rdr->opaque, rdr);
-
- return 0;
-}
diff --git a/sys/base/flate/rules.mk b/sys/base/flate/rules.mk
deleted file mode 100644
index 54d8c14..0000000
--- a/sys/base/flate/rules.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-SRCS_$(d)+=\
- $(d)/flate/read.c\
- $(d)/flate/reader.c\
- $(d)/flate/write.c\
- $(d)/flate/writer.c\
- $(d)/flate/writer.c\
diff --git a/sys/base/flate/write.c b/sys/base/flate/write.c
deleted file mode 100644
index 3f07b94..0000000
--- a/sys/base/flate/write.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "internal.h"
-
-int
-flate·write(flate·Writer *wtr, int sz, int n, void *buf)
-{
- int r;
- int err;
- flate·Writer zwtr;
-
- zwtr = *wtr;
- zwtr.next_out = buf;
-DEFLATE:
- zwtr.avail_out = n*sz;
- err = deflate(&zwtr.z, Z_NO_FLUSH);
-
- switch (err) {
- case Z_STREAM_END:
- return n;
-
- case Z_OK:
- r = (zwtr.next_out - (ubyte*)buf)/sz;
- n -= r;
- if (!n) {
- return r;
- }
- buf += n;
- goto DEFLATE;
-
- case Z_STREAM_ERROR:
- errorf("zlib: bad input");
- goto ERROR;
-
- case Z_BUF_ERROR:
- if (!zwtr.avail_in) {
- zwtr.avail_in += zwtr.wtr.write(zwtr.impl, 1, arrlen(zwtr.buf), buf);
- if (!zwtr.avail_in) {
- errorf("reader: failed read");
- goto ERROR;
- }
- goto DEFLATE;
- }
- }
-
- return 0;
-ERROR:
- errorf("zlib: %s", zwtr.msg);
- return -1;
-}
diff --git a/sys/base/flate/writer.c b/sys/base/flate/writer.c
deleted file mode 100644
index f339ae0..0000000
--- a/sys/base/flate/writer.c
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "internal.h"
-
-flate·Writer*
-flate·openwriter(io·Writer wtr, void* w, mem·Allocator mem, void* m)
-{
- error err;
- flate·Writer *zwtr;
-
- zwtr = mem.alloc(m, 1, sizeof(*zwtr));
- zwtr->zalloc = (void *(*)(void *, unsigned int, unsigned int))mem.alloc;
- zwtr->zfree = mem.free;
- zwtr->opaque = m;
- zwtr->avail_in = 0;
-
- err = deflateInit(&zwtr->b.z, Z_DEFAULT_COMPRESSION);
-
- switch (err) {
- case Z_OK:
- return zwtr;
-
- case Z_MEM_ERROR:
- errorf("zlib: not enough memory");
- goto ERROR;
-
- case Z_VERSION_ERROR:
- errorf("zlib: incompatible version");
- goto ERROR;
-
- case Z_STREAM_ERROR:
- errorf("zlib: incorrect compression level");
- goto ERROR;
-
- default:
- errorf("zlib: unrecognized error code");
- }
-ERROR:
- errorf("zlib: msg: %s", zwtr->msg);
- mem.free(m, zwtr);
- return nil;
-}
-
-error
-flate·closewriter(flate·Writer *wtr)
-{
- int err;
- flate·Writer zwtr;
-
- zwtr = *wtr;
- err = deflateEnd(&zwtr.b.z);
- if (err != Z_OK) {
- errorf("zlib: failed to cleanup");
- return err;
- }
- zwtr.zfree(zwtr.opaque, wtr);
-
- return 0;
-}
diff --git a/sys/base/fs/internal.h b/sys/base/fs/internal.h
deleted file mode 100644
index 7fde093..0000000
--- a/sys/base/fs/internal.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <base/macro/map.h>
-#include <dirent.h>
-
-/*
- * path history
- */
-struct Key
-{
- ino_t ino;
- dev_t dev;
-};
-
-struct fs·History
-{
- SET_STRUCT_BODY(struct Key);
-};
diff --git a/sys/base/fs/rules.mk b/sys/base/fs/rules.mk
deleted file mode 100644
index 3927ae3..0000000
--- a/sys/base/fs/rules.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-SRCS_$(d)+=\
- $(d)/fs/walk.c\
- $(d)/fs/walker.c\
diff --git a/sys/base/fs/walk.c b/sys/base/fs/walk.c
deleted file mode 100644
index d528896..0000000
--- a/sys/base/fs/walk.c
+++ /dev/null
@@ -1,119 +0,0 @@
-#include "internal.h"
-
-#define hash(k) ((int32)k.ino ^ (int32)k.dev)
-#define equal(k1, k2) (k1.ino == k2.ino && k1.dev == k2.dev)
-
-static
-int
-morehistory(fs·History *h, int n)
-{
- SET_GROW(h, struct Key, n, hash, sys·Memory, nil);
-}
-
-static
-int
-addentry(fs·History *h, struct Key key, int *err)
-{
- SET_PUT(h, key, hash, equal, morehistory, err);
-}
-
-static
-void
-forget(fs·History *h)
-{
- if (!h)
- return;
-
- SET_RESET(h);
-}
-
-void
-fs·walk(fs·Walker *fs)
-{
- char *e, *b;
- DIR *dir;
- int new, fd, ofd, flags;
- fs·History *h;
- struct dirent *d;
- io·Stat cwd;
- struct fs·Entry *it;
-
- flags = 0;
- if(fs->flags & fs·nolinks)
- flags |= AT_SYMLINK_NOFOLLOW;
-
- /* get info for base relative to current fd */
- if(fstatat(fs->fd, fs->base, &cwd, flags) < 0){
- if(fs->flags & fs·verbose)
- errorf("stat: %s", fs->path);
- return;
- }
-
- /* if we hit a file, finish! */
- if(!S_ISDIR(cwd.st_mode)) {
- fs->func(fs->data, fs->base, fs->path, &cwd);
- return;
- }
-
- /* have we been here before? (cycle detection) */
- /* if not, add to our path history */
- if (!(fs->flags & fs·nolinks)) {
- addentry(fs->hist, (struct Key){.dev=cwd.st_dev, .ino=cwd.st_ino}, &new);
- if (!new)
- return;
- }
-
- /*
- * operate on directory first if preorder traversal
- * truncate recursion if callback returns an error code
- */
- if (fs->flags & fs·preorder) {
- if (fs->func(fs->data, fs->base, fs->path, &cwd))
- return;
- }
-
- /* open directory */
- if(!fs->max || fs->lev + 1 < fs->max) {
- fd = openat(fs->fd, fs->base, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
- if (fd < 0)
- errorf("open %s:", fs->path);
-
- if (!(dir=fdopendir(fd))) {
- if(fs->flags & fs·verbose)
- errorf("fdopendir: %s", fs->path);
- return;
- }
-
- ofd = fs->fd, fs->fd = fd;
-
- /* traverse children */
- e = fs->end, b = fs->base;
- if (fs->end[-1] != '/')
- *fs->end++ = '/';
-
- fs->base = fs->end;
- while((d = readdir(dir))) {
- if(*d->d_name == '.')
- if(d->d_name[1] == 0 || /* . */
- (d->d_name[1] == '.' && d->d_name[2] == 0)) /* .. */
- continue;
-
- fs->end = str·copyn(fs->base, d->d_name, arrend(fs->path) - fs->base);
-
- fs->lev++;
- fs·walk(fs);
- fs->lev--;
- }
- *e = 0;
- fs->fd = ofd;
- fs->end = e, fs->base = b;
- closedir(dir);
- }
-
- /* operate on directory if postorder (default) traversal */
- if (!(fs->flags & fs·preorder))
- fs->func(fs->data, fs->base, fs->path, &cwd);
-
- if (!fs->lev)
- forget(fs->hist);
-}
diff --git a/sys/base/fs/walker.c b/sys/base/fs/walker.c
deleted file mode 100644
index 65ff391..0000000
--- a/sys/base/fs/walker.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "internal.h"
-
-static
-void
-delete(fs·History *h)
-{
- SET_FREE(h, sys·Memory, nil);
-}
-
-int
-fs·init(fs·Walker *fs, char *path)
-{
- fs->base = fs->end = fs->path;
-
- if(!path || !path[0]){
- path = getcwd(fs->path, arrlen(fs->path));
- if (!path)
- return 1;
- fs->end += strlen(path);
- }else
- fs->end = str·copyn(fs->base, path, arrlen(fs->path));
-
- if(fs->path[0] != '/')
- fs->fd = AT_FDCWD;
-
- if(!fs->hist && !(fs->flags & fs·nolinks))
- fs->hist = calloc(1, sizeof(*fs->hist));
-
- return 0;
-}
-
-void
-fs·fini(fs·Walker *fs)
-{
- if(fs->hist){
- delete(fs->hist);
- free(fs->hist);
- }
-}
diff --git a/sys/base/gz/flush.c b/sys/base/gz/flush.c
deleted file mode 100644
index 011a3ab..0000000
--- a/sys/base/gz/flush.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-error
-gz·flush(gz·Stream *s)
-{
- return gzflush(s, Z_FINISH);
-}
diff --git a/sys/base/gz/get.c b/sys/base/gz/get.c
deleted file mode 100644
index 24ba23a..0000000
--- a/sys/base/gz/get.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "internal.h"
-
-byte
-gz·getbyte(gz·Stream *s)
-{
- // NOTE: Can't call macro
- byte b[2];
- gzread(s, b, 1);
-
- return b[0];
-}
-
-error
-gz·ungetbyte(gz·Stream *s, byte c)
-{
- return gzungetc(c, s);
-}
diff --git a/sys/base/gz/interface.c b/sys/base/gz/interface.c
deleted file mode 100644
index 15b8f10..0000000
--- a/sys/base/gz/interface.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-io·Reader gz·Reader = (io·Reader){ gz·read };
-io·Peeker gz·Peeker = (io·Peeker){ gz·getbyte, gz·ungetbyte };
-io·Seeker gz·Seeker = (io·Seeker){ gz·seek, gz·tell };
-io·PeekReader gz·Peekreader = (io·PeekReader){ gz·read, gz·getbyte, gz·ungetbyte };
-
-io·Writer gz·Writer = (io·Writer){ gz·write };
-io·Putter gz·Putter = (io·Putter){ gz·putbyte, gz·putstring };
-io·PutWriter gz·PutWriter = (io·PutWriter){ gz·write, gz·putbyte, gz·putstring };
-
-io·ReadWriter gz·ReadWriter = (io·ReadWriter){ gz·read, gz·write };
diff --git a/sys/base/gz/internal.h b/sys/base/gz/internal.h
deleted file mode 100644
index 6a268c4..0000000
--- a/sys/base/gz/internal.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-
-#include <zlib.h>
diff --git a/sys/base/gz/open.c b/sys/base/gz/open.c
deleted file mode 100644
index c84ce5e..0000000
--- a/sys/base/gz/open.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "internal.h"
-
-gz·Stream*
-gz·open(byte *path, byte *mode)
-{
- return gzopen(path, mode);
-}
-
-error
-gz·close(gz·Stream* s)
-{
- return gzclose(s);
-}
diff --git a/sys/base/gz/printf.c b/sys/base/gz/printf.c
deleted file mode 100644
index d7f75cf..0000000
--- a/sys/base/gz/printf.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "internal.h"
-
-int
-gz·printf(gz·Stream *s, byte *fmt, ...)
-{
- error err;
-
- va_list args;
- va_start(args, fmt);
- err = gzprintf(s, fmt, args);
- va_end(args);
-
- return err;
-}
-
diff --git a/sys/base/gz/put.c b/sys/base/gz/put.c
deleted file mode 100644
index fa9807d..0000000
--- a/sys/base/gz/put.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-error
-gz·putbyte(gz·Stream *s, byte c)
-{
- return gzputc(s, c);
-}
diff --git a/sys/base/gz/putstring.c b/sys/base/gz/putstring.c
deleted file mode 100644
index 64ff470..0000000
--- a/sys/base/gz/putstring.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "internal.h"
-
-error
-gz·putstring(gz·Stream *s, byte *str)
-{
- return gzputs(s, str);
-}
-
diff --git a/sys/base/gz/read.c b/sys/base/gz/read.c
deleted file mode 100644
index 112fe4d..0000000
--- a/sys/base/gz/read.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "internal.h"
-
-int
-gz·read(gz·Stream *s, int sz, int n, void* buf)
-{
- return gzread(s, buf, n*sz);
-}
-
-int
-gz·readln(gz·Stream *s, int n, byte *buf)
-{
- byte* b;
- b = gzgets(s, buf, n);
-
- return strlen(b);
-}
diff --git a/sys/base/gz/rules.mk b/sys/base/gz/rules.mk
deleted file mode 100644
index a933291..0000000
--- a/sys/base/gz/rules.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-SRCS_$(d)+=\
- $(d)/gz/flush.c\
- $(d)/gz/get.c\
- $(d)/gz/interface.c\
- $(d)/gz/open.c\
- $(d)/gz/printf.c\
- $(d)/gz/put.c\
- $(d)/gz/putstring.c\
- $(d)/gz/read.c\
- $(d)/gz/seek.c\
- $(d)/gz/write.c\
diff --git a/sys/base/gz/seek.c b/sys/base/gz/seek.c
deleted file mode 100644
index 328886d..0000000
--- a/sys/base/gz/seek.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-gz·seek(gz·Stream *s, long off, enum SeekPos whence)
-{
- return gzseek(s, off, whence);
-}
diff --git a/sys/base/gz/write.c b/sys/base/gz/write.c
deleted file mode 100644
index 862d833..0000000
--- a/sys/base/gz/write.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-gz·write(gz·Stream *s, int sz, int n, void* buf)
-{
- return gzwrite(s, buf, n*sz);
-}
diff --git a/sys/base/io/fd.c b/sys/base/io/fd.c
deleted file mode 100644
index ded1b02..0000000
--- a/sys/base/io/fd.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-io·fd(io·Stream *s)
-{
- return fileno(s);
-}
diff --git a/sys/base/io/flush.c b/sys/base/io/flush.c
deleted file mode 100644
index 0f1217a..0000000
--- a/sys/base/io/flush.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-io·flush(io·Stream *s)
-{
- return fflush(s);
-}
diff --git a/sys/base/io/get.c b/sys/base/io/get.c
deleted file mode 100644
index d4e52f8..0000000
--- a/sys/base/io/get.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-byte
-io·getbyte(io·Stream *s)
-{
- return fgetc(s);
-}
diff --git a/sys/base/io/interface.c b/sys/base/io/interface.c
deleted file mode 100644
index bead9e1..0000000
--- a/sys/base/io/interface.c
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "internal.h"
-
-static
-int
-·read(void *rdr, int size, int n, void *buf)
-{
- return io·read((io·Stream *)rdr, size, n, buf);
-}
-
-static
-byte
-·get(void *rdr)
-{
- return io·getbyte((io·Stream *)rdr);
-}
-
-static
-error
-·unget(void *rdr, byte c)
-{
- return io·ungetbyte((io·Stream *)rdr, c);
-}
-
-static
-int
-·write(void *wtr, int sz, int n, void *buf)
-{
- return io·write((io·Stream *)wtr, sz, n, buf);
-}
-
-static
-error
-·put(void *wtr, byte c)
-{
- return io·putbyte((io·Stream *)wtr, c);
-}
-
-static
-int
-·puts(void *wtr, string s)
-{
- return io·putstring((io·Stream *)wtr, s);
-}
-
-static
-int
-·seek(void *skr, long off, enum SeekPos whence)
-{
- return io·seek((io·Stream *)skr, off, whence);
-}
-
-static
-long
-·tell(void *skr)
-{
- return io·tell((io·Stream *)skr);
-}
-
-/* actual interfaces */
-io·Reader sys·Reader = (io·Reader){ ·read };
-io·Seeker sys·Seeker = (io·Seeker){ ·seek, ·tell };
-io·Peeker sys·Peeker = (io·Peeker){ ·get, ·unget };
-io·SeekReader sys·SeekReader = (io·SeekReader){ ·seek, ·tell, ·read };
-io·PeekReader sys·PeekReader = (io·PeekReader){ ·read, ·get, ·unget };
-
-io·Writer sys·Writer = (io·Writer){ ·write };
-io·Putter sys·Putter = (io·Putter){ ·put, ·puts };
-io·PutWriter sys·PutWriter = (io·PutWriter){ ·write, ·put, ·puts };
-
-io·ReadWriter sys·ReadWriter = (io·ReadWriter){ ·read, ·write };
diff --git a/sys/base/io/internal.h b/sys/base/io/internal.h
deleted file mode 100644
index 302c035..0000000
--- a/sys/base/io/internal.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
diff --git a/sys/base/io/open.c b/sys/base/io/open.c
deleted file mode 100644
index e50e334..0000000
--- a/sys/base/io/open.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "internal.h"
-
-io·Stream*
-io·open(byte *name, byte *mode)
-{
- return fopen(name, mode);
-}
-
-error
-io·close(io·Stream *s)
-{
- return fclose(s);
-}
diff --git a/sys/base/io/putbyte.c b/sys/base/io/putbyte.c
deleted file mode 100644
index 2350a8d..0000000
--- a/sys/base/io/putbyte.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-io·putbyte(io·Stream *s, byte c)
-{
- return fputc(c, s);
-}
diff --git a/sys/base/io/putstring.c b/sys/base/io/putstring.c
deleted file mode 100644
index 53fa993..0000000
--- a/sys/base/io/putstring.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-io·putstring(io·Stream *s, string str)
-{
- return fputs(str, s);
-}
diff --git a/sys/base/io/read.c b/sys/base/io/read.c
deleted file mode 100644
index b0ed3d2..0000000
--- a/sys/base/io/read.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-io·read(io·Stream *s, int sz, int n, void *buf)
-{
- return fread(buf, sz, n, s);
-}
diff --git a/sys/base/io/readln.c b/sys/base/io/readln.c
deleted file mode 100644
index 283472d..0000000
--- a/sys/base/io/readln.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-int
-io·readln(io·Stream *s, int n, byte* buf)
-{
- byte* b;
- b = fgets(buf, n+1, s);
- if(b == nil)
- return -1;
-
- return strlen(buf);
-}
diff --git a/sys/base/io/rules.mk b/sys/base/io/rules.mk
deleted file mode 100644
index 2e03ca5..0000000
--- a/sys/base/io/rules.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-SRCS_$(d)+=\
- $(d)/io/fd.c\
- $(d)/io/flush.c\
- $(d)/io/interface.c\
- $(d)/io/open.c\
- $(d)/io/putbyte.c\
- $(d)/io/putstring.c\
- $(d)/io/read.c\
- $(d)/io/readln.c\
- $(d)/io/seek.c\
- $(d)/io/stat.c\
- $(d)/io/tell.c\
- $(d)/io/unget.c\
- $(d)/io/write.c\
diff --git a/sys/base/io/seek.c b/sys/base/io/seek.c
deleted file mode 100644
index d0e7488..0000000
--- a/sys/base/io/seek.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-io·seek(io·Stream *s, long off, enum SeekPos origin)
-{
- return fseek(s, off, origin);
-}
diff --git a/sys/base/io/stat.c b/sys/base/io/stat.c
deleted file mode 100644
index d86f1ee..0000000
--- a/sys/base/io/stat.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-error
-io·stat(io·Stream *s, io·Stat *buf)
-{
- return fstat(fileno(s), buf);
-}
diff --git a/sys/base/io/tell.c b/sys/base/io/tell.c
deleted file mode 100644
index 1c50439..0000000
--- a/sys/base/io/tell.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-long
-io·tell(io·Stream *s)
-{
- return ftell(s);
-}
diff --git a/sys/base/io/unget.c b/sys/base/io/unget.c
deleted file mode 100644
index 5ec3536..0000000
--- a/sys/base/io/unget.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-error
-io·ungetbyte(io·Stream *s, byte c)
-{
- return ungetc(c, s);
-}
diff --git a/sys/base/io/write.c b/sys/base/io/write.c
deleted file mode 100644
index 63df664..0000000
--- a/sys/base/io/write.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-io·write(io·Stream *s, int sz, int n, void *buf)
-{
- return fwrite(buf, sz, n, s);
-}
diff --git a/sys/base/mem/arena.c b/sys/base/mem/arena.c
deleted file mode 100644
index b2ce044..0000000
--- a/sys/base/mem/arena.c
+++ /dev/null
@@ -1,119 +0,0 @@
-#include "internal.h"
-
-#define ARENA_ALIGN 8
-#define ARENA_BLOCK_SIZE 1024 * 1024
-
-#define ALIGN_DOWN(n, a) ((n) & ~((a)-1))
-#define ALIGN_UP(n, a) ALIGN_DOWN((n) + (a)-1, (a))
-#define ALIGN_DOWN_PTR(p, a) ((void*)ALIGN_DOWN((uintptr)(p), (a)))
-#define ALIGN_UP_PTR(p, a) ((void*)ALIGN_UP((uintptr)(p), (a)))
-
-struct Block
-{
- struct Block *next;
- byte buf[];
-};
-
-struct mem·Arena
-{
- void *heap;
- mem·Allocator mem;
-
- byte *off;
- byte *end;
- struct Block *curr;
- struct Block first;
-};
-
-static
-void*
-·arenaalloc(void *heap, uint n, ulong size)
-{
- return mem·arenaalloc(heap, n, size);
-}
-
-static
-void
-·arenafree(void *heap, void *ptr)
-{
- /* no-op */
-}
-
-mem·Allocator mem·ArenaAllocator = {
- .alloc = ·arenaalloc,
- .free = ·arenafree,
-};
-
-
-static
-void
-grow(mem·Arena *a, vlong min)
-{
- uintptr size;
- struct Block *blk;
-
- size = ALIGN_UP(MAX(min, ARENA_BLOCK_SIZE), ARENA_ALIGN);
- blk = a->mem.alloc(a->heap, 1, sizeof(*blk) + size);
- a->off = blk->buf;
- a->end = a->off + size;
-
- assert(a->curr->next == nil);
- assert(a->off == ALIGN_DOWN_PTR(a->off, ARENA_ALIGN));
-
- a->curr->next = blk;
- a->curr = blk;
-}
-
-mem·Arena*
-mem·makearena(mem·Allocator from, void *impl)
-{
- mem·Arena *a = from.alloc(impl, 1, sizeof(*a) + ARENA_BLOCK_SIZE);
- a->mem = from;
- a->heap = impl;
- a->off = a->first.buf;
- a->end = a->first.buf + ARENA_BLOCK_SIZE;
- a->curr = &a->first;
- a->first.next = nil;
-
- return a;
-}
-
-void
-mem·freearena(mem·Arena *a)
-{
- struct Block *it, *next;
-
- it = a->first.next;
- while (it != nil) {
- next = it->next;
- a->mem.free(a->heap, it);
- it = next;
- }
-
- a->mem.free(a->heap, a);
-}
-
-void*
-mem·arenaalloc(mem·Arena *a, uint n, ulong size)
-{
- if(!n) {
- return nil;
- }
-
- void *ptr;
- // TODO(nnoll): check for overflow
- size = n * size;
-
- if (size > (ulong)(a->end - a->off)) {
- grow(a, size);
- assert(size <= (uintptr)(a->end - a->off));
- }
-
- ptr = a->off;
- a->off = ALIGN_UP_PTR(a->off + size, ARENA_ALIGN);
-
- assert(a->off <= a->end);
- assert(ptr == ALIGN_DOWN_PTR(ptr, ARENA_ALIGN));
-
- return ptr;
-}
diff --git a/sys/base/mem/buffer.c b/sys/base/mem/buffer.c
deleted file mode 100644
index b684d35..0000000
--- a/sys/base/mem/buffer.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "internal.h"
-
-/* Grow to particular size */
-void*
-·bufgrow(void* buf, vlong newLen, vlong eltsize)
-{
- assert(bufcap(buf) <= (SIZE_MAX - 1) / 2);
-
- vlong newCap = MAX(16, MAX(1 + 2 * bufcap(buf), newLen));
-
- assert(newLen <= newCap);
- assert(newCap <= (SIZE_MAX - offsetof(BufHdr, buf)) / eltsize);
-
- vlong newSize = offsetof(BufHdr, buf) + newCap * eltsize;
-
- BufHdr* newHdr;
- if (buf) {
- newHdr = bufhdr(buf);
- newHdr = (BufHdr*)realloc((void*)newHdr, newSize);
- } else {
- newHdr = (BufHdr*)malloc(newSize);
- newHdr->len = 0;
- }
-
- newHdr->cap = newCap;
- return (void*)newHdr->buf;
-}
-
-/* Pop out a value */
-void
-·bufdel(void *buf, int i, vlong eltsize)
-{
- int n;
- byte *b;
- byte stk[1024];
- assert(eltsize < sizeof(stk));
-
- b = (byte*)buf;
- if(n = buflen(buf), i < n) {
- memcpy(stk, b+eltsize*i, eltsize);
- memcpy(b+eltsize*i, b+eltsize*(i+1), eltsize*(n-i-1));
- memcpy(b+eltsize*(n-1), stk, eltsize);
- }
- bufhdr(buf)->len--;
-}
diff --git a/sys/base/mem/interface.c b/sys/base/mem/interface.c
deleted file mode 100644
index 4d7d1ce..0000000
--- a/sys/base/mem/interface.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "internal.h"
-
-static
-void
-·free(void *_, void *ptr) {
- return free(ptr);
-}
-
-static
-void *
-·alloc(void *_, uint n, ulong size) {
- return malloc(n*size);
-}
-
-static
-void *
-·calloc(void *_, uint n, ulong size) {
- return calloc(n, size);
-}
-
-static
-void *
-·realloc(void *_, void *ptr, uint n, ulong size) {
- return realloc(ptr, n*size);
-}
-
-mem·Allocator sys·Memory = {
- .alloc = ·calloc,
- .free = ·free
-};
-
-mem·Reallocator sys·FullMemory = {
- .alloc = ·calloc,
- .realloc = ·realloc,
- .free = ·free
-};
diff --git a/sys/base/mem/internal.h b/sys/base/mem/internal.h
deleted file mode 100644
index 302c035..0000000
--- a/sys/base/mem/internal.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
diff --git a/sys/base/mem/rules.mk b/sys/base/mem/rules.mk
deleted file mode 100644
index b912d0c..0000000
--- a/sys/base/mem/rules.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-SRCS_$(d)+=\
- $(d)/mem/arena.c\
- $(d)/mem/buffer.c\
- $(d)/mem/interface.c\
- $(d)/mem/set64.c\
diff --git a/sys/base/mem/set64.c b/sys/base/mem/set64.c
deleted file mode 100644
index 464b3ad..0000000
--- a/sys/base/mem/set64.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "internal.h"
-
-void
-mem·set64(void *dst, uint64 val, uintptr size)
-{
- intptr i;
-
- for(i = 0; i < (size & (~7)); i += 8)
- memcpy((byte*)dst + i, &val, 8);
-
- for(; i < size; i++)
- ((byte*)dst)[i] = ((byte*)&val)[i&7];
-}
diff --git a/sys/base/mmap/internal.h b/sys/base/mmap/internal.h
deleted file mode 100644
index 7606c7e..0000000
--- a/sys/base/mmap/internal.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-#include <sys/mman.h>
diff --git a/sys/base/mmap/mmap.c b/sys/base/mmap/mmap.c
deleted file mode 100644
index ce3011c..0000000
--- a/sys/base/mmap/mmap.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "internal.h"
-
-mmap·Reader
-mmap·open(byte *filename)
-{
- int fd;
- int err;
- void *buf;
- io·Stream *s;
- io·Stat st;
-
- s = io·open(filename, "r");
- fd = io·fd(s);
- err = io·stat(s, &st);
- if(err){
- errorf("file stat: error code %d", err);
- goto ERROR;
- }
-
- buf = mmap(nil, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
- if(!buf){
- errorf("mmap: failed");
- goto ERROR;
- }
- // NOTE: posix systems require that reference kept to mmap file after fd is closed
- io·close(s);
- return (mmap·Reader){.len=st.st_size, .b=buf};
-
-ERROR:
- io·close(s);
- return (mmap·Reader){ 0 };
-}
-
-error
-mmap·close(mmap·Reader rdr)
-{
- munmap(rdr.b, rdr.len);
- return 0;
-}
diff --git a/sys/base/mmap/rules.mk b/sys/base/mmap/rules.mk
deleted file mode 100644
index fb3cab5..0000000
--- a/sys/base/mmap/rules.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-SRCS_$(d)+=\
- $(d)/mmap/mmap.c\
diff --git a/sys/base/os/basename.c b/sys/base/os/basename.c
deleted file mode 100644
index b5bb343..0000000
--- a/sys/base/os/basename.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "internal.h"
-
-char*
-os·basename(char *path)
-{
- char *sep;
-
- sep = strrchr(path, os·sep());
- return (sep == nil) ? path : sep+1;
-}
diff --git a/sys/base/os/exists.c b/sys/base/os/exists.c
deleted file mode 100644
index a3c8935..0000000
--- a/sys/base/os/exists.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-int
-os·exists(byte *path, int flag)
-{
- return access(path, flag) == 0;
-}
diff --git a/sys/base/os/internal.h b/sys/base/os/internal.h
deleted file mode 100644
index 302c035..0000000
--- a/sys/base/os/internal.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
diff --git a/sys/base/os/rules.mk b/sys/base/os/rules.mk
deleted file mode 100644
index bf1e71d..0000000
--- a/sys/base/os/rules.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-SRCS_$(d)+=\
- $(d)/os/basename.c\
- $(d)/os/exists.c\
- $(d)/os/sep.c\
diff --git a/sys/base/os/sep.c b/sys/base/os/sep.c
deleted file mode 100644
index 750e627..0000000
--- a/sys/base/os/sep.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "internal.h"
-
-int
-os·sep(void)
-{
-#if defined(UNIX) || defined(__linux__)
- return '/';
-#elif defined(WIN32)
- return '\\';
-#else
- panicf("unrecognized operating system");
- return '\0';
-#endif
-}
diff --git a/sys/base/rng/base.c b/sys/base/rng/base.c
deleted file mode 100644
index 9ec496e..0000000
--- a/sys/base/rng/base.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "internal.h"
-
-static uint64
-splitmix64(struct Mix *state)
-{
- uint64 result = state->s;
-
- state->s = result + 0x9E3779B97f4A7C15;
- result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9;
- result = (result ^ (result >> 27)) * 0x94D049BB133111EB;
- return result ^ (result >> 31);
-}
-
-int
-rng·init(uint64 seed)
-{
- int i;
- Mix smstate = {seed};
-
- for(i=0; i < 4; i++)
- rng·RNG.s[i] = splitmix64(&smstate);
-
- return 0;
-}
diff --git a/sys/base/rng/bernoulli.c b/sys/base/rng/bernoulli.c
deleted file mode 100644
index 02f531e..0000000
--- a/sys/base/rng/bernoulli.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "internal.h"
-
-bool
-rng·bernoulli(double f)
-{
- return rng·random() < f;
-}
diff --git a/sys/base/rng/exponential.c b/sys/base/rng/exponential.c
deleted file mode 100644
index c07e007..0000000
--- a/sys/base/rng/exponential.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "internal.h"
-
-/* Returns a random float64 between 0 and 1 */
-double
-rng·exponential(double lambda)
-{
- double f;
-
- f = rng·random();
- return -log(1 - f)/lambda;
-}
diff --git a/sys/base/rng/internal.h b/sys/base/rng/internal.h
deleted file mode 100644
index 9cf5f41..0000000
--- a/sys/base/rng/internal.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-
-#define rol64(x, k) ((x) << (k) | ((x) >> (64-(k))))
-
-typedef struct Rng
-{
- uint64 s[4];
-} Rng;
-
-typedef struct Mix
-{
- uint64 s;
-} Mix;
-
-
-extern Rng rng·RNG;
diff --git a/sys/base/rng/normal.c b/sys/base/rng/normal.c
deleted file mode 100644
index aab5731..0000000
--- a/sys/base/rng/normal.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "internal.h"
-
-static inline double
-erfinv(double x)
-{
- /* useful constants */
- static double
- a0 = 1.1975323115670912564578e0, a1 = 4.7072688112383978012285e1,
- a2 = 6.9706266534389598238465e2, a3 = 4.8548868893843886794648e3,
- a4 = 1.6235862515167575384252e4, a5 = 2.3782041382114385731252e4,
- a6 = 1.1819493347062294404278e4, a7 = 8.8709406962545514830200e2,
-
- b0 = 1.0000000000000000000e0, b1 = 4.2313330701600911252e1,
- b2 = 6.8718700749205790830e2, b3 = 5.3941960214247511077e3,
- b4 = 2.1213794301586595867e4, b5 = 3.9307895800092710610e4,
- b6 = 2.8729085735721942674e4, b7 = 5.2264952788528545610e3,
-
- c0 = 1.42343711074968357734e0, c1 = 4.63033784615654529590e0,
- c2 = 5.76949722146069140550e0, c3 = 3.64784832476320460504e0,
- c4 = 1.27045825245236838258e0, c5 = 2.41780725177450611770e-1,
- c6 = 2.27238449892691845833e-2, c7 = 7.74545014278341407640e-4,
-
- d0 = 1.4142135623730950488016887e0, d1 = 2.9036514445419946173133295e0,
- d2 = 2.3707661626024532365971225e0, d3 = 9.7547832001787427186894837e-1,
- d4 = 2.0945065210512749128288442e-1, d5 = 2.1494160384252876777097297e-2,
- d6 = 7.7441459065157709165577218e-4, d7 = 1.4859850019840355905497876e-9,
-
- e0 = 6.65790464350110377720e0, e1 = 5.46378491116411436990e0,
- e2 = 1.78482653991729133580e0, e3 = 2.96560571828504891230e-1,
- e4 = 2.65321895265761230930e-2, e5 = 1.24266094738807843860e-3,
- e6 = 2.71155556874348757815e-5, e7 = 2.01033439929228813265e-7,
-
- f0 = 1.414213562373095048801689e0, f1 = 8.482908416595164588112026e-1,
- f2 = 1.936480946950659106176712e-1, f3 = 2.103693768272068968719679e-2,
- f4 = 1.112800997078859844711555e-3, f5 = 2.611088405080593625138020e-5,
- f6 = 2.010321207683943062279931e-7, f7 = 2.891024605872965461538222e-15,
-
- Ln2 = 0.693147180559945309417232121458176568075500134360255254120680009;
-
- int s;
- double r, z1, z2;
-
- if(x < 0) {
- s = -1;
- x = -x;
- } else {
- s = +1;
- }
-
- if(x <= 0.85) {
- r = 0.180625 - 0.25*x*x;
- z1 = ((((((a7*r+a6)*r+a5)*r+a4)*r+a3)*r+a2)*r+a1)*r + a0;
- z2 = ((((((b7*r+b6)*r+b5)*r+b4)*r+b3)*r+b2)*r+b1)*r + b0;
- return s*(x*z1) / z2;
- }
- r = sqrt(Ln2 - log(1.0-x));
- if(r <= 5.0) {
- r -= 1.6;
- z1 = ((((((c7*r+c6)*r+c5)*r+c4)*r+c3)*r+c2)*r+c1)*r + c0;
- z2 = ((((((d7*r+d6)*r+d5)*r+d4)*r+d3)*r+d2)*r+d1)*r + d0;
- } else {
- r -= 5.0;
- z1 = ((((((e7*r+e6)*r+e5)*r+e4)*r+e3)*r+e2)*r+e1)*r + e0;
- z2 = ((((((f7*r+f6)*r+f5)*r+f4)*r+f3)*r+f2)*r+f1)*r + f0;
- }
-
- return s*z1/z2;
-}
-
-double
-rng·normal(void)
-{
- double f;
- f = rng·random();
-
- return sqrt(2)*erfinv(2*f-1);
-}
diff --git a/sys/base/rng/poisson.c b/sys/base/rng/poisson.c
deleted file mode 100644
index 3ec15c9..0000000
--- a/sys/base/rng/poisson.c
+++ /dev/null
@@ -1,126 +0,0 @@
-#include "internal.h"
-
-/*
- * Ahrens, J. H., & Dieter, U. (1982).
- * Computer Generation of Poisson Deviates from Modified Normal Distributions.
- */
-static double factorial[10] = {1., 1., 2., 6., 24., 120., 720., 5040., 40320., 362880.};
-static double coeffs[9] = {
- -.500000000, +.333333333, -.249999856,
- +.200011780, -.166684875, +.142187833,
- -.124196313, +.125005956, -.114265030,
-};
-
-static inline
-double
-log1pmx(double x, double off)
-{
- int i;
- double r, t;
-
- if(-0.25 < x && x < 0.25) {
- r = 0;
- t = 1;
- for(i=0;i<arrlen(coeffs);i++) {
- r += coeffs[i]*t;
- t *= x;
- }
-
- return x*x*r;
- }
- return log(1+x) - off;
-}
-
-static inline
-double
-procf(double mu, double s, int64 K, double *px, double *py, double *fx, double *fy)
-{
- double d, V, X;
- double w, b1, b2, c1, c2, c3, c0, c;
-
- w = 0.3989422804014327/s;
- b1 = 0.041666666666666664/mu;
- b2 = 0.3*b1*b1;
- c3 = 0.14285714285714285*b1*b2;
- c2 = b2 - 15.*c3;
- c1 = b1 - 6.*b2 + 45.*c3;
- c0 = 1 - b1 + 3.*b2 - 15.*c3;
- c = .1069/mu;
-
- if(K < 10) {
- *px = -mu;
- *py = pow(mu,K) / factorial[K];
- }else{
- d = 0.08333333333333333/K;
- d = d - 4.8*d*d*d;
- V = (mu - K) / K;
-
- *px = K*log1pmx(V,mu-K) - d;
- *py = 0.3989422804014327/sqrt(K);
- }
-
- X = (K - mu + 0.5)/s;
- *fx = -0.5*X*X;
- *fy = w*(((c3*X*X + c2)*X*X + c1)*X*X + c0);
-
- return c;
-}
-
-static inline
-uint64
-bigpoisson(double mu)
-{
- int64 L,K;
- double G,s,d,U,E,T;
- double px,py,fx,fy,c;
-
- s = sqrt(mu);
- d = 6*mu*mu;
- L = floor(mu - 1.1484);
-
-stepN:
- G = mu + s*rng·normal();
- K = floor(G);
- if(K<0)
- goto stepP;
-stepI:
- if(K>=L)
- return K;
-stepS:
- U = rng·random();
- if(d*U >= (mu-K)*(mu-K)*(mu-K))
- return K;
-stepP:
- if(G < 0)
- goto stepE;
-stepQ:
- c = procf(mu, s, K, &px, &py, &fx, &fy);
-stepE:
- E = rng·exponential(1.0);
- U = rng·random();
- U = U + U - 1;
- T = 1.8 + copysign(E,U);
- if(T < 0.6744)
- goto stepE;
- K = floor(mu + s*T);
- c = procf(mu, s, K, &px, &py, &fx, &fy);
-stepH:
- if(c*fabs(U) > (py*exp(px + E) - fy*exp(fx + E)))
- goto stepE;
- return K;
-}
-
-uint64
-rng·poisson(double mean)
-{
- int64 n;
- double z;
-
- if(mean<10.0) {
- for(n=0, z=rng·exponential(1.0); z<mean; ++n, z+=rng·exponential(1.0))
- ;
- return n;
- }
-
- return bigpoisson(mean);
-}
diff --git a/sys/base/rng/random.c b/sys/base/rng/random.c
deleted file mode 100644
index bd1bd6b..0000000
--- a/sys/base/rng/random.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "internal.h"
-
-static uint64
-xoshiro256ss(Rng *state)
-{
- uint64 *s = state->s;
- uint64 result = rol64(s[1] * 5, 7) * 9;
- uint64 t = s[1] << 17;
-
- s[2] ^= s[0];
- s[3] ^= s[1];
- s[1] ^= s[2];
- s[0] ^= s[3];
-
- s[2] ^= t;
- s[3] = rol64(s[3], 45);
-
- return result;
-}
-
-double
-rng·random(void)
-{
- uint64 r = xoshiro256ss(&rng·RNG);
- return (double)r / (double)UINT64_MAX;
-}
-
-uint64
-rng·randi(int max)
-{
- uint64 r = xoshiro256ss(&rng·RNG);
- return r % max;
-}
diff --git a/sys/base/rng/rules.mk b/sys/base/rng/rules.mk
deleted file mode 100644
index 407b1bf..0000000
--- a/sys/base/rng/rules.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-SRCS_$(d)+=\
- $(d)/rng/base.c\
- $(d)/rng/bernoulli.c\
- $(d)/rng/exponential.c\
- $(d)/rng/normal.c\
- $(d)/rng/poisson.c\
- $(d)/rng/random.c\
diff --git a/sys/base/rules.mk b/sys/base/rules.mk
deleted file mode 100644
index 1726aa3..0000000
--- a/sys/base/rules.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-include share/push.mk
-
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := $(d)/arg.c
-include $(d)/bufio/rules.mk
-include $(d)/coro/rules.mk
-include $(d)/error/rules.mk
-include $(d)/flate/rules.mk
-include $(d)/fs/rules.mk
-include $(d)/gz/rules.mk
-include $(d)/io/rules.mk
-include $(d)/mem/rules.mk
-include $(d)/mmap/rules.mk
-include $(d)/os/rules.mk
-include $(d)/rng/rules.mk
-include $(d)/sort/rules.mk
-include $(d)/string/rules.mk
-
-
-TSTS_$(d) := $(d)/test.c
-
-LIBS_$(d) := $(d)/base.a
-BINS_$(d) :=
-
-include share/paths.mk
-
-$(LIBS_$(d)): $(OBJS_$(d))
- $(ARCHIVE)
-
-$(UNTS_$(d)): TCLIBS := $(LIBS_$(d))
-$(UNTS_$(d)): $(TOBJS_$(d)) $(LIBS_$(d))
- $(LINK)
-
-include share/pop.mk
diff --git a/sys/base/sort/double.c b/sys/base/sort/double.c
deleted file mode 100644
index c3feac2..0000000
--- a/sys/base/sort/double.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·double(uintptr sz, double arr[])
-{
- double tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/float.c b/sys/base/sort/float.c
deleted file mode 100644
index 57bd482..0000000
--- a/sys/base/sort/float.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·float(uintptr sz, float arr[])
-{
- float tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/int.c b/sys/base/sort/int.c
deleted file mode 100644
index 33e1def..0000000
--- a/sys/base/sort/int.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·int(uintptr sz, int arr[])
-{
- int tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/int16.c b/sys/base/sort/int16.c
deleted file mode 100644
index 072a3eb..0000000
--- a/sys/base/sort/int16.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·int16(uintptr sz, int16 arr[])
-{
- int16 tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/int32.c b/sys/base/sort/int32.c
deleted file mode 100644
index 27b3b7b..0000000
--- a/sys/base/sort/int32.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·int32(uintptr sz, int32 arr[])
-{
- int32 tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/int64.c b/sys/base/sort/int64.c
deleted file mode 100644
index b3fa5d4..0000000
--- a/sys/base/sort/int64.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·int64(uintptr sz, int64 arr[])
-{
- int64 tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/int8.c b/sys/base/sort/int8.c
deleted file mode 100644
index 5848e6e..0000000
--- a/sys/base/sort/int8.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·int8(uintptr sz, int8 arr[])
-{
- int8 tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/internal.h b/sys/base/sort/internal.h
deleted file mode 100644
index ac569de..0000000
--- a/sys/base/sort/internal.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-#include <base/macro/qsort.h>
diff --git a/sys/base/sort/rules.mk b/sys/base/sort/rules.mk
deleted file mode 100644
index 780d6ea..0000000
--- a/sys/base/sort/rules.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-SRCS_$(d)+=\
- $(d)/sort/double.c\
- $(d)/sort/float.c\
- $(d)/sort/int.c\
- $(d)/sort/int16.c\
- $(d)/sort/int32.c\
- $(d)/sort/int64.c\
- $(d)/sort/int8.c\
- $(d)/sort/string.c\
- $(d)/sort/uint.c\
- $(d)/sort/uint16.c\
- $(d)/sort/uint32.c\
- $(d)/sort/uint64.c\
- $(d)/sort/uint8.c\
diff --git a/sys/base/sort/string.c b/sys/base/sort/string.c
deleted file mode 100644
index b511efa..0000000
--- a/sys/base/sort/string.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·string(uintptr sz, byte* arr[])
-{
- byte *tmp;
-#define LESS(i, j) (strcmp(arr[i], arr[j]) < 0)
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/uint.c b/sys/base/sort/uint.c
deleted file mode 100644
index 5b27330..0000000
--- a/sys/base/sort/uint.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·uint(uintptr sz, uint arr[])
-{
- uint tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/uint16.c b/sys/base/sort/uint16.c
deleted file mode 100644
index 2b635b4..0000000
--- a/sys/base/sort/uint16.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·uint16(uintptr sz, uint16 arr[])
-{
- uint16 tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/uint32.c b/sys/base/sort/uint32.c
deleted file mode 100644
index 99a58cf..0000000
--- a/sys/base/sort/uint32.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·uint32(uintptr sz, uint32 arr[])
-{
- uint32 tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/uint64.c b/sys/base/sort/uint64.c
deleted file mode 100644
index 2769825..0000000
--- a/sys/base/sort/uint64.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·uint64(uintptr sz, uint64 arr[])
-{
- uint64 tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/sort/uint8.c b/sys/base/sort/uint8.c
deleted file mode 100644
index ff02b3c..0000000
--- a/sys/base/sort/uint8.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-void
-sort·uint8(uintptr sz, uint8 arr[])
-{
- uint8 tmp;
-#define LESS(i, j) (arr[i] < arr[j])
-#define SWAP(i, j) (tmp = arr[i], arr[i] = arr[j], arr[j] = tmp)
- QSORT(sz, LESS, SWAP);
-#undef SWAP
-#undef LESS
-}
diff --git a/sys/base/string/append.c b/sys/base/string/append.c
deleted file mode 100644
index d4d0396..0000000
--- a/sys/base/string/append.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "internal.h"
-
-// append will append the given null terminated c string to the string data
-// structure. this variant can append a substring of length len of the given
-// string to our buffer. the result is reallocated if not enough room is present
-// in the buffer.
-int
-str·appendlen(string *s, vlong n, const byte* b)
-{
- /*
- bl = strlen(b);
- if (n > bl) panicf("attempted to make a substring longer than string");
- */
-
- str·grow(s, n);
- if(*s == nil)
- return 0;
-
- Hdr* h = (Hdr*)(*s - sizeof(Hdr));
-
- memcpy(*s + str·len(*s), b, n);
- h->len += n;
- (*s)[h->len] = '\0';
-
- return n;
-}
-
-// append will append the given null terminated c string to the string data
-// structure. this variant will append the entire string.
-int
-str·append(string *s, const byte* b)
-{
- return str·appendlen(s, strlen(b), b);
-}
-
-// appendbyte will append the given byte to our string.
-// NOTE: as the byte is on the stack, it is not null-terminated.
-// can not pass to the above functions.
-int
-str·appendbyte(string *s, const byte b)
-{
- str·grow(s, 1);
- if(*s == nil)
- return 0;
-
- Hdr* h = (Hdr*)(*s - sizeof(Hdr));
-
- *(*s + str·len(*s)) = b;
- h->len++;
- (*s)[h->len] = '\0'; // NOTE: I don't think an explicit zero is required..?
-
- return 1;
-}
diff --git a/sys/base/string/appendf.c b/sys/base/string/appendf.c
deleted file mode 100644
index 4b8d76c..0000000
--- a/sys/base/string/appendf.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "internal.h"
-
-/*
- * appendf will append the given formatted string to our buffer.
- * returns the newly minted string
- */
-
-int
-str·appendf(string *s, const byte* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- int remain = str·cap(*s) - str·len(*s);
- int n = vsnprintf(*s + str·len(*s), remain + 1, fmt, args);
- va_end(args);
-
- if(n > remain){
- // If the first write was incomplete, we overwite the data again.
- str·grow(s, n);
- va_list args;
- va_start(args, fmt);
- n = vsnprintf(*s + str·len(*s), n + 1, fmt, args);
- assert(n - remain <= str·cap(*s));
- va_end(args);
- }
-
- Hdr* h = (Hdr*)(*s - sizeof(Hdr));
- h->len += n;
-
- return n;
-}
diff --git a/sys/base/string/clear.c b/sys/base/string/clear.c
deleted file mode 100644
index 986f809..0000000
--- a/sys/base/string/clear.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "internal.h"
-
-void
-str·clear(string *s)
-{
- Hdr* h = (Hdr*)(*s - sizeof(Hdr));
- h->len = 0;
- *s[0] = '\0';
-}
diff --git a/sys/base/string/copyn.c b/sys/base/string/copyn.c
deleted file mode 100644
index 09c2879..0000000
--- a/sys/base/string/copyn.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "internal.h"
-
-char *
-str·copyn(char *dst, char *src, int n)
-{
- while(*src && n-- > 0)
- *dst++ = *src++;
-
- *dst = 0;
- return dst;
-}
diff --git a/sys/base/string/equals.c b/sys/base/string/equals.c
deleted file mode 100644
index a975cf5..0000000
--- a/sys/base/string/equals.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-// Equals returns true if string s and t are equivalent.
-bool
-str·equals(const string s, const string t)
-{
- vlong sL = str·len(s);
- vlong tL = str·len(t);
- if (sL != tL) return false;
-
- return memcmp(s, t, sL) == 0;
-}
diff --git a/sys/base/string/find.c b/sys/base/string/find.c
deleted file mode 100644
index 20f990e..0000000
--- a/sys/base/string/find.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "internal.h"
-
-// find will find the first occurence of
-// substr in the string returns -1 if nothing was found.
-int
-str·find(string s, const byte* substr)
-{
- byte* loc = strstr(s, substr);
- if (loc == nil) return -1;
- return (int)(loc - s);
-}
diff --git a/sys/base/string/fit.c b/sys/base/string/fit.c
deleted file mode 100644
index 56ab041..0000000
--- a/sys/base/string/fit.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "internal.h"
-
-// fit reallocates the string such that the buffer is exactly sized for the
-// buffer. if the capacity equals the length, then the function is a noop. the
-// byte array is unchanged.
-void
-str·fit(string *s)
-{
- Hdr* h;
- vlong cap = str·cap(*s);
- vlong len = str·len(*s);
-
- if (cap == len) return;
-
- h = (Hdr*)(s - sizeof(Hdr));
- h = realloc(h, sizeof(*h) + len + 1);
- h->cap = len;
-
- *s = h->buf;
-}
diff --git a/sys/base/string/free.c b/sys/base/string/free.c
deleted file mode 100644
index 7b5ee98..0000000
--- a/sys/base/string/free.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "internal.h"
-
-// free returns memory associated to the buffer.
-void
-str·free(string s)
-{
- free(s - sizeof(Hdr));
-}
diff --git a/sys/base/string/grow.c b/sys/base/string/grow.c
deleted file mode 100644
index 39a9d2f..0000000
--- a/sys/base/string/grow.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "internal.h"
-
-// grow ensures that the string can encompass at least delta bytes.
-// if it already can, this is a no op.
-// if it can't, the string will be reallocated.
-void
-str·grow(string *s, vlong delta)
-{
- Hdr *h, *newh;
- vlong cap = str·cap(*s);
- vlong len = str·len(*s);
- assert(cap >= len); // To prevent unsigned behavior
-
- if (cap - len >= delta) return;
-
- h = (Hdr*)(*s - sizeof(Hdr));
-
- vlong newCap = cap + delta;
- assert(newCap >= cap); // To prevent unsigned behavior
- if (newCap < MAX_STRING_ALLOC) {
- newCap *= 2;
- } else
- newCap += MAX_STRING_ALLOC;
-
- newh = (Hdr*)realloc(h, sizeof(*h) + newCap + 1);
- if (newh == nil) return;
-
- memset(newh->buf + len, '\0', newCap - len);
- newh->cap = newCap;
- newh->len = len;
-
- *s = newh->buf;
-}
diff --git a/sys/base/string/internal.h b/sys/base/string/internal.h
deleted file mode 100644
index 8c16c64..0000000
--- a/sys/base/string/internal.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include <u.h>
-#include <base.h>
-
-#define MAX_STRING_ALLOC 1024 * 1024
-
-typedef struct Hdr
-{
- vlong len;
- vlong cap;
- byte buf[];
-} Hdr;
diff --git a/sys/base/string/join.c b/sys/base/string/join.c
deleted file mode 100644
index fb97b6c..0000000
--- a/sys/base/string/join.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "internal.h"
-
-string
-str·join(vlong len, byte** fields, const byte* sep)
-{
- string s = str·makecap("", 0, 10);
- int j = 0;
-
- for (j = 0; j < len; j++) {
- str·append(&s, fields[j]);
- if (j < len - 1)
- str·appendlen(&s, 1, sep);
- }
-
- return s;
-}
diff --git a/sys/base/string/len.c b/sys/base/string/len.c
deleted file mode 100644
index 5e42919..0000000
--- a/sys/base/string/len.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "internal.h"
-
-// len returns the length of the string.
-int
-str·len(const string s)
-{
- Hdr* h = (Hdr*)(s - sizeof(Hdr));
- return h->len;
-}
-
-// cap returns the capacity of the string buffer.
-int
-str·cap(const string s)
-{
- Hdr* h = (Hdr*)(s - sizeof(Hdr));
- return h->cap;
-}
diff --git a/sys/base/string/lower.c b/sys/base/string/lower.c
deleted file mode 100644
index c6935f8..0000000
--- a/sys/base/string/lower.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-// lower will force all runes in the string to be lowercase
-void
-str·lower(string s)
-{
- byte *b, *e;
- b = s;
- e = b + str·len(s);
- while (b++ != e)
- *b = tolower(*b);
-}
diff --git a/sys/base/string/make.c b/sys/base/string/make.c
deleted file mode 100644
index eb71543..0000000
--- a/sys/base/string/make.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "internal.h"
-
-// new returns a new dynamic string object, initialized from the given c string.
-// len defines the length of the c substring that we will copy into our buffer.
-// the backing buffer will have capacity cap.
-string
-str·makecap(const byte *s, vlong len, vlong cap)
-{
- struct Hdr* h;
-
- h = malloc(sizeof(*h) + cap + 1);
- if (s == nil) memset(h, 0, sizeof(*h));
-
- if (h == nil) return nil; // Allocation failed.
-
- h->len = (s == nil) ? 0 : len;
- h->cap = cap;
-
- if (cap < h->len) goto cleanup;
-
- if (s != nil && cap > 0) {
- memcpy(h->buf, s, h->len);
- memset(h->buf + h->len, '\0', h->cap - h->len + 1);
- }
-
- return h->buf;
-
-cleanup:
- free(h);
- panicf("Attempted to create a string with less capacity than length");
- return nil;
-}
-
-// new returns a new dynamic string object, initialized from the given c string.
-// the backing buffer capacity is equivalent to the string length.
-string
-str·makelen(const byte *s, vlong len)
-{
- vlong sl = (!s) ? 0 : strlen(s);
- if (sl < len) panicf("attempted to take a bigger substring than string length");
-
- vlong cap = (len == 0) ? 1 : len;
- return str·makecap(s, len, cap);
-}
-
-// new returns a new dynamic string object, initialized from the given c string.
-// the backing buffer capacity is equivalent to the string length.
-string
-str·make(const byte *s)
-{
- vlong len = (!s) ? 0 : strlen(s);
- return str·makelen(s, len);
-}
diff --git a/sys/base/string/makef.c b/sys/base/string/makef.c
deleted file mode 100644
index 8fb9c38..0000000
--- a/sys/base/string/makef.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include "internal.h"
-
-// Newf returns a new dynamic string object
-string
-str·makef(const byte *fmt, ...)
-{
- vlong n;
- string s;
- va_list args;
-
- va_start(args, fmt);
- n = vsnprintf(nil, 0, fmt, args);
- va_end(args);
-
- s = str·makecap(nil, 0, n);
-
- va_start(args, fmt);
- vsnprintf(s, n + 1, fmt, args);
- va_end(args);
-
- Hdr* h = (Hdr*)(s - sizeof(Hdr));
- h->len = n;
-
- return s;
-}
diff --git a/sys/base/string/read.c b/sys/base/string/read.c
deleted file mode 100644
index df2028f..0000000
--- a/sys/base/string/read.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-int
-str·read(string s, int size, int n, void *buf)
-{
- int len;
-
- len = MIN(n * size, str·len(s));
- memcpy(buf, s, len);
-
- return len;
-}
diff --git a/sys/base/string/replace.c b/sys/base/string/replace.c
deleted file mode 100644
index 127daed..0000000
--- a/sys/base/string/replace.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "internal.h"
-
-// replace will replace all occurences of the given bytes 'from' to bytes 'to'
-// edits are done in place and modify the string.
-// NOTE: as of now strings from and to must be the same size.
-void
-str·replace(string s, const byte* from, const byte* to)
-{
- vlong fromL = strlen(from);
- vlong toL = strlen(to);
- if (toL != fromL) { panicf("different sized replacement string not supported"); }
-
- vlong l = str·len(s);
- vlong i = l;
- vlong j = l;
-
- for (i = 0; i < l; i++) {
- for (j = 0; j < toL; j++) {
- if (s[i] == from[j]) {
- s[i] = to[j];
- break;
- }
- }
- }
-}
-
diff --git a/sys/base/string/rules.mk b/sys/base/string/rules.mk
deleted file mode 100644
index e517ca5..0000000
--- a/sys/base/string/rules.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-SRCS_$(d)+=\
- $(d)/string/append.c\
- $(d)/string/appendf.c\
- $(d)/string/clear.c\
- $(d)/string/copyn.c\
- $(d)/string/equals.c\
- $(d)/string/find.c\
- $(d)/string/fit.c\
- $(d)/string/free.c\
- $(d)/string/grow.c\
- $(d)/string/join.c\
- $(d)/string/len.c\
- $(d)/string/lower.c\
- $(d)/string/make.c\
- $(d)/string/makef.c\
- $(d)/string/read.c\
- $(d)/string/replace.c\
- $(d)/string/split.c\
- $(d)/string/upper.c\
diff --git a/sys/base/string/split.c b/sys/base/string/split.c
deleted file mode 100644
index 2aa68b4..0000000
--- a/sys/base/string/split.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "internal.h"
-
-// split will split the string by the given token.
-// returns a stretchy buffer of strings that result from the partition.
-// it is the caller's responsibility to clean the memory.
-string*
-str·split(string s, const byte* tok)
-{
- string* fields = nil;
- vlong start = 0;
-
- vlong sL = str·len(s);
- vlong tokL = strlen(tok);
- if (sL == 0 || tokL == 0) return nil;
-
- buffit(fields, 5);
-
- for (vlong i = 0; i < sL - tokL; i++) {
- if ((tokL == 1 && s[i] == tokL) || !memcmp(s + i, tok, tokL)) {
- bufpush(fields, str·makelen(s + start, i - start));
- if (fields[buflen(fields) - 1] == nil) goto cleanup;
-
- start = i + tokL;
- i += tokL - 1;
- }
- }
-
- bufpush(fields, str·makelen(s + start, sL - start));
-
- return fields;
-
-cleanup:
- for (vlong i = 0; i < buflen(fields); i++) {
- str·free(fields[i]);
- }
- buffree(fields);
- return nil;
-}
-
diff --git a/sys/base/string/upper.c b/sys/base/string/upper.c
deleted file mode 100644
index ab692c1..0000000
--- a/sys/base/string/upper.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "internal.h"
-
-// Upper will force all runes in the string to be uppercase.
-void
-str·upper(string s)
-{
- byte *b, *e;
- b = s;
- e = b + str·len(s);
- while (b++ != e)
- *b = toupper(*b);
-}
diff --git a/sys/base/test.c b/sys/base/test.c
deleted file mode 100644
index a29be1d..0000000
--- a/sys/base/test.c
+++ /dev/null
@@ -1,170 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <base/macro/map.h>
-
-#include <time.h>
-
-uintptr
-printtest(Coro *c, uintptr d)
-{
- printf("--> Recieved %lu\n", d);
- d = coro·yield(c, d+10);
- printf("--> Now %lu\n", d);
-
- return d;
-}
-
-uintptr
-sequence(Coro *c, uintptr start)
-{
- int d = start;
- for (;;) {
- coro·yield(c, d++);
- }
-
- return d;
-}
-
-struct PrimeMsg
-{
- Coro *seq;
- int p;
-};
-
-uintptr
-filter(Coro *c, uintptr data)
-{
- int x, p;
- Coro *seq;
- struct PrimeMsg *msg;
-
- // Need to copy relevant variables onto the local stack
- // Data is volatile.
- msg = (struct PrimeMsg*)data;
- seq = msg->seq;
- p = msg->p;
-
- for (;;) {
- x = coro·yield(seq, x);
- if (x % p != 0) {
- x = coro·yield(c, x);
- }
- }
-
- return 0;
-}
-
-error
-test·coro()
-{
- int i;
- Coro *c[4];
- uintptr d;
-
- printf("Starting singleton test\n");
-
- for (i = 0; i < arrlen(c); i++) {
- c[i] = coro·make(0, &printtest);
- }
-
- /* Singleton test */
- d = 0;
- for (i = 0; i < 10; i++) {
- d = coro·yield(c[0], d);
- }
-
- printf("Starting triplet test\n");
-
- /* Triplet test */
- for (i = 0; i < 10; i++) {
- d = coro·yield(c[1], d);
- d = coro·yield(c[2], d+100);
- d = coro·yield(c[3], d+200);
- }
-
- for (i = 0; i < arrlen(c); i++) {
- coro·free(c[i]);
- }
-
- /* Prime sieve */
- printf("Starting prime test\n");
- uintptr num;
- Coro *cur, *seq[50];
-
- num = 2;
- seq[0] = coro·make(4096, &sequence);
- cur = *seq;
-
- num = coro·yield(cur, num);
- for (i = 1; i < arrlen(seq); i++) {
- seq[i] = coro·make(4096, &filter);
- struct PrimeMsg msg = {
- .seq = cur,
- .p = num,
- };
- cur = seq[i];
- num = coro·yield(cur, (uintptr)&msg);
- printf("--> prime number %lu\n", num);
- }
- return 0;
-}
-
-int
-less(void* a, void* b)
-{
- int ai, bi;
- ai = *(int*)a;
- bi = *(int*)b;
-
- return ai - bi;
-}
-
-error
-test·sort()
-{
- clock_t t;
- int i, test[10000];
- for (i = 0; i < arrlen(test); i++) {
- test[i] = rand();
- }
-
- t = clock();
- sort·int(arrlen(test), test);
- t = clock() - t;
- printf("inlined code took %f ms to execute\n", 1000.*t/CLOCKS_PER_SEC);
-
- for (i = 0; i < arrlen(test); i++) {
- test[i] = rand();
- }
-
- t = clock();
- qsort(test, arrlen(test), sizeof(int), (int (*)(const void *, const void *))less);
- t = clock() - t;
- printf("std qsort code took %f ms to execute\n", 1000.*t/CLOCKS_PER_SEC);
-
- /*
- for (i = 1; i < arrlen(test); i++) {
- if (test[i] >= test[i-1]) {
- printf("%d is less that %d\n", test[i], test[i-1]);
- } else {
- printf("ERROR: %d is NOT less that %d\n", test[i], test[i-1]);
- }
- }
- */
-
- return 0;
-}
-
-error
-main()
-{
- error err;
-#if 0
- if (err = test·coro(), err) {
- errorf("test fail: coroutine");
- }
-#endif
- if (err = test·sort(), err) {
- errorf("test fail: coroutine");
- }
-}
diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c
deleted file mode 100644
index 4330bcc..0000000
--- a/sys/cmd/cc/ast.c
+++ /dev/null
@@ -1,2139 +0,0 @@
-#include "cc.h"
-
-// -----------------------------------------------------------------------
-// helper macros
-
-#define alloc(ptr) (ptr) = mem·arenaalloc(C.heap, 1, sizeof *(ptr))
-#define copyarray(dst, arr, n) (dst) = mem·arenaalloc(C.heap, (n), sizeof *(arr)), memcpy((dst), (arr), n * sizeof *(arr))
-#define movearray(dst, arr, n) copyarray(dst,arr,n), free(arr)
-
-#define attop(prs) ((uintptr)prs->sp == (uintptr)prs->spstk)
-#define peek(p, i) (p->tok[i])
-#define iskw(t, k) (((t).kind == Akeywd) && (t).val.i == (k))
-#define advance(p, l) (p->tok[0] = p->tok[1], p->tok[1] = lex(l), p->tok[0])
-
-#define Bit(i) (1 << (i))
-
-// -----------------------------------------------------------------------
-// helper functions
-
-static
-string
-nameof(Name *n)
-{
- switch (n->kind) {
- /* 0 corresponds to no state - i.e. an abstract name */
- case Nnil:
- return nil;
- case Nident:
- return n->ident;
- case Nparen:
- return nameof(n->paren->name);
- case Nindex:
- case Ncall:
- return nameof(n->sfx.name);
- }
- panicf("unreachable");
- return nil;
-}
-
-static
-void
-openscope(Parser *p)
-{
- if (++p->sp >= arrend(p->spstk))
- panicf("scope stack overflow");
-}
-
-/*
- * TODO: save the symbol table with the ast node
- * write a "copy(move)scope"
- */
-
-static
-void
-closescope(Parser *p)
-{
- if (p->sp <= p->spstk)
- panicf("scope stack underflow");
-
- forgetall(&p->sp->objs);
- forgetall(&p->sp->tags);
- p->sp--;
-}
-
-/* temporary stack helpers */
-static
-Name*
-getname(Parser *p)
-{
- if (p->nm >= arrend(p->nmstk))
- panicf("name stack overflow");
- return p->nm++;
-}
-
-static void putdtor(Parser *p, Dtor *dt);
-
-static
-void
-putname(Parser *p, Name *n)
-{
- if (p->nm <= p->nmstk)
- panicf("name stack underflow");
-
- switch (n->kind) {
- case Nnil:
- case Nident:
- break;
- case Nparen:
- putdtor(p, n->paren);
- break;
- case Nindex:
- case Ncall:
- putname(p, n->sfx.name);
- break;
- default:
- panicf("unrecognized name kind");
- }
- *p->nm-- = (Name){0};
-}
-
-static
-Ptr*
-getptr(Parser *p)
-{
- if (p->pt >= arrend(p->ptstk))
- panicf("pointer stack overflow");
-
- return p->pt++;
-}
-
-static
-void
-putptr(Parser *p, Ptr *ptr)
-{
- if (p->pt <= p->ptstk)
- panicf("pointer stack underflow");
-
- while ((ptr = ptr->link))
- putptr(p, ptr);
-
- *p->pt-- = (Ptr){0};
-}
-
-
-static
-Dtor*
-getdtor(Parser *p)
-{
- if (p->dt >= arrend(p->dtstk))
- panicf("dtor stack overflow");
-
- p->dt->name = getname(p);
- return p->dt++;
-}
-
-static
-void
-putdtor(Parser *p, Dtor *dt)
-{
- if (p->dt <= p->dtstk)
- panicf("dtor stack underflow");
-
- /* release the pointer overflow if we had to use it */
- if (p->dt->ptr.link)
- putptr(p, p->dt->ptr.link);
-
- /* the dtor could encompass multiple names hierarchically */
- putname(p, dt->name);
- *p->dt-- = (Dtor){0};
-}
-
-/* TODO: This will fail for forward declarations */
-static
-void
-declareobj(Parser *p, Decl *d)
-{
- Sym *sym;
- string ident;
- uint32 kind;
- struct Decls *link;
-
- switch (d->kind) {
- case Dfunc:
- case Dvar:
- kind = Svar;
- goto one;
- case Dtype:
- kind = Stype;
- one:
- ident = d->name;
- break;
-
- case Dvars:
- kind = Svar;
- goto many;
- case Dtypes:
- kind = Stype;
- many:
- while (link = &d->list, link != nil) {
- ident = link->name;
- sym = lookup(&p->sp->objs, ident);
- if (sym) {
- errorat(peek(p, 0).pos, "redeclaration of name '%s' in object space", ident);
- return;
- }
- sym = define(&p->sp->objs, ident, kind);
- if (kind == Svar)
- sym->obj = d;
- else
- sym->type = d->type;
- }
- break;
-
- default:
- panicf("unrecognized node kind %d. expected declaration", d->kind);
- }
- sym = lookup(&p->sp->objs, ident);
- if (sym) {
- errorat(peek(p, 0).pos, "redeclaration of name '%s' in object space", ident);
- return;
- }
- sym = define(&p->sp->objs, ident, kind);
- if (kind == Svar)
- sym->obj = d;
- else
- sym->type = d->type;
-}
-
-/* enters the object identifier space */
-static
-void
-declareenum(Parser *p, int n, string *elts, Expr *vals)
-{
- int i;
- Sym *s;
-
- for (i = 0; i < n; i++) {
- s = lookup(&p->sp->objs, elts[i]);
- if (s) {
- errorat(peek(p, 0).pos, "redeclaration of name %s in object space", elts[i]);
- continue;
- }
- s = define(&p->sp->objs, elts[i], Senum);
- s->val = vals + i;
- }
-}
-
-static
-void
-declaretag(Parser *p, uint32 t, string name)
-{
- Sym *sym;
- sym = lookup(&p->sp->tags, name);
- if (sym) {
- errorat(peek(p, 0).pos, "redeclaration of name '%s' in tag space", name);
- return;
- }
-
- sym = define(&p->sp->tags, name, Stype);
- sym->type = t;
-}
-
-static
-Sym *
-lookupobj(Parser *p, string ident)
-{
- Sym *sym;
- Scope *it;
-
- it = p->sp;
- do {
- sym = lookup(&it->objs, ident);
- } while (sym == nil && --it >= p->spstk);
-
- return sym;
-}
-
-static
-Sym *
-lookuptag(Parser *p, string ident)
-{
- Sym *sym;
- Scope *it;
-
- it = p->sp;
- do {
- sym = lookup(&it->tags, ident);
- } while (sym == nil && --it >= p->spstk);
-
- return sym;
-}
-
-static
-int
-nomatch(Token t, vlong kind)
-{
- if (t.kind == kind)
- return 0;
-
- if (t.kind == Akeywd)
- errorat(t.pos, "expected token '%s', instead found keyword '%s'", tokens[kind], keywords[t.val.i]);
- else
- errorat(t.pos, "expected token '%s', instead found '%s'", tokens[kind], tokens[t.kind]);
- return 1;
-}
-
-// -----------------------------------------------------------------------
-// needed forward declarations
-
-static error spec(Parser *, Lexer *, uint64 *);
-static uint32 basetype(Parser *, Lexer *, uint64 *s);
-static string namedecl(Parser *, Lexer *, uint32 *, int);
-static uint32 typename(Parser *, Lexer *, uint32 *);
-
-static error dtor(Parser *p, Lexer *lx, Dtor *d, int ab);
-static uint32 typeofdtor(Dtor *, uint32);
-
-
-static Decl *decl(Parser *, Lexer *);
-
-static Expr *ternary(Parser *, Lexer *);
-static Expr *expr(Parser *, Lexer *);
-
-static error blkstmt(Parser *, Lexer *, Stmt **);
-
-
-// -----------------------------------------------------------------------
-// expressions
-
-#define MAKEX(x, state) alloc((x)), (x)->kind = X##state
-
-static
-Expr*
-primary(Parser *p, Lexer *lx)
-{
- int k;
- Expr *x;
- Token t;
- Pos b;
-
- t = peek(p, 0);
- b = t.pos;
- switch (k = (t.kind & Vmask)) {
- case Aident:
- MAKEX(x, ident);
- x->pos.beg = b;
- x->pos.end = lx->pos;
- x->name = t.val.s;
- break;
-
- case Alit:
- MAKEX(x, lit);
- x->pos.beg = b;
- x->pos.end = lx->pos;
- x->val.kind = t.kind & ~Vmask;
- x->val.v = t.val;
- break;
-
- case Alparen:
- advance(p, lx);
- x = expr(p, lx);
- t = peek(p, 0);
- if (nomatch(t, Arparen)) {
- errorat(lx->pos, "unterminated paren expression");
- goto Bad;
- }
- break;
-
- default:
- panicf("unreachable");
- }
-
- advance(p, lx);
- return x;
-Bad:
- errorat(lx->pos, "unable to parse operand expression");
- return nil;
-}
-
-static
-int
-istypename(Parser *p, Token t)
-{
- Sym *sym;
-
- if (t.kind == Akeywd && (Kconst <= t.val.i && t.val.i <= Kenum))
- return 1;
- if (t.kind == Aident) {
- sym = lookupobj(p, t.val.s);
- return (sym != nil) && sym->kind == Stype;
- }
-
- return 0;
-}
-
-static Expr* initx(Parser *p, Lexer *lx);
-
-static
-Expr*
-initlist(Parser *p, Lexer *lx)
-{
- Token t;
- int c, n;
- Expr *x, **a;
- struct Key *k;
-
- MAKEX(x, initlist);
- x->pos.beg = lx->pos;
- x->init.n = 0;
- if (t.kind == Arbrace) {
- x->init.k = nil;
- x->init.v = nil;
- return x;
- }
-
- c = 0;
- n = 0;
- a = nil;
- k = nil;
-Key0:
- if (n >= c) {
- c += 20;
- k = realloc(k, c * sizeof(*k));
- a = realloc(a, c * sizeof(*a));
- }
-Key1:
- switch (t.kind) {
- case Adot:
- t = advance(p, lx);
- if (t.kind != Aident) {
- errorat(t.pos, "dot designator must be followed by identifier");
- goto Bad;
- }
- k[n++] = (struct Key) {
- .kind = (uint32)x->init.n,
- .s = t.val.s,
- };
- t = advance(p, lx);
- goto Key0;
-
- case Albrakt:
- t = advance(p, lx);
- k[n++] = (struct Key) {
- .kind = (uint32)x->init.n | (1ULL << 32),
- .x = expr(p, lx),
- };
- t = peek(p, 0);
- goto Key0;
-
- case Aeq:
- t = advance(p, lx);
- /* fallthrough */
- default:
- a[x->init.n++] = initx(p, lx);
-
- t = peek(p, 0);
- switch (t.kind) {
- case Arbrace:
- break;
- case Acomma:
- advance(p, lx);
- /* fallthrough */
- default:
- goto Key0;
- }
- break;
-
- case Acomma:
- t = advance(p, lx);
- break;
- }
- movearray(x->init.k, k, n);
- movearray(x->init.v, a, x->init.n);
- return x;
-Bad:
- errorat(t.pos, "could not parse initializer list");
- return nil;
-}
-
-static
-Expr*
-initx(Parser *p, Lexer *lx)
-{
- Expr *x;
- Token t;
-
- t = peek(p, 0);
- if (t.kind != Albrace)
- return ternary(p, lx);
-
- advance(p, lx);
- x = initlist(p, lx);
- t = peek(p, 0);
- if (nomatch(t, Arbrace)) {
- errorat(t.pos, "unmatched brace in initializer list, found %s instead", tokens[t.kind]);
- advance(p, lx);
- }
-
- return x;
-}
-
-static
-Expr*
-postfix(Parser *p, Lexer *lx)
-{
- Pos b;
- Token t;
- int c, n;
- uint32 type, qual;
- Expr *x, *y, **a;
-
- t = peek(p, 0);
- if (t.kind == Alparen)
- if (istypename(p, peek(p, 1))) {
- t = advance(p, lx);
- type = typename(p, lx, &qual);
- t = peek(p, 0);
- if (nomatch(t, Arparen)) {
- errorat(lx->pos, "unmatched paren: found %s instead", tokens[t.kind]);
- goto Bad;
- }
- t = advance(p, lx);
- if (nomatch(t, Albrace)) {
- errorat(lx->pos, "bad initializer list: found %s", tokens[t.kind]);
- goto Bad;
- }
-
- x = initlist(p, lx);
-
- t = peek(p, 0);
- if (nomatch(t, Arbrace)) {
- errorat(lx->pos, "unmatched brace: found %s instead", tokens[t.kind]);
- goto Bad;
- }
-
- x->type = type;
- x->qual = qual;
- return x;
- }
-
- x = primary(p, lx);
- t = peek(p, 0);
- for (;;) {
- b = x->pos.beg;
- switch (t.kind) {
- case Ainc:
- MAKEX(y, postinc);
- goto Postfix;
- case Adec:
- MAKEX(y, postdec);
- Postfix:
- y->pos.beg = b;
- y->pos.end = lx->pos;
- y->unary.post = x;
- x = y, y = nil;
- break;
-
- case Adot:
- MAKEX(y, self);
- goto Select;
- case Aarrow:
- MAKEX(y, selp);
- Select:
- t = advance(p, lx);
- if (t.kind != Aident) {
- errorat(t.pos, "invalid operand of selector expression");
- goto Bad;
- }
- y->pos.beg = b;
- y->pos.end = lx->pos;
-
- y->idx.f = t.val.s;
- y->idx.x = x;
- x = y, y = nil;
- break;
-
- case Albrakt:
- t = advance(p, lx);
- if (t.kind == Arbrakt) {
- errorat(t.pos, "empty index expression");
- goto Bad;
- }
- MAKEX(y, index);
- y->idx.x = x;
- y->idx.i = expr(p, lx);
-
- t = peek(p, 0);
- if (t.kind != Albrakt) {
- errorat(t.pos, "malformed index expression");
- goto Bad;
- }
-
- x = y, y = nil;
- break;
-
- case Alparen:
- t = advance(p, lx);
- MAKEX(y, call);
- y->call.fn = x;
- y->pos.beg = b;
- y->call.n = 0;
- if (t.kind == Arparen) {
- y->call.arg = nil;
- goto Endfunc;
- }
- c = 0;
- a = nil;
- Arg:
- if (y->call.n >= c) {
- c += 20;
- a = realloc(a, c * sizeof(*a));
- }
- a[y->call.n++] = expr(p, lx);
- t = peek(p, 0);
- if (t.kind == Acomma) {
- advance(p, lx);
- goto Arg;
- }
- if (t.kind != Arparen) {
- errorat(t.pos, "invalid token '%s' found in call argument");
- goto Bad;
- }
- movearray(y->call.arg, a, y->call.n);
- Endfunc:
- y->pos.end = lx->pos;
- x = y, y = nil;
- break;
-
- default:
- return x;
- }
- t = advance(p, lx);
- }
- return x;
-Bad:
- errorat(lx->pos, "failed to parse primary expression");
- return nil;
-}
-
-static
-uint32
-typename(Parser *p, Lexer *lx, uint32 *spec)
-{
- uint32 base;
- uint64 s;
-
- base = basetype(p, lx, &s);
- if (!base) {
- errorat(lx->pos, "failed to parse type name specifiers");
- return 0;
- }
- *spec = (uint32)s;
- namedecl(p, lx, &base, 1);
-
- return base;
-}
-
-static Expr* cast(Parser *p, Lexer *lx);
-
-static
-Expr*
-unary(Parser *p, Lexer *lx)
-{
- Expr *x;
- Token t;
-
- t = peek(p, 0);
- switch (t.kind) {
- case Ainc: MAKEX(x, preinc); goto Prefix;
- case Adec: MAKEX(x, predec); /* fallthrough */
- Prefix:
- advance(p, lx);
- x->pos.beg = t.pos;
- x->unary.pre = unary(p, lx);
- x->pos.end = x->unary.pre->pos.end;
- return x;
-
- case Aneg: MAKEX(x, neg); goto Unary;
- case Aand: MAKEX(x, ref); goto Unary;
- case Anot: MAKEX(x, not); goto Unary;
- case Astar: MAKEX(x, star); goto Unary;
- case Aadd: MAKEX(x, plus); goto Unary;
- case Asub: MAKEX(x, minus); /* fallthrough */
- Unary:
- advance(p, lx);
- x->pos.beg = t.pos;
- x->unary.pre = cast(p, lx);
- x->pos.end = x->unary.pre->pos.end;
- return x;
-
- case Akeywd:
- switch (t.val.i) {
- case Ksizeof:
- MAKEX(x, sizeof);
- goto Key;
- case Kalignof:
- MAKEX(x, alignof);
- /* fallthrough */
- Key:
- t = advance(p, lx);
- if (t.kind == Alparen)
- if (istypename(p, peek(p, 1))) {
- t = advance(p, lx);
- x->info.type = 0;
- x->info.of.type = typename(p, lx, &x->info.of.qual);
-
- t = peek(p, 0);
- if (nomatch(t, Arparen)) {
- errorat(t.pos, "missing paren for size/alignof statement");
- goto Bad;
- }
- advance(p, lx);
- return x;
- }
-
- x->info.type = 1;
- x->info.x = unary(p, lx);
- return x;
-
- default:
- ;
- }
- /* fallthrough */
- default:
- return postfix(p, lx);
- }
-Bad:
- return nil;
-}
-
-static
-Expr*
-cast(Parser *p, Lexer *lx)
-{
- Expr *x;
- Token t;
-
- t = peek(p, 0);
- if (t.kind == Alparen && istypename(p, peek(p,1))) {
- t = advance(p, lx);
- MAKEX(x, cast);
-
- x->pos.beg = t.pos;
- x->cast.to.type = typename(p, lx, &x->cast.to.qual);
- if (!x->cast.to.type) {
- errorat(lx->pos, "invalid type operand of cast");
- goto Bad;
- }
-
- t = peek(p, 0);
- if (nomatch(t, Arparen)) {
- errorat(lx->pos, "missing closing paren after cast expression");
- goto Bad;
- }
- advance(p, lx);
-
- x->cast.x = cast(p, lx);
- x->pos.beg = lx->pos;
- return x;
- }
- return unary(p, lx);
-
-Bad:
- errorat(lx->pos, "failed to parse cast expression");
- return nil;
-}
-
-/* static data for binary operators */
-#define OPERATORS \
- OPERATOR(Astar, 10, Xmul) \
- OPERATOR(Adiv, 10, Xdiv) \
- OPERATOR(Amod, 10, Xmod) \
- OPERATOR(Aadd, 9, Xadd) \
- OPERATOR(Asub, 9, Xsub) \
- OPERATOR(Alsft, 8, Xlsft) \
- OPERATOR(Arsft, 8, Xrsft) \
- OPERATOR(Agteq, 7, Xgteq) \
- OPERATOR(Alteq, 7, Xlteq) \
- OPERATOR(Alt, 7, Xlt) \
- OPERATOR(Agt, 7, Xgt) \
- OPERATOR(Aeq, 6, Xeql) \
- OPERATOR(Aneq, 6, Xneq) \
- OPERATOR(Aand, 5, Xand) \
- OPERATOR(Axor, 4, Xxor) \
- OPERATOR(Aor, 3, Xor) \
- OPERATOR(Aandand, 2, Xandand) \
- OPERATOR(Aoror, 1, Xoror)
-
-static int prectab[NUM_TOKENS] =
-{
-#define OPERATOR(a, b, c) [a] = b,
- OPERATORS
-#undef OPERATOR
-};
-
-static int optab[NUM_TOKENS] =
-{
-#define OPERATOR(a, b, c) [a] = c,
- OPERATORS
-#undef OPERATOR
-};
-#undef OPERATORS
-
-static
-Expr*
-binary(Parser *p, Lexer *lx, int prec)
-{
- Token t;
- int k, np;
- Expr *l, *x;
-
- l = cast(p, lx);
- for (;;) {
- t = peek(p, 0);
- k = t.kind;
- np = prectab[k];
- if (np < prec)
- return l;
-
- alloc(x);
- t = advance(p, lx);
-
- x->pos.beg = l->pos.beg;
- x->kind = optab[k];
- x->binary.l = l;
- x->binary.r = binary(p, lx, np + 1);
- x->pos.end = x->binary.r->pos.end;
-
- l = x;
- }
- return l;
-Bad:
- errorat(t.pos, "failed to parse expression");
- return nil;
-}
-
-static
-Expr*
-ternary(Parser *p, Lexer *lx)
-{
- Pos b;
- Token t;
- Expr *x, *y;
-
- x = binary(p, lx, 1);
- t = peek(p, 0);
- b = t.pos;
-
- switch (t.kind) {
- case Aqmark:
- t = advance(p, lx);
- y = x;
- MAKEX(x, ternary);
- x->pos.beg = b;
- x->kind = Xternary;
- x->cond.c = y;
- x->cond.t = expr(p, lx);
-
- t = peek(p, 0);
- if (nomatch(t, Acolon)) {
- errorat(t.pos, "ternary expression missing ':'");
- goto Bad;
- }
- t = advance(p, lx);
- x->cond.e = expr(p, lx);
- x->pos.end = lx->pos;
- break;
-
- case Aasn: MAKEX(y, asn); goto Assign;
- case Aorasn: MAKEX(y, orasn); goto Assign;
- case Axorasn: MAKEX(y, xorasn); goto Assign;
- case Aandasn: MAKEX(y, andasn); goto Assign;
- case Asubasn: MAKEX(y, subasn); goto Assign;
- case Amulasn: MAKEX(y, mulasn); goto Assign;
- case Adivasn: MAKEX(y, divasn); goto Assign;
- case Amodasn: MAKEX(y, modasn); goto Assign;
- case Alsftasn: MAKEX(y, lsftasn); goto Assign;
- case Arsftasn: MAKEX(y, rsftasn); goto Assign;
- Assign:
- advance(p, lx);
-
- y->asn.l = x;
- y->asn.r = ternary(p, lx);
- x = y;
- x->pos.beg = b;
- x->pos.end = lx->pos;
- break;
- default:
- ;
- }
-
- return x;
-Bad:
- errorat(lx->pos, "failing expression parse");
- return nil;
-}
-
-static
-Expr*
-expr(Parser *p, Lexer *lx)
-{
- Pos b;
- Token t;
- Expr *x, *y;
-
- x = ternary(p, lx);
- while (t = peek(p, 0), t.kind == Acomma) {
- advance(p, lx);
- y = x;
- MAKEX(x, comma);
- x->pos.beg = y->pos.beg;
- x->comma.x[0] = y;
- x->comma.x[1] = ternary(p, lx);
- x->pos.end = lx->pos;
- y = nil;
- }
-
- return x;
-}
-
-// -----------------------------------------------------------------------
-// statements
-
-static
-struct Node*
-stmt(Parser *p, Lexer *lx)
-{
- int k;
- Stmt *s;
- Sym *sym;
- Token t;
-
- t = peek(p, 0);
- k = t.kind;
-
- /* intercept decl before allocating a statement */
- if (k == Aident) {
- if (peek(p, 1).kind == Acolon)
- goto Tlabel;
- sym = lookupobj(p, t.val.s);
- if (!sym) {
- errorat(lx->pos, "unrecognized type identifier '%s'", t.val.s);
- goto Bad;
- }
-
- if (sym->kind == Stype)
- goto Tdecl;
- if (sym->kind == Svar) {
- alloc(s);
- s->pos.beg = lx->pos;
- goto Texpr;
- }
-
- errorat(lx->pos, "bad symbol type used as type identifier");
- goto Bad;
- }
-
- if (k == Akeywd) {
- if ((Kauto <= t.val.i && t.val.i <= Ktypedef) || (Kconst <= t.val.i && t.val.i <= Kenum)) {
- Tdecl:
- return (Node *)decl(p, lx);
- }
- }
-
- alloc(s);
- s->pos.beg = lx->pos;
-
- switch (k) {
- case Akeywd:
- switch (k = t.val.i) {
- case Kif:
- t = advance(p, lx);
- s->kind = Sif;
-
- if (nomatch(t, Alparen)) {
- errorat(lx->pos, "missing opening paren before if conditional");
- goto Bad;
- }
- s->br.cond = expr(p, lx);
- if (nomatch(t, Arparen)) {
- errorat(lx->pos, "missing closing paren after if conditional");
- goto Bad;
- }
- s->br.body = stmt(p, lx);
-
- t = peek(p, 0);
- if (iskw(t, Kelse))
- s->br.orelse = stmt(p, lx);
- else
- s->br.orelse = nil;
-
- break;
-
- case Kswitch:
- t = advance(p, lx);
- s->kind = Sswitch;
-
- if (nomatch(t, Alparen)) {
- errorat(lx->pos, "missing opening paren before switch conditional");
- goto Bad;
- }
- s->br.cond = expr(p, lx);
- if (nomatch(t, Arparen)) {
- errorat(lx->pos, "missing closing paren after switch conditional");
- goto Bad;
- }
- s->br.body = stmt(p, lx);
- s->br.orelse = nil;
-
- break;
-
- case Kfor:
- t = advance(p, lx);
- s->kind = Sfor;
-
- if (nomatch(t, Alparen)) {
- errorat(lx->pos, "missing opening paren before for loop preamble");
- goto Bad;
- }
-
- if (t.kind == Asemi)
- s->loop.init = nil;
- else {
- // TODO: test for declaration
- s->loop.init = (Node *)expr(p, lx);
- }
-
- if (nomatch(t, Asemi)) {
- errorat(lx->pos, "missing semicolon");
- goto Bad;
- }
-
- if (t.kind == Asemi)
- s->loop.cond = nil;
- else
- s->loop.cond = expr(p, lx);
-
- if (nomatch(t, Asemi)) {
- errorat(lx->pos, "missing semicolon");
- goto Bad;
- }
-
- if (t.kind == Asemi)
- s->loop.step = nil;
- else
- s->loop.step = expr(p, lx);
-
- if (nomatch(t, Alparen)) {
- errorat(lx->pos, "missing closing paren after for loop preamble");
- goto Bad;
- }
- s->loop.body = stmt(p, lx);
- break;
-
- case Kwhile:
- t = advance(p, lx);
- s->kind = Swhile;
- if (nomatch(t, Alparen)) {
- errorat(lx->pos, "missing opening paren before while loop conditional");
- goto Bad;
- }
- s->loop.cond = expr(p, lx);
- if (nomatch(t, Arparen)) {
- errorat(t.pos, "missing closing paren after while loop conditional");
- goto Bad;
- }
-
- s->loop.init = nil;
- s->loop.step = nil;
- s->loop.body = stmt(p, lx);
- break;
-
- case Kdo:
- t = advance(p, lx);
- s->kind = Sdo;
- s->loop.body = stmt(p, lx);
-
- if (!iskw(t, Kwhile)) {
- errorat(t.pos, "missing while statement conditional after do body");
- goto Bad;
- }
- t = advance(p, lx);
- if (nomatch(t, Alparen)) {
- errorat(t.pos, "missing open paren after while conditional");
- goto Bad;
- }
-
- s->loop.init = nil;
- s->loop.step = nil;
- s->loop.cond = expr(p, lx);
- break;
-
- case Kgoto:
- t = advance(p, lx);
- s->kind = Sgoto;
- if (t.kind != Aident) {
- errorat(t.pos, "invalid argument to goto");
- goto Bad;
- }
- s->jmp.lbl = t.val.s;
- t = advance(p, lx);
- if (nomatch(t, Asemi)) {
- errorat(t.pos, "missing semicolon after goto");
- goto Bad;
- }
- advance(p, lx);
- break;
-
- case Kcontinue:
- t = advance(p, lx);
- s->kind = Scontin;
- s->jmp.lbl = nil;
- s->jmp.x = nil;
- if (nomatch(t, Asemi)) {
- errorat(t.pos, "missing semicolon after continue");
- goto Bad;
- }
- advance(p, lx);
- break;
-
- case Kbreak:
- t = advance(p, lx);
- s->kind = Sbreak;
- s->jmp.lbl = nil;
- s->jmp.x = nil;
- if (nomatch(t, Asemi)) {
- errorat(t.pos, "missing semicolon after break");
- goto Bad;
- }
- advance(p, lx);
- break;
-
- case Kreturn:
- t = advance(p, lx);
- s->kind = Sreturn;
-
- s->jmp.lbl = nil;
- s->jmp.x = (t.kind == Asemi) ? nil : expr(p, lx);
-
- t = peek(p, 0);
- if (nomatch(t, Asemi)) {
- errorat(t.pos, "missing semicolon after return statement");
- goto Bad;
- }
- advance(p, lx);
- break;
-
- case Kcase:
- t = advance(p, lx);
- s->kind = Scase;
- s->lbl.x = expr(p, lx);
- if (nomatch(t, Acolon)) {
- errorat(t.pos, "missing colon after default label");
- goto Bad;
- }
- t = advance(p, lx);
- s->lbl.stmt = stmt(p, lx);
- break;
-
- case Kdefault:
- t = advance(p, lx);
- s->kind = Scase;
- s->lbl.x = nil;
- if (nomatch(t, Acolon)) {
- errorat(t.pos, "missing colon after default label");
- goto Bad;
- }
- t = advance(p, lx);
- s->lbl.stmt = stmt(p, lx);
- break;
-
- default:
- panicf("unexpected statement keyword %s", keywords[k]);
- }
- break;
- case Albrace:
- s->kind = Sblock;
- openscope(p);
- if (blkstmt(p, lx, &s)) {
- errorat(lx->pos, "failed to parse block statement");
- goto Bad;
- }
- closescope(p);
- break;
-
- case Asemi:
- t = advance(p, lx);
- s->kind = Sempty;
- break;
-
- case Aident:
- Tlabel:
- t = advance(p, lx);
- s->kind = Slabel;
- if (nomatch(t, Acolon)) {
- errorat(t.pos, "missing colon after labelled block");
- goto Bad;
- }
- t = advance(p, lx);
- s->lbl.stmt = stmt(p, lx);
- break;
-
- default:
- Texpr:
- s->kind = Sexpr;
- s->x = expr(p, lx);
-
- t = peek(p, 0);
- if (nomatch(t, Asemi)) {
- errorat(t.pos, "missing semicolon after statement expression");
- goto Bad;
- }
- advance(p, lx);
- }
-
- s->pos.end = lx->pos;
- return (Node *)s;
-Bad:
- errorat(lx->pos, "failed to parse statement");
- return nil;
-}
-
-static
-error
-blkstmt(Parser *p, Lexer *lx, Stmt **s)
-{
- Token t;
- int len;
- int cap;
- Node **ns;
-
- alloc(*s);
- (*s)->kind = Sblock;
- (*s)->pos.beg = lx->pos;
-
- t = peek(p, 0);
- if (nomatch(t, Albrace))
- goto Bad;
- t = advance(p, lx);
-
- len = 0, cap = 20;
- ns = malloc(cap*sizeof(*ns));
- while (t.kind != Arbrace) {
- if (cap == len) {
- cap += 20;
- ns = realloc(ns, cap*sizeof(*ns));
- }
- ns[len++] = stmt(p, lx);
- t = peek(p, 0);
- }
- advance(p, lx);
-
- (*s)->pos.end = lx->pos;
- (*s)->blk.n = len;
- movearray((*s)->blk.item, ns, len);
- return 0;
-Bad:
- errorat(lx->pos, "failed to parse block statement");
- free(ns);
- return 1;
-}
-
-// -----------------------------------------------------------------------
-// types
-
-uint32
-ptrtype(uint32 base, uint32 qual)
-{
- uint32 i;
- Type *t;
-
- i = type();
- t = C.type.info + i;
- t->kind = Tptr;
- t->ptr.base = base;
- t->ptr.qual = qual;
- t->size = pointer.size;
- t->align = pointer.align;
- t->sign = pointer.sign;
-
- return i;
-}
-
-uint32
-arraytype(uint32 base, uint32 qual, Expr *ix)
-{
- int i, n;
- Type *t;
-
- /* TODO: evaluate the length */
- n = 10;
- i = type();
- t = C.type.info + i;
- t->kind = Tarray;
- t->ptr.base = base;
- t->size = n * C.type.info[base].size;
- t->align = C.type.info[base].align;
- t->sign = 0;
-
- return i;
-}
-
-uint32
-functype(uint32 ret, int n, Field *args, int dots)
-{
- uint32 i;
- Type *t;
-
- i = type();
- t = C.type.info + i;
- t->kind = Tfunc;
- t->size = pointer.size;
- t->align = pointer.align;
- t->sign = pointer.sign;
-
- t->func.ret = ret;
- t->func.n = n;
- t->func.arg = args;
- t->func.dots = dots;
-
- return i;
-}
-
-#define ALIGN_DOWN(n, a) ((n) & ~((a)-1))
-#define ALIGN_UP(n, a) ALIGN_DOWN((n) + (a)-1, (a))
-uint32
-structtype(int n, Field *field, Expr *bits)
-{
- uint32 i;
- Type *t;
- Field *f, *e;
-
- i = type();
- t = C.type.info + i;
- t->kind = Tstruct;
- t->size = 0;
- t->align = 0;
- for (f = field, e = field+n; f != e; ++f) {
- t->size += C.type.info[f->type].size + ALIGN_UP(t->size, C.type.info[f->type].align);
- t->align = MAX(t->align, C.type.info[f->type].align);
- }
- t->aggr.len = n;
- t->aggr.f = field;
- t->aggr.x = bits;
-
- return i;
-}
-
-uint32
-uniontype(int n, Field *field, Expr *bits)
-{
- uint32 i;
- Type *t;
- Field *f, *e;
-
- i = type();
- t = C.type.info + i;
- t->kind = Tstruct;
- t->size = 0;
- t->align = 0;
- for (f = field, e = field+n; f != e; ++f) {
- t->size = MAX(t->size, C.type.info[f->type].size);
- t->align = MAX(t->align, C.type.info[f->type].align);
- }
- t->aggr.len = n;
- t->aggr.f = field;
- t->aggr.x = bits;
-
- return i;
-}
-
-uint32
-enumtype(int n, string *elts, Expr *vals)
-{
- uint32 i;
- Type *t;
- Field *f, *e;
-
- i = type();
- t = C.type.info + i;
- t->kind = Tenum;
- /* TODO: dont hardcode int32 */
- t->size = 4;
- t->align = 4;
- t->enm.len = n;
- t->enm.elt = elts;
- t->enm.val = vals;
-
- return i;
-}
-#undef ALIGN_UP
-#undef ALIGN_DOWN
-
-/* unpacking C declarations into sensible types */
-static
-uint32
-typeofname(Name *name, uint32 base)
-{
- switch (name->kind) {
- /* Nnil corresponds to an abstract declarator (i.e. no identifier) */
- case Nnil:
- case Nident:
- return base;
- case Nparen:
- return typeofdtor(name->paren, base);
- case Nindex:
- return typeofname(name->sfx.name, arraytype(base, name->sfx.idx.q, name->sfx.idx.x));
- case Ncall:
- return typeofname(name->sfx.name, functype(base, name->sfx.call.n, name->sfx.call.arg, name->sfx.call.dots));
- default:
- panicf("unreachable");
- }
- return 0;
-}
-
-static
-uint32
-typeofdtor(Dtor *decl, uint32 base)
-{
- int n;
- Ptr *p;
- uint64 b, tmp;
-
- n = 0;
- p = &decl->ptr;
- b = p->kind;
- while (b & 1) {
- base = ptrtype(base, b >> 1);
- if (++n >= 8) {
- p = p->link;
- b = p->kind;
- } else {
- b >>= 6;
- }
- }
-
- return typeofname(decl->name, base);
-}
-
-static
-uint32
-basetype(Parser *p, Lexer *lx, uint64 *s)
-{
- int n;
- uint64 m;
-
- if (spec(p, lx, s)) {
- errorat(lx->pos, "failed to parse type specifier");
- return 0;
- }
-
- m = (((*s<<32)>>32) & ~(MaskQul|MaskMem|MaskFcn));
- for (n = 0; n < arrlen(validtypespec); n++) {
- if (validtypespec[n] == m) {
- if (indextypespec[n] < 0) {
- m = *s >> 32;
- if (!m) {
- errorat(lx->pos, "not a valid type identifier");
- return 0;
- }
- return m;
- }
- return indextypespec[n];
- }
- }
-
- errorat(lx->pos, "invalid type specifier");
- return 0;
-}
-
-static
-string
-namedecl(Parser *p, Lexer *lx, uint32 *base, int noname)
-{
- Dtor *dt;
- string name;
- Type *t;
-
- dt = getdtor(p);
- name = nil;
- if (dtor(p, lx, dt, noname)) {
- errorat(lx->pos, "invalid declarator");
- goto End;
- }
- if (!noname || noname == 2 && dt->name->kind)
- name = nameof(dt->name);
-
- *base = typeofdtor(dt, *base);
- putdtor(p, dt);
- return name;
-End:
- putdtor(p, dt);
- return nil;
-}
-
-// -----------------------------------------------------------------------
-// declarations
-
-static
-uint32
-enumerate(Parser *p, Lexer *lx, string name, int kind)
-{
- int i, n;
- uint64 s;
- uint32 t;
- Token tk;
- /* TODO: think of a better soln */
- string nm[1024], *elts;
- Expr *cx[1024], *vals;
-
- for (n = 0; tk.kind != Arbrace && n < arrlen(nm); n++) {
- if (tk.kind != Aident) {
- errorat(tk.pos, "invalid token %s in enum declaration", tokens[tk.kind]);
- goto Bad;
- }
- nm[n] = tk.val.s;
- cx[n] = nil;
-
- tk = advance(p, lx);
- switch(tk.kind) {
- case Aeq:
- advance(p, lx);
- cx[n] = expr(p, lx);
- tk = peek(p, 0);
- if (tk.kind != Acomma)
- continue;
- /* fallthrough */
- case Acomma:
- tk = advance(p, lx);
- }
- }
- copyarray(elts, nm, n);
- copyarray(vals, cx, n);
-
- t = enumtype(n, elts, vals);
- declareenum(p, n, elts, vals);
- return t;
-Bad:
- errorat(tk.pos, "failed to parse enum declaration");
- return 0;
-}
-
-static
-uint32
-aggregate(Parser *p, Lexer *lx, string name, int kind)
-{
- int n;
- uint64 s;
- Token tk;
- /* TODO: think of a better soln */
- static Field fs[1024];
- Field *f;
- static Expr *cx[1024];
- Expr *x;
-
- for (n = 0, tk = peek(p, 0); tk.kind != Arbrace && n < arrlen(fs); n++) {
- fs[n].type = basetype(p, lx, &s);
- fs[n].qual = (uint32)(s & ~(MaskTyp|MaskInt|MaskFlt));
- Field:
- fs[n].name = namedecl(p, lx, &fs[n].type, 0);
- tk = peek(p, 0);
- switch (tk.kind) {
- case Acolon:
- advance(p, lx);
- cx[n] = expr(p, lx);
- tk = peek(p, 0);
- if (tk.kind == Asemi) {
- tk = advance(p, lx);
- continue;
- }
- if (tk.kind != Acomma) {
- errorat(tk.pos, "unrecognized token %s in struct field declaration", tokens[tk.kind]);
- goto Bad;
- }
- /* fallthrough */
- case Acomma:
- advance(p, lx);
- n++;
- goto Field;
-
- case Asemi:
- tk = advance(p, lx);
- continue;
-
- default:
- errorat(tk.pos, "unrecognized token %s in struct field declaration", tokens[tk.kind]);
- goto Bad;
- }
- }
- copyarray(f, fs, n);
- copyarray(x, cx, n);
- return (kind == Tstruct) ? structtype(n, f, x) : uniontype(n, f, x);
-Bad:
- errorat(tk.pos, "failed to parse aggregate declaration");
- return 0;
-}
-
-static
-error
-spec(Parser *p, Lexer *lx, uint64 *spec)
-{
- Token t;
- int n, i;
- Sym *typ;
- string name;
- uint32 tag;
- uint64 s, sm;
- static uint32 (*aggrfunc[2])(Parser *, Lexer *, string , int) = {aggregate, enumerate};
-
- s = 0;
- while (t = peek(p, 0), t.kind >= Aident) {
- /* typename */
- if (t.kind == Aident) {
- typ = lookupobj(p, t.val.s);
- if (!typ || (typ && typ->kind != Stype))
- break;
-
- sm = typ->type;
- s |= (sm << 32 | Tname);
- advance(p, lx);
- continue;
- }
-
- /* keyword */
- switch (n = t.val.i) {
- case Kauto: case Kregister: case Kstatic: case Kextern: case Ktypedef: case Ktls:
- if (s & MaskMem) {
- errorat(lx->pos, "multiple storage class specifiers: second was %s", keywords[n]);
- goto Bad;
- }
- break;
-
- case Kinline: case Knoret:
- if (s & Bit(n))
- warnat(lx->pos, "duplicate %s function specifier", keywords[n]);
- break;
-
- case Kconst: case Kvolatile:
- if (s & Bit(n))
- warnat(lx->pos, "duplicate %s specifier found in declaration", keywords[n]);
- break;
-
- case Ksigned: case Kunsigned:
- if (s & MaskSgn) {
- if (s & Bit(n)) {
- warnat(lx->pos, "duplicated storage class specifier: second was %s", keywords[n]);
- break;
- }
- errorat(lx->pos, "multiple storage class specifiers");
- goto Bad;
- }
- break;
-
- case Kshort:
- if (s & Tshort) {
- warnat(lx->pos, "duplicated short specifier");
- break;
- }
- break;
-
- case Klong:
- if ((s >> Klong) & 2) {
- errorat(lx->pos, "cannot chain three or more long specifiers");
- goto Bad;
- }
- s += Bit(n);
- t = advance(p, lx);
- continue;
-
- case Kvoid: case Kchar: case Kint: case Kfloat: case Kdouble:
- if (s & MaskTyp) {
- errorat(lx->pos, "more than one base type specified");
- goto Bad;
- }
- break;
-
- case Kstruct: case Kunion:
- i = 0;
- goto Aggr;
- case Kenum:
- i = 1;
- Aggr:
- if (s & (Tstruct | Tunion | Tenum)) {
- errorat(lx->pos, "more than one aggregate/enum type specified");
- goto Bad;
- }
- t = advance(p, lx);
- if (t.kind != Aident && t.kind != Albrace) {
- errorat(t.pos, "enum specifier missing valid declaration");
- goto Bad;
- }
-
- /* NOTE: This offset is needed to correctly obtain Tstruct */
- n++;
- name = nil;
- tag = 0;
- if (t.kind == Aident) {
- name = t.val.s;
- t = advance(p, lx);
- }
- if (t.kind == Albrace) {
- /* TODO: we need check if the name exists. */
- t = advance(p, lx);
- /* NOTE: This depends on the enum order. KEEP IN SYNC */
- tag = aggrfunc[i](p, lx, name, Bit(n));
- if (t = peek(p, 0), nomatch(t, Arbrace)) {
- errorat(t.pos, "invalid token %s in aggregate/enum declaration", tokens[t.kind]);
- goto Bad;
- }
- /* high bits encode the type index */
- s |= (uint64)tag << 32;
- }
- /* TODO: if name does not exist, enter in an incomplete type! */
- if (name)
- declaretag(p, tag, name);
-
- break;
-
- default:
- errorat(t.pos, "invalid keyword '%s' found in declaration specifier", keywords[n]);
- }
-
- s |= Bit(n);
- advance(p, lx);
- }
-
- *spec = s;
- return 0;
-
-Bad:
- /* TODO: serialize bitflags to string for nice error message */
- errorat(lx->pos, "ignoring specifier");
- *spec = Sbad;
- return 1;
-}
-
-/*
- * name declaration
- * see dtor for valid values of ab
- */
-static
-error
-name(Parser *p, Lexer *lx, Name **nmp, int ab)
-{
- Token t;
- int n, k;
- uint64 s;
- Sym *sym;
- Name *nm, *tmp;
-
- /* max args = 100 */
- struct Field args[100];
-
- nm = *nmp;
- t = peek(p, 0);
- switch (k = t.kind) {
- case Aident:
- if (ab == 1) {
- errorat(t.pos, "identifier not allowed in abstract declarator");
- goto Bad;
- }
- nm->kind = Nident;
- nm->ident = t.val.s;
- break;
-
- case Alparen:
- advance(p, lx);
- nm->kind = Nparen;
- nm->paren = getdtor(p);
- if (dtor(p, lx, nm->paren, ab)) {
- putdtor(p, nm->paren);
- nm->paren = nil;
- errorat(lx->pos, "invalid declarator in parenthesis");
- goto Bad;
- }
-
- t = peek(p, 0);
- if (nomatch(t, Arparen)) {
- putdtor(p, nm->paren);
- nm->paren = nil;
- errorat(lx->pos, "missing closing paren in declarator");
- goto Bad;
- }
- break;
-
- case Albrakt:
- if (ab)
- goto Sfx;
- errorat(lx->pos, "missing identifier in non-abstract declarator");
- /* fallthrough */
- default:
- if (ab)
- goto Sfx;
- errorat(lx->pos, "invalid token '%s' in name declaration", tokens[k]);
- goto Bad;
- }
-
- t = advance(p, lx);
-Sfx:
- for (;;) {
- switch (k = t.kind) {
- case Albrakt:
- tmp = getname(p);
- tmp->kind = Nindex;
- tmp->sfx.name = nm;
-
- nm = tmp, tmp = nil;
-
- t = advance(p, lx);
- if (t.kind == Arbrakt) {
- nm->sfx.idx.q = 0;
- Iend:
- nm->sfx.idx.x = nil;
- t = advance(p, lx);
- break;
- }
- if (t.kind == Astar) {
- nm->sfx.idx.q = -1;
- IStar:
- nm->sfx.idx.x = nil;
- t = advance(p, lx);
- if (t.kind != Arbrakt) {
- errorat(t.pos, "invalid '*' syntax in index expression");
- goto Bad;
- }
- t = advance(p, lx);
- break;
- }
-
- if (spec(p, lx, &s)) {
- errorat(lx->pos, "invalid type qualifier list in index expression");
- goto Bad;
- }
-
- nm->sfx.idx.q = (uint32)s;
- t = peek(p, 0);
-
- if (t.kind == Astar)
- goto IStar;
-
- if (t.kind == Arbrakt)
- goto Iend;
-
- nm->sfx.idx.x = expr(p, lx);
-
- t = peek(p, 0);
- if (nomatch(t, Arbrakt)) {
- errorat(t.pos, "unterminated index expression");
- goto Bad;
- }
-
- t = advance(p, lx);
- continue;
-
- case Alparen:
- tmp = getname(p);
- tmp->kind = Ncall;
- tmp->sfx.name = nm;
-
- nm = tmp, tmp = nil;
-
- t = advance(p, lx);
- nm->sfx.call.n = 0;
- switch (t.kind) {
- case Arparen:
- nm->sfx.call.arg = nil;
- break;
-
- case Aident:
- sym = lookupobj(p, t.val.s);
- if (!sym || (sym && sym->kind != Stype)) {
- while (t.kind == Aident) {
- if (nm->sfx.call.n >= arrlen(args))
- panicf("ident stack overflow");
- args[nm->sfx.call.n++] = (struct Field) {
- .qual = 0,
- .type = 0,
- .name = t.val.s,
- };
- t = advance(p, lx);
- }
- if (nomatch(t, Arparen)) {
- errorat(t.pos, "token '%s' found in function parameter identifier list");
- goto Bad;
- }
- copyarray(nm->sfx.call.arg, args, nm->sfx.call.n);
- break;
- }
- goto ParamLoop;
-
- case Akeywd:
- if (t.val.i < Kconst || t.val.i > Kenum) {
- errorat(t.pos, "invalid keyword %s inside function signature");
- goto Bad;
- }
-
- ParamLoop:
- if (nm->sfx.call.n >= arrlen(args)-1)
- panicf("out of argument buffer");
-
- args[nm->sfx.call.n].type = basetype(p, lx, &s);
- if (!args[nm->sfx.call.n].type) {
- errorat(lx->pos, "could not parse base type in function call");
- goto Bad;
- }
-
- args[nm->sfx.call.n].qual = (uint32)s & ~(MaskTyp|MaskInt|MaskFlt);
- args[nm->sfx.call.n].name = namedecl(p, lx, &args[nm->sfx.call.n].type, 2);
-
- nm->sfx.call.n++;
- if ((t = peek(p, 0)).kind == Acomma) {
- advance(p, lx);
- goto ParamLoop;
- }
-
- if (t.kind == Aellip) {
- nm->sfx.call.dots = 1;
- t = advance(p, lx);
- }
-
- if (nomatch(t, Arparen)) {
- errorat(t.pos, "token '%s' found in function parameter list");
- goto Bad;
- }
- copyarray(nm->sfx.call.arg, args, nm->sfx.call.n);
- break;
-
- default:
- errorat(t.pos, "invalid token %s inside function call signature", tokens[t.kind]);
- goto Bad;
- }
-
- t = advance(p, lx);
- continue;
-
- default:
- break;
- }
- break;
- }
-
- *nmp = nm;
- return 0;
-Bad:
- return 1;
-}
-
-/* pointer kind is partitioned into 8x6 regions
- * ab => abstract
- * @ 0: must have identifier
- * @ 1: must not have identifier
- * @ 2: don't care
- * else: undefined
- */
-static
-error
-dtor(Parser *p, Lexer *lx, Dtor *d, int ab)
-{
- int n, k;
- error err;
- Token t;
- Dtor *link;
- Ptr *ptr, *x;
-
- err = 1;
-
- ptr = &d->ptr;
- ptr->kind = 0;
- ptr->link = nil;
-
- t = peek(p, 0);
- if (t.kind != Astar) {
- if (ab || t.kind == Aident || t.kind == Arparen)
- goto Name;
- goto Bad;
- }
- n = 0;
-Ptr:
- ptr->kind |= Bit(n);
- advance(p, lx);
-Key:
- t = peek(p, 0);
- switch (k = t.kind) {
- case Akeywd:
- if (Kconst <= t.val.i && t.val.i <= Katomic)
- ptr->kind |= Bit(6*n + (t.val.i - Kconst + 1));
- else {
- errorat(lx->pos, "invalid keyword '%s' modifies pointer", keywords[t.val.i]);
- goto Bad;
- }
- advance(p, lx);
- goto Key;
-
- case Astar:
- if (++n >= 8) {
- x = getptr(p);
- x->kind = 0;
- x->link = nil;
- ptr->link = x;
- ptr = x;
- n = 0;
- }
- goto Ptr;
-
- case Aident:
- case Alparen:
- goto Name;
-
- default:
- if (ab)
- goto Name;
- errorat(lx->pos, "invalid token '%s' modifies pointer specification", tokens[t.kind]);
- goto Bad;
- }
-Name:
- return name(p, lx, &d->name, ab);
-Bad:
- return err;
-}
-
-static
-Decl *
-decl(Parser *p, Lexer *lx)
-{
- uint64 s;
- Token t;
- Decl *d;
- Expr *x;
- string name;
- struct Decls *ds;
- uint32 base, type;
-
- alloc(d);
-
- d->kind = 0;
- d->pos.beg = lx->pos;
-
- base = basetype(p, lx, &s);
- if (!base) {
- errorat(lx->pos, "could not parse type declaration");
- goto Bad;
- }
-
- x = nil;
- d->spec = (uint32)s & ~(MaskInt|MaskFlt|MaskTyp);
- d->type = base;
- d->name = namedecl(p, lx, &d->type, 0);
- /* TODO: think about functions (both decls and defs) */
- d->kind = (s & Mtype) ? Dtype : Dvar;
-
- switch (t = peek(p, 0), t.kind) {
- case Aeq:
- if (s & Mtype) {
- errorat(d->pos.beg, "initialization of type not allowed");
- goto Bad;
- }
- t = advance(p, lx);
- x = initx(p, lx);
- d->kind = Dvar;
- if (t.kind != Acomma) {
- d->init = x;
- goto Semi;
- }
- /* fallthrough */
- case Acomma:
- d->kind |= Dlist;
- d->list.init = x;
- /* move singleton data over */
- name = d->name;
- type = d->type;
- d->list.name = name;
- d->list.type = type;
- ds = &d->list;
- /* iterate until we hit end of list */
- while (t.kind == Acomma) {
- t = advance(p, lx);
-
- alloc(ds->link);
- ds = ds->link;
- ds->type = base;
- ds->name = namedecl(p, lx, &ds->type, 0);
-
- t = peek(p, 0);
- if (t.kind == Aeq) {
- t = advance(p, lx);
- ds->init = initx(p, lx);
- } else
- ds->init = nil;
- }
- goto Semi;
-
- case Albrace:
- d->kind = Dfunc;
- alloc(d->body);
-
- if (!attop(p)) {
- errorat(lx->pos, "nested function declarations are illegal");
- goto Bad;
- }
-
- if (C.type.info[d->type].kind != Tfunc) {
- errorat(lx->pos, "attempted to define function body for non function type");
- goto Bad;
- }
-
- openscope(p);
- if (blkstmt(p, lx, &d->body)) {
- errorat(lx->pos, "failed to parse function body");
- goto Bad;
- }
- closescope(p);
- break;
-
- default:
- Semi:
- if (nomatch(t, Asemi)) {
- errorat(t.pos, "no semicolon after declaration");
- goto Bad;
- }
- t = advance(p, lx);
- }
-
- d->pos.end = lx->pos;
- declareobj(p, d);
- return d;
-Bad:
- errorat(lx->pos, "failed to parse top level declaration");
- return nil;
-}
-
-// -----------------------------------------------------------------------
-// top level api
-
-void
-setup(Parser *p, Lexer *lx)
-{
- advance(p,lx);
- advance(p,lx);
-
- /* define all builtin typedefs */
- declareobj(p, &C.builtin.vargs);
-}
-
-error
-parse(Parser *p, Lexer *lx)
-{
- Token tok;
-
- setup(p, lx);
- while ((tok = peek(p, 0)), tok.kind > Aeof) {
- if (p->ast.len >= p->ast.cap) {
- p->ast.cap += 20;
- p->ast.decls = realloc(p->ast.decls, p->ast.cap*sizeof(*p->ast.decls));
- }
- p->ast.decls[p->ast.len++] = decl(p, lx);
- }
-
- return 0;
-}
diff --git a/sys/cmd/cc/bits.c b/sys/cmd/cc/bits.c
deleted file mode 100644
index 4b405dc..0000000
--- a/sys/cmd/cc/bits.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include "cc.h"
-
-// -----------------------------------------------------------------------
-// Architecture
-
-enum
-{
- archx64,
- numarch,
-};
-
-// -----------------------------------------------------------------------
-// Types
-
-/*
- * enumerated type specifers
- * see https://en.wikipedia.org/wiki/C_data_types
- */
-#define VOID X(Tvoid, 2)
-
-#define BOOL X(Tbool, 3)
-#define CHAR X(Tchar, 4)
-#define SCHAR X(Tsign|Tchar, 5)
-#define UCHAR X(Tunsign|Tchar, 6)
-
-#define SHORT X(Tshort, 7), X(Tshort|Tint, 7)
-#define SSHORT X(Tsign|Tshort, 8), X(Tsign|Tshort|Tint, 8)
-#define USHORT X(Tunsign|Tshort, 9), X(Tunsign|Tshort|Tint, 9)
-
-#define INT X(0, 10), X(Tint, 10)
-#define SINT X(Tsign, 11), X(Tsign|Tint, 11)
-#define UINT X(Tunsign, 12), X(Tunsign|Tint, 12)
-
-#define LONG X(Tlong, 13), X(Tlong|Tint, 13)
-#define SLONG X(Tsign|Tlong, 14), X(Tsign|Tlong|Tint, 14)
-#define ULONG X(Tunsign|Tlong, 15), X(Tunsign|Tlong|Tint, 15)
-
-#define VLONG X(Tvlong, 16), X(Tvlong|Tint, 16)
-#define SVLONG X(Tsign|Tvlong, 17), X(Tsign|Tvlong|Tint, 17)
-#define UVLONG X(Tunsign|Tvlong, 18), X(Tunsign|Tvlong|Tint, 18)
-
-#define FLOAT X(Tfloat, 19)
-#define DOUBLE X(Tdouble, 20)
-#define LONGDB X(Tlong|Tdouble, 21)
-#define COMPLEX X(Tcmplx, 22)
-#define IMAGINARY X(Timag, 23)
-
-/* fixed width definitions */
-#define DEF(sz, aln, mx, sgn) {.size=sz, .align=aln, .max=mx, .sign=sgn }
-
-#define INT8 DEF(1, 1, 0x7fff, 0)
-#define UINT8 DEF(1, 1, 0xffff, 1)
-
-#define INT16 DEF(2, 2, 0x7fff, 0)
-#define UINT16 DEF(2, 2, 0xffff, 1)
-
-#define INT32 DEF(4, 4, 0x7fffffff, 0)
-#define UINT32 DEF(4, 4, 0xffffffff, 1)
-
-#define INT64 DEF(8, 8, 0x7fffffffffffffff, 0)
-#define UINT64 DEF(8, 8, 0xffffffffffffffff, 1)
-
-/* architecture specific definitions */
-// TODO: max value should be able to take floats
-#define TYPES \
- TYPE(DEF(0, 0, 0, 0), VOID) \
- TYPE(INT8, BOOL) \
- TYPE(UINT8, CHAR) \
- TYPE(INT8, SCHAR) \
- TYPE(UINT8, UCHAR) \
- TYPE(INT16, SHORT) \
- TYPE(INT16, SSHORT) \
- TYPE(UINT16, USHORT) \
- TYPE(INT32, INT) \
- TYPE(INT32, SINT) \
- TYPE(UINT32, UINT) \
- TYPE(INT64, LONG) \
- TYPE(INT64, SLONG) \
- TYPE(UINT64, ULONG) \
- TYPE(INT64, VLONG) \
- TYPE(INT64, SVLONG) \
- TYPE(UINT64, UVLONG) \
- TYPE(DEF(4, 4, 0, 0), FLOAT) \
- TYPE(DEF(8, 8, 0, 0), DOUBLE) \
- TYPE(DEF(16, 16, 0, 0), LONGDB) \
- TYPE(DEF(8, 8, 0, 0), COMPLEX) \
- TYPE(DEF(4, 4, 0, 0), IMAGINARY) \
-
-Type pointer = {.size=8, .align=8, .max=0xffffffffffffffff, .sign=0};
-
-/* pack architecture specific definitions into exported arrays */
-#define TYPE(a, ...) a,
-Type basetypes[] = {
- { 0 }, /* sentinel value for bad types */
- { 0 }, /* sentinel value for variadic args */
- TYPES
-};
-#undef TYPE
-
-#define TYPE(a, ...) __VA_ARGS__,
-#define X(a, b) a
-uint64 validtypespec[38] = {
- TYPES
- Tstruct, Tunion, Tenum, Tname,
-};
-#undef X
-
-#define X(a, b) b
-int indextypespec[38] = {
- TYPES
- -1, -1, -1, -1,
-};
-#undef X
-#undef TYPE
diff --git a/sys/cmd/cc/cc.c b/sys/cmd/cc/cc.c
deleted file mode 100644
index 8ad0022..0000000
--- a/sys/cmd/cc/cc.c
+++ /dev/null
@@ -1,409 +0,0 @@
-#include "cc.h"
-#include <libn/macro/map.h>
-
-// -----------------------------------------------------------------------
-// string interning
-
-/* jenkins' one at a time hash */
-static
-int32
-hash_string(byte* s)
-{
- int32 h;
-
- h = 0;
- if (s != nil) {
- for (; *s; ++s) {
- h += *s;
- h = (h << 10);
- h = (h >> 6);
- }
- }
-
- h += (h << 3);
- h ^= (h >> 11);
- h += (h >> 11);
-
- return h;
-}
-
-static
-int
-streq(byte *s, byte *t)
-{
- if (s == nil) {
- if (t == nil)
- return 1;
- else
- return 0;
- }
-
- return (t == nil) ? 0 : strcmp(s, t) == 0;
-}
-
-#define HASH(s) hash_string(s)
-#define EQUAL(s, t) (streq(s, t))
-static
-int
-getstr(string key, int *ok)
-{
- int idx;
- MAP_GET(idx, (&C.strs), key, HASH, EQUAL);
-
- *ok = idx < C.strs.n_buckets;
- return idx;
-}
-
-static
-void
-·free(void* _, void* ptr) {
- return free(ptr);
-}
-
-static
-void *
-·alloc(void* _, uint n, ulong size) {
- return malloc(n*size);
-}
-
-static
-void *
-·calloc(void* _, uint n, ulong size) {
- return calloc(n, size);
-}
-
-static
-int
-morestrtab(StrTab *tab, int n)
-{
- MAP_GROW(tab, string, int32, n, HASH, ·calloc, ·free, nil);
-}
-
-static
-int
-putstr(byte *s, error *err)
-{
- int sz;
- sz = C.strs.size;
- MAP_PUT((&C.strs), s, sz, HASH, EQUAL, morestrtab, err);
-}
-#undef HASH
-#undef EQUAL
-
-int32
-intern(byte **s)
-{
- int i, ok;
-
- i = getstr(*s, &ok);
- if (ok) {
- *s = C.strs.keys[i];
- goto END;
- }
-
- *s = str·make(*s);
- i = putstr(*s, &ok);
- C.strs.vals[i] = C.strs.size - 1;
-
-END:
- return C.strs.vals[i];
-}
-
-// -----------------------------------------------------------------------
-// type interning
-
-/* TODO: intern types for memory savings */
-int
-type()
-{
- if (C.type.len >= C.type.cap) {
- C.type.cap += 100;
- C.type.info = realloc(C.type.info, C.type.cap * sizeof(*C.type.info));
- }
-
- return C.type.len++;
-}
-
-// -----------------------------------------------------------------------
-// universal compiler builtins
-
-#define KEYWORD(a, b) b,
-byte *keywords[NUM_KEYWORDS] = { KEYWORDS };
-#undef KEYWORD
-
-#define DIRECTIVE(a, b, c) b,
-byte *directives[NUM_DIRECTIVES] = { DIRECTIVES };
-#undef DIRECTIVE
-
-struct Compiler C = { 0 };
-
-// -----------------------------------------------------------------------
-// cli flag handlers
-
-void
-pushinclude(byte *dirs)
-{
- string d, s, *it, *end;
-
- while (*dirs != '\0') {
- d = strchr(dirs, ' ');
- if (d != nil)
- *d = '\0';
-
- s = dirs;
- intern(&s);
- for (it = C.inc.dir, end = it + C.inc.len; it != end; ++it) {
- if ((uintptr)s == (uintptr)(*it))
- goto Nextdir;
- }
-
- if (C.inc.len == C.inc.cap) {
- C.inc.cap += 20;
- C.inc.dir = realloc(C.inc.dir, C.inc.cap*sizeof(*C.inc.dir));
- }
- C.inc.dir[C.inc.len++] = s;
-Nextdir:
- if (d == nil)
- break;
- dirs = d + 1;
- }
-}
-
-// -----------------------------------------------------------------------
-// error reporting
-
-void
-errorat(Pos x, byte *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- printf("error:%s:%d:%d: ", os·basename(x.path), x.line, x.col);
- vprintf(fmt, args);
- printf("\n");
-
- va_end(args);
- assert(0);
-}
-
-void
-warnat(Pos x, byte *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- printf("warning:%s:%d:%d: ", os·basename(x.path), x.line, x.col);
- vprintf(fmt, args);
- printf("\n");
-
- va_end(args);
-}
-
-// -----------------------------------------------------------------------
-// main point of entry
-
-void
-init(void)
-{
- int i;
-
- for (i = 0; i < arrlen(keywords); i++)
- intern(&keywords[i]);
-
- for (i = 0; i < arrlen(directives); i++)
- intern(&directives[i]);
-
- C.heap = mem·makearena(mem·sys, nil);
-
- /* compiler definitions */
- C.def.len = 0;
- C.def.cap = 100;
- C.def.val = calloc(C.def.cap, sizeof(*C.def.val));
-
- /* compiler include paths */
- C.inc.len = 0;
- C.inc.cap = 100;
- C.inc.dir = calloc(C.inc.cap, sizeof(*C.inc.dir));
- C.inc.dir[C.inc.len++] = ".";
-
- C.outfile = nil;
-
- /* type info */
- C.type.len = arrlen(basetypes);
- C.type.cap = 100 + arrlen(basetypes);
- C.type.info = calloc(C.type.cap, sizeof(*C.type.info));
-
- memcpy(C.type.info, basetypes, C.type.len * sizeof(*C.type.info));
-
- /* builtins */
- C.builtin.vargs = (Decl) {
- .pos = (Range) {
- .beg = {
- .col = 0,
- .line = 0,
- .path = "<builtin>",
- },
- .end = {
- .col = 0,
- .line = 0,
- .path = "<builtin>",
- },
- },
- .kind = Dtype,
- .spec = Mtype,
- .type = 1,
- .name = "__builtin_va_list",
- };
-
- intern(&C.builtin.vargs.name);
-}
-
-void
-initlx(Lexer *lx)
-{
- int i;
-
- memset(lx, 0, sizeof(*lx));
- lx->b = lx->buf;
-
- /* predefine macros */
- dodefine(lx, "__LINE__");
- dodefine(lx, "__FILE__");
- lx->macline = (uintptr)lookup(&lx->sym, "__LINE__");
- lx->macfile = (uintptr)lookup(&lx->sym, "__FILE__");
-
- for (i = 0; i < C.def.len; i++)
- dodefine(lx, C.def.val[i]);
-
- lx->omit.len = 0;
- lx->omit.cap = 100;
- lx->omit.path = calloc(lx->omit.cap, sizeof(*C.inc.dir));
-
- lx->new = lx->iostk;
- lx->new->link = nil;
- memset(lx->iostk, 0, sizeof(lx->iostk));
-
- lx->sym = (SymTab){ 0 };
-}
-
-void
-freelx(Lexer *lx)
-{
- free(lx->omit.path);
-}
-
-void
-initp(Parser *p)
-{
- /* initialize temporary buffers */
- memset(p->spstk, 0, sizeof(p->spstk));
- memset(p->nmstk, 0, sizeof(p->nmstk));
- memset(p->dtstk, 0, sizeof(p->dtstk));
- memset(p->ptstk, 0, sizeof(p->ptstk));
-
- p->sp = p->spstk;
- p->nm = p->nmstk;
- p->dt = p->dtstk;
- p->pt = p->ptstk;
-
- /* initialize ast */
- p->ast.cap = 0;
- p->ast.len = 0;
- p->ast.decls = nil;
-}
-
-error
-compile(byte *path)
-{
- Lexer lx;
- Parser p;
- error err;
- byte *sep, out[400];
-
- intern(&path);
- strcpy(out, path);
-
- sep = utf8·findrrune(out, '/');
- if (sep)
- *sep++ = '\0';
- else
- sep = out;
-
- if (!C.outfile) {
- C.outfile = sep;
- if (C.outfile) {
- if ((sep = utf8·findrrune(C.outfile, '.'))) {
- sep[0] = '.';
- sep[1] = 'o';
- sep[2] = '\0';
- }
- } else {
- C.outfile = "/dev/null";
- }
- }
-
- initlx(&lx);
- initp(&p);
-
- lx.io = openio(&lx, path);
- lx.pos = (Pos){
- .path = path,
- .line = 1,
- .col = 1,
- };
-
- err = parse(&p, &lx);
- freelx(&lx);
- return err;
-}
-
-error
-main(int argc, byte *argv[])
-{
- byte *a, *src;
- int err;
-
- init();
-
- ARGBEGIN {
- case 'o':
- C.outfile = ARGF();
- break;
-
- case 'D':
- a = ARGF();
- if (a) {
- intern(&a);
- if (C.def.len >= C.def.cap) {
- C.def.cap += 20;
- C.def.val = realloc(C.def.val, C.def.cap * sizeof(*C.def.val));
- }
- C.def.val[C.def.len++] = a;
- }
- break;
-
- case 'I':
- a = ARGF();
- if (a)
- pushinclude(a);
- break;
- } ARGEND
-
- if (argc < 1 && C.outfile == nil) {
- printf("usage: cc [-options] files\n");
- exit(1);
- }
-
- // NOTE: This is just for my comfort during debugging.
- pushinclude("/home/nolln/root/include");
- pushinclude("/home/nolln/root/include/vendor/libc");
-
- src = (argc == 0) ? "<stdin>" : argv[0];
- intern(&src);
-
- if ((err = compile(src)), err) {
- exit(2);
- }
-
- exit(0);
-}
diff --git a/sys/cmd/cc/cc.h b/sys/cmd/cc/cc.h
deleted file mode 100644
index 8fc5f73..0000000
--- a/sys/cmd/cc/cc.h
+++ /dev/null
@@ -1,806 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <libn.h>
-
-#define iota(x) 1 << (x)
-
-/* core types */
-typedef struct Io Io;
-typedef struct Pos Pos;
-typedef struct Range Range;
-typedef struct Token Token;
-
-typedef struct Lexer Lexer;
-
-typedef struct Sym Sym;
-typedef struct Type Type;
-typedef struct Scope Scope;
-
-typedef struct Parser Parser;
-
-typedef struct Ptr Ptr;
-typedef struct Name Name;
-typedef struct Dtor Dtor;
-typedef struct Field Field;
-
-typedef struct Node Node;
-typedef struct Decl Decl;
-typedef struct Stmt Stmt;
-typedef struct Expr Expr;
-
-typedef struct SymTab SymTab;
-typedef struct StrTab StrTab;
-
-typedef struct Compiler Compiler;
-
-/* keywords of language */
-#define KEYWORDS \
- KEYWORD(Kauto,"auto") \
- KEYWORD(Kregister,"register") \
- KEYWORD(Kstatic,"static") \
- KEYWORD(Kextern,"extern") \
- KEYWORD(Ktls,"thread_local") \
- KEYWORD(Ktypedef,"typedef") \
- KEYWORD(Kinline,"inline") \
- KEYWORD(Knoret,"_Noreturn") \
- KEYWORD(Kconst,"const") \
- KEYWORD(Kvolatile,"volatile") \
- KEYWORD(Krestrict,"restrict") \
- KEYWORD(Katomic,"_Atomic") \
- KEYWORD(Ksigned,"signed") \
- KEYWORD(Kunsigned,"unsigned") \
- KEYWORD(Kvoid,"void") \
- KEYWORD(Kbool,"_Bool") \
- KEYWORD(Kchar,"char") \
- KEYWORD(Kfloat,"float") \
- KEYWORD(Kdouble,"double") \
- KEYWORD(Kcomplex,"complex") \
- KEYWORD(Kimaginary,"imaginary") \
- KEYWORD(Kint,"int") \
- KEYWORD(Kshort,"short") \
- KEYWORD(Klong,"long") \
- KEYWORD(Kstruct,"struct") \
- KEYWORD(Kunion,"union") \
- KEYWORD(Kenum,"enum") \
- KEYWORD(Kfor,"for") \
- KEYWORD(Kdo,"do") \
- KEYWORD(Kwhile,"while") \
- KEYWORD(Kcontinue,"continue") \
- KEYWORD(Kif,"if") \
- KEYWORD(Kelse,"else") \
- KEYWORD(Kswitch,"switch") \
- KEYWORD(Kcase,"case") \
- KEYWORD(Kdefault,"default") \
- KEYWORD(Kbreak,"break") \
- KEYWORD(Kgoto,"goto") \
- KEYWORD(Kreturn,"return") \
- KEYWORD(Ksizeof,"sizeof") \
- KEYWORD(Kalignof,"alignof") \
- KEYWORD(Kalignas,"alignas")
-
-#define KEYWORD(a, b) a,
-enum { KEYWORDS NUM_KEYWORDS };
-#undef KEYWORD
-
-extern byte *keywords[NUM_KEYWORDS];
-
-// -----------------------------------------------------------------------
-// lexing: byte stream -> tokens
-// pre-processor built in
-
-/* source position: error reporting */
-struct Pos
-{
- int col;
- int line;
- string path;
-};
-
-
-struct Range
-{
- Pos beg;
- Pos end;
-};
-
-void errorat(Pos x, byte *fmt, ...);
-void warnat(Pos x, byte *fmt, ...);
-
-/* pre-processor */
-#define DIRECTIVES \
- DIRECTIVE(Dpragma,"pragma", ppprag) \
- DIRECTIVE(Dinclude,"include", ppinc) \
- DIRECTIVE(Ddefine,"define", ppdef) \
- DIRECTIVE(Dundef,"undef", ppund) \
- DIRECTIVE(Dif,"if", ppif0) \
- DIRECTIVE(Delif,"elif", ppif1) \
- DIRECTIVE(Delse, "else", ppif1) \
- DIRECTIVE(Difdef,"ifdef", ppif2) \
- DIRECTIVE(Difndef,"ifndef", ppif3) \
- DIRECTIVE(Dendif,"endif", ppend)
-
-#define DIRECTIVE(a, b, c) a,
-enum { DIRECTIVES NUM_DIRECTIVES };
-#undef DIRECTIVE
-
-extern byte *directives[NUM_DIRECTIVES];
-
-error domacro(Lexer*);
-error dodefine(Lexer *lx, string s);
-int expandmacro(Lexer *lx, Sym *s, byte *dst);
-
-extern error (*macros[NUM_DIRECTIVES])(Lexer*);
-
-/* tokenization of byte stream */
-#define TOKENS \
- TOK(Anil,"nil") \
- TOK(Aeof,"eof") \
- TOK(Aeq, "==") \
- TOK(Aneq, "!=") \
- TOK(Anot, "!") \
- TOK(Aneg, "~") \
- TOK(Axor, "^") \
- TOK(Aor, "|") \
- TOK(Aand, "&") \
- TOK(Aoror, "||") \
- TOK(Aandand, "&&") \
- TOK(Aadd,"+") \
- TOK(Asub,"-") \
- TOK(Astar,"*") \
- TOK(Adiv,"/") \
- TOK(Amod,"%") \
- TOK(Agt,">") \
- TOK(Alt,"<") \
- TOK(Agteq,">=") \
- TOK(Alteq,"<=") \
- TOK(Alsft,"<<") \
- TOK(Arsft,">>") \
- TOK(Ainc,"++") \
- TOK(Adec,"--") \
- TOK(Aasn,"=") \
- TOK(Aorasn,"|=") \
- TOK(Axorasn,"^=") \
- TOK(Aandasn,"&=") \
- TOK(Aaddasn,"+=") \
- TOK(Asubasn,"-=") \
- TOK(Amulasn,"*=") \
- TOK(Adivasn,"/=") \
- TOK(Amodasn,"%=") \
- TOK(Alsftasn,"<<=") \
- TOK(Arsftasn,">>=") \
- TOK(Acomma,",") \
- TOK(Acolon,":") \
- TOK(Asemi,";") \
- TOK(Alparen,"(") \
- TOK(Arparen,")") \
- TOK(Albrace,"{") \
- TOK(Arbrace,"}") \
- TOK(Albrakt,"[") \
- TOK(Arbrakt,"]") \
- TOK(Adot,".") \
- TOK(Aarrow,"->") \
- TOK(Aqmark,"?") \
- TOK(Aellip,"...") \
- TOK(Alit,"<literal>") \
- TOK(Aident,"<identifier>") \
- TOK(Akeywd,"<keyword>") \
-
-#define TOK(a, b) a,
-enum
-{
- TOKENS
- NUM_TOKENS,
-
- Vchar = iota(8),
- Vrune = iota(9),
- Vint = iota(10),
- Vlong = iota(11),
- Vvlong = iota(12),
- Vun = iota(13),
- Vfloat = iota(14),
- Vstr = iota(15),
- Vwstr = iota(16),
-
- Vmask = Vchar - 1,
-};
-#undef TOK
-
-extern byte *tokens[NUM_TOKENS];
-
-/* TODO: store literals in a big val */
-union Val
-{
- byte *s;
- double f;
- vlong i;
- uvlong ui;
- int32 c;
- uint32 uc;
- rune r;
-};
-
-struct Token
-{
- uint32 kind;
- Pos pos;
- union Val val;
-};
-
-enum
-{
- Svar = iota(1),
- Sfunc = iota(2),
- Stype = iota(3),
- Stag = iota(4),
- Senum = iota(5),
- Slabl = iota(6),
- Smacro = iota(7),
-};
-
-struct Sym
-{
- uint32 kind;
- string name;
- union {
- string macro;
- Decl *obj;
- int32 type;
- Stmt *blk;
- Expr *val;
- };
-};
-
-struct SymTab
-{
- int32 n_buckets;
- int32 size;
- int32 n_occupied;
- int32 upper_bound;
- int32 *flags;
- string *keys;
- Sym **vals;
-};
-
-Sym *define(SymTab *tab, string ident, uint32 kind);
-Sym *lookup(SymTab *tab, string ident);
-error forget(SymTab *tab, string ident);
-void forgetall(SymTab *tab);
-
-enum
-{
- IOnil = iota(0),
- IOfile = iota(1),
- IObuff = iota(2),
-};
-
-struct Io
-{
- io·Buffer rdr;
- string path;
- uint32 kind;
- union {
- Stream *f;
- byte *b;
- };
-
- Pos store;
- struct Io *link;
-};
-
-struct Lexer
-{
- Pos pos;
- SymTab sym;
- byte *b;
- byte buf[2*1024];
-
- /* predefined dynamic macros */
- uintptr macfile;
- uintptr macline;
-
- /* i/o data */
- Io *io, *new;
- Io iostk[100];
- struct {
- int cap;
- int len;
- string *path;
- } omit;
-};
-
-/* lex.c functions */
-Token lex(Lexer *);
-
-int getbyte(Lexer *);
-int getnsbyte(Lexer *l);
-rune getrune(Lexer *);
-byte ungetbyte(Lexer *);
-rune ungetrune(Lexer *, rune r);
-
-Io* openio(Lexer *lx, byte *path);
-void pushio(Lexer *lx, Io *new);
-void popio(Lexer *lx);
-
-void puttok(Token);
-
-// -----------------------------------------------------------------------
-// parsing & type resolution
-// tokens -> ast
-
-/* parent data */
-struct Node
-{
- Range pos;
- uint32 kind;
-};
-
-/* ast types */
-enum
-{
- Nbad,
- /* labels */
- Sempty, Slabel, Scase,
- Sblock,
- Sexpr, Sdecl,
- Sselect,
- /* loops */
- Sfor, Swhile, Sdo,
- /* jumps */
- Sgoto, Scontin, Sbreak, Sreturn,
- /* forks */
- Sif, Sswitch,
-
-
- /* assignments */
- Xasn, Xmulasn, Xdivasn, Xmodasn, Xsubasn, Xaddasn,
- Xlsftasn, Xrsftasn, Xandasn, Xxorasn, Xorasn,
- /* conditional */
- Xternary,
- /* unary prefix ops */
- Xref, Xstar, Xplus, Xminus, Xneg, Xnot, Xsizeof, Xalignof, Xpreinc, Xpredec,
- Xcast,
- /* unary postfix ops */
- Xpostinc, Xpostdec, Xindex, Xcall, Xselp, Xself, Xinitlist,
- /* binary ops */
- Xoror, Xandand, Xor, Xxor, Xand, Xneq, Xeql, Xgt, Xlt, Xgteq, Xlteq, Xlsft, Xrsft,
- Xadd, Xsub, Xmul, Xdiv, Xmod,
- /* primary */
- Xparen, Xident, Xlit,
- /* lists */
- Xcomma,
-
-
- Dvar,
- Dfunc,
- Dtype,
- Dlist = iota(20),
- Dvars = Dvar | Dlist,
- Dtypes = Dtype | Dlist,
-
- /* names (don't interact w/ final AST) */
- Nnil = 0,
- Nident,
- Nparen,
- Nindex,
- Ncall,
-};
-
-/* expressions */
-enum
-{
- Keynil,
- Keyidx,
- Keysel,
-};
-
-struct Key
-{
- uint kind : 2;
- union {
- Expr *x;
- string s;
- };
-};
-
-struct Expr
-{
- struct Node;
- uint32 qual;
- uint32 type;
- union {
- string name;
- struct {
- uint64 kind;
- union {
- union Val;
- union Val v;
- };
- } val;
- struct {
- int n;
- struct Key *k;
- Expr *v;
- } init;
- Expr *x;
- struct {
- Expr *l;
- Expr *r;
- } asn;
- struct {
- Expr *c;
- Expr *t;
- Expr *e;
- } cond;
- struct {
- Expr *x;
- union {
- Expr *i;
- string f;
- };
- } idx;
- struct {
- Expr *fn;
- int n;
- Expr **arg;
- } call;
- union {
- Expr *pre;
- Expr *post;
- } unary;
- struct {
- int type : 1;
- union {
- struct {
- uint32 qual;
- uint32 type;
- } of;
- Expr *x;
- };
- } info;
- struct {
- struct {
- uint32 qual;
- uint32 type;
- } to;
- Expr *x;
- } cast;
- struct {
- Expr *l;
- Expr *r;
- } binary;
- struct {
- Expr *x[2];
- } comma;
- };
-};
-
-
-/* statements */
-struct Stmt
-{
- struct Node;
- union {
- struct {
- union {
- string ident;
- Expr *x;
- };
- Node *stmt;
- } lbl;
- struct {
- long n;
- struct Node **item;
- } blk;
- Expr *x;
- struct {
- Node *init;
- Expr *cond;
- Expr *step;
- Node *body;
- } loop;
- union{
- string lbl;
- Expr *x;
- } jmp;
- struct {
- Expr *cond;
- Node *body;
- Node *orelse;
- } br;
- };
-};
-
-/* declarations */
-
-/*
- * specifiers
- * the design is the following:
- * type info is held w/in a 64 bit integer.
- * the bottom 32 bits are associated to specializations
- * the top 32 bits index into a type-info array held by the compiler.
- */
-enum
-{
- /* memory */
- Mauto = iota(Kauto),
- Mstatic = iota(Kstatic),
- Mreg = iota(Kregister),
- Mtls = iota(Ktls),
- Mtype = iota(Ktypedef),
- Mextern = iota(Kextern),
-
- MaskMem = Mauto | Mstatic | Mreg | Mtls | Mtype | Mextern,
-
- /* qualifiers */
- Qconst = iota(Kconst),
- Qrestr = iota(Krestrict),
- Qvoltl = iota(Kvolatile),
- Qatom = iota(Katomic),
-
- MaskQul = Qconst | Qrestr | Qvoltl | Qatom,
-
- Finlne = iota(Kinline),
- Fnoret = iota(Knoret),
-
- MaskFcn = Finlne | Fnoret,
-
- /* types */
- Tsign = iota(Ksigned),
- Tunsign = iota(Kunsigned),
-
- MaskSgn = Tsign | Tunsign,
-
- Tvoid = iota(Kvoid),
- Tfloat = iota(Kfloat),
- Tdouble = iota(Kdouble),
- Tcmplx = iota(Kcomplex),
- Timag = iota(Kimaginary),
-
- MaskFlt = Tfloat | Tdouble | Tcmplx | Timag,
-
- Tchar = iota(Kchar),
- Tbool = iota(Kbool),
-
- Tshort = iota(Kshort),
- Tint = iota(Kint),
- Tlong = iota(Klong),
- Tvlong = iota(Klong+1),
-
- MaskInt = Tshort | Tint | Tlong | Tvlong,
- MaskTyp = Tvoid | Tbool | Tchar | Tint | Tfloat | Timag | Tcmplx,
- /*
- * NOTE IMPORTANT: vlong takes over the struct bit place
- * DON'T MOVE KEYWORDS WITHOUT REORGANIZING
- */
- Tstruct = iota(Kstruct+1),
- Tunion = iota(Kunion+1),
- Tenum = iota(Kenum+1),
- Tname = iota(Kenum+2),
-
- Sbad = -1,
-};
-
-/* intermediate nodes */
-struct Ptr
-{
- uint64 kind;
- Ptr *link;
-};
-
-struct Name
-{
- uint32 kind;
- union {
- string ident;
- struct Dtor *paren;
- struct {
- Name *name;
- union {
- struct {
- uint32 q;
- Expr *x;
- } idx;
- struct {
- int n;
- int dots : 1;
- Field *arg;
- } call;
- };
- } sfx;
- };
-};
-
-struct Dtor
-{
- Ptr ptr;
- Name *name;
-};
-
-/* final ast node */
-
-struct Field
-{
- uint32 qual;
- uint32 type;
- string name;
-};
-
-struct Decls
-{
- string name;
- uint32 type;
- Expr *init;
- struct Decls *link;
-};
-
-
-struct Decl
-{
- struct Node;
- uint32 spec;
- union {
- struct {
- string name;
- uint32 type;
- union {
- Stmt *body;
- Expr *init;
- };
- };
- struct Decls list;
- };
-};
-
-enum
-{
- Tbad,
- Tbase,
- Tdef,
- Tptr,
- Tarray,
- Tfunc,
-};
-
-/* types */
-struct Type
-{
- uint32 kind;
- Sym *sym;
- uintptr size;
- uintptr max;
- uint16 align : 8;
- uint8 sign : 2;
- union {
- struct {
- uint32 qual;
- uint32 base;
- } ptr;
- struct {
- int len;
- uint32 qual;
- uint32 *elt;
- } arr;
- struct {
- int len;
- Field *f;
- Expr *x;
- } aggr;
- struct {
- int len;
- string *elt;
- Expr *val;
- } enm;
- struct {
- uint32 ret;
- int n;
- int dots : 1;
- Field *arg;
- } func;
- };
-};
-
-/* platform specific */
-extern Type pointer;
-extern Type basetypes[24];
-/* mandated by C standard */
-extern uint64 validtypespec[38];
-extern int indextypespec[38];
-
-struct Scope
-{
- SymTab tags;
- SymTab objs;
-};
-
-struct Parser
-{
- Token tok[2];
- struct {
- int cap;
- int len;
- Decl **decls;
- } ast;
-
- /* static buffers/stacks */
- Scope *sp;
- Scope spstk[40];
-
- Name *nm;
- Name nmstk[40];
-
- Ptr *pt;
- Ptr ptstk[10];
-
- Dtor *dt;
- Dtor dtstk[40];
-};
-
-/* ast.c functions */
-error parse(Parser *, Lexer *);
-
-// -----------------------------------------------------------------------
-// global compiler data
-
-struct StrTab
-{
- int32 n_buckets;
- int32 size;
- int32 n_occupied;
- int32 upper_bound;
- int32 *flags;
- string *keys;
- int32 *vals;
-};
-
-#if 0
-struct TypeSet
-{
- int32 n_buckets;
- int32 size;
- int32 n_occupied;
- int32 upper_bound;
- int32 *flags;
- Type **keys;
-};
-#endif
-
-/* main data */
-struct Compiler
-{
- mem·Arena *heap;
- StrTab strs;
- string outfile;
-
- struct {
- int cap;
- int len;
- string *val;
- } def;
-
- struct {
- int cap;
- int len;
- string *dir;
- } inc;
-
- struct {
- int cap;
- int len;
- Type *info;
- } type;
-
- /* TODO: make array */
- struct {
- Decl vargs;
- } builtin;
-};
-
-extern Compiler C;
-
-/* cc.c functions */
-void init();
-int32 intern(byte **str);
-int32 type();
-
-#undef iota
diff --git a/sys/cmd/cc/lex.c b/sys/cmd/cc/lex.c
deleted file mode 100644
index 33fc5d0..0000000
--- a/sys/cmd/cc/lex.c
+++ /dev/null
@@ -1,873 +0,0 @@
-#include "cc.h"
-#include <libn/macro/map.h>
-
-// -----------------------------------------------------------------------
-// printing functions
-
-void
-puttok(Token tok)
-{
- if (tok.kind < Alit)
- printf("%s", tokens[tok.kind]);
- else if (tok.kind & Alit) {
- if (tok.kind & Vchar)
- if (tok.kind & Vint)
- if (tok.kind & Vlong)
- if (tok.kind & Vvlong)
- printf("literal <%lld>", tok.val.i);
- if (tok.kind & Vfloat)
- printf("literal <%f>", tok.val.f);
- printf("literal <%s>", tok.val.s);
- } else
- printf("ident <%s>", tok.val.s);
-}
-
-// -----------------------------------------------------------------------
-// io buffer management
-
-#define asrdr(x) (io·Reader){(int (*)(void *, int, int, void *))x}
-
-// path should be absolute
-Io*
-openio(Lexer *lx, byte *path)
-{
- string *it, *end;
-
- intern(&path);
-
- // See if we have already opened file;
- // If so, and it hasn't been flagged return it
- for (it = lx->omit.path, end = it + lx->omit.len; it < end; ++it) {
- if ((uintptr)(*it) == (uintptr)(path))
- return nil;
- }
-
- // TODO: See if we have already loaded the file
-
- if ((lx->new - lx->iostk) >= arrlen(lx->iostk)-1)
- panicf("out of I/O space!");
-
- lx->new->f = io·open(path, "r");
- if (!lx->new->f)
- panicf("file %s not found", path);
-
- lx->new->kind = IOfile;
- lx->new->path = path;
- bufio·initreader(&lx->new->rdr, asrdr(io·read), lx->new->f);
-
- return lx->new++;
-}
-
-static
-Io*
-makeio(Lexer *lx, byte *name)
-{
- if ((lx->new - lx->iostk) >= arrlen(lx->iostk)-1)
- panicf("out of I/O space!");
-
- lx->new->path = name;
- lx->new->rdr = (io·Buffer) {
- .state = bufio·rdr | bufio·end,
- .runesize = 0,
- .h = nil,
- .size = bufio·size,
- .beg = lx->new->rdr.buf + bufio·ungets,
- .pos = lx->new->rdr.buf + bufio·ungets,
- .end = lx->new->rdr.buf + bufio·ungets,
- };
- lx->new->b = lx->new->rdr.beg;
-
- return lx->new++;
-}
-#undef asrdr
-
-static
-void
-freeio(Lexer *lx, Io *io)
-{
- if (io->kind & IOfile) {
- io·close(io->f);
- }
-
- io->rdr.state = 0;
- io->kind = 0;
- io->link = nil;
- io->path = nil;
- io->store = (Pos){ 0 };
- io->path = "<empty>";
-}
-
-void
-pushio(Lexer *lx, Io *new)
-{
- new->link = lx->io;
- lx->io->store = lx->pos;
- lx->io = new;
-
- lx->pos = (Pos){
- .line = 1,
- .col = 1,
- .path = new->path,
- };
-}
-
-void
-popio(Lexer *lx)
-{
- Io *prev;
-
- assert(lx->io == lx->new-1);
- --lx->new;
-
- prev = lx->io->link;
- freeio(lx, lx->io);
-
- lx->io = prev;
- if (!prev) {
- return;
- }
-
- lx->pos = prev->store;
-}
-
-// -----------------------------------------------------------------------
-// simple wrappers
-
-int
-getbyte(Lexer *lx)
-{
- return bufio·getbyte(&lx->io->rdr);
-}
-
-int
-getnsbyte(Lexer *lx)
-{
- int b;
- b = getbyte(lx);
- for (;;) {
- if (b == EOF) {
- if (lx->io->link) {
- popio(lx);
- assert(lx->io);
- b = getbyte(lx);
- continue;
- } else
- return b;
- }
- if (b >= RuneSelf || !isspace(b))
- return b;
- if (b == '\n')
- return b;
- b = getbyte(lx);
- }
- return b;
-}
-
-rune
-getrune(Lexer *lx)
-{
- return bufio·getrune(&lx->io->rdr);
-}
-
-byte
-ungetbyte(Lexer *lx)
-{
- byte b;
- return bufio·ungetbyte(&lx->io->rdr, b);
-}
-
-rune
-ungetrune(Lexer *l, rune r)
-{
- return bufio·ungetrune(&l->io->rdr, r);
-}
-
-// -----------------------------------------------------------------------
-// main lexer
-
-#define TOK(a, b) b,
-byte *tokens[NUM_TOKENS] = { TOKENS };
-#undef TOK
-
-static uint8 Atoi[256] =
-{
- ['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5,
- ['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9, ['a'] = 10, ['A'] = 10,
- ['b'] = 11, ['B'] = 11, ['c'] = 12, ['C'] = 12, ['d'] = 13, ['D'] = 13,
- ['e'] = 14, ['E'] = 14, ['f'] = 15, ['F'] = 15,
-};
-
-static
-error
-escapechar(Lexer *lx, int x, int islong, int esc, vlong *val)
-{
- int i, u, c;
- vlong l;
-
- c = getrune(lx);
-
- switch (c) {
- case '\\':
- break;
- case EOF:
- errorat(lx->pos, "EOF in string");
- return 1;
- case '\n':
- errorat(lx->pos, "newline in string");
- return 1;
- default:
- if (c == x)
- return 1;
- *val = c;
- return 0;
- }
-
- u = 0;
- c = getrune(lx);
-
- switch(c) {
- case 'x':
- i = islong ? 4 : 2;
- goto hex;
-
- case 'u':
- i = islong ? 8 : 4;
- u = 1;
- goto hex;
-
- case 'U':
- i = 8;
- u = 1;
- goto hex;
-
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- i = islong ? 4 : 2;
- goto oct;
-
- case 'a': c = '\a'; break;
- case 'b': c = '\b'; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case 'v': c = '\v'; break;
- case '\\':c = '\\'; break;
-
- default:
- if(c != x) errorat(lx->pos, "unknown escape sequence: %c", c);
- }
- *val = c;
- return 0;
-
-hex:
- l = 0;
- for(; i > 0; i--) {
- c = getbyte(lx);
- if (c >= '0' && c <= '9') {
- l = l*16 + c-'0';
- continue;
- }
- if (c >= 'a' && c <= 'f') {
- l = l*16 + c-'a' + 10;
- continue;
- }
- if (c >= 'A' && c <= 'F') {
- l = l*16 + c-'A' + 10;
- continue;
- }
- ungetbyte(lx);
- break;
- }
- if (u && (l > RuneMax || (0xd800 <= l && l < 0xe000))) {
- errorat(lx->pos, "invalid unicode code point in escape sequence: %#llx", l);
- l = RuneErr;
- }
- *val = l;
- if (esc)
- *val |= RuneMask + 1;
- return 0;
-
-oct:
- l = c - '0';
- for (; i > 0; i--) {
- c = getbyte(lx);
- if (c >= '0' && c <= '7') {
- l = l*8 + c-'0';
- continue;
- }
- ungetbyte(lx);
- break;
- }
- if (l > 255) errorat(lx->pos, "octal escape value > 255: %d", l);
-
- *val = l;
- if (esc)
- *val |= RuneMask + 1;
- return 0;
-}
-
-#define CASE1(stmt1, kind1) \
- case stmt1: \
- tok.kind = kind1; \
- goto Return
-
-#define CASE2(stmt1, kind1, b1, kind2) \
- case stmt1: \
- tok.kind = kind1; \
- b = getbyte(lx); \
- if (b == b1) \
- tok.kind = kind2; \
- else \
- ungetbyte(lx); \
- goto Return
-
-#define CASE3(stmt1, kind1, b1, kind2, b2, kind3) \
- case stmt1: \
- tok.kind = kind1; \
- b = getbyte(lx); \
- if (b == b1) \
- tok.kind = kind2; \
- else if (b == b2) \
- tok.kind = kind3; \
- else \
- ungetbyte(lx); \
- goto Return
-
-#define CASE4(stmt1, kind1, b1, kind2, b2, kind3, b3, type4) \
- case stmt1: \
- tok.kind = kind1; \
- b = getbyte(lx); \
- if (b == b1) \
- tok.kind = kind2; \
- else if (b == b2) \
- tok.kind = kind3; \
- else if (b == b3) \
- tok.kind = type4; \
- else \
- ungetbyte(lx); \
- goto Return
-
-
-Token
-lex(Lexer *lx)
-{
- int b, n, f;
- vlong v, _;
- rune r;
- string s;
- double d;
- byte *e;
- Token tok;
- Sym *sym;
- Io *io;
-
-GetByte:
- b = getbyte(lx);
-Dispatch:
- tok.pos = lx->pos;
-
- if ((b != EOF && b >= RuneSelf) || b == '_')
- goto Talpha;
- if (isalpha(b)) {
- if (b != 'L')
- goto Talpha;
-
- n = b;
- b = getbyte(lx);
- if (b == '\'') {
- if (escapechar(lx, '\'', 1, 0, &v))
- b = '\'';
- if (!escapechar(lx, '\'', 1, 0, &_)) {
- errorat(lx->pos, "missing ' at end of character constant");
- }
- tok.kind = Alit | Vrune;
- tok.val.r = v;
- goto Return;
- }
- if (b == '"')
- goto TLstr;
- ungetbyte(lx);
- b = n;
-
- goto Talpha;
- }
- if (isdigit(b))
- goto Tnum;
-
- switch (b) {
- case '\n':
- lx->pos.line++;
- case ' ': case '\r': case '\t': case '\v': case '\f':
- while (b = getbyte(lx), isspace(b))
- if (b == '\n')
- lx->pos.line++;
- goto Dispatch;
-
- case '\\':
- b = getbyte(lx);
- if (b != '\n')
- errorat(lx->pos, "'\\' without a trailing newline");
- goto GetByte;
-
- Tchar:
- case '\'':
- if (escapechar(lx, '\'', 0, 0, &v)) {
- errorat(lx->pos, "empty literal or escaped ' in char literal");
- v = '\'';
- }
- if (!escapechar(lx, '\'', 0, 0, &_)) {
- errorat(lx->pos, "missing '");
- ungetbyte(lx);
- }
-
- if (v > 0xff) {
- errorat(lx->pos, "overflowed character literal");
- v = 0;
- }
- tok.kind = Alit | Vchar;
- tok.val.c = v;
- goto Return;
-
- case '"':
- s = str·makecap("", 0, 8);
- for (;;) {
- if (escapechar(lx, '"', 0, 1, &v))
- break;
-
- if (v & (RuneMask + 1))
- str·appendbyte(&s, v);
- else {
- r = v;
- b = utf8·runelen(r);
- utf8·runetobyte(lx->buf, &r);
- str·appendlen(&s, b, lx->buf);
- }
- }
- tok.kind = Alit | Vstr;
- tok.val.s = s;
- intern(&tok.val.s);
-
- str·free(s);
- goto Return;
-
- TLstr:
- s = str·makecap("", 0, 8);
- // NOTE: this violates strict aliasing
- for (;;) {
- if (escapechar(lx, '"', 1, 0, &v))
- break;
- str·appendlen(&s, sizeof(wchar_t), (byte*)&v);
- }
- tok.kind = Alit | Vwstr;
- tok.val.s = s;
- intern(&tok.val.s);
-
- str·free(s);
- goto Return;
-
- case '.':
- tok.kind = Adot;
- b = getbyte(lx);
-
- if (isdigit(b)) {
- // *lx->b++ = b;
- goto Tflt;
- } else if (b == '.') {
- b = getbyte(lx);
- if (b != '.') {
- errorat(lx->pos, "invalid token '..'");
- tok.kind = Aellip;
- break;
- }
- }
- ungetbyte(lx);
- goto Return;
-
- case '<':
- tok.kind = Alt;
- b = getbyte(lx);
-
- if (b == '<') {
- tok.kind = Alsft;
- b = getbyte(lx);
- if (b == '=')
- tok.kind = Alsftasn;
- else
- ungetbyte(lx);
- } else if (b == '=')
- tok.kind = Alteq;
- else
- ungetbyte(lx);
- goto Return;
-
- case '>':
- tok.kind = Agt;
- b = getbyte(lx);
-
- if (b == '>') {
- tok.kind = Arsft;
- b = getbyte(lx);
- if (b == '=')
- tok.kind = Arsftasn;
- else
- ungetbyte(lx);
- } else if (b == '=')
- tok.kind = Agteq;
- else
- ungetbyte(lx);
- goto Return;
-
- case '/':
- tok.kind = Adiv;
- b = getbyte(lx);
-
- if (b == '=')
- tok.kind = Adivasn;
- else if (b == '/') {
- while (b != EOF && b != '\n')
- b = getbyte(lx);
- goto Dispatch;
- } else if (b == '*') {
- int level = 1;
- b = getbyte(lx);
- while (b != EOF && level > 0) {
- if (b == '/') {
- b = getbyte(lx);
- if (b == '*')
- level++;
- } else if (b == '*') {
- b = getbyte(lx);
- if (b == '/')
- level--;
- }
- if (b == '\n')
- lx->pos.line++;
- b = getbyte(lx);
- }
- goto Dispatch;
- } else
- ungetbyte(lx);
- goto Return;
-
- case '#':
- if (domacro(lx)) {
- tok.kind = Anil;
- errorat(lx->pos, "failed to perform preprocessor directive");
- return tok;
- }
- goto GetByte;
-
- case EOF:
- popio(lx);
- if (lx->io)
- goto GetByte;
- tok.kind = Aeof;
- goto Return;
-
- CASE1('(', Alparen);
- CASE1(')', Arparen);
- CASE1('{', Albrace);
- CASE1('}', Arbrace);
- CASE1('[', Albrakt);
- CASE1(']', Arbrakt);
- CASE1(',', Acomma);
- CASE1('?', Aqmark);
- CASE1(';', Asemi);
- CASE1('~', Aneg);
- CASE1(':', Acolon);
- CASE2('^', Axor, '=', Axorasn);
- CASE2('!', Anot, '=', Aneq);
- CASE2('*', Astar,'=', Amulasn);
- CASE2('=', Aasn, '=', Aeq);
- CASE2('%', Amod, '=', Amodasn);
- CASE3('+', Aadd, '=', Aaddasn, '+', Ainc);
- CASE3('&', Aand, '=', Aandasn, '&', Aandand);
- CASE3('|', Aor, '=', Aorasn, '|', Aoror);
- CASE4('-', Asub, '=', Asubasn, '-', Adec, '>', Aarrow);
-
- Tnum:
- e = lx->buf + arrlen(lx->buf);
- do {
- if (lx->b >= e) {
- errorat(lx->pos, "number overflows lexer buffer");
- goto Nospace;
- }
- *lx->b++ = b;
- } while (b = getbyte(lx), isdigit(b) || b == '_');
-
- if (b == '.' || tolower(b) == 'e')
- goto Tflt;
- Tint:
- n = 10;
- s = lx->buf;
- if (*s == '0') {
- switch (b) {
- case 'x': n = 16; break;
- case 'b': n = 2; break;
- case 'o': n = 8; break;
- default: goto Rint;
- }
- lx->b = s;
- /* reparse number, now with base info */
- while (b = getbyte(lx), (isdigit(b) ||
- ('a' <= b && b <= 'f') ||
- ('A' <= b && b <= 'F') ||
- b == '_'))
- *lx->b++ = b;
- }
- Rint:
- v = 0;
- r = b;
- for (; s != lx->b ; s++) {
- b = *s;
- if (b == '_') continue;
-
- f = Atoi[b];
- if (f == 0 && b != '0')
- break;
-
- if (f >= n) {
- errorat(lx->pos, "digit '%c' out of range for base %d", b, n);
- f = 0;
- }
-
- if (v > (UINT64_MAX - f) / n) {
- errorat(lx->pos, "integer literal overflow");
- v = 0;
- break;
- }
-
- v = v * n + f;
- }
-
- b = r;
- tok.kind = Alit;
- tok.val.i = v;
-
- if (b == 'u' || b == 'U') {
- tok.kind |= Vun;
- b = getbyte(lx);
- }
- if (b == 'l' || b == 'L') {
- r = getbyte(lx);
- if (r == 'l' || r == 'L') {
- if (r != b)
- errorat(lx->pos, "mismatched case on long long integer suffix");
- tok.kind |= Vvlong;
- r = getbyte(lx);
- } else
- tok.kind |= Vlong;
-
- if (r == 'u' || r == 'U') {
- if (tok.kind & Vun)
- errorat(lx->pos, "multiple unsigned designators on integer suffix");
- tok.kind |= Vun;
- goto Return;
- }
-
- ungetbyte(lx);
- goto Return;
- }
-
- tok.kind |= Vint;
- ungetbyte(lx);
- goto Return;
-
- Tflt:
- if (b == '.') {
- *lx->b++ = b;
- b = getbyte(lx);
- }
-
- while (isdigit(b)) {
- *lx->b++ = b;
-
- if (lx->b >= e) {
- errorat(lx->pos, "number overflows lexer buffer");
- goto Nospace;
- }
- }
-
- if (tolower(b) == 'e') {
- b = getbyte(lx);
- if (b == '-' || b == '+')
- b = getbyte(lx);
-
- if (!isdigit(b))
- errorat(lx->pos, "expected number after exponent, found %c", b);
-
- do {
- *lx->b++ = b;
- } while (b = getbyte(lx), isdigit(b));
- }
- *lx->b = '\0';
- d = strtod(lx->buf, nil);
- ungetbyte(lx);
-
- tok.kind = Alit | Vfloat;
- tok.val.f = d;
-
- goto Return;
-
- Talpha:
- s = lx->buf;
- e = lx->buf + arrlen(lx->buf);
- for (;;) {
- if (s >= e) {
- errorat(lx->pos, "identifier too long for buffer: %s", s);
- goto Nospace;
- }
- if (b != EOF && b >= RuneSelf) {
- ungetbyte(lx);
- r = getrune(lx);
- if (!utf8·isletter(r) && !utf8·isdigit(r) && r != 0xb7) {
- errorat(lx->pos, "invalid identifier character %d", r);
- }
- s += utf8·runetobyte(s, &r);
- } else if (!isalnum(b) && b != '_')
- break;
- else
- *s++ = b;
- b = getbyte(lx);
- }
- *s = '\0';
- ungetbyte(lx);
-
- tok.kind = Aident;
- tok.val.s = lx->buf;
-
- n = intern(&tok.val.s);
- if (n < arrlen(keywords)) {
- tok.kind = Akeywd;
- tok.val.i = n;
- goto Return;
- }
-
- sym = lookup(&lx->sym, tok.val.s);
- if (sym && ((uintptr)sym->name != (uintptr)lx->io->path)) {
- if ((uintptr)sym == lx->macline) {
- tok.kind = Alit | Vint;
- tok.val.i = lx->pos.line;
- goto Return;
- }
- if ((uintptr)sym == lx->macfile) {
- tok.kind = Alit | Vstr;
- tok.val.s = lx->pos.path;
- goto Return;
- }
- io = makeio(lx, sym->name);
- io->rdr.end += expandmacro(lx, sym, io->b);
- printf("EXPANDED %s: %s\n", sym->name, io->rdr.beg);
- *io->rdr.end++ = EOF;
- pushio(lx, io);
- goto GetByte;
- }
- goto Return;
-
- default:
- tok.kind = Anil;
- errorat(lx->pos, "invalid token, crashing");
- abort();
- }
-
-Return:
- lx->b = lx->buf;
- return tok;
-
-Nospace:
- panicf("aborting compilation");
- exit(1);
-}
-
-#undef CASE4
-#undef CASE3
-#undef CASE2
-#undef CASE1
-
-// -----------------------------------------------------------------------
-// symbol tables
-
-#define PTR_HASH(p) (uintptr)(p)
-#define PTR_EQUAL(p1, p2) ((uintptr)(p1) == (uintptr)(p2))
-
-static
-void
-·free(void* _, void* ptr) {
- return free(ptr);
-}
-
-static
-void *
-·alloc(void* _, uint n, ulong size) {
- return malloc(n*size);
-}
-
-static
-void *
-·calloc(void* _, uint n, ulong size) {
- return calloc(n, size);
-}
-
-static
-int
-moresymtab(SymTab *tab, int n)
-{
- MAP_GROW(tab, string, Sym*, n, PTR_HASH, sys·Memory, nil);
-}
-
-static
-int
-putsym(SymTab *tab, Sym *sym, error *err)
-{
- MAP_PUT(tab, sym->name, sym, PTR_HASH, PTR_EQUAL, moresymtab, err);
-}
-
-Sym*
-define(SymTab *tab, string name, uint32 kind)
-{
- int i;
- Sym *sym;
- error err;
-
- sym = mem·arenaalloc(C.heap, 1, sizeof(*sym));
- sym->name = name;
- sym->kind = kind;
-
- i = putsym(tab, sym, &err);
- tab->vals[i] = sym;
-
- return sym;
-}
-
-Sym*
-lookup(SymTab *tab, string ident)
-{
- int idx;
- MAP_GET(idx, tab, ident, PTR_HASH, PTR_EQUAL);
-
- if (idx < tab->n_buckets)
- return tab->vals[idx];
-
- return nil;
-}
-
-
-error
-forget(SymTab *tab, string ident)
-{
- int idx;
- MAP_GET(idx, tab, ident, PTR_HASH, PTR_EQUAL);
-
- if (idx < tab->n_buckets) {
- MAP_DEL(tab, idx);
- return 0;
- }
- return 1;
-}
-
-void
-forgetall(SymTab *tab)
-{
- MAP_RESET(tab);
-}
diff --git a/sys/cmd/cc/pp.c b/sys/cmd/cc/pp.c
deleted file mode 100644
index 57c3501..0000000
--- a/sys/cmd/cc/pp.c
+++ /dev/null
@@ -1,1125 +0,0 @@
-#include "cc.h"
-
-// -----------------------------------------------------------------------
-// helper functions
-
-static
-void
-pushomit(Lexer *lx, string omit)
-{
- if (lx->omit.len == lx->omit.cap) {
- lx->omit.cap += 20;
- lx->omit.path = realloc(lx->omit.path, lx->omit.cap*sizeof(*lx->omit.path));
- }
- lx->omit.path[lx->omit.len++] = omit;
-}
-
-// NOTE: The iterator of lexer lx->b IS NOT reset.
-// Its the caller's responsibility.
-static
-string
-ident(Lexer *lx)
-{
- int b;
- byte *s;
-
- b = getnsbyte(lx);
- if (!isalpha(b) && b != '_' && b < RuneSelf) {
- ungetbyte(lx);
- return "";
- }
-
- s = lx->b;
- for (;;) {
- *lx->b++ = b;
- b = getbyte(lx);
- if (isalnum(b) || b == '_' || b >= RuneSelf)
- continue;
- ungetbyte(lx);
- break;
- }
- *lx->b++ = '\0';
-
- return s;
-}
-
-static
-string
-identdots(Lexer *lx, int *dots)
-{
- int c;
- byte *s;
-
- s = ident(lx);
- if (*s != '\0')
- return s;
-
- c = getnsbyte(lx);
- if (c != '.') {
- ungetbyte(lx);
- return s;
- }
-
- if (getbyte(lx) != '.' || getbyte(lx) != '.')
- errorat(lx->pos, "incorrect '...' token in macro");
-
- *dots = 1;
- // TODO: should only run intern once...
- s = "__VA_ARGS__";
- intern(&s);
- return s;
-}
-
-static
-Sym*
-defmacro(Lexer *lx, string name, string macro)
-{
- Sym *mac;
-
- // printf("DEFINING MACRO %s ON LINE %d, file %s\n", name, lx->pos.line, os·basename(lx->pos.path));
- mac = define(&lx->sym, name, Smacro);
- mac->macro = macro;
-
- return mac;
-}
-
-static vlong evalmacro(Lexer *lx, byte prec);
-
-static
-vlong
-opand(Lexer *lx)
-{
- int b;
- vlong v;
- string s;
- Token tok;
- Sym *sym;
-
- b = getnsbyte(lx);
- if (b == '\n') {
- errorat(lx->pos, "new line in macro expression");
- return 0;
- }
- ungetbyte(lx);
-
- tok = lex(lx);
-
- switch (tok.kind & Vmask) {
- case Aneg:
- return ~opand(lx);
-
- case Anot:
- return !opand(lx);
-
- case Alparen:
- v = evalmacro(lx, 1);
- tok = lex(lx);
- if (!(tok.kind & Arparen)) {
- errorat(lx->pos, "unbalanced parenthesis in macro expression");
- return 0;
- }
- return v;
-
- case Alit:
- switch (tok.kind & ~Vmask) {
- case Vint: case Vlong: case Vvlong:
- return tok.val.i;
- case Vun|Vint : case Vun|Vlong : case Vun|Vvlong:
- return tok.val.ui;
- case Vrune:
- return tok.val.r;
- case Vchar:
- return tok.val.c;
- default:
- errorat(lx->pos, "invalid literal of type '%s' in conditional macro", tokens[tok.kind & ~Vmask]);
- return 0;
- }
-
- case Aident:
- sym = lookup(&lx->sym, tok.val.s);
- if (!sym) {
- /* calling lex directly would expand the operand here
- * manually lex the result
- */
- if (strcmp(tok.val.s, "defined") == 0) {
- b = getnsbyte(lx);
- if (b == '\n') {
- errorat(lx->pos, "new line in defined operand");
- return 0;
- }
- s = lx->buf;
- if (b == '(') {
- b = getnsbyte(lx);
- while (b != ')') {
- if (b == '\n') {
- errorat(lx->pos, "new line inside defined operand");
- return 0;
- }
- if (b == '(') {
- errorat(lx->pos, "nested parens not allowed inside defined operator");
- return 0;
- }
- if (!isspace(b))
- *s++ = b;
- b = getbyte(lx);
- }
- } else {
- while (!isspace(b)) {
- *s++ = b;
- b = getbyte(lx);
-
- if (b == '\n') {
- errorat(lx->pos, "new line inside defined operand");
- return 0;
- }
- }
- }
- *s = '\0';
- s = lx->buf;
- intern(&s);
- return lookup(&lx->sym, s) != nil;
- }
- return 0;
- }
- panicf("unreachable");
- return 1;
-
- default:
- errorat(lx->pos, "opand: invalid token found in macro conditional: '%s'", tokens[tok.kind & Vmask]);
- return 0;
- }
-}
-
-// recursively evaluates a macro
-// reduced set of operators allowed here
-static
-vlong
-evalmacro(Lexer *lx, byte prec)
-{
- int b;
- vlong l, r;
- Token tok;
-
- l = opand(lx);
- for (;;) {
- b = getnsbyte(lx);
- // NOTE: Either this or we pass in what are stopping byte is
- // New line should always stop us...
- // Is there any case where we SHOULDN'T STOP ON ')'?
- if (b == '\n' || b == ')') {
- ungetbyte(lx);
- break;
- }
- ungetbyte(lx);
-
- tok = lex(lx);
- // simplified jump table of precedence
- // unpacked to evaluate inline
- switch (tok.kind & Vmask) {
- case Astar:
- if (prec > 10) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 10 + 1);
- l = l * r;
- continue;
-
- case Adiv:
- if (prec > 10) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 10 + 1);
- l = l / r;
- continue;
-
- case Amod:
- if (prec > 10) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 10 + 1);
- l = l % r;
- continue;
-
- case Aadd:
- if (prec > 9) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 9 + 1);
- l = l + r;
- continue;
-
- case Asub:
- if (prec > 9) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 9 + 1);
- l = l - r;
- continue;
-
- case Alsft:
- if (prec > 8) {
- ungetbyte(lx);
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 8 + 1);
- l = l << r;
- continue;
-
- case Arsft:
- if (prec > 8) {
- ungetbyte(lx);
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 8 + 1);
- l = l >> r;
- continue;
-
- case Alt:
- if (prec > 7) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 7 + 1);
- l = l < r;
- continue;
-
- case Agt:
- if (prec > 7) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 7 + 1);
- l = l > r;
- continue;
-
- case Agteq:
- if (prec > 7) {
- ungetbyte(lx);
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 7 + 1);
- l = l >= r;
- continue;
-
- case Alteq:
- if (prec > 7) {
- ungetbyte(lx);
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 7 + 1);
- l = l >= r;
- continue;
-
- case Aeq:
- if (prec > 6) {
- ungetbyte(lx);
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 6 + 1);
- l = l == r;
- continue;
-
- case Aneq:
- if (prec > 6) {
- ungetbyte(lx);
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 6 + 1);
- l = l != r;
- continue;
-
- case Aand:
- if (prec > 5) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 5 + 1);
- l = l & r;
- continue;
-
- case Axor:
- if (prec > 4) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 4 + 1);
- l = l ^ r;
- continue;
-
- case Aor:
- if (prec > 3) {
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 3 + 1);
- l = l | r;
- continue;
-
- case Aandand:
- if (prec > 2) {
- ungetbyte(lx);
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 2 + 1);
- l = l && r;
- continue;
-
- case Aoror:
- if (prec > 1) {
- ungetbyte(lx);
- ungetbyte(lx);
- return l;
- }
- r = evalmacro(lx, 1 + 1);
- l = l || r;
- continue;
-
- default:
- errorat(lx->pos, "eval: invalid token found in macro conditional '%s'", tokens[tok.kind & Vmask]);
- abort();
- return 0;
- }
- }
-
- return l;
-}
-
-// -----------------------------------------------------------------------
-// preprocessor magic numbers
-
-enum
-{
- PPbeg = 0x02,
- PParg = 0x03,
- PPcat = 0x04,
- PPstr = 0x05,
-
- PPnarg = 30,
-};
-
-#define PPvar 0x80u
-
-// -----------------------------------------------------------------------
-// preprocessor functions
-
-/* #endif */
-static
-error
-ppend(Lexer *lx)
-{
- int b;
- do {
- b = getnsbyte(lx);
- } while (b > 0 && b != '\n');
-
- if (b == '\n')
- lx->pos.line++;
-
- return 0;
-}
-
-
-/* #undef */
-static
-error
-ppund(Lexer *lx)
-{
- string s;
- error err;
-
- s = ident(lx);
- intern(&s);
- lx->b = lx->buf;
-
- err = forget(&lx->sym, s);
- if (err)
- warnat(lx->pos, "attempting to undefine unrecognized symbol '%s'", s);
-
- ppend(lx);
- return 0;
-}
-
-/* #define */
-static
-error
-ppdef(Lexer *lx)
-{
- int b;
- Sym *sym;
- int i, j, n, dot;
- string s, a, base, end, buf, args[PPnarg];
-
- s = ident(lx);
- if (!s) {
- errorat(lx->pos, "failed to parse defined identifer");
- goto Bad;
- }
- intern(&s);
- printf("DEFINING %s\n", s);
- lx->b = lx->buf;
-
- sym = lookup(&lx->sym, s);
- if (sym)
- warnat(lx->pos, "macro redefined: '%s'", sym->name);
-
- n = 0;
- dot = 0;
- b = getbyte(lx);
- if (b == '(') {
- b = getnsbyte(lx);
- if (b != ')') {
- ungetbyte(lx);
- for (;;) {
- // NOTE: This is a pointer into the lx->buffer.
- // Can't reset lx->b while we hold the args!
- a = identdots(lx, &dot);
- if (a == nil) {
- errorat(lx->pos, "macro syntax error: improper argument");
- goto Bad;
- }
- if (n >= PPnarg) {
- errorat(lx->pos, "macro syntax error: too many arguments: %d > %d", n, PPnarg);
- goto Bad;
- }
-
- args[n++] = a;
- b = getnsbyte(lx);
-
- if (b == ')')
- break;
- if (b != ',') {
- errorat(lx->pos, "macro syntax error: bad token in argument '%b'", b);
- goto Bad;
- }
- }
- }
- b = getbyte(lx);
- }
-
- if (isspace(b))
- if (b != '\n')
- b = getnsbyte(lx);
-
- base = lx->b;
- end = lx->buf + arrlen(lx->buf);
- if (base >= end) {
- errorat(lx->pos, "out of macro buffer space!");
- goto Bad;
- }
- buf = str·makef("%c%c", n, PPbeg);
- for (;;) {
- if (isalpha(b) || b == '_') {
- lx->b = base;
- *lx->b++ = b;
-
- b = getbyte(lx);
- while (isalnum(b) || b == '_') {
- *lx->b++ = b;
- if (lx->b >= end) {
- errorat(lx->pos, "out of macro buffer space!");
- goto Bad;
- }
- b = getbyte(lx);
- }
- *lx->b++ = '\0';
-
- for (i = 0; i < n; i++) {
- if (strcmp(base, args[i]) == 0) {
- goto Arg;
- }
- }
- str·appendlen(&buf, (lx->b - base - 1), base);
- continue;
- Arg:
- str·appendbyte(&buf, PParg);
- str·appendbyte(&buf, 'a' + i);
- continue;
- }
-
- if (b == '/') {
- b = getbyte(lx);
- if (b == '/') {
- while (b = getbyte(lx), b != '\n');
- continue;
- }
- if (b == '*') {
- b = getbyte(lx);
- for (;;) {
- if (b == '*') {
- b = getbyte(lx);
- if (b != '/')
- continue;
- b = getbyte(lx);
- break;
- }
- if (b == '\n') {
- errorat(lx->pos, "comment and newline found in define statement of %s", s);
- break;
- }
- b = getbyte(lx);
- }
- continue;
- }
- str·appendbyte(&buf, '/');
- continue;
- }
-
- if (b == '\\') {
- b = getbyte(lx);
- /* unix */
- if (b == '\n') {
- lx->pos.line++;
- b = getbyte(lx);
- continue;
- }
- /* windows */
- if (b == '\r') {
- b = getbyte(lx);
- if (b == '\n') {
- lx->pos.line++;
- b = getbyte(lx);
- continue;
- }
- }
- str·appendbyte(&buf, '\\');
- }
- if (b == '\n') {
- lx->pos.line++;
- break;
- }
-
- if (b == '#') {
- b = getnsbyte(lx);
- if (b == '#') {
- str·appendbyte(&buf, PPcat);
- b = getbyte(lx);
- continue;
- }
-
- lx->b = base;
- while (isalnum(b) || b == '_') {
- *lx->b++ = b;
- b = getbyte(lx);
- }
- *lx->b = '\0';
-
- for (i = 0; i < n; i++) {
- if (strcmp(base, args[i]) == 0)
- goto Str;
- }
- errorat(lx->pos, "macro operator '#' must be followed by a valid variable identifier");
- goto Bad;
- Str:
- str·appendbyte(&buf, PPstr);
- str·appendbyte(&buf, 'a' + i);
- continue;
- }
-
- str·appendbyte(&buf, b);
- b = getbyte(lx);
- if (b == EOF) {
- errorat(lx->pos, "eof found in macro '%s'", s);
- goto Bad;
- }
- }
- if (dot)
- *buf |= PPvar;
-
- lx->b = lx->buf;
- sym = defmacro(lx, s, buf);
- return 0;
-Bad:
- errorat(lx->pos, "failed parse of #define macro '%s'", s);
- lx->b = lx->buf;
- ppend(lx);
- return 1;
-}
-
-/* macro expansion */
-int
-expandmacro(Lexer *lx, Sym *s, byte *dst)
-{
- int n, lv, nargs, dots;
- byte b, *it, *e, *arg[PPnarg];
-
- /* not a function macro */
- if (s->macro[0] == '\0') {
- if (s->macro[1] != PPbeg) {
- errorat(lx->pos, "malformed macro");
- goto Bad;
- }
- strcpy(dst, s->macro + 2);
- return str·len(s->macro)-2;
- }
- dots = (ubyte)s->macro[0] & PPvar;
- nargs = (ubyte)s->macro[0] & (~PPvar);
-
- b = getnsbyte(lx);
- if (b != '(') {
- errorat(lx->pos, "macro function not given arguments");
- goto Bad;
- }
-
- n = 0;
- b = getbyte(lx);
- if (b != ')') {
- ungetbyte(lx);
- lv = 0;
- lx->b = lx->buf;
- e = lx->buf + arrlen(lx->buf) - 4;
- arg[n++] = lx->buf;
- for (;;) {
- if (lx->b >= e)
- goto Nospace;
- b = getbyte(lx);
- if (b == '"')
- for (;;) {
- if (lx->b >= e)
- goto Nospace;
- *lx->b++ = b;
- b = getbyte(lx);
- if (b == '\\') {
- *lx->b++ = b;
- b = getbyte(lx);
- continue;
- }
- if (b == '\n') {
- errorat(lx->pos, "newline found in arguments: macro '%s'", s->name);
- goto Bad;
- }
- if (b == '"')
- break;
- }
- if (b == '\'')
- for (;;) {
- if (lx->b >= e)
- goto Nospace;
- *lx->b++ = b;
- b = getbyte(lx);
- if (b == '\\') {
- *lx->b++ = b;
- b = getbyte(lx);
- continue;
- }
- if (b == '\n') {
- errorat(lx->pos, "newline found in arguments: macro '%s'", s->name);
- goto Bad;
- }
- if (b == '"')
- break;
- }
- if (b == '/') {
- b = getbyte(lx);
- switch(b) {
- case '*':
- for (;;) {
- b = getbyte(lx);
- if (b == '*') {
- b = getbyte(lx);
- if (b == '/')
- break;
- }
- }
- *lx->b++ = ' ';
- continue;
- case '/':
- while ((b = getbyte(lx)) != '\n')
- ;
- break;
-
- default:
- ungetbyte(lx);
- b = '/';
- }
- }
- if (lv == 0) {
- if (b == ',') {
- if (n == nargs && dots) {
- *lx->b++ = ',';
- continue;
- }
- *lx->b++ = '\0';
- arg[n++] = lx->b;
- if (n > nargs)
- break;
- continue;
- }
- if (b == ')')
- break;
- }
- if (b == '\n')
- b = ' ';
- *lx->b++ = b;
- if (b == '(')
- lv++;
- if (b == ')')
- lv--;
- }
- *lx->b = '\0';
- }
-
- if (n != nargs) {
- errorat(lx->pos, "number of arguments don't match macro definition: %s", s->name);
- *dst = '\0';
- goto Bad;
- }
-
- if (s->macro[1] != PPbeg) {
- errorat(lx->pos, "corrupted macro buffer: %s", s->name);
- *dst = '\0';
- goto Bad;
- }
-
- it = s->macro+2;
- e = dst;
- for (;;) {
- b = *it++;
- if (b == '\n')
- b = ' ';
- switch (b) {
- case PParg:
- b = *it++;
- b -= 'a';
- if (b < 0 && b > n) {
- errorat(lx->pos, "malformed macro index: %s", s->name);
- goto Bad;
- }
- strcpy(dst, arg[b]);
- dst += strlen(arg[b]);
-
- break;
-
- case PPstr:
- b = *it++;
- b -= 'a';
- if (b < 0 && b > n) {
- errorat(lx->pos, "malformed macro index: %s", s->name);
- goto Bad;
- }
- *dst++ = '"';
- strcpy(dst, arg[b]);
- *dst++ = '"';
-
- break;
-
- case PPcat:
- continue;
-
- case '\0':
- goto End;
-
- default:
- *dst++ = b;
- continue;
- }
- }
-End:
- *dst = '\0';
- return dst - e;
-Nospace:
- errorat(lx->pos, "out of memory during macro expansion %s", s->name);
-Bad:
- ppend(lx);
- lx->b = lx->buf;
- errorat(lx->pos, "failed to expand macro %s", s->name);
- return -1;
-}
-
-/* #include */
-static
-error
-ppinc(Lexer *lx)
-{
- int i;
- byte b, end;
- string s;
-
- Stream *f;
- Io *io;
-
- b = getnsbyte(lx);
- if (b != '"') {
- end = b;
- if (b != '<') {
- errorat(lx->pos, "unrecognized token '%c' in include directive", b);
- goto Bad;
- }
- end = '>';
- } else
- end = '"';
-
- lx->b = lx->buf;
- for (;;) {
- b = getbyte(lx);
- if (b == end)
- break;
- if (b == '\n') {
- errorat(lx->pos, "hit end of line before include directive completed");
- goto Bad;
- }
- *lx->b++ = b;
- }
- *lx->b = '\0';
- s = lx->buf;
- intern(&s); // NOTE: we could use this to see if we already have the file
-
- lx->b = lx->buf;
- for (i = 0; i < C.inc.len; i++) {
- if (i == 0 && end == '>')
- continue;
-
- strcpy(lx->buf, C.inc.dir[i]);
- strcat(lx->buf, "/");
-
- if (strcmp(lx->buf, "./") == 0)
- lx->buf[0] = '\0';
- strcat(lx->buf, s);
-
- if (os·exists(lx->buf, ReadOK)) {
- break;
- }
- }
- if (i == C.inc.len) {
- errorat(lx->pos, "could not find file '%s' on standard include search path", s);
- goto Bad;
- }
-
- io = openio(lx, lx->buf);
- if (io != nil) {
- pushio(lx, io);
- }
-
- return 0;
-
-Bad:
- ungetbyte(lx);
- lx->b = lx->buf;
- errorat(lx->pos, "failed include");
- ppend(lx);
- return 1;
-}
-
-/* #pragma */
-static
-error
-ppprag(Lexer *lx)
-{
- string s;
-
- s = ident(lx);
- if (s == nil) {
- errorat(lx->pos, "failed to parse pragma identifier");
- goto Bad;
- }
- lx->b = lx->buf;
- if (strcmp(s, "once") == 0) {
- pushomit(lx, lx->io->path);
- return 0;
- }
-Bad:
- lx->b = lx->buf;
- errorat(lx->pos, "unrecognized pragma '%s'", s);
- ppend(lx);
- return 1;
-}
-
-/* all #if statements */
-static
-error
-ppif(Lexer *lx, int f)
-{
- Sym *sym;
- string s;
- int c, l, b;
-
-Eval:
- if (f == 0) {
- b = evalmacro(lx, 1);
- if (b) {
- ppend(lx);
- return 0;
- }
- goto Skip;
- }
-
- if (f == 1)
- goto Skip;
-
- s = ident(lx);
- if (s == nil) {
- errorat(lx->pos, "failed to parse preprocessor identifier");
- goto Bad;
- }
- intern(&s);
- lx->b = lx->buf;
-
- sym = lookup(&lx->sym, s);
- if ((!sym && (f == 3)) || (sym && (f == 2)))
- return 0;
-
-Skip:
- b = 1;
- l = 0;
- for (;;) {
- c = getbyte(lx);
- if (c != '#') {
- if (!isspace(c))
- b = 0;
- if (c == '\n') {
- lx->pos.line++;
- b = 1;
- }
- if (c == EOF) {
- errorat(lx->pos, "EOF hit while skipping if block. Missing endif");
- goto Bad;
- }
- continue;
- }
- if (!b)
- continue;
- s = ident(lx);
- lx->b = lx->buf;
- if (!s)
- continue;
-
- if (l == 0 && (strcmp(s, "elif") == 0)) {
- f = 0;
- goto Eval;
- }
-
- if (strcmp(s, "endif") == 0) {
- if (l) {
- l--;
- continue;
- }
- ppend(lx);
- return 0;
- }
- if (strcmp(s, "if") == 0 ||
- strcmp(s, "ifdef") == 0 ||
- strcmp(s, "ifndef") == 0) {
- l++;
- continue;
- }
-
- if (l == 0 && f != 1 && strcmp(s, "else") == 0) {
- return 0;
- }
- }
-
-Bad:
- lx->b = lx->buf;
- errorat(lx->pos, "bad syntax in preprocessor conditional directive");
- ppend(lx);
- return 1;
-}
-
-/* #if */
-static
-error
-ppif0(Lexer *lx)
-{
- return ppif(lx, 0);
-}
-
-/* #else */
-static
-error
-ppif1(Lexer *lx)
-{
- return ppif(lx, 1);
-}
-
-/* #ifdef */
-static
-error
-ppif2(Lexer *lx)
-{
- return ppif(lx, 2);
-}
-
-/* #ifndef */
-static
-error
-ppif3(Lexer *lx)
-{
- return ppif(lx, 3);
-}
-
-// -----------------------------------------------------------------------
-// dispatch function
-
-#define DIRECTIVE(a, b, c) c,
-error (*macros[NUM_DIRECTIVES])(Lexer*) = { DIRECTIVES };
-#undef DIRECTIVE
-
-/* reads an identifier into the lexer's buffer */
-/* caller must intern */
-
-error
-domacro(Lexer *lx)
-{
- int n;
- error err;
- string s;
-
- s = ident(lx);
- intern(&s);
- lx->b = lx->buf;
- for (n = 0; n < NUM_DIRECTIVES; n++) {
- if ((uintptr)s == (uintptr)directives[n]) {
- goto Do;
- }
- }
- errorat(lx->pos, "unrecognized directive name '%s'", s);
- return 1;
-Do:
- err = macros[n](lx);
- return err;
-}
-
-error
-dodefine(Lexer *lx, string s)
-{
- int n;
- byte *c, *def;
- Sym *sym;
-
- strcpy(lx->buf, s);
- c = strchr(lx->buf, '=');
- if (c) {
- *c++ = '\0';
- sym = lookup(&lx->sym, lx->buf);
- if (sym) {
- errorf("redefinition of symbol '%s'", sym->name);
- return 1;
- }
- sym = define(&lx->sym, lx->buf, Smacro);
- n = strlen(c) + 2;
- sym->macro = str·makelen("", n);
- str·appendbyte(&sym->macro, '\0');
- str·append(&sym->macro, c);
- } else {
- sym = lookup(&lx->sym, lx->buf);
- if (sym) {
- errorf("redefinition of symbol '%s'", sym->name);
- return 1;
- }
- sym = define(&lx->sym, s, Smacro);
- sym->macro = "\00\02";
- }
-
- return 0;
-}
diff --git a/sys/cmd/cc/rules.mk b/sys/cmd/cc/rules.mk
deleted file mode 100644
index 34df34d..0000000
--- a/sys/cmd/cc/rules.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-include share/push.mk
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := \
- $(d)/pp.c \
- $(d)/lex.c \
- $(d)/ast.c \
- $(d)/bits.c \
- $(d)/cc.c
-
-
-LIBS_$(d) :=
-BINS_$(d) := $(d)/cc
-UNTS_$(d) :=
-
-include share/paths.mk
-
-# Local rules
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/libn/libn.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/cc/scratch.c b/sys/cmd/cc/scratch.c
deleted file mode 100644
index b37d9a5..0000000
--- a/sys/cmd/cc/scratch.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#define XXX(a, b, c) a ## b ## c
-
-int
-main()
-{
- XXX(d, e, f);
-}
diff --git a/sys/cmd/cc/util.c b/sys/cmd/cc/util.c
deleted file mode 100644
index cca16f2..0000000
--- a/sys/cmd/cc/util.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "cc.h"
-
-void
-·free(void* _, void* ptr) {
- return free(ptr);
-}
-
-void *
-·alloc(void* _, uint n, ulong size) {
- return malloc(n*size);
-}
-
-void *
-·calloc(void* _, uint n, ulong size) {
- return calloc(n, size);
-}
-
-void *
-·realloc(void* _, void *ptr, uint n, ulong size) {
- return realloc(ptr, n*size);
-}
diff --git a/sys/cmd/dwm/LICENSE b/sys/cmd/dwm/LICENSE
deleted file mode 100644
index d221f09..0000000
--- a/sys/cmd/dwm/LICENSE
+++ /dev/null
@@ -1,37 +0,0 @@
-MIT/X Consortium License
-
-© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
-© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
-© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
-© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com>
-© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com>
-© 2007-2009 Christof Musik <christof at sendfax dot de>
-© 2007-2009 Premysl Hruby <dfenze at gmail dot com>
-© 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
-© 2008 Martin Hurton <martin dot hurton at gmail dot com>
-© 2008 Neale Pickett <neale dot woozle dot org>
-© 2009 Mate Nagy <mnagy at port70 dot net>
-© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
-© 2010-2012 Connor Lane Smith <cls@lubutu.com>
-© 2011 Christoph Lohmann <20h@r-36.net>
-© 2015-2016 Quentin Rameau <quinq@fifth.space>
-© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
-© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/sys/cmd/dwm/client.c b/sys/cmd/dwm/client.c
deleted file mode 100644
index fa04f5f..0000000
--- a/sys/cmd/dwm/client.c
+++ /dev/null
@@ -1,657 +0,0 @@
-#include "dwm.h"
-
-void
-applyrules(Client *c)
-{
- char *class, *instance;
- uint i;
- Rule *r;
- Monitor *m;
- XClassHint ch = { nil, nil };
-
- c->isfloating = 0;
- c->tags = 0;
- c->noswallow = -1;
-
- /* rule matching */
- XGetClassHint(dpy, c->win, &ch);
- class = ch.res_class ? ch.res_class : broken;
- instance = ch.res_name ? ch.res_name : broken;
-
- for (i = 0; i < arrlen(rules); i++) {
- r = &rules[i];
- if ((!r->title || strstr(c->name, r->title))
- && (!r->class || strstr(class, r->class))
- && (!r->instance || strstr(instance, r->instance)))
- {
- c->isterm = r->isterm;
- c->noswallow = r->noswallow;
- c->isfloating = r->isfloating;
- c->tags |= r->tags;
- for (m = mons; m && m->num != r->monitor; m = m->next)
- ;
- if (m)
- c->mon = m;
- }
- }
- if (ch.res_class)
- XFree(ch.res_class);
- if (ch.res_name)
- XFree(ch.res_name);
- c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
-}
-
-int
-applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
-{
- int baseismin;
- Monitor *m = c->mon;
-
- /* set minimum possible */
- *w = MAX(1, *w);
- *h = MAX(1, *h);
- if (interact) {
- if (*x > sw)
- *x = sw - WIDTH(c);
- if (*y > sh)
- *y = sh - HEIGHT(c);
- if (*x + *w + 2 * c->bw < 0)
- *x = 0;
- if (*y + *h + 2 * c->bw < 0)
- *y = 0;
- } else {
- if (*x >= m->wx + m->ww)
- *x = m->wx + m->ww - WIDTH(c);
- if (*y >= m->wy + m->wh)
- *y = m->wy + m->wh - HEIGHT(c);
- if (*x + *w + 2 * c->bw <= m->wx)
- *x = m->wx;
- if (*y + *h + 2 * c->bw <= m->wy)
- *y = m->wy;
- }
- if (*h < bh)
- *h = bh;
- if (*w < bh)
- *w = bh;
- if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
- /* see last two sentences in ICCCM 4.1.2.3 */
- baseismin = c->basew == c->minw && c->baseh == c->minh;
- if (!baseismin) { /* temporarily remove base dimensions */
- *w -= c->basew;
- *h -= c->baseh;
- }
- /* adjust for aspect limits */
- if (c->mina > 0 && c->maxa > 0) {
- if (c->maxa < (float)*w / *h)
- *w = *h * c->maxa + 0.5;
- else if (c->mina < (float)*h / *w)
- *h = *w * c->mina + 0.5;
- }
- if (baseismin) { /* increment calculation requires this */
- *w -= c->basew;
- *h -= c->baseh;
- }
- /* adjust for increment value */
- if (c->incw)
- *w -= *w % c->incw;
- if (c->inch)
- *h -= *h % c->inch;
- /* restore base dimensions */
- *w = MAX(*w + c->basew, c->minw);
- *h = MAX(*h + c->baseh, c->minh);
- if (c->maxw)
- *w = MIN(*w, c->maxw);
- if (c->maxh)
- *h = MIN(*h, c->maxh);
- }
- return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
-}
-
-void
-attach(Client *c)
-{
- c->next = c->mon->clients;
- c->mon->clients = c;
-}
-
-void
-enqueue(Client *c)
-{
- Client *l;
-
- for (l = c->mon->clients; l && l->next; l = l->next)
- ;
-
- if (l) {
- l->next = c;
- c->next = nil;
- }
-}
-
-void
-attachbottom(Client *c)
-{
- Client **tc;
- c->next = nil;
- for (tc = &c->mon->clients; *tc; tc = &(*tc)->next)
- ;
- *tc = c;
-}
-
-void
-attachstack(Client *c)
-{
- c->snext = c->mon->stack;
- c->mon->stack = c;
-}
-
-void
-enqueuestack(Client *c)
-{
- Client *l;
- for (l = c->mon->clients; l && l->next; l = l->next)
- ;
-
- if (l) {
- l->snext = c;
- c->snext = nil;
- }
-}
-
-void
-configure(Client *c)
-{
- XConfigureEvent ce;
-
- ce.type = ConfigureNotify;
- ce.display = dpy;
- ce.event = c->win;
- ce.window = c->win;
- ce.x = c->x;
- ce.y = c->y;
- ce.width = c->w;
- ce.height = c->h;
- ce.border_width = c->bw;
- ce.above = None;
- ce.override_redirect = False;
- XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
-}
-
-void
-detach(Client *c)
-{
- Client **tc;
-
- for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next)
- ;
- *tc = c->next;
-}
-
-void
-detachstack(Client *c)
-{
- Client **tc, *t;
-
- for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext)
- ;
-
- *tc = c->snext;
-
- if (c == c->mon->sel) {
- for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext)
- ;
- c->mon->sel = t;
- }
-}
-
-void
-focus(Client *c)
-{
- if (!c || !ISVISIBLE(c))
- for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext)
- ;
- if (selmon->sel && selmon->sel != c)
- unfocus(selmon->sel, 0);
- if (c) {
- if (c->mon != selmon)
- selmon = c->mon;
- if (c->isurgent)
- seturgent(c, 0);
- detachstack(c);
- attachstack(c);
- grabbuttons(c, 1);
- XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
- setfocus(c);
- } else {
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
- XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
- }
- selmon->sel = c;
- drawbars();
-}
-
-Atom
-getatomprop(Client *c, Atom prop)
-{
- int di;
- unsigned long dl;
- uchar *p = nil;
- Atom da, atom = None;
-
- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
- &da, &di, &dl, &dl, &p) == Success && p) {
- atom = *(Atom *)p;
- XFree(p);
- }
- return atom;
-}
-
-void
-grabbuttons(Client *c, int focused)
-{
- updatenumlockmask();
- {
- uint i, j;
- uint modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
- XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
- if (!focused)
- XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
- BUTTONMASK, GrabModeSync, GrabModeSync, None, None);
- for (i = 0; i < arrlen(buttons); i++)
- if (buttons[i].click == ClkClientWin)
- for (j = 0; j < arrlen(modifiers); j++)
- XGrabButton(dpy, buttons[i].button,
- buttons[i].mask | modifiers[j],
- c->win, False, BUTTONMASK,
- GrabModeAsync, GrabModeSync, None, None);
- }
-}
-
-Client *
-nexttiled(Client *c)
-{
- for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next)
- ;
- return c;
-}
-
-void
-pop(Client *c)
-{
- detach(c);
- attach(c);
- focus(c);
- arrange(c->mon);
-}
-
-void
-resize(Client *c, int x, int y, int w, int h, int interact)
-{
- if (applysizehints(c, &x, &y, &w, &h, interact))
- resizeclient(c, x, y, w, h);
-}
-
-
-void
-resizeclient(Client *c, int x, int y, int w, int h)
-{
- XWindowChanges wc;
-
- c->oldx = c->x; c->x = wc.x = x;
- c->oldy = c->y; c->y = wc.y = y;
- c->oldw = c->w; c->w = wc.width = w;
- c->oldh = c->h; c->h = wc.height = h;
- wc.border_width = c->bw;
- XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
- configure(c);
- XSync(dpy, False);
-}
-
-void
-sendtomon(Client *c, Monitor *m)
-{
- if (c->mon == m)
- return;
- unfocus(c, 1);
- detach(c);
- detachstack(c);
- c->mon = m;
- c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
- /* attach(c); */
- attachbottom(c);
- attachstack(c);
- focus(nil);
- arrange(nil);
-}
-
-void
-setclientstate(Client *c, long state)
-{
- long data[] = { state, None };
-
- XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
- PropModeReplace, (uchar *)data, 2);
-}
-
-int
-sendevent(Client *c, Atom proto)
-{
- int n;
- Atom *protocols;
- int exists = 0;
- XEvent ev;
-
- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
- while (!exists && n--)
- exists = protocols[n] == proto;
- XFree(protocols);
- }
- if (exists) {
- ev.type = ClientMessage;
- ev.xclient.window = c->win;
- ev.xclient.message_type = wmatom[WMProtocols];
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = proto;
- ev.xclient.data.l[1] = CurrentTime;
- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
- }
- return exists;
-}
-
-void
-setfocus(Client *c)
-{
- if (!c->neverfocus) {
- XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
- XChangeProperty(dpy, root, netatom[NetActiveWindow],
- XA_WINDOW, 32, PropModeReplace,
- (uchar *) &(c->win), 1);
- }
- sendevent(c, wmatom[WMTakeFocus]);
-}
-
-void
-setfullscreen(Client *c, int fullscreen)
-{
- static uint32 opacity = 0xFFFFFFFFul;
- if (fullscreen && !c->isfullscreen) {
- XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
- PropModeReplace, (uchar*)&netatom[NetWMFullscreen], 1);
- XChangeProperty(dpy, c->win, netatom[NetWMWindowOpacity], XA_CARDINAL, 32, PropModeReplace, (uchar *)&opacity, 1L);
-
- c->isfullscreen = 1;
- c->oldstate = c->isfloating;
- c->oldbw = c->bw;
- c->bw = 0;
- c->isfloating = 1;
-
- resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
-
- XRaiseWindow(dpy, c->win);
- } else if (!fullscreen && c->isfullscreen){
- XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
- PropModeReplace, (uchar*)nil, 0);
- XDeleteProperty(dpy, c->win, netatom[NetWMWindowOpacity]);
-
- c->isfullscreen = 0;
- c->isfloating = c->oldstate;
- c->bw = c->oldbw;
- c->x = c->oldx;
- c->y = c->oldy;
- c->w = c->oldw;
- c->h = c->oldh;
- resizeclient(c, c->x, c->y, c->w, c->h);
- arrange(c->mon);
- }
-}
-
-void
-seturgent(Client *c, int urg)
-{
- XWMHints *wmh;
-
- c->isurgent = urg;
- if (!(wmh = XGetWMHints(dpy, c->win)))
- return;
- wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint);
- XSetWMHints(dpy, c->win, wmh);
- XFree(wmh);
-}
-
-void
-showhide(Client *c)
-{
- if (!c)
- return;
- if (ISVISIBLE(c)) {
- /* show clients top down */
- XMoveWindow(dpy, c->win, c->x, c->y);
- if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
- resize(c, c->x, c->y, c->w, c->h, 0);
- showhide(c->snext);
- } else {
- /* hide clients bottom up */
- showhide(c->snext);
- XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
- }
-}
-
-void
-swallow(Client *p, Client *c)
-{
- Client *s;
-
-
- if (c->noswallow > 0 || c->isterm)
- return;
- if (c->noswallow < 0 && !swallowfloating && c->isfloating)
- return;
-
- detach(c);
- detachstack(c);
-
- setclientstate(c, WithdrawnState);
- XUnmapWindow(dpy, p->win);
-
- p->swallowing = c;
- c->mon = p->mon;
-
- Window w = p->win;
- p->win = c->win;
- c->win = w;
-
- XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace,
- (unsigned char *) &(p->win), 1);
-
- updatetitle(p);
- s = scanner ? c : p;
- XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h);
- arrange(p->mon);
- configure(p);
- updateclientlist();
-}
-
-Client *
-termof(Client *w)
-{
- Client *c;
- Monitor *m;
-
- if (!w->pid || w->isterm)
- return NULL;
-
- for (m = mons; m; m = m->next) {
- for (c = m->clients; c; c = c->next) {
- if (c->isterm && !c->swallowing && c->pid && isdescendent(c->pid, w->pid))
- return c;
- }
- }
-
- return NULL;
-}
-
-void
-unfocus(Client *c, int setfocus)
-{
- if (!c)
- return;
- grabbuttons(c, 0);
- XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
- if (setfocus) {
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
- XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
- }
-}
-
-void
-unmanage(Client *c, int destroyed)
-{
- Client *s;
- Monitor *m = c->mon;
- XWindowChanges wc;
-
- if (c->swallowing) {
- unswallow(c);
- return;
- }
-
- s = swallowing(c->win);
- if (s) {
- free(s->swallowing);
- s->swallowing = nil;
- arrange(m);
- focus(nil);
- return;
- }
-
-
- detach(c);
- detachstack(c);
-
- if (!destroyed) {
- wc.border_width = c->oldbw;
- XGrabServer(dpy); /* avoid race conditions */
- XSetErrorHandler(xerrordummy);
- XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
- XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
- setclientstate(c, WithdrawnState);
- XSync(dpy, False);
- XSetErrorHandler(xerror);
- XUngrabServer(dpy);
- }
- free(c);
- focus(nil);
- updateclientlist();
- arrange(m);
-
- if (!s) {
- // arrange(m);
- focus(nil);
- updateclientlist();
- }
-}
-
-void
-unswallow(Client *c)
-{
- c->win = c->swallowing->win;
-
- free(c->swallowing);
- c->swallowing = nil;
-
- XDeleteProperty(dpy, c->win, netatom[NetClientList]);
-
- /* unfullscreen the client */
- setfullscreen(c, 0);
- updatetitle(c);
- arrange(c->mon);
- XMapWindow(dpy, c->win);
- XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
- setclientstate(c, NormalState);
- focus(nil);
- arrange(c->mon);
-}
-
-
-void
-updatesizehints(Client *c)
-{
- long msize;
- XSizeHints size;
-
- if (!XGetWMNormalHints(dpy, c->win, &size, &msize))
- /* size is uninitialized, ensure that size.flags aren't used */
- size.flags = PSize;
- if (size.flags & PBaseSize) {
- c->basew = size.base_width;
- c->baseh = size.base_height;
- } else if (size.flags & PMinSize) {
- c->basew = size.min_width;
- c->baseh = size.min_height;
- } else
- c->basew = c->baseh = 0;
- if (size.flags & PResizeInc) {
- c->incw = size.width_inc;
- c->inch = size.height_inc;
- } else
- c->incw = c->inch = 0;
- if (size.flags & PMaxSize) {
- c->maxw = size.max_width;
- c->maxh = size.max_height;
- } else
- c->maxw = c->maxh = 0;
- if (size.flags & PMinSize) {
- c->minw = size.min_width;
- c->minh = size.min_height;
- } else if (size.flags & PBaseSize) {
- c->minw = size.base_width;
- c->minh = size.base_height;
- } else
- c->minw = c->minh = 0;
- if (size.flags & PAspect) {
- c->mina = (float)size.min_aspect.y / size.min_aspect.x;
- c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
- } else
- c->maxa = c->mina = 0.0;
- c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
-}
-
-void
-updatetitle(Client *c)
-{
- if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
- gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
- if (c->name[0] == '\0') /* hack to mark broken clients */
- strcpy(c->name, broken);
-}
-
-void
-updatewindowtype(Client *c)
-{
- Atom state = getatomprop(c, netatom[NetWMState]);
- Atom wtype = getatomprop(c, netatom[NetWMWindowType]);
-
- if (state == netatom[NetWMFullscreen])
- setfullscreen(c, 1);
- if (wtype == netatom[NetWMWindowTypeDialog])
- c->isfloating = 1;
-}
-
-void
-updatewmhints(Client *c)
-{
- XWMHints *wmh;
-
- if ((wmh = XGetWMHints(dpy, c->win))) {
- if (c == selmon->sel && wmh->flags & XUrgencyHint) {
- wmh->flags &= ~XUrgencyHint;
- XSetWMHints(dpy, c->win, wmh);
- } else
- c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0;
- if (wmh->flags & InputHint)
- c->neverfocus = !wmh->input;
- else
- c->neverfocus = 0;
- XFree(wmh);
- }
-}
diff --git a/sys/cmd/dwm/config.h b/sys/cmd/dwm/config.h
deleted file mode 100644
index 1f82b1f..0000000
--- a/sys/cmd/dwm/config.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#define VERSION "1"
-
-/* appearance */
-static uint borderpx = 2; /* border pixel of windows */
-static uint gapx = 4; /* gaps between windows */
-static uint snap = 32; /* snap pixel */
-static int swallowfloating = 0; /* 1 will swallow floating by default */
-static int showbar = 1; /* 0 means no bar */
-static int topbar = 1; /* 0 means bottom bar */
-static char *fonts[] = { "consolas:size=16" };
-static char col_gray1[] = "#504945";
-static char col_gray2[] = "#282828";
-static char col_gray3[] = "#fbf1c7";
-static char col_gray4[] = "#504945";
-static char col_cyan[] = "#83a598";
-static char *colors[][3] =
-{
- /* fg bg border */
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
-};
-
-/* tagging */
-static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-
-static Rule rules[] = {
- /* xprop(1):
- * WM_CLASS(STRING) = instance, class
- * WM_NAME(STRING) = title
- */
- /* class instance title tags mask isfloating isterminal noswallow monitor */
- { "Gimp", nil, nil, 0, 1, 0, 0, -1 },
- { "Inkscape", nil, nil, 0, 1, 0, 0, -1 },
- { "zoom", nil, nil, 0, 1, 0, 0, -1 },
- { "qutebrowser", nil, nil, 0, 0, 0, 0, -1 },
- { "term-256color", nil, nil, 0, 0, 1, -1, -1 },
-};
-
-/* layout(s) */
-static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
-static int nmaster = 1; /* number of clients in master area */
-static int resizehints = 1; /* 1 means respect size hints in tiled resizals */
-
-static Layout layouts[] = {
- /* symbol arrange function */
- { "[]=", tile }, /* first entry is default */
- { "><>", nil }, /* no layout function means floating behavior */
- { "[M]", monocle },
-};
-
-/* key definitions */
-#define MODKEY Mod4Mask
-#define TAGKEYS(KEY,TAG) \
- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
- { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
-
-/* commands */
-static char *menucmd[] = { "menu_run", nil };
-static char *termcmd[] = { "term", nil };
-static char *webscmd[] = { "qutebrowser", nil };
-static char scratchname[] = "scratchpad";
-static char *scratchcmd[] = { "term", "-t", scratchname, "-g", "120x34", nil };
-static char *upvolcmd[] = { "vol", "+5%", nil };
-static char *lovolcmd[] = { "vol", "-5%", nil };
-static char *novolcmd[] = { "vol", "mute", nil };
-
-#define XK_lovol XF86XK_AudioLowerVolume
-#define XK_upvol XF86XK_AudioRaiseVolume
-#define XK_novol XF86XK_AudioMute
-
-static Key keys[] = {
- /* modifier key function argument */
- { MODKEY, XK_d, spawn, {.v = menucmd } },
- { MODKEY, XK_Return, spawn, {.v = termcmd } },
- { MODKEY, XK_q, spawn, {.v = webscmd } },
- { 0, XK_upvol, spawn, {.v = upvolcmd} },
- { 0, XK_lovol, spawn, {.v = lovolcmd} },
- { 0, XK_novol, spawn, {.v = novolcmd} },
- { MODKEY, XK_s, togglescratch, {.v = scratchcmd} },
- { MODKEY, XK_b, togglebar, {0} },
- { MODKEY, XK_f, togglefocus, {0} },
- { MODKEY, XK_Up, focusstack, {.i = +1 } },
- { MODKEY, XK_Down, focusstack, {.i = -1 } },
- { MODKEY|ShiftMask, XK_Up, rotatestack, {.i = +1 } },
- { MODKEY|ShiftMask, XK_Down, rotatestack, {.i = -1 } },
- { MODKEY, XK_i, incnmaster, {.i = +1 } },
- { MODKEY, XK_o, incnmaster, {.i = -1 } },
- { MODKEY, XK_h, focusdirection, {.i = 'l'} },
- { MODKEY, XK_l, focusdirection, {.i = 'r'} },
- { MODKEY, XK_k, focusdirection, {.i = 'u'} },
- { MODKEY, XK_j, focusdirection, {.i = 'd'} },
- { MODKEY|ShiftMask, XK_h, setmfact, {.f = -0.05} },
- { MODKEY|ShiftMask, XK_l, setmfact, {.f = +0.05} },
- { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } },
- { MODKEY|ShiftMask, XK_j, rotatestack, {.i = +1 } },
- { MODKEY|ShiftMask, XK_Return, zoom, {0} },
- { MODKEY, XK_Tab, view, {0} },
- { MODKEY|ShiftMask, XK_q, killclient, {0} },
- { MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[0]} },
- { MODKEY|ShiftMask, XK_f, setlayout, {.v = &layouts[1]} },
- { MODKEY|ShiftMask, XK_m, setlayout, {.v = &layouts[2]} },
- { MODKEY, XK_space, setlayout, {0} },
- { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
- { MODKEY, XK_0, view, {.ui = ~0 } },
- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
- { MODKEY, XK_comma, focusmon, {.i = -1 } },
- { MODKEY, XK_period, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
- TAGKEYS( XK_1, 0)
- TAGKEYS( XK_2, 1)
- TAGKEYS( XK_3, 2)
- TAGKEYS( XK_4, 3)
- TAGKEYS( XK_5, 4)
- TAGKEYS( XK_6, 5)
- TAGKEYS( XK_7, 6)
- TAGKEYS( XK_8, 7)
- TAGKEYS( XK_9, 8)
- { MODKEY|ShiftMask, XK_e, quit, {0} },
-};
-
-/* button definitions */
-/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
-static Button buttons[] = {
- /* click event mask button function argument */
- { ClkLtSymbol, 0, Button1, setlayout, {0} },
- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
- { ClkClientWin, MODKEY, Button1, movemouse, {0} },
- { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
- { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
- { ClkTagBar, 0, Button1, view, {0} },
- { ClkTagBar, 0, Button3, toggleview, {0} },
- { ClkTagBar, MODKEY, Button1, tag, {0} },
- { ClkTagBar, MODKEY, Button3, toggletag, {0} },
-};
-
diff --git a/sys/cmd/dwm/drw.c b/sys/cmd/dwm/drw.c
deleted file mode 100644
index a6d6902..0000000
--- a/sys/cmd/dwm/drw.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "dwm.h"
-
-Drw *
-drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
-{
- Drw *drw = ecalloc(1, sizeof(Drw));
-
- drw->dpy = dpy;
- drw->screen = screen;
- drw->root = root;
- drw->w = w;
- drw->h = h;
- drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
- drw->gc = XCreateGC(dpy, root, 0, NULL);
- XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
-
- return drw;
-}
-
-void
-drw_resize(Drw *drw, unsigned int w, unsigned int h)
-{
- if (!drw)
- return;
-
- drw->w = w;
- drw->h = h;
- if (drw->drawable)
- XFreePixmap(drw->dpy, drw->drawable);
- drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
-}
-
-void
-drw_free(Drw *drw)
-{
- XFreePixmap(drw->dpy, drw->drawable);
- XFreeGC(drw->dpy, drw->gc);
- free(drw);
-}
-
-/* This function is an implementation detail. Library users should use
- * drw_fontset_create instead.
- */
-static Fnt *
-xfont_create(Drw *drw, char *fontname, FcPattern *fontpattern)
-{
- Fnt *font;
- XftFont *xfont = NULL;
- FcPattern *pattern = NULL;
-
- if (fontname) {
- /* Using the pattern found at font->xfont->pattern does not yield the
- * same substitution results as using the pattern returned by
- * FcNameParse; using the latter results in the desired fallback
- * behaviour whereas the former just results in missing-character
- * rectangles being drawn, at least with some fonts. */
- if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
- fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
- return NULL;
- }
- if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
- fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
- XftFontClose(drw->dpy, xfont);
- return NULL;
- }
- } else if (fontpattern) {
- if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
- fprintf(stderr, "error, cannot load font from pattern.\n");
- return NULL;
- }
- } else {
- fatal("no font specified.");
- }
-
- /* Do not allow using color fonts. This is a workaround for a BadLength
- * error from Xft with color glyphs. Modelled on the Xterm workaround. See
- * https://bugzilla.redhat.com/show_bug.cgi?id=1498269
- * https://lists.suckless.org/dev/1701/30932.html
- * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
- * and lots more all over the internet.
- */
- FcBool iscol;
- if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
- XftFontClose(drw->dpy, xfont);
- return NULL;
- }
-
- font = ecalloc(1, sizeof(Fnt));
- font->xfont = xfont;
- font->pattern = pattern;
- font->h = xfont->ascent + xfont->descent;
- font->dpy = drw->dpy;
-
- return font;
-}
-
-static void
-xfont_free(Fnt *font)
-{
- if (!font)
- return;
- if (font->pattern)
- FcPatternDestroy(font->pattern);
- XftFontClose(font->dpy, font->xfont);
- free(font);
-}
-
-Fnt*
-drw_fontset_create(Drw* drw, char *fonts[], size_t fontcount)
-{
- Fnt *cur, *ret = NULL;
- size_t i;
-
- if (!drw || !fonts)
- return NULL;
-
- for (i = 1; i <= fontcount; i++) {
- if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
- cur->next = ret;
- ret = cur;
- }
- }
- return (drw->fonts = ret);
-}
-
-void
-drw_fontset_free(Fnt *font)
-{
- if (font) {
- drw_fontset_free(font->next);
- xfont_free(font);
- }
-}
-
-void
-drw_clr_create(Drw *drw, Clr *dest, char *clrname)
-{
- if (!drw || !dest || !clrname)
- return;
-
- if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
- DefaultColormap(drw->dpy, drw->screen),
- clrname, dest))
- fatal("error, cannot allocate color '%s'", clrname);
-}
-
-/* Wrapper to create color schemes. The caller has to call free(3) on the
- * returned color scheme when done using it. */
-Clr *
-drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)
-{
- size_t i;
- Clr *ret;
-
- /* need at least two colors for a scheme */
- if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
- return NULL;
-
- for (i = 0; i < clrcount; i++)
- drw_clr_create(drw, &ret[i], clrnames[i]);
- return ret;
-}
-
-void
-drw_setfontset(Drw *drw, Fnt *set)
-{
- if (drw)
- drw->fonts = set;
-}
-
-void
-drw_setscheme(Drw *drw, Clr *scm)
-{
- if (drw)
- drw->scheme = scm;
-}
-
-void
-drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
-{
- if (!drw || !drw->scheme)
- return;
- XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
- if (filled)
- XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
- else
- XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
-}
-
-int
-drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, char *text, int invert)
-{
- char buf[1024];
- int ty;
- unsigned int ew;
- XftDraw *d = NULL;
- Fnt *usedfont, *curfont, *nextfont;
- size_t i, len;
- int utf8strlen, utf8charlen, render = x || y || w || h;
- rune utf8codepoint = 0;
- char *utf8str;
- FcCharSet *fccharset;
- FcPattern *fcpattern;
- FcPattern *match;
- XftResult result;
- int charexists = 0;
-
- if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
- return 0;
-
- if (!render) {
- w = ~w;
- } else {
- XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
- XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
- d = XftDrawCreate(drw->dpy, drw->drawable,
- DefaultVisual(drw->dpy, drw->screen),
- DefaultColormap(drw->dpy, drw->screen));
- x += lpad;
- w -= lpad;
- }
-
- usedfont = drw->fonts;
- while (1) {
- utf8strlen = 0;
- utf8str = text;
- nextfont = NULL;
- while (*text) {
- utf8charlen = utf8·decode(text, &utf8codepoint);
- for (curfont = drw->fonts; curfont; curfont = curfont->next) {
- charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
- if (charexists) {
- if (curfont == usedfont) {
- utf8strlen += utf8charlen;
- text += utf8charlen;
- } else {
- nextfont = curfont;
- }
- break;
- }
- }
-
- if (!charexists || nextfont)
- break;
- else
- charexists = 0;
- }
-
- if (utf8strlen) {
- drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
- /* shorten text if necessary */
- for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
- drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
-
- if (len) {
- memcpy(buf, utf8str, len);
- buf[len] = '\0';
- if (len < utf8strlen)
- for (i = len; i && i > len - 3; buf[--i] = '.')
- ; /* NOP */
-
- if (render) {
- ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
- XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
- usedfont->xfont, x, ty, (XftChar8 *)buf, len);
- }
- x += ew;
- w -= ew;
- }
- }
-
- if (!*text) {
- break;
- } else if (nextfont) {
- charexists = 0;
- usedfont = nextfont;
- } else {
- /* Regardless of whether or not a fallback font is found, the
- * character must be drawn. */
- charexists = 1;
-
- fccharset = FcCharSetCreate();
- FcCharSetAddChar(fccharset, utf8codepoint);
-
- if (!drw->fonts->pattern) {
- /* Refer to the comment in xfont_create for more information. */
- fatal("the first font in the cache must be loaded from a font string.");
- }
-
- fcpattern = FcPatternDuplicate(drw->fonts->pattern);
- FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
- FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
- FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
-
- FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
- FcDefaultSubstitute(fcpattern);
- match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
-
- FcCharSetDestroy(fccharset);
- FcPatternDestroy(fcpattern);
-
- if (match) {
- usedfont = xfont_create(drw, NULL, match);
- if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
- for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
- ; /* NOP */
- curfont->next = usedfont;
- } else {
- xfont_free(usedfont);
- usedfont = drw->fonts;
- }
- }
- }
- }
- if (d)
- XftDrawDestroy(d);
-
- return x + (render ? w : 0);
-}
-
-void
-drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
-{
- if (!drw)
- return;
-
- XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
- XSync(drw->dpy, False);
-}
-
-unsigned int
-drw_fontset_getwidth(Drw *drw, char *text)
-{
- if (!drw || !drw->fonts || !text)
- return 0;
- return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
-}
-
-void
-drw_font_getexts(Fnt *font, char *text, unsigned int len, unsigned int *w, unsigned int *h)
-{
- XGlyphInfo ext;
-
- if (!font || !text)
- return;
-
- XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
- if (w)
- *w = ext.xOff;
- if (h)
- *h = font->h;
-}
-
-Cur *
-drw_cur_create(Drw *drw, int shape)
-{
- Cur *cur;
-
- if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
- return NULL;
-
- cur->cursor = XCreateFontCursor(drw->dpy, shape);
-
- return cur;
-}
-
-void
-drw_cur_free(Drw *drw, Cur *cursor)
-{
- if (!cursor)
- return;
-
- XFreeCursor(drw->dpy, cursor->cursor);
- free(cursor);
-}
diff --git a/sys/cmd/dwm/dwm.c b/sys/cmd/dwm/dwm.c
deleted file mode 100644
index 0567650..0000000
--- a/sys/cmd/dwm/dwm.c
+++ /dev/null
@@ -1,1185 +0,0 @@
-#include "dwm.h"
-
-/* global variables */
-char broken[] = "<broken>";
-char stext[256];
-int scanner;
-int screen;
-int sw, sh; /* X display screen geometry width, height */
-int bh, blw = 0; /* bar geometry */
-int lrpad; /* sum of left and right padding for text */
-int (*xerrorxlib)(Display *, XErrorEvent *);
-uint numlockmask = 0;
-void (*handler[LASTEvent]) (XEvent *) = {
- [ButtonPress] = buttonpress,
- [ClientMessage] = clientmessage,
- [ConfigureRequest] = configurerequest,
- [ConfigureNotify] = configurenotify,
- [DestroyNotify] = destroynotify,
- [EnterNotify] = enternotify,
- [Expose] = expose,
- [FocusIn] = focusin,
- [KeyPress] = keypress,
- [MappingNotify] = mappingnotify,
- [MapRequest] = maprequest,
- [MotionNotify] = motionnotify,
- [PropertyNotify] = propertynotify,
- [UnmapNotify] = unmapnotify
-};
-
-xcb_connection_t *xcon;
-
-Atom wmatom[WMLast] = {0}, netatom[NetLast] = {0};
-int running = 1;
-Cur *cursor[MouseLast] = {0};
-Clr **scheme = nil;
-Display *dpy = nil;
-Drw *drw = nil;
-Monitor *mons = nil, *selmon = nil;
-Window root = {0}, wmcheckwin = {0};
-
-/* compile-time check if all tags fit into an uint bit array. */
-struct NumTags { char limitexceeded[arrlen(tags) > 31 ? -1 : 1]; };
-
-/* function implementations */
-void
-arrange(Monitor *m)
-{
- if (m)
- showhide(m->stack);
- else for (m = mons; m; m = m->next)
- showhide(m->stack);
- if (m) {
- arrangemon(m);
- restack(m);
- } else for (m = mons; m; m = m->next)
- arrangemon(m);
-}
-
-void
-arrangemon(Monitor *m)
-{
- strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
- if (m->lt[m->sellt]->arrange)
- m->lt[m->sellt]->arrange(m);
-}
-
-void
-buttonpress(XEvent *e)
-{
- uint i, x, click;
- Arg arg = {0};
- Client *c;
- Monitor *m;
- XButtonPressedEvent *ev = &e->xbutton;
-
- click = ClkRootWin;
- /* focus monitor if necessary */
- if ((m = wintomon(ev->window)) && m != selmon) {
- unfocus(selmon->sel, 1);
- selmon = m;
- focus(nil);
- }
- if (ev->window == selmon->barwin) {
- i = x = 0;
- do
- x += TEXTW(tags[i]);
- while (ev->x >= x && ++i < arrlen(tags));
- if (i < arrlen(tags)) {
- click = ClkTagBar;
- arg.ui = 1 << i;
- } else if (ev->x < x + blw)
- click = ClkLtSymbol;
- else if (ev->x > selmon->ww - TEXTW(stext))
- click = ClkStatusText;
- else
- click = ClkWinTitle;
- } else if ((c = wintoclient(ev->window))) {
- focus(c);
- restack(selmon);
- XAllowEvents(dpy, ReplayPointer, CurrentTime);
- click = ClkClientWin;
- }
- for (i = 0; i < arrlen(buttons); i++)
- if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
- && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
- buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
-}
-
-void
-checkotherwm(void)
-{
- xerrorxlib = XSetErrorHandler(xerrorstart);
- /* this causes an error if some other window manager is running */
- XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
- XSync(dpy, False);
- XSetErrorHandler(xerror);
- XSync(dpy, False);
-}
-
-void
-cleanup(void)
-{
- Arg a = {.ui = ~0};
- Layout foo = { "", nil };
- Monitor *m;
- size_t i;
-
- view(&a);
- selmon->lt[selmon->sellt] = &foo;
- for (m = mons; m; m = m->next)
- while (m->stack)
- unmanage(m->stack, 0);
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- while (mons)
- cleanupmon(mons);
- for (i = 0; i < MouseLast; i++)
- drw_cur_free(drw, cursor[i]);
- for (i = 0; i < arrlen(colors); i++)
- free(scheme[i]);
- XDestroyWindow(dpy, wmcheckwin);
- drw_free(drw);
- XSync(dpy, False);
- XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
- XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
-}
-
-void
-cleanupmon(Monitor *mon)
-{
- Monitor *m;
-
- if (mon == mons)
- mons = mons->next;
- else {
- for (m = mons; m && m->next != mon; m = m->next);
- m->next = mon->next;
- }
- XUnmapWindow(dpy, mon->barwin);
- XDestroyWindow(dpy, mon->barwin);
- free(mon);
-}
-
-void
-clientmessage(XEvent *e)
-{
- XClientMessageEvent *cme = &e->xclient;
- Client *c = wintoclient(cme->window);
-
- if (!c)
- return;
- if (cme->message_type == netatom[NetWMState]) {
- if (cme->data.l[1] == netatom[NetWMFullscreen]
- || cme->data.l[2] == netatom[NetWMFullscreen])
- setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */
- || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
- } else if (cme->message_type == netatom[NetActiveWindow]) {
- if (c != selmon->sel && !c->isurgent)
- seturgent(c, 1);
- }
-}
-
-void
-configurenotify(XEvent *e)
-{
- Monitor *m;
- Client *c;
- XConfigureEvent *ev = &e->xconfigure;
- int dirty;
-
- /* TODO: updategeom handling sucks, needs to be simplified */
- if (ev->window == root) {
- dirty = (sw != ev->width || sh != ev->height);
- sw = ev->width;
- sh = ev->height;
- if (updategeom() || dirty) {
- drw_resize(drw, sw, bh);
- updatebars();
- for (m = mons; m; m = m->next) {
- for (c = m->clients; c; c = c->next)
- if (c->isfullscreen)
- resizeclient(c, m->mx, m->my, m->mw, m->mh);
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
- }
- focus(nil);
- arrange(nil);
- }
- }
-}
-
-void
-configurerequest(XEvent *e)
-{
- Client *c;
- Monitor *m;
- XConfigureRequestEvent *ev = &e->xconfigurerequest;
- XWindowChanges wc;
-
- if ((c = wintoclient(ev->window))) {
- if (ev->value_mask & CWBorderWidth)
- c->bw = ev->border_width;
- else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
- m = c->mon;
- if (ev->value_mask & CWX) {
- c->oldx = c->x;
- c->x = m->mx + ev->x;
- }
- if (ev->value_mask & CWY) {
- c->oldy = c->y;
- c->y = m->my + ev->y;
- }
- if (ev->value_mask & CWWidth) {
- c->oldw = c->w;
- c->w = ev->width;
- }
- if (ev->value_mask & CWHeight) {
- c->oldh = c->h;
- c->h = ev->height;
- }
- if ((c->x + c->w) > m->mx + m->mw && c->isfloating)
- c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */
- if ((c->y + c->h) > m->my + m->mh && c->isfloating)
- c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
- if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
- configure(c);
- if (ISVISIBLE(c))
- XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
- } else
- configure(c);
- } else {
- wc.x = ev->x;
- wc.y = ev->y;
- wc.width = ev->width;
- wc.height = ev->height;
- wc.border_width = ev->border_width;
- wc.sibling = ev->above;
- wc.stack_mode = ev->detail;
- XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
- }
- XSync(dpy, False);
-}
-
-Monitor *
-createmon(void)
-{
- Monitor *m;
-
- m = ecalloc(1, sizeof(Monitor));
- m->tagset[0] = m->tagset[1] = 1;
- m->mfact = mfact;
- m->nmaster = nmaster;
- m->showbar = showbar;
- m->topbar = topbar;
- m->lt[0] = &layouts[0];
- m->lt[1] = &layouts[1 % arrlen(layouts)];
- strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
- return m;
-}
-
-void
-destroynotify(XEvent *e)
-{
- Client *c;
- XDestroyWindowEvent *ev = &e->xdestroywindow;
-
- if ((c = wintoclient(ev->window)))
- unmanage(c, 1);
- else if ((c = swallowing(ev->window)))
- unmanage(c->swallowing, 1);
-}
-
-Monitor *
-dirtomon(int dir)
-{
- Monitor *m = nil;
-
- if (dir > 0) {
- if (!(m = selmon->next))
- m = mons;
- } else if (selmon == mons)
- for (m = mons; m->next; m = m->next);
- else
- for (m = mons; m->next != selmon; m = m->next);
- return m;
-}
-
-void
-drawbar(Monitor *m)
-{
- int x, w, tw = 0;
- int boxs = drw->fonts->h / 9;
- int boxw = drw->fonts->h / 6 + 2;
- uint i, occ = 0, urg = 0;
- Client *c;
-
- /* draw status first so it can be overdrawn by tags later */
- if(m == selmon) { /* status is only drawn on selected monitor */
- drw_setscheme(drw, scheme[SchemeNorm]);
- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
- }
-
- for(c = m->clients; c; c = c->next) {
- occ |= c->tags;
- if (c->isurgent)
- urg |= c->tags;
- }
- x = 0;
- for(i = 0; i < arrlen(tags); i++) {
- w = TEXTW(tags[i]);
- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
- if (occ & 1 << i)
- drw_rect(drw, x + boxs, boxs, boxw, boxw,
- m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- urg & 1 << i);
- x += w;
- }
- w = blw = TEXTW(m->ltsymbol);
- drw_setscheme(drw, scheme[SchemeNorm]);
- x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
-
- if((w = m->ww - tw - x) > bh) {
- if (m->sel) {
- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
- if (m->sel->isfloating)
- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
- } else {
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_rect(drw, x, 0, w, bh, 1, 1);
- }
- }
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
-}
-
-void
-drawbars(void)
-{
- Monitor *m;
-
- for (m = mons; m; m = m->next)
- drawbar(m);
-}
-
-void
-enternotify(XEvent *e)
-{
- Client *c;
- Monitor *m;
- XCrossingEvent *ev = &e->xcrossing;
-
- if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
- return;
- c = wintoclient(ev->window);
- m = c ? c->mon : wintomon(ev->window);
- if (m != selmon) {
- unfocus(selmon->sel, 1);
- selmon = m;
- } else if (!c || c == selmon->sel)
- return;
- focus(c);
-}
-
-void
-expose(XEvent *e)
-{
- Monitor *m;
- XExposeEvent *ev = &e->xexpose;
-
- if (ev->count == 0 && (m = wintomon(ev->window)))
- drawbar(m);
-}
-
-/* there are some broken focus acquiring clients needing extra handling */
-void
-focusin(XEvent *e)
-{
- XFocusChangeEvent *ev = &e->xfocus;
-
- if (selmon->sel && ev->window != selmon->sel->win)
- setfocus(selmon->sel);
-}
-
-int
-getrootptr(int *x, int *y)
-{
- int di;
- uint dui;
- Window dummy;
-
- return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
-}
-
-long
-getstate(Window w)
-{
- int format;
- long result = -1;
- unsigned char *p = nil;
- unsigned long n, extra;
- Atom real;
-
- if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
- &real, &format, &n, &extra, (unsigned char **)&p) != Success)
- return -1;
- if (n != 0)
- result = *p;
- XFree(p);
- return result;
-}
-
-int
-gettextprop(Window w, Atom atom, char *text, uint size)
-{
- char **list = nil;
- int n;
- XTextProperty name;
-
- if (!text || size == 0)
- return 0;
- text[0] = '\0';
- if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
- return 0;
- if (name.encoding == XA_STRING)
- strncpy(text, (char *)name.value, size - 1);
- else {
- if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
- strncpy(text, *list, size - 1);
- XFreeStringList(list);
- }
- }
- text[size - 1] = '\0';
- XFree(name.value);
- return 1;
-}
-
-void
-grabkeys(void)
-{
- updatenumlockmask();
- {
- uint i, j;
- uint modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
- KeyCode code;
-
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- for (i = 0; i < arrlen(keys); i++)
- if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
- for (j = 0; j < arrlen(modifiers); j++)
- XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
- True, GrabModeAsync, GrabModeAsync);
- }
-}
-
-static
-int
-isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
-{
- while (n--)
- if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
- && unique[n].width == info->width && unique[n].height == info->height)
- return 0;
- return 1;
-}
-
-void
-keypress(XEvent *e)
-{
- uint i;
- KeySym keysym;
- XKeyEvent *ev;
-
- ev = &e->xkey;
- keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0);
- for (i = 0; i < arrlen(keys); i++)
- if (keysym == keys[i].keysym
- && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
- && keys[i].func)
- keys[i].func(&(keys[i].arg));
-}
-
-void
-manage(Window w, XWindowAttributes *wa)
-{
- Client *c, *t = nil, *term = nil;
- Window trans = None;
- XWindowChanges wc;
-
- c = ecalloc(1, sizeof(Client));
- c->win = w;
- c->pid = winpid(w);
- /* geometry */
- c->x = c->oldx = wa->x;
- c->y = c->oldy = wa->y;
- c->w = c->oldw = wa->width;
- c->h = c->oldh = wa->height;
- c->oldbw = wa->border_width;
-
- updatetitle(c);
- if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
- c->mon = t->mon;
- c->tags = t->tags;
- } else {
- c->mon = selmon;
- applyrules(c);
- term = termof(c);
- }
-
- if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
- c->x = c->mon->mx + c->mon->mw - WIDTH(c);
- if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh)
- c->y = c->mon->my + c->mon->mh - HEIGHT(c);
- c->x = MAX(c->x, c->mon->mx);
- /* only fix client y-offset, if the client center might cover the bar */
- c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
- && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
- c->bw = borderpx;
-
- selmon->tagset[selmon->seltags] &= ~scratchtag;
- if(!strcmp(c->name, scratchname)) {
- c->mon->tagset[c->mon->seltags] |= c->tags = scratchtag;
- c->isfloating = 1;
- c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
- c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
- }
-
- wc.border_width = c->bw;
- XConfigureWindow(dpy, w, CWBorderWidth, &wc);
- XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
- configure(c); /* propagates border_width, if size doesn't change */
- updatewindowtype(c);
- updatesizehints(c);
- updatewmhints(c);
- XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
- grabbuttons(c, 0);
-
- if (!c->isfloating)
- c->isfloating = c->oldstate = trans != None || c->isfixed;
- if (c->isfloating)
- XRaiseWindow(dpy, c->win);
-
- /* attach(c); */
- attachbottom(c);
- attachstack(c);
-
- XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
- XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
- setclientstate(c, NormalState);
- if (c->mon == selmon)
- unfocus(selmon->sel, 0);
- c->mon->sel = c;
- arrange(c->mon);
- XMapWindow(dpy, c->win);
- if (term)
- swallow(term, c);
- focus(nil);
-}
-
-void
-mappingnotify(XEvent *e)
-{
- XMappingEvent *ev = &e->xmapping;
-
- XRefreshKeyboardMapping(ev);
- if (ev->request == MappingKeyboard)
- grabkeys();
-}
-
-void
-maprequest(XEvent *e)
-{
- static XWindowAttributes wa;
- XMapRequestEvent *ev = &e->xmaprequest;
-
- if (!XGetWindowAttributes(dpy, ev->window, &wa))
- return;
- if (wa.override_redirect)
- return;
- if (!wintoclient(ev->window))
- manage(ev->window, &wa);
-}
-
-void
-monocle(Monitor *m)
-{
- uint n = 0;
- Client *c;
-
- for (c = m->clients; c; c = c->next)
- if (ISVISIBLE(c))
- n++;
- if (n > 0) /* override layout symbol */
- snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
- for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
-}
-
-void
-motionnotify(XEvent *e)
-{
- static Monitor *mon = nil;
- Monitor *m;
- XMotionEvent *ev = &e->xmotion;
-
- if (ev->window != root)
- return;
- if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) {
- unfocus(selmon->sel, 1);
- selmon = m;
- focus(nil);
- }
- mon = m;
-}
-
-void
-propertynotify(XEvent *e)
-{
- Client *c;
- Window trans;
- XPropertyEvent *ev = &e->xproperty;
-
- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
- updatestatus();
- else if (ev->state == PropertyDelete)
- return; /* ignore */
- else if ((c = wintoclient(ev->window))) {
- switch(ev->atom) {
- default: break;
- case XA_WM_TRANSIENT_FOR:
- if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
- (c->isfloating = (wintoclient(trans)) != nil))
- arrange(c->mon);
- break;
- case XA_WM_NORMAL_HINTS:
- updatesizehints(c);
- break;
- case XA_WM_HINTS:
- updatewmhints(c);
- drawbars();
- break;
- }
- if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
- updatetitle(c);
- if (c == c->mon->sel)
- drawbar(c->mon);
- }
- if (ev->atom == netatom[NetWMWindowType])
- updatewindowtype(c);
- }
-}
-
-Monitor *
-recttomon(int x, int y, int w, int h)
-{
- Monitor *m, *r = selmon;
- int a, area = 0;
-
- for (m = mons; m; m = m->next)
- if ((a = INTERSECT(x, y, w, h, m)) > area) {
- area = a;
- r = m;
- }
- return r;
-}
-
-void
-restack(Monitor *m)
-{
- Client *c;
- XEvent ev;
- XWindowChanges wc;
-
- drawbar(m);
- if (!m->sel)
- return;
- if (m->sel->isfloating || !m->lt[m->sellt]->arrange)
- XRaiseWindow(dpy, m->sel->win);
- if (m->lt[m->sellt]->arrange) {
- wc.stack_mode = Below;
- wc.sibling = m->barwin;
- for (c = m->stack; c; c = c->snext)
- if (!c->isfloating && ISVISIBLE(c)) {
- XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
- wc.sibling = c->win;
- }
- }
- XSync(dpy, False);
- while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
-}
-
-void
-run(void)
-{
- XEvent ev;
- /* main event loop */
- XSync(dpy, False);
- while (running && !XNextEvent(dpy, &ev))
- if (handler[ev.type])
- handler[ev.type](&ev); /* call handler */
-}
-
-void
-scan(void)
-{
- uint i, num;
- Window d1, d2, *wins = nil;
- XWindowAttributes wa;
- char swin[256];
-
- scanner = 1;
-
- if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
- for (i = 0; i < num; i++) {
- if (!XGetWindowAttributes(dpy, wins[i], &wa)
- || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
- continue;
- if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
- manage(wins[i], &wa);
- else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin))
- manage(wins[i], &wa);
- }
- for (i = 0; i < num; i++) { /* now the transients */
- if (!XGetWindowAttributes(dpy, wins[i], &wa))
- continue;
- if (XGetTransientForHint(dpy, wins[i], &d1)
- && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
- manage(wins[i], &wa);
- }
- if (wins)
- XFree(wins);
- }
-
- scanner = 0;
-}
-
-void
-setup(void)
-{
- int i;
- XSetWindowAttributes wa;
- Atom utf8string;
-
- /* clean up any zombies immediately */
- sigchld(0);
-
- /* init screen */
- screen = DefaultScreen(dpy);
- sw = DisplayWidth(dpy, screen);
- sh = DisplayHeight(dpy, screen);
- root = RootWindow(dpy, screen);
- drw = drw_create(dpy, screen, root, sw, sh);
- if (!drw_fontset_create(drw, fonts, arrlen(fonts)))
- fatal("no fonts could be loaded.");
-
- lrpad = drw->fonts->h;
- bh = drw->fonts->h + 2;
- updategeom();
-
- /* init atoms */
- utf8string = XInternAtom(dpy, "UTF8_STRING", False);
- wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
- wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
- wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
- wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
-
- netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
- netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
- netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
- netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
- netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
- netatom[NetWMWindowOpacity] = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False);
- netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
- netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
-
- /* init cursors */
- cursor[MouseNormal] = drw_cur_create(drw, XC_left_ptr);
- cursor[MouseResize] = drw_cur_create(drw, XC_sizing);
- cursor[MouseMove] = drw_cur_create(drw, XC_fleur);
-
- /* init appearance */
- scheme = ecalloc(arrlen(colors), sizeof(Clr *));
- for (i = 0; i < arrlen(colors); i++)
- scheme[i] = drw_scm_create(drw, colors[i], 3);
-
- /* init bars */
- updatebars();
- updatestatus();
-
- /* supporting window for NetWMCheck */
- wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
- XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
- PropModeReplace, (uchar *) &wmcheckwin, 1);
- XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
- PropModeReplace, (uchar *) "dwm", 3);
- XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
- PropModeReplace, (uchar *) &wmcheckwin, 1);
- /* EWMH support per view */
- XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
- PropModeReplace, (uchar *) netatom, NetLast);
- XDeleteProperty(dpy, root, netatom[NetClientList]);
- /* select events */
- wa.cursor = cursor[MouseNormal]->cursor;
- wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
- |ButtonPressMask|PointerMotionMask|EnterWindowMask
- |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
- XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
- XSelectInput(dpy, root, wa.event_mask);
- grabkeys();
- focus(nil);
-}
-
-
-void
-sigchld(int unused)
-{
- if (signal(SIGCHLD, sigchld) == SIG_ERR)
- fatal("can't install SIGCHLD handler:");
- while (0 < waitpid(-1, nil, WNOHANG));
-}
-
-Client *
-swallowing(Window w)
-{
- Client *c;
- Monitor *m;
-
- for (m = mons; m; m = m->next) {
- for (c = m->clients; c; c = c->next) {
- if (c->swallowing && c->swallowing->win == w)
- return c;
- }
- }
-
- return nil;
-}
-
-void
-tile(Monitor *m)
-{
- uint i, n, h, r, mw, my, ty;
- Client *c;
-
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
- ;
-
- if (n == 0)
- return;
-
- if (n > m->nmaster)
- mw = m->nmaster ? (m->ww+gapx) * m->mfact : 0;
- else
- mw = m->ww - gapx;
-
- for (i = 0, my = ty = gapx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if (i < m->nmaster) {
- r = MIN(n, m->nmaster) - i;
- h = (m->wh - my)/r - gapx;
- resize(c, m->wx + gapx, m->wy + my, mw - (2*c->bw) - gapx, h - (2*c->bw), 0);
- if (my + HEIGHT(c) + gapx < m->wh)
- my += HEIGHT(c) + gapx;
- } else {
- r = (n-i);
- h = (m->wh - ty)/r - gapx;
- resize(c, m->wx + mw + gapx, m->wy + ty, m->ww - mw - (2*c->bw) - (2*gapx), h - (2*c->bw), 0);
- if (ty + HEIGHT(c) + gapx < m->wh)
- ty += HEIGHT(c) + gapx;
- }
-}
-
-void
-unmapnotify(XEvent *e)
-{
- Client *c;
- XUnmapEvent *ev = &e->xunmap;
-
- if ((c = wintoclient(ev->window))) {
- if (ev->send_event)
- setclientstate(c, WithdrawnState);
- else
- unmanage(c, 0);
- }
-}
-
-void
-updatebars(void)
-{
- Monitor *m;
- XSetWindowAttributes wa = {
- .override_redirect = True,
- .background_pixmap = ParentRelative,
- .event_mask = ButtonPressMask|ExposureMask
- };
- XClassHint ch = {"dwm", "dwm"};
- for (m = mons; m; m = m->next) {
- if (m->barwin)
- continue;
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
- CopyFromParent, DefaultVisual(dpy, screen),
- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
- XDefineCursor(dpy, m->barwin, cursor[MouseNormal]->cursor);
- XMapRaised(dpy, m->barwin);
- XSetClassHint(dpy, m->barwin, &ch);
- }
-}
-
-void
-updatebarpos(Monitor *m)
-{
- m->wy = m->my;
- m->wh = m->mh;
- if (m->showbar) {
- m->wh -= bh;
- m->by = m->topbar ? m->wy : m->wy + m->wh;
- m->wy = m->topbar ? m->wy + bh : m->wy;
- } else
- m->by = -bh;
-}
-
-void
-updateclientlist()
-{
- Client *c;
- Monitor *m;
-
- XDeleteProperty(dpy, root, netatom[NetClientList]);
- for (m = mons; m; m = m->next)
- for (c = m->clients; c; c = c->next)
- XChangeProperty(dpy, root, netatom[NetClientList],
- XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
-}
-
-int
-updategeom(void)
-{
- int dirty = 0;
-
- if (XineramaIsActive(dpy)) {
- int i, j, n, nn;
- Client *c;
- Monitor *m;
- XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
- XineramaScreenInfo *unique = nil;
-
- for (n = 0, m = mons; m; m = m->next, n++);
- /* only consider unique geometries as separate screens */
- unique = ecalloc(nn, sizeof(XineramaScreenInfo));
- for (i = 0, j = 0; i < nn; i++)
- if (isuniquegeom(unique, j, &info[i]))
- memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
- XFree(info);
- nn = j;
- if (n <= nn) { /* new monitors available */
- for (i = 0; i < (nn - n); i++) {
- for (m = mons; m && m->next; m = m->next);
- if (m)
- m->next = createmon();
- else
- mons = createmon();
- }
- for (i = 0, m = mons; i < nn && m; m = m->next, i++)
- if (i >= n
- || unique[i].x_org != m->mx || unique[i].y_org != m->my
- || unique[i].width != m->mw || unique[i].height != m->mh)
- {
- dirty = 1;
- m->num = i;
- m->mx = m->wx = unique[i].x_org;
- m->my = m->wy = unique[i].y_org;
- m->mw = m->ww = unique[i].width;
- m->mh = m->wh = unique[i].height;
- updatebarpos(m);
- }
- } else { /* less monitors available nn < n */
- for (i = nn; i < n; i++) {
- for (m = mons; m && m->next; m = m->next);
- while ((c = m->clients)) {
- dirty = 1;
- m->clients = c->next;
- detachstack(c);
- c->mon = mons;
- /* attach(c); */
- attachbottom(c);
- attachstack(c);
- }
- if (m == selmon)
- selmon = mons;
- cleanupmon(m);
- }
- }
- free(unique);
- } else
- { /* default monitor setup */
- if (!mons)
- mons = createmon();
- if (mons->mw != sw || mons->mh != sh) {
- dirty = 1;
- mons->mw = mons->ww = sw;
- mons->mh = mons->wh = sh;
- updatebarpos(mons);
- }
- }
- if (dirty) {
- selmon = mons;
- selmon = wintomon(root);
- }
- return dirty;
-}
-
-void
-updatenumlockmask(void)
-{
- uint i, j;
- XModifierKeymap *modmap;
-
- numlockmask = 0;
- modmap = XGetModifierMapping(dpy);
- for (i = 0; i < 8; i++)
- for (j = 0; j < modmap->max_keypermod; j++)
- if (modmap->modifiermap[i * modmap->max_keypermod + j]
- == XKeysymToKeycode(dpy, XK_Num_Lock))
- numlockmask = (1 << i);
- XFreeModifiermap(modmap);
-}
-
-void
-updatestatus(void)
-{
- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
- strcpy(stext, "dwm-"VERSION);
- drawbar(selmon);
-}
-
-pid_t
-winpid(Window w)
-{
- pid_t result = 0;
-
- xcb_res_client_id_spec_t spec = {0};
- spec.client = w;
- spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
-
- xcb_generic_error_t *e = NULL;
- xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
- xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
-
- if (!r)
- return (pid_t)0;
-
- xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
- for (; i.rem; xcb_res_client_id_value_next(&i)) {
- spec = i.data->spec;
- if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
- uint32_t *t = xcb_res_client_id_value_value(i.data);
- result = *t;
- break;
- }
- }
-
- free(r);
-
- if (result == (pid_t)-1)
- result = 0;
-
- return result;
-}
-
-Client *
-wintoclient(Window w)
-{
- Client *c;
- Monitor *m;
-
- for (m = mons; m; m = m->next)
- for (c = m->clients; c; c = c->next)
- if (c->win == w)
- return c;
- return nil;
-}
-
-Monitor *
-wintomon(Window w)
-{
- int x, y;
- Client *c;
- Monitor *m;
-
- if (w == root && getrootptr(&x, &y))
- return recttomon(x, y, 1, 1);
- for (m = mons; m; m = m->next)
- if (w == m->barwin)
- return m;
- if ((c = wintoclient(w)))
- return c->mon;
- return selmon;
-}
-
-/* There's no way to check accesses to destroyed windows, thus those cases are
- * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
- * default error handler, which may call exit. */
-int
-xerror(Display *dpy, XErrorEvent *ee)
-{
- if (ee->error_code == BadWindow
- || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
- || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
- || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
- || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
- || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
- || (ee->request_code == X_GrabButton && ee->error_code == BadAccess)
- || (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
- || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
- return 0;
- fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
- ee->request_code, ee->error_code);
- return xerrorxlib(dpy, ee); /* may call exit */
-}
-
-int
-xerrordummy(Display *dpy, XErrorEvent *ee)
-{
- return 0;
-}
-
-/* Startup Error handler to check if another window manager
- * is already running. */
-int
-xerrorstart(Display *dpy, XErrorEvent *ee)
-{
- fatal("dwm: another window manager is already running");
- return -1;
-}
-
-int
-main(int argc, char *argv[])
-{
- if (argc == 2 && !strcmp("-v", argv[1]))
- fatal("dwm-"VERSION);
- else if (argc != 1)
- fatal("usage: dwm [-v]");
- if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
- fputs("warning: no locale support\n", stderr);
- if (!(dpy = XOpenDisplay(nil)))
- fatal("dwm: cannot open display");
- if (!(xcon = XGetXCBConnection(dpy)))
- fatal("dwm: cannot get xcb connection");
-
- checkotherwm();
- setup();
-
-#ifdef __OpenBSD__
- if (pledge("stdio rpath proc exec", nil) == -1)
- fatal("pledge");
-#endif /* __OpenBSD__ */
-
- scan();
- run();
- cleanup();
-
- XCloseDisplay(dpy);
- return 0;
-}
diff --git a/sys/cmd/dwm/dwm.h b/sys/cmd/dwm/dwm.h
deleted file mode 100644
index afec1f2..0000000
--- a/sys/cmd/dwm/dwm.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#pragma once
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-
-#include <errno.h>
-#include <locale.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <X11/cursorfont.h>
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#include <X11/XKBlib.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/Xlib-xcb.h>
-#include <xcb/res.h>
-#include <X11/extensions/Xinerama.h>
-#include <X11/Xft/Xft.h>
-#include <X11/XF86keysym.h>
-
-/* macros */
-#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
-#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
-#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
- * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
-#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
-#define WIDTH(X) ((X)->w + 2 * (X)->bw)
-#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
-#define TAGMASK ((1 << arrlen(tags)) - 1)
-#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
-#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
-
-
-/* enums */
-enum
-{
- MouseNormal,
- MouseResize,
- MouseMove,
- MouseLast,
-}; /* mouse states */
-
-enum
-{
- SchemeNorm,
- SchemeSel
-}; /* color schemes */
-
-enum
-{
- NetSupported,
- NetWMName,
- NetWMState,
- NetWMCheck,
- NetWMFullscreen,
- NetActiveWindow,
- NetWMWindowType,
- NetWMWindowTypeDialog,
- NetWMWindowOpacity,
- NetClientList,
- NetLast
-}; /* EWMH atoms */
-
-enum
-{
- WMProtocols,
- WMDelete,
- WMState,
- WMTakeFocus,
- WMLast
-}; /* default atoms */
-
-enum
-{
- ClkTagBar,
- ClkLtSymbol,
- ClkStatusText,
- ClkWinTitle,
- ClkClientWin,
- ClkRootWin,
- ClkLast
-}; /* clicks */
-
-enum
-{
- ColFg,
- ColBg,
- ColBorder
-}; /* color scheme index */
-
-typedef struct Monitor Monitor;
-typedef struct Layout Layout;
-typedef struct Client Client;
-typedef struct Keyboard Keyboard;
-typedef struct Button Button;
-typedef struct Key Key;
-typedef struct Rule Rule;
-typedef union Arg Arg;
-
-union Arg {
- int i;
- uint ui;
- float f;
- void *v;
-};
-
-struct Button {
- uint click;
- uint mask;
- uint button;
- void (*func)(Arg *arg);
- Arg arg;
-};
-
-struct Client {
- char name[256];
- float mina, maxa;
- int x, y, w, h;
- int oldx, oldy, oldw, oldh;
- int basew, baseh, incw, inch, maxw, maxh, minw, minh;
- int bw, oldbw;
- uint tags;
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterm, noswallow;
- pid_t pid;
- Client *next;
- Client *snext;
- Client *swallowing;
- Monitor *mon;
- Window win;
-};
-
-struct Key {
- uint mod;
- KeySym keysym;
- void (*func)(Arg *);
- Arg arg;
-};
-
-struct Layout {
- char *symbol;
- void (*arrange)(Monitor *);
-};
-
-struct Monitor {
- char ltsymbol[16];
- float mfact;
- int nmaster;
- int num;
- int by; /* bar geometry */
- int mx, my, mw, mh; /* screen size */
- int wx, wy, ww, wh; /* window area */
- uint seltags;
- uint sellt;
- uint tagset[2];
- int showbar;
- int topbar;
- Client *clients;
- Client *sel;
- Client *stack;
- Monitor *next;
- Window barwin;
- Layout *lt[2];
-};
-
-struct Rule {
- char *class;
- char *instance;
- char *title;
- uint tags;
- int isfloating;
- int isterm;
- int noswallow;
- int monitor;
-};
-
-/* draw.c */
-typedef struct {
- Cursor cursor;
-} Cur;
-
-typedef struct Fnt {
- Display *dpy;
- uint h;
- XftFont *xfont;
- FcPattern *pattern;
- struct Fnt *next;
-} Fnt;
-
-typedef XftColor Clr;
-
-typedef struct {
- uint w, h;
- Display *dpy;
- int screen;
- Window root;
- Drawable drawable;
- GC gc;
- Clr *scheme;
- Fnt *fonts;
-} Drw;
-
-/* global state */
-
-extern char broken[];
-extern char stext[256];
-extern int scanner;
-extern int screen;
-extern int sw, sh;
-extern int bh, blw;
-extern int lrpad;
-extern int (*xerrorxlib)(Display *, XErrorEvent *);
-extern uint numlockmask;
-extern void (*handler[LASTEvent]) (XEvent *);
-extern int scratchtag;
-
-extern xcb_connection_t *xcon;
-
-extern Atom wmatom[WMLast], netatom[NetLast];
-extern int running;
-extern Cur *cursor[MouseLast];
-extern Clr **scheme;
-extern Display *dpy;
-extern Drw *drw;
-extern Monitor *mons, *selmon;
-extern Window root, wmcheckwin;
-
-// -----------------------------------------------------------------------
-// function declarations
-
-// TODO: remove declarations that don't require global existence...
-void applyrules(Client *c);
-int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
-void arrange(Monitor *m);
-void arrangemon(Monitor *m);
-void attach(Client *c);
-void enqueue(Client *c);
-void attachbottom(Client *c);
-void attachstack(Client *c);
-void enqueuestack(Client *c);
-void buttonpress(XEvent *e);
-void checkotherwm(void);
-void cleanup(void);
-void cleanupmon(Monitor *mon);
-void clientmessage(XEvent *e);
-void configure(Client *c);
-void configurenotify(XEvent *e);
-void configurerequest(XEvent *e);
-Monitor *createmon(void);
-void destroynotify(XEvent *e);
-void detach(Client *c);
-void detachstack(Client *c);
-Monitor *dirtomon(int dir);
-void drawbar(Monitor *m);
-void drawbars(void);
-void enternotify(XEvent *e);
-void expose(XEvent *e);
-void focus(Client *c);
-void focusin(XEvent *e);
-void focusmon(Arg *arg);
-void focusstack(Arg *arg);
-void focusdirection(Arg *arg);
-void rotatestack(Arg *arg);
-Atom getatomprop(Client *c, Atom prop);
-int getrootptr(int *x, int *y);
-long getstate(Window w);
-int gettextprop(Window w, Atom atom, char *text, uint size);
-void grabbuttons(Client *c, int focused);
-void grabkeys(void);
-void incnmaster(Arg *arg);
-void keypress(XEvent *e);
-void killclient(Arg *arg);
-void manage(Window w, XWindowAttributes *wa);
-void mappingnotify(XEvent *e);
-void maprequest(XEvent *e);
-void monocle(Monitor *m);
-void motionnotify(XEvent *e);
-void movemouse(Arg *arg);
-Client *nexttiled(Client *c);
-void pop(Client *);
-void propertynotify(XEvent *e);
-void quit(Arg *arg);
-Monitor *recttomon(int x, int y, int w, int h);
-void resize(Client *c, int x, int y, int w, int h, int interact);
-void resizeclient(Client *c, int x, int y, int w, int h);
-void resizemouse(Arg *arg);
-void restack(Monitor *m);
-void run(void);
-void scan(void);
-int sendevent(Client *c, Atom proto);
-void sendtomon(Client *c, Monitor *m);
-void setclientstate(Client *c, long state);
-void setfocus(Client *c);
-void setfullscreen(Client *c, int fullscreen);
-void setlayout(Arg *arg);
-void setmfact(Arg *arg);
-void setup(void);
-void seturgent(Client *c, int urg);
-void showhide(Client *c);
-void sigchld(int unused);
-void swallow(Client *p, Client *c);
-Client *swallowing(Window w);
-void spawn(Arg *arg);
-void tag(Arg *arg);
-void tagmon(Arg *arg);
-Client *termof(Client *c);
-void tile(Monitor *);
-void togglebar(Arg *arg);
-void togglefocus(Arg *arg);
-void togglefloating(Arg *arg);
-void togglescratch(Arg *arg);
-void toggletag(Arg *arg);
-void toggleview(Arg *arg);
-void unfocus(Client *c, int setfocus);
-void unmanage(Client *c, int destroyed);
-void unmapnotify(XEvent *e);
-void unswallow(Client *c);
-void updatebarpos(Monitor *m);
-void updatebars(void);
-void updateclientlist(void);
-int updategeom(void);
-void updatenumlockmask(void);
-void updatesizehints(Client *c);
-void updatestatus(void);
-void updatetitle(Client *c);
-void updatewindowtype(Client *c);
-void updatewmhints(Client *c);
-void view(Arg *arg);
-pid_t winpid(Window w);
-Client *wintoclient(Window w);
-Monitor *wintomon(Window w);
-int xerror(Display *dpy, XErrorEvent *ee);
-int xerrordummy(Display *dpy, XErrorEvent *ee);
-int xerrorstart(Display *dpy, XErrorEvent *ee);
-void zoom(Arg *arg);
-
-#include "config.h"
-
-/* draw.c */
-
-/* Drawable abstraction */
-Drw *drw_create(Display *dpy, int screen, Window win, uint w, uint h);
-void drw_resize(Drw *drw, uint w, uint h);
-void drw_free(Drw *drw);
-
-/* Fnt abstraction */
-Fnt *drw_fontset_create(Drw* drw, char *fonts[], size_t fontcount);
-void drw_fontset_free(Fnt* set);
-uint drw_fontset_getwidth(Drw *drw, char *text);
-void drw_font_getexts(Fnt *font, char *text, uint len, uint *w, uint *h);
-
-/* Colorscheme abstraction */
-void drw_clr_create(Drw *drw, Clr *dest, char *clrname);
-Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
-
-/* Cursor abstraction */
-Cur *drw_cur_create(Drw *drw, int shape);
-void drw_cur_free(Drw *drw, Cur *cursor);
-
-/* Drawing context manipulation */
-void drw_setfontset(Drw *drw, Fnt *set);
-void drw_setscheme(Drw *drw, Clr *scm);
-
-/* Drawing functions */
-void drw_rect(Drw *drw, int x, int y, uint w, uint h, int filled, int invert);
-int drw_text(Drw *drw, int x, int y, uint w, uint h, uint lpad, char *text, int invert);
-
-/* Map functions */
-void drw_map(Drw *drw, Window win, int x, int y, uint w, uint h);
-
-/* util.c */
-void fatal(char *fmt, ...);
-void *ecalloc(size_t nmemb, size_t size);
-pid_t getparentproc(pid_t p);
-pid_t isdescendent(pid_t p, pid_t c);
diff --git a/sys/cmd/dwm/hook.c b/sys/cmd/dwm/hook.c
deleted file mode 100644
index 9758965..0000000
--- a/sys/cmd/dwm/hook.c
+++ /dev/null
@@ -1,489 +0,0 @@
-#include "dwm.h"
-
-int scratchtag = 1 << arrlen(tags);
-
-void
-focusmon(Arg *arg)
-{
- Monitor *m;
-
- if (!mons->next)
- return;
- if ((m = dirtomon(arg->i)) == selmon)
- return;
- unfocus(selmon->sel, 0);
- selmon = m;
- focus(nil);
-}
-
-void
-focusstack(Arg *arg)
-{
- Client *c = nil, *i;
-
- if (!selmon->sel)
- return;
- if (arg->i > 0) {
- for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
- if(!c)
- for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
- } else {
- for(i = selmon->clients; i != selmon->sel; i = i->next)
- if(ISVISIBLE(i))
- c = i;
- if(!c)
- for(; i; i = i->next)
- if (ISVISIBLE(i))
- c = i;
- }
- if(c) {
- focus(c);
- restack(selmon);
- }
-}
-
-void
-focusdirection(Arg *arg)
-{
- Monitor *m;
- Client *it, *c;
- int x, y, cx, cy;
-
- if(!selmon || !selmon->sel)
- return;
-
- c = selmon->sel;
- x = c->x, y = c->y;
-
- c = nil;
- switch(arg->i) {
- case 'l':
- cx = INT_MIN;
- cy = y;
- for(m=mons; m; m=m->next) {
- for(it=m->clients; it; it = it->next) {
- if(ISVISIBLE(it) && (it->x < x)) {
- if((it->x > cx) || ((it->x == cx) && abs(y-it->y) < abs(y-cy))) {
- c = it;
- cx = it->x;
- cy = it->y;
- }
- }
- }
- }
- break;
-
- case 'r':
- cx = INT_MAX;
- cy = y;
- for(m=mons; m; m=m->next) {
- for(it=m->clients; it; it = it->next) {
- if(ISVISIBLE(it) && (it->x > x)) {
- if((it->x < cx) || ((it->x == cx) && abs(y-it->y) < abs(y-cy))) {
- c = it;
- cx = it->x;
- cy = it->y;
- }
- }
- }
- }
- break;
-
- case 'u':
- cx = x;
- cy = INT_MIN;
- for(m=mons; m; m=m->next) {
- for(it=m->clients; it; it = it->next) {
- if(ISVISIBLE(it) && (it->y < y)) {
- if((it->y > cy) || ((it->y == cy) && abs(x-it->x) < abs(x-cx))) {
- c = it;
- cx = it->x;
- cy = it->y;
- }
- }
- }
- }
- break;
-
- case 'd':
- cx = x;
- cy = INT_MAX;
- for(m=mons; m; m=m->next) {
- for(it=m->clients; it; it = it->next) {
- if(ISVISIBLE(it) && (it->y > y)) {
- if((it->y < cy) || ((it->y == cy) && abs(x-it->x) < abs(x-cx))) {
- c = it;
- cx = it->x;
- cy = it->y;
- }
- }
- }
- }
- break;
-
- default:
- ;
- }
-
- if(c) {
- focus(c);
- restack(selmon);
- if(c->mon != selmon)
- restack(c->mon);
- }
-}
-
-void
-rotatestack(Arg *arg)
-{
- Client *c = nil, *f;
-
- if (!selmon->sel)
- return;
-
- f = selmon->sel;
- if (arg->i > 0) {
- for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next))
- ;
-
- if (c) {
- detach(c);
- attach(c);
- detachstack(c);
- attachstack(c);
- }
- } else {
- if ((c = nexttiled(selmon->clients))) {
- detach(c);
- enqueue(c);
- detachstack(c);
- enqueuestack(c);
- }
- }
-
- if (c) {
- arrange(selmon);
- focus(f);
- restack(selmon);
- }
-}
-
-
-void
-incnmaster(Arg *arg)
-{
- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
- arrange(selmon);
-}
-
-void
-killclient(Arg *arg)
-{
- if (!selmon->sel)
- return;
- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
- XGrabServer(dpy);
- XSetErrorHandler(xerrordummy);
- XSetCloseDownMode(dpy, DestroyAll);
- XKillClient(dpy, selmon->sel->win);
- XSync(dpy, False);
- XSetErrorHandler(xerror);
- XUngrabServer(dpy);
- }
-}
-
-void
-movemouse(Arg *arg)
-{
- int x, y, ocx, ocy, nx, ny;
- Client *c;
- Monitor *m;
- XEvent ev;
- Time lasttime = 0;
-
- if (!(c = selmon->sel))
- return;
- if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
- return;
- restack(selmon);
- ocx = c->x;
- ocy = c->y;
- if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
- None, cursor[MouseMove]->cursor, CurrentTime) != GrabSuccess)
- return;
- if (!getrootptr(&x, &y))
- return;
- do {
- XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
- switch(ev.type) {
- case ConfigureRequest:
- case Expose:
- case MapRequest:
- handler[ev.type](&ev);
- break;
- case MotionNotify:
- if ((ev.xmotion.time - lasttime) <= (1000 / 60))
- continue;
- lasttime = ev.xmotion.time;
-
- nx = ocx + (ev.xmotion.x - x);
- ny = ocy + (ev.xmotion.y - y);
- if (abs(selmon->wx - nx) < snap)
- nx = selmon->wx;
- else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
- nx = selmon->wx + selmon->ww - WIDTH(c);
- if (abs(selmon->wy - ny) < snap)
- ny = selmon->wy;
- else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
- ny = selmon->wy + selmon->wh - HEIGHT(c);
- if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
- && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
- togglefloating(nil);
- if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
- resize(c, nx, ny, c->w, c->h, 1);
- break;
- }
- } while (ev.type != ButtonRelease);
- XUngrabPointer(dpy, CurrentTime);
- if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
- sendtomon(c, m);
- selmon = m;
- focus(nil);
- }
-}
-
-void
-quit(Arg *arg)
-{
- running = 0;
-}
-
-void
-resizemouse(Arg *arg)
-{
- int ocx, ocy, nw, nh;
- Client *c;
- Monitor *m;
- XEvent ev;
- Time lasttime = 0;
-
- if (!(c = selmon->sel))
- return;
- if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */
- return;
- restack(selmon);
- ocx = c->x;
- ocy = c->y;
- if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
- None, cursor[MouseResize]->cursor, CurrentTime) != GrabSuccess)
- return;
- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
- do {
- XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
- switch(ev.type) {
- case ConfigureRequest:
- case Expose:
- case MapRequest:
- handler[ev.type](&ev);
- break;
- case MotionNotify:
- if ((ev.xmotion.time - lasttime) <= (1000 / 60))
- continue;
- lasttime = ev.xmotion.time;
-
- nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
- nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
- if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
- && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
- {
- if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
- && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
- togglefloating(nil);
- }
- if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
- resize(c, c->x, c->y, nw, nh, 1);
- break;
- }
- } while (ev.type != ButtonRelease);
- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
- XUngrabPointer(dpy, CurrentTime);
- while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
- if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
- sendtomon(c, m);
- selmon = m;
- focus(nil);
- }
-}
-
-void
-setlayout(Arg *arg)
-{
- if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
- selmon->sellt ^= 1;
- if (arg && arg->v)
- selmon->lt[selmon->sellt] = (Layout *)arg->v;
- strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
- if (selmon->sel)
- arrange(selmon);
- else
- drawbar(selmon);
-}
-
-/* arg > 1.0 will set mfact absolutely */
-void
-setmfact(Arg *arg)
-{
- float f;
-
- if (!arg || !selmon->lt[selmon->sellt]->arrange)
- return;
- f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
- if (f < 0.05 || f > 0.95)
- return;
- selmon->mfact = f;
- arrange(selmon);
-}
-
-void
-spawn(Arg *arg)
-{
- selmon->tagset[selmon->seltags] &= ~scratchtag;
-
- if (fork() == 0) {
- if (dpy)
- close(ConnectionNumber(dpy));
- setsid();
- execvp(((char **)arg->v)[0], (char **)arg->v);
- fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
- perror(" failed");
- exit(EXIT_SUCCESS);
- }
-}
-
-void
-tag(Arg *arg)
-{
- if (selmon->sel && arg->ui & TAGMASK) {
- selmon->sel->tags = arg->ui & TAGMASK;
- focus(nil);
- arrange(selmon);
- }
-}
-
-void
-tagmon(Arg *arg)
-{
- if (!selmon->sel || !mons->next)
- return;
- sendtomon(selmon->sel, dirtomon(arg->i));
-}
-
-void
-togglebar(Arg *arg)
-{
- selmon->showbar = !selmon->showbar;
- updatebarpos(selmon);
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
- arrange(selmon);
-}
-
-void
-togglefloating(Arg *arg)
-{
- if (!selmon->sel)
- return;
- if (selmon->sel->isfullscreen) /* no support for fullscreen windows */
- return;
- selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed;
- if (selmon->sel->isfloating)
- resize(selmon->sel, selmon->sel->x, selmon->sel->y,
- selmon->sel->w, selmon->sel->h, 0);
- arrange(selmon);
-}
-
-void
-togglescratch(Arg *arg)
-{
- Client *c;
- uint f = 0;
-
- for(c = selmon->clients; c && !(f = (c->tags & scratchtag)); c = c->next)
- ;
-
- if(f) {
- f = selmon->tagset[selmon->seltags] ^ scratchtag;
- if(f) {
- selmon->tagset[selmon->seltags] = f;
- focus(nil);
- arrange(selmon);
- }
- if(ISVISIBLE(c)) {
- focus(c);
- restack(selmon);
- }
- } else
- spawn(arg);
-
-}
-
-void
-toggletag(Arg *arg)
-{
- uint newtags;
- if (!selmon->sel)
- return;
-
- newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
- if (newtags) {
- selmon->sel->tags = newtags;
- focus(nil);
- arrange(selmon);
- }
-}
-
-void
-togglefocus(Arg *arg)
-{
- if (selmon->sel)
- setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
-
- togglebar(arg);
-}
-
-void
-toggleview(Arg *arg)
-{
- uint newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
-
- if (newtagset) {
- selmon->tagset[selmon->seltags] = newtagset;
- focus(nil);
- arrange(selmon);
- }
-}
-
-void
-view(Arg *arg)
-{
- if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
- return;
- selmon->seltags ^= 1; /* toggle sel tagset */
- if (arg->ui & TAGMASK)
- selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
- focus(nil);
- arrange(selmon);
-}
-
-void
-zoom(Arg *arg)
-{
- Client *c = selmon->sel;
-
- if (!selmon->lt[selmon->sellt]->arrange
- || (selmon->sel && selmon->sel->isfloating))
- return;
- if (c == nexttiled(selmon->clients))
- if (!c || !(c = nexttiled(c->next)))
- return;
- pop(c);
-}
diff --git a/sys/cmd/dwm/rules.mk b/sys/cmd/dwm/rules.mk
deleted file mode 100644
index 79c4548..0000000
--- a/sys/cmd/dwm/rules.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-include share/push.mk
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := \
- $(d)/drw.c \
- $(d)/hook.c \
- $(d)/client.c \
- $(d)/util.c \
- $(d)/dwm.c
-BINS_$(d) := $(d)/dwm
-
-include share/paths.mk
-
-# Local rules
-include share/dynamic.mk
-$(BINS_$(d)): TCFLAGS = \
- `$(PKG) --cflags fontconfig` \
- `$(PKG) --cflags freetype2`
-$(BINS_$(d)): TCLIBS = \
- `$(PKG) --libs fontconfig` \
- `$(PKG) --libs freetype2` \
- -lX11 -lXinerama -lXft -lX11-xcb -lxcb -lxcb-res
-
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/libutf/libutf.a $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/dwm/util.c b/sys/cmd/dwm/util.c
deleted file mode 100644
index 0db71cc..0000000
--- a/sys/cmd/dwm/util.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "dwm.h"
-
-void
-fatal(char *fmt, ...) {
- va_list args;
-
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
-
- if(fmt[0] && fmt[strlen(fmt)-1] == ':') {
- fputc(' ', stderr);
- perror(NULL);
- } else {
- fputc('\n', stderr);
- }
-
- exit(1);
-}
-
-void *
-ecalloc(size_t nmemb, size_t size)
-{
- void *p;
-
- if (!(p = calloc(nmemb, size)))
- fatal("calloc:");
- return p;
-}
-
-pid_t
-getparentprocess(pid_t p)
-{
- uint v = 0;
-
-#if defined(__linux__)
- io·Stream *f;
- char buf[256];
- snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
-
- if (!(f = fopen(buf, "r")))
- return (pid_t)0;
-
- if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1)
- v = (pid_t)0;
- fclose(f);
-#elif defined(__FreeBSD__)
- struct kinfo_proc *proc = kinfo_getproc(p);
- if (!proc)
- return (pid_t)0;
-
- v = proc->ki_ppid;
- free(proc);
-#endif
- return (pid_t)v;
-}
-
-int
-isdescendent(pid_t p, pid_t c)
-{
- while (p != c && c != 0)
- c = getparentprocess(c);
-
- return (int)c;
-}
diff --git a/sys/cmd/filter/filter.c b/sys/cmd/filter/filter.c
deleted file mode 100644
index abc9a88..0000000
--- a/sys/cmd/filter/filter.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include <u.h>
-#include <base.h>
-
-#include <dirent.h>
-#include <sys/stat.h>
-
-#define FLAG(x) (flag[(x)-'a'])
-
-static void filter(const char *, const char *);
-static void usage(void);
-
-static int match = 0;
-static int flag[26];
-static struct stat old, new;
-
-static
-void
-filter(const char *path, const char *name)
-{
- struct stat st, ln;
-
- if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /* hidden files */
- && (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */
- && (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */
- && (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */
- && (!FLAG('e') || access(path, F_OK) == 0) /* exists */
- && (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */
- && (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */
- && (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */
- && (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */
- && (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */
- && (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */
- && (!FLAG('r') || access(path, R_OK) == 0) /* readable */
- && (!FLAG('s') || st.st_size > 0) /* not empty */
- && (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */
- && (!FLAG('w') || access(path, W_OK) == 0) /* writable */
- && (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /* executable */
- if (FLAG('q'))
- exit(0);
- match = 1;
- puts(name);
- }
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] "
- "[-n file] [-o file] [file...]\n", argv0);
- exit(2); /* like test(1) return > 1 on error */
-}
-
-int
-main(int argc, char *argv[])
-{
- struct dirent *d;
- char path[PATH_MAX], *line = NULL, *file;
- size_t linesiz = 0;
- ssize_t n;
- DIR *dir;
- int r;
-
- ARGBEGIN {
- case 'n': /* newer than file */
- case 'o': /* older than file */
- file = EARGF(usage());
- if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new : &old))))
- perror(file);
- break;
- default:
- /* miscellaneous operators */
- if (strchr("abcdefghlpqrsuvwx", ARGC()))
- FLAG(ARGC()) = 1;
- else
- usage(); /* unknown flag */
- } ARGEND;
-
- if (!argc) {
- /* read list from stdin */
- while ((n = getline(&line, &linesiz, stdin)) > 0) {
- if (n && line[n - 1] == '\n')
- line[n - 1] = '\0';
- filter(line, line);
- }
- free(line);
- } else {
- for (; argc; argc--, argv++) {
- if (FLAG('l') && (dir = opendir(*argv))) {
- /* filter directory contents */
- while ((d = readdir(dir))) {
- r = snprintf(path, sizeof path, "%s/%s",
- *argv, d->d_name);
- if (r >= 0 && (size_t)r < sizeof path)
- filter(path, d->d_name);
- }
- closedir(dir);
- } else {
- filter(*argv, *argv);
- }
- }
- }
- return match ? 0 : 1;
-}
diff --git a/sys/cmd/filter/rules.mk b/sys/cmd/filter/rules.mk
deleted file mode 100644
index 31bb257..0000000
--- a/sys/cmd/filter/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := $(d)/filter.c
-BINS_$(d) := $(d)/filter
-
-include share/paths.mk
-
-# Local rules
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/ic/LICENSE b/sys/cmd/ic/LICENSE
deleted file mode 100644
index a5816a8..0000000
--- a/sys/cmd/ic/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-MIT/X Consortium License
-
-(C)opyright 2014-2018 Hiltjo Posthuma <hiltjo at codemadness dot org>
-(C)opyright 2005-2006 Anselm R. Garbe <garbeam@wmii.de>
-(C)opyright 2005-2011 Nico Golde <nico at ngolde dot de>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/sys/cmd/ic/ic.1 b/sys/cmd/ic/ic.1
deleted file mode 100644
index 3302dad..0000000
--- a/sys/cmd/ic/ic.1
+++ /dev/null
@@ -1,100 +0,0 @@
-.TH II 1 ic\-VERSION
-.SH NAME
-ic \- irc it or irc improved
-.SH DESCRIPTION
-.B ic
-is a minimalistic FIFO and filesystem based IRC client.
-It creates an irc directory tree with server, channel and
-nick name directories.
-In every directory a FIFO file (in) and normal file (out)
-is placed. This will be for example ~/irc/irc.freenode.net/.
-The in file is used to communicate with the servers and the out
-files includes the server messages. For every channel and every nick
-name there will be new in and out files.
-The basic idea of this is to be able to communicate with an IRC
-server with basic command line tools.
-For example if you will join a channel just do echo "/j #channel" > in
-and ic creates a new channel directory with in and out file.
-.SH SYNOPSIS
-.B ic
-.RB < \-s
-.IR servername >
-.RB [ \-p
-.IR port ]
-.RB [ \-k
-.IR "environment variable" ]
-.RB [ \-i
-.IR prefix ]
-.RB [ \-n
-.IR nickname ]
-.RB [ \-f
-.IR realname ]
-.RB < \-u
-.IR sockname >
-.SH OPTIONS
-.TP
-.BI \-s " servername"
-server to connect to, for example: irc.freenode.net
-.TP
-.BI \-u " sockname"
-connect to a UNIX domain socket instead of directly to a server.
-.TP
-.BI \-p " port"
-lets you override the default port (6667)
-.TP
-.BI \-k " environment variable"
-lets you specify an environment variable that contains your IRC password, e.g. IIPASS="foobar" ic -k IIPASS.
-This is done in order to prevent other users from eavesdropping the server password via the process list.
-.TP
-.BI \-i " prefix"
-lets you override the default irc path (~/irc)
-.TP
-.BI \-n " nickname"
-lets you override the default nick ($USER)
-.TP
-.BI \-f " realname"
-lets you specify your real name associated with your nick
-.SH DIRECTORIES
-.TP
-.B ~/irc
-In this directory the irc tree will be created. In this directory you
-will find a directory for your server (default: irc.freenode.net) in
-which the FIFO and the output file will be stored.
-If you join a channel a new directory with the name of the channel
-will be created in the ~/irc/$servername/ directory.
-.SH COMMANDS
-.TP
-.BI /a " [<message>]"
-mark yourself as away
-.TP
-.BI /j " #channel/nickname [<message>]"
-join a channel or open private conversation with user
-.TP
-.BI /l " [reason]"
-leave a channel or query
-.TP
-.BI /n " nick"
-change the nick name
-.TP
-.BI /q " [reason]"
-quit ic
-.TP
-.BI /t " topic"
-set the topic of a channel
-.SH RAW COMMANDS
-.LP
-Everything which is not a command will be posted into the channel or to the server.
-So if you need /who just write /WHO as described in RFC#1459 to the server in FIFO.
-.SH SSL PROTOCOL SUPPORT
-.LP
-For TLS/SSL protocol support you can connect to a local tunnel, for example with stunnel or socat.
-.SH CONTACT
-.LP
-Subscribe to the mailinglist and write to dev (at) suckless (dot) org for suggestions, fixes, etc.
-.SH AUTHORS
-ic engineers, see LICENSE file
-.SH SEE ALSO
-.BR echo (1),
-.BR tail (1)
-.SH BUGS
-Please report them!
diff --git a/sys/cmd/ic/ic.c b/sys/cmd/ic/ic.c
deleted file mode 100644
index 7fc37d8..0000000
--- a/sys/cmd/ic/ic.c
+++ /dev/null
@@ -1,878 +0,0 @@
-/* See LICENSE file for license details. */
-#include <u.h>
-#include <base.h>
-
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-
-#include <time.h>
-#include <signal.h>
-
-#include <netdb.h>
-#include <netinet/in.h>
-
-size_t strlcpy(char *, const char *, size_t);
-
-#define IRC_CHANNEL_MAX 200
-#define IRC_MSG_MAX 512 /* guaranteed to be <= than PIPE_BUF */
-#define PING_TIMEOUT 300
-
-enum { TOK_NICKSRV = 0, TOK_USER, TOK_CMD, TOK_CHAN, TOK_ARG, TOK_TEXT, TOK_LAST };
-
-typedef struct Channel Channel;
-struct Channel {
- int fdin;
- char name[IRC_CHANNEL_MAX]; /* channel name (normalized) */
- char inpath[PATH_MAX]; /* input path */
- char outpath[PATH_MAX]; /* output path */
- Channel *next;
-};
-
-static Channel * channel_add(const char *);
-static Channel * channel_find(const char *);
-static Channel * channel_join(const char *);
-static void channel_leave(Channel *);
-static Channel * channel_new(const char *);
-static void channel_normalize_name(char *);
-static void channel_normalize_path(char *);
-static int channel_open(Channel *);
-static void channel_print(Channel *, const char *);
-static int channel_reopen(Channel *);
-static void channel_rm(Channel *);
-
-static void create_dirtree(const char *);
-static void create_filepath(char *, size_t, const char *, const char *, const char *);
-static void ewritestr(int, const char *);
-static void handle_channels_input(int, Channel *);
-static void handle_server_output(int);
-static int isnumeric(const char *);
-static void loginkey(int, const char *);
-static void loginuser(int, const char *, const char *);
-static void proc_channels_input(int, Channel *, char *);
-static void proc_channels_privmsg(int, Channel *, char *);
-static void proc_server_cmd(int, char *);
-static int read_line(int, char *, size_t);
-static void run(int, const char *);
-static void setup(void);
-static void sighandler(int);
-static int tcpopen(const char *, const char *);
-static size_t tokenize(char **, size_t, char *, int);
-static int udsopen(const char *);
-static void usage(void);
-
-static int isrunning = 1;
-static time_t last_response = 0;
-static Channel *channels = nil;
-static Channel *channelmaster = nil;
-static char nick[32], _nick[arrlen(nick)]; /* active nickname at runtime */
-static char ircpath[PATH_MAX]; /* irc dir (-i) */
-static char msg[IRC_MSG_MAX]; /* message buf used for communication */
-
-static
-void
-usage(void)
-{
- fprintf(stderr, "usage: %s <-s host> [-i <irc dir>] [-p <port>] "
- "[-u <sockname>] [-n <nick>] [-k <password>] "
- "[-f <fullname>]\n", argv0);
- exit(1);
-}
-
-static
-void
-ewritestr(int fd, const char *s)
-{
- size_t len, off = 0;
- int w = -1;
-
- len = strlen(s);
- for (off = 0; off < len; off += w) {
- if ((w = write(fd, s + off, len - off)) == -1)
- break;
- off += w;
- }
- if (w == -1) {
- fprintf(stderr, "%s: write: %s\n", argv0, strerror(errno));
- exit(1);
- }
-}
-
-/* creates directories bottom-up, if necessary */
-static
-void
-create_dirtree(const char *dir)
-{
- char tmp[PATH_MAX], *p;
- struct stat st;
- size_t len;
-
- strlcpy(tmp, dir, sizeof(tmp));
- len = strlen(tmp);
- if (len > 0 && tmp[len - 1] == '/')
- tmp[len - 1] = '\0';
-
- if ((stat(tmp, &st) != -1) && S_ISDIR(st.st_mode))
- return; /* dir exists */
-
- for (p = tmp + 1; *p; p++) {
- if (*p != '/')
- continue;
- *p = '\0';
- mkdir(tmp, S_IRWXU);
- *p = '/';
- }
- mkdir(tmp, S_IRWXU);
-}
-
-static
-void
-channel_normalize_path(char *s)
-{
- for (; *s; s++) {
- if (isalpha((unsigned char)*s))
- *s = tolower((unsigned char)*s);
- else if (!isdigit((unsigned char)*s) && !strchr(".#&+!-", *s))
- *s = '_';
- }
-}
-
-static
-void
-channel_normalize_name(char *s)
-{
- char *p;
-
- while (*s == '&' || *s == '#')
- s++;
- for (p = s; *s; s++) {
- if (!strchr(" ,&#\x07", *s)) {
- *p = *s;
- p++;
- }
- }
- *p = '\0';
-}
-
-static
-void
-create_filepath(char *filepath, size_t len, const char *path,
- const char *channel, const char *suffix)
-{
- int r;
-
- if (channel[0]) {
- r = snprintf(filepath, len, "%s/%s", path, channel);
- if (r < 0 || (size_t)r >= len)
- goto error;
- create_dirtree(filepath);
- r = snprintf(filepath, len, "%s/%s/%s", path, channel, suffix);
- if (r < 0 || (size_t)r >= len)
- goto error;
- } else {
- r = snprintf(filepath, len, "%s/%s", path, suffix);
- if (r < 0 || (size_t)r >= len)
- goto error;
- }
- return;
-
-error:
- fprintf(stderr, "%s: path to irc directory too long\n", argv0);
- exit(1);
-}
-
-static
-int
-channel_open(Channel *c)
-{
- int fd;
- struct stat st;
-
- /* make "in" fifo if it doesn't exist already. */
- if (lstat(c->inpath, &st) != -1) {
- if (!(st.st_mode & S_IFIFO))
- return -1;
- } else if (mkfifo(c->inpath, S_IRWXU)) {
- return -1;
- }
- c->fdin = -1;
- fd = open(c->inpath, O_RDONLY | O_NONBLOCK, 0);
- if (fd == -1)
- return -1;
- c->fdin = fd;
-
- return 0;
-}
-
-static
-int
-channel_reopen(Channel *c)
-{
- if (c->fdin > 2) {
- close(c->fdin);
- c->fdin = -1;
- }
- return channel_open(c);
-}
-
-static
-Channel *
-channel_new(const char *name)
-{
- Channel *c;
- char channelpath[PATH_MAX];
-
- strlcpy(channelpath, name, sizeof(channelpath));
- channel_normalize_path(channelpath);
-
- if (!(c = calloc(1, sizeof(Channel)))) {
- fprintf(stderr, "%s: calloc: %s\n", argv0, strerror(errno));
- exit(1);
- }
-
- strlcpy(c->name, name, sizeof(c->name));
- channel_normalize_name(c->name);
-
- create_filepath(c->inpath, sizeof(c->inpath), ircpath,
- channelpath, "in");
- create_filepath(c->outpath, sizeof(c->outpath), ircpath,
- channelpath, "out");
- return c;
-}
-
-static
-Channel *
-channel_find(const char *name)
-{
- Channel *c;
- char chan[IRC_CHANNEL_MAX];
-
- strlcpy(chan, name, sizeof(chan));
- channel_normalize_name(chan);
- for (c = channels; c; c = c->next) {
- if (!strcmp(chan, c->name))
- return c; /* already handled */
- }
- return nil;
-}
-
-static
-Channel *
-channel_add(const char *name)
-{
- Channel *c;
-
- c = channel_new(name);
- if (channel_open(c) == -1) {
- fprintf(stderr, "%s: cannot create channel: %s: %s\n",
- argv0, name, strerror(errno));
- free(c);
- return nil;
- }
- if (!channels) {
- channels = c;
- } else {
- c->next = channels;
- channels = c;
- }
- return c;
-}
-
-static
-Channel *
-channel_join(const char *name)
-{
- Channel *c;
-
- if (!(c = channel_find(name)))
- c = channel_add(name);
- return c;
-}
-
-static
-void
-channel_rm(Channel *c)
-{
- Channel *p;
-
- if (channels == c) {
- channels = channels->next;
- } else {
- for (p = channels; p && p->next != c; p = p->next)
- ;
- if (p && p->next == c)
- p->next = c->next;
- }
- free(c);
-}
-
-static
-void
-channel_leave(Channel *c)
-{
- if (c->fdin > 2) {
- close(c->fdin);
- c->fdin = -1;
- }
- /* remove "in" file on leaving the channel */
- unlink(c->inpath);
- channel_rm(c);
-}
-
-static
-void
-loginkey(int ircfd, const char *key)
-{
- snprintf(msg, sizeof(msg), "PASS %s\r\n", key);
- ewritestr(ircfd, msg);
-}
-
-static
-void
-loginuser(int ircfd, const char *host, const char *fullname)
-{
- snprintf(msg, sizeof(msg), "NICK %s\r\nUSER %s localhost %s :%s\r\n",
- nick, nick, host, fullname);
- puts(msg);
- ewritestr(ircfd, msg);
-}
-
-static
-int
-udsopen(const char *uds)
-{
- struct sockaddr_un sun;
- size_t len;
- int fd;
-
- if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- fprintf(stderr, "%s: socket: %s\n", argv0, strerror(errno));
- exit(1);
- }
-
- sun.sun_family = AF_UNIX;
- if(strlcpy(sun.sun_path, uds, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
- fprintf(stderr, "%s: UNIX domain socket path truncation\n", argv0);
- exit(1);
- }
- len = strlen(sun.sun_path) + 1 + sizeof(sun.sun_family);
- if (connect(fd, (struct sockaddr *)&sun, len) == -1) {
- fprintf(stderr, "%s: connect: %s\n", argv0, strerror(errno));
- exit(1);
- }
- return fd;
-}
-
-static
-int
-tcpopen(const char *host, const char *service)
-{
- struct addrinfo hints, *res = nil, *rp;
- int fd = -1, e;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */
- hints.ai_flags = AI_NUMERICSERV; /* avoid name lookup for port */
- hints.ai_socktype = SOCK_STREAM;
-
- if ((e = getaddrinfo(host, service, &hints, &res))) {
- fprintf(stderr, "%s: getaddrinfo: %s\n", argv0, gai_strerror(e));
- exit(1);
- }
-
- for (rp = res; rp; rp = rp->ai_next) {
- fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if (fd == -1)
- continue;
- if (connect(fd, rp->ai_addr, rp->ai_addrlen) == -1) {
- close(fd);
- fd = -1;
- continue;
- }
- break; /* success */
- }
- if (fd == -1) {
- fprintf(stderr, "%s: could not connect to %s:%s: %s\n",
- argv0, host, service, strerror(errno));
- exit(1);
- }
-
- freeaddrinfo(res);
- return fd;
-}
-
-static
-int
-isnumeric(const char *s)
-{
- errno = 0;
- strtol(s, nil, 10);
- return errno == 0;
-}
-
-static
-size_t
-tokenize(char **result, size_t reslen, char *str, int delim)
-{
- char *p = nil, *n = nil;
- size_t i = 0;
-
- for (n = str; *n == ' '; n++)
- ;
- p = n;
- while (*n != '\0') {
- if (i >= reslen)
- return 0;
- if (i > TOK_CHAN - TOK_CMD && result[0] && isnumeric(result[0]))
- delim = ':'; /* workaround non-RFC compliant messages */
- if (*n == delim) {
- *n = '\0';
- result[i++] = p;
- p = ++n;
- } else {
- n++;
- }
- }
- /* add last entry */
- if (i < reslen && p < n && p && *p)
- result[i++] = p;
- return i; /* number of tokens */
-}
-
-static
-void
-channel_print(Channel *c, const char *buf)
-{
- FILE *fp = nil;
- time_t t = time(nil);
-
- if (!(fp = fopen(c->outpath, "a")))
- return;
- fprintf(fp, "%lu %s\n", (unsigned long)t, buf);
- fclose(fp);
-}
-
-static
-void
-proc_channels_privmsg(int ircfd, Channel *c, char *buf)
-{
- snprintf(msg, sizeof(msg), "<%s> %s", nick, buf);
- channel_print(c, msg);
- snprintf(msg, sizeof(msg), "PRIVMSG %s :%s\r\n", c->name, buf);
- ewritestr(ircfd, msg);
-}
-
-static
-void
-proc_channels_input(int ircfd, Channel *c, char *buf)
-{
- char *p = nil;
- size_t buflen;
-
- if (buf[0] == '\0')
- return;
- if (buf[0] != '/') {
- proc_channels_privmsg(ircfd, c, buf);
- return;
- }
-
- msg[0] = '\0';
- if ((buflen = strlen(buf)) < 2)
- return;
- if (buf[2] == ' ' || buf[2] == '\0') {
- switch (buf[1]) {
- case 'j': /* join */
- if (buflen < 3)
- return;
- if ((p = strchr(&buf[3], ' '))) /* password parameter */
- *p = '\0';
- if ((buf[3] == '#') || (buf[3] == '&') || (buf[3] == '+') ||
- (buf[3] == '!'))
- {
- /* password protected channel */
- if (p)
- snprintf(msg, sizeof(msg), "JOIN %s %s\r\n", &buf[3], p + 1);
- else
- snprintf(msg, sizeof(msg), "JOIN %s\r\n", &buf[3]);
- channel_join(&buf[3]);
- } else if (p) {
- if ((c = channel_join(&buf[3])))
- proc_channels_privmsg(ircfd, c, p + 1);
- return;
- }
- break;
- case 't': /* topic */
- if (buflen >= 3)
- snprintf(msg, sizeof(msg), "TOPIC %s :%s\r\n", c->name, &buf[3]);
- break;
- case 'a': /* away */
- if (buflen >= 3) {
- snprintf(msg, sizeof(msg), "-!- %s is away \"%s\"", nick, &buf[3]);
- channel_print(c, msg);
- }
- if (buflen >= 3)
- snprintf(msg, sizeof(msg), "AWAY :%s\r\n", &buf[3]);
- else
- snprintf(msg, sizeof(msg), "AWAY\r\n");
- break;
- case 'n': /* change nick */
- if (buflen >= 3) {
- strlcpy(_nick, &buf[3], sizeof(_nick));
- snprintf(msg, sizeof(msg), "NICK %s\r\n", &buf[3]);
- }
- break;
- case 'l': /* leave */
- if (c == channelmaster)
- return;
- if (buflen >= 3)
- snprintf(msg, sizeof(msg), "PART %s :%s\r\n", c->name, &buf[3]);
- else
- snprintf(msg, sizeof(msg),
- "PART %s :leaving\r\n", c->name);
- ewritestr(ircfd, msg);
- channel_leave(c);
- return;
- break;
- case 'q': /* quit */
- if (buflen >= 3)
- snprintf(msg, sizeof(msg), "QUIT :%s\r\n", &buf[3]);
- else
- snprintf(msg, sizeof(msg),
- "QUIT %s\r\n", "bye");
- ewritestr(ircfd, msg);
- isrunning = 0;
- return;
- break;
- default: /* raw IRC command */
- snprintf(msg, sizeof(msg), "%s\r\n", &buf[1]);
- break;
- }
- } else {
- /* raw IRC command */
- snprintf(msg, sizeof(msg), "%s\r\n", &buf[1]);
- }
- if (msg[0] != '\0')
- ewritestr(ircfd, msg);
-}
-
-static
-void
-proc_server_cmd(int fd, char *buf)
-{
- Channel *c;
- const char *channel;
- char *argv[TOK_LAST], *cmd = nil, *p = nil;
- unsigned int i;
-
- if (!buf || buf[0] == '\0')
- return;
-
- /* clear tokens */
- for (i = 0; i < TOK_LAST; i++)
- argv[i] = nil;
-
- /* check prefix */
- if (buf[0] == ':') {
- if (!(p = strchr(buf, ' ')))
- return;
- *p = '\0';
- for (++p; *p == ' '; p++)
- ;
- cmd = p;
- argv[TOK_NICKSRV] = &buf[1];
- if ((p = strchr(buf, '!'))) {
- *p = '\0';
- argv[TOK_USER] = ++p;
- }
- } else {
- cmd = buf;
- }
-
- /* remove CRLFs */
- for (p = cmd; p && *p != '\0'; p++) {
- if (*p == '\r' || *p == '\n')
- *p = '\0';
- }
-
- if ((p = strchr(cmd, ':'))) {
- *p = '\0';
- argv[TOK_TEXT] = ++p;
- }
-
- tokenize(&argv[TOK_CMD], TOK_LAST - TOK_CMD, cmd, ' ');
-
- if (!argv[TOK_CMD] || !strcmp("PONG", argv[TOK_CMD])) {
- return;
- } else if (!strcmp("PING", argv[TOK_CMD])) {
- snprintf(msg, sizeof(msg), "PONG %s\r\n", argv[TOK_TEXT]);
- ewritestr(fd, msg);
- return;
- } else if (!argv[TOK_NICKSRV] || !argv[TOK_USER]) {
- /* server command */
- snprintf(msg, sizeof(msg), "%s%s",
- argv[TOK_ARG] ? argv[TOK_ARG] : "",
- argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
- channel_print(channelmaster, msg);
- return; /* don't process further */
- } else if (!strcmp("ERROR", argv[TOK_CMD]))
- snprintf(msg, sizeof(msg), "-!- error %s",
- argv[TOK_TEXT] ? argv[TOK_TEXT] : "unknown");
- else if (!strcmp("JOIN", argv[TOK_CMD]) && (argv[TOK_CHAN] || argv[TOK_TEXT])) {
- if (argv[TOK_TEXT])
- argv[TOK_CHAN] = argv[TOK_TEXT];
- snprintf(msg, sizeof(msg), "-!- %s(%s) has joined %s",
- argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]);
- } else if (!strcmp("PART", argv[TOK_CMD]) && argv[TOK_CHAN]) {
- snprintf(msg, sizeof(msg), "-!- %s(%s) has left %s",
- argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]);
- /* if user itself leaves, don't write to channel (don't reopen channel). */
- if (!strcmp(argv[TOK_NICKSRV], nick))
- return;
- } else if (!strcmp("MODE", argv[TOK_CMD])) {
- snprintf(msg, sizeof(msg), "-!- %s changed mode/%s -> %s %s",
- argv[TOK_NICKSRV],
- argv[TOK_CHAN] ? argv[TOK_CHAN] : "",
- argv[TOK_ARG] ? argv[TOK_ARG] : "",
- argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
- } else if (!strcmp("QUIT", argv[TOK_CMD])) {
- snprintf(msg, sizeof(msg), "-!- %s(%s) has quit \"%s\"",
- argv[TOK_NICKSRV], argv[TOK_USER],
- argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
- } else if (!strncmp("NICK", argv[TOK_CMD], 5) && argv[TOK_TEXT] &&
- !strcmp(_nick, argv[TOK_TEXT])) {
- strlcpy(nick, _nick, sizeof(nick));
- snprintf(msg, sizeof(msg), "-!- changed nick to \"%s\"", nick);
- channel_print(channelmaster, msg);
- } else if (!strcmp("NICK", argv[TOK_CMD]) && argv[TOK_TEXT]) {
- snprintf(msg, sizeof(msg), "-!- %s changed nick to %s",
- argv[TOK_NICKSRV], argv[TOK_TEXT]);
- } else if (!strcmp("TOPIC", argv[TOK_CMD])) {
- snprintf(msg, sizeof(msg), "-!- %s changed topic to \"%s\"",
- argv[TOK_NICKSRV],
- argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
- } else if (!strcmp("KICK", argv[TOK_CMD]) && argv[TOK_ARG]) {
- snprintf(msg, sizeof(msg), "-!- %s kicked %s (\"%s\")",
- argv[TOK_NICKSRV], argv[TOK_ARG],
- argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
- } else if (!strcmp("NOTICE", argv[TOK_CMD])) {
- snprintf(msg, sizeof(msg), "-!- \"%s\"",
- argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
- } else if (!strcmp("PRIVMSG", argv[TOK_CMD])) {
- snprintf(msg, sizeof(msg), "<%s> %s", argv[TOK_NICKSRV],
- argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
- } else {
- return; /* can't read this message */
- }
- if (argv[TOK_CHAN] && !strcmp(argv[TOK_CHAN], nick))
- channel = argv[TOK_NICKSRV];
- else
- channel = argv[TOK_CHAN];
-
- if (!channel || channel[0] == '\0')
- c = channelmaster;
- else
- c = channel_join(channel);
- if (c)
- channel_print(c, msg);
-}
-
-static
-int
-read_line(int fd, char *buf, size_t bufsiz)
-{
- size_t i = 0;
- char c = '\0';
-
- do {
- if (read(fd, &c, sizeof(char)) != sizeof(char))
- return -1;
- buf[i++] = c;
- } while (c != '\n' && i < bufsiz);
- buf[i - 1] = '\0'; /* eliminates '\n' */
- return 0;
-}
-
-static
-void
-handle_channels_input(int ircfd, Channel *c)
-{
- char buf[IRC_MSG_MAX];
-
- if(read_line(c->fdin, buf, sizeof(buf)) == -1) {
- if(channel_reopen(c) == -1)
- channel_rm(c);
- return;
- }
- proc_channels_input(ircfd, c, buf);
-}
-
-static
-void
-handle_server_output(int ircfd)
-{
- char buf[IRC_MSG_MAX];
-
- if (read_line(ircfd, buf, sizeof(buf)) == -1) {
- fprintf(stderr, "%s: remote host closed connection: %s\n",
- argv0, strerror(errno));
- exit(1);
- }
- fprintf(stdout, "%lu %s\n", (unsigned long)time(nil), buf);
- fflush(stdout);
- proc_server_cmd(ircfd, buf);
-}
-
-static
-void
-sighandler(int sig)
-{
- if (sig == SIGTERM || sig == SIGINT)
- isrunning = 0;
-}
-
-static
-void
-setup(void)
-{
- struct sigaction sa;
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = sighandler;
- sigaction(SIGTERM, &sa, nil);
- sigaction(SIGINT, &sa, nil);
-}
-
-static
-void
-run(int ircfd, const char *host)
-{
- Channel *c, *tmp;
- fd_set rdset;
- struct timeval tv;
- char ping_msg[IRC_MSG_MAX];
- int r, maxfd;
-
- snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host);
- while(isrunning) {
- maxfd = ircfd;
- FD_ZERO(&rdset);
- FD_SET(ircfd, &rdset);
- for (c = channels; c; c = c->next) {
- if (c->fdin > maxfd)
- maxfd = c->fdin;
- FD_SET(c->fdin, &rdset);
- }
- memset(&tv, 0, sizeof(tv));
- tv.tv_sec = 120;
- r = select(maxfd + 1, &rdset, 0, 0, &tv);
- if(r < 0){
- if (errno == EINTR)
- continue;
- fprintf(stderr, "%s: select: %s\n", argv0, strerror(errno));
- exit(1);
- }else if(r == 0){
- if (time(nil) - last_response >= PING_TIMEOUT) {
- channel_print(channelmaster, "-!- ii shutting down: ping timeout");
- exit(2); /* status code 2 for timeout */
- }
- ewritestr(ircfd, ping_msg);
- continue;
- }
- if(FD_ISSET(ircfd, &rdset)) {
- handle_server_output(ircfd);
- last_response = time(nil);
- }
- for(c = channels; c; c = tmp) {
- tmp = c->next;
- if (FD_ISSET(c->fdin, &rdset))
- handle_channels_input(ircfd, c);
- }
- }
-}
-
-int
-main(int argc, char *argv[])
-{
- Channel *c, *tmp;
- struct passwd *spw;
- const char *key = nil, *fullname = nil, *host = "";
- const char *uds = nil, *service = "6667";
- char prefix[PATH_MAX];
- int ircfd, r;
-
- /* use nickname and home dir of user by default */
- if(!(spw = getpwuid(getuid()))) {
- fprintf(stderr, "%s: getpwuid: %s\n", argv0, strerror(errno));
- exit(1);
- }
- strlcpy(nick, spw->pw_name, sizeof(nick));
- snprintf(prefix, sizeof(prefix), "%s/irc", spw->pw_dir);
-
- ARGBEGIN {
- case 'f':
- fullname = EARGF(usage());
- break;
- case 'i':
- strlcpy(prefix, EARGF(usage()), sizeof(prefix));
- break;
- case 'k':
- key = getenv(EARGF(usage()));
- break;
- case 'n':
- strlcpy(nick, EARGF(usage()), sizeof(nick));
- break;
- case 'p':
- service = EARGF(usage());
- break;
- case 's':
- host = EARGF(usage());
- break;
- case 'u':
- uds = EARGF(usage());
- break;
- default:
- usage();
- break;
- } ARGEND
-
- if(!*host)
- usage();
-
- if(uds)
- ircfd = udsopen(uds);
- else
- ircfd = tcpopen(host, service);
-
-#ifdef __OpenBSD__
- /* OpenBSD pledge(2) support */
- if (pledge("stdio rpath wpath cpath dpath", nil) == -1) {
- fprintf(stderr, "%s: pledge: %s\n", argv0, strerror(errno));
- exit(1);
- }
-#endif
-
- r = snprintf(ircpath, sizeof(ircpath), "%s/%s", prefix, host);
- if (r < 0 || (size_t)r >= sizeof(ircpath)) {
- fprintf(stderr, "%s: path to irc directory too long\n", argv0);
- exit(1);
- }
- create_dirtree(ircpath);
-
- channelmaster = channel_add(""); /* master channel */
- if(key)
- loginkey(ircfd, key);
- loginuser(ircfd, host, fullname && *fullname ? fullname : nick);
- setup();
- run(ircfd, host);
- if(channelmaster)
- channel_leave(channelmaster);
-
- for(c = channels; c; c = tmp) {
- tmp = c->next;
- channel_leave(c);
- }
-
- return 0;
-}
diff --git a/sys/cmd/ic/rules.mk b/sys/cmd/ic/rules.mk
deleted file mode 100644
index 649c9ac..0000000
--- a/sys/cmd/ic/rules.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-include share/push.mk
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := $(d)/strlcpy.c $(d)/ic.c
-BINS_$(d) := $(d)/ic
-
-include share/paths.mk
-
-# Local rules
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/ic/strlcpy.c b/sys/cmd/ic/strlcpy.c
deleted file mode 100644
index 5af7906..0000000
--- a/sys/cmd/ic/strlcpy.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Taken from OpenBSD */
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Copy src to string dst of size siz. At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-size_t
-strlcpy(char *dst, const char *src, size_t siz)
-{
- char *d = dst;
- const char *s = src;
- size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if(n != 0) {
- while(--n != 0) {
- if((*d++ = *s++) == '\0')
- break;
- }
- }
- /* Not enough room in dst, add NUL and traverse rest of src */
- if(n == 0) {
- if(siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while(*s++)
- ;
- }
- return s - src - 1; /* count does not include NUL */
-}
diff --git a/sys/cmd/menu/LICENSE b/sys/cmd/menu/LICENSE
deleted file mode 100644
index 9762166..0000000
--- a/sys/cmd/menu/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-MIT/X Consortium License
-
-© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
-© 2006-2008 Sander van Dijk <a.h.vandijk@gmail.com>
-© 2006-2007 Michał Janeczek <janeczek@gmail.com>
-© 2007 Kris Maglione <jg@suckless.org>
-© 2009 Gottox <gottox@s01.de>
-© 2009 Markus Schnalke <meillo@marmaro.de>
-© 2009 Evan Gates <evan.gates@gmail.com>
-© 2010-2012 Connor Lane Smith <cls@lubutu.com>
-© 2014-2019 Hiltjo Posthuma <hiltjo@codemadness.org>
-© 2015-2019 Quentin Rameau <quinq@fifth.space>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/sys/cmd/menu/config.h b/sys/cmd/menu/config.h
deleted file mode 100644
index 9bfd5b3..0000000
--- a/sys/cmd/menu/config.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-/* Default settings; can be overriden by command line. */
-#define VERSION "1.0"
-
-static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
-/* -fn option overrides fonts[0]; default X11 font or font set */
-static const char *fonts[] = {
- "consolas:size=16"
-};
-
-static const char *prompt = "cmds"; /* -p option; prompt to the left of input field */
-static const char *colors[SchemeLast][2] = {
- /* fg bg */
- [SchemeNorm] = { "#fbf1c7", "#504945" },
- [SchemeSel] = { "#504945", "#83a598" },
- [SchemeOut] = { "#000000", "#00ffff" },
-};
-/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
-static unsigned int lines = 0;
-
-/*
- * Characters not considered part of a word while deleting words
- * e.g. " /?\"&[]"
- */
-static const char worddelimiters[] = " ";
diff --git a/sys/cmd/menu/drw.c b/sys/cmd/menu/drw.c
deleted file mode 100644
index 162fe40..0000000
--- a/sys/cmd/menu/drw.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "menu.h"
-
-#define UTF_INVALID 0xFFFD
-#define UTF_SIZ 4
-
-static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
-static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
-static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
-static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
-
-static long
-utf8decodebyte(const char c, size_t *i)
-{
- for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
- if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
- return (unsigned char)c & ~utfmask[*i];
- return 0;
-}
-
-static size_t
-utf8validate(long *u, size_t i)
-{
- if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
- *u = RuneErr;
- for (i = 1; *u > utfmax[i]; ++i)
- ;
- return i;
-}
-
-static size_t
-utf8decode(const char *c, long *u, size_t clen)
-{
- size_t i, j, len, type;
- long udecoded;
-
- *u = RuneErr;
- if (!clen)
- return 0;
- udecoded = utf8decodebyte(c[0], &len);
- if (!BETWEEN(len, 1, UTF_SIZ))
- return 1;
- for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
- udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
- if (type)
- return j;
- }
- if (j < len)
- return 0;
- *u = udecoded;
- utf8validate(u, len);
-
- return len;
-}
-
-Drw *
-drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
-{
- Drw *drw = ecalloc(1, sizeof(Drw));
-
- drw->dpy = dpy;
- drw->screen = screen;
- drw->root = root;
- drw->w = w;
- drw->h = h;
- drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
- drw->gc = XCreateGC(dpy, root, 0, NULL);
- XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
-
- return drw;
-}
-
-void
-drw_resize(Drw *drw, unsigned int w, unsigned int h)
-{
- if (!drw)
- return;
-
- drw->w = w;
- drw->h = h;
- if (drw->drawable)
- XFreePixmap(drw->dpy, drw->drawable);
- drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
-}
-
-void
-drw_free(Drw *drw)
-{
- XFreePixmap(drw->dpy, drw->drawable);
- XFreeGC(drw->dpy, drw->gc);
- free(drw);
-}
-
-/* This function is an implementation detail. Library users should use
- * drw_fontset_create instead.
- */
-static Fnt *
-xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
-{
- Fnt *font;
- XftFont *xfont = NULL;
- FcPattern *pattern = NULL;
-
- if (fontname) {
- /* Using the pattern found at font->xfont->pattern does not yield the
- * same substitution results as using the pattern returned by
- * FcNameParse; using the latter results in the desired fallback
- * behaviour whereas the former just results in missing-character
- * rectangles being drawn, at least with some fonts. */
- if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
- fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
- return NULL;
- }
- if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
- fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
- XftFontClose(drw->dpy, xfont);
- return NULL;
- }
- } else if (fontpattern) {
- if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
- fprintf(stderr, "error, cannot load font from pattern.\n");
- return NULL;
- }
- } else {
- fatal("no font specified.");
- }
-
- /* Do not allow using color fonts. This is a workaround for a BadLength
- * error from Xft with color glyphs. Modelled on the Xterm workaround. See
- * https://bugzilla.redhat.com/show_bug.cgi?id=1498269
- * https://lists.suckless.org/dev/1701/30932.html
- * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
- * and lots more all over the internet.
- */
- FcBool iscol;
- if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
- XftFontClose(drw->dpy, xfont);
- return NULL;
- }
-
- font = ecalloc(1, sizeof(Fnt));
- font->xfont = xfont;
- font->pattern = pattern;
- font->h = xfont->ascent + xfont->descent;
- font->dpy = drw->dpy;
-
- return font;
-}
-
-static void
-xfont_free(Fnt *font)
-{
- if (!font)
- return;
- if (font->pattern)
- FcPatternDestroy(font->pattern);
- XftFontClose(font->dpy, font->xfont);
- free(font);
-}
-
-Fnt*
-drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
-{
- Fnt *cur, *ret = NULL;
- size_t i;
-
- if (!drw || !fonts)
- return NULL;
-
- for (i = 1; i <= fontcount; i++) {
- if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
- cur->next = ret;
- ret = cur;
- }
- }
- return (drw->fonts = ret);
-}
-
-void
-drw_fontset_free(Fnt *font)
-{
- if (font) {
- drw_fontset_free(font->next);
- xfont_free(font);
- }
-}
-
-void
-drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
-{
- if (!drw || !dest || !clrname)
- return;
-
- if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
- DefaultColormap(drw->dpy, drw->screen),
- clrname, dest))
- fatal("error, cannot allocate color '%s'", clrname);
-}
-
-/* Wrapper to create color schemes. The caller has to call free(3) on the
- * returned color scheme when done using it. */
-Clr *
-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
-{
- size_t i;
- Clr *ret;
-
- /* need at least two colors for a scheme */
- if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
- return NULL;
-
- for (i = 0; i < clrcount; i++)
- drw_clr_create(drw, &ret[i], clrnames[i]);
- return ret;
-}
-
-void
-drw_setfontset(Drw *drw, Fnt *set)
-{
- if (drw)
- drw->fonts = set;
-}
-
-void
-drw_setscheme(Drw *drw, Clr *scm)
-{
- if (drw)
- drw->scheme = scm;
-}
-
-void
-drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
-{
- if (!drw || !drw->scheme)
- return;
- XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
- if (filled)
- XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
- else
- XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
-}
-
-int
-drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
-{
- char buf[1024];
- int ty;
- unsigned int ew;
- XftDraw *d = NULL;
- Fnt *usedfont, *curfont, *nextfont;
- size_t i, len;
- int utf8strlen, utf8charlen, render = x || y || w || h;
- long utf8codepoint = 0;
- const char *utf8str;
- FcCharSet *fccharset;
- FcPattern *fcpattern;
- FcPattern *match;
- XftResult result;
- int charexists = 0;
-
- if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
- return 0;
-
- if (!render) {
- w = ~w;
- } else {
- XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
- XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
- d = XftDrawCreate(drw->dpy, drw->drawable,
- DefaultVisual(drw->dpy, drw->screen),
- DefaultColormap(drw->dpy, drw->screen));
- x += lpad;
- w -= lpad;
- }
-
- usedfont = drw->fonts;
- while (1) {
- utf8strlen = 0;
- utf8str = text;
- nextfont = NULL;
- while (*text) {
- utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
- for (curfont = drw->fonts; curfont; curfont = curfont->next) {
- charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
- if (charexists) {
- if (curfont == usedfont) {
- utf8strlen += utf8charlen;
- text += utf8charlen;
- } else {
- nextfont = curfont;
- }
- break;
- }
- }
-
- if (!charexists || nextfont)
- break;
- else
- charexists = 0;
- }
-
- if (utf8strlen) {
- drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
- /* shorten text if necessary */
- for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
- drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
-
- if (len) {
- memcpy(buf, utf8str, len);
- buf[len] = '\0';
- if (len < utf8strlen)
- for (i = len; i && i > len - 3; buf[--i] = '.')
- ; /* NOP */
-
- if (render) {
- ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
- XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
- usedfont->xfont, x, ty, (XftChar8 *)buf, len);
- }
- x += ew;
- w -= ew;
- }
- }
-
- if (!*text) {
- break;
- } else if (nextfont) {
- charexists = 0;
- usedfont = nextfont;
- } else {
- /* Regardless of whether or not a fallback font is found, the
- * character must be drawn. */
- charexists = 1;
-
- fccharset = FcCharSetCreate();
- FcCharSetAddChar(fccharset, utf8codepoint);
-
- if (!drw->fonts->pattern) {
- /* Refer to the comment in xfont_create for more information. */
- fatal("the first font in the cache must be loaded from a font string.");
- }
-
- fcpattern = FcPatternDuplicate(drw->fonts->pattern);
- FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
- FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
- FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
-
- FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
- FcDefaultSubstitute(fcpattern);
- match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
-
- FcCharSetDestroy(fccharset);
- FcPatternDestroy(fcpattern);
-
- if (match) {
- usedfont = xfont_create(drw, NULL, match);
- if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
- for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
- ; /* NOP */
- curfont->next = usedfont;
- } else {
- xfont_free(usedfont);
- usedfont = drw->fonts;
- }
- }
- }
- }
- if (d)
- XftDrawDestroy(d);
-
- return x + (render ? w : 0);
-}
-
-void
-drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
-{
- if (!drw)
- return;
-
- XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
- XSync(drw->dpy, False);
-}
-
-unsigned int
-drw_fontset_getwidth(Drw *drw, const char *text)
-{
- if (!drw || !drw->fonts || !text)
- return 0;
- return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
-}
-
-void
-drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
-{
- XGlyphInfo ext;
-
- if (!font || !text)
- return;
-
- XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
- if (w)
- *w = ext.xOff;
- if (h)
- *h = font->h;
-}
-
-Cur *
-drw_cur_create(Drw *drw, int shape)
-{
- Cur *cur;
-
- if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
- return NULL;
-
- cur->cursor = XCreateFontCursor(drw->dpy, shape);
-
- return cur;
-}
-
-void
-drw_cur_free(Drw *drw, Cur *cursor)
-{
- if (!cursor)
- return;
-
- XFreeCursor(drw->dpy, cursor->cursor);
- free(cursor);
-}
diff --git a/sys/cmd/menu/drw.h b/sys/cmd/menu/drw.h
deleted file mode 100644
index 4c67419..0000000
--- a/sys/cmd/menu/drw.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-
-typedef struct {
- Cursor cursor;
-} Cur;
-
-typedef struct Fnt {
- Display *dpy;
- unsigned int h;
- XftFont *xfont;
- FcPattern *pattern;
- struct Fnt *next;
-} Fnt;
-
-enum { ColFg, ColBg }; /* Clr scheme index */
-typedef XftColor Clr;
-
-typedef struct {
- unsigned int w, h;
- Display *dpy;
- int screen;
- Window root;
- Drawable drawable;
- GC gc;
- Clr *scheme;
- Fnt *fonts;
-} Drw;
-
-/* Drawable abstraction */
-Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
-void drw_resize(Drw *drw, unsigned int w, unsigned int h);
-void drw_free(Drw *drw);
-
-/* Fnt abstraction */
-Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
-void drw_fontset_free(Fnt* set);
-unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
-void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
-
-/* Colorscheme abstraction */
-void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
-
-/* Cursor abstraction */
-Cur *drw_cur_create(Drw *drw, int shape);
-void drw_cur_free(Drw *drw, Cur *cursor);
-
-/* Drawing context manipulation */
-void drw_setfontset(Drw *drw, Fnt *set);
-void drw_setscheme(Drw *drw, Clr *scm);
-
-/* Drawing functions */
-void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
-int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
-
-/* Map functions */
-void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
diff --git a/sys/cmd/menu/menu.c b/sys/cmd/menu/menu.c
deleted file mode 100644
index e6e4bb2..0000000
--- a/sys/cmd/menu/menu.c
+++ /dev/null
@@ -1,765 +0,0 @@
-#include "menu.h"
-
-static char text[BUFSIZ] = "";
-static char *embed;
-static int bh, mw, mh;
-static int inputw = 0, promptw, passwd = 0;
-static int lrpad; /* sum of left and right padding */
-static size_t cursor;
-static struct item *items = nil;
-static struct item *matches, *matchend;
-static struct item *prev, *curr, *next, *sel;
-static int mon = -1, screen;
-
-static Atom clip, utf8;
-static Display *dpy;
-static Window root, parentwin, win;
-static XIC xic;
-
-static Drw *drw;
-static Clr *scheme[SchemeLast];
-
-#include "config.h"
-
-static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
-static char *(*fstrstr)(const char *, const char *) = strstr;
-
-static
-void
-appenditem(struct item *item, struct item **list, struct item **last)
-{
- if (*last)
- (*last)->right = item;
- else
- *list = item;
-
- item->left = *last;
- item->right = nil;
- *last = item;
-}
-
-static
-void
-calcoffsets(void)
-{
- int i, n;
-
- if (lines > 0)
- n = lines * bh;
- else
- n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
- /* calculate which items will begin the next page and previous page */
- for (i = 0, next = curr; next; next = next->right)
- if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n)
- break;
- for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
- if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n)
- break;
-}
-
-static
-void
-cleanup(void)
-{
- size_t i;
-
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- for (i = 0; i < SchemeLast; i++)
- free(scheme[i]);
- drw_free(drw);
- XSync(dpy, False);
- XCloseDisplay(dpy);
-}
-
-static
-char *
-cistrstr(const char *s, const char *sub)
-{
- size_t len;
-
- for (len = strlen(sub); *s; s++)
- if (!strncasecmp(s, sub, len))
- return (char *)s;
- return nil;
-}
-
-static
-int
-drawitem(struct item *item, int x, int y, int w)
-{
- if (item == sel)
- drw_setscheme(drw, scheme[SchemeSel]);
- else if (item->out)
- drw_setscheme(drw, scheme[SchemeOut]);
- else
- drw_setscheme(drw, scheme[SchemeNorm]);
-
- return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
-}
-
-static
-void
-drawmenu(void)
-{
- uint curpos;
- struct item *item;
- int x = 0, y = 0, w;
- char *censort;
-
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_rect(drw, 0, 0, mw, mh, 1, 1);
-
- if (prompt && *prompt) {
- drw_setscheme(drw, scheme[SchemeSel]);
- x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0);
- }
- /* draw input field */
- w = (lines > 0 || !matches) ? mw - x : inputw;
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
- if(passwd){
- censort = ecalloc(1, sizeof(text));
- memset(censort, '.', strlen(text));
- drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0);
- free(censort);
- }
-
- curpos = TEXTW(text) - TEXTW(&text[cursor]);
- if ((curpos += lrpad / 2 - 1) < w) {
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
- }
-
- if (lines > 0) {
- /* draw vertical list */
- for (item = curr; item != next; item = item->right)
- drawitem(item, x, y += bh, mw - x);
- } else if (matches) {
- /* draw horizontal list */
- x += inputw;
- w = TEXTW("<");
- if (curr->left) {
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0);
- }
- x += w;
- for (item = curr; item != next; item = item->right)
- x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">")));
- if (next) {
- w = TEXTW(">");
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0);
- }
- }
- drw_map(drw, win, 0, 0, mw, mh);
-}
-
-static
-void
-grabfocus(void)
-{
- struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
- Window focuswin;
- int i, revertwin;
-
- for (i = 0; i < 100; ++i) {
- XGetInputFocus(dpy, &focuswin, &revertwin);
- if (focuswin == win)
- return;
- XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
- nanosleep(&ts, nil);
- }
- fatal("cannot grab focus");
-}
-
-static
-void
-grabkeyboard(void)
-{
- struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
- int i;
-
- if (embed)
- return;
- /* try to grab keyboard, we may have to wait for another process to ungrab */
- for (i = 0; i < 1000; i++) {
- if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
- GrabModeAsync, CurrentTime) == GrabSuccess)
- return;
- nanosleep(&ts, nil);
- }
- fatal("cannot grab keyboard");
-}
-
-static
-void
-match(void)
-{
- static char **tokv = nil;
- static int tokn = 0;
-
- char buf[sizeof text], *s;
- int i, tokc = 0;
- size_t len, textsize;
- struct item *item, *lprefix, *lsubstr, *prefixend, *substrend;
-
- strcpy(buf, text);
- /* separate input text into tokens to be matched individually */
- for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(nil, " "))
- if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
- fatal("cannot realloc %u bytes:", tokn * sizeof *tokv);
- len = tokc ? strlen(tokv[0]) : 0;
-
- matches = lprefix = lsubstr = matchend = prefixend = substrend = nil;
- textsize = strlen(text) + 1;
- for (item = items; item && item->text; item++) {
- for (i = 0; i < tokc; i++)
- if (!fstrstr(item->text, tokv[i]))
- break;
- if (i != tokc) /* not all tokens match */
- continue;
- /* exact matches go first, then prefixes, then substrings */
- if (!tokc || !fstrncmp(text, item->text, textsize))
- appenditem(item, &matches, &matchend);
- else if (!fstrncmp(tokv[0], item->text, len))
- appenditem(item, &lprefix, &prefixend);
- else
- appenditem(item, &lsubstr, &substrend);
- }
- if (lprefix) {
- if (matches) {
- matchend->right = lprefix;
- lprefix->left = matchend;
- } else
- matches = lprefix;
- matchend = prefixend;
- }
- if (lsubstr) {
- if (matches) {
- matchend->right = lsubstr;
- lsubstr->left = matchend;
- } else
- matches = lsubstr;
- matchend = substrend;
- }
- curr = sel = matches;
- calcoffsets();
-}
-
-static
-void
-insert(const char *str, ssize_t n)
-{
- if (strlen(text) + n > sizeof text - 1)
- return;
- /* move existing text out of the way, insert new text, and update cursor */
- memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0));
- if (n > 0)
- memcpy(&text[cursor], str, n);
- cursor += n;
- match();
-}
-
-static
-size_t
-nextrune(int inc)
-{
- ssize_t n;
-
- /* return location of next utf8 rune in the given direction (+1 or -1) */
- for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc)
- ;
- return n;
-}
-
-static
-void
-movewordedge(int dir)
-{
- if (dir < 0) { /* move cursor to the start of the word*/
- while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)]))
- cursor = nextrune(-1);
- while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)]))
- cursor = nextrune(-1);
- } else { /* move cursor to the end of the word */
- while (text[cursor] && strchr(worddelimiters, text[cursor]))
- cursor = nextrune(+1);
- while (text[cursor] && !strchr(worddelimiters, text[cursor]))
- cursor = nextrune(+1);
- }
-}
-
-static
-void
-keypress(XKeyEvent *ev)
-{
- char buf[32];
- int len;
- KeySym ksym;
- Status status;
-
- len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
- switch (status) {
- default: /* XLookupNone, XBufferOverflow */
- return;
- case XLookupChars:
- goto insert;
- case XLookupKeySym:
- case XLookupBoth:
- break;
- }
-
- if (ev->state & ControlMask) {
- switch(ksym) {
- case XK_a: ksym = XK_Home; break;
- case XK_b: ksym = XK_Left; break;
- case XK_c: ksym = XK_Escape; break;
- case XK_d: ksym = XK_Delete; break;
- case XK_e: ksym = XK_End; break;
- case XK_f: ksym = XK_Right; break;
- case XK_g: ksym = XK_Escape; break;
- case XK_h: ksym = XK_BackSpace; break;
- case XK_i: ksym = XK_Tab; break;
- case XK_j: /* fallthrough */
- case XK_J: /* fallthrough */
- case XK_m: /* fallthrough */
- case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break;
- case XK_n: ksym = XK_Down; break;
- case XK_p: ksym = XK_Up; break;
-
- case XK_k: /* delete right */
- text[cursor] = '\0';
- match();
- break;
- case XK_u: /* delete left */
- insert(nil, 0 - cursor);
- break;
- case XK_w: /* delete word */
- while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)]))
- insert(nil, nextrune(-1) - cursor);
- while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)]))
- insert(nil, nextrune(-1) - cursor);
- break;
- case XK_y: /* paste selection */
- case XK_Y:
- XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
- utf8, utf8, win, CurrentTime);
- return;
- case XK_Left:
- movewordedge(-1);
- goto draw;
- case XK_Right:
- movewordedge(+1);
- goto draw;
- case XK_Return:
- case XK_KP_Enter:
- break;
- case XK_bracketleft:
- cleanup();
- exit(1);
- default:
- return;
- }
- } else if (ev->state & Mod1Mask) {
- switch(ksym) {
- case XK_b:
- movewordedge(-1);
- goto draw;
- case XK_f:
- movewordedge(+1);
- goto draw;
- case XK_g: ksym = XK_Home; break;
- case XK_G: ksym = XK_End; break;
- case XK_h: ksym = XK_Up; break;
- case XK_j: ksym = XK_Next; break;
- case XK_k: ksym = XK_Prior; break;
- case XK_l: ksym = XK_Down; break;
- default:
- return;
- }
- }
-
- switch(ksym) {
- default:
-insert:
- if (!iscntrl(*buf))
- insert(buf, len);
- break;
- case XK_Delete:
- if (text[cursor] == '\0')
- return;
- cursor = nextrune(+1);
- /* fallthrough */
- case XK_BackSpace:
- if (cursor == 0)
- return;
- insert(nil, nextrune(-1) - cursor);
- break;
- case XK_End:
- if (text[cursor] != '\0') {
- cursor = strlen(text);
- break;
- }
- if (next) {
- /* jump to end of list and position items in reverse */
- curr = matchend;
- calcoffsets();
- curr = prev;
- calcoffsets();
- while (next && (curr = curr->right))
- calcoffsets();
- }
- sel = matchend;
- break;
- case XK_Escape:
- cleanup();
- exit(1);
- case XK_Home:
- if (sel == matches) {
- cursor = 0;
- break;
- }
- sel = curr = matches;
- calcoffsets();
- break;
- case XK_Left:
- if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
- cursor = nextrune(-1);
- break;
- }
- if (lines > 0)
- return;
- /* fallthrough */
- case XK_Up:
- if (sel && sel->left && (sel = sel->left)->right == curr) {
- curr = prev;
- calcoffsets();
- }
- break;
- case XK_Next:
- if (!next)
- return;
- sel = curr = next;
- calcoffsets();
- break;
- case XK_Prior:
- if (!prev)
- return;
- sel = curr = prev;
- calcoffsets();
- break;
- case XK_Return:
- case XK_KP_Enter:
- puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
- if (!(ev->state & ControlMask)) {
- cleanup();
- exit(0);
- }
- if (sel)
- sel->out = 1;
- break;
- case XK_Right:
- if (text[cursor] != '\0') {
- cursor = nextrune(+1);
- break;
- }
- if (lines > 0)
- return;
- /* fallthrough */
- case XK_Down:
- if (sel && sel->right && (sel = sel->right) == next) {
- curr = next;
- calcoffsets();
- }
- break;
- case XK_Tab:
- if (!sel)
- return;
- strncpy(text, sel->text, sizeof text - 1);
- text[sizeof text - 1] = '\0';
- cursor = strlen(text);
- match();
- break;
- }
-
-draw:
- drawmenu();
-}
-
-static
-void
-paste(void)
-{
- char *p, *q;
- int di;
- unsigned long dl;
- Atom da;
-
- /* we have been given the current selection, now insert it into input */
- if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
- utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
- == Success && p) {
- insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p));
- XFree(p);
- }
- drawmenu();
-}
-
-static
-void
-readstdin(void)
-{
- char buf[sizeof text], *p;
- size_t i, imax = 0, size = 0;
- uint tmpmax = 0;
- if(passwd){
- inputw = lines = 0;
- return;
- }
-
- /* read each line from stdin and add it to the item list */
- for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
- if (i + 1 >= size / sizeof *items)
- if (!(items = realloc(items, (size += BUFSIZ))))
- fatal("cannot realloc %u bytes:", size);
- if ((p = strchr(buf, '\n')))
- *p = '\0';
- if (!(items[i].text = strdup(buf)))
- fatal("cannot strdup %u bytes:", strlen(buf) + 1);
- items[i].out = 0;
- drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, nil);
- if (tmpmax > inputw) {
- inputw = tmpmax;
- imax = i;
- }
- }
- if (items)
- items[i].text = nil;
- inputw = items ? TEXTW(items[imax].text) : 0;
- lines = MIN(lines, i);
-}
-
-static
-void
-run(void)
-{
- XEvent ev;
-
- while (!XNextEvent(dpy, &ev)) {
- if (XFilterEvent(&ev, win))
- continue;
- switch(ev.type) {
- case DestroyNotify:
- if (ev.xdestroywindow.window != win)
- break;
- cleanup();
- exit(1);
- case Expose:
- if (ev.xexpose.count == 0)
- drw_map(drw, win, 0, 0, mw, mh);
- break;
- case FocusIn:
- /* regrab focus from parent window */
- if (ev.xfocus.window != win)
- grabfocus();
- break;
- case KeyPress:
- keypress(&ev.xkey);
- break;
- case SelectionNotify:
- if (ev.xselection.property == utf8)
- paste();
- break;
- case VisibilityNotify:
- if (ev.xvisibility.state != VisibilityUnobscured)
- XRaiseWindow(dpy, win);
- break;
- }
- }
-}
-
-static
-void
-setup(void)
-{
- int x, y, i, j;
- uint du;
- XSetWindowAttributes swa;
- XIM xim;
- Window w, dw, *dws;
- XWindowAttributes wa;
- XClassHint ch = {"menu", "menu"};
- XineramaScreenInfo *info;
- Window pw;
- int a, di, n, area = 0;
-
- /* init appearance */
- for (j = 0; j < SchemeLast; j++)
- scheme[j] = drw_scm_create(drw, colors[j], 2);
-
- clip = XInternAtom(dpy, "CLIPBOARD", False);
- utf8 = XInternAtom(dpy, "UTF8_STRING", False);
-
- /* calculate menu geometry */
- bh = drw->fonts->h + 2;
- lines = MAX(lines, 0);
- mh = (lines + 1) * bh;
- i = 0;
- if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
- XGetInputFocus(dpy, &w, &di);
- if (mon >= 0 && mon < n)
- i = mon;
- else if (w != root && w != PointerRoot && w != None) {
- /* find top-level window containing current input focus */
- do {
- if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
- XFree(dws);
- } while (w != root && w != pw);
- /* find xinerama screen with which the window intersects most */
- if (XGetWindowAttributes(dpy, pw, &wa))
- for (j = 0; j < n; j++)
- if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
- area = a;
- i = j;
- }
- }
- /* no focused window is on screen, so use pointer location instead */
- if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
- for (i = 0; i < n; i++)
- if (INTERSECT(x, y, 1, 1, info[i]))
- break;
-
- x = info[i].x_org;
- y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
- mw = info[i].width;
- XFree(info);
- } else
- {
- if (!XGetWindowAttributes(dpy, parentwin, &wa))
- fatal("could not get embedding window attributes: 0x%lx",
- parentwin);
- x = 0;
- y = topbar ? 0 : wa.height - mh;
- mw = wa.width;
- }
- promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
- inputw = MIN(inputw, mw/3);
- match();
-
- /* create menu window */
- swa.override_redirect = True;
- swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
- win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
- CopyFromParent, CopyFromParent, CopyFromParent,
- CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
- XSetClassHint(dpy, win, &ch);
-
-
- /* input methods */
- if ((xim = XOpenIM(dpy, nil, nil, nil)) == nil)
- fatal("XOpenIM failed: could not open input device");
-
- xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, win, XNFocusWindow, win, nil);
-
- XMapRaised(dpy, win);
- if (embed) {
- XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
- if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
- for (i = 0; i < du && dws[i] != win; ++i)
- XSelectInput(dpy, dws[i], FocusChangeMask);
- XFree(dws);
- }
- grabfocus();
- }
- drw_resize(drw, mw, mh);
- drawmenu();
-}
-
-static
-void
-usage(void)
-{
- fputs("usage: menu [-bfivP] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- XWindowAttributes wa;
- int i, fast = 0;
-
- for (i = 1; i < argc; i++)
- /* these options take no arguments */
- if (!strcmp(argv[i], "-v")) { /* prints version information */
- puts("menu-"VERSION);
- exit(0);
- } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */
- topbar = 0;
- else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
- fast = 1;
- else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
- fstrncmp = strncasecmp;
- fstrstr = cistrstr;
- } else if (!strcmp(argv[i], "-P")) {
- passwd = 1;
- } else if (i + 1 == argc)
- usage();
- /* these options take one argument */
- else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */
- lines = atoi(argv[++i]);
- else if (!strcmp(argv[i], "-m"))
- mon = atoi(argv[++i]);
- else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */
- prompt = argv[++i];
- else if (!strcmp(argv[i], "-fn")) /* font or font set */
- fonts[0] = argv[++i];
- else if (!strcmp(argv[i], "-nb")) /* normal background color */
- colors[SchemeNorm][ColBg] = argv[++i];
- else if (!strcmp(argv[i], "-nf")) /* normal foreground color */
- colors[SchemeNorm][ColFg] = argv[++i];
- else if (!strcmp(argv[i], "-sb")) /* selected background color */
- colors[SchemeSel][ColBg] = argv[++i];
- else if (!strcmp(argv[i], "-sf")) /* selected foreground color */
- colors[SchemeSel][ColFg] = argv[++i];
- else if (!strcmp(argv[i], "-w")) /* embedding window id */
- embed = argv[++i];
- else
- usage();
-
- if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
- fputs("warning: no locale support\n", stderr);
- if (!(dpy = XOpenDisplay(nil)))
- fatal("cannot open display");
- screen = DefaultScreen(dpy);
- root = RootWindow(dpy, screen);
- if (!embed || !(parentwin = strtol(embed, nil, 0)))
- parentwin = root;
- if (!XGetWindowAttributes(dpy, parentwin, &wa))
- fatal("could not get embedding window attributes: 0x%lx",
- parentwin);
- drw = drw_create(dpy, screen, root, wa.width, wa.height);
- if (!drw_fontset_create(drw, fonts, arrlen(fonts)))
- fatal("no fonts could be loaded.");
- lrpad = drw->fonts->h;
-
-#ifdef __OpenBSD__
- if (pledge("stdio rpath", nil) == -1)
- fatal("pledge");
-#endif
-
- if (fast && !isatty(0)) {
- grabkeyboard();
- readstdin();
- } else {
- readstdin();
- grabkeyboard();
- }
- setup();
- run();
-
- return 1; /* unreachable */
-}
diff --git a/sys/cmd/menu/menu.h b/sys/cmd/menu/menu.h
deleted file mode 100644
index f4345bb..0000000
--- a/sys/cmd/menu/menu.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-
-#include <time.h>
-#include <locale.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/Xinerama.h>
-#include <X11/Xft/Xft.h>
-
-#include "drw.h"
-
-/* macros */
-#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \
- * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
-#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
-#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
-
-
-/* enums */
-enum {
- SchemeNorm,
- SchemeSel,
- SchemeOut,
- SchemeLast
-}; /* color schemes */
-
-struct item {
- char *text;
- struct item *left, *right;
- int out;
-};
-
-/* util.c */
-void fatal(const char *fmt, ...);
-void *ecalloc(size_t nmemb, size_t size);
diff --git a/sys/cmd/menu/rules.mk b/sys/cmd/menu/rules.mk
deleted file mode 100644
index 1ee3ab0..0000000
--- a/sys/cmd/menu/rules.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-include share/push.mk
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := \
- $(d)/menu.c \
- $(d)/drw.c \
- $(d)/util.c
-
-BINS_$(d) := $(d)/menu
-
-include share/paths.mk
-
-# Local rules
-include share/dynamic.mk
-$(BINS_$(d)): TCLIBS = \
- -lfontconfig -lXft -lXinerama -lX11
-$(BINS_$(d)): TCINCS = \
- `$(PKG) --cflags fontconfig` \
- `$(PKG) --cflags freetype2`
-
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/menu/util.c b/sys/cmd/menu/util.c
deleted file mode 100644
index 14bfe1c..0000000
--- a/sys/cmd/menu/util.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "menu.h"
-
-void *
-ecalloc(size_t nmemb, size_t size)
-{
- void *p;
-
- if (!(p = calloc(nmemb, size)))
- fatal("calloc:");
- return p;
-}
-
-void
-fatal(const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
- fputc(' ', stderr);
- perror(NULL);
- } else {
- fputc('\n', stderr);
- }
-
- exit(1);
-}
diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c
deleted file mode 100644
index 786f284..0000000
--- a/sys/cmd/rc/code.c
+++ /dev/null
@@ -1,277 +0,0 @@
-#include "rc.h"
-#include "parse.h"
-#include "exec.h"
-
-// -----------------------------------------------------------------------
-// types
-
-struct Interpreter
-{
- int i, cap;
- Code *code;
-};
-
-Code *compiled = nil;
-static struct Interpreter interpreter;
-#define emiti(x) ((void)(interpreter.i != interpreter.cap || grow()), interpreter.code[interpreter.i].i = (x), interpreter.i++)
-#define emitf(x) ((void)(interpreter.i != interpreter.cap || grow()), interpreter.code[interpreter.i].f = (x), interpreter.i++)
-#define emits(x) ((void)(interpreter.i != interpreter.cap || grow()), interpreter.code[interpreter.i].s = (x), interpreter.i++)
-
-static
-int
-grow(void)
-{
- interpreter.cap += 100;
- interpreter.code = erealloc(interpreter.code, sizeof(*interpreter.code)*interpreter.cap);
- memset(interpreter.code+interpreter.cap-100, 0, 100*sizeof(*interpreter.code));
-
- return 0;
-}
-
-static
-void
-storepc(int a)
-{
- if(interpreter.i <= a || a < 0)
- fatal("bad address %d in interpreter", a);
-
- interpreter.code[a].i = interpreter.i;
-}
-
-static
-void
-walk(Tree *node)
-{
- Tree *n;
- int addr1, addr2;
-
- if(!node)
- return;
-
- switch(node->type){
- default:
- print(shell.err, "bad type %d in interpreter walk\n", node->type);
- fatal("crashing\n");
- break;
-
- case '$':
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xdollar);
- break;
-
- case Tcount:
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xcount);
- break;
-
- case Tjoin:
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xjoin);
- break;
-
- case Tindex:
- emitf(Xmark);
- walk(node->child[1]);
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xindex);
- break;
-
- case ';':
- walk(node->child[0]);
- walk(node->child[1]);
- break;
-
- case '^':
- emitf(Xmark);
- walk(node->child[1]);
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xconcatenate);
- break;
-
- case Tandand:
- walk(node->child[0]);
- emitf(Xtrue);
- addr1 = emiti(0);
- walk(node->child[1]);
- storepc(addr1);
- break;
-
- case Toror:
- walk(node->child[0]);
- emitf(Xfalse);
- addr1 = emiti(0);
- walk(node->child[1]);
- storepc(addr1);
- break;
-
- case Targs:
- walk(node->child[1]);
- walk(node->child[0]);
- break;
-
- case Tparen: case Tblock:
- walk(node->child[0]);
- break;
-
- case Tbasic:
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xbasic);
- break;
-
- case Tbang:
- walk(node->child[0]);
- emitf(Xbang);
-
- case Tword:
- emitf(Xword);
- emits(strdup(node->str));
- break;
-
- case Twords:
- walk(node->child[1]);
- walk(node->child[0]);
- break;
-
- case '=':
- for(n=node; node && node->type == '='; node = node->child[2])
- ;
- if(node){
- for(node=n; node->type=='='; node = node->child[2]){
- emitf(Xmark);
- walk(node->child[1]);
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xlocal);
- }
- walk(node);
- for(node=n; node->type=='='; node = node->child[2])
- emitf(Xunlocal);
- }else{
- for(node=n; node; node=node->child[2]){
- emitf(Xmark);
- walk(node->child[1]);
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xassign);
- }
- }
- node = n;
- break;
- /* control structures */
- case Twhile:
- addr1 = interpreter.i; // head of loop
- walk(node->child[0]);
- if(addr1 == interpreter.i)
- fatal("TODO");
- emitf(Xtrue);
- addr2 = emiti(0); // goto end of loop
-
- walk(node->child[1]);
- emitf(Xgoto);
- emiti(addr1); // goto top of loop
- storepc(addr2);
- break;
-
- case Tfor:
- emitf(Xmark);
- if(node->child[1]){ // for( x in X )
- walk(node->child[1]);
- // emitf(Xglob)
- }else{ // for(X)
- fatal("TODO");
- }
- emitf(Xmark); // null initial value for Xlocal
- emitf(Xmark);
- walk(node->child[0]);
- emitf(Xlocal);
-
- addr1 = emitf(Xfor);
- addr2 = emiti(0);
-
- walk(node->child[2]);
- emitf(Xgoto);
- emiti(addr1);
- storepc(addr2);
- emitf(Xunlocal);
- break;
-
- /* forks */
- case '&':
- emitf(Xasync);
- addr1 = emiti(0);
- walk(node->child[0]);
- emitf(Xexit);
- storepc(addr1);
- break;
-
- case Tsubshell:
- emitf(Xsubshell);
- addr1 = emiti(0);
- walk(node->child[0]);
- emitf(Xexit);
- storepc(addr1);
- break;
-
- case Tpipe:
- emitf(Xpipe);
-
- emiti(node->redir.fd[0]);
- emiti(node->redir.fd[1]);
- addr1 = emiti(0);
- addr2 = emiti(0);
-
- walk(node->child[0]);
- emitf(Xexit);
- storepc(addr1);
-
- walk(node->child[1]);
- emitf(Xreturn);
- storepc(addr2);
-
- emitf(Xpipewait);
-
- break;
- }
-}
-
-// -----------------------------------------------------------------------
-// main exports
-
-void
-freecode(Code *c)
-{
- if(--c[0].i!=0)
- return;
- efree(c);
-}
-
-Code *
-copycode(Code *c)
-{
- c[0].i++;
- return c;
-}
-
-int
-compile(Tree *node)
-{
- flush(shell.err);
-
- interpreter.i = 0;
- interpreter.code = emalloc(100*sizeof(*interpreter.code));
- emiti(0); // reference count: no thread owns code yet
-
- walk(node);
-
- emitf(Xreturn);
- emitf(nil);
-
- compiled = interpreter.code;
- return 0;
-}
diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c
deleted file mode 100644
index 5baaf1a..0000000
--- a/sys/cmd/rc/exec.c
+++ /dev/null
@@ -1,1267 +0,0 @@
-#include "rc.h"
-#include "exec.h"
-
-#include <sys/wait.h>
-
-int yyparse(void);
-
-struct Builtin{
- char *name;
- void (*func)(void);
-};
-
-struct State {
- int async;
-};
-
-static struct State state;
-
-// -----------------------------------------------------------------------
-// globals
-
-static Word nullpath = { .str="", .link=nil };
-
-struct Builtin builtin[]={
- {"cd", xcd},
- {".", xdot},
- {"echo", xecho},
- {"exit", xexit},
- {"fg", xfg},
- {"jobs", xjob},
- 0,
-};
-
-// -----------------------------------------------------------------------
-// internal
-
-/* words and lists */
-
-static
-void
-pushword(char *str)
-{
- if(!runner->args)
- fatal("attempt to push on empty argument stack\n");
-
- runner->args->word = makeword(str, runner->args->word);
-}
-
-static
-void
-popword(void)
-{
- Word *w;
- if(!runner->args)
- fatal("tried to pop word on empty argument stack\n");
-
- w = runner->args->word;
- if(!w)
- fatal("tried to pop word but nothing there\n");
-
- runner->args->word = w->link;
- efree(w->str);
- efree(w);
-}
-
-static
-Word*
-copywords(Word *a, Word *tail)
-{
- Word *v = nil, **end;
-
- for(end=&v; a; a = a->link,end=&(*end)->link)
- *end = makeword(a->str, nil);
- *end = tail;
-
- return v;
-}
-
-static
-void
-freewords(Word *w)
-{
- Word *n;
- while(w){
- efree(w->str);
- n = w->link;
- efree(w);
- w = n;
- }
-}
-
-static
-void
-freelist(Word *w)
-{
- Word *n;
- while(w){
- n = w->link;
- efree(w->str);
- efree(w);
- w = n;
- }
-
-}
-
-static
-void
-pushlist(void)
-{
- List *stack = emalloc(sizeof(*stack));
-
- stack->word = nil;
- stack->link = runner->args;
-
- runner->args = stack;
-}
-
-static
-void
-poplist(void)
-{
- List *stack = runner->args;
- if(!stack)
- fatal("attempted to pop an empty argument stack\n");
-
- freelist(stack->word);
- runner->args = stack->link;
- efree(stack);
-}
-
-/* system interop */
-static
-Word*
-path(char *w)
-{
- Word *path;
-
- if(strncmp(w, "/", 1)==0
- || strncmp(w, "./", 2)==0
- || strncmp(w, "../", 3)==0
- || (path = var("path")->val)==0)
- path=&nullpath;
-
- return path;
-}
-
-static inline
-void
-undoredirs(void)
-{
- while(runner->redir.end != runner->redir.start)
- Xpopredir();
-}
-
-static inline
-int
-exitsnext(void)
-{
- Code *c = &runner->code.exe[runner->code.i];
- while(c->f == Xpopredir)
- c++;
-
- return c->f == Xexit;
-}
-
-static inline
-void
-defaultsignal(void)
-{
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTSTP, SIG_DFL);
- signal(SIGTTIN, SIG_DFL);
- signal(SIGTTOU, SIG_DFL);
- signal(SIGCHLD, SIG_DFL);
-}
-
-static inline
-void
-setpid(Thread *job, int pid)
-{
- job->pid = pid;
- if(job->pgid <= 0){
- job->pgid = pid;
- addjob(job);
- }
-
- setpgid(pid, job->pgid);
-}
-
-/* fork/execute helpers */
-
-static inline
-void
-initchild(Thread *job, int fg)
-{
- int pid = getpid();
- setpid(job, pid);
-
- if(job->flag.user){
- if(fg)
- tcsetpgrp(0, job->pgid);
- else
- job->flag.user = 0;
- defaultsignal();
- }
-
- clearwait(job);
-}
-
-static inline
-void
-initparent(Thread *job, int pid, int fg)
-{
- setpid(job, pid);
-
- if(job->flag.user){
- if(!fg){
- tcsetpgrp(0, job->pgid);
- job->flag.user = 0;
- }
- }
- addwait(job, pid);
-}
-
-static
-void
-xx(void)
-{
- popword(); // "exec"
- if(!runner->args->word){
- Xerror("empty argument list");
- return;
- }
-
- redirect(runner->redir.end);
- execute(runner->args->word, path(runner->args->word->str));
- poplist();
-}
-
-static
-int
-xforkx(void)
-{
- int n, pid;
-
- switch(pid=fork()){
- case -1:
- Xerror("try again\n");
- return -1;
- case 0: // child
- initchild(runner, 1);
-
- pushword("exec");
- xx();
-
- exit(2); // NOTE: unreachable: xx does not return
- default: // parent
- initparent(runner, pid, 0);
-
- return pid;
- }
-}
-
-/* redirections */
-void
-pushredir(int type, int from, int to)
-{
- Redir *r = emalloc(sizeof(*r));
-
- r->type = type;
- r->from = from;
- r->to = to;
-
- r->link = runner->redir.end, runner->redir.end = r;
-}
-
-/* byte code */
-static
-void
-run(Code *c, int pc, Var *local, int inherit)
-{
- Thread *new = emalloc(sizeof(*new));
-
- new->code.i = pc;
- new->code.exe = copycode(c);
-
- new->cmd.path = nil;
- new->cmd.io = nil;
-
- new->args = nil;
- new->local = local;
-
- new->flag.eof = 0;
- if(runner){
- new->pid = runner->pid;
- new->flag.user = runner->flag.user;
- new->redir.end = new->redir.start = runner->redir.end;
- }else{
- new->pid = shell.pid;
- new->flag.user = shell.interactive;
- new->redir.end = new->redir.start = nil;
- }
-
- new->wait.status = 0;
- new->wait.len = 0;
- new->wait.cap = 0;
- new->wait.on = nil;
-
- new->status = 0;
- if(inherit)
- new->pgid = runner->pgid;
- else
- new->pgid = -1;
-
- new->line = 0;
- new->caller = runner;
- new->link = nil;
-
- runner = new;
-}
-
-// -----------------------------------------------------------------------
-// exported builtins
-
-// XXX: find a better place for these
-Word*
-makeword(char *str, Word *link)
-{
- Word *w = emalloc(sizeof(*w));
-
- w->str = strdup(str);
- w->link = link;
-
- return w;
-}
-
-void
-freeword(Word *word)
-{
- Word *n;
-
- while(word){
- efree(word->str);
- n = word->link;
- efree(word);
- word = n;
- }
-}
-
-int
-count(Word *w)
-{
- int n;
- for(n = 0; w; n++)
- w = w->link;
- return n;
-}
-
-// -----------------------------------------------------------------------
-// builtins
-
-void
-xecho(void)
-{
- int fd;
- Word *arg;
- char *b, *s, buf[128];
-
- fd = mapfd(1);
- b = buf;
-
- popword(); // echo
-
- // TODO: controllable flags here
- arg = runner->args->word;
-printword:
- s = arg->str;
- while(*s){
- *b++ = *s++;
- if(b == arrend(buf)-2) // always have 2 bytes available
- write(fd, buf, arrlen(buf)-2), b = buf;
- }
-
- arg = arg->link;
- if(arg){
- *b++ = ' ';
- goto printword;
- }else{
- *b++ = '\n';
- *b++ = 0;
- /* fallthrough */
- }
- write(fd, buf, b-buf);
-
- poplist();
-}
-
-void
-xexit(void)
-{
- Word *arg;
-
- popword(); // exit
- arg = runner->args->word;
- switch(count(arg)){
- default:
- print(shell.err, "invalid number of arguments to exit, exiting anyways\n");
- case 0:
- Xexit();
- }
- /* unreachable */
-}
-
-void
-xcd(void)
-{
- Word *arg;
- Word *cdpath;
- char dir[512];
-
- popword(); // cd
-
- arg = runner->args->word;
- switch(count(arg)){
- default:
- print(shell.err, "usage: cd [directory]\n");
- break;
- case 0:
- arg = var("home")->val;
- if(count(arg) >= 1){
- if(chdir(arg->str) < 0)
- print(shell.err, "failed cd: %s\n", strerror(errno));
- }else{
- print(shell.err, "ambiguous cd: $home empty\n");
- }
- break;
-
- case 1:
- // TODO: add cdpath
- cdpath = &nullpath;
- for(; cdpath; cdpath = cdpath->link){
- strcpy(dir, cdpath->str);
- if(dir[0])
- strcat(dir,"/");
- strcat(dir, arg->str);
- if(chdir(dir) < 0){
- print(shell.err, "failed cd %s: %s\n", dir, strerror(errno));
- }
- break;
- }
- break;
- }
-
- poplist();
-}
-
-static Code dotcmd[14] =
-{
- [0] = {.i = 0},
- [1] = {.f = Xmark},
- [2] = {.f = Xword},
- [3] = {.s = "0"},
- [4] = {.f = Xlocal},
- [5] = {.f = Xmark},
- [6] = {.f = Xword},
- [7] = {.s = "*"},
- [8] = {.f = Xlocal},
- [9] = {.f = Xreadcmd},
- [10] = {.f = Xunlocal},
- [11] = {.f = Xunlocal},
- [12] = {.f = Xreturn},
-};
-
-void
-xdot(void)
-{
- Word *p;
- List *argv;
- char *base;
- int fd, iflag = 0;
- Thread *old;
- char file[512];
-
- popword(); // "."
-#if 0
- if(proc->args->word && strcmp(proc->args->word->str, "-i")==0){
- iflag = 1;
- popword();
- }
-#endif
- /* get input file */
- if(!runner->args->word){
- Xerror("usage: . [-i] file [arg ...]\n");
- return;
- }
-
- base = strdup(runner->args->word->str);
- popword();
- for(fd=-1, p=path(base); p; p = p->link){
- strcpy(file, p->str);
-
- if(file[0])
- strcat(file, "/");
- strcat(file, base);
-
- if((fd = open(file, 0))>=0)
- break;
- }
-
- if(fd<0){
- print(shell.err, "failed open: %s: ", base);
- return;
- }
- /* set up for a new command loop */
- old = runner; // store pointer to old code
- run(dotcmd, 1, nil, 0);
-
- /* operations on new command stack */
- pushredir(Rclose, fd, 0);
- runner->cmd.path = base;
- runner->cmd.io = openfd(fd);
-
- /* push $* value */
- pushlist();
- runner->args->word = old->args->word;
-
- /* free caller's copy of $* */
- argv = old->args;
- old->args = argv->link;
- efree(argv);
-
- /* push $0 value */
- pushlist();
- pushword(base);
- //ndot++;
-}
-
-void
-xjob(void)
-{
- int i;
- Thread *job;
-
- for(i=0, job = shell.jobs; job; job = job->link, i++)
- report(job,i);
-
- poplist();
-}
-
-void
-xfg(void)
-{
- int i;
- Thread *job, *old;
-
- popword(); // fg
-
- /* get input job id */
- if(!runner->args->word){
- print(shell.err, "usage: fg [pid|\%num]\n");
- poplist();
- return;
- }
-
- i = atoi(runner->args->word->str);
- popword(); // [pid|num]
-
- for(job=shell.jobs; i > 0; job=job->link, --i)
- ;
-
- poplist(); // this goes here?
-
- wakeup(job);
- job->caller = runner, runner = job; // XXX: can this leave zombies?
- foreground(job, 1);
-}
-
-void
-xboot(int argc, char *argv[])
-{
- int i;
- Code bootstrap[32];
- char num[12];
-
- i = 0;
- bootstrap[i++].i = 1;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s="*";
- bootstrap[i++].f = Xassign;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s="*";
- bootstrap[i++].f = Xdollar;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s = "/dev/stdin";
- bootstrap[i++].f = Xword;
- bootstrap[i++].s=".";
- bootstrap[i++].f = Xbasic;
- bootstrap[i++].f = Xexit;
- bootstrap[i].i = 0;
-
- run(bootstrap, 1, nil, 0);
- runner->pid = runner->pgid = shell.pid;
- pushlist(); // prime bootstrap argv
-
- argv0 = strdup(argv[0]);
- for(i = argc-1; i > 0; --i)
- pushword(argv[i]);
-
- /* main interpreter loop */
- for(;;){
- runner->code.i++;
- (*runner->code.exe[runner->code.i-1].f)();
- }
-}
-
-// -----------------------------------------------------------------------
-// exported interpreter bytecode
-
-void
-Xmark(void)
-{
- pushlist();
-}
-
-void
-Xword(void)
-{
- pushword(runner->code.exe[runner->code.i++].s);
-}
-
-void
-Xtrue(void)
-{
- if(!runner->status){
- assert(runner->wait.status == Pdone);
- runner->code.i++;
- deljob(runner);
- runner->pgid = -1;
- }else
- runner->code.i = runner->code.exe[runner->code.i].i;
-}
-
-void
-Xfalse(void)
-{
- if(runner->status){
- assert(runner->wait.status == Pdone);
- runner->code.i++;
- deljob(runner);
- runner->pgid = -1;
- } else
- runner->code.i = runner->code.exe[runner->code.i].i;
-}
-
-void
-Xgoto(void)
-{
- runner->code.i = runner->code.exe[runner->code.i].i;
-}
-
-void
-Xfor(void)
-{
- if(!runner->args->word){
- poplist();
- runner->code.i = runner->code.exe[runner->code.i].i;
- }else{
- freelist(runner->local->val);
-
- runner->local->val = runner->args->word;
- runner->local->new = 1;
- runner->args->word = runner->args->word->link;
-
- runner->local->val->link = nil;
- runner->code.i++;
- }
-
-}
-
-static
-Word*
-catlist(Word *l, Word *r, Word *tail)
-{
- Word *w;
- char *buf;
-
- if(l->link || r->link)
- tail = catlist( (!l->link)?l:l->link, (!r->link)?r:r->link, tail);
-
- buf = emalloc(strlen(l->str)+strlen(r->str)+1);
- strcpy(buf, l->str);
- strcat(buf, r->str);
-
- w = makeword(buf, tail);
- efree(buf);
-
- return w;
-}
-
-void
-Xconcatenate(void)
-{
- int rn, ln;
- Word *l = runner->args->word;
- Word *r = runner->args->link->word;
- Word *w = runner->args->link->link->word;
-
- ln = count(l), rn = count(r);
- if(ln != 0 || rn != 0) {
- if(ln == 0 || rn == 0){
- Xerror("null list in concatenation\n");
- return;
- }
- if(ln != 1 && rn != 1 && ln != rn) {
- Xerror("mismatched list lengths in concatenation\n");
- return;
- }
- w = catlist(l, r, w);
- }
-
- poplist();
- poplist();
- runner->args->word = w;
-}
-
-void
-Xdollar(void)
-{
- int n;
- char *s, *t;
- Word *a, *star;
-
- if(count(runner->args->word)!=1){
- Xerror("variable name not singleton!\n");
- return;
- }
- s = runner->args->word->str;
- // deglob(s);
- n = 0;
-
- for(t = s;'0'<=*t && *t<='9';t++)
- n = n*10+*t-'0';
-
- a = runner->args->link->word;
-
- if(n==0 || *t)
- a = copywords(var(s)->val, a);
- else{
- star = var("*")->val;
- if(star && 1<=n && n<=count(star)){
- while(--n)
- star = star->link;
-
- a = makeword(star->str, a);
- }
- }
-
- poplist();
- runner->args->word = a;
-}
-
-static
-Word*
-cpwords(Word *array, Word *tail, int n)
-{
- Word *cp, **end;
-
- cp = nil, end = &cp;
- while(n-- > 0){
- *end = makeword(array->str, nil);
- end = &(*end)->link;
- array = array->link;
- }
- *end = tail;
-
- return cp;
-}
-
-
-static
-Word*
-getindex(Word *array, int len, Word *index, Word *tail)
-{
- char *s;
- int n, m;
- if(!index)
- return tail;
-
- tail = getindex(array, len, index->link, tail);
-
- s = index->str;
- //deglob(s)
-
- m = 0, n = 0;
- while('0' <= *s && *s <= '9')
- n = 10*n + (*s++ - '0');
- if(*s == '-'){
- if(*++s == 0)
- m = len - n;
- else{
- while('0' <= *s && *s <= '9')
- m = 10*m + (*s++ - '0');
- m -= n;
- }
- }
-
- if(n<1 || n > len || m < 0)
- return tail;
- if(n+m > len)
- m = len-n;
- while(--n > 0)
- array = array->link;
- return cpwords(array, tail, m+1);
-}
-
-void
-Xindex(void)
-{
- char *s;
- Word *val, *ret;
-
- if(count(runner->args->word) != 1){
- Xerror("variable name not a singleton");
- return;
- }
- s = runner->args->word->str;
- //deglob(s)
- val = var(s)->val;
- poplist();
-
- ret = runner->args->link->word; // pointer to next stack frame
- ret = getindex(val, count(val), runner->args->word, ret);
- poplist();
-
- // push result back on stack
- runner->args->word = ret;
-}
-
-void
-Xjoin(void)
-{
- int n;
- char *s;
- Word *arg, *elt;
-
- if(count(runner->args->word) != 1){
- Xerror("variable name is not singleton\n");
- return;
- }
-
- s = runner->args->word->str;
- // deglob(s)
-
- arg = var(s)->val;
- poplist();
-
- n = count(arg);
- if(n==0){
- pushword("");
- return;
- }
-
- for(elt = arg; elt; elt=elt->link)
- n += strlen(elt->str);
-
- s = emalloc(n);
- if(arg){
- strcpy(s, arg->str);
- for(elt = arg->link; elt; elt = elt->link){
- strcat(s, " ");
- strcat(s, elt->str);
- }
- }else
- s[0] = 0;
-
- pushword(s);
- efree(s);
-}
-
-void
-Xassign(void)
-{
- Var *v;
-
- if(count(runner->args->word)!=1){
- Xerror("variable name not singleton!\n");
- return;
- }
- //deglob(runq->argv->words->word);
- v = var(runner->args->word->str);
- poplist();
-
- //globlist();
- freewords(v->val);
- v->val = runner->args->word;
- v->new = 1;
- if(v->update)
- v->update(v);
-
- runner->args->word = nil;
- poplist();
-}
-
-void
-Xreadcmd(void)
-{
- Thread *root;
- Word *prompt;
-
- flush(shell.err);
- root = runner;
-
- resetprompt();
-
- if(yyparse()){
- // resource cleanup?
- if(runner->flag.eof)
- Xreturn();
- else
- --root->code.i;
- }else{
- --root->code.i; /* re-execute Xreadcmd after codebuf runs */
- run(compiled, 1, root->local, 0);
- }
-
- killzombies();
- freeparsetree();
-}
-
-void
-Xlocal(void)
-{
- if(count(runner->args->word)!=1){
- Xerror("variable name must be singleton\n");
- return;
- }
- //deglob(shell->args->word->str);
-
- runner->local = makevar(strdup(runner->args->word->str), runner->local);
- runner->local->val = copywords(runner->args->link->word, nil);
- runner->local->new = 1;
-
- poplist();
- poplist();
-}
-
-void
-Xunlocal(void)
-{
- Var *v = runner->local, *hide;
- if(!v)
- fatal("Xunlocal: no locals!\n", 0);
-
- runner->local = v->link;
- hide = var(v->name);
- hide->new = 1;
-
- efree(v->name);
- freewords(v->val);
- efree(v);
-}
-
-void
-Xasync(void)
-{
- int pid;
- /*
- int null = open("/dev/null", 0);
- if(!null){
- Xerror("can not open /dev/null\n");
- return;
- }
- */
-
- switch(pid=fork()){
- case -1:
- // close(null);
- Xerror("fork failed: try again");
- break;
-
- case 0: // child in background
- initchild(runner,0);
- /* pushredir(Ropen, null, 0); */
-
- run(runner->code.exe, runner->code.i+1, runner->local, 0);
- runner->caller = nil;
- runner->flag.user = 0;
- break;
-
- default: // parent in foreground
- initparent(runner,pid,1);
- // close(null);
-
- runner->code.i = runner->code.exe[runner->code.i].i; /* jump to end of async command */
- /* don't wait: continue running */
- }
-}
-
-void
-Xsubshell(void)
-{
- int pid, user;
-
- user = runner->flag.user;
- switch(pid=fork()){
- case -1:
- Xerror("fork failed: try again");
- break;
-
- case 0: // child
- initchild(runner, 1);
- run(runner->code.exe, runner->code.i+1, runner->local, 1);
- runner->caller = nil;
- break;
-
- default: // parent
- initparent(runner, pid, 0); // relinquish control
- waitfor(runner, pid); // wait until child finishes
- if(user){
- tcsetpgrp(0, shell.pid);
- runner->flag.user = 1; // take control
- }
-
- runner->code.i = runner->code.exe[runner->code.i].i; // jump to end of subshell command and continue execution
- }
-}
-
-void
-Xpipewait(void)
-{
- foreground(runner, 0);
-}
-
-void
-Xpipe(void)
-{
- Thread *orig;
- int pc, pid, lfd, rfd, pfd[2];
-
- orig = runner;
- pc = orig->code.i;
- lfd = orig->code.exe[pc++].i;
- rfd = orig->code.exe[pc++].i;
-
- if(pipe(pfd)<0){
- Xerror("can't get pipe\n");
- return;
- }
-
- switch(pid=fork()){
- case -1:
- Xerror("try again");
- break;
- case 0: // child
- initchild(runner,1);
-
- /* child 0 (writer) forked process */
- run(runner->code.exe, pc+2, runner->local, 1);
- runner->caller = nil;
-
- close(pfd[0]);
- pushredir(Ropen, pfd[1], lfd);
- break;
-
- default: // parent
- initparent(runner,pid,0);
-
- /* child 1 (reader) subprocess*/
- run(runner->code.exe, runner->code.exe[pc].i, runner->local, 1);
-
- close(pfd[1]);
- pushredir(Ropen, pfd[0], rfd);
-
- orig->code.i = orig->code.exe[pc+1].i;
- break;
- }
-}
-
-void
-Xbasic(void)
-{
- Var *v;
- Word *arg;
- int pid, status;
- struct Builtin *b;
-
- arg = runner->args->word;
- if(!arg){
- Xerror("empty argument list\n");
- return;
- }
-
- v = var(arg->str);
- if(v->func){
- return;
- }
-
- // see if it matches a builtin
- for(b = builtin; b->name; b++){
- if(strcmp(b->name, arg->str)==0){
- b->func();
- return;
- }
- }
-
- /* if we are here then it's an external command */
- if(exitsnext()){ // if we exit immediately, no need to fork
- pushword("exec");
- xx();
- Xexit();
- }
-
- // run the external command
- if((pid = xforkx()) < 0) {
- Xerror("try again");
- return;
- }
-
- poplist();
- foreground(runner, 0); // waits for child
-}
-
-void
-Xcount(void)
-{
- Word *arg;
- char *str, num[12];
-
- if(count(runner->args->word) != 1){
- Xerror("variable name not a singleton\n");
- return;
- }
-
- str = runner->args->word->str;
- arg = var(str)->val;
- poplist();
-
- itoa(num, count(arg));
- pushword(num);
-}
-
-void
-Xflat(void)
-{
- int len;
- char *str;
- Word *arg, *a;
-
- if(count(runner->args->word)!=1){
- Xerror("variable name is not a singleton\n");
- return;
- }
-
- str = runner->args->word->str;
- arg = var(str)->val;
- poplist();
-
- len = count(arg);
- if(!len){
- pushword("");
- return;
- }
-
- for(a=arg; a; a=a->link)
- len += strlen(a->str);
-
- str = emalloc(len);
- if(arg){
- strcpy(str, arg->str);
- for(a = arg->link; a; a = a->link){
- strcat(str," ");
- strcat(str,a->str);
- }
- }else
- str[0] = 0;
-
- pushword(str);
- efree(str);
-}
-
-void
-Xbang(void)
-{
- if(runner->status)
- runner->status = 0;
- else
- runner->status = 1;
-}
-
-void
-Xpopredir(void)
-{
- Redir *r = runner->redir.end;
- if(!r)
- fatal("attempted to pop a nil redir\n");
-
- runner->redir.end = runner->redir.end->link;
- if(r->type==Ropen)
- close(r->from);
-
- efree(r);
-}
-
-void
-Xreturn(void)
-{
- Thread *curr = runner;
-
- switch(curr->wait.status){
- /*
- * If our job is still running or suspended we must:
- * 1. move program one step back to rerun Xreturn upon recall
- * 2. return to our calling thread
- * 3. don't free!
- */
- case Prun:
- report(curr, 0);
- curr->flag.user = 0;
- case Pstop:
- curr->code.i--;
- runner = curr->caller;
- curr->caller = nil; // detach job
- return;
- /*
- * If our job has finished:
- * 1. remove from our list
- * 2. continue to clean up its memory
- */
- case Pdone:
- deljob(curr);
- /* fallthrough */
- default:
- ;
- }
-
- undoredirs();
-
- while(curr->args)
- poplist();
- freecode(curr->code.exe);
- efree(curr->wait.on);
-
- runner = curr->caller;
- efree(curr);
- if(!runner)
- exit(0);
-}
-
-void
-Xexit(void)
-{
- exit(runner->status);
-}
-
-void
-Xerror(char *msg)
-{
- print(shell.err, "rc: %s", msg);
- flush(shell.err);
- while(!runner->flag.user)
- Xreturn();
-}
-
diff --git a/sys/cmd/rc/exec.h b/sys/cmd/rc/exec.h
deleted file mode 100644
index a3a6ae9..0000000
--- a/sys/cmd/rc/exec.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-/*
- * opcode routines
- * arguments on stack (...)
- * arguments in line [...]
- * code in line with jump around {...}
- */
-
-void Xmark(void); // Xmark marks stack location for word
-void Xindex(void); // Xindex
-void Xlocal(void); // Xlocal(name,val) create local variable, assign value
-void Xunlocal(void); // Xunlocal delete local variable
-void Xdollar(void); // Xdollar(name) get value of name
-void Xtrue(void); // Xtrue{...} execute {} if true
-void Xfalse(void); // Xfalse{...} execute {} if false
-void Xgoto(void); // Xgoto[addr] goto address
-void Xfor(void); // Xfor(var, list){... Xreturn}
-void Xreadcmd(void); //
-void Xassign(void);
-void Xbang(void);
-void Xasync(void);
-void Xbasic(void); // Xbasic(args) run command and wait for result
-void Xsubshell(void);
-void Xword(void);
-void Xjoin(void);
-void Xconcatenate(void);
-void Xcount(void);
-void Xflat(void);
-void Xpipe(void);
-void Xpipewait(void);
-void Xpopredir(void);
-
-void Xreturn(void);
-void Xexit(void);
-
-void Xerror(char*);
-
-/* builtin commands */
-void xcd(void);
-void xdot(void);
-void xecho(void);
-void xexit(void);
-void xfg(void);
-void xjob(void);
-
-void xboot(int argc, char *argv[]);
diff --git a/sys/cmd/rc/input.c b/sys/cmd/rc/input.c
deleted file mode 100644
index cc2383d..0000000
--- a/sys/cmd/rc/input.c
+++ /dev/null
@@ -1,1679 +0,0 @@
-#include "rc.h"
-
-#include <termios.h>
-#include <sys/ioctl.h>
-
-/* don't change order of these without modifying matrix */
-enum
-{
- NonPrintable,
- Alnum,
- Punctuation,
- Space
-};
-
-static int ascii[256] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 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, 0,
-};
-
-struct Mode
-{
- ushort raw : 1;
- ushort multiline : 1;
- ushort mask : 1;
- ushort defer : 1;
- struct {
- ushort on : 1;
- ushort insert : 1;
- } vi ;
-};
-
-/*
- * the structure represents the state during line editing.
- * we pass this state to functions implementing specific editing functionalities
- */
-struct TerminalState
-{
- int ifd; /* terminal stdin file descriptor. */
- int ofd; /* terminal stdout file descriptor. */
-
- struct{
- char *s; /* raw UTF-8 bytes */
- int len; /* number of bytes in prompt */
- int size; /* number of (printed) runes in prompt */
- } prompt;
-
- struct{
- intptr cap; /* capacity of edit buffer */
- intptr len; /* current number of bytes stored */
- intptr pos; /* position within edit buffer */
- char *buf;
- } edit; /* edit buffer */
-
- struct{
- intptr cap; /* number of columns in terminal */
- intptr len; /* current edited line length (in runes) */
- intptr pos; /* current cursor position (in runes) */
- intptr old; /* previous refresh cursor position (in runes) */
- } cursor;
-
- struct{
- intptr cap;
- intptr len;
- char *buf;
- } yank; /* yank buffer */
-
- intptr maxrows; /* maximum num of rows used so far (multiline mode) */
- intptr history; /* index of history we are currently editing */
-};
-
-/*
- * line history (circular buffer)
- */
-struct History
-{
- char **bot, **top, *entry[1024];
-};
-
-/* globals */
-static struct Mode mode;
-static struct History history;
-static struct termios originalterm;
-
-enum
-{
- KeyNil = 0, /* nil */
- KeyCtrlA = 1, /* Ctrl+a */
- KeyCtrlB = 2, /* Ctrl-b */
- KeyCtrlC = 3, /* Ctrl-c */
- KeyCtrlD = 4, /* Ctrl-d */
- KeyCtrlE = 5, /* Ctrl-e */
- KeyCtrlF = 6, /* Ctrl-f */
- KeyCtrlH = 8, /* Ctrl-h */
- KeyTab = 9, /* Tab */
- KeyCtrlK = 11, /* Ctrl+k */
- KeyCtrlL = 12, /* Ctrl+l */
- KeyEnter = 13, /* Enter */
- KeyCtrlN = 14, /* Ctrl-n */
- KeyCtrlP = 16, /* Ctrl-p */
- KeyCtrlT = 20, /* Ctrl-t */
- KeyCtrlU = 21, /* Ctrl+u */
- KeyCtrlW = 23, /* Ctrl+w */
- KeyEsc = 27, /* Escape */
- KeyBackspace = 127 /* Backspace */
-};
-
-static void doatexit(void);
-
-/* vi operations */
-typedef struct
-{
- intptr buffer;
- intptr cursor;
-} Position;
-
-typedef Position (*Noun)(struct TerminalState*, int);
-typedef void (*Verb)(struct TerminalState*, Position);
-
-static
-int
-runetype(rune r)
-{
- if(r<128)
- return ascii[r];
- if(utf8·isspace(r))
- return Space;
- if(utf8·isdigit(r) || utf8·isalpha(r))
- return Alnum;
- if(utf8·ispunct(r))
- return Punctuation;
-
- return NonPrintable;
-}
-
-static
-void
-normalcursor(int fd)
-{
- write(fd,"\e[2 q",5);
-}
-
-static
-void
-insertcursor(int fd)
-{
- write(fd,"\e[6 q",5);
-}
-
-/* raw mode: 1960 magic shit. */
-static
-int
-enterraw(int fd)
-{
- struct termios raw;
-
- if(!shell.interactive)
- goto fatal;
-
- if(!mode.defer){
- atexit(doatexit);
- mode.defer = 1;
- }
- if(tcgetattr(fd,&originalterm) == -1)
- goto fatal;
-
- raw = originalterm; /* modify the original mode */
-
- /* input modes: no break, no CR to NL, no parity check, no strip char,
- * no start/stop output control. */
- raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
- /* output modes - disable post processing */
- raw.c_oflag &= ~(OPOST);
- /* control modes - set 8 bit chars */
- raw.c_cflag |= (CS8);
- /* local modes - choing off, canonical off, no extended functions,
- * no signal chars (^Z,^C) */
- raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
- /* control chars - set return condition: min number of bytes and timer.
- * We want read to return every single byte, without timeout. */
- raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
-
- /* put terminal in raw mode after flushing */
- if(tcsetattr(fd,TCSAFLUSH,&raw) < 0)
- goto fatal;
-
- mode.raw = 1;
- return 1;
-
-fatal:
- errno = ENOTTY;
- return 0;
-}
-
-static
-void
-exitraw(int fd)
-{
- /* don't even check the return value as it's too late. */
- if(mode.raw && tcsetattr(fd,TCSAFLUSH,&originalterm) != -1)
- mode.raw = 0;
-}
-
-/* use the esc [6n escape sequence to query the horizontal cursor position
- * and return it. on error -1 is returned, on success the position of the
- * cursor. */
-static
-int
-cursorposition(int ifd, int ofd)
-{
- char buf[32];
- int cols, rows;
- unsigned int i = 0;
-
- /* Report cursor location */
- if(write(ofd, "\x1b[6n", 4) != 4)
- return -1;
-
- /* Read the response: ESC [ rows ; cols R */
- while(i < sizeof(buf)-1) {
- if(read(ifd,buf+i,1) != 1)
- break;
- if(buf[i] == 'R')
- break;
- i++;
- }
- buf[i] = '\0';
-
- /* Parse it. */
- if(buf[0] != KeyEsc || buf[1] != '[')
- return -1;
- if(sscanf(buf+2,"%d;%d",&rows,&cols) != 2)
- return -1;
-
- return cols;
-}
-
-/* try to get the number of columns in the current terminal, or assume 80 if it fails. */
-static
-int
-columns(int ifd, int ofd)
-{
- struct winsize ws;
-
- if(ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0){
- /* ioctl() failed. Try to query the terminal itself. */
- int start, cols;
-
- /* Get the initial position so we can restore it later. */
- start = cursorposition(ifd,ofd);
- if(start == -1)
- goto failed;
-
- /* Go to right margin and get position. */
- if(write(ofd,"\x1b[999C",6) != 6)
- goto failed;
- cols = cursorposition(ifd,ofd);
- if(cols == -1)
- goto failed;
-
- /* Restore position. */
- if(cols > start){
- char esc[32];
- snprintf(esc,32,"\x1b[%dD",cols-start);
- if(write(ofd,esc,strlen(esc)) == -1)
- ;
- }
- return cols;
- }else
- return ws.ws_col;
-
-failed:
- return 80;
-}
-
-static
-void
-clear(void)
-{
- if(write(1,"\x1b[H\x1b[2J",7) <= 0)
- ;
-}
-
-/* beep: used for completion when there is nothing to complete or when all
- * the choices were already shown. */
-static
-void
-beep(void)
-{
- fprintf(stderr, "\x7");
- fflush(stderr);
-}
-
-// -----------------------------------------------------------------------
-// command history
-
-void
-inithistory(void)
-{
- history.bot = history.top = history.entry;
-}
-
-int
-addhistory(char *line)
-{
- char *copy;
-
- copy = strdup(line);
- if(!copy)
- return 0;
-
- *history.top++ = copy;
- if(history.top == arrend(history.entry))
- history.top = history.entry;
-
- if(history.top == history.bot){
- efree(history.bot);
- history.bot++;
- }
-
- return 1;
-}
-
-static
-void
-pophistory(void)
-{
- if(--history.top < history.entry)
- history.top = arrend(history.entry)-1;
- efree(*history.top);
-}
-
-static void refreshline(struct TerminalState *);
-
-static
-char **
-currenthistory(struct TerminalState *term, intptr *size)
-{
- char **entry;
- intptr len, head;
-
- if(history.top > history.bot){
- len = history.top - history.bot;
- entry = history.top - term->history - 1;
- }else if(history.top < history.bot){
- len = (arrend(history.entry) - history.bot) + (history.top - history.entry);
- if((head=history.top - history.entry) < term->history)
- entry = arrend(history.entry) - head;
- else
- entry = history.top - term->history - 1;
- }else
- return nil;
-
- *size = len;
- return entry;
-}
-
-static
-void
-usehistory(struct TerminalState *term, int d)
-{
- rune r;
- intptr w, len;
- char *b, *e, **entry;
-
- if(!(entry = currenthistory(term, &len)))
- return;
-
- efree(*entry);
- *entry = strdup(term->edit.buf);
-
- term->history += d;
- if(term->history < 0){
- term->history = 0;
- return;
- }else if(term->history >= len){
- term->history = len - 1;
- return;
- }
- entry = currenthistory(term, &len);
-
- strncpy(term->edit.buf, *entry, term->edit.cap);
- term->edit.buf[term->edit.cap-1] = 0;
-
- /* update cursor/buffer positions */
- term->edit.len = term->edit.pos = strlen(term->edit.buf);
- for(w=0, b=term->edit.buf, e=term->edit.buf+term->edit.len; b < e; ){
- b += utf8·decode(b, &r);
- w += utf8·runewidth(r);
- }
- term->cursor.len = term->cursor.pos = w;
-
- refreshline(term);
-}
-
-// -----------------------------------------------------------------------
-// line editing
-
-/*
- * we define a very simple "append buffer" structure, that is an heap
- * allocated string where we can append to. this is useful in order to
- * write all the escape sequences in a buffer and flush them to the standard
- * output in a single call, to avoid flickering effects.
- */
-
-struct Buffer
-{
- int len;
- char *b;
-};
-
-static
-void
-initbuffer(struct Buffer *ab)
-{
- ab->b = nil;
- ab->len = 0;
-}
-
-static
-void
-append(struct Buffer *ab, const char *s, int len)
-{
- char *new = realloc(ab->b,ab->len+len);
-
- if (new == nil) return;
- memcpy(new+ab->len,s,len);
- ab->b = new;
- ab->len += len;
-}
-
-static
-void
-freebuffer(struct Buffer *ab)
-{
- free(ab->b);
-}
-
-/* single line low level line refresh.
- *
- * rewrite the currently edited line accordingly to the buffer content,
- * cursor position, and number of columns of the terminal. */
-static
-void
-refreshsingleline(struct TerminalState *term)
-{
- char esc[64];
- struct Buffer ab;
-
- int n, w;
- rune r;
- int fd = term->ofd;
- intptr off = term->prompt.size;
- char *buf = term->edit.buf;
- intptr len = term->edit.len;
- intptr pos = term->cursor.pos;
- intptr col = term->cursor.len;
-
- while((off+pos) >= term->cursor.cap){
- n = utf8·decode(buf, &r);
- w = utf8·runewidth(r);
-
- buf+=n, len-=n;
- pos-=w, col-=w;
- }
-
- assert(buf <= term->edit.buf + len);
-
- while(off+col > term->cursor.cap){
- n = utf8·decodeprev(buf+len-1, &r);
- w = utf8·runewidth(r);
-
- len-=n, col-=w;
- }
- assert(len >= 0);
-
- initbuffer(&ab); // TODO: do we need so much malloc pressure?
-
- /* move cursor to left edge */
- snprintf(esc,64,"\r");
- append(&ab,"\r",1);
-
- /* write the prompt and the current buffer content */
- append(&ab, term->prompt.s, term->prompt.len);
-
- if(mode.mask == 1)
- while(len--)
- append(&ab,"*",1);
- else
- append(&ab,buf,len);
-
- snprintf(esc,64,"\x1b[0K"); // erase to right
- append(&ab,esc,strlen(esc));
-
- snprintf(esc,64,"\r\x1b[%dC", (int)(off+pos)); // move cursor to original position
- append(&ab,esc,strlen(esc));
-
- if(write(fd,ab.b,ab.len) == -1) /* can't recover from write error. */
- ;
-
- freebuffer(&ab);
-}
-
-/* multi line low level line refresh.
- *
- * Rewrite the currently edited line accordingly to the buffer content,
- * cursor position, and number of columns of the terminal. */
-static
-void
-refreshmultilines(struct TerminalState *term)
-{
-#if 0
- char esc[64];
- int plen = term->plen;
- int rows = (plen+term->len+term->cols-1)/term->cols; /* rows used by current buf. */
- int rpos = (plen+term->oldpos+term->cols)/term->cols; /* cursor relative row. */
- int rpos2; /* rpos after refresh. */
- int col; /* colum position, zero-based. */
- int i;
- int old_rows = term->maxrows;
- int fd = term->ofd, j;
- struct Buffer ab;
-
- /* Update maxrows if needed. */
- if(rows > (int)term->maxrows)
- term->maxrows = rows;
-
- /* First step: clear all the lines used before. To do so start by
- * going to the last row. */
- initbuffer(&ab);
- if(old_rows-rpos > 0){
- snprintf(esc,64,"\x1b[%dB", old_rows-rpos);
- append(&ab,esc,strlen(esc));
- }
-
- /* Now for every row clear it, go up. */
- for(j = 0; j < old_rows-1; j++){
- snprintf(esc,64,"\r\x1b[0K\x1b[1A");
- append(&ab,esc,strlen(esc));
- }
-
- /* clean the top line. */
- snprintf(esc,64,"\r\x1b[0K");
- append(&ab,esc,strlen(esc));
-
- /* Write the prompt and the current buffer content */
- append(&ab,term->prompt,strlen(term->prompt));
- if(mode.mask == 1){
- for(i = 0; i < term->len; i++) append(&ab,"*",1);
- }else
- append(&ab,term->buf,term->len);
-
- /* If we are at the very end of the screen with our prompt, we need to
- * emit a newline and move the prompt to the first column. */
- if(term->pos && term->pos == term->len && (term->pos+plen) % term->cols == 0) {
- append(&ab,"\n",1);
- snprintf(esc,64,"\r");
- append(&ab,esc,strlen(esc));
- rows++;
- if(rows > (int)term->maxrows)
- term->maxrows = rows;
- }
-
- /* Move cursor to right position. */
- rpos2 = (plen+term->pos+term->cols)/term->cols; /* current cursor relative row. */
-
- /* Go up till we reach the expected positon. */
- if(rows-rpos2 > 0){
- snprintf(esc,64,"\x1b[%dA", rows-rpos2);
- append(&ab,esc,strlen(esc));
- }
-
- /* Set column. */
- col = (plen+(int)term->pos) % (int)term->cols;
- if(col)
- snprintf(esc,64,"\r\x1b[%dC", col);
- else
- snprintf(esc,64,"\r");
- append(&ab,esc,strlen(esc));
-
- term->oldpos = term->pos;
-
- if(write(fd,ab.b,ab.len) == -1) /* Can't recover from write error. */
- ;
-
- freebuffer(&ab);
-#endif
-}
-
-/* Calls the two low level functions refreshSingleLine() or
- * refreshMultiLine() according to the selected mode. */
-static
-void
-refreshline(struct TerminalState *term)
-{
- if(mode.multiline)
- refreshmultilines(term);
- else
- refreshsingleline(term);
-}
-
-/* insert the rune 'c' at cursor current position.
- * on error writing to the terminal -1 is returned, otherwise 0. */
-int
-insertrune(struct TerminalState *term, int n, char *c)
-{
- int w;
- rune r;
-
- utf8·decode(c, &r);
- w = utf8·runewidth(r);
-
- if(term->edit.len + n <= term->edit.cap){
- if(term->edit.pos == term->edit.len){
- memcpy(term->edit.buf+term->edit.pos, c, n);
-
- term->edit.pos += n, term->edit.len += n;
- term->cursor.pos += w, term->cursor.len += w;
-
- term->edit.buf[term->edit.len] = '\0';
-
- if(!mode.multiline && ((term->prompt.size+term->cursor.pos+n) <= term->cursor.cap)){
- if(mode.mask){
- c = "*";
- n = 1;
- }
- if(write(term->ofd, c, n) == -1)
- return 0;
- }
- refreshline(term);
- }else{
- memmove(term->edit.buf+term->edit.pos+n, term->edit.buf+term->edit.pos, term->edit.len-term->edit.pos);
- memcpy(term->edit.buf+term->edit.pos, c, n);
-
- term->edit.pos += n, term->edit.len += n;
- term->cursor.pos += w, term->cursor.len += w;
-
- term->edit.buf[term->edit.len] = '\0';
- refreshline(term);
- }
- }
-
- return 1;
-}
-
-int
-insertbytes(struct TerminalState *term, int len, char *buf)
-{
- int nr;
- if(term->edit.len + len > term->edit.cap){
- len = term->edit.cap - term->edit.len;
- buf[len] = 0;
- }
- nr = utf8·len(buf);
-
- if(term->edit.pos == term->cursor.len){
- memcpy(term->edit.buf+term->edit.len, buf, len);
-
- term->edit.pos += len, term->edit.len += len;
- term->cursor.pos += nr, term->cursor.len += nr;
-
- // XXX: transfer the modeline here?
- term->edit.buf[term->edit.len] = '\0';
- refreshline(term);
- }else{
- memmove(term->edit.buf+term->edit.pos+len,term->edit.buf+term->edit.pos,term->edit.len-term->edit.pos);
- memcpy(term->edit.buf+term->edit.pos, buf, len);
-
- term->edit.pos += len, term->edit.len += len;
- term->cursor.pos += nr, term->cursor.len += nr;
-
- term->edit.buf[term->edit.len] = '\0';
- refreshline(term);
- }
-
- return 1;
-}
-
-// -----------------------------------------------------------------------
-// vi functionality
-
-/* modes */
-
-static
-void
-normalmode(int fd)
-{
- mode.vi.insert = 0;
- normalcursor(fd);
-}
-
-static
-void
-insertmode(int fd)
-{
- mode.vi.insert = 1;
- insertcursor(fd);
-}
-
-/* actions */
-
-static
-void
-move(struct TerminalState *term, Position to)
-{
- if(to.buffer != term->edit.pos){
- term->edit.pos = to.buffer;
- term->cursor.pos = to.cursor;
- refreshline(term);
- }
-}
-
-static
-void
-yank(struct TerminalState *term, Position to)
-{
- intptr len, off;
-
- if(to.buffer == term->edit.pos)
- return; // noop
-
- if(to.buffer > term->edit.pos){
- len = to.buffer - term->edit.pos;
- off = term->edit.pos;
- }else{
- len = term->edit.pos - to.buffer;
- off = to.buffer;
- }
-
- if(term->yank.cap < len+1){
- efree(term->yank.buf);
- term->yank.cap = len+1;
- term->yank.buf = emalloc(len+1);
- }
- term->yank.len = len;
- memcpy(term->yank.buf, term->edit.buf+off, len);
- term->yank.buf[len] = 0;
-}
-
-static
-void
-delete(struct TerminalState *term, Position to)
-{
- intptr diff;
-
- // delete characters in front of us (exclusive)
- if(to.buffer > term->edit.pos){
- diff = to.buffer - term->edit.pos;
- memmove(term->edit.buf+term->edit.pos, term->edit.buf+to.buffer, term->edit.len-to.buffer+1);
- term->edit.len -= diff;
-
- diff = to.cursor - term->cursor.pos;
- goto refresh;
- }
-
- // delete characters behind us
- if(to.buffer < term->edit.pos){
- diff = term->edit.pos - to.buffer;
- memmove(term->edit.buf+to.buffer, term->edit.buf+term->edit.pos, term->edit.len-term->edit.pos+1);
- term->edit.pos = to.buffer;
- term->edit.len -= diff;
-
- diff = term->cursor.pos - to.cursor;
- term->cursor.pos = to.cursor;
- goto refresh;
- }
- // do nothing
- return;
-
-refresh:
- term->cursor.len -= diff;
- refreshline(term);
-}
-/* movements */
-
-#define CURRENT(term) (Position){ .buffer=(term)->edit.pos, .cursor=(term)->cursor.pos };
-
-// move cursor to the left n boxes
-static
-Position
-left(struct TerminalState *term, int n)
-{
- rune r;
- int w, d;
- Position pos = CURRENT(term);
- char *buf = term->edit.buf + term->edit.pos;
-
- d = 0;
- while(n > 0 && buf > term->edit.buf){
- buf -= utf8·decodeprev(buf-1, &r);
-
- w = utf8·runewidth(r);
- n -= w;
- d += w;
- }
-
- pos.cursor = MAX(pos.cursor-d, 0);
- pos.buffer = MAX(buf-term->edit.buf, 0);
- return pos;
-}
-
-// move cursor to the right n boxes
-static
-Position
-right(struct TerminalState *term, int n)
-{
- rune r;
- int w, d;
- Position pos = CURRENT(term);
-
- char *buf = term->edit.buf + term->edit.pos;
- char *end = term->edit.buf + term->edit.len;
-
- d = 0;
- while(n > 0 && buf < end){
- buf += utf8·decode(buf, &r);
-
- w = utf8·runewidth(r);
- n -= w;
- d += w;
- }
-
- pos.cursor = MIN(pos.cursor+d, term->cursor.len);
- pos.buffer = MIN(buf-term->edit.buf, term->edit.len);
- return pos;
-}
-
-static
-Position
-prevword(struct TerminalState *term, int n)
-{
- rune r;
- int c, w, b, d;
- Position pos = CURRENT(term);
-
- char *buf = term->edit.buf + term->edit.pos;
-
- d = 0;
- while(n-- > 0 && buf > term->edit.buf){
- eatspace:
- b = utf8·decodeprev(buf-1, &r);
- w = utf8·runewidth(r);
- if((c=runetype(r)) == Space){
- buf -= b;
- d += w;
-
- if(buf <= term->edit.buf)
- break;
-
- goto eatspace;
- }
-
- eatword:
- if(runetype(r) == c){
- buf -= b;
- d += w;
-
- if(buf <= term->edit.buf)
- break;
-
- b = utf8·decodeprev(buf-1, &r);
- w = utf8·runewidth(r);
-
- goto eatword;
- }
- }
-
- pos.cursor = MAX(pos.cursor-d, 0);
- pos.buffer = MAX(buf-term->edit.buf, 0);
- return pos;
-}
-
-static
-Position
-nextword(struct TerminalState *term, int n)
-{
- rune r;
- int c, b, w, d;
- Position pos = CURRENT(term);
-
- char *buf = term->edit.buf + term->edit.pos;
- char *end = term->edit.buf + term->edit.len;
-
- d = 0;
- while(n-- > 0 && buf < end){
- b = utf8·decode(buf, &r);
- w = utf8·runewidth(r);
- c = runetype(r);
- eatword:
- if(runetype(r) == c){
- buf += b;
- d += w;
-
- if(buf >= end)
- break;
-
- b = utf8·decode(buf, &r);
- w = utf8·runewidth(r);
- goto eatword;
- }
- eatspace:
- while((c=runetype(r)) == Space){
- buf += b;
- d += w;
-
- if(buf >= end)
- break;
-
- b = utf8·decode(buf, &r);
- w = utf8·runewidth(r);
- goto eatspace;
- }
- }
-
- pos.cursor = MIN(pos.cursor+d, term->cursor.len);
- pos.buffer = MIN(buf-term->edit.buf, term->edit.len);
- return pos;
-}
-
-
-static
-Position
-prevWord(struct TerminalState *term, int n)
-{
- rune r;
- int c, w, b, d;
- Position pos = CURRENT(term);
-
- char *buf = term->edit.buf + term->edit.pos;
-
- d = 0;
- while(n-- > 0 && buf > term->edit.buf){
- eatspace:
- b = utf8·decodeprev(buf-1, &r);
- w = utf8·runewidth(r);
- if((c=runetype(r)) == Space){
- buf -= b;
- d += w;
-
- if(buf <= term->edit.buf)
- break;
-
- goto eatspace;
- }
-
- eatword:
- if((c=runetype(r)) != Space){
- buf -= b;
- d += w;
-
- if(buf <= term->edit.buf)
- break;
-
- b = utf8·decodeprev(buf-1, &r);
- w = utf8·runewidth(r);
-
- goto eatword;
- }
- }
-
- pos.cursor = MAX(pos.cursor-d, 0);
- pos.buffer = MAX(buf-term->edit.buf, 0);
- return pos;
-}
-
-static
-Position
-nextWord(struct TerminalState *term, int n)
-{
- rune r;
- int b, w, d;
- Position pos = CURRENT(term);
-
- char *buf = term->edit.buf + term->edit.pos;
- char *end = term->edit.buf + term->edit.len;
-
- d = 0;
- while(n-- > 0 && buf < end){
- eatword:
- b = utf8·decode(buf, &r);
- w = utf8·runewidth(r);
- if(runetype(r) != Space){
- buf += b;
- d += w;
-
- if(buf > end)
- break;
-
- goto eatword;
- }
-
- eatspace:
- if(runetype(r) == Space){
- buf += b;
- d += w;
-
- if(buf > end)
- break;
-
- b = utf8·decode(buf, &r);
- w = utf8·runewidth(r);
-
- goto eatspace;
- }
- }
-
- pos.cursor = MIN(pos.cursor+d, term->cursor.len);
- pos.buffer = MIN(buf-term->edit.buf, term->edit.len);
- return pos;
-}
-
-static
-Position
-nextend(struct TerminalState *term, int n)
-{
- rune r;
- int c, b, w, d;
- Position pos = CURRENT(term);
-
- char *buf = term->edit.buf + term->edit.pos;
- char *end = term->edit.buf + term->edit.len;
-
- d = 0;
- while(n-- > 0 && buf+1 < end){
- eatspace:
- b = utf8·decode(buf+1, &r);
- w = utf8·runewidth(r);
- while((c=runetype(r)) == Space){
- buf += b;
- d += w;
-
- if(buf+1 >= end)
- break;
-
- goto eatspace;
- }
- eatword:
- if(runetype(r) == c){
- buf += b;
- d += w;
-
- if(buf+1 >= end)
- break;
-
- b = utf8·decode(buf+1, &r);
- w = utf8·runewidth(r);
- goto eatword;
- }
- }
-
- pos.cursor = MIN(pos.cursor+d, term->cursor.len);
- pos.buffer = MIN(buf-term->edit.buf, term->edit.len);
- return pos;
-}
-
-static
-Position
-nextEnd(struct TerminalState *term, int n)
-{
- rune r;
- int b, w, d;
- Position pos = CURRENT(term);
-
- char *buf = term->edit.buf + term->edit.pos;
- char *end = term->edit.buf + term->edit.len;
-
- d = 0;
- while(n-- > 0 && buf+1 < end){
- eatspace:
- b = utf8·decode(buf+1, &r);
- w = utf8·runewidth(r);
- if(runetype(r) == Space){
- buf += b;
- d += w;
-
- if(buf+1 > end)
- break;
-
- goto eatspace;
- }
-
- eatword:
- if(runetype(r) != Space){
- buf += b;
- d += w;
-
- if(buf+1 > end)
- break;
-
- b = utf8·decode(buf+1, &r);
- w = utf8·runewidth(r);
-
- goto eatword;
- }
- }
-
- pos.cursor = MIN(pos.cursor+d, term->cursor.len);
- pos.buffer = MIN(buf-term->edit.buf, term->edit.len);
- return pos;
-}
-
-#define HOME(term) (Position){0}
-#define END(term) (Position){(term)->edit.len, (term)->cursor.len}
-
-static
-int
-vi(struct TerminalState *term, char c)
-{
- int n = 1;
- Verb verb = move;
-
-action:
- switch(c){
- /* # of repeats */
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- n = 0;
- while('0' <= c && c <= '9'){
- n = 10*n + (c-'0');
- if(read(term->ifd, &c, 1)<1)
- return -1;
- }
- goto action;
-
- /* composable actions */
- case 'l': verb(term, right(term, n)); break;
- case 'h': verb(term, left(term, n)); break;
- case '0': verb(term, HOME(term)); break;
- case '$': verb(term, END(term)); break;
- case 'b': verb(term, prevword(term,n)); break;
- case 'B': verb(term, prevWord(term,n)); break;
- case 'w': verb(term, nextword(term,n)); break;
- case 'W': verb(term, nextWord(term,n)); break;
- case 'e': verb(term, nextend(term,n)); break;
- case 'E': verb(term, nextEnd(term,n)); break;
-
- /* verb switches */
- case 'd': // delete
- verb = delete;
- if(read(term->ifd, &c, 1)<1)
- return -1;
- /* special cases */
- switch(c){
- case 'd':
- move(term, HOME(term));
- delete(term, END(term));
- return 0;
- default:
- goto action;
- }
- case 'y': // yank
- verb = yank;
- if(read(term->ifd, &c, 1)<1)
- return -1;
- /* special cases */
- switch(c){
- case 'y':
- if(term->yank.cap < term->edit.len+1){
- efree(term->yank.buf);
- term->yank.len = term->edit.len;
- term->yank.cap = term->edit.len+1;
- term->yank.buf = emalloc(term->yank.cap);
- }
- memcpy(term->yank.buf, term->edit.buf, term->edit.len+1);
- break;
- default:
- goto action;
- }
- break;
-
- case 'p': // put
- insertbytes(term, term->yank.len, term->yank.buf);
- refreshline(term);
- return 0;
-
- /* special cases
- * sadly I don't know a better way than to have these checks for move
- * the vi language doesn't fully compose
- */
- case 'i': insertmode:
- if(verb != move) goto unrecognized;
- insertmode(term->ofd);
- break;
-
- case 'I':
- if(verb != move) goto unrecognized;
- move(term, HOME(term));
- goto insertmode;
-
- case 'a':
- if(verb != move) goto unrecognized;
- if(term->edit.pos < term->edit.len){
- term->edit.pos++;
- refreshline(term);
- }
- goto insertmode;
-
- case 'A':
- if(verb != move) goto unrecognized;
- move(term, END(term));
- goto insertmode;
-
- case 'x':
- if(verb != move) goto unrecognized;
- delete(term, right(term, 1));
- break;
-
- case 'X':
- if(verb != move) goto unrecognized;
- delete(term, left(term, 1));
- break;
-
- case 'r':
- if(verb != move) goto unrecognized;
- if(read(term->ifd, &c, 1)<1)
- return -1;
- if(c < ' ')
- break;
- term->edit.buf[term->edit.pos] = c;
- refreshline(term);
- break;
-
- // TODO: replace mode?
-
- case 'c':
- if(verb != move) goto unrecognized;
- insertmode(term->ofd);
- verb = delete;
- if(read(term->ifd, &c, 1)<1)
- return -1;
- goto action;
-
- case 'C':
- if(verb != move) goto unrecognized;
- insertmode(term->ofd);
- goto deleteln;
-
- case 'D':
- if(verb != move) goto unrecognized;
- deleteln:
- term->edit.len = term->edit.pos;
- term->edit.buf[term->edit.pos] = 0;
- refreshline(term);
- break;
-
- default: unrecognized:
- beep();
- break;
- }
-
- return 0;
-}
-#undef END
-
-#define END(term) (Position){(term).edit.len, (term).cursor.len}
-
-static
-int
-size(char *s)
-{
- rune c;
- int n, len = 0;;
- while((c=*s)){
- if(c == '\033'){
- n = 1;
- esccode:
- c = s[n];
- if(!c) // we hit end of string in the middle of parsing an escape code!
- return len;
- if(c == 'm'){
- s += n + 1;
- continue; // outer loop
- }
- n++;
- goto esccode;
- }
- n = utf8·decode(s, &c);
- s += n;
- len += utf8·runewidth(c);
- }
- return len;
-}
-
-/* this function is the core of the line editing capability of linenoise.
- * it expects 'fd' to be already in "raw mode" so that every key pressed
- * will be returned asap to read().
- *
- * the resulting string is put into 'buf' when the user type enter, or
- * when ctrl+d is typed.
- *
- * the function returns the length of the current buffer. */
-static
-int
-interact(int ifd, int ofd, char *buf, intptr len, char *prompt)
-{
- int n, aux;
- char esc[3];
- char c[UTFmax+1] = { 0 };
- rune r;
-
- struct TerminalState term;
- /*
- * populate the state that we pass to functions implementing
- * specific editing functionalities
- */
- term.ifd = ifd;
- term.ofd = ofd;
-
- term.edit.buf = buf;
- term.edit.cap = len;
- term.edit.len = 0;
- term.edit.pos = 0;
-
- term.prompt.s = prompt;
- term.prompt.len = strlen(prompt);
- term.prompt.size = size(prompt);
-
- term.cursor.pos = 0;
- term.cursor.len = 0;
- term.cursor.cap = columns(ifd, ofd);
-
- term.maxrows = 0;
- term.history = 0;
-
- term.yank.buf = nil;
- term.yank.cap = term.yank.len = 0;
-
- /* buffer starts empty. */
- term.edit.buf[0] = '\0';
- term.edit.cap--; /* make sure there is always space for the nulterm */
-
- /* push current (empty) command onto history stack */
- addhistory("");
-
- if(write(term.ofd,prompt,term.prompt.len) == -1)
- return -1;
-
- for(;;){
- n = read(term.ifd,c,1);
- if(n <= 0)
- goto finish;
-
- /* partition input by rune */
- if(utf8·onebyte(c[0])){
- r = c[0];
- }else if(utf8·twobyte(c[0])){
- n = read(term.ifd,c+1,1);
- if(n < 1 || (n=utf8·decode(c, &r)) != 2)
- goto finish;
- }else if(utf8·threebyte(c[0])){
- n = read(term.ifd,c+1,2);
- if(n < 2 || (n=utf8·decode(c, &r)) != 3)
- goto finish;
- }else if(utf8·fourbyte(c[0])){
- n = read(term.ifd,c+1,3);
- if(n < 3 || (n=utf8·decode(c, &r)) != 4)
- goto finish;
- }else
- goto finish;
-
- switch(r){
- case KeyEnter:
- pophistory();
- if(mode.multiline)
- move(&term, END(term));
- goto finish;
-
- case KeyCtrlC:
- errno = EAGAIN;
- return -1;
-
- case KeyBackspace:
- case KeyCtrlH:
- delete(&term, left(&term, 1));
- break;
-
- case KeyCtrlD:
- if(term.edit.len > 0)
- delete(&term, right(&term, 1));
- break;
-
- case KeyCtrlT:
- if(term.edit.pos > 0 && term.edit.pos < term.edit.len){
- aux = buf[term.edit.pos-1];
-
- buf[term.edit.pos-1] = buf[term.edit.pos];
- buf[term.edit.pos] = aux;
-
- if(term.edit.pos != term.edit.len-1)
- term.edit.pos++;
-
- refreshline(&term);
- }
- break;
-
- case KeyCtrlB:
- move(&term, left(&term, 1));
- break;
-
- case KeyCtrlF: /* ctrl-f */
- move(&term, right(&term, 1));
- break;
-
- case KeyCtrlP: /* ctrl-p */
- usehistory(&term, +1);
- break;
-
- case KeyCtrlN: /* ctrl-n */
- usehistory(&term, -1);
- break;
-
- case KeyEsc: /* escape sequence */
- /*
- * try to read two bytes representing the escape sequence.
- * if we read less than 2 and we are in vi mode, interpret as command
- *
- * NOTE: we could do a timed read here
- */
- switch(read(term.ifd,esc,2)){
- case 0:
- if(mode.vi.on){
- if(mode.vi.insert){
- normalmode(term.ofd);
- if(term.edit.pos > 0){
- --term.edit.pos;
- refreshline(&term);
- }
- continue;
- }
- }
- case 1:
- if(mode.vi.on){
- if(mode.vi.insert){
- normalmode(term.ofd);
- if(vi(&term,esc[0]) < 0){
- term.edit.len = -1;
- goto finish;
- }
- continue;
- }
- }
- default: // 2
- ;
- }
-
- /* ESC [ sequences. */
- if(esc[0] == '['){
- if(0 <= esc[1] && esc[1] <= '9'){
- /* extended escape, read additional byte. */
- if(read(term.ifd,esc+2,1) == -1)
- break;
-
- if(esc[2] == '~'){
- switch(esc[1]){
- case '3': /* delete key. */
- delete(&term, left(&term,1));
- break;
- }
- }
- }else{
- switch(esc[1]) {
- case 'A': /* up */
- usehistory(&term, +1);
- break;
- case 'B': /* down */
- usehistory(&term, -1);
- break;
- case 'C': /* right */
- move(&term, right(&term, 1));
- break;
- case 'D': /* left */
- move(&term, left(&term, 1));
- break;
- case 'H': /* home */
- move(&term, HOME(term));
- break;
- case 'F': /* end*/
- move(&term, END(term));
- break;
- }
- }
- }
- /* ESC O sequences. */
- else if(esc[0] == 'O'){
- switch(esc[1]) {
- case 'H': /* home */
- move(&term, HOME(term));
- break;
- case 'F': /* end*/
- move(&term, END(term));
- break;
- }
- }
- break;
-
- default:
- if(mode.vi.on && !mode.vi.insert && n == 1){
- if(vi(&term,c[0]) < 0){
- term.edit.len = -1;
- goto finish;
- }
- }else if(!insertrune(&term,n,c)){
- term.edit.len = -1;
- goto finish;
- }
-
- break;
-
- case KeyCtrlU: /* Ctrl+u, delete the whole line. */
- buf[0] = '\0';
- term.edit.pos = term.edit.len = 0;
- term.cursor.pos = term.cursor.len = 0;
- refreshline(&term);
- break;
-
- case KeyCtrlK: /* Ctrl+k, delete from current to end of line. */
- buf[term.edit.pos] = '\0';
- term.edit.len = term.edit.pos;
- term.cursor.len = term.cursor.pos;
- refreshline(&term);
- break;
-
- case KeyCtrlA: /* Ctrl+a, go to the start of the line */
- move(&term, HOME(term));
- break;
-
- case KeyCtrlE: /* ctrl+e, go to the end of the line */
- move(&term, END(term));
- break;
-
- case KeyCtrlL: /* ctrl+term, clear screen */
- clear();
- refreshline(&term);
- break;
-
- case KeyCtrlW: /* ctrl+w, delete previous word */
- delete(&term, prevword(&term,1));
- break;
- }
- }
-finish:
- efree(term.yank.buf);
- return term.edit.len;
-}
-
-/*
- * this special mode is used by linenoise in order to print scan codes
- * on screen for debugging / development purposes. It is implemented
- * by the linenoise_example program using the --keycodes option.
- */
-void
-printkeycode(void)
-{
- int n;
- char c, quit[4];
-
- printf("entering debugging mode. printing key codes.\n"
- "press keys to see scan codes. type 'quit' at any time to exit.\n");
-
- if(!enterraw(0))
- return;
-
- memset(quit,' ',4);
-
- for(;;){
- n = read(0,&c,1);
- if(n <= 0)
- continue;
- memmove(quit,quit+1,sizeof(quit)-1); // shift string to left
- quit[arrlen(quit)-1] = c; /* Insert current char on the right. */
-
- if(memcmp(quit,"quit",sizeof(quit)) == 0)
- break;
-
- printf("'%c' %02x (%d) (type quit to exit)\n", isprint(c) ? c : '?', (int)c, (int)c);
- printf("\r"); /* go to left edge manually, we are in raw mode. */
- fflush(stdout);
- }
- exitraw(0);
-}
-
-/*
- * this function calls the line editing function edit() using the stdin set in raw mode
- */
-static
-int
-raw(char *buf, intptr len, char *prompt)
-{
- int n;
-
- if(!len){
- errno = EINVAL;
- return -1;
- }
-
- // XXX: should we not hardcode stdin and stdout fd?
- if(!enterraw(0)) return -1;
- n = interact(0, 1, buf, len, prompt);
- exitraw(0);
-
- return n;
-}
-
-/*
- * called when readline() is called with the standard
- * input file descriptor not attached to a TTY. For example when the
- * program is called in pipe or with a file redirected to its standard input
- * in this case, we want to be able to return the line regardless of its length
- */
-static
-int
-notty(void)
-{
- int c;
-
- for(;;){
- c = fgetc(stdin);
- put(&runner->cmd.io, c);
- }
-}
-
-void
-enablevi(void)
-{
- mode.vi.on = 1;
- insertmode(1);
-}
-
-/*
- * The high level function that is the main API.
- * This function checks if the terminal has basic capabilities and later
- * either calls the line editing function or uses dummy fgets() so that
- * you will be able to type something even in the most desperate of the
- * conditions.
- */
-int
-readline(char *prompt)
-{
- int n;
-
- // reset the command buffer
- runner->cmd.io->e = runner->cmd.io->b = runner->cmd.io->buf;
-
- if(!shell.interactive)
- return notty();
-
- if((n = raw(runner->cmd.io->e, runner->cmd.io->cap-1, prompt)) == -1)
- return 0;
- runner->cmd.io->e += n;
-
- /* insert a newline character at the end */
- put(&runner->cmd.io, '\n');
-
- return 1;
-}
-
-/* At exit we'll try to fix the terminal to the initial conditions. */
-static
-void
-doatexit(void)
-{
- exitraw(0);
- normalcursor(1);
-}
diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c
deleted file mode 100644
index dc81c2e..0000000
--- a/sys/cmd/rc/io.c
+++ /dev/null
@@ -1,437 +0,0 @@
-#include "rc.h"
-#include "parse.h"
-
-#define CAP0 512
-
-Io*
-openfd(int fd)
-{
- Io *io = emalloc(sizeof(*io) + CAP0);
-
- io->fd = fd;
- io->cap = CAP0;
- io->b = io->e = io->buf;
- io->s = nil;
-
- return io;
-}
-
-Io*
-openstr(void)
-{
- char *s;
- Io *io = emalloc(sizeof(*io) + CAP0);
-
- io->fd = -1;
- io->cap = CAP0;
- io->b = io->s = emalloc(101);
- io->e = io->b+100;
-
- for(s = io->b; s<=io->e; s++)
- *s=0;
-
- return io;
-}
-
-#if 0
-/*
- * open a corebuffer to read. EOF occurs after reading len characters from buf
- */
-
-Io*
-opencore(char *s, int len)
-{
- Io *io = emalloc(sizeof(*io));
- char *buf = emalloc(len);
- io->fd = -1 /*open("/dev/null", 0)*/;
- io->b = io->s = buf;
- io->e = buf+len;
- memcpy(buf, s, len);
-
- return io;
-}
-#endif
-
-void
-iorewind(Io *io)
-{
- if(io->fd==-1)
- io->b = io->s;
- else{
- io->b = io->e = io->buf;
- lseek(io->fd, 0L, 0);
- }
-}
-
-void
-terminate(Io *io)
-{
- if(io->fd>=0)
- close(io->fd);
- if(io->s)
- efree(io->s);
-
- efree((char *)io);
-}
-
-static
-int
-refill(Io *io)
-{
- int n;
-
- if(io->fd==-1 || (n = read(io->fd, io->buf, io->cap))<=0)
- return EOF;
-
- io->b = io->buf;
- io->e = io->buf+n;
-
- return *io->b++&0xff;
-}
-
-
-void
-flush(Io *io)
-{
- int n;
- char *s;
-
- if(io->s){
- n = io->e-io->s;
- io->s = realloc(io->s, n+101);
- if(io->s==0)
- panicf("Can't realloc %d bytes in flush!", n+101);
- io->b = io->s+n;
- io->e = io->b+100;
- for(s = io->b;s<=io->e;s++) *s='\0';
- }else{
- n = io->b-io->buf;
- if(n && write(io->fd, io->buf, n) < 0)
- write(3, "write error\n", 12);
- io->b = io->buf;
- io->e = io->buf + io->cap;
- }
-}
-
-
-static
-void
-printchar(Io *io, int c)
-{
- if(io->b==io->e)
- flush(io);
-
- *io->b++=c;
-}
-
-void
-printquote(Io *io, char *s)
-{
- printchar(io, '\'');
- for(;*s;s++)
- if(*s=='\'')
- print(io, "''");
- else printchar(io, *s);
- printchar(io, '\'');
-}
-
-void
-printstr(Io *io, char *s)
-{
- if(s==0)
- s="(null)";
- while(*s) printchar(io, *s++);
-}
-
-void
-printword(Io *io, char *s)
-{
- char *t;
-
- for(t = s;*t;t++)
- if(!iswordchar(*t))
- break;
-
- if(t==s || *t)
- printquote(io, s);
- else
- printstr(io, s);
-}
-
-void
-printptr(Io *io, void *v)
-{
- int n;
- uintptr p;
-
- p = (uintptr)v;
- if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
- for(n = 60;n>=32;n-=4) printchar(io, "0123456789ABCDEF"[(p>>n)&0xF]);
-
- for(n = 28;n>=0;n-=4) printchar(io, "0123456789ABCDEF"[(p>>n)&0xF]);
-}
-
-static
-void
-printint(Io *io, int n)
-{
- if(n<0){
- if(n!=INT_MIN){
- printchar(io, '-');
- printint(io, -n);
- return;
- }
- /* n is two's complement minimum integer */
- n = -(INT_MIN+1);
- printchar(io, '-');
- printint(io, n/10);
- printchar(io, n%10+'1');
- return;
- }
- if(n>9)
- printint(io, n/10);
- printchar(io, n%10+'0');
-}
-
-static
-void
-printoct(Io *io, unsigned n)
-{
- if(n>7)
- printoct(io, n>>3);
- printchar(io, (n&7)+'0');
-}
-
-static
-void
-printval(Io *io, Word *a)
-{
- if(a){
- while(a->link && a->link->str){
- printword(io, a->str);
- printchar(io, ' ');
- a = a->link;
- }
- printword(io, a->str);
- }
-}
-
-#define C0 t->child[0]
-#define C1 t->child[1]
-#define C2 t->child[2]
-
-static
-void
-printtree(Io *io, Tree *t)
-{
- if(!t)
- return;
-
- switch(t->type){
- default: print(io, "bad(%d)[%p %p %p]", t->type, C0, C1, C2); break;
- case '$': print(io,"$%t",C0); break;
- case '&': print(io,"%t&",C0); break;
- case '^': print(io,"%t^%t",C0,C1); break;
- case '`': print(io,"`%t",C0); break;
-
- case Tbasic: print(io, "%t", C0); break;
- case Tbang: print(io, "!%t", C0); break;
- case Tblock: print(io, "{%t}", C0); break;
- case Tcount: print(io, "$#%t", C0); break;
- case Tparen: print(io, "(%t)", C0); break;
- case Tjoin: print(io,"$\"%t",C0); break;
- case Tindex: print(io, "%t(%t)",C0); break;
- case Tsubshell: print(io, "@ %t",C0); break;
- //case Ttwiddle: print(io, "~ %t %t", C0, C1); break;
-
- case Toror:
- case Tandand:
-
- case Targs:
- if(!C0)
- print(io, "%t", C1);
- else if(!C1)
- print(io, "%t", C0);
- else
- print(io, "%t %t", C0, C1);
- break;
-
- case ';':
- if(C0){
- if(C1)
- print(io, "%t;%t", C0, C1);
- else
- print(io, "%t", C0);
- }else
- print(io, "%t", C1);
- break;
-
- case Twords:
- if(C0)
- print(io, "%t", C0);
- print(io, "%t", C1);
-
- case Tword:
- if(t->quoted)
- print(io, "%Q", t->str);
- print(io, "%q", t->str);
- break;
-
- case '=':
- print(io, "%t=%t", C0, C1);
- if(C2)
- print(io, " %t", C2);
- break;
-
- case Tdup:
- if(t->redir.type == Rdupfd)
- print(io, ">[%d=%d]", t->redir.fd[1], t->redir.fd[0]);
- else
- print(io, ">[%d=]", t->redir.fd[0]);
- print(io, "%t", C1);
- break;
-
- case Tredir:
- switch(t->redir.type){
- case Rhere:
- printchar(io, '<');
- case Rread:
- printchar(io, '<');
- goto readfd;
- case Rrdwr:
- printchar(io, '<');
- printchar(io, '>');
- readfd:
- if(t->redir.fd[0]!=0)
- print(io, "[%d]", t->redir.fd[0]);
- break;
- case Rappend:
- printchar(io, '>');
- goto writefd;
- case Rwrite:
- printchar(io, '>');
- printchar(io, '>');
- writefd:
- if(t->redir.fd[0]!=1)
- print(io, "[%d]", t->redir.fd[0]);
- break;
- }
- print(io, "%t", C0);
- if(C1)
- print(io, " %t", C1);
- break;
-
- case Tpipe:
- print(io, "%t|", C0);
- if(t->redir.fd[1]==0){
- if(t->redir.fd[0]!=1)
- print(io, "[%d]", t->redir.fd[0]);
- }
- else
- print(io, "[%d=%d]", t->redir.fd[0], t->redir.fd[1]);
- print(io, "%t", C1);
- break;
- }
-}
-
-#undef C0
-#undef C1
-#undef C2
-
-// -----------------------------------------------------------------------
-// exports
-
-/* readers */
-int
-get(Io *io)
-{
- if(io->b==io->e)
- return refill(io);
-
- return *io->b++ & 0xFF;
-}
-
-/* writers */
-int
-put(Io **iop, char c)
-{
- int nb, ne, nc;
- Io *io = *iop;
- char *e = io->b + io->cap;
-
- if(io->e == e){
- nb = io->b - io->buf;
- ne = io->e - io->buf;
- nc = 2*io->cap;
-
- if(!(io = erealloc(io, sizeof(*io)+nc)))
- return 0;
-
- io->b = io->buf + nb;
- io->e = io->buf + ne;
- io->cap = nc;
-
- *iop = io;
- }
-
- *io->e++ = c;
- return 1;
-}
-
-/* printers */
-static int pfmtnest;
-
-void
-print(Io *io, char *fmt, ...)
-{
- va_list args;
- char err[ERRMAX];
-
- va_start(args, fmt);
- pfmtnest++;
-
- for(;*fmt;fmt++)
- if(*fmt!='%')
- printchar(io, *fmt);
- else
- switch(*++fmt){
- case '\0':
- va_end(args);
- return;
- case 'c':
- printchar(io, va_arg(args, int));
- break;
- case 'd':
- printint(io, va_arg(args, int));
- break;
- case 'o':
- printoct(io, va_arg(args, unsigned));
- break;
- case 'p':
- printptr(io, va_arg(args, void*));
- break;
- case 'Q':
- printquote(io, va_arg(args, char *));
- break;
- case 'q':
- printword(io, va_arg(args, char *));
- break;
- case 's':
- printstr(io, va_arg(args, char *));
- break;
- case 't':
- printtree(io, va_arg(args, struct Tree *));
- break;
- case 'v':
- printval(io, va_arg(args, struct Word *));
- break;
- default:
- printchar(io, *fmt);
- break;
- }
-
- va_end(args);
-
- if(--pfmtnest==0)
- flush(io);
-}
diff --git a/sys/cmd/rc/job.c b/sys/cmd/rc/job.c
deleted file mode 100644
index 1587951..0000000
--- a/sys/cmd/rc/job.c
+++ /dev/null
@@ -1,91 +0,0 @@
-#include "rc.h"
-
-#include <signal.h>
-#include <termios.h>
-
-// -----------------------------------------------------------------------
-// exports
-
-Thread *
-getjob(int pid, int *index)
-{
- int i;
- Thread *job;
- for(i=0,job=shell.jobs; job && job->pid != pid; i++, job=job->link)
- ;
-
- return job;
-}
-
-void
-report(Thread *job, int index)
-{
- switch(job->wait.status){
- case Pdone:
- print(shell.err, "job %d [%d]: done\n", index, job->pid);
- break;
- case Pstop:
- print(shell.err, "job %d [%d]: suspended\n", index, job->pid);
- break;
- case Pagain:
- print(shell.err, "job %d [%d]: continued\n", index, job->pid);
- break;
- case Prun:
- print(shell.err, "job %d [%d]: running\n", index, job->pid);
- break;
- default:
- fatal("bad wait status: %d\n", job->wait.status);
- }
-}
-
-void
-wakeup(Thread *job)
-{
- int i;
- job->wait.status = Prun;
- for(i=0; i < job->wait.len; i++){
- if(job->wait.on[i].status == Pstop)
- job->wait.on[i].status = Prun;
- }
-
- tcsetpgrp(0, job->pgid);
-}
-
-void
-foreground(Thread *job, int now)
-{
- Thread *caller = job->caller;
- if(now){
- if(kill(-job->pgid, SIGCONT) < 0)
- perror("kill[SIGCONT]");
- }
-
- waitall(job);
- /*
- * reset state if we have a caller
- * otherwise we will exit anyways
- */
- if(caller && caller->flag.user){
- tcsetpgrp(0, caller->pid);
- job->flag.user = 1;
- }
-}
-
-void
-addjob(Thread *job)
-{
- job->link = shell.jobs;
- shell.jobs = job;
- job->wait.status = Prun;
-}
-
-void
-deljob(Thread *job)
-{
- Thread **jp;
-
- for(jp = &shell.jobs; *jp && *jp != job; jp = &(*jp)->link)
- ;
-
- *jp = job->link;
-}
diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c
deleted file mode 100644
index 9ca2453..0000000
--- a/sys/cmd/rc/lex.c
+++ /dev/null
@@ -1,394 +0,0 @@
-#include "rc.h"
-#include "parse.h"
-
-static int advance(void);
-
-// -----------------------------------------------------------------------
-// lexer
-
-struct Lexer
-{
- int c[2];
- ushort doprompt;
- ushort hadword;
- ushort haddollar;
- ushort inquote;
- char buf[BUFSIZ];
-};
-
-static struct Lexer lexer = { .c={0, EOF}, .doprompt=1 };
-
-#define put1(b) lexer.buf[0] = (b), lexer.buf[1] = 0;
-#define put2(b0,b1) lexer.buf[0] = (b0), lexer.buf[1] = (b1), lexer.buf[2] = 0;
-#define put3(b0,b1,b2) lexer.buf[0] = (b0), lexer.buf[1] = (b1), lexer.buf[2] = b2, lexer.buf[3] = 0;
-
-void
-yyerror(const char *msg)
-{
- print(shell.err, "rc:%d: ", runner->line);
-
- if(lexer.buf[0] && lexer.buf[0]!='\n')
- print(shell.err, "%q: ", lexer.buf);
-
- print(shell.err, "%s\n", msg);
- flush(shell.err);
-
- lexer.hadword = 0;
- lexer.haddollar = 0;
-
- /* consume remaining tokens */
- while(lexer.c[0] !='\n' && lexer.c[0] != EOF)
- advance();
-}
-
-int
-readc(void)
-{
- int c;
- static int peek = EOF;
-
- if(peek!=EOF){
- c = peek;
- peek = EOF;
- return c;
- }
-
- if(runner->flag.eof)
- return EOF;
-
- if(!prompt(&lexer.doprompt))
- exit(1); // XXX: hack for signal handling right now...
-
- c = get(runner->cmd.io);
- lexer.doprompt = lexer.doprompt || c=='\n' || c==EOF;
-
- if(c==EOF)
- runner->flag.eof = 1;
-
- return c;
-}
-
-static
-int
-peekc(void)
-{
- if(lexer.c[1] == EOF)
- lexer.c[1] = readc();
-
- return lexer.c[1];
-}
-
-static
-int
-advance(void)
-{
- int c = peekc();
- lexer.c[0] = lexer.c[1], lexer.c[1] = EOF;
-
- return c;
-}
-
-static
-void
-skipws(void)
-{
- int c;
- for(;;){
- c = peekc();
- if(c== ' ' || c == '\t')
- advance();
- else
- return;
- }
-}
-
-static
-void
-skipnl(void)
-{
- int c;
- for(;;){
- c = peekc();
- if(c== ' ' || c == '\t' || c == '\n')
- advance();
- else
- return;
- }
-}
-
-static
-int
-nextis(int c)
-{
- if(peekc()==c){
- advance();
- return 1;
- }
- return 0;
-}
-
-static
-char *
-putbyte(char *buf, int c)
-{
- if(!buf)
- return buf;
-
- if(buf == arrend(lexer.buf)){
- fatal("lexer: out of buffer space");
- return nil;
- }
- *buf++ = c;
- return buf;
-}
-
-static
-char *
-putrune(char *buf, int c)
-{
- buf = putbyte(buf, c);
- if(utf8·onebyte(c))
- return buf;
- if(utf8·twobyte(c))
- return putbyte(buf,advance());
- if(utf8·threebyte(c)){
- buf = putbyte(buf,advance());
- return putbyte(buf,advance());
- }
- if(utf8·fourbyte(c)){
- buf = putbyte(buf,advance());
- buf = putbyte(buf,advance());
- return putbyte(buf,advance());
- }
- fatal("malformed utf8 stream");
-
- return nil;
-}
-
-// -----------------------------------------------------------------------
-// exported functions
-
-// TODO: turn into static tables
-int
-iswordchar(int c)
-{
- return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
-}
-
-int
-isidentchar(int c)
-{
- return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
-}
-
-int
-yylex(void)
-{
- int c, d = peekc();
- Tree *node;
- char *w = lexer.buf;
-
- yylval.tree = nil;
-
- /* inject tokens */
- if(lexer.hadword){
- lexer.hadword = 0;
- if(d=='('){
- advance();
- strcpy(lexer.buf, "( [Tindex]");
- return Tindex;
- }
- if(iswordchar(d) || d=='\'' || d=='`' || d=='$' || d=='"'){
- strcpy(lexer.buf, "^");
- return '^';
- }
- }
-
- lexer.inquote = 0;
-
- skipws();
- switch(c=advance()){
- case EOF:
- lexer.haddollar = 0;
- put3('E','O','F');
- return EOF;
-
- case '$':
- lexer.haddollar = 1;
- if(nextis('#')){
- put2('$','#');
- return Tcount;
- }
- if(nextis('^')){
- put2('$','^');
- return Tjoin;
- }
- put1('$');
- return '$';
-
- case '@':
- lexer.haddollar = 0;
- put1('@');
- return Tsubshell;
-
- case '!':
- lexer.haddollar = 0;
- put1('!');
- return Tbang;
-
- case '&':
- lexer.haddollar = 0;
- if(nextis('&')){
- put2('&','&');
- return Tandand;
- }
- put1('&');
- return '&';
-
- case '|':
- lexer.haddollar = 0;
- if(nextis('|')){
- put2('|','|');
- return Toror;
- }
- node = maketree();
- *w++ = '|';
-
- node->type = Tpipe;
- node->redir.fd[0] = 1;
- node->redir.fd[1] = 0;
- goto redir;
-
- case '>':
- lexer.haddollar = 0;
- node = maketree();
- *w++ = '>';
- node->type = Tredir;
-
- if(nextis('>')){
- node->redir.type = Rappend;
- *w++ = '>';
- }else
- node->redir.type = Rwrite;
- node->redir.fd[0] = 1;
- goto redir;
-
- case '<':
- lexer.haddollar = 0;
- node = maketree();
- *w++ = '<';
- node->type = Tredir;
-
- if(nextis('<')){
- node->redir.type = Rhere;
- *w++ = '<';
- }else if(nextis('>')){
- node->redir.type = Rrdwr;
- *w++ = '>';
- }else{
- node->redir.type = Rread;
- }
- node->redir.fd[0] = 0;
- /* fallthrough */
- redir:
- if(nextis('[')){
- *w++='[';
- c = advance();
- *w++ = c;
- if(c < '0' || '9' < c){
- badredir:
- *w = 0;
- yyerror(node->type == Tpipe ? "pipe syntax" : "redirection syntax");
- return EOF;
- }
- node->redir.fd[0] = 0;
- do{
- node->redir.fd[0] = 10*node->redir.fd[0]+(c-'0');
- *w++ = c;
- c = advance();
- }while('0'<=c && c<='9');
-
- if(c == '='){
- *w++ = '=';
- if(node->type==Tredir)
- node->type = Tdup;
- c = advance();
- }
- if(c < '0' || '9' < c){
- if(node->type == Tpipe)
- goto badredir;
- node->redir.type = Rclose;
- }else{
- node->redir.type = Rdupfd;
- node->redir.fd[1] = node->redir.fd[0];
- node->redir.fd[0] = 0;
- do{
- node->redir.fd[0] = 10*node->redir.fd[0]+(c-'0');
- *w++ = c;
- c = advance();
- }while('0'<=c && c<='9');
- }
- if(c != ']' || (node->type == Tdup && (node->redir.type = Rhere || node->redir.type == Rappend)))
- goto badredir;
- *w++ = ']';
- }
- *w++ = 0;
- yylval.tree = node;
-
- return node->type;
-
- case '\'':
- lexer.hadword = 1;
- lexer.inquote = 1;
- lexer.haddollar = 0;
- for(;;){
- c = advance();
- if(c==EOF)
- break;
-
- if(c=='\''){
- if(peekc()!='\'')
- break;
- advance();
- }
- w = putrune(w, c);
- }
- if(w)
- *w = 0;
- node = token(Tword, lexer.buf);
- node->quoted = 1;
- return node->type;
-
- default:
- ;
- }
- if(!iswordchar(c)){
- put1(c);
- lexer.haddollar = 0;
- return c;
- }
-
- for(;;){
- w = putrune(w, c);
- c = peekc();
- if(lexer.haddollar ? !isidentchar(c) : !iswordchar(c))
- break;
- advance();
- }
-
- lexer.hadword = 1;
- lexer.haddollar = 0;
- if(w)
- *w = 0;
-
- node = token(Tword, lexer.buf);
- if((c=iskeyword(lexer.buf))){
- node->type = c;
- lexer.hadword = 0;
- }
-
- node->quoted = 0;
-
- yylval.tree = node;
- return node->type;
-}
diff --git a/sys/cmd/rc/main.c b/sys/cmd/rc/main.c
deleted file mode 100644
index 2c0aa42..0000000
--- a/sys/cmd/rc/main.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "rc.h"
-#include "parse.h"
-#include "exec.h"
-
-#include <signal.h>
-#include <termios.h>
-
-// -----------------------------------------------------------------------
-// globals
-
-Thread *runner = nil;
-Shell shell = { 0 };
-
-// -----------------------------------------------------------------------
-// functions
-
-void
-initshell(void)
-{
- if((shell.interactive=isatty(0))){
- while(tcgetpgrp(0) != (shell.pid = getpgrp()))
- kill(-shell.pid, SIGTTIN);
-
- /* ignore job control signals */
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- signal(SIGTSTP, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- /*
- * NOTE: if SIGCHLD is set to SIG_IGN then
- * 1. children that terminate do not become zombies
- * 2. call a to wait() will block until all children have terminated
- * 3. the call to wait will fail with errno == ECHILD
- * see for discussion:
- * https://stackoverflow.com/questions/1608017/no-child-process-error-from-waitpid-when-waiting-for-process-group
- */
- // signal(SIGCHLD, SIG_IGN);
-
- /* take control */
- shell.pid = getpid();
- if(setpgid(shell.pid, shell.pid)<0)
- fatal("could not put shell in its own process group");
-
- tcsetpgrp(shell.pid, shell.pid);
- }
-}
-
-// -----------------------------------------------------------------------
-// main point of entry
-
-int
-main(int argc, char *argv[])
-{
- shell.err = openfd(2);
-
- initenv();
- initpath();
- initkeywords();
- initshell();
- inithistory();
-
- enablevi();
- xboot(argc, argv);
- /* unreachable */
-}
diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c
deleted file mode 100644
index 1b29d41..0000000
--- a/sys/cmd/rc/parse.c
+++ /dev/null
@@ -1,2059 +0,0 @@
-/* A Bison parser, made by GNU Bison 3.8.2. */
-
-/* Bison implementation for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
- Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
- simplifying the original so-called "semantic" parser. */
-
-/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
- especially those whose name start with YY_ or yy_. They are
- private implementation details that can be changed or removed. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* Identify Bison output, and Bison version. */
-#define YYBISON 30802
-
-/* Bison version string. */
-#define YYBISON_VERSION "3.8.2"
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 0
-
-/* Push parsers. */
-#define YYPUSH 0
-
-/* Pull parsers. */
-#define YYPULL 1
-
-
-
-
-/* First part of user prologue. */
-#line 7 "sys/cmd/rc/syntax.y"
-
- #include "rc.h"
-
- int yylex(void);
- void yyerror(const char *);
-
-#line 78 "sys/cmd/rc/parse.c"
-
-# ifndef YY_CAST
-# ifdef __cplusplus
-# define YY_CAST(Type, Val) static_cast<Type> (Val)
-# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
-# else
-# define YY_CAST(Type, Val) ((Type) (Val))
-# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
-# endif
-# endif
-# ifndef YY_NULLPTR
-# if defined __cplusplus
-# if 201103L <= __cplusplus
-# define YY_NULLPTR nullptr
-# else
-# define YY_NULLPTR 0
-# endif
-# else
-# define YY_NULLPTR ((void*)0)
-# endif
-# endif
-
-#include "parse.h"
-/* Symbol kind. */
-enum yysymbol_kind_t
-{
- YYSYMBOL_YYEMPTY = -2,
- YYSYMBOL_YYEOF = 0, /* "end of file" */
- YYSYMBOL_YYerror = 1, /* error */
- YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
- YYSYMBOL_Tfor = 3, /* Tfor */
- YYSYMBOL_Tin = 4, /* Tin */
- YYSYMBOL_Twhile = 5, /* Twhile */
- YYSYMBOL_Tif = 6, /* Tif */
- YYSYMBOL_Telse = 7, /* Telse */
- YYSYMBOL_Tswitch = 8, /* Tswitch */
- YYSYMBOL_Tcase = 9, /* Tcase */
- YYSYMBOL_Tcasebody = 10, /* Tcasebody */
- YYSYMBOL_Ttwiddle = 11, /* Ttwiddle */
- YYSYMBOL_Tbang = 12, /* Tbang */
- YYSYMBOL_Tsubshell = 13, /* Tsubshell */
- YYSYMBOL_Tfunc = 14, /* Tfunc */
- YYSYMBOL_Tredir = 15, /* Tredir */
- YYSYMBOL_Tdup = 16, /* Tdup */
- YYSYMBOL_Tpipe = 17, /* Tpipe */
- YYSYMBOL_Tindex = 18, /* Tindex */
- YYSYMBOL_Tbasic = 19, /* Tbasic */
- YYSYMBOL_Targs = 20, /* Targs */
- YYSYMBOL_Tword = 21, /* Tword */
- YYSYMBOL_Twords = 22, /* Twords */
- YYSYMBOL_Tparen = 23, /* Tparen */
- YYSYMBOL_Tblock = 24, /* Tblock */
- YYSYMBOL_25_ = 25, /* ')' */
- YYSYMBOL_Tandand = 26, /* Tandand */
- YYSYMBOL_Toror = 27, /* Toror */
- YYSYMBOL_28_n_ = 28, /* '\n' */
- YYSYMBOL_29_ = 29, /* '^' */
- YYSYMBOL_30_ = 30, /* '$' */
- YYSYMBOL_Tcount = 31, /* Tcount */
- YYSYMBOL_Tjoin = 32, /* Tjoin */
- YYSYMBOL_33_ = 33, /* '(' */
- YYSYMBOL_34_ = 34, /* '{' */
- YYSYMBOL_35_ = 35, /* '}' */
- YYSYMBOL_36_ = 36, /* ';' */
- YYSYMBOL_37_ = 37, /* '&' */
- YYSYMBOL_38_ = 38, /* '=' */
- YYSYMBOL_39_ = 39, /* '`' */
- YYSYMBOL_YYACCEPT = 40, /* $accept */
- YYSYMBOL_rc = 41, /* rc */
- YYSYMBOL_line = 42, /* line */
- YYSYMBOL_body = 43, /* body */
- YYSYMBOL_paren = 44, /* paren */
- YYSYMBOL_block = 45, /* block */
- YYSYMBOL_cmds = 46, /* cmds */
- YYSYMBOL_cmdsln = 47, /* cmdsln */
- YYSYMBOL_ifbody = 48, /* ifbody */
- YYSYMBOL_case = 49, /* case */
- YYSYMBOL_casebody = 50, /* casebody */
- YYSYMBOL_assign = 51, /* assign */
- YYSYMBOL_redir = 52, /* redir */
- YYSYMBOL_epilog = 53, /* epilog */
- YYSYMBOL_cmd = 54, /* cmd */
- YYSYMBOL_basic = 55, /* basic */
- YYSYMBOL_atom = 56, /* atom */
- YYSYMBOL_word = 57, /* word */
- YYSYMBOL_executable = 58, /* executable */
- YYSYMBOL_nonkeyword = 59, /* nonkeyword */
- YYSYMBOL_keyword = 60, /* keyword */
- YYSYMBOL_words = 61, /* words */
- YYSYMBOL_wordsnl = 62, /* wordsnl */
- YYSYMBOL_nl = 63 /* nl */
-};
-typedef enum yysymbol_kind_t yysymbol_kind_t;
-
-
-
-
-#ifdef short
-# undef short
-#endif
-
-/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
- <limits.h> and (if available) <stdint.h> are included
- so that the code can choose integer types of a good width. */
-
-#ifndef __PTRDIFF_MAX__
-# include <limits.h> /* INFRINGES ON USER NAME SPACE */
-# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
-# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_STDINT_H
-# endif
-#endif
-
-/* Narrow types that promote to a signed type and that can represent a
- signed or unsigned integer of at least N bits. In tables they can
- save space and decrease cache pressure. Promoting to a signed type
- helps avoid bugs in integer arithmetic. */
-
-#ifdef __INT_LEAST8_MAX__
-typedef __INT_LEAST8_TYPE__ yytype_int8;
-#elif defined YY_STDINT_H
-typedef int_least8_t yytype_int8;
-#else
-typedef signed char yytype_int8;
-#endif
-
-#ifdef __INT_LEAST16_MAX__
-typedef __INT_LEAST16_TYPE__ yytype_int16;
-#elif defined YY_STDINT_H
-typedef int_least16_t yytype_int16;
-#else
-typedef short yytype_int16;
-#endif
-
-/* Work around bug in HP-UX 11.23, which defines these macros
- incorrectly for preprocessor constants. This workaround can likely
- be removed in 2023, as HPE has promised support for HP-UX 11.23
- (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
- <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */
-#ifdef __hpux
-# undef UINT_LEAST8_MAX
-# undef UINT_LEAST16_MAX
-# define UINT_LEAST8_MAX 255
-# define UINT_LEAST16_MAX 65535
-#endif
-
-#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
-typedef __UINT_LEAST8_TYPE__ yytype_uint8;
-#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
- && UINT_LEAST8_MAX <= INT_MAX)
-typedef uint_least8_t yytype_uint8;
-#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
-typedef unsigned char yytype_uint8;
-#else
-typedef short yytype_uint8;
-#endif
-
-#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
-typedef __UINT_LEAST16_TYPE__ yytype_uint16;
-#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
- && UINT_LEAST16_MAX <= INT_MAX)
-typedef uint_least16_t yytype_uint16;
-#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
-typedef unsigned short yytype_uint16;
-#else
-typedef int yytype_uint16;
-#endif
-
-#ifndef YYPTRDIFF_T
-# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
-# define YYPTRDIFF_T __PTRDIFF_TYPE__
-# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
-# elif defined PTRDIFF_MAX
-# ifndef ptrdiff_t
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# endif
-# define YYPTRDIFF_T ptrdiff_t
-# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
-# else
-# define YYPTRDIFF_T long
-# define YYPTRDIFF_MAXIMUM LONG_MAX
-# endif
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-# define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-# define YYSIZE_T size_t
-# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# else
-# define YYSIZE_T unsigned
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM \
- YY_CAST (YYPTRDIFF_T, \
- (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
- ? YYPTRDIFF_MAXIMUM \
- : YY_CAST (YYSIZE_T, -1)))
-
-#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
-
-
-/* Stored state numbers (used for stacks). */
-typedef yytype_uint8 yy_state_t;
-
-/* State numbers in computations. */
-typedef int yy_state_fast_t;
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-# if ENABLE_NLS
-# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
-# endif
-# endif
-# ifndef YY_
-# define YY_(Msgid) Msgid
-# endif
-#endif
-
-
-#ifndef YY_ATTRIBUTE_PURE
-# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
-# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
-# else
-# define YY_ATTRIBUTE_PURE
-# endif
-#endif
-
-#ifndef YY_ATTRIBUTE_UNUSED
-# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
-# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
-# else
-# define YY_ATTRIBUTE_UNUSED
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E. */
-#if ! defined lint || defined __GNUC__
-# define YY_USE(E) ((void) (E))
-#else
-# define YY_USE(E) /* empty */
-#endif
-
-/* Suppress an incorrect diagnostic about yylval being uninitialized. */
-#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
-# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
-# else
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
- _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# endif
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
- _Pragma ("GCC diagnostic pop")
-#else
-# define YY_INITIAL_VALUE(Value) Value
-#endif
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
-#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
-# define YY_IGNORE_USELESS_CAST_BEGIN \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
-# define YY_IGNORE_USELESS_CAST_END \
- _Pragma ("GCC diagnostic pop")
-#endif
-#ifndef YY_IGNORE_USELESS_CAST_BEGIN
-# define YY_IGNORE_USELESS_CAST_BEGIN
-# define YY_IGNORE_USELESS_CAST_END
-#endif
-
-
-#define YY_ASSERT(E) ((void) (0 && (E)))
-
-#if 1
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# elif defined __BUILTIN_VA_ARG_INCR
-# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-# elif defined _AIX
-# define YYSTACK_ALLOC __alloca
-# elif defined _MSC_VER
-# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-# define alloca _alloca
-# else
-# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
- /* Use EXIT_SUCCESS as a witness for stdlib.h. */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
-# endif
-# endif
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's 'empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# ifndef YYSTACK_ALLOC_MAXIMUM
- /* The OS might guarantee only one guard page at the bottom of the stack,
- and a page size can be as small as 4096 bytes. So we cannot safely
- invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
- to allow for a few compiler-allocated temporary stack slots. */
-# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-# endif
-# else
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# ifndef YYSTACK_ALLOC_MAXIMUM
-# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-# endif
-# if (defined __cplusplus && ! defined EXIT_SUCCESS \
- && ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
-# endif
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# if ! defined malloc && ! defined EXIT_SUCCESS
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# ifndef YYFREE
-# define YYFREE free
-# if ! defined free && ! defined EXIT_SUCCESS
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# endif
-#endif /* 1 */
-
-#if (! defined yyoverflow \
- && (! defined __cplusplus \
- || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- yy_state_t yyss_alloc;
- YYSTYPE yyvs_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
- + YYSTACK_GAP_MAXIMUM)
-
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
- do \
- { \
- YYPTRDIFF_T yynewbytes; \
- YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
- Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / YYSIZEOF (*yyptr); \
- } \
- while (0)
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
-# else
-# define YYCOPY(Dst, Src, Count) \
- do \
- { \
- YYPTRDIFF_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (Dst)[yyi] = (Src)[yyi]; \
- } \
- while (0)
-# endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 56
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 478
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 40
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 24
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 73
-/* YYNSTATES -- Number of states. */
-#define YYNSTATES 129
-
-/* YYMAXUTOK -- Last valid token kind. */
-#define YYMAXUTOK 283
-
-
-/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
- as returned by yylex, with out-of-bounds checking. */
-#define YYTRANSLATE(YYX) \
- (0 <= (YYX) && (YYX) <= YYMAXUTOK \
- ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \
- : YYSYMBOL_YYUNDEF)
-
-/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
- as returned by yylex. */
-static const yytype_int8 yytranslate[] =
-{
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 28, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 30, 2, 37, 2,
- 33, 25, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 36,
- 2, 38, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 29, 2, 39, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 34, 2, 35, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 26, 27, 31, 32
-};
-
-#if YYDEBUG
-/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
-static const yytype_uint8 yyrline[] =
-{
- 0, 38, 38, 39, 42, 43, 46, 47, 50, 53,
- 56, 57, 60, 61, 64, 65, 68, 69, 72, 73,
- 74, 77, 80, 81, 84, 85, 88, 89, 90, 91,
- 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
- 102, 105, 106, 107, 110, 111, 114, 115, 118, 119,
- 122, 123, 124, 125, 126, 127, 128, 132, 132, 132,
- 132, 132, 132, 132, 132, 132, 132, 135, 136, 139,
- 140, 141, 143, 145
-};
-#endif
-
-/** Accessing symbol of state STATE. */
-#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])
-
-#if 1
-/* The user-facing name of the symbol whose (internal) number is
- YYSYMBOL. No bounds checking. */
-static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
-
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "\"end of file\"", "error", "\"invalid token\"", "Tfor", "Tin",
- "Twhile", "Tif", "Telse", "Tswitch", "Tcase", "Tcasebody", "Ttwiddle",
- "Tbang", "Tsubshell", "Tfunc", "Tredir", "Tdup", "Tpipe", "Tindex",
- "Tbasic", "Targs", "Tword", "Twords", "Tparen", "Tblock", "')'",
- "Tandand", "Toror", "'\\n'", "'^'", "'$'", "Tcount", "Tjoin", "'('",
- "'{'", "'}'", "';'", "'&'", "'='", "'`'", "$accept", "rc", "line",
- "body", "paren", "block", "cmds", "cmdsln", "ifbody", "case", "casebody",
- "assign", "redir", "epilog", "cmd", "basic", "atom", "word",
- "executable", "nonkeyword", "keyword", "words", "wordsnl", "nl", YY_NULLPTR
-};
-
-static const char *
-yysymbol_name (yysymbol_kind_t yysymbol)
-{
- return yytname[yysymbol];
-}
-#endif
-
-#define YYPACT_NINF (-82)
-
-#define yypact_value_is_default(Yyn) \
- ((Yyn) == YYPACT_NINF)
-
-#define YYTABLE_NINF (-3)
-
-#define yytable_value_is_error(Yyn) \
- 0
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-static const yytype_int16 yypact[] =
-{
- 121, -17, -2, -2, 5, 439, 439, 343, -82, -82,
- 343, 343, 343, -82, 439, -23, 45, 32, 11, 439,
- 439, 439, 13, 158, -14, -82, 343, 439, -82, -82,
- 343, 30, 30, -82, -82, -82, -82, -82, -82, -82,
- -82, -82, -82, -82, 34, -82, -82, 47, -82, -82,
- 195, 41, -82, 439, 54, -82, -82, -82, 11, -82,
- -82, 30, 30, -82, -82, -82, -82, -82, -82, 34,
- 343, 343, 19, 44, 375, 375, 4, 343, -82, -82,
- -82, 34, -82, -82, -82, -82, 375, 375, 375, -82,
- 34, -82, -82, -82, -82, 29, 77, -82, 29, -82,
- -82, 269, -82, 30, 30, 306, 375, -82, 25, -82,
- 34, -82, 29, 375, 407, 375, 29, -82, 407, 407,
- 48, 54, 29, 232, -82, -82, -82, -82, -82
-};
-
-/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE does not specify something else to do. Zero
- means the default is an error. */
-static const yytype_int8 yydefact[] =
-{
- 26, 0, 0, 0, 0, 26, 26, 0, 22, 50,
- 0, 0, 0, 69, 26, 0, 0, 0, 24, 26,
- 26, 26, 4, 27, 41, 48, 0, 26, 72, 72,
- 0, 34, 35, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 46, 23, 44, 45, 51, 54, 55,
- 0, 0, 12, 26, 6, 56, 1, 3, 24, 28,
- 5, 33, 32, 72, 72, 72, 10, 11, 43, 42,
- 0, 0, 0, 0, 26, 26, 0, 0, 67, 53,
- 70, 71, 9, 7, 13, 25, 26, 26, 26, 49,
- 21, 67, 72, 8, 73, 38, 24, 39, 14, 72,
- 47, 0, 29, 30, 31, 0, 26, 72, 0, 52,
- 68, 72, 36, 26, 26, 26, 15, 67, 26, 26,
- 0, 18, 37, 0, 20, 19, 40, 17, 16
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int8 yypgoto[] =
-{
- -82, -82, 75, -19, 93, -11, 18, -52, -82, -82,
- -21, -82, -1, 42, 0, -82, -9, 28, -82, 2,
- -82, -81, -82, -22
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int8 yydefgoto[] =
-{
- 0, 16, 17, 51, 28, 18, 52, 53, 97, 119,
- 120, 20, 21, 59, 54, 23, 43, 110, 24, 25,
- 46, 101, 50, 74
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule whose
- number is the opposite. If YYTABLE_NINF, syntax error. */
-static const yytype_int16 yytable[] =
-{
- 22, 47, 48, 49, 55, 31, 32, 75, 73, 45,
- 105, 14, 45, 45, 45, 70, 26, 58, 19, 22,
- 61, 62, 68, 91, 71, 45, 7, 8, 45, 99,
- 63, 27, 45, 77, 83, 44, 123, 19, 30, 64,
- 65, 86, 87, 88, 92, 56, 63, 63, 77, 66,
- 67, 69, 45, 94, 72, 64, 65, 58, 76, 114,
- 57, 89, 118, 77, 96, 78, 118, 118, 100, 93,
- 106, 63, 45, 45, 95, 98, 82, 108, 81, 45,
- 64, 65, 84, 126, 107, 113, 102, 103, 104, 115,
- 66, 67, 7, 8, 60, 58, 29, 124, 125, 90,
- 85, 0, 0, 45, 0, 0, 112, 45, 0, 0,
- 0, 0, 0, 116, 121, 122, 0, 0, 121, 121,
- 0, -2, 0, 0, 1, 45, 2, 3, 0, 4,
- 0, 0, 0, 5, 6, 0, 7, 8, 0, 0,
- 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
- 0, 10, 11, 12, 13, 14, 0, 0, 0, 0,
- 15, 33, 34, 35, 36, 37, 38, 39, 0, 0,
- 40, 41, 42, 7, 8, 0, 0, 0, 0, 9,
- 0, 0, 0, 0, 0, 0, 0, 0, 10, 11,
- 12, 13, 0, 0, 0, 0, 0, 15, 33, 34,
- 35, 36, 37, 38, 39, 0, 0, 40, 41, 42,
- 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
- 79, 0, 0, 80, 0, 10, 11, 12, 13, 0,
- 0, 0, 0, 0, 15, 33, 34, 35, 36, 37,
- 38, 39, 0, 0, 40, 41, 42, 0, 0, 0,
- 0, 0, 0, 9, 0, 0, 0, 0, 0, 0,
- 127, 0, 10, 11, 12, 13, 0, 0, 128, 0,
- 0, 15, 33, 34, 35, 36, 37, 38, 39, 0,
- 0, 40, 41, 42, 0, 0, 0, 0, 0, 0,
- 9, 0, 0, 0, 109, 0, 0, 0, 0, 10,
- 11, 12, 13, 0, 0, 0, 0, 0, 15, 33,
- 34, 35, 36, 37, 38, 39, 0, 0, 40, 41,
- 42, 0, 0, 0, 0, 0, 0, 9, 0, 0,
- 0, 111, 0, 0, 0, 0, 10, 11, 12, 13,
- 0, 0, 0, 0, 0, 15, 33, 34, 35, 36,
- 37, 38, 39, 0, 0, 40, 41, 42, 0, 0,
- 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
- 0, 0, 0, 10, 11, 12, 13, 0, 1, 0,
- 2, 3, 15, 4, 0, 0, 0, 5, 6, 0,
- 7, 8, 0, 0, 0, 0, 9, 0, 0, 0,
- 0, 0, 0, 94, 0, 10, 11, 12, 13, 14,
- 1, 0, 2, 3, 15, 4, 117, 0, 0, 5,
- 6, 0, 7, 8, 0, 0, 0, 0, 9, 0,
- 0, 0, 0, 0, 0, 0, 0, 10, 11, 12,
- 13, 14, 1, 0, 2, 3, 15, 4, 0, 0,
- 0, 5, 6, 0, 7, 8, 0, 0, 0, 0,
- 9, 0, 0, 0, 0, 0, 0, 0, 0, 10,
- 11, 12, 13, 14, 0, 0, 0, 0, 15
-};
-
-static const yytype_int8 yycheck[] =
-{
- 0, 10, 11, 12, 15, 5, 6, 29, 27, 7,
- 91, 34, 10, 11, 12, 29, 33, 18, 0, 19,
- 20, 21, 23, 4, 38, 23, 15, 16, 26, 25,
- 17, 33, 30, 29, 53, 7, 117, 19, 33, 26,
- 27, 63, 64, 65, 25, 0, 17, 17, 29, 36,
- 37, 23, 50, 28, 26, 26, 27, 58, 30, 34,
- 28, 70, 114, 29, 75, 18, 118, 119, 77, 25,
- 92, 17, 70, 71, 74, 75, 35, 99, 50, 77,
- 26, 27, 28, 35, 7, 107, 86, 87, 88, 111,
- 36, 37, 15, 16, 19, 96, 3, 118, 119, 71,
- 58, -1, -1, 101, -1, -1, 106, 105, -1, -1,
- -1, -1, -1, 113, 114, 115, -1, -1, 118, 119,
- -1, 0, -1, -1, 3, 123, 5, 6, -1, 8,
- -1, -1, -1, 12, 13, -1, 15, 16, -1, -1,
- -1, -1, 21, -1, -1, -1, -1, -1, -1, -1,
- -1, 30, 31, 32, 33, 34, -1, -1, -1, -1,
- 39, 3, 4, 5, 6, 7, 8, 9, -1, -1,
- 12, 13, 14, 15, 16, -1, -1, -1, -1, 21,
- -1, -1, -1, -1, -1, -1, -1, -1, 30, 31,
- 32, 33, -1, -1, -1, -1, -1, 39, 3, 4,
- 5, 6, 7, 8, 9, -1, -1, 12, 13, 14,
- -1, -1, -1, -1, -1, -1, 21, -1, -1, -1,
- 25, -1, -1, 28, -1, 30, 31, 32, 33, -1,
- -1, -1, -1, -1, 39, 3, 4, 5, 6, 7,
- 8, 9, -1, -1, 12, 13, 14, -1, -1, -1,
- -1, -1, -1, 21, -1, -1, -1, -1, -1, -1,
- 28, -1, 30, 31, 32, 33, -1, -1, 36, -1,
- -1, 39, 3, 4, 5, 6, 7, 8, 9, -1,
- -1, 12, 13, 14, -1, -1, -1, -1, -1, -1,
- 21, -1, -1, -1, 25, -1, -1, -1, -1, 30,
- 31, 32, 33, -1, -1, -1, -1, -1, 39, 3,
- 4, 5, 6, 7, 8, 9, -1, -1, 12, 13,
- 14, -1, -1, -1, -1, -1, -1, 21, -1, -1,
- -1, 25, -1, -1, -1, -1, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, 39, 3, 4, 5, 6,
- 7, 8, 9, -1, -1, 12, 13, 14, -1, -1,
- -1, -1, -1, -1, 21, -1, -1, -1, -1, -1,
- -1, -1, -1, 30, 31, 32, 33, -1, 3, -1,
- 5, 6, 39, 8, -1, -1, -1, 12, 13, -1,
- 15, 16, -1, -1, -1, -1, 21, -1, -1, -1,
- -1, -1, -1, 28, -1, 30, 31, 32, 33, 34,
- 3, -1, 5, 6, 39, 8, 9, -1, -1, 12,
- 13, -1, 15, 16, -1, -1, -1, -1, 21, -1,
- -1, -1, -1, -1, -1, -1, -1, 30, 31, 32,
- 33, 34, 3, -1, 5, 6, 39, 8, -1, -1,
- -1, 12, 13, -1, 15, 16, -1, -1, -1, -1,
- 21, -1, -1, -1, -1, -1, -1, -1, -1, 30,
- 31, 32, 33, 34, -1, -1, -1, -1, 39
-};
-
-/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
- state STATE-NUM. */
-static const yytype_int8 yystos[] =
-{
- 0, 3, 5, 6, 8, 12, 13, 15, 16, 21,
- 30, 31, 32, 33, 34, 39, 41, 42, 45, 46,
- 51, 52, 54, 55, 58, 59, 33, 33, 44, 44,
- 33, 54, 54, 3, 4, 5, 6, 7, 8, 9,
- 12, 13, 14, 56, 57, 59, 60, 56, 56, 56,
- 62, 43, 46, 47, 54, 45, 0, 28, 52, 53,
- 42, 54, 54, 17, 26, 27, 36, 37, 52, 57,
- 29, 38, 57, 43, 63, 63, 57, 29, 18, 25,
- 28, 57, 35, 43, 28, 53, 63, 63, 63, 56,
- 57, 4, 25, 25, 28, 54, 45, 48, 54, 25,
- 56, 61, 54, 54, 54, 61, 63, 7, 63, 25,
- 57, 25, 54, 63, 34, 63, 54, 9, 47, 49,
- 50, 54, 54, 61, 50, 50, 35, 28, 36
-};
-
-/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
-static const yytype_int8 yyr1[] =
-{
- 0, 40, 41, 41, 42, 42, 43, 43, 44, 45,
- 46, 46, 47, 47, 48, 48, 49, 49, 50, 50,
- 50, 51, 52, 52, 53, 53, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 55, 55, 55, 56, 56, 57, 57, 58, 58,
- 59, 59, 59, 59, 59, 59, 59, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 61, 61, 62,
- 62, 62, 63, 63
-};
-
-/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
-static const yytype_int8 yyr2[] =
-{
- 0, 2, 0, 2, 1, 2, 1, 2, 3, 3,
- 2, 2, 1, 2, 1, 4, 3, 3, 1, 2,
- 2, 3, 1, 2, 0, 2, 0, 1, 2, 4,
- 4, 4, 2, 2, 2, 2, 6, 8, 4, 4,
- 8, 1, 2, 2, 1, 1, 1, 3, 1, 3,
- 1, 2, 5, 3, 2, 2, 2, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 2, 0,
- 2, 2, 0, 2
-};
-
-
-enum { YYENOMEM = -2 };
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-#define YYNOMEM goto yyexhaustedlab
-
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
- do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
- while (0)
-
-/* Backward compatibility with an undocumented macro.
- Use YYerror or YYUNDEF. */
-#define YYERRCODE YYUNDEF
-
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (0)
-
-
-
-
-# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Kind, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (0)
-
-
-/*-----------------------------------.
-| Print this symbol's value on YYO. |
-`-----------------------------------*/
-
-static void
-yy_symbol_value_print (FILE *yyo,
- yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep)
-{
- FILE *yyoutput = yyo;
- YY_USE (yyoutput);
- if (!yyvaluep)
- return;
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YY_USE (yykind);
- YY_IGNORE_MAYBE_UNINITIALIZED_END
-}
-
-
-/*---------------------------.
-| Print this symbol on YYO. |
-`---------------------------*/
-
-static void
-yy_symbol_print (FILE *yyo,
- yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep)
-{
- YYFPRINTF (yyo, "%s %s (",
- yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));
-
- yy_symbol_value_print (yyo, yykind, yyvaluep);
- YYFPRINTF (yyo, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-static void
-yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
-{
- YYFPRINTF (stderr, "Stack now");
- for (; yybottom <= yytop; yybottom++)
- {
- int yybot = *yybottom;
- YYFPRINTF (stderr, " %d", yybot);
- }
- YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-static void
-yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,
- int yyrule)
-{
- int yylno = yyrline[yyrule];
- int yynrhs = yyr2[yyrule];
- int yyi;
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
- yyrule - 1, yylno);
- /* The symbols being reduced. */
- for (yyi = 0; yyi < yynrhs; yyi++)
- {
- YYFPRINTF (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr,
- YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
- &yyvsp[(yyi + 1) - (yynrhs)]);
- YYFPRINTF (stderr, "\n");
- }
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyssp, yyvsp, Rule); \
-} while (0)
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args) ((void) 0)
-# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-/* Context of a parse error. */
-typedef struct
-{
- yy_state_t *yyssp;
- yysymbol_kind_t yytoken;
-} yypcontext_t;
-
-/* Put in YYARG at most YYARGN of the expected tokens given the
- current YYCTX, and return the number of tokens stored in YYARG. If
- YYARG is null, return the number of expected tokens (guaranteed to
- be less than YYNTOKENS). Return YYENOMEM on memory exhaustion.
- Return 0 if there are more than YYARGN expected tokens, yet fill
- YYARG up to YYARGN. */
-static int
-yypcontext_expected_tokens (const yypcontext_t *yyctx,
- yysymbol_kind_t yyarg[], int yyargn)
-{
- /* Actual size of YYARG. */
- int yycount = 0;
- int yyn = yypact[+*yyctx->yyssp];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (!yyarg)
- ++yycount;
- else if (yycount == yyargn)
- return 0;
- else
- yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx);
- }
- }
- if (yyarg && yycount == 0 && 0 < yyargn)
- yyarg[0] = YYSYMBOL_YYEMPTY;
- return yycount;
-}
-
-
-
-
-#ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
-# else
-/* Return the length of YYSTR. */
-static YYPTRDIFF_T
-yystrlen (const char *yystr)
-{
- YYPTRDIFF_T yylen;
- for (yylen = 0; yystr[yylen]; yylen++)
- continue;
- return yylen;
-}
-# endif
-#endif
-
-#ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-{
- char *yyd = yydest;
- const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-#endif
-
-#ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
- quotes and backslashes, so that it's suitable for yyerror. The
- heuristic is that double-quoting is unnecessary unless the string
- contains an apostrophe, a comma, or backslash (other than
- backslash-backslash). YYSTR is taken from yytname. If YYRES is
- null, do not copy; instead, return the length of what the result
- would have been. */
-static YYPTRDIFF_T
-yytnamerr (char *yyres, const char *yystr)
-{
- if (*yystr == '"')
- {
- YYPTRDIFF_T yyn = 0;
- char const *yyp = yystr;
- for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- else
- goto append;
-
- append:
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
- do_not_strip_quotes: ;
- }
-
- if (yyres)
- return yystpcpy (yyres, yystr) - yyres;
- else
- return yystrlen (yystr);
-}
-#endif
-
-
-static int
-yy_syntax_error_arguments (const yypcontext_t *yyctx,
- yysymbol_kind_t yyarg[], int yyargn)
-{
- /* Actual size of YYARG. */
- int yycount = 0;
- /* There are many possibilities here to consider:
- - If this state is a consistent state with a default action, then
- the only way this function was invoked is if the default action
- is an error action. In that case, don't check for expected
- tokens because there are none.
- - The only way there can be no lookahead present (in yychar) is if
- this state is a consistent state with a default action. Thus,
- detecting the absence of a lookahead is sufficient to determine
- that there is no unexpected or expected token to report. In that
- case, just report a simple "syntax error".
- - Don't assume there isn't a lookahead just because this state is a
- consistent state with a default action. There might have been a
- previous inconsistent state, consistent state with a non-default
- action, or user semantic action that manipulated yychar.
- - Of course, the expected token list depends on states to have
- correct lookahead information, and it depends on the parser not
- to perform extra reductions after fetching a lookahead from the
- scanner and before detecting a syntax error. Thus, state merging
- (from LALR or IELR) and default reductions corrupt the expected
- token list. However, the list is correct for canonical LR with
- one exception: it will still contain any token that will not be
- accepted due to an error action in a later state.
- */
- if (yyctx->yytoken != YYSYMBOL_YYEMPTY)
- {
- int yyn;
- if (yyarg)
- yyarg[yycount] = yyctx->yytoken;
- ++yycount;
- yyn = yypcontext_expected_tokens (yyctx,
- yyarg ? yyarg + 1 : yyarg, yyargn - 1);
- if (yyn == YYENOMEM)
- return YYENOMEM;
- else
- yycount += yyn;
- }
- return yycount;
-}
-
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
-
- Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the
- required number of bytes is too large to store. */
-static int
-yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
- const yypcontext_t *yyctx)
-{
- enum { YYARGS_MAX = 5 };
- /* Internationalized format string. */
- const char *yyformat = YY_NULLPTR;
- /* Arguments of yyformat: reported tokens (one for the "unexpected",
- one per "expected"). */
- yysymbol_kind_t yyarg[YYARGS_MAX];
- /* Cumulated lengths of YYARG. */
- YYPTRDIFF_T yysize = 0;
-
- /* Actual size of YYARG. */
- int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX);
- if (yycount == YYENOMEM)
- return YYENOMEM;
-
- switch (yycount)
- {
-#define YYCASE_(N, S) \
- case N: \
- yyformat = S; \
- break
- default: /* Avoid compiler warnings. */
- YYCASE_(0, YY_("syntax error"));
- YYCASE_(1, YY_("syntax error, unexpected %s"));
- YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
- YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
- YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
- YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-#undef YYCASE_
- }
-
- /* Compute error message size. Don't count the "%s"s, but reserve
- room for the terminator. */
- yysize = yystrlen (yyformat) - 2 * yycount + 1;
- {
- int yyi;
- for (yyi = 0; yyi < yycount; ++yyi)
- {
- YYPTRDIFF_T yysize1
- = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return YYENOMEM;
- }
- }
-
- if (*yymsg_alloc < yysize)
- {
- *yymsg_alloc = 2 * yysize;
- if (! (yysize <= *yymsg_alloc
- && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
- *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return -1;
- }
-
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- {
- char *yyp = *yymsg;
- int yyi = 0;
- while ((*yyp = *yyformat) != '\0')
- if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]);
- yyformat += 2;
- }
- else
- {
- ++yyp;
- ++yyformat;
- }
- }
- return 0;
-}
-
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-static void
-yydestruct (const char *yymsg,
- yysymbol_kind_t yykind, YYSTYPE *yyvaluep)
-{
- YY_USE (yyvaluep);
- if (!yymsg)
- yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
-
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YY_USE (yykind);
- YY_IGNORE_MAYBE_UNINITIALIZED_END
-}
-
-
-/* Lookahead token kind. */
-int yychar;
-
-/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval;
-/* Number of syntax errors so far. */
-int yynerrs;
-
-
-
-
-/*----------.
-| yyparse. |
-`----------*/
-
-int
-yyparse (void)
-{
- yy_state_fast_t yystate = 0;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus = 0;
-
- /* Refer to the stacks through separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* Their size. */
- YYPTRDIFF_T yystacksize = YYINITDEPTH;
-
- /* The state stack: array, bottom, top. */
- yy_state_t yyssa[YYINITDEPTH];
- yy_state_t *yyss = yyssa;
- yy_state_t *yyssp = yyss;
-
- /* The semantic value stack: array, bottom, top. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp = yyvs;
-
- int yyn;
- /* The return value of yyparse. */
- int yyresult;
- /* Lookahead symbol kind. */
- yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
-
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
-
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
-
- /* The number of symbols on the RHS of the reduced rule.
- Keep to zero when no symbol should be popped. */
- int yylen = 0;
-
- YYDPRINTF ((stderr, "Starting parse\n"));
-
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- goto yysetstate;
-
-
-/*------------------------------------------------------------.
-| yynewstate -- push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
-yynewstate:
- /* In all cases, when you get here, the value and location stacks
- have just been pushed. So pushing a state here evens the stacks. */
- yyssp++;
-
-
-/*--------------------------------------------------------------------.
-| yysetstate -- set current state (the top of the stack) to yystate. |
-`--------------------------------------------------------------------*/
-yysetstate:
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
- YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
- YY_IGNORE_USELESS_CAST_BEGIN
- *yyssp = YY_CAST (yy_state_t, yystate);
- YY_IGNORE_USELESS_CAST_END
- YY_STACK_PRINT (yyss, yyssp);
-
- if (yyss + yystacksize - 1 <= yyssp)
-#if !defined yyoverflow && !defined YYSTACK_RELOCATE
- YYNOMEM;
-#else
- {
- /* Get the current used size of the three stacks, in elements. */
- YYPTRDIFF_T yysize = yyssp - yyss + 1;
-
-# if defined yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- yy_state_t *yyss1 = yyss;
- YYSTYPE *yyvs1 = yyvs;
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * YYSIZEOF (*yyssp),
- &yyvs1, yysize * YYSIZEOF (*yyvsp),
- &yystacksize);
- yyss = yyss1;
- yyvs = yyvs1;
- }
-# else /* defined YYSTACK_RELOCATE */
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- YYNOMEM;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- yy_state_t *yyss1 = yyss;
- union yyalloc *yyptr =
- YY_CAST (union yyalloc *,
- YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
- if (! yyptr)
- YYNOMEM;
- YYSTACK_RELOCATE (yyss_alloc, yyss);
- YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
- }
-# endif
-
- yyssp = yyss + yysize - 1;
- yyvsp = yyvs + yysize - 1;
-
- YY_IGNORE_USELESS_CAST_BEGIN
- YYDPRINTF ((stderr, "Stack size increased to %ld\n",
- YY_CAST (long, yystacksize)));
- YY_IGNORE_USELESS_CAST_END
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
-
-
- if (yystate == YYFINAL)
- YYACCEPT;
-
- goto yybackup;
-
-
-/*-----------.
-| yybackup. |
-`-----------*/
-yybackup:
- /* Do appropriate processing given the current state. Read a
- lookahead token if we need one and don't already have one. */
-
- /* First try to decide what to do without reference to lookahead token. */
- yyn = yypact[yystate];
- if (yypact_value_is_default (yyn))
- goto yydefault;
-
- /* Not known => get a lookahead token if don't already have one. */
-
- /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token\n"));
- yychar = yylex ();
- }
-
- if (yychar <= YYEOF)
- {
- yychar = YYEOF;
- yytoken = YYSYMBOL_YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else if (yychar == YYerror)
- {
- /* The scanner already issued an error message, process directly
- to error recovery. But do not keep the error token as
- lookahead, it is too special and may lead us to an endless
- loop in error recovery. */
- yychar = YYUNDEF;
- yytoken = YYSYMBOL_YYerror;
- goto yyerrlab1;
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yytable_value_is_error (yyn))
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- /* Shift the lookahead token. */
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
- yystate = yyn;
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- *++yyvsp = yylval;
- YY_IGNORE_MAYBE_UNINITIALIZED_END
-
- /* Discard the shifted token. */
- yychar = YYEMPTY;
- goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
-
- /* If YYLEN is nonzero, implement the default value of the action:
- '$$ = $1'.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
-
-
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2: /* rc: %empty */
-#line 38 "sys/cmd/rc/syntax.y"
- { return 0; }
-#line 1549 "sys/cmd/rc/parse.c"
- break;
-
- case 3: /* rc: line '\n' */
-#line 39 "sys/cmd/rc/syntax.y"
- { return compile((yyvsp[-1].tree)); }
-#line 1555 "sys/cmd/rc/parse.c"
- break;
-
- case 5: /* line: cmds line */
-#line 43 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1561 "sys/cmd/rc/parse.c"
- break;
-
- case 7: /* body: cmdsln body */
-#line 47 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1567 "sys/cmd/rc/parse.c"
- break;
-
- case 8: /* paren: '(' body ')' */
-#line 50 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tparen, (yyvsp[-1].tree)); }
-#line 1573 "sys/cmd/rc/parse.c"
- break;
-
- case 9: /* block: '{' body '}' */
-#line 53 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tblock, (yyvsp[-1].tree)); }
-#line 1579 "sys/cmd/rc/parse.c"
- break;
-
- case 11: /* cmds: cmd '&' */
-#line 57 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1('&', (yyvsp[-1].tree)); }
-#line 1585 "sys/cmd/rc/parse.c"
- break;
-
- case 14: /* ifbody: cmd */
-#line 64 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Tif, nil, (yyvsp[0].tree)); }
-#line 1591 "sys/cmd/rc/parse.c"
- break;
-
- case 15: /* ifbody: block Telse nl cmd */
-#line 65 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree3(Tif, nil, (yyvsp[-3].tree), (yyvsp[-2].tree)); }
-#line 1597 "sys/cmd/rc/parse.c"
- break;
-
- case 16: /* case: Tcase words ';' */
-#line 68 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-2].tree), (yyvsp[-1].tree), 0); }
-#line 1603 "sys/cmd/rc/parse.c"
- break;
-
- case 17: /* case: Tcase words '\n' */
-#line 69 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-2].tree), (yyvsp[-1].tree), 0); }
-#line 1609 "sys/cmd/rc/parse.c"
- break;
-
- case 18: /* casebody: cmd */
-#line 72 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Tcasebody, (yyvsp[0].tree), nil); }
-#line 1615 "sys/cmd/rc/parse.c"
- break;
-
- case 19: /* casebody: case casebody */
-#line 73 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Tcasebody, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1621 "sys/cmd/rc/parse.c"
- break;
-
- case 20: /* casebody: cmdsln casebody */
-#line 74 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Tcasebody, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1627 "sys/cmd/rc/parse.c"
- break;
-
- case 21: /* assign: executable '=' word */
-#line 77 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2('=', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1633 "sys/cmd/rc/parse.c"
- break;
-
- case 23: /* redir: Tredir word */
-#line 81 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 0); }
-#line 1639 "sys/cmd/rc/parse.c"
- break;
-
- case 24: /* epilog: %empty */
-#line 84 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = nil; }
-#line 1645 "sys/cmd/rc/parse.c"
- break;
-
- case 25: /* epilog: redir epilog */
-#line 85 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 1); }
-#line 1651 "sys/cmd/rc/parse.c"
- break;
-
- case 26: /* cmd: %empty */
-#line 88 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = nil; }
-#line 1657 "sys/cmd/rc/parse.c"
- break;
-
- case 27: /* cmd: basic */
-#line 89 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tbasic, (yyvsp[0].tree)); }
-#line 1663 "sys/cmd/rc/parse.c"
- break;
-
- case 28: /* cmd: block epilog */
-#line 90 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangepilog((yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1669 "sys/cmd/rc/parse.c"
- break;
-
- case 29: /* cmd: cmd Tpipe nl cmd */
-#line 91 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild2((yyvsp[-2].tree), (yyvsp[-3].tree), 0, (yyvsp[0].tree), 1); }
-#line 1675 "sys/cmd/rc/parse.c"
- break;
-
- case 30: /* cmd: cmd Tandand nl cmd */
-#line 92 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Tandand, (yyvsp[-3].tree), (yyvsp[0].tree)); }
-#line 1681 "sys/cmd/rc/parse.c"
- break;
-
- case 31: /* cmd: cmd Toror nl cmd */
-#line 93 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Toror, (yyvsp[-3].tree), (yyvsp[0].tree)); }
-#line 1687 "sys/cmd/rc/parse.c"
- break;
-
- case 32: /* cmd: redir cmd */
-#line 94 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 1); }
-#line 1693 "sys/cmd/rc/parse.c"
- break;
-
- case 33: /* cmd: assign cmd */
-#line 95 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 2); }
-#line 1699 "sys/cmd/rc/parse.c"
- break;
-
- case 34: /* cmd: Tbang cmd */
-#line 96 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tbang, (yyvsp[0].tree)); }
-#line 1705 "sys/cmd/rc/parse.c"
- break;
-
- case 35: /* cmd: Tsubshell cmd */
-#line 97 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tsubshell, (yyvsp[0].tree)); }
-#line 1711 "sys/cmd/rc/parse.c"
- break;
-
- case 36: /* cmd: Tfor '(' word ')' nl cmd */
-#line 98 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild3((yyvsp[-5].tree), (yyvsp[-3].tree), nil, (yyvsp[0].tree)); }
-#line 1717 "sys/cmd/rc/parse.c"
- break;
-
- case 37: /* cmd: Tfor '(' word Tin words ')' nl cmd */
-#line 99 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild3((yyvsp[-7].tree), (yyvsp[-5].tree), (yyvsp[-3].tree), (yyvsp[0].tree)); }
-#line 1723 "sys/cmd/rc/parse.c"
- break;
-
- case 38: /* cmd: Twhile paren nl cmd */
-#line 100 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild2((yyvsp[-3].tree), (yyvsp[-2].tree), 0, (yyvsp[0].tree), 1); }
-#line 1729 "sys/cmd/rc/parse.c"
- break;
-
- case 39: /* cmd: Tif paren nl ifbody */
-#line 101 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild1((yyvsp[-2].tree), (yyvsp[-3].tree), 0); }
-#line 1735 "sys/cmd/rc/parse.c"
- break;
-
- case 40: /* cmd: Tswitch '(' word ')' nl '{' casebody '}' */
-#line 102 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = hangchild2((yyvsp[-7].tree), (yyvsp[-5].tree), 0, (yyvsp[-1].tree), 1); }
-#line 1741 "sys/cmd/rc/parse.c"
- break;
-
- case 42: /* basic: basic word */
-#line 106 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Targs, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1747 "sys/cmd/rc/parse.c"
- break;
-
- case 43: /* basic: basic redir */
-#line 107 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Targs, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1753 "sys/cmd/rc/parse.c"
- break;
-
- case 45: /* atom: keyword */
-#line 111 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tword, (yyvsp[0].tree)); }
-#line 1759 "sys/cmd/rc/parse.c"
- break;
-
- case 47: /* word: word '^' atom */
-#line 115 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1765 "sys/cmd/rc/parse.c"
- break;
-
- case 49: /* executable: executable '^' atom */
-#line 119 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); }
-#line 1771 "sys/cmd/rc/parse.c"
- break;
-
- case 51: /* nonkeyword: '$' atom */
-#line 123 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1('$', (yyvsp[0].tree)); }
-#line 1777 "sys/cmd/rc/parse.c"
- break;
-
- case 52: /* nonkeyword: '$' atom Tindex words ')' */
-#line 124 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Tindex, (yyvsp[-3].tree), (yyvsp[-1].tree)); }
-#line 1783 "sys/cmd/rc/parse.c"
- break;
-
- case 53: /* nonkeyword: '(' wordsnl ')' */
-#line 125 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = (yyvsp[-1].tree); }
-#line 1789 "sys/cmd/rc/parse.c"
- break;
-
- case 54: /* nonkeyword: Tcount atom */
-#line 126 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tcount, (yyvsp[0].tree)); }
-#line 1795 "sys/cmd/rc/parse.c"
- break;
-
- case 55: /* nonkeyword: Tjoin atom */
-#line 127 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tjoin, (yyvsp[0].tree)); }
-#line 1801 "sys/cmd/rc/parse.c"
- break;
-
- case 56: /* nonkeyword: '`' block */
-#line 128 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1('`', (yyvsp[0].tree)); }
-#line 1807 "sys/cmd/rc/parse.c"
- break;
-
- case 67: /* words: %empty */
-#line 135 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = nil; }
-#line 1813 "sys/cmd/rc/parse.c"
- break;
-
- case 68: /* words: words word */
-#line 136 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = maketree2(Twords, (yyvsp[-1].tree), (yyvsp[0].tree)); }
-#line 1819 "sys/cmd/rc/parse.c"
- break;
-
- case 69: /* wordsnl: %empty */
-#line 139 "sys/cmd/rc/syntax.y"
- { (yyval.tree) = nil; }
-#line 1825 "sys/cmd/rc/parse.c"
- break;
-
- case 71: /* wordsnl: wordsnl word */
-#line 141 "sys/cmd/rc/syntax.y"
- {(yyval.tree) = (!(yyvsp[-1].tree)) ? ((!(yyvsp[0].tree)) ? nil : (yyvsp[0].tree)) : ((!(yyvsp[0].tree)) ? (yyvsp[-1].tree) : maketree2(Twords, (yyvsp[-1].tree), (yyvsp[0].tree))); }
-#line 1831 "sys/cmd/rc/parse.c"
- break;
-
-
-#line 1835 "sys/cmd/rc/parse.c"
-
- default: break;
- }
- /* User semantic actions sometimes alter yychar, and that requires
- that yytoken be updated with the new translation. We take the
- approach of translating immediately before every use of yytoken.
- One alternative is translating here after every semantic action,
- but that translation would be missed if the semantic action invokes
- YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
- if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
- incorrect destructor might then be invoked immediately. In the
- case of YYERROR or YYBACKUP, subsequent parser actions might lead
- to an incorrect destructor call or verbose syntax error message
- before the lookahead is translated. */
- YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);
-
- YYPOPSTACK (yylen);
- yylen = 0;
-
- *++yyvsp = yyval;
-
- /* Now 'shift' the result of the reduction. Determine what state
- that goes to, based on the state we popped back to and the rule
- number reduced by. */
- {
- const int yylhs = yyr1[yyn] - YYNTOKENS;
- const int yyi = yypgoto[yylhs] + *yyssp;
- yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
- ? yytable[yyi]
- : yydefgoto[yylhs]);
- }
-
- goto yynewstate;
-
-
-/*--------------------------------------.
-| yyerrlab -- here on detecting error. |
-`--------------------------------------*/
-yyerrlab:
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
- {
- yypcontext_t yyctx
- = {yyssp, yytoken};
- char const *yymsgp = YY_("syntax error");
- int yysyntax_error_status;
- yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
- if (yysyntax_error_status == 0)
- yymsgp = yymsg;
- else if (yysyntax_error_status == -1)
- {
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = YY_CAST (char *,
- YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc)));
- if (yymsg)
- {
- yysyntax_error_status
- = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
- yymsgp = yymsg;
- }
- else
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = YYENOMEM;
- }
- }
- yyerror (yymsgp);
- if (yysyntax_error_status == YYENOMEM)
- YYNOMEM;
- }
- }
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse lookahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
- else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval);
- yychar = YYEMPTY;
- }
- }
-
- /* Else will try to reuse lookahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
- /* Pacify compilers when the user code never invokes YYERROR and the
- label yyerrorlab therefore never appears in user code. */
- if (0)
- YYERROR;
- ++yynerrs;
-
- /* Do not reclaim the symbols of the rule whose action triggered
- this YYERROR. */
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- /* Pop stack until we find a state that shifts the error token. */
- for (;;)
- {
- yyn = yypact[yystate];
- if (!yypact_value_is_default (yyn))
- {
- yyn += YYSYMBOL_YYerror;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
-
-
- yydestruct ("Error: popping",
- YY_ACCESSING_SYMBOL (yystate), yyvsp);
- YYPOPSTACK (1);
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- *++yyvsp = yylval;
- YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturnlab;
-
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturnlab;
-
-
-/*-----------------------------------------------------------.
-| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
-`-----------------------------------------------------------*/
-yyexhaustedlab:
- yyerror (YY_("memory exhausted"));
- yyresult = 2;
- goto yyreturnlab;
-
-
-/*----------------------------------------------------------.
-| yyreturnlab -- parsing is finished, clean up and return. |
-`----------------------------------------------------------*/
-yyreturnlab:
- if (yychar != YYEMPTY)
- {
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = YYTRANSLATE (yychar);
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval);
- }
- /* Do not reclaim the symbols of the rule whose action triggered
- this YYABORT or YYACCEPT. */
- YYPOPSTACK (yylen);
- YY_STACK_PRINT (yyss, yyssp);
- while (yyssp != yyss)
- {
- yydestruct ("Cleanup: popping",
- YY_ACCESSING_SYMBOL (+*yyssp), yyvsp);
- YYPOPSTACK (1);
- }
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- return yyresult;
-}
-
-#line 147 "sys/cmd/rc/syntax.y"
-
diff --git a/sys/cmd/rc/parse.h b/sys/cmd/rc/parse.h
deleted file mode 100644
index 64ee07b..0000000
--- a/sys/cmd/rc/parse.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* A Bison parser, made by GNU Bison 3.8.2. */
-
-/* Bison interface for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
- Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
- especially those whose name start with YY_ or yy_. They are
- private implementation details that can be changed or removed. */
-
-#ifndef YY_YY_SYS_CMD_RC_PARSE_H_INCLUDED
-# define YY_YY_SYS_CMD_RC_PARSE_H_INCLUDED
-/* Debug traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
-/* Token kinds. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- enum yytokentype
- {
- YYEMPTY = -2,
- YYEOF = 0, /* "end of file" */
- YYerror = 256, /* error */
- YYUNDEF = 257, /* "invalid token" */
- Tfor = 258, /* Tfor */
- Tin = 259, /* Tin */
- Twhile = 260, /* Twhile */
- Tif = 261, /* Tif */
- Telse = 262, /* Telse */
- Tswitch = 263, /* Tswitch */
- Tcase = 264, /* Tcase */
- Tcasebody = 265, /* Tcasebody */
- Ttwiddle = 266, /* Ttwiddle */
- Tbang = 267, /* Tbang */
- Tsubshell = 268, /* Tsubshell */
- Tfunc = 269, /* Tfunc */
- Tredir = 270, /* Tredir */
- Tdup = 271, /* Tdup */
- Tpipe = 272, /* Tpipe */
- Tindex = 273, /* Tindex */
- Tbasic = 274, /* Tbasic */
- Targs = 275, /* Targs */
- Tword = 276, /* Tword */
- Twords = 277, /* Twords */
- Tparen = 278, /* Tparen */
- Tblock = 279, /* Tblock */
- Tandand = 280, /* Tandand */
- Toror = 281, /* Toror */
- Tcount = 282, /* Tcount */
- Tjoin = 283 /* Tjoin */
- };
- typedef enum yytokentype yytoken_kind_t;
-#endif
-/* Token kinds. */
-#define YYEMPTY -2
-#define YYEOF 0
-#define YYerror 256
-#define YYUNDEF 257
-#define Tfor 258
-#define Tin 259
-#define Twhile 260
-#define Tif 261
-#define Telse 262
-#define Tswitch 263
-#define Tcase 264
-#define Tcasebody 265
-#define Ttwiddle 266
-#define Tbang 267
-#define Tsubshell 268
-#define Tfunc 269
-#define Tredir 270
-#define Tdup 271
-#define Tpipe 272
-#define Tindex 273
-#define Tbasic 274
-#define Targs 275
-#define Tword 276
-#define Twords 277
-#define Tparen 278
-#define Tblock 279
-#define Tandand 280
-#define Toror 281
-#define Tcount 282
-#define Tjoin 283
-
-/* Value type. */
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-union YYSTYPE
-{
-#line 24 "sys/cmd/rc/syntax.y"
-
- struct Tree *tree;
-
-#line 127 "sys/cmd/rc/parse.h"
-
-};
-typedef union YYSTYPE YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-
-extern YYSTYPE yylval;
-
-
-int yyparse (void);
-
-
-#endif /* !YY_YY_SYS_CMD_RC_PARSE_H_INCLUDED */
diff --git a/sys/cmd/rc/prompt.c b/sys/cmd/rc/prompt.c
deleted file mode 100644
index 1122d54..0000000
--- a/sys/cmd/rc/prompt.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "rc.h"
-
-/* static char promptbuf[7] = {'>', ' ', 0, ' ' , ' ', ' ', 0}; */
-static char *base= "\x1b[1;31m" ">" "\x1b[0;0m" " ", *promptstr;
-
-void
-resetprompt(void)
-{
- promptstr = base;
-}
-
-int
-prompt(ushort *flag)
-{
- int f = *flag;
-
- if(f){
- if(!readline(promptstr)){
- runner->flag.eof = 1;
- return 0;
- }
- if(runner->cmd.io->e[-1] == '\n'){
- runner->cmd.io->e[-1] = 0;
- addhistory(runner->cmd.io->b);
- runner->cmd.io->e[-1] = '\n';
- }
-
- write(mapfd(0), "\n\r", 2);
- promptstr = " ";
-
- runner->line++;
- *flag = 0;
- }
-
- return 1;
-}
diff --git a/sys/cmd/rc/rc.h b/sys/cmd/rc/rc.h
deleted file mode 100644
index 9b415fc..0000000
--- a/sys/cmd/rc/rc.h
+++ /dev/null
@@ -1,263 +0,0 @@
-
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-
-// -----------------------------------------------------------------------
-// types
-
-typedef struct Io Io;
-typedef struct Var Var;
-typedef struct Word Word;
-typedef struct List List;
-typedef struct Tree Tree;
-typedef struct Redir Redir;
-typedef union Code Code;
-typedef struct Thread Thread;
-typedef struct Shell Shell;
-
-struct Io
-{
- int fd, cap;
- char *s;
- char *b, *e, buf[];
-};
-
-enum
-{
- Rappend,
- Rwrite,
- Rread,
- Rhere,
- Rdupfd,
- Ropen,
- Rclose,
- Rrdwr
-};
-
-struct Tree
-{
- int type;
- union{
- struct {
- ushort quoted;
- char *str; // Tword
- };
- struct {
- ushort type; // Tpipe, Tredir, Tdup
- int fd[2];
- } redir;
- };
- Tree *child[3];
- Tree *link;
-};
-
-struct Word
-{
- char *str;
- Word *link;
-};
-
-struct List
-{
- Word *word;
- List *link;
-};
-
-/*
- * the first word of any code vector is a reference count
- * always create a new reference to a code vector by calling copycode()
- * always call freecode() when deleting a reference
- */
-union Code
-{
- int i;
- void (*f)(void);
- char *s;
-};
-
-struct Var
-{
- char *name;
- Word *val;
- short new : 1;
- short newfunc : 1;
- Code *func;
- void (*update)(Var *);
- Var *link;
-};
-
-struct Redir
-{
- char type; /* what to do */
- short from, to; /* what to do it to */
- struct Redir *link; /* what else to do (reverse order) */
-};
-
-enum
-{
- Pnil,
- Prun,
- Pstop,
- Psig,
- Pagain,
- Pdone,
-};
-
-struct WaitItem
-{
- int pid;
- ushort status;
-};
-
-struct Thread
-{
- struct {
- int i;
- Code *exe;
- } code; // execution stack
- struct {
- Io *io;
- char *path;
- } cmd; // command input
-
- List *args; // argument stack
- Var *local; // local variables
- struct {
- Redir *start;
- Redir *end;
- } redir; // list of redirections
-
- struct {
- ushort user : 1;
- ushort eof : 1;
- } flag;
-
- struct {
- ushort status;
- int len, cap;
- struct WaitItem *on;
- } wait;
-
- int pid, pgid, status;
- long line;
-
- Thread *caller; // process we return to
- Thread *link; // next job
-};
-
-struct Shell
-{
- int pid;
- Io *err;
- int status;
- int interactive;
- Thread *jobs;
-};
-
-// -----------------------------------------------------------------------
-// globals
-
-extern Shell shell;
-extern Thread *runner;
-extern Code *compiled;
-
-// -----------------------------------------------------------------------
-// functions
-
-/* util.c */
-void itoa(char*, long i);
-void fatal(char *, ...);
-void *emalloc(uintptr);
-void *erealloc(void*, uintptr);
-void efree(void*);
-
-/* input.c */
-int readline(char *);
-void enablevi(void);
-
-void inithistory(void);
-int addhistory(char *);
-
-/* prompt.c */
-void resetprompt(void);
-int prompt(ushort *);
-
-/* io.c */
-Io *openfd(int fd);
-Io *openstr(void);
-void terminate(Io *io);
-
-int get(Io *);
-int put(Io **, char);
-
-void flush(Io *io);
-void print(Io *, char *, ...);
-
-/* lex.c */
-int iswordchar(int c);
-int yylex(void);
-
-/* tree.c */
-Tree *maketree(void);
-Tree *maketree1(int, Tree*);
-Tree *maketree2(int, Tree*, Tree*);
-Tree *maketree3(int, Tree*, Tree*, Tree*);
-
-Tree *token(int, char *);
-Tree *hangchild1(Tree *, Tree *, int);
-Tree *hangchild2(Tree *, Tree *, int, Tree *, int);
-Tree *hangchild3(Tree *, Tree *, Tree *, Tree *);
-Tree *hangepilog(Tree *, Tree*);
-
-void freeparsetree(void);
-
-/* sys.c */
-void initenv(void);
-void redirect(struct Redir *);
-void execute(Word *, Word*);
-int mapfd(int fd);
-
-/* wait.c */
-void addwait(Thread *, int);
-void delwait(Thread *, int);
-void clearwait(Thread*);
-
-int waitall(Thread *);
-int waitfor(Thread *, int);
-
-void killzombies(void);
-
-/* job.c */
-Thread *getjob(int, int*);
-void addjob(Thread *);
-void deljob(Thread *);
-void wakeup(Thread *);
-void report(Thread *, int);
-
-void foreground(Thread *, int);
-void background(Thread *, int);
-
-/* exec.c */
-// XXX: odd place for this
-int count(Word *);
-Word *makeword(char *str, Word *link);
-void freeword(Word *w);
-
-/* var.c */
-Var *var(char*);
-Var *definevar(char*, Var *);
-Var *globalvar(char*);
-Var *makevar(char *name, Var *link);
-void setvar(char *, Word *);
-int iskeyword(char *);
-
-void initpath(void);
-void initkeywords(void);
-
-char **mkenv(void);
-
-/* code.c */
-int compile(Tree *);
-Code *copycode(Code *c);
-void freecode(Code *c);
diff --git a/sys/cmd/rc/rules.mk b/sys/cmd/rc/rules.mk
deleted file mode 100644
index a2fd058..0000000
--- a/sys/cmd/rc/rules.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-include share/push.mk
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) :=\
- $(d)/util.c\
- $(d)/input.c\
- $(d)/prompt.c\
- $(d)/io.c\
- $(d)/lex.c\
- $(d)/parse.c\
- $(d)/tree.c\
- $(d)/code.c\
- $(d)/var.c\
- $(d)/sys.c\
- $(d)/wait.c\
- $(d)/job.c\
- $(d)/exec.c\
- $(d)/main.c
-
-BINS_$(d) := $(d)/rc
-
-include share/paths.mk
-$(d)/parse.h $(d)/parse.c: $(d)/syntax.y
- yacc --header=$(<D)/parse.h --output=$(<D)/parse.c $(<)
-
-# Local rules
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/libutf/libutf.a $(OBJ_DIR)/sys/base/base.a $(d)/parse.h
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/rc/syntax.y b/sys/cmd/rc/syntax.y
deleted file mode 100644
index 0bdc776..0000000
--- a/sys/cmd/rc/syntax.y
+++ /dev/null
@@ -1,147 +0,0 @@
-%token Tfor Tin Twhile Tif Telse Tswitch Tcase Tcasebody Ttwiddle Tbang Tsubshell Tfunc
-%token Tredir Tdup Tpipe Tindex
-%token Tbasic Targs Tword Twords Tparen Tblock
-
-%define parse.error verbose
-
-%{
- #include "rc.h"
-
- int yylex(void);
- void yyerror(const char *);
-%}
-
-/* operator precendence: lowest first */
-%left Tif Tfor Tswitch Tcase ')' Twhile Telse
-%left Tandand Toror '\n'
-%left Tbang Tsubshell
-%left Tpipe;
-%left '^';
-%right '$' Tcount Tjoin
-%left Tindex
-
-/* semantic types */
-%union{
- struct Tree *tree;
-}
-%type<tree> line cmds cmdsln body paren block ifbody casebody case assign epilog redir;
-%type<tree> cmd basic executable nonkeyword keyword word words wordsnl atom;
-%type<tree> Tfor Tin Twhile Tif Telse Tswitch Tcase Ttwiddle Tbang Tsubshell Tfunc;
-%type<tree> Tword Tredir Tpipe Tdup;
-
-/* grammar */
-
-%start rc
-
-%%
-rc:
-/*empty*/ { return 0; }
-| line '\n' { return compile($1); }
-
-line:
- cmd
-| cmds line { $$ = maketree2(';', $1, $2); }
-
-body:
- cmd
-| cmdsln body { $$ = maketree2(';', $1, $2); }
-
-paren:
- '(' body ')' { $$ = maketree1(Tparen, $2); }
-
-block:
- '{' body '}' { $$ = maketree1(Tblock, $2); }
-
-cmds:
- cmd ';'
-| cmd '&' { $$ = maketree1('&', $1); }
-
-cmdsln:
- cmds
-| cmd '\n'
-
-ifbody:
- cmd %prec Telse { $$ = maketree2(Tif, nil, $1); }
-| block Telse nl cmd { $$ = maketree3(Tif, nil, $1, $2); }
-
-case:
- Tcase words ';' { $$ = hangchild1($1, $2, 0); }
-| Tcase words '\n' { $$ = hangchild1($1, $2, 0); }
-
-casebody:
- cmd { $$ = maketree2(Tcasebody, $1, nil); }
-| case casebody { $$ = maketree2(Tcasebody, $1, $2); }
-| cmdsln casebody { $$ = maketree2(Tcasebody, $1, $2); }
-
-assign:
- executable '=' word { $$ = maketree2('=', $1, $3); }
-
-redir:
- Tdup
-| Tredir word { $$ = hangchild1($1, $2, 0); }
-
-epilog:
-/* empty */ { $$ = nil; }
-| redir epilog { $$ = hangchild1($1, $2, 1); }
-
-cmd:
-/* empty */ %prec Twhile { $$ = nil; }
-| basic { $$ = maketree1(Tbasic, $1); }
-| block epilog { $$ = hangepilog($1, $2); }
-| cmd Tpipe nl cmd { $$ = hangchild2($2, $1, 0, $4, 1); }
-| cmd Tandand nl cmd { $$ = maketree2(Tandand, $1, $4); }
-| cmd Toror nl cmd { $$ = maketree2(Toror, $1, $4); }
-| redir cmd %prec Tbang { $$ = hangchild1($1, $2, 1); }
-| assign cmd %prec Tbang { $$ = hangchild1($1, $2, 2); }
-| Tbang cmd { $$ = maketree1(Tbang, $2); }
-| Tsubshell cmd { $$ = maketree1(Tsubshell, $2); }
-| Tfor '(' word ')' nl cmd { $$ = hangchild3($1, $3, nil, $6); }
-| Tfor '(' word Tin words ')' nl cmd { $$ = hangchild3($1, $3, $5, $8); }
-| Twhile paren nl cmd { $$ = hangchild2($1, $2, 0, $4, 1); }
-| Tif paren nl ifbody { $$ = hangchild1($2, $1, 0); }
-| Tswitch '(' word ')' nl '{' casebody '}' { $$ = hangchild2($1, $3, 0, $7, 1); }
-
-basic:
- executable
-| basic word { $$ = maketree2(Targs, $1, $2); }
-| basic redir { $$ = maketree2(Targs, $1, $2); }
-
-atom:
- nonkeyword
-| keyword { $$ = maketree1(Tword, $1); }
-
-word:
- atom
-| word '^' atom { $$ = maketree2('^', $1, $3); }
-
-executable:
- nonkeyword
-| executable '^' atom { $$ = maketree2('^', $1, $3); }
-
-nonkeyword:
- Tword
-| '$' atom { $$ = maketree1('$', $2); }
-| '$' atom Tindex words ')' { $$ = maketree2(Tindex, $2, $4); }
-| '(' wordsnl ')' { $$ = $2; }
-| Tcount atom { $$ = maketree1(Tcount, $2); }
-| Tjoin atom { $$ = maketree1(Tjoin, $2); }
-| '`' block { $$ = maketree1('`', $2); }
-//| Tredir block { $$ = hangchild1($1, $2, 0); $$->type = Tpipefd; }
-
-keyword:
- Tfor|Tin|Twhile|Tif|Telse|Tswitch|Tcase|Tbang|Tsubshell|Tfunc
-
-words:
-/* empty */ { $$ = nil; }
-| words word { $$ = maketree2(Twords, $1, $2); }
-
-wordsnl:
-/* empty */ { $$ = nil; }
-| wordsnl '\n' /* empty */
-| wordsnl word {$$ = (!$1) ? ((!$2) ? nil : $2) : ((!$2) ? $1 : maketree2(Twords, $1, $2)); }
-
-nl:
-/*empty*/
-| nl '\n'
-
-%%
diff --git a/sys/cmd/rc/sys.c b/sys/cmd/rc/sys.c
deleted file mode 100644
index 807359d..0000000
--- a/sys/cmd/rc/sys.c
+++ /dev/null
@@ -1,137 +0,0 @@
-#include "rc.h"
-
-// -----------------------------------------------------------------------
-// internal
-
-static
-char**
-mkargv(Word *args)
-{
- char **argv=emalloc((count(args)+2)*sizeof(char *));
- char **argp=argv+1; /* leave one at front for runcoms */
-
- for(;args;args=args->link)
- *argp++=args->str;
- *argp=nil;
-
- return argv;
-}
-
-static
-Word*
-envval(char *s)
-{
- Word *v;
- char *t, c;
-
- for(t=s; *t && *t!='\1'; t++)
- ;
-
- c = *t;
- *t = '\0';
-
- v = makeword(s, (c=='\0') ? nil : envval(t+1));
- *t=c;
-
- return v;
-}
-
-// -----------------------------------------------------------------------
-// exported
-
-void
-initenv(void)
-{
- extern char **environ;
-
- char *s;
- char **env;
-
- for(env=environ; *env; env++) {
- for(s=*env; *s && *s != '(' && *s != '='; s++)
- ;
- switch(*s){
- case '\0':
- break;
- case '(': /* ignore functions */
- break;
- case '=':
- *s = '\0';
- setvar(*env, envval(s+1));
- *s = '=';
- break;
- }
- }
-}
-
-void
-execute(Word *cmd, Word *path)
-{
- int nc;
- char **argv = mkargv(cmd);
- char **env = mkenv();
- char file[1024];
-
- for(; path; path=path->link){
- nc = strlen(path->str);
- if(nc < arrlen(file)){
- strcpy(file, path->str);
- if(file[0]){
- strcat(file, "/");
- nc++;
- }
- if(nc+strlen(argv[1]) < arrlen(file)){
- strcat(file, argv[1]);
- execve(file, argv+1, env);
- }else
- fatal("command name too long");
- }
- }
- print(shell.err, "could not execute command: %s\n", argv[1]);
- efree(argv);
-}
-
-void
-redirect(Redir *r)
-{
- if(r){
- redirect(r->link);
- switch(r->type){
- case Ropen:
- if(r->from != r->to){
- dup2(r->from, r->to);
- close(r->from);
- }
- break;
- case Rdupfd:
- dup2(r->from, r->to); // TODO: error checking
- break;
- case Rclose:
- close(r->from);
- break;
- default:
- fatal("unrecognized redirection type %d\n", r->type);
- }
- }
-}
-
-int
-mapfd(int fd)
-{
- Redir *r;
- for(r = runner->redir.end; r; r = r->link){
- switch(r->type){
- case Rclose:
- if(r->from == fd)
- fd = -1;
- break;
- case Rdupfd:
- case Ropen:
- if(r->to == fd)
- fd = r->from;
- break;
- }
- }
-
- return fd;
-}
diff --git a/sys/cmd/rc/tree.c b/sys/cmd/rc/tree.c
deleted file mode 100644
index 2c65041..0000000
--- a/sys/cmd/rc/tree.c
+++ /dev/null
@@ -1,111 +0,0 @@
-#include "rc.h"
-#include "parse.h"
-
-static Tree *nodes;
-
-Tree*
-maketree(void)
-{
- Tree *node = emalloc(sizeof(*node));
-
- node->link = nodes;
- nodes = node;
- return node;
-}
-
-void
-freeparsetree(void)
-{
- Tree *t, *nt;
- for(t = nodes; t; t = nt) {
- nt = t->link;
- if(t->type == Tword && t->str)
- efree(t->str);
- efree(t);
- }
- nodes = nil;
-}
-
-Tree*
-maketree1(int type, Tree *c0)
-{
- return maketree2(type, c0, nil);
-}
-
-Tree*
-maketree2(int type, Tree *c0, Tree *c1)
-{
- return maketree3(type, c0, c1, nil);
-}
-
-Tree*
-maketree3(int type, Tree *c0, Tree *c1, Tree *c2)
-{
- Tree *node = maketree();
-
- node->type = type;
- node->child[0] = c0;
- node->child[1] = c1;
- node->child[2] = c2;
-
- return node;
-}
-
-Tree*
-hangchild1(Tree *node, Tree *c, int i)
-{
- node->child[i] = c;
-
- return node;
-}
-
-Tree*
-hangchild2(Tree *node, Tree *c1, int i1, Tree *c2, int i2)
-{
- node->child[i1] = c1;
- node->child[i2] = c2;
-
- return node;
-}
-
-Tree*
-hangchild3(Tree *node, Tree *c0, Tree *c1, Tree *c2)
-{
- node->child[0] = c0;
- node->child[1] = c1;
- node->child[2] = c2;
-
- return node;
-}
-
-Tree*
-hangepilog(Tree *cmd, Tree *epi)
-{
- Tree *p;
- if(!epi)
- return cmd;
- for(p = epi; p->child[1]; p = p->child[1])
- ;
-
- p->child[1] = cmd;
- return epi;
-}
-
-Tree*
-token(int type, char *s)
-{
- Tree *node = maketree();
-
- node->type = type;
- node->str = strdup(s);
-
- return node;
-}
-
-/*
-Tree*
-basic(Tree *node)
-{
- return maketree1(Tbasic, node);
-}
-*/
diff --git a/sys/cmd/rc/util.c b/sys/cmd/rc/util.c
deleted file mode 100644
index b0be788..0000000
--- a/sys/cmd/rc/util.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "rc.h"
-
-void
-fatal(char *msg, ...)
-{
- va_list args;
- vfprintf(stderr, msg, args);
- va_end(args);
-
- abort();
-}
-
-void*
-emalloc(uintptr n)
-{
- void *p;
- if(!(p = malloc(n)))
- fatal("out of memory: can't allocate %d bytes", n);
-
- memset(p, 0, n);
- return p;
-}
-
-void*
-erealloc(void *p, uintptr n)
-{
- void *r;
- if(!(r = realloc(p,n)))
- fatal("out of memory: can't reallocate %d bytes", n);
-
- return r;
-}
-
-void
-efree(void *p)
-{
- if(p)
- free(p);
- // TODO: log the double free
-}
-
-
-char *bp;
-
-static
-void
-iacvt(int n)
-{
- if(n<0){
- *bp++='-';
- n=-n; /* doesn't work for n==-inf */
- }
- if(n/10)
- iacvt(n/10);
-
- *bp++=n%10+'0';
-}
-
-void
-itoa(char *s, long n)
-{
- bp = s;
- iacvt(n);
- *bp='\0';
-}
diff --git a/sys/cmd/rc/var.c b/sys/cmd/rc/var.c
deleted file mode 100644
index 3e9635f..0000000
--- a/sys/cmd/rc/var.c
+++ /dev/null
@@ -1,336 +0,0 @@
-#include "rc.h"
-#include "parse.h"
-
-// TODO: string interning
-
-// -----------------------------------------------------------------------
-// globals
-
-struct Keyword
-{
- char *name;
- int type;
-};
-
-static Var *globals[512];
-static struct Keyword keywords[100]; // sparse map means less hits
-
-// -----------------------------------------------------------------------
-// internals
-
-static
-int
-hash(char *s, int len)
-{
- int h =0, i = 1;
- while(*s)
- h += *s++*i++;
-
- h %= len;
- return h < 0 ? h+len : h;
-}
-
-static
-void
-·setvar(char *name, Word *val, int call)
-{
- Var *v = var(name);
- freeword(v->val);
-
- v->val = val;
- v->new = 1; // this never turns off?
-
- if(call && v->update)
- v->update(v);
-}
-
-static
-char*
-list2strcolon(Word *words)
-{
- char *value, *s, *t;
- int len = 0;
- Word *ap;
- for(ap = words;ap;ap = ap->link)
- len+=1+strlen(ap->str);
-
- value = emalloc(len+1);
-
- s = value;
- for(ap = words; ap; ap = ap->link){
- for(t = ap->str;*t;) *s++=*t++;
- *s++=':';
- }
-
- if(s==value)
- *s='\0';
- else
- s[-1]='\0';
-
- return value;
-}
-
-static
-void
-littlepath(Var *v)
-{
- /* convert $path to $PATH */
- char *p;
- Word *w;
-
- p = list2strcolon(v->val);
- w = emalloc(sizeof(*w));
- w->str = p;
- w->link = nil;
-
- ·setvar("PATH", w, 1);
-}
-
-static
-void
-bigpath(Var *v)
-{
- /* convert $PATH to $path */
- char *p, *q;
- Word **l, *w;
-
- if(v->val == nil){
- ·setvar("path", nil, 0);
- return;
- }
-
- p = v->val->str;
- w = nil;
- l = &w;
-
- /* Doesn't handle escaped colon nonsense. */
- if(p[0] == 0)
- p = nil;
-
- while(p){
- q = strchr(p, ':');
- if(q)
- *q = 0;
-
- *l = makeword(p[0] ? p : ".", nil);
- l = &(*l)->link;
-
- if(q){
- *q = ':';
- p = q+1;
- }else
- p = nil;
- }
- ·setvar("path", w, 0);
-}
-
-// -----------------------------------------------------------------------
-// exports
-
-Var*
-makevar(char *name, Var *link)
-{
- Var *v = emalloc(sizeof(*v));
-
- v->name = name;
- v->val = 0;
- v->new = 0;
- v->newfunc = 0;
- v->link = link;
- v->func = nil;
- v->update = nil;
-
- return v;
-}
-
-void
-setvar(char *name, Word *val)
-{
- ·setvar(name, val, 1);
-}
-
-Var*
-definevar(char *name, Var *link)
-{
- Var *v = emalloc(sizeof(*v));
-
- v->name = name;
- v->val = 0;
- v->link = link;
-
- return v;
-}
-
-Var*
-globalvar(char *name)
-{
- int h;
- Var *v;
-
- h = hash(name, arrlen(globals));
-
- if(strcmp(name,"PATH")==0){
- flush(shell.err);
- }
-
- for(v = globals[h]; v; v = v->link){
- if(strcmp(v->name, name) == 0){
- return v;
- }
- }
-
- return globals[h] = definevar(strdup(name), globals[h]);
-}
-
-Var*
-var(char *name)
-{
- Var *v;
- if(runner){
- for(v = runner->local; v; v=v->link)
- if(strcmp(v->name, name) == 0)
- return v;
- }
- return globalvar(name);
-}
-
-static
-int
-cmpenv(const void *a, const void *b)
-{
- return strcmp(*(char**)a, *(char**)b);
-}
-
-char**
-mkenv(void)
-{
- char **env, **ep, *p, *q;
- Var **h, *v;
- Word *a;
- int nvar=0, nchr=0, sep;
-
-#define BODY \
- if((v==var(v->name)) && v->val){ \
- nvar++; \
- nchr+=strlen(v->name)+1; \
- for(a=v->val;a;a=a->link) \
- nchr+=strlen(a->str)+1; \
- }
-
- for(v= runner->local; v; v=v->link){
- BODY
- }
- for(h=globals; h!=arrend(globals); h++){
- for(v = *h; v; v=v->link){
- BODY
- }
- }
-
-#undef BODY
-
- env=emalloc((nvar+1)*sizeof(*env)+nchr);
- ep=env;
- p=(char *)&env[nvar+1];
-
-#define BODY \
- if((v==var(v->name)) && v->val){ \
- *ep++=p; \
- q=v->name; \
- while(*q) \
- *p++=*q++; \
- sep='='; \
- for(a=v->val;a;a=a->link){ \
- *p++=sep; \
- sep='\1'; \
- q=a->str; \
- while(*q) \
- *p++=*q++; \
- } \
- *p++='\0'; \
- }
-
- for(v=runner->local; v; v=v->link){
- BODY
- }
- for(h=globals; h!=arrend(globals); h++){
- for(v = *h; v; v=v->link){
- BODY
- }
- }
-#undef BODY
-
- *ep=0;
-
- qsort((char *)env, nvar, sizeof ep[0], cmpenv);
- return env;
-}
-
-void
-initpath(void)
-{
- Var *v;
-
- v = globalvar("path");
- v->update = littlepath;
-
- v = globalvar("PATH");
- v->update = bigpath;
-
- flush(shell.err);
- bigpath(v);
-}
-
-#define KEYWORDS \
- KEYWORD("for", Tfor) \
- KEYWORD("in", Tin) \
- KEYWORD("while", Twhile) \
- KEYWORD("if", Tif) \
- KEYWORD("else", Telse) \
- KEYWORD("switch", Tswitch) \
- KEYWORD("case", Tcase) \
- KEYWORD("!", Tbang) \
- KEYWORD("@", Tsubshell) \
- KEYWORD("func", Tfunc)
-
-void
-initkeywords(void)
-{
- int i, s, j, h;
-#define KEYWORD(a, b) a,
- static char *name[] = { KEYWORDS };
-#undef KEYWORD
-#define KEYWORD(a, b) b,
- static int type[] = { KEYWORDS };
-#undef KEYWORD
-
- for(i = 0; i < arrlen(type); i++){
- h = hash(name[i], arrlen(keywords));
- for(s=0; s < arrlen(keywords); s++){
- j = (h + s) % arrlen(keywords);
- if(!keywords[j].type || strcmp(keywords[j].name, name[i]) == 0){
- keywords[j].name = name[i];
- keywords[j].type = type[i];
- goto nextkeyword;
- }
- }
- nextkeyword:;
- }
-}
-
-int
-iskeyword(char *word)
-{
- int i, s, h;
-
- h = hash(word, arrlen(keywords));
- for(s = 0; s < arrlen(keywords); s++){
- i = (h + s) % arrlen(keywords);
- if(!keywords[i].type)
- return 0;
- if(strcmp(keywords[i].name, word) == 0)
- return keywords[i].type;
- }
- return 0;
-}
-
-#undef KEYWORDS
diff --git a/sys/cmd/rc/wait.c b/sys/cmd/rc/wait.c
deleted file mode 100644
index 911601c..0000000
--- a/sys/cmd/rc/wait.c
+++ /dev/null
@@ -1,247 +0,0 @@
-#include "rc.h"
-
-#include <sys/wait.h>
-
-// -----------------------------------------------------------------------
-// globals
-
-struct WaitMsg
-{
- int pid;
- int type;
- ulong time[3];
- int status;
-};
-
-// -----------------------------------------------------------------------
-// internal
-
-static
-int
-await(int pid4, int opt, struct WaitMsg *msg)
-{
- int pid, status, core;
- struct rusage ru;
- ulong u, s;
-
- /* event loop */
- for(;;){
- if((pid = wait4(pid4, &status, opt, &ru)) <= 0){
- if(errno == ECHILD){
- msg->pid = -1;
- return 1;
- }
- msg->pid = 0;
- perror("failed wait4");
- return 0;
- }
-
- u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000);
- s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000);
-
- if(WIFEXITED(status)){
- msg->pid = pid;
- msg->time[0] = u;
- msg->time[1] = s;
- msg->time[2] = u+s;
- msg->status = WEXITSTATUS(status);
- msg->type = Pdone;
-
- return 1;
- }
-
- if(WIFSIGNALED(status)){
- msg->pid = pid;
- msg->time[0] = u;
- msg->time[1] = s;
- msg->time[2] = u+s;
- msg->status = WTERMSIG(status);
- msg->type = Psig;
-
- return 1;
- }
-
- if(WIFSTOPPED(status)){
- msg->pid = pid;
- msg->time[0] = u;
- msg->time[1] = s;
- msg->time[2] = u+s;
- msg->status = WSTOPSIG(status);
- msg->type = Pstop;
-
- return 1;
- }
- }
-}
-
-static
-int
-shouldwait(Thread *job)
-{
- int i;
-
- for(i=0; i<job->wait.len; i++){
- if(job->wait.on[i].status == Prun)
- return 1;
- }
-
- return 0;
-}
-
-static inline
-void
-notify(Thread *job, struct WaitMsg msg)
-{
- int i;
- for(i=0; i < job->wait.len; i++){
- if(job->wait.on[i].pid == msg.pid){
- job->status = msg.status;
- switch(msg.type){
- case Pstop:
- print(shell.err, "%d: suspended\n", msg.pid);
- job->wait.status = Pstop;
- job->wait.on[i].status = Pstop;
- break;
-
- case Psig:
- print(shell.err, "%d: terminated by signal %d\n", msg.pid, msg.status);
- /* fallthrough */
- case Pdone:
- job->wait.on[i].status = Pdone;
- delwait(job, msg.pid);
- if(!job->wait.len)
- job->wait.status = Pdone;
- break;
-
- default:
- fatal("%d: unrecognized message type %d\n", msg.pid, msg.type);
- }
- break;
- }
- }
-}
-
-// -----------------------------------------------------------------------
-// exported
-
-void
-clearwait(Thread *job)
-{
- job->wait.len = 0;
-}
-
-int
-havewait(Thread *job, int pid)
-{
- int i;
-
- for(i=0; i<job->wait.len; i++)
- if(job->wait.on[i].pid == pid)
- return 1;
- return 0;
-}
-
-void
-addwait(Thread *job, int pid)
-{
- if(job->wait.len == job->wait.cap){
- job->wait.cap = job->wait.cap + 2;
- job->wait.on = erealloc(job->wait.on, job->wait.cap*sizeof(*job->wait.on));
- }
-
- job->wait.on[job->wait.len++] = (struct WaitItem){.pid=pid, .status=Prun};
-}
-
-void
-delwait(Thread *job, int pid)
-{
- int r, w;
-
- for(r=w=0; r < job->wait.len; r++){
- if(job->wait.on[r].pid != pid)
- job->wait.on[w++].pid = job->wait.on[r].pid;
- }
- job->wait.len = w;
-}
-
-int
-waitall(Thread *job)
-{
- int i;
- Thread *t;
- struct WaitMsg msg;
-
- while(shouldwait(job) && await(-job->pgid, WUNTRACED, &msg)){
- switch(msg.pid){
- case 0: // error
- perror("wait job");
- return 0;
- case -1: // no children: assume they have exited
- job->wait.status = Pdone;
- clearwait(job);
- return 1;
- default:
- ;
- }
-
- notify(job, msg);
- }
- return 1;
-}
-
-int
-waitfor(Thread *job, int pid)
-{
- int i;
- Thread *t;
- struct WaitMsg msg;
-
- while(shouldwait(job) && await(-job->pgid, WUNTRACED, &msg)){
- switch(msg.pid){
- case 0: // error
- perror("wait for");
- return 0;
- case -1: // no children: assume they have exited
- job->wait.status = Pdone;
- clearwait(job);
- return 1;
- default:
- ;
- }
-
- notify(job, msg);
- /* allow for an early exit */
- if(msg.pid == pid)
- return 1;
- }
- return 1;
-
-}
-
-void
-killzombies(void)
-{
- Thread *job;
- int index, status, pid;
-
- while((pid=waitpid(-1, &status, WNOHANG))>0){
- print(shell.err, "found zombie pid %d\n", pid);
- flush(shell.err);
-
- job = getjob(pid, &index);
- if(!job)
- perror("invalid pid");
-
- if(WIFEXITED(status))
- job->wait.status = Pdone;
- if(WIFSTOPPED(status))
- job->wait.status = Pstop;
- if(WIFCONTINUED(status))
- job->wait.status = Pagain;
-
- if(job->wait.status == Pdone){
- report(job,index);
- deljob(job);
- }
- }
-}
diff --git a/sys/cmd/rules.mk b/sys/cmd/rules.mk
deleted file mode 100644
index 52a059b..0000000
--- a/sys/cmd/rules.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-include share/push.mk
-
-# Iterate through subdirectory tree
-
-# DIR := $(d)/cc
-# include $(DIR)/rules.mk
-
-DIR := $(d)/rc
-include $(DIR)/rules.mk
-
-DIR := $(d)/walk
-include $(DIR)/rules.mk
-
-DIR := $(d)/filter
-include $(DIR)/rules.mk
-
-# DIR := $(d)/test
-# include $(DIR)/rules.mk
-
-DIR := $(d)/ic
-include $(DIR)/rules.mk
-
-DIR := $(d)/dwm
-include $(DIR)/rules.mk
-
-DIR := $(d)/wm
-include $(DIR)/rules.mk
-
-DIR := $(d)/menu
-include $(DIR)/rules.mk
-
-DIR := $(d)/term
-include $(DIR)/rules.mk
-
-# DIR := $(d)/term2
-# include $(DIR)/rules.mk
-
-include share/pop.mk
diff --git a/sys/cmd/term/LICENSE b/sys/cmd/term/LICENSE
deleted file mode 100644
index c356c39..0000000
--- a/sys/cmd/term/LICENSE
+++ /dev/null
@@ -1,34 +0,0 @@
-MIT/X Consortium License
-
-© 2014-2018 Hiltjo Posthuma <hiltjo at codemadness dot org>
-© 2018 Devin J. Pohly <djpohly at gmail dot com>
-© 2014-2017 Quentin Rameau <quinq at fifth dot space>
-© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com>
-© 2008-2017 Anselm R Garbe <garbeam at gmail dot com>
-© 2012-2017 Roberto E. Vargas Caballero <k0ga at shike2 dot com>
-© 2012-2016 Christoph Lohmann <20h at r-36 dot net>
-© 2013 Eon S. Jeon <esjeon at hyunmu dot am>
-© 2013 Alexander Sedov <alex0player at gmail dot com>
-© 2013 Mark Edgar <medgar123 at gmail dot com>
-© 2013-2014 Eric Pruitt <eric.pruitt at gmail dot com>
-© 2013 Michael Forney <mforney at mforney dot org>
-© 2013-2014 Markus Teich <markus dot teich at stusta dot mhn dot de>
-© 2014-2015 Laslo Hunhold <dev at frign dot de>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/sys/cmd/term/config.h b/sys/cmd/term/config.h
deleted file mode 100644
index a740ecf..0000000
--- a/sys/cmd/term/config.h
+++ /dev/null
@@ -1,474 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#define VERSION "1"
-
-/*
- * appearance
- *
- * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
- */
-static char *font = "consolas:size=16";
-static int borderpx = 2;
-
-/*
- * What program is execed by st depends of these precedence rules:
- * 1: program passed with -e
- * 2: scroll and/or utmp
- * 3: SHELL environment variable
- * 4: value of shell in /etc/passwd
- * 5: value of shell in config.h
- */
-static char *shell = "/bin/mksh";
-char *utmp = nil;
-/* scroll program: to enable use a string like "scroll" */
-char *scroll = nil;
-char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400";
-
-/* identification sequence returned in DA and DECID */
-char *vtiden = "\033[?6c";
-
-/* Kerning / character bounding-box multipliers */
-static float cwscale = 1.0;
-static float chscale = 1.0;
-
-/*
- * word delimiter string
- *
- * More advanced example: L" `'\"()[]{}"
- */
-wchar_t *worddelimiters = L" ";
-
-/* selection timeouts (in milliseconds) */
-static uint doubleclicktimeout = 300;
-static uint tripleclicktimeout = 600;
-
-/* alt screens */
-int allowaltscreen = 1;
-
-/* allow certain non-interactive (insecure) window operations such as:
- setting the clipboard text */
-int allowwindowops = 0;
-
-/*
- * draw latency range in ms - from new content/keypress/etc until drawing.
- * within this range, st draws when content stops arriving (idle). mostly it's
- * near minlatency, but it waits longer for slow updates to avoid partial draw.
- * low minlatency will tear/flicker more, as it can "detect" idle too early.
- */
-static double minlatency = 8;
-static double maxlatency = 33;
-
-/*
- * blinking timeout (set to 0 to disable blinking) for the terminal blinking
- * attribute.
- */
-static uint blinktimeout = 800;
-
-/*
- * thickness of underline and bar cursors
- */
-static uint cursorthickness = 2;
-
-/*
- * bell volume. It must be a value between -100 and 100. Use 0 for disabling
- * it
- */
-static int bellvolume = 0;
-
-/* default TERM value */
-char *termname = "term-256color";
-
-/*
- * spaces per tab
- *
- * When you are changing this value, don't forget to adapt the »it« value in
- * the st.info and appropriately install the st.info in the environment where
- * you use this st version.
- *
- * it#$tabspaces,
- *
- * Secondly make sure your kernel is not expanding tabs. When running `stty
- * -a` »tab0« should appear. You can tell the terminal to not expand tabs by
- * running following command:
- *
- * stty tabs
- */
-uint tabspaces = 4;
-
-/* bg opacity */
-float alpha = 0.98;
-
-/* Terminal colors (16 first used in escape sequence) */
-static char *colorname[] = {
- "#282828", /* hard contrast: #1d2021 / soft contrast: #32302f */
- "#ea6962", /* red */
- "#a9b665", /* green */
- "#d8a657", /* yellow */
- "#7daea3", /* blue */
- "#d3869b", /* magenta */
- "#89b482", /* cyan */
- "#d4be98", /* white */
-
- "#928374", /* black */
- "#ef938e", /* red */
- "#bbc585", /* green */
- "#e1bb7e", /* yellow */
- "#9dc2ba", /* blue */
- "#e1acbb", /* magenta */
- "#a7c7a2", /* cyan */
- "#e2d3ba", /* white */
-
- [255] = 0,
-
- /* more colors can be added after 255 to use with DefaultXX */
- "#fbf1c7",
- "#3c3836",
- "#555555",
-};
-
-/*
- * Default colors (colorname index)
- * foreground, background, cursor, reverse cursor
- */
-uint defaultfg = 256;
-uint defaultbg = 257;
-static uint defaultcs = 15;
-static uint defaultrcs = 258;
-
-/*
- * Default shape of cursor
- * 2: Block ("█")
- * 4: Underline ("_")
- * 6: Bar ("|")
- * 7: Snowman ("☃")
- */
-static uint cursorshape = 2;
-
-/*
- * Default columns and rows numbers
- */
-
-static uint cols = 80;
-static uint rows = 24;
-
-/*
- * Default colour and shape of the mouse cursor
- */
-static uint mouseshape = XC_left_ptr;
-static uint mousefg = 0;
-static uint mousebg = 7;
-
-/*
- * Color used to display font attributes when fontconfig selected a font which
- * doesn't match the ones requested.
- */
-static uint defaultattr = 11;
-
-/*
- * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set).
- * Note that if you want to use ShiftMask with selmasks, set this to an other
- * modifier, set to 0 to not use it.
- */
-static uint forcemousemod = ShiftMask;
-
-/*
- * Internal mouse shortcuts.
- * Beware that overloading Button1 will disable the selection.
- */
-static MouseShortcut mshortcuts[] = {
- /* mask button function argument release */
- { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
- { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
- { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
- { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} },
- { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} },
-};
-
-/* Internal keyboard shortcuts. */
-#define MODKEY Mod1Mask
-#define TERMMOD (ControlMask|ShiftMask)
-
-static Shortcut shortcuts[] = {
- /* mask keysym function argument */
- { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} },
- { ControlMask, XK_Print, toggleprinter, {.i = 0} },
- { ShiftMask, XK_Print, printscreen, {.i = 0} },
- { XK_ANY_MOD, XK_Print, printsel, {.i = 0} },
- { TERMMOD, XK_plus, zoom, {.f = +1} },
- { ControlMask, XK_minus, zoom, {.f = -1} },
- { TERMMOD, XK_Home, zoomreset, {.f = 0} },
- { TERMMOD, XK_C, clipcopy, {.i = 0} },
- { TERMMOD, XK_V, clippaste, {.i = 0} },
- { TERMMOD, XK_Y, selpaste, {.i = 0} },
- { ShiftMask, XK_Insert, selpaste, {.i = 0} },
- { TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
-};
-
-/*
- * Special keys (change & recompile st.info accordingly)
- *
- * Mask value:
- * * Use XK_ANY_MOD to match the key no matter modifiers state
- * * Use XK_NO_MOD to match the key alone (no modifiers)
- * appkey value:
- * * 0: no value
- * * > 0: keypad application mode enabled
- * * = 2: term.numlock = 1
- * * < 0: keypad application mode disabled
- * appcursor value:
- * * 0: no value
- * * > 0: cursor application mode enabled
- * * < 0: cursor application mode disabled
- *
- * Be careful with the order of the definitions because st searches in
- * this table sequentially, so any XK_ANY_MOD must be in the last
- * position for a key.
- */
-
-/*
- * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF)
- * to be mapped below, add them to this array.
- */
-static KeySym mappedkeys[] = { -1 };
-
-/*
- * State bits to ignore when matching key or button events. By default,
- * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored.
- */
-static uint ignoremod = Mod2Mask|XK_SWITCH_MOD;
-
-/*
- * This is the huge key array which defines all compatibility to the Linux
- * world. Please decide about changes wisely.
- */
-static Key key[] = {
- /* keysym mask string appkey appcursor */
- { XK_KP_Home, ShiftMask, "\033[2J", 0, -1},
- { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1},
- { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1},
- { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1},
- { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0},
- { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1},
- { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1},
- { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0},
- { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1},
- { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1},
- { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0},
- { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1},
- { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1},
- { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0},
- { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1},
- { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1},
- { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0},
- { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0},
- { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0},
- { XK_KP_End, ControlMask, "\033[J", -1, 0},
- { XK_KP_End, ControlMask, "\033[1;5F", +1, 0},
- { XK_KP_End, ShiftMask, "\033[K", -1, 0},
- { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0},
- { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0},
- { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0},
- { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0},
- { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0},
- { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0},
- { XK_KP_Insert, ControlMask, "\033[L", -1, 0},
- { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0},
- { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0},
- { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0},
- { XK_KP_Delete, ControlMask, "\033[M", -1, 0},
- { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0},
- { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0},
- { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0},
- { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0},
- { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
- { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0},
- { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0},
- { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0},
- { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0},
- { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0},
- { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0},
- { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0},
- { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0},
- { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0},
- { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0},
- { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0},
- { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0},
- { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0},
- { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0},
- { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0},
- { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0},
- { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0},
- { XK_Up, ShiftMask, "\033[1;2A", 0, 0},
- { XK_Up, Mod1Mask, "\033[1;3A", 0, 0},
- { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0},
- { XK_Up, ControlMask, "\033[1;5A", 0, 0},
- { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0},
- { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0},
- { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0},
- { XK_Up, XK_ANY_MOD, "\033[A", 0, -1},
- { XK_Up, XK_ANY_MOD, "\033OA", 0, +1},
- { XK_Down, ShiftMask, "\033[1;2B", 0, 0},
- { XK_Down, Mod1Mask, "\033[1;3B", 0, 0},
- { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0},
- { XK_Down, ControlMask, "\033[1;5B", 0, 0},
- { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0},
- { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0},
- { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0},
- { XK_Down, XK_ANY_MOD, "\033[B", 0, -1},
- { XK_Down, XK_ANY_MOD, "\033OB", 0, +1},
- { XK_Left, ShiftMask, "\033[1;2D", 0, 0},
- { XK_Left, Mod1Mask, "\033[1;3D", 0, 0},
- { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0},
- { XK_Left, ControlMask, "\033[1;5D", 0, 0},
- { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0},
- { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0},
- { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0},
- { XK_Left, XK_ANY_MOD, "\033[D", 0, -1},
- { XK_Left, XK_ANY_MOD, "\033OD", 0, +1},
- { XK_Right, ShiftMask, "\033[1;2C", 0, 0},
- { XK_Right, Mod1Mask, "\033[1;3C", 0, 0},
- { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0},
- { XK_Right, ControlMask, "\033[1;5C", 0, 0},
- { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0},
- { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0},
- { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0},
- { XK_Right, XK_ANY_MOD, "\033[C", 0, -1},
- { XK_Right, XK_ANY_MOD, "\033OC", 0, +1},
- { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0},
- { XK_Return, Mod1Mask, "\033\r", 0, 0},
- { XK_Return, XK_ANY_MOD, "\r", 0, 0},
- { XK_Insert, ShiftMask, "\033[4l", -1, 0},
- { XK_Insert, ShiftMask, "\033[2;2~", +1, 0},
- { XK_Insert, ControlMask, "\033[L", -1, 0},
- { XK_Insert, ControlMask, "\033[2;5~", +1, 0},
- { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0},
- { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0},
- { XK_Delete, ControlMask, "\033[M", -1, 0},
- { XK_Delete, ControlMask, "\033[3;5~", +1, 0},
- { XK_Delete, ShiftMask, "\033[2K", -1, 0},
- { XK_Delete, ShiftMask, "\033[3;2~", +1, 0},
- { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0},
- { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
- { XK_BackSpace, XK_NO_MOD, "\177", 0, 0},
- { XK_BackSpace, Mod1Mask, "\033\177", 0, 0},
- { XK_Home, ShiftMask, "\033[2J", 0, -1},
- { XK_Home, ShiftMask, "\033[1;2H", 0, +1},
- { XK_Home, XK_ANY_MOD, "\033[H", 0, -1},
- { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1},
- { XK_End, ControlMask, "\033[J", -1, 0},
- { XK_End, ControlMask, "\033[1;5F", +1, 0},
- { XK_End, ShiftMask, "\033[K", -1, 0},
- { XK_End, ShiftMask, "\033[1;2F", +1, 0},
- { XK_End, XK_ANY_MOD, "\033[4~", 0, 0},
- { XK_Prior, ControlMask, "\033[5;5~", 0, 0},
- { XK_Prior, ShiftMask, "\033[5;2~", 0, 0},
- { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0},
- { XK_Next, ControlMask, "\033[6;5~", 0, 0},
- { XK_Next, ShiftMask, "\033[6;2~", 0, 0},
- { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0},
- { XK_F1, XK_NO_MOD, "\033OP" , 0, 0},
- { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0},
- { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0},
- { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0},
- { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0},
- { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0},
- { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0},
- { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0},
- { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0},
- { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0},
- { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0},
- { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0},
- { XK_F3, XK_NO_MOD, "\033OR" , 0, 0},
- { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0},
- { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0},
- { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0},
- { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0},
- { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0},
- { XK_F4, XK_NO_MOD, "\033OS" , 0, 0},
- { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0},
- { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0},
- { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0},
- { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0},
- { XK_F5, XK_NO_MOD, "\033[15~", 0, 0},
- { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0},
- { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0},
- { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0},
- { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0},
- { XK_F6, XK_NO_MOD, "\033[17~", 0, 0},
- { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0},
- { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0},
- { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0},
- { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0},
- { XK_F7, XK_NO_MOD, "\033[18~", 0, 0},
- { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0},
- { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0},
- { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0},
- { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0},
- { XK_F8, XK_NO_MOD, "\033[19~", 0, 0},
- { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0},
- { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0},
- { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0},
- { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0},
- { XK_F9, XK_NO_MOD, "\033[20~", 0, 0},
- { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0},
- { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0},
- { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0},
- { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0},
- { XK_F10, XK_NO_MOD, "\033[21~", 0, 0},
- { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0},
- { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0},
- { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0},
- { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0},
- { XK_F11, XK_NO_MOD, "\033[23~", 0, 0},
- { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0},
- { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0},
- { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0},
- { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0},
- { XK_F12, XK_NO_MOD, "\033[24~", 0, 0},
- { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0},
- { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0},
- { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0},
- { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0},
- { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0},
- { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0},
- { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0},
- { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0},
- { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0},
- { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0},
- { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0},
- { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0},
- { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0},
- { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0},
- { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0},
- { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0},
- { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0},
- { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0},
- { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0},
- { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0},
- { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0},
- { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0},
- { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0},
- { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0},
- { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0},
- { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0},
- { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0},
-};
-
-/*
- * Selection types' masks.
- * Use the same masks as usual.
- * Button1Mask is always unset, to make masks match between ButtonPress.
- * ButtonRelease and MotionNotify.
- * If no match is found, regular selection is used.
- */
-static uint selmasks[] = {
- [SelRectangular] = Mod1Mask,
-};
-
-/*
- * Printable characters in ASCII, used to estimate the advance width
- * of single wide characters.
- */
-static char ascii_printable[] =
- " !\"#$%&'()*+,-./0123456789:;<=>?"
- "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
- "`abcdefghijklmnopqrstuvwxyz{|}~";
diff --git a/sys/cmd/term/hb.c b/sys/cmd/term/hb.c
deleted file mode 100644
index 4b6b42d..0000000
--- a/sys/cmd/term/hb.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include "term.h"
-
-#include <X11/Xft/Xft.h>
-#include <harfbuzz/hb-ft.h>
-
-#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END }
-
-hb_font_t *hbfindfont(XftFont *match);
-void hbtransformsegment(XftFont *xfont, const Letter *glyph, rune *codepoints, int start, int end);
-
-typedef struct
-{
- XftFont *match;
- hb_font_t *font;
-} HbFontMatch;
-
-static int hbfontslen = 0;
-static HbFontMatch *hbfontcache = nil;
-
-/*
- * Replace 0 with a list of font features, wrapped in FEATURE macro, e.g.
- * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g')
- */
-hb_feature_t features[] = { 0 };
-
-void
-hbunloadfonts()
-{
- int i;
- for(i = 0; i < hbfontslen; i++) {
- hb_font_destroy(hbfontcache[i].font);
- XftUnlockFace(hbfontcache[i].match);
- }
-
- if(hbfontcache != nil) {
- free(hbfontcache);
- hbfontcache = nil;
- }
-
- hbfontslen = 0;
-}
-
-hb_font_t *
-hbfindfont(XftFont *match)
-{
- int i;
- for (i = 0; i < hbfontslen; i++) {
- if (hbfontcache[i].match == match)
- return hbfontcache[i].font;
- }
-
- /* Font not found in cache, caching it now. */
- hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfontslen + 1));
- FT_Face face = XftLockFace(match);
- hb_font_t *font = hb_ft_font_create(face, NULL);
- if(!font)
- fatal("failed to load Harfbuzz font.");
-
- hbfontcache[hbfontslen].match = match;
- hbfontcache[hbfontslen].font = font;
- hbfontslen += 1;
-
- return font;
-}
-
-void
-hbtransform(XftGlyphFontSpec *specs, const Letter *glyphs, size_t len, int x, int y)
-{
- int idx, specidx, start = 0, length = 1, gstart = 0;
- rune *runes = calloc((unsigned int)len, sizeof(hb_codepoint_t));
-
- for(idx = 1, specidx = 1; idx < len; idx++) {
- if(glyphs[idx].mode & Gwdummy) {
- length += 1;
- continue;
- }
-
- if(specs[specidx].font != specs[start].font
- || GLYPHCMP(glyphs[gstart], glyphs[idx])
- || selected(x + idx, y) != selected(x + gstart, y)
- ) {
- hbtransformsegment(specs[start].font, glyphs, runes, gstart, length);
- /* reset the sequence. */
- length = 1;
- start = specidx;
- gstart = idx;
- } else {
- length += 1;
- }
-
- specidx++;
- }
-
- /* eol */
- hbtransformsegment(specs[start].font, glyphs, runes, gstart, length);
-
- /* apply the transformation to glyph specs. */
- for(idx = 0, specidx = 0; idx < len; idx++) {
- if(glyphs[idx].mode & Gwdummy)
- continue;
-
- if(runes[idx] != specs[specidx].glyph)
- ((Letter *)glyphs)[idx].mode |= Gliga;
-
- specs[specidx++].glyph = runes[idx];
- }
-
- free(runes);
-}
-
-void
-hbtransformsegment(XftFont *xfont, const Letter *glyph, rune *codepoints, int start, int len)
-{
- hb_font_t *font = hbfindfont(xfont);
- if(!font)
- return;
-
- int i;
- rune r;
- ushort mode = USHRT_MAX;
- hb_buffer_t *buffer = hb_buffer_create();
- hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
-
- /* Fill buffer with codepoints. */
- for(i=start; i < (start+len); i++) {
- r = glyph[i].u;
- mode = glyph[i].mode;
- if(mode & Gwdummy)
- r = 0x0020;
- hb_buffer_add_codepoints(buffer, &r, 1, 0, 1);
- }
-
- /* Shape the segment. */
- hb_shape(font, buffer, features, sizeof(features));
-
- /* Get new glyph info. */
- hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL);
-
- /* Write new codepoints. */
- for(i = 0; i < len; i++) {
- r = info[i].codepoint;
- codepoints[start+i] = r;
- }
-
- /* Cleanup. */
- hb_buffer_destroy(buffer);
-}
diff --git a/sys/cmd/term/nonspacing.h b/sys/cmd/term/nonspacing.h
deleted file mode 100644
index 5d05a3d..0000000
--- a/sys/cmd/term/nonspacing.h
+++ /dev/null
@@ -1,89 +0,0 @@
-16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,16,16,32,16,16,16,33,34,35,
-36,37,38,39,16,16,40,16,16,16,16,16,16,16,16,16,16,16,41,42,16,16,43,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,44,16,45,46,47,48,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,49,16,16,50,
-51,16,52,53,54,16,16,16,16,16,16,55,16,16,56,16,57,58,59,60,61,62,63,64,65,66,
-67,68,16,69,70,71,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,72,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,73,74,16,16,16,75,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,76,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,77,78,16,16,16,16,16,16,16,79,16,16,16,16,16,80,81,82,16,16,16,16,16,83,
-84,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,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,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,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,248,3,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,254,255,255,255,255,191,182,0,0,0,0,0,0,0,63,0,255,23,0,0,0,0,0,248,255,
-255,0,0,1,0,0,0,0,0,0,0,0,0,0,0,192,191,159,61,0,0,0,128,2,0,0,0,255,255,255,
-7,0,0,0,0,0,0,0,0,0,0,192,255,1,0,0,0,0,0,0,248,15,32,0,0,192,251,239,62,0,0,
-0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,255,255,255,255,
-255,7,0,0,0,0,0,0,20,254,33,254,0,12,0,0,0,2,0,0,0,0,0,0,16,30,32,0,0,12,0,0,
-64,6,0,0,0,0,0,0,16,134,57,2,0,0,0,35,0,6,0,0,0,0,0,0,16,190,33,0,0,12,0,0,
-252,2,0,0,0,0,0,0,144,30,32,64,0,12,0,0,0,4,0,0,0,0,0,0,0,1,32,0,0,0,0,0,0,17,
-0,0,0,0,0,0,192,193,61,96,0,12,0,0,0,2,0,0,0,0,0,0,144,64,48,0,0,12,0,0,0,3,0,
-0,0,0,0,0,24,30,32,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,4,92,0,0,0,0,0,0,0,0,0,0,0,
-242,7,128,127,0,0,0,0,0,0,0,0,0,0,0,0,242,31,0,63,0,0,0,0,0,0,0,0,0,3,0,0,160,
-2,0,0,0,0,0,0,254,127,223,224,255,254,255,255,255,31,64,0,0,0,0,0,0,0,0,0,0,0,
-0,224,253,102,0,0,0,195,1,0,30,0,100,32,0,32,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,
-0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254,15,32,0,0,0,0,0,120,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,1,4,14,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,128,9,0,0,0,0,0,0,64,127,
-229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0,15,0,0,0,0,0,208,23,4,0,0,
-0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0,0,0,0,0,240,207,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,
-251,0,248,0,0,0,124,0,0,0,0,0,0,223,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,
-255,1,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,128,3,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,
-0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,6,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,128,247,63,0,0,0,192,0,0,0,0,0,0,0,0,0,0,3,0,68,8,0,0,96,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,255,255,3,128,0,0,0,0,192,63,0,0,128,255,3,0,
-0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0,0,0,0,0,0,0,126,102,0,8,16,0,0,0,0,
-0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64,
-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,32,33,0,0,0,0,0,64,
-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,255,255,0,0,255,255,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,128,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,14,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,32,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,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,110,240,0,0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,
-0,0,0,0,0,240,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,192,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255,
-127,0,0,0,0,0,0,128,3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0,
-0,0,0,0,0,0,8,0,3,0,0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192,
-31,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0,
-0,0,0,0,0,248,133,13,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,60,176,1,0,0,48,0,0,0,
-0,0,0,0,0,0,0,248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0,
-0,224,188,15,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,
-128,255,6,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,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0,
-126,14,0,0,0,0,0,252,127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0,
-0,0,0,0,0,0,0,252,255,255,252,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,180,191,0,
-0,0,0,0,0,0,0,0,163,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,24,
-0,0,0,0,0,0,0,255,1,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,31,0,0,0,0,0,0,0,127,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,128,0,0,0,0,0,0,
-0,128,7,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,96,15,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,255,255,255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248,
-254,255,0,0,0,0,0,0,0,0,0,
-0,127,255,255,249,219,7,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,127,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,240,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,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,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/cmd/term/rules.mk b/sys/cmd/term/rules.mk
deleted file mode 100644
index 45c9eb2..0000000
--- a/sys/cmd/term/rules.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-include share/push.mk
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := $(d)/term.c $(d)/x.c #$(d)/hb.c
-BINS_$(d) := $(d)/term
-
-include share/paths.mk
-
-# Local rules
-include share/dynamic.mk
-$(BINS_$(d)): TCFLAGS = \
- `$(PKG) --cflags fontconfig` \
- `$(PKG) --cflags freetype2`
-
-$(BINS_$(d)): TCLIBS = \
- `$(PKG) --libs fontconfig` \
- `$(PKG) --libs freetype2` \
- -lm -lrt -lX11 -lutil -lXft -lXrender #-lharfbuzz
-
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/libutf/libutf.a $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/term/term.c b/sys/cmd/term/term.c
deleted file mode 100644
index 50ab29c..0000000
--- a/sys/cmd/term/term.c
+++ /dev/null
@@ -1,2417 +0,0 @@
-/* See LICENSE for license details. */
-#include "term.h"
-
-#include <pwd.h>
-#include <termios.h>
-#if defined(__linux)
- #include <pty.h>
-#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
- #include <util.h>
-#elif defined(__FreeBSD__) || defined(__DragonFly__)
- #include <libutil.h>
-#endif
-
-/* macros */
-#define IS_SET(flag) ((term.mode & (flag)) != 0)
-#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f)
-#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
-#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
-#define ISDELIM(u) (u && wcschr(worddelimiters, u))
-
-/* forward declare functions */
-static void execsh(char *, char **);
-static void stty(char **);
-static void sigchld(int);
-static void ttywriteraw(char *, size_t);
-
-static void csidump(void);
-static void csihandle(void);
-static void csiparse(void);
-static void csireset(void);
-static int eschandle(uchar);
-static void strdump(void);
-static void strhandle(void);
-static void strparse(void);
-static void strreset(void);
-
-static void tprinter(char *, size_t);
-static void tdumpsel(void);
-static void tdumpline(int);
-static void tdump(void);
-static void tclearregion(int, int, int, int);
-static void tcursor(int);
-static void tdeletechar(int);
-static void tdeleteline(int);
-static void tinsertblank(int);
-static void tinsertblankline(int);
-static int tlinelen(int);
-static void tmoveto(int, int);
-static void tmoveato(int, int);
-static void tnewline(int);
-static void tputtab(int);
-static void tputc(rune);
-static void treset(void);
-static void tscrollup(int, int);
-static void tscrolldown(int, int);
-static void tsetattr(int *, int);
-static void tsetchar(rune, Letter *, int, int);
-static void tsetdirt(int, int);
-static void tsetscroll(int, int);
-static void tswapscreen(void);
-static void tsetmode(int, int, int *, int);
-static int twrite(char *, int, int);
-static void tfulldirt(void);
-static void tcontrolcode(uchar );
-static void tdectest(char );
-static void tdefutf8(char);
-static int32 tdefcolor(int *, int *, int);
-static void tdeftran(char);
-static void tstrsequence(uchar);
-
-static void drawregion(int, int, int, int);
-
-static void selnormalize(void);
-static void selscroll(int, int);
-static void selsnap(int *, int *, int);
-
-static char *base64dec(char *);
-static char base64dec_getc(char **);
-
-static uintptr xwrite(int, char *, size_t);
-extern int wcwidth(wchar_t wc);
-
-/* globals */
-static Terminal term;
-static Selection sel;
-static CSIEscape csiescseq;
-static STREscape strescseq;
-static int iofd = 1;
-static int cmdfd;
-static pid_t pid;
-
-/* functions */
-uintptr
-xwrite(int fd, char *s, size_t len)
-{
- size_t aux = len;
- ssize_t r;
-
- while (len > 0) {
- r = write(fd, s, len);
- if (r < 0)
- return r;
- len -= r;
- s += r;
- }
-
- return aux;
-}
-
-void *
-xmalloc(size_t len)
-{
- void *p;
-
- if (!(p = malloc(len)))
- fatal("malloc: %s\n", strerror(errno));
-
- return p;
-}
-
-void *
-xrealloc(void *p, size_t len)
-{
- if ((p = realloc(p, len)) == nil)
- fatal("realloc: %s\n", strerror(errno));
-
- return p;
-}
-
-char *
-xstrdup(char *s)
-{
- if ((s = strdup(s)) == nil)
- fatal("strdup: %s\n", strerror(errno));
-
- return s;
-}
-
-static char base64_digits[] = {
- 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, 62, 0, 0, 0,
- 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1,
- 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 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, 0, 0, 0, 0
-};
-
-char
-base64dec_getc(char **src)
-{
- while (**src && !isprint(**src))
- (*src)++;
- return **src ? *((*src)++) : '='; /* emulate padding if string ends */
-}
-
-char *
-base64dec(char *src)
-{
- size_t in_len = strlen(src);
- char *result, *dst;
-
- if (in_len % 4)
- in_len += 4 - (in_len % 4);
- result = dst = xmalloc(in_len / 4 * 3 + 1);
- while (*src) {
- int a = base64_digits[(unsigned char) base64dec_getc(&src)];
- int b = base64_digits[(unsigned char) base64dec_getc(&src)];
- int c = base64_digits[(unsigned char) base64dec_getc(&src)];
- int d = base64_digits[(unsigned char) base64dec_getc(&src)];
-
- /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */
- if (a == -1 || b == -1)
- break;
-
- *dst++ = (a << 2) | ((b & 0x30) >> 4);
- if (c == -1)
- break;
- *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2);
- if (d == -1)
- break;
- *dst++ = ((c & 0x03) << 6) | d;
- }
- *dst = '\0';
- return result;
-}
-
-void
-selinit(void)
-{
- sel.mode = SelIdle;
- sel.snap = 0;
- sel.ob.x = -1;
-}
-
-int
-tlinelen(int y)
-{
- int i = term.col;
-
- if (term.line[y][i - 1].mode & Gwrap)
- return i;
-
- while (i > 0 && term.line[y][i - 1].u == ' ')
- --i;
-
- return i;
-}
-
-void
-selstart(int col, int row, int snap)
-{
- selclear();
- sel.mode = SelEmpty;
- sel.type = SelRegular;
- sel.alt = IS_SET(Taltscreen);
- sel.snap = snap;
- sel.oe.x = sel.ob.x = col;
- sel.oe.y = sel.ob.y = row;
- selnormalize();
-
- if (sel.snap != 0)
- sel.mode = SelReady;
- tsetdirt(sel.nb.y, sel.ne.y);
-}
-
-void
-selextend(int col, int row, int type, int done)
-{
- int oldey, oldex, oldsby, oldsey, oldtype;
-
- if (sel.mode == SelIdle)
- return;
- if (done && sel.mode == SelEmpty) {
- selclear();
- return;
- }
-
- oldey = sel.oe.y;
- oldex = sel.oe.x;
- oldsby = sel.nb.y;
- oldsey = sel.ne.y;
- oldtype = sel.type;
-
- sel.oe.x = col;
- sel.oe.y = row;
- selnormalize();
- sel.type = type;
-
- if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SelEmpty)
- tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey));
-
- sel.mode = done ? SelIdle : SelReady;
-}
-
-void
-selnormalize(void)
-{
- int i;
-
- if (sel.type == SelRegular && sel.ob.y != sel.oe.y) {
- sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x;
- sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x;
- } else {
- sel.nb.x = MIN(sel.ob.x, sel.oe.x);
- sel.ne.x = MAX(sel.ob.x, sel.oe.x);
- }
- sel.nb.y = MIN(sel.ob.y, sel.oe.y);
- sel.ne.y = MAX(sel.ob.y, sel.oe.y);
-
- selsnap(&sel.nb.x, &sel.nb.y, -1);
- selsnap(&sel.ne.x, &sel.ne.y, +1);
-
- /* expand selection over line breaks */
- if (sel.type == SelRectangular)
- return;
- i = tlinelen(sel.nb.y);
- if (i < sel.nb.x)
- sel.nb.x = i;
- if (tlinelen(sel.ne.y) <= sel.ne.x)
- sel.ne.x = term.col - 1;
-}
-
-int
-selected(int x, int y)
-{
- if(sel.mode == SelEmpty || sel.ob.x == -1 ||
- sel.alt != IS_SET(Taltscreen))
- return 0;
-
- if(sel.type == SelRectangular)
- return BETWEEN(y, sel.nb.y, sel.ne.y)
- && BETWEEN(x, sel.nb.x, sel.ne.x);
-
- return BETWEEN(y, sel.nb.y, sel.ne.y)
- && (y != sel.nb.y || x >= sel.nb.x)
- && (y != sel.ne.y || x <= sel.ne.x);
-}
-
-void
-selsnap(int *x, int *y, int direction)
-{
- int newx, newy, xt, yt;
- int delim, prevdelim;
- Letter *gp, *prevgp;
-
- switch (sel.snap) {
- case SnapWord:
- /*
- * Snap around if the word wraps around at the end or
- * beginning of a line.
- */
- prevgp = &term.line[*y][*x];
- prevdelim = ISDELIM(prevgp->u);
- for (;;) {
- newx = *x + direction;
- newy = *y;
- if (!BETWEEN(newx, 0, term.col - 1)) {
- newy += direction;
- newx = (newx + term.col) % term.col;
- if (!BETWEEN(newy, 0, term.row - 1))
- break;
-
- if (direction > 0)
- yt = *y, xt = *x;
- else
- yt = newy, xt = newx;
- if (!(term.line[yt][xt].mode & Gwrap))
- break;
- }
-
- if (newx >= tlinelen(newy))
- break;
-
- gp = &term.line[newy][newx];
- delim = ISDELIM(gp->u);
- if (!(gp->mode & Gwdummy) && (delim != prevdelim
- || (delim && gp->u != prevgp->u)))
- break;
-
- *x = newx;
- *y = newy;
- prevgp = gp;
- prevdelim = delim;
- }
- break;
- case SnapLine:
- /*
- * Snap around if the the previous line or the current one
- * has set ATTR_WRAP at its end. Then the whole next or
- * previous line will be selected.
- */
- *x = (direction < 0) ? 0 : term.col - 1;
- if (direction < 0) {
- for (; *y > 0; *y += direction) {
- if (!(term.line[*y-1][term.col-1].mode
- & Gwrap)) {
- break;
- }
- }
- } else if (direction > 0) {
- for (; *y < term.row-1; *y += direction) {
- if (!(term.line[*y][term.col-1].mode
- & Gwrap)) {
- break;
- }
- }
- }
- break;
- }
-}
-
-char *
-getsel(void)
-{
- char *str, *ptr;
- int y, bufsize, lastx, linelen;
- Letter *gp, *last;
-
- if (sel.ob.x == -1)
- return nil;
-
- bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTFmax;
- ptr = str = xmalloc(bufsize);
-
- /* append every set & selected glyph to the selection */
- for(y = sel.nb.y; y <= sel.ne.y; y++) {
- if((linelen = tlinelen(y)) == 0) {
- *ptr++ = '\n';
- continue;
- }
-
- if(sel.type == SelRectangular) {
- gp = &term.line[y][sel.nb.x];
- lastx = sel.ne.x;
- }else{
- gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
- lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
- }
- last = &term.line[y][MIN(lastx, linelen-1)];
- while (last >= gp && last->u == ' ')
- --last;
-
- for ( ; gp <= last; ++gp) {
- if (gp->mode & Gwdummy)
- continue;
-
- ptr += utf8·encode(&gp->u, ptr);
- }
-
- /*
- * Copy and pasting of line endings is inconsistent
- * in the inconsistent terminal and GUI world.
- * The best solution seems like to produce '\n' when
- * something is copied from st and convert '\n' to
- * '\r', when something to be pasted is received by
- * st.
- * FIXME: Fix the computer world.
- */
- if ((y < sel.ne.y || lastx >= linelen) &&
- (!(last->mode & Gwrap) || sel.type == SelRectangular))
- *ptr++ = '\n';
- }
- *ptr = 0;
- return str;
-}
-
-void
-selclear(void)
-{
- if (sel.ob.x == -1)
- return;
- sel.mode = SelIdle;
- sel.ob.x = -1;
- tsetdirt(sel.nb.y, sel.ne.y);
-}
-
-void
-fatal(char *errstr, ...)
-{
- va_list ap;
-
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
- exit(1);
-}
-
-void
-execsh(char *cmd, char **args)
-{
- char *sh, *prog, *arg;
- struct passwd *pw;
-
- errno = 0;
- if ((pw = getpwuid(getuid())) == nil) {
- if (errno)
- fatal("getpwuid: %s\n", strerror(errno));
- else
- fatal("who are you?\n");
- }
-
- if ((sh = getenv("SHELL")) == nil)
- sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd;
-
- if (args) {
- prog = args[0];
- arg = nil;
- } else if (scroll) {
- prog = scroll;
- arg = utmp ? utmp : sh;
- } else if (utmp) {
- prog = utmp;
- arg = nil;
- } else {
- prog = sh;
- arg = nil;
- }
- DEFAULT(args, ((char *[]) {prog, arg, nil}));
-
- unsetenv("COLUMNS");
- unsetenv("LINES");
- unsetenv("TERMCAP");
- setenv("LOGNAME", pw->pw_name, 1);
- setenv("USER", pw->pw_name, 1);
- setenv("SHELL", sh, 1);
- setenv("HOME", pw->pw_dir, 1);
- setenv("TERM", termname, 1);
-
- signal(SIGCHLD, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGALRM, SIG_DFL);
-
- execvp(prog, args);
- _exit(1);
-}
-
-void
-sigchld(int a)
-{
- int stat;
- pid_t p;
-
- if ((p = waitpid(pid, &stat, WNOHANG)) < 0)
- fatal("waiting for pid %hd failed: %s\n", pid, strerror(errno));
-
- if (pid != p)
- return;
-
- if (WIFEXITED(stat) && WEXITSTATUS(stat))
- fatal("child exited with status %d\n", WEXITSTATUS(stat));
- else if (WIFSIGNALED(stat))
- fatal("child terminated due to signal %d\n", WTERMSIG(stat));
- _exit(0);
-}
-
-void
-stty(char **args)
-{
- char cmd[_POSIX_ARG_MAX], **p, *q, *s;
- size_t n, siz;
-
- if ((n = strlen(stty_args)) > sizeof(cmd)-1)
- fatal("incorrect stty parameters\n");
- memcpy(cmd, stty_args, n);
- q = cmd + n;
- siz = sizeof(cmd) - n;
- for (p = args; p && (s = *p); ++p) {
- if ((n = strlen(s)) > siz-1)
- fatal("stty parameter length too long\n");
- *q++ = ' ';
- memcpy(q, s, n);
- q += n;
- siz -= n + 1;
- }
- *q = '\0';
- if (system(cmd) != 0)
- perror("Couldn't call stty");
-}
-
-int
-ttynew(char *line, char *cmd, char *out, char **args)
-{
- int m, s;
-
- if (out) {
- term.mode |= Tprint;
- iofd = (!strcmp(out, "-")) ?
- 1 : open(out, O_WRONLY | O_CREAT, 0666);
- if (iofd < 0) {
- fprintf(stderr, "Error opening %s:%s\n",
- out, strerror(errno));
- }
- }
-
- if (line) {
- if ((cmdfd = open(line, O_RDWR)) < 0)
- fatal("open line '%s' failed: %s\n",
- line, strerror(errno));
- dup2(cmdfd, 0);
- stty(args);
- return cmdfd;
- }
-
- /* seems to work fine on linux, openbsd and freebsd */
- if (openpty(&m, &s, nil, nil, nil) < 0)
- fatal("openpty failed: %s\n", strerror(errno));
-
- switch (pid = fork()) {
- case -1:
- fatal("fork failed: %s\n", strerror(errno));
- break;
- case 0:
- close(iofd);
- setsid(); /* create a new process group */
- dup2(s, 0);
- dup2(s, 1);
- dup2(s, 2);
- if (ioctl(s, TIOCSCTTY, nil) < 0)
- fatal("ioctl TIOCSCTTY failed: %s\n", strerror(errno));
- close(s);
- close(m);
-#ifdef __OpenBSD__
- if (pledge("stdio getpw proc exec", nil) == -1)
- fatal("pledge\n");
-#endif
- execsh(cmd, args);
- break;
- default:
-#ifdef __OpenBSD__
- if (pledge("stdio rpath tty proc", nil) == -1)
- fatal("pledge\n");
-#endif
- close(s);
- cmdfd = m;
- signal(SIGCHLD, sigchld);
- break;
- }
- return cmdfd;
-}
-
-size_t
-ttyread(void)
-{
- static char buf[BUFSIZ];
- static int buflen = 0;
- int ret, written;
-
- /* append read bytes to unprocessed bytes */
- ret = read(cmdfd, buf+buflen, arrlen(buf)-buflen);
-
- switch (ret) {
- case 0:
- exit(0);
- case -1:
- fatal("couldn't read from shell: %s\n", strerror(errno));
- default:
- buflen += ret;
- written = twrite(buf, buflen, 0);
- buflen -= written;
- /* keep any incomplete UTF-8 byte sequence for the next call */
- if(buflen > 0)
- memmove(buf, buf + written, buflen);
- return ret;
- }
-}
-
-void
-ttywrite(char *s, size_t n, int may_echo)
-{
- char *next;
-
- if (may_echo && IS_SET(Techo))
- twrite(s, n, 1);
-
- if (!IS_SET(Tcrlf)) {
- ttywriteraw(s, n);
- return;
- }
-
- /* This is similar to how the kernel handles ONLCR for ttys */
- while (n > 0) {
- if (*s == '\r') {
- next = s + 1;
- ttywriteraw("\r\n", 2);
- } else {
- next = memchr(s, '\r', n);
- DEFAULT(next, s + n);
- ttywriteraw(s, next - s);
- }
- n -= next - s;
- s = next;
- }
-}
-
-void
-ttywriteraw(char *s, size_t n)
-{
- fd_set wfd, rfd;
- ssize_t r;
- size_t lim = 256;
-
- /*
- * Remember that we are using a pty, which might be a modem line.
- * Writing too much will clog the line. That's why we are doing this
- * dance.
- * FIXME: Migrate the world to Plan 9.
- */
- while (n > 0) {
- FD_ZERO(&wfd);
- FD_ZERO(&rfd);
- FD_SET(cmdfd, &wfd);
- FD_SET(cmdfd, &rfd);
-
- /* Check if we can write. */
- if (pselect(cmdfd+1, &rfd, &wfd, nil, nil, nil) < 0) {
- if (errno == EINTR)
- continue;
- fatal("select failed: %s\n", strerror(errno));
- }
- if (FD_ISSET(cmdfd, &wfd)) {
- /*
- * Only write the bytes written by ttywrite() or the
- * default of 256. This seems to be a reasonable value
- * for a serial line. Bigger values might clog the I/O.
- */
- if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0)
- goto write_error;
- if (r < n) {
- /*
- * We weren't able to write out everything.
- * This means the buffer is getting full
- * again. Empty it.
- */
- if (n < lim)
- lim = ttyread();
- n -= r;
- s += r;
- } else {
- /* All bytes have been written. */
- break;
- }
- }
- if (FD_ISSET(cmdfd, &rfd))
- lim = ttyread();
- }
- return;
-
-write_error:
- fatal("write error on tty: %s\n", strerror(errno));
-}
-
-void
-ttyresize(int tw, int th)
-{
- struct winsize w;
-
- w.ws_row = term.row;
- w.ws_col = term.col;
- w.ws_xpixel = tw;
- w.ws_ypixel = th;
- if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0)
- fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno));
-}
-
-void
-ttyhangup()
-{
- /* Send SIGHUP to shell */
- kill(pid, SIGHUP);
-}
-
-int
-tattrset(int attr)
-{
- int i, j;
-
- for (i = 0; i < term.row-1; i++) {
- for (j = 0; j < term.col-1; j++) {
- if (term.line[i][j].mode & attr)
- return 1;
- }
- }
-
- return 0;
-}
-
-void
-tsetdirt(int top, int bot)
-{
- int i;
-
- LIMIT(top, 0, term.row-1);
- LIMIT(bot, 0, term.row-1);
-
- for (i = top; i <= bot; i++)
- term.dirty[i] = 1;
-}
-
-void
-tsetdirtattr(int attr)
-{
- int i, j;
-
- for (i = 0; i < term.row-1; i++) {
- for (j = 0; j < term.col-1; j++) {
- if (term.line[i][j].mode & attr) {
- tsetdirt(i, i);
- break;
- }
- }
- }
-}
-
-void
-tfulldirt(void)
-{
- tsetdirt(0, term.row-1);
-}
-
-void
-tcursor(int mode)
-{
- static Dot c[2];
- int alt = IS_SET(Taltscreen);
-
- if (mode == CursorSave) {
- c[alt] = term.c;
- } else if (mode == CursorLoad) {
- term.c = c[alt];
- tmoveto(c[alt].x, c[alt].y);
- }
-}
-
-void
-treset(void)
-{
- uint i;
-
- term.c = (Dot){{
- .mode = Gnil,
- .fg = defaultfg,
- .bg = defaultbg
- }, .x = 0, .y = 0, .state = CursorDefault};
-
- memset(term.tabs, 0, term.col * sizeof(*term.tabs));
- for (i = tabspaces; i < term.col; i += tabspaces)
- term.tabs[i] = 1;
- term.top = 0;
- term.bot = term.row - 1;
- term.mode = Twrap|Tutf8;
- memset(term.trantbl, CSusa, sizeof(term.trantbl));
- term.charset = 0;
-
- for (i = 0; i < 2; i++) {
- tmoveto(0, 0);
- tcursor(CursorSave);
- tclearregion(0, 0, term.col-1, term.row-1);
- tswapscreen();
- }
-}
-
-void
-tnew(int col, int row)
-{
- term = (Terminal){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } };
- tresize(col, row);
- treset();
-}
-
-void
-tswapscreen(void)
-{
- Letter **tmp = term.line;
-
- term.line = term.alt;
- term.alt = tmp;
- term.mode ^= Taltscreen;
- tfulldirt();
-}
-
-void
-tscrolldown(int orig, int n)
-{
- int i;
- Letter *temp;
-
- LIMIT(n, 0, term.bot-orig+1);
-
- tsetdirt(orig, term.bot-n);
- tclearregion(0, term.bot-n+1, term.col-1, term.bot);
-
- for (i = term.bot; i >= orig+n; i--) {
- temp = term.line[i];
- term.line[i] = term.line[i-n];
- term.line[i-n] = temp;
- }
-
- selscroll(orig, n);
-}
-
-void
-tscrollup(int orig, int n)
-{
- int i;
- Letter *temp;
-
- LIMIT(n, 0, term.bot-orig+1);
-
- tclearregion(0, orig, term.col-1, orig+n-1);
- tsetdirt(orig+n, term.bot);
-
- for (i = orig; i <= term.bot-n; i++) {
- temp = term.line[i];
- term.line[i] = term.line[i+n];
- term.line[i+n] = temp;
- }
-
- selscroll(orig, -n);
-}
-
-void
-selscroll(int orig, int n)
-{
- if (sel.ob.x == -1)
- return;
-
- if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) {
- selclear();
- } else if (BETWEEN(sel.nb.y, orig, term.bot)) {
- sel.ob.y += n;
- sel.oe.y += n;
- if (sel.ob.y < term.top || sel.ob.y > term.bot ||
- sel.oe.y < term.top || sel.oe.y > term.bot) {
- selclear();
- } else {
- selnormalize();
- }
- }
-}
-
-void
-tnewline(int first_col)
-{
- int y = term.c.y;
-
- if (y == term.bot) {
- tscrollup(term.top, 1);
- } else {
- y++;
- }
- tmoveto(first_col ? 0 : term.c.x, y);
-}
-
-void
-csiparse(void)
-{
- char *p = csiescseq.buf, *np;
- long int v;
-
- csiescseq.narg = 0;
- if (*p == '?') {
- csiescseq.priv = 1;
- p++;
- }
-
- csiescseq.buf[csiescseq.len] = '\0';
- while (p < csiescseq.buf+csiescseq.len) {
- np = nil;
- v = strtol(p, &np, 10);
- if (np == p)
- v = 0;
- if (v == LONG_MAX || v == LONG_MIN)
- v = -1;
- csiescseq.arg[csiescseq.narg++] = v;
- p = np;
- if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
- break;
- p++;
- }
- csiescseq.mode[0] = *p++;
- csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0';
-}
-
-/* for absolute user moves, when decom is set */
-void
-tmoveato(int x, int y)
-{
- tmoveto(x, y + ((term.c.state & CursorOrigin) ? term.top: 0));
-}
-
-void
-tmoveto(int x, int y)
-{
- int miny, maxy;
-
- if (term.c.state & CursorOrigin) {
- miny = term.top;
- maxy = term.bot;
- } else {
- miny = 0;
- maxy = term.row - 1;
- }
- term.c.state &= ~CursorWrap;
- term.c.x = LIMIT(x, 0, term.col-1);
- term.c.y = LIMIT(y, miny, maxy);
-}
-
-void
-tsetchar(rune u, Letter *attr, int x, int y)
-{
- static char *vt100_0[62] = { /* 0x41 - 0x7e */
- "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
- 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
- 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
- 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */
- "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */
- "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */
- "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */
- "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */
- };
-
- /*
- * table is proudly stolen from rxvt.
- */
- if (term.trantbl[term.charset] == CSgfx0 &&
- BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41])
- utf8·decode(vt100_0[u - 0x41], &u);
-
- if (term.line[y][x].mode & Gwide) {
- if (x+1 < term.col) {
- term.line[y][x+1].u = ' ';
- term.line[y][x+1].mode &= ~Gwdummy;
- }
- } else if (term.line[y][x].mode & Gwdummy) {
- term.line[y][x-1].u = ' ';
- term.line[y][x-1].mode &= ~Gwide;
- }
-
- term.dirty[y] = 1;
- term.line[y][x] = *attr;
- term.line[y][x].u = u;
-}
-
-void
-tclearregion(int x1, int y1, int x2, int y2)
-{
- int x, y, temp;
- Letter *gp;
-
- if(x1 > x2)
- temp = x1, x1 = x2, x2 = temp;
- if(y1 > y2)
- temp = y1, y1 = y2, y2 = temp;
-
- LIMIT(x1, 0, term.col-1);
- LIMIT(x2, 0, term.col-1);
- LIMIT(y1, 0, term.row-1);
- LIMIT(y2, 0, term.row-1);
-
- for(y = y1; y <= y2; y++) {
- term.dirty[y] = 1;
- for(x = x1; x <= x2; x++) {
- gp = &term.line[y][x];
- if(selected(x, y))
- selclear();
- gp->fg = term.c.attr.fg;
- gp->bg = term.c.attr.bg;
- gp->mode = 0;
- gp->u = ' ';
- }
- }
-}
-
-void
-tdeletechar(int n)
-{
- int dst, src, size;
- Letter *line;
-
- LIMIT(n, 0, term.col - term.c.x);
-
- dst = term.c.x;
- src = term.c.x + n;
- size = term.col - src;
- line = term.line[term.c.y];
-
- memmove(&line[dst], &line[src], size * sizeof(Letter));
- tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
-}
-
-void
-tinsertblank(int n)
-{
- int dst, src, size;
- Letter *line;
-
- LIMIT(n, 0, term.col - term.c.x);
-
- dst = term.c.x + n;
- src = term.c.x;
- size = term.col - dst;
- line = term.line[term.c.y];
-
- memmove(&line[dst], &line[src], size * sizeof(Letter));
- tclearregion(src, term.c.y, dst - 1, term.c.y);
-}
-
-void
-tinsertblankline(int n)
-{
- if (BETWEEN(term.c.y, term.top, term.bot))
- tscrolldown(term.c.y, n);
-}
-
-void
-tdeleteline(int n)
-{
- if (BETWEEN(term.c.y, term.top, term.bot))
- tscrollup(term.c.y, n);
-}
-
-int32_t
-tdefcolor(int *attr, int *npar, int l)
-{
- int32_t idx = -1;
- uint r, g, b;
-
- switch (attr[*npar + 1]) {
- case 2: /* direct color in RGB space */
- if (*npar + 4 >= l) {
- fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", *npar);
- break;
- }
- r = attr[*npar + 2];
- g = attr[*npar + 3];
- b = attr[*npar + 4];
- *npar += 4;
- if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255))
- fprintf(stderr, "erresc(38): bad rgb color (%u,%u,%u)\n", r, g, b);
- else
- idx = TRUECOLOR(r, g, b);
- break;
- case 5: /* indexed color */
- if (*npar + 2 >= l) {
- fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", *npar);
- break;
- }
- *npar += 2;
- if (!BETWEEN(attr[*npar], 0, 255))
- fprintf(stderr, "erresc: bad color %d\n", attr[*npar]);
- else
- idx = attr[*npar];
- break;
- case 0: /* implemented defined (only foreground) */
- case 1: /* transparent */
- case 3: /* direct color in CMY space */
- case 4: /* direct color in CMYK space */
- default:
- fprintf(stderr, "erresc(38): gfx attr %d unknown\n", attr[*npar]);
- break;
- }
-
- return idx;
-}
-
-void
-tsetattr(int *attr, int l)
-{
- int i;
- int32_t idx;
-
- for (i = 0; i < l; i++) {
- switch (attr[i]) {
- case 0:
- term.c.attr.mode &= ~(
- Gbold |
- Gfaint |
- Gitalic |
- Gunline |
- Gblink |
- Greverse |
- Ginvisible |
- Gstruck );
- term.c.attr.fg = defaultfg;
- term.c.attr.bg = defaultbg;
- break;
- case 1:
- term.c.attr.mode |= Gbold;
- break;
- case 2:
- term.c.attr.mode |= Gfaint;
- break;
- case 3:
- term.c.attr.mode |= Gitalic;
- break;
- case 4:
- term.c.attr.mode |= Gunline;
- break;
- case 5: /* slow blink */
- /* FALLTHROUGH */
- case 6: /* rapid blink */
- term.c.attr.mode |= Gblink;
- break;
- case 7:
- term.c.attr.mode |= Greverse;
- break;
- case 8:
- term.c.attr.mode |= Ginvisible;
- break;
- case 9:
- term.c.attr.mode |= Gstruck;
- break;
- case 22:
- term.c.attr.mode &= ~(Gbold | Gfaint);
- break;
- case 23:
- term.c.attr.mode &= ~Gitalic;
- break;
- case 24:
- term.c.attr.mode &= ~Gunline;
- break;
- case 25:
- term.c.attr.mode &= ~Gblink;
- break;
- case 27:
- term.c.attr.mode &= ~Greverse;
- break;
- case 28:
- term.c.attr.mode &= ~Ginvisible;
- break;
- case 29:
- term.c.attr.mode &= ~Gstruck;
- break;
- case 38:
- if ((idx = tdefcolor(attr, &i, l)) >= 0)
- term.c.attr.fg = idx;
- break;
- case 39:
- term.c.attr.fg = defaultfg;
- break;
- case 48:
- if ((idx = tdefcolor(attr, &i, l)) >= 0)
- term.c.attr.bg = idx;
- break;
- case 49:
- term.c.attr.bg = defaultbg;
- break;
- default:
- if (BETWEEN(attr[i], 30, 37)) {
- term.c.attr.fg = attr[i] - 30;
- } else if (BETWEEN(attr[i], 40, 47)) {
- term.c.attr.bg = attr[i] - 40;
- } else if (BETWEEN(attr[i], 90, 97)) {
- term.c.attr.fg = attr[i] - 90 + 8;
- } else if (BETWEEN(attr[i], 100, 107)) {
- term.c.attr.bg = attr[i] - 100 + 8;
- } else {
- fprintf(stderr,
- "erresc(default): gfx attr %d unknown\n",
- attr[i]);
- csidump();
- }
- break;
- }
- }
-}
-
-void
-tsetscroll(int t, int b)
-{
- int temp;
-
- LIMIT(t, 0, term.row-1);
- LIMIT(b, 0, term.row-1);
- if (t > b) {
- temp = t;
- t = b;
- b = temp;
- }
- term.top = t;
- term.bot = b;
-}
-
-void
-tsetmode(int priv, int set, int *args, int narg)
-{
- int alt, *lim;
-
- for (lim = args + narg; args < lim; ++args) {
- if (priv) {
- switch (*args) {
- case 1: /* DECCKM -- Cursor key */
- xsetmode(set, Wappcursor);
- break;
- case 5: /* DECSCNM -- Reverse video */
- xsetmode(set, Wreverse);
- break;
- case 6: /* DECOM -- Origin */
- MODBIT(term.c.state, set, CursorOrigin);
- tmoveato(0, 0);
- break;
- case 7: /* DECAWM -- Auto wrap */
- MODBIT(term.mode, set, Twrap);
- break;
- case 0: /* Error (IGNORED) */
- case 2: /* DECANM -- ANSI/VT52 (IGNORED) */
- case 3: /* DECCOLM -- Column (IGNORED) */
- case 4: /* DECSCLM -- Scroll (IGNORED) */
- case 8: /* DECARM -- Auto repeat (IGNORED) */
- case 18: /* DECPFF -- Printer feed (IGNORED) */
- case 19: /* DECPEX -- Printer extent (IGNORED) */
- case 42: /* DECNRCM -- National characters (IGNORED) */
- case 12: /* att610 -- Start blinking cursor (IGNORED) */
- break;
- case 25: /* DECTCEM -- Text Cursor Enable Mode */
- xsetmode(!set, Whide);
- break;
- case 9: /* X10 mouse compatibility mode */
- xsetpointermotion(0);
- xsetmode(0, Wmouse);
- xsetmode(set, Wmousex10);
- break;
- case 1000: /* 1000: report button press */
- xsetpointermotion(0);
- xsetmode(0, Wmouse);
- xsetmode(set, Wmousebtn);
- break;
- case 1002: /* 1002: report motion on button press */
- xsetpointermotion(0);
- xsetmode(0, Wmouse);
- xsetmode(set, Wmousemotion);
- break;
- case 1003: /* 1003: enable all mouse motions */
- xsetpointermotion(set);
- xsetmode(0, Wmouse);
- xsetmode(set, Wmousemany);
- break;
- case 1004: /* 1004: send focus events to tty */
- xsetmode(set, Wfocus);
- break;
- case 1006: /* 1006: extended reporting mode */
- xsetmode(set, Wmousesgr);
- break;
- case 1034:
- xsetmode(set, W8bit);
- break;
- case 1049: /* swap screen & set/restore cursor as xterm */
- if (!allowaltscreen)
- break;
- tcursor((set) ? CursorSave : CursorLoad);
- /* FALLTHROUGH */
- case 47: /* swap screen */
- case 1047:
- if (!allowaltscreen)
- break;
- alt = IS_SET(Taltscreen);
- if (alt) {
- tclearregion(0, 0, term.col-1,
- term.row-1);
- }
- if (set ^ alt) /* set is always 1 or 0 */
- tswapscreen();
- if (*args != 1049)
- break;
- /* FALLTHROUGH */
- case 1048:
- tcursor((set) ? CursorSave : CursorLoad);
- break;
- case 2004: /* 2004: bracketed paste mode */
- xsetmode(set, Wbrcktpaste);
- break;
- /* Not implemented mouse modes. See comments there. */
- case 1001: /* mouse highlight mode; can hang the
- terminal by design when implemented. */
- case 1005: /* UTF-8 mouse mode; will confuse
- applications not supporting UTF-8
- and luit. */
- case 1015: /* urxvt mangled mouse mode; incompatible
- and can be mistaken for other control
- codes. */
- break;
- default:
- fprintf(stderr,
- "erresc: unknown private set/reset mode %d\n",
- *args);
- break;
- }
- } else {
- switch (*args) {
- case 0: /* Error (IGNORED) */
- break;
- case 2:
- xsetmode(set, Wkbdblock);
- break;
- case 4: /* IRM -- Insertion-replacement */
- MODBIT(term.mode, set, Tinsert);
- break;
- case 12: /* SRM -- Send/Receive */
- MODBIT(term.mode, !set, Techo);
- break;
- case 20: /* LNM -- Linefeed/new line */
- MODBIT(term.mode, set, Tcrlf);
- break;
- default:
- fprintf(stderr,
- "erresc: unknown set/reset mode %d\n",
- *args);
- break;
- }
- }
- }
-}
-
-void
-csihandle(void)
-{
- char buf[40];
- int len;
-
- switch (csiescseq.mode[0]) {
- default:
- unknown:
- fprintf(stderr, "erresc: unknown csi ");
- csidump();
- /* fatal(""); */
- break;
- case '@': /* ICH -- Insert <n> blank char */
- DEFAULT(csiescseq.arg[0], 1);
- tinsertblank(csiescseq.arg[0]);
- break;
- case 'A': /* CUU -- Cursor <n> Up */
- DEFAULT(csiescseq.arg[0], 1);
- tmoveto(term.c.x, term.c.y-csiescseq.arg[0]);
- break;
- case 'B': /* CUD -- Cursor <n> Down */
- case 'e': /* VPR --Cursor <n> Down */
- DEFAULT(csiescseq.arg[0], 1);
- tmoveto(term.c.x, term.c.y+csiescseq.arg[0]);
- break;
- case 'i': /* MC -- Media Copy */
- switch (csiescseq.arg[0]) {
- case 0:
- tdump();
- break;
- case 1:
- tdumpline(term.c.y);
- break;
- case 2:
- tdumpsel();
- break;
- case 4:
- term.mode &= ~Tprint;
- break;
- case 5:
- term.mode |= Tprint;
- break;
- }
- break;
- case 'c': /* DA -- Device Attributes */
- if (csiescseq.arg[0] == 0)
- ttywrite(vtiden, strlen(vtiden), 0);
- break;
- case 'b': /* REP -- if last char is printable print it <n> more times */
- DEFAULT(csiescseq.arg[0], 1);
- if (term.lastc)
- while (csiescseq.arg[0]-- > 0)
- tputc(term.lastc);
- break;
- case 'C': /* CUF -- Cursor <n> Forward */
- case 'a': /* HPR -- Cursor <n> Forward */
- DEFAULT(csiescseq.arg[0], 1);
- tmoveto(term.c.x+csiescseq.arg[0], term.c.y);
- break;
- case 'D': /* CUB -- Cursor <n> Backward */
- DEFAULT(csiescseq.arg[0], 1);
- tmoveto(term.c.x-csiescseq.arg[0], term.c.y);
- break;
- case 'E': /* CNL -- Cursor <n> Down and first col */
- DEFAULT(csiescseq.arg[0], 1);
- tmoveto(0, term.c.y+csiescseq.arg[0]);
- break;
- case 'F': /* CPL -- Cursor <n> Up and first col */
- DEFAULT(csiescseq.arg[0], 1);
- tmoveto(0, term.c.y-csiescseq.arg[0]);
- break;
- case 'g': /* TBC -- Tabulation clear */
- switch (csiescseq.arg[0]) {
- case 0: /* clear current tab stop */
- term.tabs[term.c.x] = 0;
- break;
- case 3: /* clear all the tabs */
- memset(term.tabs, 0, term.col * sizeof(*term.tabs));
- break;
- default:
- goto unknown;
- }
- break;
- case 'G': /* CHA -- Move to <col> */
- case '`': /* HPA */
- DEFAULT(csiescseq.arg[0], 1);
- tmoveto(csiescseq.arg[0]-1, term.c.y);
- break;
- case 'H': /* CUP -- Move to <row> <col> */
- case 'f': /* HVP */
- DEFAULT(csiescseq.arg[0], 1);
- DEFAULT(csiescseq.arg[1], 1);
- tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1);
- break;
- case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */
- DEFAULT(csiescseq.arg[0], 1);
- tputtab(csiescseq.arg[0]);
- break;
- case 'J': /* ED -- Clear screen */
- switch (csiescseq.arg[0]) {
- case 0: /* below */
- tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
- if (term.c.y < term.row-1) {
- tclearregion(0, term.c.y+1, term.col-1,
- term.row-1);
- }
- break;
- case 1: /* above */
- if (term.c.y > 1)
- tclearregion(0, 0, term.col-1, term.c.y-1);
- tclearregion(0, term.c.y, term.c.x, term.c.y);
- break;
- case 2: /* all */
- tclearregion(0, 0, term.col-1, term.row-1);
- break;
- default:
- goto unknown;
- }
- break;
- case 'K': /* EL -- Clear line */
- switch (csiescseq.arg[0]) {
- case 0: /* right */
- tclearregion(term.c.x, term.c.y, term.col-1,
- term.c.y);
- break;
- case 1: /* left */
- tclearregion(0, term.c.y, term.c.x, term.c.y);
- break;
- case 2: /* all */
- tclearregion(0, term.c.y, term.col-1, term.c.y);
- break;
- }
- break;
- case 'S': /* SU -- Scroll <n> line up */
- DEFAULT(csiescseq.arg[0], 1);
- tscrollup(term.top, csiescseq.arg[0]);
- break;
- case 'T': /* SD -- Scroll <n> line down */
- DEFAULT(csiescseq.arg[0], 1);
- tscrolldown(term.top, csiescseq.arg[0]);
- break;
- case 'L': /* IL -- Insert <n> blank lines */
- DEFAULT(csiescseq.arg[0], 1);
- tinsertblankline(csiescseq.arg[0]);
- break;
- case 'l': /* RM -- Reset Mode */
- tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg);
- break;
- case 'M': /* DL -- Delete <n> lines */
- DEFAULT(csiescseq.arg[0], 1);
- tdeleteline(csiescseq.arg[0]);
- break;
- case 'X': /* ECH -- Erase <n> char */
- DEFAULT(csiescseq.arg[0], 1);
- tclearregion(term.c.x, term.c.y,
- term.c.x + csiescseq.arg[0] - 1, term.c.y);
- break;
- case 'P': /* DCH -- Delete <n> char */
- DEFAULT(csiescseq.arg[0], 1);
- tdeletechar(csiescseq.arg[0]);
- break;
- case 'Z': /* CBT -- Cursor Backward Tabulation <n> tab stops */
- DEFAULT(csiescseq.arg[0], 1);
- tputtab(-csiescseq.arg[0]);
- break;
- case 'd': /* VPA -- Move to <row> */
- DEFAULT(csiescseq.arg[0], 1);
- tmoveato(term.c.x, csiescseq.arg[0]-1);
- break;
- case 'h': /* SM -- Set terminal mode */
- tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg);
- break;
- case 'm': /* SGR -- Terminal attribute (color) */
- tsetattr(csiescseq.arg, csiescseq.narg);
- break;
- case 'n': /* DSR – Device Status Report (cursor position) */
- if (csiescseq.arg[0] == 6) {
- len = snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y+1, term.c.x+1);
- ttywrite(buf, len, 0);
- }
- break;
- case 'r': /* DECSTBM -- Set Scrolling Region */
- if (csiescseq.priv) {
- goto unknown;
- } else {
- DEFAULT(csiescseq.arg[0], 1);
- DEFAULT(csiescseq.arg[1], term.row);
- tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1);
- tmoveato(0, 0);
- }
- break;
- case 's': /* DECSC -- Save cursor position (ANSI.SYS) */
- tcursor(CursorSave);
- break;
- case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */
- tcursor(CursorLoad);
- break;
- case ' ':
- switch (csiescseq.mode[1]) {
- case 'q': /* DECSCUSR -- Set Cursor Style */
- if (xsetcursor(csiescseq.arg[0]))
- goto unknown;
- break;
- default:
- goto unknown;
- }
- break;
- }
-}
-
-void
-csidump(void)
-{
- size_t i;
- uint c;
-
- fprintf(stderr, "ESC[");
- for (i = 0; i < csiescseq.len; i++) {
- c = csiescseq.buf[i] & 0xff;
- if (isprint(c)) {
- putc(c, stderr);
- } else if (c == '\n') {
- fprintf(stderr, "(\\n)");
- } else if (c == '\r') {
- fprintf(stderr, "(\\r)");
- } else if (c == 0x1b) {
- fprintf(stderr, "(\\e)");
- } else {
- fprintf(stderr, "(%02x)", c);
- }
- }
- putc('\n', stderr);
-}
-
-void
-csireset(void)
-{
- memset(&csiescseq, 0, sizeof(csiescseq));
-}
-
-void
-strhandle(void)
-{
- char *p = nil, *dec;
- int j, narg, par;
-
- term.esc &= ~(Xstrend|Xstr);
- strparse();
- par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0;
-
- switch (strescseq.type) {
- case ']': /* OSC -- Operating System Command */
- switch (par) {
- case 0:
- case 1:
- case 2:
- if (narg > 1)
- xsettitle(strescseq.args[1]);
- return;
- case 52:
- if (narg > 2 && allowwindowops) {
- dec = base64dec(strescseq.args[2]);
- if (dec) {
- xsetsel(dec);
- xclipcopy();
- } else {
- fprintf(stderr, "erresc: invalid base64\n");
- }
- }
- return;
- case 4: /* color set */
- if (narg < 3)
- break;
- p = strescseq.args[2];
- /* FALLTHROUGH */
- case 104: /* color reset, here p = nil */
- j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
- if (xsetcolorname(j, p)) {
- if (par == 104 && narg <= 1)
- return; /* color reset without parameter */
- fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
- j, p ? p : "(null)");
- } else {
- /*
- * TODO if defaultbg color is changed, borders
- * are dirty
- */
- redraw();
- }
- return;
- }
- break;
- case 'k': /* old title set compatibility */
- xsettitle(strescseq.args[0]);
- return;
- case 'P': /* DCS -- Device Control String */
- term.mode |= Xdcs;
- case '_': /* APC -- Application Program Command */
- case '^': /* PM -- Privacy Message */
- return;
- }
-
- fprintf(stderr, "erresc: unknown str ");
- strdump();
-}
-
-void
-strparse(void)
-{
- int c;
- char *p = strescseq.buf;
-
- strescseq.narg = 0;
- strescseq.buf[strescseq.len] = '\0';
-
- if (*p == '\0')
- return;
-
- while (strescseq.narg < STR_ARG_SIZ) {
- strescseq.args[strescseq.narg++] = p;
- while ((c = *p) != ';' && c != '\0')
- ++p;
- if (c == '\0')
- return;
- *p++ = '\0';
- }
-}
-
-void
-strdump(void)
-{
- size_t i;
- uint c;
-
- fprintf(stderr, "ESC%c", strescseq.type);
- for (i = 0; i < strescseq.len; i++) {
- c = strescseq.buf[i] & 0xff;
- if (c == '\0') {
- putc('\n', stderr);
- return;
- } else if (isprint(c)) {
- putc(c, stderr);
- } else if (c == '\n') {
- fprintf(stderr, "(\\n)");
- } else if (c == '\r') {
- fprintf(stderr, "(\\r)");
- } else if (c == 0x1b) {
- fprintf(stderr, "(\\e)");
- } else {
- fprintf(stderr, "(%02x)", c);
- }
- }
- fprintf(stderr, "ESC\\\n");
-}
-
-void
-strreset(void)
-{
- strescseq = (STREscape){
- .buf = xrealloc(strescseq.buf, STR_BUF_SIZ),
- .siz = STR_BUF_SIZ,
- };
-}
-
-void
-sendbreak(Arg *arg)
-{
- if (tcsendbreak(cmdfd, 0))
- perror("Error sending break");
-}
-
-void
-tprinter(char *s, size_t len)
-{
- if (iofd != -1 && xwrite(iofd, s, len) < 0) {
- perror("Error writing to output file");
- close(iofd);
- iofd = -1;
- }
-}
-
-void
-toggleprinter(Arg *arg)
-{
- term.mode ^= Tprint;
-}
-
-void
-printscreen(Arg *arg)
-{
- tdump();
-}
-
-void
-printsel(Arg *arg)
-{
- tdumpsel();
-}
-
-void
-tdumpsel(void)
-{
- char *ptr;
-
- if ((ptr = getsel())) {
- tprinter(ptr, strlen(ptr));
- free(ptr);
- }
-}
-
-void
-tdumpline(int n)
-{
- char buf[UTFmax];
- Letter *bp, *end;
-
- bp = &term.line[n][0];
- end = &bp[MIN(tlinelen(n), term.col) - 1];
- if (bp != end || bp->u != ' ') {
- for ( ; bp <= end; ++bp)
- tprinter(buf, utf8·encode(&bp->u, buf));
- }
- tprinter("\n", 1);
-}
-
-void
-tdump(void)
-{
- int i;
-
- for (i = 0; i < term.row; ++i)
- tdumpline(i);
-}
-
-void
-tputtab(int n)
-{
- uint x = term.c.x;
-
- if (n > 0) {
- while (x < term.col && n--)
- for (++x; x < term.col && !term.tabs[x]; ++x)
- /* nothing */ ;
- } else if (n < 0) {
- while (x > 0 && n++)
- for (--x; x > 0 && !term.tabs[x]; --x)
- /* nothing */ ;
- }
- term.c.x = LIMIT(x, 0, term.col-1);
-}
-
-void
-tdefutf8(char ascii)
-{
- if (ascii == 'G')
- term.mode |= Tutf8;
- else if (ascii == '@')
- term.mode &= ~Tutf8;
-}
-
-void
-tdeftran(char ascii)
-{
- static char cs[] = "0B";
- static int vcs[] = {CSgfx0, CSusa};
- char *p;
-
- if ((p = strchr(cs, ascii)) == nil) {
- fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
- } else {
- term.trantbl[term.icharset] = vcs[p - cs];
- }
-}
-
-void
-tdectest(char c)
-{
- int x, y;
-
- if (c == '8') { /* DEC screen alignment test. */
- for (x = 0; x < term.col; ++x) {
- for (y = 0; y < term.row; ++y)
- tsetchar('E', &term.c.attr, x, y);
- }
- }
-}
-
-void
-tstrsequence(uchar c)
-{
- strreset();
-
- switch (c) {
- case 0x90: /* DCS -- Device Control String */
- c = 'P';
- term.esc |= Xdcs;
- break;
- case 0x9f: /* APC -- Application Program Command */
- c = '_';
- break;
- case 0x9e: /* PM -- Privacy Message */
- c = '^';
- break;
- case 0x9d: /* OSC -- Operating System Command */
- c = ']';
- break;
- }
- strescseq.type = c;
- term.esc |= Xstr;
-}
-
-void
-tcontrolcode(uchar ascii)
-{
- switch (ascii) {
- case '\t': /* HT */
- tputtab(1);
- return;
- case '\b': /* BS */
- tmoveto(term.c.x-1, term.c.y);
- return;
- case '\r': /* CR */
- tmoveto(0, term.c.y);
- return;
- case '\f': /* LF */
- case '\v': /* VT */
- case '\n': /* LF */
- /* go to first col if the mode is set */
- tnewline(IS_SET(Tcrlf));
- return;
- case '\a': /* BEL */
- if (term.esc & Xstrend) {
- /* backwards compatibility to xterm */
- strhandle();
- } else {
- xbell();
- }
- break;
- case '\033': /* ESC */
- csireset();
- term.esc &= ~(Xcsi|Xaltcs|Xtest);
- term.esc |= Xstart;
- return;
- case '\016': /* SO (LS1 -- Locking shift 1) */
- case '\017': /* SI (LS0 -- Locking shift 0) */
- term.charset = 1 - (ascii - '\016');
- return;
- case '\032': /* SUB */
- tsetchar('?', &term.c.attr, term.c.x, term.c.y);
- /* FALLTHROUGH */
- case '\030': /* CAN */
- csireset();
- break;
- case '\005': /* ENQ (IGNORED) */
- case '\000': /* NUL (IGNORED) */
- case '\021': /* XON (IGNORED) */
- case '\023': /* XOFF (IGNORED) */
- case 0177: /* DEL (IGNORED) */
- return;
- case 0x80: /* TODO: PAD */
- case 0x81: /* TODO: HOP */
- case 0x82: /* TODO: BPH */
- case 0x83: /* TODO: NBH */
- case 0x84: /* TODO: IND */
- break;
- case 0x85: /* NEL -- Next line */
- tnewline(1); /* always go to first col */
- break;
- case 0x86: /* TODO: SSA */
- case 0x87: /* TODO: ESA */
- break;
- case 0x88: /* HTS -- Horizontal tab stop */
- term.tabs[term.c.x] = 1;
- break;
- case 0x89: /* TODO: HTJ */
- case 0x8a: /* TODO: VTS */
- case 0x8b: /* TODO: PLD */
- case 0x8c: /* TODO: PLU */
- case 0x8d: /* TODO: RI */
- case 0x8e: /* TODO: SS2 */
- case 0x8f: /* TODO: SS3 */
- case 0x91: /* TODO: PU1 */
- case 0x92: /* TODO: PU2 */
- case 0x93: /* TODO: STS */
- case 0x94: /* TODO: CCH */
- case 0x95: /* TODO: MW */
- case 0x96: /* TODO: SPA */
- case 0x97: /* TODO: EPA */
- case 0x98: /* TODO: SOS */
- case 0x99: /* TODO: SGCI */
- break;
- case 0x9a: /* DECID -- Identify Terminal */
- ttywrite(vtiden, strlen(vtiden), 0);
- break;
- case 0x9b: /* TODO: CSI */
- case 0x9c: /* TODO: ST */
- break;
- case 0x90: /* DCS -- Device Control String */
- case 0x9d: /* OSC -- Operating System Command */
- case 0x9e: /* PM -- Privacy Message */
- case 0x9f: /* APC -- Application Program Command */
- tstrsequence(ascii);
- return;
- }
- /* only CAN, SUB, \a and C1 chars interrupt a sequence */
- term.esc &= ~(Xstrend|Xstr);
-}
-
-/*
- * returns 1 when the sequence is finished and it hasn't to read
- * more characters for this sequence, otherwise 0
- */
-int
-eschandle(uchar ascii)
-{
- switch (ascii) {
- case '[':
- term.esc |= Xcsi;
- return 0;
- case '#':
- term.esc |= Xtest;
- return 0;
- case '%':
- term.esc |= Xutf8;
- return 0;
- case 'P': /* DCS -- Device Control String */
- case '_': /* APC -- Application Program Command */
- case '^': /* PM -- Privacy Message */
- case ']': /* OSC -- Operating System Command */
- case 'k': /* old title set compatibility */
- tstrsequence(ascii);
- return 0;
- case 'n': /* LS2 -- Locking shift 2 */
- case 'o': /* LS3 -- Locking shift 3 */
- term.charset = 2 + (ascii - 'n');
- break;
- case '(': /* GZD4 -- set primary charset G0 */
- case ')': /* G1D4 -- set secondary charset G1 */
- case '*': /* G2D4 -- set tertiary charset G2 */
- case '+': /* G3D4 -- set quaternary charset G3 */
- term.icharset = ascii - '(';
- term.esc |= Xaltcs;
- return 0;
- case 'D': /* IND -- Linefeed */
- if (term.c.y == term.bot) {
- tscrollup(term.top, 1);
- } else {
- tmoveto(term.c.x, term.c.y+1);
- }
- break;
- case 'E': /* NEL -- Next line */
- tnewline(1); /* always go to first col */
- break;
- case 'H': /* HTS -- Horizontal tab stop */
- term.tabs[term.c.x] = 1;
- break;
- case 'M': /* RI -- Reverse index */
- if (term.c.y == term.top) {
- tscrolldown(term.top, 1);
- } else {
- tmoveto(term.c.x, term.c.y-1);
- }
- break;
- case 'Z': /* DECID -- Identify Terminal */
- ttywrite(vtiden, strlen(vtiden), 0);
- break;
- case 'c': /* RIS -- Reset to initial state */
- treset();
- resettitle();
- xloadcols();
- break;
- case '=': /* DECPAM -- Application keypad */
- xsetmode(1, Wappkeypad);
- break;
- case '>': /* DECPNM -- Normal keypad */
- xsetmode(0, Wappkeypad);
- break;
- case '7': /* DECSC -- Save Cursor */
- tcursor(CursorSave);
- break;
- case '8': /* DECRC -- Restore Cursor */
- tcursor(CursorLoad);
- break;
- case '\\': /* ST -- String Terminator */
- if (term.esc & Xstrend)
- strhandle();
- break;
- default:
- fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
- (uchar) ascii, isprint(ascii)? ascii:'.');
- break;
- }
- return 1;
-}
-
-void
-tputc(rune u)
-{
- char c[UTFmax];
- int control;
- int width, len;
- rune nu;
- Letter *gp;
-
- control = ISCONTROL(u);
- if (u < 127 || !IS_SET(Tutf8 | Tsixel)) {
- c[0] = u;
- width = len = 1;
- } else {
- len = utf8·encode(&u, c);
- if(!control && (width = wcwidth(u)) == -1)
- width = 1;
- }
-
- /* combining characters */
- if(!width){
- if(term.c.x > 0)
- gp = &term.line[term.c.y][term.c.x-1];
- else if(term.c.y > 0)
- gp = &term.line[term.c.y-1][term.col-1];
- else
- return;
-
-#if 0
- if(!hb_unicode_compose(hb_unicode_funcs_get_default(),gp->u, u, &nu)) {
- return;
- }
-#endif
-
- gp->u = nu;
- return;
- }
-
- if (IS_SET(Tprint))
- tprinter(c, len);
-
- /*
- * STR sequence must be checked before anything else
- * because it uses all following characters until it
- * receives a ESC, a SUB, a ST or any other C1 control
- * character.
- */
- if(term.esc & Xstr) {
- if (u == '\a' || u == 030 || u == 032 || u == 033 ||
- ISCONTROLC1(u)) {
- term.esc &= ~(Xstart|Xstr|Xdcs);
- if (IS_SET(Tsixel)) {
- /* TODO: render sixel */;
- term.mode &= ~Tsixel;
- return;
- }
- term.esc |= Xstrend;
- goto check_control_code;
- }
-
- if(IS_SET(Tsixel)) {
- /* TODO: implement sixel mode */
- return;
- }
- if (term.esc&Xdcs && strescseq.len == 0 && u == 'q')
- term.mode |= Tsixel;
-
- if (strescseq.len+len >= strescseq.siz) {
- /*
- * Here is a bug in terminals. If the user never sends
- * some code to stop the str or esc command, then st
- * will stop responding. But this is better than
- * silently failing with unknown characters. At least
- * then users will report back.
- *
- * In the case users ever get fixed, here is the code:
- */
- /*
- * term.esc = 0;
- * strhandle();
- */
- if(strescseq.siz > (SIZE_MAX - UTFmax) / 2)
- return;
- strescseq.siz *= 2;
- strescseq.buf = xrealloc(strescseq.buf, strescseq.siz);
- }
-
- memmove(&strescseq.buf[strescseq.len], c, len);
- strescseq.len += len;
- return;
- }
-
-check_control_code:
- /*
- * Actions of control codes must be performed as soon they arrive
- * because they can be embedded inside a control sequence, and
- * they must not cause conflicts with sequences.
- */
- if(control) {
- tcontrolcode(u);
- /*
- * control codes are not shown ever
- */
- if (!term.esc)
- term.lastc = 0;
- return;
- } else if(term.esc & Xstart) {
- if (term.esc & Xcsi) {
- csiescseq.buf[csiescseq.len++] = u;
- if (BETWEEN(u, 0x40, 0x7E)
- || csiescseq.len >= \
- sizeof(csiescseq.buf)-1) {
- term.esc = 0;
- csiparse();
- csihandle();
- }
- return;
- } else if (term.esc & Xutf8) {
- tdefutf8(u);
- } else if (term.esc & Xaltcs) {
- tdeftran(u);
- } else if (term.esc & Xtest) {
- tdectest(u);
- } else {
- if (!eschandle(u))
- return;
- /* sequence already finished */
- }
- term.esc = 0;
- /*
- * All characters which form part of a sequence are not
- * printed
- */
- return;
- }
-
- if(selected(term.c.x, term.c.y))
- selclear();
-
- gp = &term.line[term.c.y][term.c.x];
- if(IS_SET(Twrap) && (term.c.state & CursorWrap)) {
- gp->mode |= Gwrap;
- tnewline(1);
- gp = &term.line[term.c.y][term.c.x];
- }
-
- if(IS_SET(Tinsert) && term.c.x+width < term.col)
- memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Letter));
-
- if(term.c.x+width > term.col) {
- tnewline(1);
- gp = &term.line[term.c.y][term.c.x];
- }
-
- tsetchar(u, &term.c.attr, term.c.x, term.c.y);
- term.lastc = u;
-
- if(width == 2) {
- gp->mode |= Gwrap;
- if (term.c.x+1 < term.col) {
- gp[1].u = '\0';
- gp[1].mode = Gwdummy;
- }
- }
- if(term.c.x+width < term.col) {
- tmoveto(term.c.x+width, term.c.y);
- }else{
- term.c.state |= CursorWrap;
- }
-}
-
-int
-twrite(char *buf, int buflen, int show_ctrl)
-{
- int charsize;
- rune u;
- int n;
-
- for (n = 0; n < buflen; n += charsize) {
- if(IS_SET(Tutf8) && !IS_SET(Tsixel)) {
- /* process a complete utf8 char */
- charsize = utf8·decode(buf + n, &u);
- if(charsize == 0)
- break;
- } else {
- u = buf[n] & 0xFF;
- charsize = 1;
- }
- if(show_ctrl && ISCONTROL(u)) {
- if (u & 0x80) {
- u &= 0x7f;
- tputc('^');
- tputc('[');
- } else if (u != '\n' && u != '\r' && u != '\t') {
- u ^= 0x40;
- tputc('^');
- }
- }
- tputc(u);
- }
- return n;
-}
-
-void
-tresize(int col, int row)
-{
- int i;
- int minrow = MIN(row, term.row);
- int mincol = MIN(col, term.col);
- int *bp;
- Dot c;
-
- if (col < 1 || row < 1) {
- fprintf(stderr,
- "tresize: error resizing to %dx%d\n", col, row);
- return;
- }
-
- /*
- * slide screen to keep cursor where we expect it -
- * tscrollup would work here, but we can optimize to
- * memmove because we're freeing the earlier lines
- */
- for (i = 0; i <= term.c.y - row; i++) {
- free(term.line[i]);
- free(term.alt[i]);
- }
- /* ensure that both src and dst are not nil */
- if (i > 0) {
- memmove(term.line, term.line + i, row * sizeof(Letter*));
- memmove(term.alt, term.alt + i, row * sizeof(Letter*));
- }
- for (i += row; i < term.row; i++) {
- free(term.line[i]);
- free(term.alt[i]);
- }
-
- /* resize to new height */
- term.line = xrealloc(term.line, row * sizeof(Letter*));
- term.alt = xrealloc(term.alt, row * sizeof(Letter*));
- term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
- term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
-
- /* resize each row to new width, zero-pad if needed */
- for (i = 0; i < minrow; i++) {
- term.line[i] = xrealloc(term.line[i], col * sizeof(Letter));
- term.alt[i] = xrealloc(term.alt[i], col * sizeof(Letter));
- }
-
- /* allocate any new rows */
- for (/* i = minrow */; i < row; i++) {
- term.line[i] = xmalloc(col * sizeof(Letter));
- term.alt[i] = xmalloc(col * sizeof(Letter));
- }
- if (col > term.col) {
- bp = term.tabs + term.col;
-
- memset(bp, 0, sizeof(*term.tabs) * (col - term.col));
- while (--bp > term.tabs && !*bp)
- /* nothing */ ;
- for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces)
- *bp = 1;
- }
- /* update terminal size */
- term.col = col;
- term.row = row;
- /* reset scrolling region */
- tsetscroll(0, row-1);
- /* make use of the LIMIT in tmoveto */
- tmoveto(term.c.x, term.c.y);
- /* Clearing both screens (it makes dirty all lines) */
- c = term.c;
- for (i = 0; i < 2; i++) {
- if (mincol < col && 0 < minrow) {
- tclearregion(mincol, 0, col - 1, minrow - 1);
- }
- if (0 < col && minrow < row) {
- tclearregion(0, minrow, col - 1, row - 1);
- }
- tswapscreen();
- tcursor(CursorLoad);
- }
- term.c = c;
-}
-
-void
-resettitle(void)
-{
- xsettitle(nil);
-}
-
-void
-drawregion(int x1, int y1, int x2, int y2)
-{
- int y;
-
- for (y = y1; y < y2; y++) {
- if (!term.dirty[y])
- continue;
-
- term.dirty[y] = 0;
- xdrawline(term.line[y], x1, y, x2);
- }
-}
-
-void
-draw(void)
-{
- int cx = term.c.x, ocx = term.ocx, ocy = term.ocy;
-
- if (!xstartdraw())
- return;
-
- /* adjust cursor position */
- LIMIT(term.ocx, 0, term.col-1);
- LIMIT(term.ocy, 0, term.row-1);
- if (term.line[term.ocy][term.ocx].mode & Gwdummy)
- term.ocx--;
- if (term.line[term.c.y][cx].mode & Gwdummy)
- cx--;
-
- drawregion(0, 0, term.col, term.row);
- xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
- term.ocx, term.ocy, term.line[term.ocy][term.ocx],
- term.line[term.ocy], term.col
- );
- term.ocx = cx;
- term.ocy = term.c.y;
- xfinishdraw();
- if (ocx != term.ocx || ocy != term.ocy)
- xximspot(term.ocx, term.ocy);
-}
-
-void
-redraw(void)
-{
- tfulldirt();
- draw();
-}
diff --git a/sys/cmd/term/term.h b/sys/cmd/term/term.h
deleted file mode 100644
index 6784974..0000000
--- a/sys/cmd/term/term.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/* See LICENSE for license details. */
-#pragma once
-
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <harfbuzz/hb.h>
-
-// -----------------------------------------------------------------------
-// macros
-
-#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b))
-#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
-#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
-#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
-#define GLYPHCMP(a, b) (((a).mode & (~Gwrap) & (~Gliga)) != ((b).mode & (~Gwrap) & (~Gliga)) || \
- (a).fg != (b).fg || (a).bg != (b).bg)
-#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_nsec-t2.tv_nsec)/1E6)
-#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit)))
-#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
-#define IS_TRUECOL(x) (1 << 24 & (x))
-
-#define iota(x) 1 << (x)
-
-/* arbitrary sizes */
-#define ESC_BUF_SIZ (128*UTFmax)
-#define ESC_ARG_SIZ 16
-#define STR_BUF_SIZ ESC_BUF_SIZ
-#define STR_ARG_SIZ ESC_ARG_SIZ
-
-// -----------------------------------------------------------------------
-// constants
-
-enum {
- Gnil,
- Gbold = iota(0),
- Gfaint = iota(1),
- Gitalic = iota(2),
- Gunline = iota(3),
- Gblink = iota(4),
- Greverse = iota(5),
- Ginvisible = iota(6),
- Gstruck = iota(7),
- Gwrap = iota(8),
- Gwide = iota(9),
- Gwdummy = iota(10),
- Gliga = iota(11),
- Gboldfaint = Gbold | Gfaint,
-};
-
-enum {
- SelIdle = 0,
- SelEmpty = 1,
- SelReady = 2
-};
-
-enum {
- SelRegular = 1,
- SelRectangular = 2
-};
-
-enum {
- SnapWord = 1,
- SnapLine = 2
-};
-
-/* cursor state */
-enum {
- CursorSave,
- CursorLoad
-};
-
-/* cursor mode */
-enum {
- CursorDefault = 0,
- CursorWrap = 1,
- CursorOrigin = 2
-};
-
-/* character set */
-enum {
- CSgfx0,
- CSgfx1,
- CSuk,
- CSusa,
- CSmulti,
- CSger,
- CSfin,
-};
-
-/* escape sequences */
-enum {
- Xstart = 1,
- Xcsi = 2,
- Xstr = 4, /* OSC, PM, APC */
- Xaltcs = 8,
- Xstrend = 16, /* a final string was encountered */
- Xtest = 32, /* Enter in test mode */
- Xutf8 = 64,
- Xdcs =128,
-};
-
-/* terminal mode */
-enum {
- Twrap = iota(0),
- Tinsert = iota(1),
- Taltscreen = iota(2),
- Tcrlf = iota(3),
- Techo = iota(4),
- Tprint = iota(5),
- Tutf8 = iota(6),
- Tsixel = iota(7),
-};
-
-/* window mode */
-enum {
- Wvisible = iota(0),
- Wfocused = iota(1),
- Wappkeypad = iota(2),
- Wmousebtn = iota(3),
- Wmousemotion = iota(4),
- Wreverse = iota(5),
- Wkbdblock = iota(6),
- Whide = iota(7),
- Wappcursor = iota(8),
- Wmousesgr = iota(9),
- W8bit = iota(10),
- Wblink = iota(11),
- Wbflink = iota(12),
- Wfocus = iota(13),
- Wmousex10 = iota(14),
- Wmousemany = iota(15),
- Wbrcktpaste = iota(16),
- Wnumlock = iota(17),
- Wmouse = Wmousebtn|Wmousemotion|Wmousex10|Wmousemany,
-};
-
-
-// -----------------------------------------------------------------------
-// types
-
-/* term.c */
-typedef struct Letter Letter;
-typedef struct Dot Dot;
-typedef struct Selection Selection;
-typedef struct Terminal Terminal;
-
-typedef union Arg Arg;
-
-struct Letter {
- rune u; /* character code */
- ushort mode; /* attribute flags */
- uint32 fg; /* foreground */
- uint32 bg; /* background */
-};
-
-struct Dot {
- Letter attr; /* current char attributes */
- int x;
- int y;
- char state;
-};
-
-struct Selection {
- int mode;
- int type;
- int snap;
- /*
- * Selection variables:
- * nb – normalized coordinates of the beginning of the selection
- * ne – normalized coordinates of the end of the selection
- * ob – original coordinates of the beginning of the selection
- * oe – original coordinates of the end of the selection
- */
- struct {
- int x, y;
- } nb, ne, ob, oe;
-
- int alt;
-};
-
-/* Internal representation of the screen */
-struct Terminal {
- int row; /* nb row */
- int col; /* nb col */
- Letter **line; /* screen */
- Letter **alt; /* alternate screen */
- int *dirty; /* dirtyness of lines */
- Dot c; /* cursor */
- int ocx; /* old cursor col */
- int ocy; /* old cursor row */
- int top; /* top scroll limit */
- int bot; /* bottom scroll limit */
- int mode; /* terminal mode flags */
- int esc; /* escape state flags */
- char trantbl[4];/* charset table translation */
- int charset; /* current charset */
- int icharset; /* selected charset for sequence */
- int *tabs;
- rune lastc; /* last printed char outside of sequence, 0 if control */
-};
-
-/* CSI Escape sequence structs */
-/* ESC '[' [[ [<priv>] <arg> [;]] <mode> [<mode>]] */
-typedef struct {
- char buf[ESC_BUF_SIZ]; /* raw string */
- ulong len; /* raw string length */
- char priv;
- int arg[ESC_ARG_SIZ];
- int narg; /* nb of args */
- char mode[2];
-} CSIEscape;
-
-/* STR Escape sequence structs */
-/* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */
-typedef struct {
- char type; /* ESC type ... */
- char *buf; /* allocated raw string */
- size_t siz; /* allocation size */
- size_t len; /* raw string length */
- char *args[STR_ARG_SIZ];
- int narg; /* nb of args */
-} STREscape;
-
-/* x.c */
-typedef struct TermWindow TermWindow;
-
-struct TermWindow {
- int tw, th; /* tty width and height */
- int w, h; /* window width and height */
- int hb, vb; /* horizontal and vertical border (in pix) */
- int ch; /* char height */
- int cw; /* char width */
- int mode; /* window state/mode flags */
- int cursor; /* cursor style */
-};
-
-/* used for user hooks */
-union Arg {
- int i;
- uint ui;
- float f;
- void *v;
- char *s;
-};
-
-// -----------------------------------------------------------------------
-// x.c (backend functions)
-
-void xbell(void);
-void xclipcopy(void);
-void xdrawcursor(int, int, Letter, int, int, Letter, Letter*, int);
-void xdrawline(Letter*, int, int, int);
-void xfinishdraw(void);
-void xloadcols(void);
-int xsetcolorname(int, char *);
-void xsettitle(char *);
-int xsetcursor(int);
-void xsetmode(int, uint);
-void xsetpointermotion(int);
-void xsetsel(char *);
-int xstartdraw(void);
-void xximspot(int, int);
-
-void fatal( char *, ...);
-void redraw(void);
-void draw(void);
-
-void printscreen(Arg *);
-void printsel(Arg *);
-void sendbreak(Arg *);
-void toggleprinter(Arg *);
-
-int tattrset(int);
-void tnew(int, int);
-void tresize(int, int);
-void tsetdirtattr(int);
-void ttyhangup(void);
-int ttynew(char *, char *, char *, char **);
-ulong ttyread(void);
-void ttyresize(int, int);
-void ttywrite( char *, size_t, int);
-
-void resettitle(void);
-
-void selclear(void);
-void selinit(void);
-void selstart(int, int, int);
-void selextend(int, int, int, int);
-int selected(int, int);
-char *getsel(void);
-
-void *xmalloc(size_t);
-void *xrealloc(void *, size_t);
-char *xstrdup(char *);
-
-/* config.h globals */
-extern char *utmp;
-extern char *scroll;
-extern char *stty_args;
-extern char *vtiden;
-extern wchar *worddelimiters;
-extern int allowaltscreen;
-extern int allowwindowops;
-extern char *termname;
-extern uint tabspaces;
-extern uint defaultfg;
-extern uint defaultbg;
-extern float alpha;
diff --git a/sys/cmd/term/term.info b/sys/cmd/term/term.info
deleted file mode 100644
index 7b90344..0000000
--- a/sys/cmd/term/term.info
+++ /dev/null
@@ -1,250 +0,0 @@
-term+mono| simpleterm monocolor,
- acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
- am,
- bce,
- bel=^G,
- blink=\E[5m,
- bold=\E[1m,
- cbt=\E[Z,
- cvvis=\E[?25h,
- civis=\E[?25l,
- clear=\E[H\E[2J,
- cnorm=\E[?12l\E[?25h,
- colors#2,
- cols#80,
- cr=^M,
- csr=\E[%i%p1%d;%p2%dr,
- cub=\E[%p1%dD,
- cub1=^H,
- cud1=^J,
- cud=\E[%p1%dB,
- cuf1=\E[C,
- cuf=\E[%p1%dC,
- cup=\E[%i%p1%d;%p2%dH,
- cuu1=\E[A,
- cuu=\E[%p1%dA,
- dch=\E[%p1%dP,
- dch1=\E[P,
- dim=\E[2m,
- dl=\E[%p1%dM,
- dl1=\E[M,
- ech=\E[%p1%dX,
- ed=\E[J,
- el=\E[K,
- el1=\E[1K,
- enacs=\E)0,
- flash=\E[?5h$<80/>\E[?5l,
- fsl=^G,
- home=\E[H,
- hpa=\E[%i%p1%dG,
- hs,
- ht=^I,
- hts=\EH,
- ich=\E[%p1%d@,
- il1=\E[L,
- il=\E[%p1%dL,
- ind=^J,
- indn=\E[%p1%dS,
- invis=\E[8m,
- is2=\E[4l\E>\E[?1034l,
- it#4,
- kel=\E[1;2F,
- ked=\E[1;5F,
- ka1=\E[1~,
- ka3=\E[5~,
- kc1=\E[4~,
- kc3=\E[6~,
- kbs=\177,
- kcbt=\E[Z,
- kb2=\EOu,
- kcub1=\EOD,
- kcud1=\EOB,
- kcuf1=\EOC,
- kcuu1=\EOA,
- kDC=\E[3;2~,
- kent=\EOM,
- kEND=\E[1;2F,
- kIC=\E[2;2~,
- kNXT=\E[6;2~,
- kPRV=\E[5;2~,
- kHOM=\E[1;2H,
- kLFT=\E[1;2D,
- kRIT=\E[1;2C,
- kind=\E[1;2B,
- kri=\E[1;2A,
- kclr=\E[3;5~,
- kdl1=\E[3;2~,
- kdch1=\E[3~,
- kich1=\E[2~,
- kend=\E[4~,
- kf1=\EOP,
- kf2=\EOQ,
- kf3=\EOR,
- kf4=\EOS,
- kf5=\E[15~,
- kf6=\E[17~,
- kf7=\E[18~,
- kf8=\E[19~,
- kf9=\E[20~,
- kf10=\E[21~,
- kf11=\E[23~,
- kf12=\E[24~,
- kf13=\E[1;2P,
- kf14=\E[1;2Q,
- kf15=\E[1;2R,
- kf16=\E[1;2S,
- kf17=\E[15;2~,
- kf18=\E[17;2~,
- kf19=\E[18;2~,
- kf20=\E[19;2~,
- kf21=\E[20;2~,
- kf22=\E[21;2~,
- kf23=\E[23;2~,
- kf24=\E[24;2~,
- kf25=\E[1;5P,
- kf26=\E[1;5Q,
- kf27=\E[1;5R,
- kf28=\E[1;5S,
- kf29=\E[15;5~,
- kf30=\E[17;5~,
- kf31=\E[18;5~,
- kf32=\E[19;5~,
- kf33=\E[20;5~,
- kf34=\E[21;5~,
- kf35=\E[23;5~,
- kf36=\E[24;5~,
- kf37=\E[1;6P,
- kf38=\E[1;6Q,
- kf39=\E[1;6R,
- kf40=\E[1;6S,
- kf41=\E[15;6~,
- kf42=\E[17;6~,
- kf43=\E[18;6~,
- kf44=\E[19;6~,
- kf45=\E[20;6~,
- kf46=\E[21;6~,
- kf47=\E[23;6~,
- kf48=\E[24;6~,
- kf49=\E[1;3P,
- kf50=\E[1;3Q,
- kf51=\E[1;3R,
- kf52=\E[1;3S,
- kf53=\E[15;3~,
- kf54=\E[17;3~,
- kf55=\E[18;3~,
- kf56=\E[19;3~,
- kf57=\E[20;3~,
- kf58=\E[21;3~,
- kf59=\E[23;3~,
- kf60=\E[24;3~,
- kf61=\E[1;4P,
- kf62=\E[1;4Q,
- kf63=\E[1;4R,
- khome=\E[1~,
- kil1=\E[2;5~,
- krmir=\E[2;2~,
- knp=\E[6~,
- kmous=\E[M,
- kpp=\E[5~,
- lines#24,
- mir,
- msgr,
- npc,
- op=\E[39;49m,
- pairs#64,
- mc0=\E[i,
- mc4=\E[4i,
- mc5=\E[5i,
- rc=\E8,
- rev=\E[7m,
- ri=\EM,
- rin=\E[%p1%dT,
- ritm=\E[23m,
- rmacs=\E(B,
- rmcup=\E[?1049l,
- rmir=\E[4l,
- rmkx=\E[?1l\E>,
- rmso=\E[27m,
- rmul=\E[24m,
- rs1=\Ec,
- rs2=\E[4l\E>\E[?1034l,
- sc=\E7,
- sitm=\E[3m,
- sgr0=\E[0m,
- smacs=\E(0,
- smcup=\E[?1049h,
- smir=\E[4h,
- smkx=\E[?1h\E=,
- smso=\E[7m,
- smul=\E[4m,
- tbc=\E[3g,
- tsl=\E]0;,
- xenl,
- vpa=\E[%i%p1%dd,
-# XTerm extensions
- rmxx=\E[29m,
- smxx=\E[9m,
-# disabled rep for now: causes some issues with older ncurses versions.
-# rep=%p1%c\E[%p2%{1}%-%db,
-# tmux extensions, see TERMINFO EXTENSIONS in tmux(1)
- Tc,
- Ms=\E]52;%p1%s;%p2%s\007,
- Se=\E[2 q,
- Ss=\E[%p1%d q,
-
-term| simpleterm,
- use=term+mono,
- colors#8, pairs#64,
- setab=\E[4%p1%dm,
- setaf=\E[3%p1%dm,
- setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
- setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
- sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m,
-
-term-256color| simpleterm with 256 colors,
- use=term,
- ccc,
- colors#256, pairs#32767,
- oc=\E]104\007,
-# Nicked from xterm-256color
- initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\,
- setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
- setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
-
-term-direct| simpleterm with true color,
- use=term,
- RGB,
-# Nicked from xterm-direct
- colors#0x1000000, pairs#0x7FFFF,
- initc@, op=\E[39;49m,
- setab=\E[%?%p1%{8}%<%t4%p1%d%e48;2;%p1%{65536}%/%d;%p1%{256}
- %/%{255}%&%d;%p1%{255}%&%d%;m,
- setaf=\E[%?%p1%{8}%<%t3%p1%d%e38;2;%p1%{65536}%/%d;%p1%{256}
- %/%{255}%&%d;%p1%{255}%&%d%;m,
- setb@, setf@,
-
-term-meta| simpleterm with meta key,
- use=term,
- km,
- rmm=\E[?1034l,
- smm=\E[?1034h,
- rs2=\E[4l\E>\E[?1034h,
- is2=\E[4l\E>\E[?1034h,
-
-term-meta-256color| simpleterm with meta key and 256 colors,
- use=term-256color,
- km,
- rmm=\E[?1034l,
- smm=\E[?1034h,
- rs2=\E[4l\E>\E[?1034h,
- is2=\E[4l\E>\E[?1034h,
-
-term-bs| simpleterm with backspace as backspace,
- use=term,
- kbs=\010,
- kdch1=\177,
-
-term-bs-256color| simpleterm with backspace as backspace and 256colors,
- use=term-256color,
- kbs=\010,
- kdch1=\177,
diff --git a/sys/cmd/term/util.c b/sys/cmd/term/util.c
deleted file mode 100644
index 3e7d81b..0000000
--- a/sys/cmd/term/util.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <u.h>
-
-static const uchar table[] = {
-#include "nonspacing.h"
-};
-
-static const uchar wtable[] = {
-#include "wide.h"
-};
-
-int
-wcwidth(wchar_t wc)
-{
- if (wc < 0xffU)
- return (wc+1 & 0x7f) >= 0x21 ? 1 : wc ? -1 : 0;
- if ((wc & 0xfffeffffU) < 0xfffe) {
- if ((table[table[wc>>8]*32+((wc&255)>>3)]>>(wc&7))&1)
- return 0;
- if ((wtable[wtable[wc>>8]*32+((wc&255)>>3)]>>(wc&7))&1)
- return 2;
- return 1;
- }
- if ((wc & 0xfffe) == 0xfffe)
- return -1;
- if (wc-0x20000U < 0x20000)
- return 2;
- if (wc == 0xe0001 || wc-0xe0020U < 0x5f || wc-0xe0100U < 0xef)
- return 0;
- return 1;
-}
diff --git a/sys/cmd/term/wide.h b/sys/cmd/term/wide.h
deleted file mode 100644
index e403c9a..0000000
--- a/sys/cmd/term/wide.h
+++ /dev/null
@@ -1,65 +0,0 @@
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,18,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,19,16,20,21,22,16,16,16,23,16,16,24,25,26,27,28,17,
-17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,29,
-17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-17,17,17,17,17,17,17,17,30,16,16,16,16,31,16,16,17,17,17,17,17,17,17,17,17,17,
-17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-17,17,17,17,17,17,17,32,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,16,16,16,33,
-34,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,35,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-17,17,17,17,17,17,36,17,17,37,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,38,39,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,40,41,42,43,44,45,46,47,16,48,49,16,16,16,16,
-16,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,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,6,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,9,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,96,0,0,48,0,0,0,0,0,0,255,15,0,0,0,0,128,0,0,8,
-0,2,12,0,96,48,64,16,0,0,4,44,36,32,12,0,0,0,1,0,0,0,80,184,0,0,0,0,0,0,0,224,
-0,0,0,1,128,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,33,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,255,255,255,251,255,255,255,255,255,255,255,
-255,255,255,15,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,63,0,0,0,255,15,255,255,255,255,
-255,255,255,127,254,255,255,255,255,255,255,255,255,255,127,254,255,255,255,
-255,255,255,255,255,255,255,255,255,224,255,255,255,255,255,254,255,255,255,
-255,255,255,255,255,255,255,127,255,255,255,255,255,7,255,255,255,255,15,0,
-255,255,255,255,255,127,255,255,255,255,255,0,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,
-0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,31,255,255,255,255,255,255,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,
-255,255,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,15,0,0,0,0,0,0,0,0,0,0,0,0,0,255,3,0,0,255,255,255,255,247,255,127,15,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,255,255,255,255,255,255,255,255,255,255,
-255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,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,15,0,0,0,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,7,0,255,255,255,127,0,0,0,0,0,
-0,7,0,240,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-15,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,64,254,7,0,0,0,0,0,0,0,0,0,0,0,0,7,0,255,255,255,
-255,255,15,255,1,3,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,
-1,224,191,255,255,255,255,255,255,255,255,223,255,255,15,0,255,255,255,255,
-255,135,15,0,255,255,17,255,255,255,255,255,255,255,255,127,253,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-159,255,255,255,255,255,255,255,63,0,120,255,255,255,0,0,4,0,0,96,0,16,0,0,0,
-0,0,0,0,0,0,0,248,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,255,255,
-255,255,255,255,255,255,63,16,39,0,0,24,240,7,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,255,15,0,
-0,0,224,255,255,255,255,255,255,255,255,255,255,255,255,123,252,255,255,255,
-255,231,199,255,255,255,231,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,15,7,7,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,
diff --git a/sys/cmd/term/x.c b/sys/cmd/term/x.c
deleted file mode 100644
index 27a2e7a..0000000
--- a/sys/cmd/term/x.c
+++ /dev/null
@@ -1,2070 +0,0 @@
-/* See LICENSE for license details. */
-#include "term.h"
-
-#include <locale.h>
-#include <time.h>
-
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#include <X11/cursorfont.h>
-#include <X11/keysym.h>
-#include <X11/Xft/Xft.h>
-#include <X11/XKBlib.h>
-
-/* harfbuzz additions */
-#if 0
-void hbunloadfonts();
-void hbtransform(XftGlyphFontSpec *, const Letter*, size_t, int, int);
-#endif
-
-/* types used in config.h */
-typedef struct Shortcut Shortcut;
-typedef struct MouseShortcut MouseShortcut;
-typedef struct Key Key;
-
-struct Shortcut{
- uint mod;
- KeySym keysym;
- void (*func)(Arg *);
- Arg arg;
-};
-
-struct MouseShortcut {
- uint mod;
- uint button;
- void (*func)(Arg *);
- Arg arg;
- uint release;
-};
-
-struct Key {
- KeySym k;
- uint mask;
- char *s;
- /* three-valued logic variables: 0 indifferent, 1 on, -1 off */
- schar appkey; /* application keypad */
- schar appcursor; /* application cursor */
-};
-
-/* X modifiers */
-#define XK_ANY_MOD UINT_MAX
-#define XK_NO_MOD 0
-#define XK_SWITCH_MOD (1<<13)
-
-/* function definitions used in config.h */
-static void clipcopy(Arg *);
-static void clippaste(Arg *);
-static void numlock(Arg *);
-static void selpaste(Arg *);
-static void zoom(Arg *);
-static void zoomabs(Arg *);
-static void zoomreset(Arg *);
-static void ttysend(Arg *);
-
-/* config.h for applying patches and the configuration. */
-#include "config.h"
-
-/* XEMBED messages */
-#define XEMBED_FOCUS_IN 4
-#define XEMBED_FOCUS_OUT 5
-
-/* macros */
-#define IS_SET(flag) ((win.mode & (flag)) != 0)
-#define TRUERED(x) (((x) & 0xff0000) >> 8)
-#define TRUEGREEN(x) (((x) & 0xff00))
-#define TRUEBLUE(x) (((x) & 0xff) << 8)
-
-typedef XftDraw *Draw;
-typedef XftColor Color;
-typedef XftGlyphFontSpec GlyphFontSpec;
-
-/* Purely graphic info */
-typedef struct {
- Display *dpy;
- Colormap cmap;
- Window win;
- Drawable buf;
- GlyphFontSpec *specbuf; /* font spec buffer used for rendering */
- Atom xembed, wmdeletewin, netwmname, netwmpid;
- struct {
- XIM xim;
- XIC xic;
- XPoint spot;
- XVaNestedList spotlist;
- } ime;
- Draw draw;
- Visual *vis;
- XSetWindowAttributes attrs;
- int scr;
- int isfixed; /* is fixed geometry? */
- int depth; /* color depth */
- int l, t; /* left and top offset */
- int gm; /* geometry mask */
-} XWindow;
-
-typedef struct {
- Atom xtarget;
- char *primary, *clipboard;
- struct timespec tclick1;
- struct timespec tclick2;
-} XSelection;
-
-/* Font structure */
-#define Font Font_
-typedef struct {
- int height;
- int width;
- int ascent;
- int descent;
- int badslant;
- int badweight;
- short lbearing;
- short rbearing;
- XftFont *match;
- FcFontSet *set;
- FcPattern *pattern;
-} Font;
-
-/* Drawing Context */
-typedef struct {
- Color *col;
- size_t collen;
- Font font, bfont, ifont, ibfont;
- GC gc;
-} DC;
-
-static inline ushort sixd_to_16bit(int);
-static int xmakeglyphfontspecs(XftGlyphFontSpec *, Letter *, int, int, int);
-static void xdrawglyphfontspecs(XftGlyphFontSpec *, Letter, int, int, int);
-static void xdrawglyph(Letter, int, int);
-static void xclear(int, int, int, int);
-static int xgeommasktogravity(int);
-static int ximopen(Display *);
-static void ximinstantiate(Display *, XPointer, XPointer);
-static void ximdestroy(XIM, XPointer, XPointer);
-static int xicdestroy(XIC, XPointer, XPointer);
-static void xinit(int, int);
-static void cresize(int, int);
-static void xresize(int, int);
-static void xhints(void);
-static int xloadcolor(int, char *, Color *);
-static int xloadfont(Font *, FcPattern *);
-static void xloadfonts(char *, double);
-static void xunloadfont(Font *);
-static void xunloadfonts(void);
-static void xsetenv(void);
-static void xseturgency(int);
-static int evcol(XEvent *);
-static int evrow(XEvent *);
-
-static void expose(XEvent *);
-static void visibility(XEvent *);
-static void unmap(XEvent *);
-static void kpress(XEvent *);
-static void cmessage(XEvent *);
-static void resize(XEvent *);
-static void focus(XEvent *);
-static uint buttonmask(uint);
-static int mouseaction(XEvent *, uint);
-static void brelease(XEvent *);
-static void bpress(XEvent *);
-static void bmotion(XEvent *);
-static void propnotify(XEvent *);
-static void selnotify(XEvent *);
-static void selclear_(XEvent *);
-static void selrequest(XEvent *);
-static void setsel(char *, Time);
-static void mousesel(XEvent *, int);
-static void mousereport(XEvent *);
-static char *kmap(KeySym, uint);
-static int match(uint, uint);
-
-static void run(void);
-static void usage(void);
-
-static void (*handler[LASTEvent])(XEvent *) = {
- [KeyPress] = kpress,
- [ClientMessage] = cmessage,
- [ConfigureNotify] = resize,
- [VisibilityNotify] = visibility,
- [UnmapNotify] = unmap,
- [Expose] = expose,
- [FocusIn] = focus,
- [FocusOut] = focus,
- [MotionNotify] = bmotion,
- [ButtonPress] = bpress,
- [ButtonRelease] = brelease,
- [SelectionClear] = selclear_,
- [SelectionNotify] = selnotify,
-/*
- * PropertyNotify is only turned on when there is some INCR transfer happening
- * for the selection retrieval.
- */
- [PropertyNotify] = propnotify,
- [SelectionRequest] = selrequest,
-};
-
-/* Globals */
-static DC dc;
-static XWindow xw;
-static XSelection xsel;
-static TermWindow win;
-
-/* Font Ring Cache */
-enum {
- FRC_NORMAL,
- FRC_ITALIC,
- FRC_BOLD,
- FRC_ITALICBOLD
-};
-
-typedef struct {
- XftFont *font;
- int flags;
- rune unicodep;
-} Fontcache;
-
-/* Fontcache is an array now. A new font will be appended to the array. */
-static Fontcache *frc = nil;
-static int frclen = 0;
-static int frccap = 0;
-static char *usedfont = nil;
-static double usedfontsize = 0;
-static double defaultfontsize = 0;
-
-static char *opt_alpha = nil;
-static char *opt_class = nil;
-static char **opt_cmd = nil;
-static char *opt_embed = nil;
-static char *opt_font = nil;
-static char *opt_io = nil;
-static char *opt_line = nil;
-static char *opt_name = nil;
-static char *opt_title = nil;
-
-static int oldbutton = 3; /* button event on startup: 3 = release */
-
-void
-clipcopy(Arg *_)
-{
- Atom clipboard;
-
- free(xsel.clipboard);
- xsel.clipboard = nil;
-
- if (xsel.primary != nil) {
- xsel.clipboard = xstrdup(xsel.primary);
- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
- XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime);
- }
-}
-
-void
-clippaste(Arg *_)
-{
- Atom clipboard;
-
- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
- XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard,
- xw.win, CurrentTime);
-}
-
-void
-selpaste(Arg *_)
-{
- XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY,
- xw.win, CurrentTime);
-}
-
-void
-numlock(Arg *_)
-{
- win.mode ^= Wnumlock;
-}
-
-void
-zoom(Arg *arg)
-{
- Arg larg;
-
- larg.f = usedfontsize + arg->f;
- zoomabs(&larg);
-}
-
-void
-zoomabs(Arg *arg)
-{
- xunloadfonts();
- xloadfonts(usedfont, arg->f);
- cresize(0, 0);
- redraw();
- xhints();
-}
-
-void
-zoomreset(Arg *arg)
-{
- Arg larg;
-
- if (defaultfontsize > 0) {
- larg.f = defaultfontsize;
- zoomabs(&larg);
- }
-}
-
-void
-ttysend(Arg *arg)
-{
- ttywrite(arg->s, strlen(arg->s), 1);
-}
-
-int
-evcol(XEvent *e)
-{
- int x = e->xbutton.x - win.hb;
- LIMIT(x, 0, win.tw - 1);
- return x / win.cw;
-}
-
-int
-evrow(XEvent *e)
-{
- int y = e->xbutton.y - win.vb;
- LIMIT(y, 0, win.th - 1);
- return y / win.ch;
-}
-
-void
-mousesel(XEvent *e, int done)
-{
- int type, seltype = SelRegular;
- uint state = e->xbutton.state & ~(Button1Mask | forcemousemod);
-
- for (type = 1; type < arrlen(selmasks); ++type) {
- if (match(selmasks[type], state)) {
- seltype = type;
- break;
- }
- }
- selextend(evcol(e), evrow(e), seltype, done);
- if (done)
- setsel(getsel(), e->xbutton.time);
-}
-
-void
-mousereport(XEvent *e)
-{
- int len, x = evcol(e), y = evrow(e),
- button = e->xbutton.button, state = e->xbutton.state;
- char buf[40];
- static int ox, oy;
-
- /* from urxvt */
- if (e->xbutton.type == MotionNotify) {
- if (x == ox && y == oy)
- return;
- if (!IS_SET(Wmousemotion) && !IS_SET(Wmousemany))
- return;
- /* MOUSE_MOTION: no reporting if no button is pressed */
- if (IS_SET(Wmousemotion) && oldbutton == 3)
- return;
-
- button = oldbutton + 32;
- ox = x;
- oy = y;
- } else {
- if (!IS_SET(Wmousesgr) && e->xbutton.type == ButtonRelease) {
- button = 3;
- } else {
- button -= Button1;
- if (button >= 3)
- button += 64 - 3;
- }
- if (e->xbutton.type == ButtonPress) {
- oldbutton = button;
- ox = x;
- oy = y;
- } else if (e->xbutton.type == ButtonRelease) {
- oldbutton = 3;
- /* Wmousex10: no button release reporting */
- if (IS_SET(Wmousex10))
- return;
- if (button == 64 || button == 65)
- return;
- }
- }
-
- if (!IS_SET(Wmousex10)) {
- button += ((state & ShiftMask ) ? 4 : 0)
- + ((state & Mod4Mask ) ? 8 : 0)
- + ((state & ControlMask) ? 16 : 0);
- }
-
- if (IS_SET(Wmousesgr)) {
- len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
- button, x+1, y+1,
- e->xbutton.type == ButtonRelease ? 'm' : 'M');
- } else if (x < 223 && y < 223) {
- len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
- 32+button, 32+x+1, 32+y+1);
- } else {
- return;
- }
-
- ttywrite(buf, len, 0);
-}
-
-uint
-buttonmask(uint button)
-{
- return button == Button1 ? Button1Mask
- : button == Button2 ? Button2Mask
- : button == Button3 ? Button3Mask
- : button == Button4 ? Button4Mask
- : button == Button5 ? Button5Mask
- : 0;
-}
-
-int
-mouseaction(XEvent *e, uint release)
-{
- MouseShortcut *ms;
-
- /* ignore Button<N>mask for Button<N> - it's set on release */
- uint state = e->xbutton.state & ~buttonmask(e->xbutton.button);
-
- for (ms = mshortcuts; ms < mshortcuts + arrlen(mshortcuts); ms++) {
- if (ms->release == release &&
- ms->button == e->xbutton.button &&
- (match(ms->mod, state) || /* exact or forced */
- match(ms->mod, state & ~forcemousemod))) {
- ms->func(&(ms->arg));
- return 1;
- }
- }
-
- return 0;
-}
-
-void
-bpress(XEvent *e)
-{
- struct timespec now;
- int snap;
-
- if (IS_SET(Wmouse) && !(e->xbutton.state & forcemousemod)) {
- mousereport(e);
- return;
- }
-
- if (mouseaction(e, 0))
- return;
-
- if (e->xbutton.button == Button1) {
- /*
- * If the user clicks below predefined timeouts specific
- * snapping behaviour is exposed.
- */
- clock_gettime(CLOCK_MONOTONIC, &now);
- if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) {
- snap = SnapLine;
- } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) {
- snap = SnapWord;
- } else {
- snap = 0;
- }
- xsel.tclick2 = xsel.tclick1;
- xsel.tclick1 = now;
-
- selstart(evcol(e), evrow(e), snap);
- }
-}
-
-void
-propnotify(XEvent *e)
-{
- XPropertyEvent *xpev;
- Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
-
- xpev = &e->xproperty;
- if (xpev->state == PropertyNewValue &&
- (xpev->atom == XA_PRIMARY ||
- xpev->atom == clipboard)) {
- selnotify(e);
- }
-}
-
-void
-selnotify(XEvent *e)
-{
- ulong nitems, ofs, rem;
- int format;
- uchar *data, *last, *repl;
- Atom type, incratom, property = None;
-
- incratom = XInternAtom(xw.dpy, "INCR", 0);
-
- ofs = 0;
- if (e->type == SelectionNotify)
- property = e->xselection.property;
- else if (e->type == PropertyNotify)
- property = e->xproperty.atom;
-
- if (property == None)
- return;
-
- do {
- if (XGetWindowProperty(xw.dpy, xw.win, property, ofs,
- BUFSIZ/4, False, AnyPropertyType,
- &type, &format, &nitems, &rem,
- &data)) {
- fprintf(stderr, "Clipboard allocation failed\n");
- return;
- }
-
- if (e->type == PropertyNotify && nitems == 0 && rem == 0) {
- /*
- * If there is some PropertyNotify with no data, then
- * this is the signal of the selection owner that all
- * data has been transferred. We won't need to receive
- * PropertyNotify events anymore.
- */
- MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask);
- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
- &xw.attrs);
- }
-
- if (type == incratom) {
- /*
- * Activate the PropertyNotify events so we receive
- * when the selection owner does send us the next
- * chunk of data.
- */
- MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
- &xw.attrs);
-
- /*
- * Deleting the property is the transfer start signal.
- */
- XDeleteProperty(xw.dpy, xw.win, (int)property);
- continue;
- }
-
- /*
- * As seen in getsel:
- * Line endings are inconsistent in the terminal and GUI world
- * copy and pasting. When receiving some selection data,
- * replace all '\n' with '\r'.
- * FIXME: Fix the computer world.
- */
- repl = data;
- last = data + nitems * format / 8;
- while ((repl = memchr(repl, '\n', last - repl))) {
- *repl++ = '\r';
- }
-
- if (IS_SET(Wbrcktpaste) && ofs == 0)
- ttywrite("\033[200~", 6, 0);
- ttywrite((char *)data, nitems * format / 8, 1);
- if (IS_SET(Wbrcktpaste) && rem == 0)
- ttywrite("\033[201~", 6, 0);
- XFree(data);
- /* number of 32-bit chunks returned */
- ofs += nitems * format / 32;
- } while (rem > 0);
-
- /*
- * Deleting the property again tells the selection owner to send the
- * next data chunk in the property.
- */
- XDeleteProperty(xw.dpy, xw.win, (int)property);
-}
-
-void
-xclipcopy(void)
-{
- clipcopy(nil);
-}
-
-void
-selclear_(XEvent *e)
-{
- selclear();
-}
-
-void
-selrequest(XEvent *e)
-{
- XSelectionRequestEvent *xsre;
- XSelectionEvent xev;
- Atom xa_targets, string, clipboard;
- char *seltext;
-
- xsre = (XSelectionRequestEvent *) e;
- xev.type = SelectionNotify;
- xev.requestor = xsre->requestor;
- xev.selection = xsre->selection;
- xev.target = xsre->target;
- xev.time = xsre->time;
- if (xsre->property == None)
- xsre->property = xsre->target;
-
- /* reject */
- xev.property = None;
-
- xa_targets = XInternAtom(xw.dpy, "TARGETS", 0);
- if (xsre->target == xa_targets) {
- /* respond with the supported type */
- string = xsel.xtarget;
- XChangeProperty(xsre->display, xsre->requestor, xsre->property,
- XA_ATOM, 32, PropModeReplace,
- (uchar *) &string, 1);
- xev.property = xsre->property;
- } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) {
- /*
- * xith XA_STRING non ascii characters may be incorrect in the
- * requestor. It is not our problem, use utf8.
- */
- clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
- if (xsre->selection == XA_PRIMARY) {
- seltext = xsel.primary;
- } else if (xsre->selection == clipboard) {
- seltext = xsel.clipboard;
- } else {
- fprintf(stderr,
- "Unhandled clipboard selection 0x%lx\n",
- xsre->selection);
- return;
- }
- if (seltext != nil) {
- XChangeProperty(xsre->display, xsre->requestor,
- xsre->property, xsre->target,
- 8, PropModeReplace,
- (uchar *)seltext, strlen(seltext));
- xev.property = xsre->property;
- }
- }
-
- /* all done, send a notification to the listener */
- if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev))
- fprintf(stderr, "Error sending SelectionNotify event\n");
-}
-
-void
-setsel(char *str, Time t)
-{
- if (!str)
- return;
-
- free(xsel.primary);
- xsel.primary = str;
-
- XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
- if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
- selclear();
-}
-
-void
-xsetsel(char *str)
-{
- setsel(str, CurrentTime);
-}
-
-void
-brelease(XEvent *e)
-{
- if (IS_SET(Wmouse) && !(e->xbutton.state & forcemousemod)) {
- mousereport(e);
- return;
- }
-
- if (mouseaction(e, 1))
- return;
- if (e->xbutton.button == Button1)
- mousesel(e, 1);
-}
-
-void
-bmotion(XEvent *e)
-{
- if (IS_SET(Wmouse) && !(e->xbutton.state & forcemousemod)) {
- mousereport(e);
- return;
- }
-
- mousesel(e, 0);
-}
-
-void
-cresize(int width, int height)
-{
- int col, row;
-
- if (width != 0)
- win.w = width;
- if (height != 0)
- win.h = height;
-
- col = (win.w - 2 * borderpx) / win.cw;
- row = (win.h - 2 * borderpx) / win.ch;
- col = MAX(1, col);
- row = MAX(1, row);
-
- win.hb = (win.w - col*win.cw)/2;
- win.vb = (win.h - row*win.ch)/2;
-
- tresize(col, row);
- xresize(col, row);
- ttyresize(win.tw, win.th);
-}
-
-void
-xresize(int col, int row)
-{
- win.tw = col * win.cw;
- win.th = row * win.ch;
-
- XFreePixmap(xw.dpy, xw.buf);
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth);
-
- XftDrawChange(xw.draw, xw.buf);
- xclear(0, 0, win.w, win.h);
-
- /* resize to new width */
- xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec));
-}
-
-ushort
-sixd_to_16bit(int x)
-{
- return x == 0 ? 0 : 0x3737 + 0x2828 * x;
-}
-
-int
-xloadcolor(int i, char *name, Color *ncolor)
-{
- XRenderColor color = { .alpha = 0xffff };
-
- if (!name) {
- if (BETWEEN(i, 16, 255)) { /* 256 color */
- if (i < 6*6*6+16) { /* same colors as xterm */
- color.red = sixd_to_16bit( ((i-16)/36)%6 );
- color.green = sixd_to_16bit( ((i-16)/6) %6 );
- color.blue = sixd_to_16bit( ((i-16)/1) %6 );
- } else { /* greyscale */
- color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16));
- color.green = color.blue = color.red;
- }
- return XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, ncolor);
- } else
- name = colorname[i];
- }
-
- return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor);
-}
-
-void
-xloadcols(void)
-{
- int i;
- static int loaded;
- Color *cp;
-
- if (loaded) {
- for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp)
- XftColorFree(xw.dpy, xw.vis, xw.cmap, cp);
- } else {
- dc.collen = MAX(arrlen(colorname), 256);
- dc.col = xmalloc(dc.collen * sizeof(Color));
- }
-
- for (i = 0; i < dc.collen; i++)
- if (!xloadcolor(i, nil, &dc.col[i])) {
- if (colorname[i])
- fatal("could not allocate color '%s'\n", colorname[i]);
- else
- fatal("could not allocate color %d\n", i);
- }
-
- if (opt_alpha)
- alpha = strtof(opt_alpha, nil);
-
- dc.col[defaultbg].color.alpha = (ushort)(0xffff * alpha);
- dc.col[defaultbg].pixel &= 0x00ffffff;
- dc.col[defaultbg].pixel |= (uchar)(0xff*alpha) << 24;
- loaded = 1;
-}
-
-int
-xsetcolorname(int x, char *name)
-{
- Color ncolor;
-
- if (!BETWEEN(x, 0, dc.collen))
- return 1;
-
- if (!xloadcolor(x, name, &ncolor))
- return 1;
-
- XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
- dc.col[x] = ncolor;
-
- return 0;
-}
-
-/*
- * Absolute coordinates.
- */
-void
-xclear(int x1, int y1, int x2, int y2)
-{
- XftDrawRect(xw.draw, &dc.col[IS_SET(Wreverse)? defaultfg : defaultbg], x1, y1, x2-x1, y2-y1);
-}
-
-void
-xhints(void)
-{
- XClassHint class = {opt_name ? opt_name : termname,
- opt_class ? opt_class : termname};
- XWMHints wm = {.flags = InputHint, .input = 1};
- XSizeHints *sizeh;
-
- sizeh = XAllocSizeHints();
-
- sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize;
- sizeh->height = win.h, sizeh->width = win.w;
- sizeh->height_inc = 1;
- sizeh->width_inc = 1;
- sizeh->base_height = 2 * borderpx;
- sizeh->base_width = 2 * borderpx;
- sizeh->min_height = win.ch + 2 * borderpx;
- sizeh->min_width = win.cw + 2 * borderpx;
- if (xw.isfixed) {
- sizeh->flags |= PMaxSize;
- sizeh->min_width = sizeh->max_width = win.w;
- sizeh->min_height = sizeh->max_height = win.h;
- }
- if (xw.gm & (XValue|YValue)) {
- sizeh->flags |= USPosition | PWinGravity;
- sizeh->x = xw.l;
- sizeh->y = xw.t;
- sizeh->win_gravity = xgeommasktogravity(xw.gm);
- }
-
- XSetWMProperties(xw.dpy, xw.win, nil, nil, nil, 0, sizeh, &wm,
- &class);
- XFree(sizeh);
-}
-
-int
-xgeommasktogravity(int mask)
-{
- switch (mask & (XNegative|YNegative)) {
- case 0:
- return NorthWestGravity;
- case XNegative:
- return NorthEastGravity;
- case YNegative:
- return SouthWestGravity;
- }
-
- return SouthEastGravity;
-}
-
-int
-xloadfont(Font *f, FcPattern *pattern)
-{
- FcPattern *configured;
- FcPattern *match;
- FcResult result;
- XGlyphInfo extents;
- int wantattr, haveattr;
-
- /*
- * Manually configure instead of calling XftMatchFont
- * so that we can use the configured pattern for
- * "missing glyph" lookups.
- */
- configured = FcPatternDuplicate(pattern);
- if (!configured)
- return 1;
-
- FcConfigSubstitute(nil, configured, FcMatchPattern);
- XftDefaultSubstitute(xw.dpy, xw.scr, configured);
-
- match = FcFontMatch(nil, configured, &result);
- if (!match) {
- FcPatternDestroy(configured);
- return 1;
- }
-
- if (!(f->match = XftFontOpenPattern(xw.dpy, match))) {
- FcPatternDestroy(configured);
- FcPatternDestroy(match);
- return 1;
- }
-
- if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) ==
- XftResultMatch)) {
- /*
- * Check if xft was unable to find a font with the appropriate
- * slant but gave us one anyway. Try to mitigate.
- */
- if ((XftPatternGetInteger(f->match->pattern, "slant", 0,
- &haveattr) != XftResultMatch) || haveattr < wantattr) {
- f->badslant = 1;
- fputs("font slant does not match\n", stderr);
- }
- }
-
- if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) ==
- XftResultMatch)) {
- if ((XftPatternGetInteger(f->match->pattern, "weight", 0,
- &haveattr) != XftResultMatch) || haveattr != wantattr) {
- f->badweight = 1;
- fputs("font weight does not match\n", stderr);
- }
- }
-
- XftTextExtentsUtf8(xw.dpy, f->match,
- (const FcChar8 *) ascii_printable,
- strlen(ascii_printable), &extents);
-
- f->set = nil;
- f->pattern = configured;
-
- f->ascent = f->match->ascent;
- f->descent = f->match->descent;
- f->lbearing = 0;
- f->rbearing = f->match->max_advance_width;
-
- f->height = f->ascent + f->descent;
- f->width = DIVCEIL(extents.xOff, strlen(ascii_printable));
-
- return 0;
-}
-
-void
-xloadfonts(char *fontstr, double fontsize)
-{
- FcPattern *pattern;
- double fontval;
-
- if (fontstr[0] == '-')
- pattern = XftXlfdParse(fontstr, False, False);
- else
- pattern = FcNameParse((FcChar8 *)fontstr);
-
- if (!pattern)
- fatal("can't open font %s\n", fontstr);
-
- if (fontsize > 1) {
- FcPatternDel(pattern, FC_PIXEL_SIZE);
- FcPatternDel(pattern, FC_SIZE);
- FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize);
- usedfontsize = fontsize;
- } else {
- if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) ==
- FcResultMatch) {
- usedfontsize = fontval;
- } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) ==
- FcResultMatch) {
- usedfontsize = -1;
- } else {
- /*
- * Default font size is 12, if none given. This is to
- * have a known usedfontsize value.
- */
- FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12);
- usedfontsize = 12;
- }
- defaultfontsize = usedfontsize;
- }
-
- if (xloadfont(&dc.font, pattern))
- fatal("can't open font %s\n", fontstr);
-
- if (usedfontsize < 0) {
- FcPatternGetDouble(dc.font.match->pattern,
- FC_PIXEL_SIZE, 0, &fontval);
- usedfontsize = fontval;
- if (fontsize == 0)
- defaultfontsize = fontval;
- }
-
- /* Setting character width and height. */
- win.cw = ceilf(dc.font.width * cwscale);
- win.ch = ceilf(dc.font.height * chscale);
-
- FcPatternDel(pattern, FC_SLANT);
- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
- if (xloadfont(&dc.ifont, pattern))
- fatal("can't open font %s\n", fontstr);
-
- FcPatternDel(pattern, FC_WEIGHT);
- FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
- if (xloadfont(&dc.ibfont, pattern))
- fatal("can't open font %s\n", fontstr);
-
- FcPatternDel(pattern, FC_SLANT);
- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
- if (xloadfont(&dc.bfont, pattern))
- fatal("can't open font %s\n", fontstr);
-
- FcPatternDestroy(pattern);
-}
-
-void
-xunloadfont(Font *f)
-{
- XftFontClose(xw.dpy, f->match);
- FcPatternDestroy(f->pattern);
- if (f->set)
- FcFontSetDestroy(f->set);
-}
-
-void
-xunloadfonts(void)
-{
-#if 0
- hbunloadfonts();
-#endif
-
- /* Free the loaded fonts in the font cache. */
- while (frclen > 0)
- XftFontClose(xw.dpy, frc[--frclen].font);
-
- xunloadfont(&dc.font);
- xunloadfont(&dc.bfont);
- xunloadfont(&dc.ifont);
- xunloadfont(&dc.ibfont);
-}
-
-int
-ximopen(Display *dpy)
-{
- XIMCallback imdestroy = { .client_data = nil, .callback = ximdestroy };
- XICCallback icdestroy = { .client_data = nil, .callback = xicdestroy };
-
- xw.ime.xim = XOpenIM(xw.dpy, nil, nil, nil);
- if (xw.ime.xim == nil)
- return 0;
-
- if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, nil))
- fprintf(stderr, "XSetIMValues: "
- "Could not set XNDestroyCallback.\n");
-
- xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot,
- nil);
-
- if (xw.ime.xic == nil) {
- xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle,
- XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, xw.win,
- XNDestroyCallback, &icdestroy,
- nil);
- }
- if (xw.ime.xic == nil)
- fprintf(stderr, "XCreateIC: Could not create input context.\n");
-
- return 1;
-}
-
-void
-ximinstantiate(Display *dpy, XPointer client, XPointer call)
-{
- if (ximopen(dpy))
- XUnregisterIMInstantiateCallback(xw.dpy, nil, nil, nil,
- ximinstantiate, nil);
-}
-
-void
-ximdestroy(XIM xim, XPointer client, XPointer call)
-{
- xw.ime.xim = nil;
- XRegisterIMInstantiateCallback(xw.dpy, nil, nil, nil,
- ximinstantiate, nil);
- XFree(xw.ime.spotlist);
-}
-
-int
-xicdestroy(XIC xim, XPointer client, XPointer call)
-{
- xw.ime.xic = nil;
- return 1;
-}
-
-void
-xinit(int cols, int rows)
-{
- XGCValues gcvalues;
- Cursor cursor;
- Window parent;
- XColor xmousefg, xmousebg;
- XWindowAttributes attr;
- XVisualInfo vis;
- pid_t thispid = getpid();
-
- if (!(xw.dpy = XOpenDisplay(nil)))
- fatal("can't open display\n");
-
- if (!(opt_embed && (parent == strtol(opt_embed, nil, 0)))) {
- parent = XRootWindow(xw.dpy, xw.scr);
- xw.depth = 32;
- } else {
- XGetWindowAttributes(xw.dpy, parent, &attr);
- xw.depth = attr.depth;
- }
-
- XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis);
- xw.vis = vis.visual;
- xw.scr = XDefaultScreen(xw.dpy);
-
- /* font */
- if (!FcInit())
- fatal("could not init fontconfig.\n");
-
- usedfont = (opt_font == nil)? font : opt_font;
- xloadfonts(usedfont, 0);
-
- /* colors */
- xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None);
- xloadcols();
-
- /* adjust fixed window geometry */
- win.w = 2 * win.hb + cols*win.cw;
- win.h = 2 * win.vb + rows*win.ch;
-
- if (xw.gm & XNegative)
- xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;
- if (xw.gm & YNegative)
- xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2;
-
- /* Events */
- xw.attrs.background_pixel = dc.col[defaultbg].pixel;
- xw.attrs.border_pixel = dc.col[defaultbg].pixel;
- xw.attrs.bit_gravity = NorthWestGravity;
- xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask
- | ExposureMask | VisibilityChangeMask | StructureNotifyMask
- | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
- xw.attrs.colormap = xw.cmap;
-
- xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t,
- win.w, win.h, 0, xw.depth, InputOutput,
- xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity
- | CWEventMask | CWColormap, &xw.attrs);
-
- memset(&gcvalues, 0, sizeof(gcvalues));
- gcvalues.graphics_exposures = False;
-
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth);
- dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues);
-
- XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel);
- XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
-
- /* font spec buffer */
- xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec));
-
- /* Xft rendering context */
- xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
-
- /* input methods */
- if (!ximopen(xw.dpy))
- XRegisterIMInstantiateCallback(xw.dpy, nil, nil, nil, ximinstantiate, nil);
-
- /* white cursor, black outline */
- cursor = XCreateFontCursor(xw.dpy, mouseshape);
- XDefineCursor(xw.dpy, xw.win, cursor);
-
- if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) {
- xmousefg.red = 0xffff;
- xmousefg.green = 0xffff;
- xmousefg.blue = 0xffff;
- }
-
- if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) {
- xmousebg.red = 0x0000;
- xmousebg.green = 0x0000;
- xmousebg.blue = 0x0000;
- }
-
- XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg);
-
- xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
- xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
- xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False);
- XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1);
-
- xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False);
- XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32,
- PropModeReplace, (uchar *)&thispid, 1);
-
- win.mode = Wnumlock;
- resettitle();
- xhints();
-
- XMapWindow(xw.dpy, xw.win);
- XSync(xw.dpy, False);
-
- clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1);
- clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2);
- xsel.primary = nil;
- xsel.clipboard = nil;
- xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0);
- if (xsel.xtarget == None)
- xsel.xtarget = XA_STRING;
-}
-
-int
-xmakeglyphfontspecs(XftGlyphFontSpec *specs, Letter *glyphs, int len, int x, int y)
-{
- float winx = win.hb + x * win.cw, winy = win.vb + y * win.ch, xp, yp;
- ushort mode, prevmode = USHRT_MAX;
- Font *font = &dc.font;
- int frcflags = FRC_NORMAL;
- float runewidth = win.cw;
- rune r;
- FT_UInt glyphidx;
- FcResult fcres;
- FcPattern *fcpattern, *fontpattern;
- FcFontSet *fcsets[] = { nil };
- FcCharSet *fccharset;
- int i, f, numspecs = 0;
-
- for(i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
- /* Fetch rune and mode for current glyph. */
- r = glyphs[i].u;
- mode = glyphs[i].mode;
-
- /* Skip dummy wide-character spacing. */
-#if 0
- if(mode & Gwdummy)
-#endif
- if(mode == Gwdummy)
- continue;
-
- /* Determine font for glyph if different from previous glyph. */
- if(prevmode != mode){
- prevmode = mode;
- font = &dc.font;
- frcflags = FRC_NORMAL;
- runewidth = win.cw * ((mode & Gwide) ? 2.0f : 1.0f);
- if ((mode & Gitalic) && (mode & Gbold)) {
- font = &dc.ibfont;
- frcflags = FRC_ITALICBOLD;
- } else if (mode & Gitalic) {
- font = &dc.ifont;
- frcflags = FRC_ITALIC;
- } else if (mode & Gbold) {
- font = &dc.bfont;
- frcflags = FRC_BOLD;
- }
- yp = winy + font->ascent;
- }
-
- /* lookup character index with default font. */
- glyphidx = XftCharIndex(xw.dpy, font->match, r);
- if(glyphidx){
- specs[numspecs].font = font->match;
- specs[numspecs].glyph = glyphidx;
- specs[numspecs].x = (short)xp;
- specs[numspecs].y = (short)yp;
- xp += runewidth;
- numspecs++;
- continue;
- }
-
- /* Fallback on font cache, search the font cache for match. */
- for(f = 0; f < frclen; f++) {
- glyphidx = XftCharIndex(xw.dpy, frc[f].font, r);
- /* Everything correct. */
- if (glyphidx && frc[f].flags == frcflags)
- break;
- /* We got a default font for a not found glyph. */
- if (!glyphidx && frc[f].flags == frcflags
- && frc[f].unicodep == r) {
- break;
- }
- }
-
- /* Nothing was found. Use fontconfig to find matching font. */
- if(f >= frclen) {
- if (!font->set)
- font->set = FcFontSort(0, font->pattern,
- 1, 0, &fcres);
- fcsets[0] = font->set;
-
- /*
- * Nothing was found in the cache. Now use
- * some dozen of Fontconfig calls to get the
- * font for one single character.
- *
- * Xft and fontconfig are design failures.
- */
- fcpattern = FcPatternDuplicate(font->pattern);
- fccharset = FcCharSetCreate();
-
- FcCharSetAddChar(fccharset, r);
- FcPatternAddCharSet(fcpattern, FC_CHARSET,
- fccharset);
- FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-
- FcConfigSubstitute(0, fcpattern,
- FcMatchPattern);
- FcDefaultSubstitute(fcpattern);
-
- fontpattern = FcFontSetMatch(0, fcsets, 1,
- fcpattern, &fcres);
-
- /* Allocate memory for the new cache entry. */
- if (frclen >= frccap) {
- frccap += 16;
- frc = xrealloc(frc, frccap * sizeof(Fontcache));
- }
-
- frc[frclen].font = XftFontOpenPattern(xw.dpy,
- fontpattern);
- if (!frc[frclen].font)
- fatal("XftFontOpenPattern failed seeking fallback font: %s\n",
- strerror(errno));
- frc[frclen].flags = frcflags;
- frc[frclen].unicodep = r;
-
- glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, r);
-
- f = frclen;
- frclen++;
-
- FcPatternDestroy(fcpattern);
- FcCharSetDestroy(fccharset);
- }
-
- specs[numspecs].font = frc[f].font;
- specs[numspecs].glyph = glyphidx;
- specs[numspecs].x = (short)xp;
- specs[numspecs].y = (short)yp;
- xp += runewidth;
- numspecs++;
- }
-
-#if 0
- hbtransform(specs, glyphs, len, x, y);
-#endif
-
- return numspecs;
-}
-
-void
-xdrawglyphfontspecs(XftGlyphFontSpec *specs, Letter base, int len, int x, int y)
-{
- int charlen = len * ((base.mode & Gwide) ? 2 : 1);
- int winx = win.hb + x * win.cw, winy = win.vb + y * win.ch, width = charlen * win.cw;
- Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
- XRenderColor colfg, colbg;
- XRectangle r;
-
- /* Fallback on color display for attributes not supported by the font */
- if (base.mode & Gitalic && base.mode & Gbold) {
- if (dc.ibfont.badslant || dc.ibfont.badweight)
- base.fg = defaultattr;
- } else if ((base.mode & Gitalic && dc.ifont.badslant) ||
- (base.mode & Gbold && dc.bfont.badweight)) {
- base.fg = defaultattr;
- }
-
- if (IS_TRUECOL(base.fg)) {
- colfg.alpha = 0xffff;
- colfg.red = TRUERED(base.fg);
- colfg.green = TRUEGREEN(base.fg);
- colfg.blue = TRUEBLUE(base.fg);
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg);
- fg = &truefg;
- } else {
- fg = &dc.col[base.fg];
- }
-
- if (IS_TRUECOL(base.bg)) {
- colbg.alpha = 0xffff;
- colbg.green = TRUEGREEN(base.bg);
- colbg.red = TRUERED(base.bg);
- colbg.blue = TRUEBLUE(base.bg);
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg);
- bg = &truebg;
- } else {
- bg = &dc.col[base.bg];
- }
-
- /* Change basic system colors [0-7] to bright system colors [8-15] */
- if ((base.mode & Gfaint) == Gbold && BETWEEN(base.fg, 0, 7))
- fg = &dc.col[base.fg + 8];
-
- if (IS_SET(Wreverse)) {
- if (fg == &dc.col[defaultfg]) {
- fg = &dc.col[defaultbg];
- } else {
- colfg.red = ~fg->color.red;
- colfg.green = ~fg->color.green;
- colfg.blue = ~fg->color.blue;
- colfg.alpha = fg->color.alpha;
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg);
- fg = &revfg;
- }
-
- if (bg == &dc.col[defaultbg]) {
- bg = &dc.col[defaultfg];
- } else {
- colbg.red = ~bg->color.red;
- colbg.green = ~bg->color.green;
- colbg.blue = ~bg->color.blue;
- colbg.alpha = bg->color.alpha;
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &revbg);
- bg = &revbg;
- }
- }
-
- if ((base.mode & Gboldfaint) == Gfaint) {
- colfg.red = fg->color.red / 2;
- colfg.green = fg->color.green / 2;
- colfg.blue = fg->color.blue / 2;
- colfg.alpha = fg->color.alpha;
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg);
- fg = &revfg;
- }
-
- if (base.mode & Greverse)
- temp = fg, fg = bg, bg = temp;
-
- if (base.mode & Gblink && win.mode & Wblink)
- fg = bg;
-
- if (base.mode & Ginvisible)
- fg = bg;
-
- /* Intelligent cleaning up of the borders. */
- if (x == 0) {
- xclear(0, (y == 0)? 0 : winy, win.vb,
- winy + win.ch +
- ((winy + win.ch >= win.vb + win.th)? win.h : 0));
- }
- if (winx + width >= win.hb + win.tw) {
- xclear(winx + width, (y == 0)? 0 : winy, win.w,
- ((winy + win.ch >= win.vb + win.th)? win.h : (winy + win.ch)));
- }
- if (y == 0)
- xclear(winx, 0, winx + width, win.hb);
- if (winy + win.ch >= win.hb + win.th)
- xclear(winx, winy + win.ch, winx + width, win.h);
-
- /* Clean up the region we want to draw to. */
- XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
-
- /* Set the clip region because Xft is sometimes dirty. */
- r.x = 0, r.y = 0;
- r.height = win.ch;
- r.width = width;
- XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
-
- /* Render the glyphs. */
- XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
-
- /* Render underline and strikethrough. */
- if (base.mode & Gunline)
- XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1);
-
- if (base.mode & Gstruck)
- XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, width, 1);
-
- /* Reset clip to none. */
- XftDrawSetClip(xw.draw, 0);
-}
-
-void
-xdrawglyph(Letter g, int x, int y)
-{
- int numspecs;
- XftGlyphFontSpec spec;
-
- numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
- xdrawglyphfontspecs(&spec, g, numspecs, x, y);
-}
-
-void
-xdrawcursor(int cx, int cy, Letter g, int ox, int oy, Letter og, Letter *line, int len)
-{
- Color drawcol;
-
- /* remove the old cursor */
- if(selected(ox, oy))
- og.mode ^= Greverse;
- xdrawglyph(og, ox, oy);
-#if 0
- xdrawline(line, 0, oy, len);
-#endif
-
- if(IS_SET(Whide))
- return;
-
- /*
- * Select the right color for the right mode.
- */
- g.mode &= Gbold|Gitalic|Gunline|Gstruck|Gwide;
-
- if(IS_SET(Wreverse)) {
- g.mode |= Greverse;
- g.bg = defaultfg;
- if (selected(cx, cy)) {
- drawcol = dc.col[defaultcs];
- g.fg = defaultrcs;
- } else {
- drawcol = dc.col[defaultrcs];
- g.fg = defaultcs;
- }
- } else {
- if(selected(cx, cy)) {
- g.fg = defaultfg;
- g.bg = defaultrcs;
- } else {
- g.fg = og.bg; //defaultbg;
- g.bg = og.fg; //defaultcs;
- if (IS_TRUECOL(og.fg)) {
- drawcol.color.alpha = 0xffff;
- drawcol.color.red = TRUERED(og.fg);
- drawcol.color.green = TRUEGREEN(og.fg);
- drawcol.color.blue = TRUEBLUE(og.fg);
- goto drawnew;
- }
- }
- drawcol = dc.col[g.bg];
- }
-
-drawnew:
- if(IS_SET(Wfocused)) {
- switch (win.cursor) {
- case 7: /* st extension */
- g.u = 0x2603; /* snowman (U+2603) */
- /* fallthrough */
- case 0: /* Blinking Block */
- case 1: /* Blinking Block (Default) */
- case 2: /* Steady Block */
- xdrawglyph(g, cx, cy);
- break;
- case 3: /* Blinking Underline */
- case 4: /* Steady Underline */
- XftDrawRect(xw.draw, &drawcol,
- win.hb + cx * win.cw,
- win.vb + (cy + 1) * win.ch - cursorthickness,
- win.cw, cursorthickness);
- break;
- case 5: /* Blinking bar */
- case 6: /* Steady bar */
- XftDrawRect(xw.draw, &drawcol,
- win.hb + cx * win.cw,
- win.vb + cy * win.ch,
- cursorthickness, win.ch);
- break;
- }
- } else {
- XftDrawRect(xw.draw, &drawcol,
- win.hb + cx * win.cw,
- win.vb + cy * win.ch,
- win.cw - 1, 1);
- XftDrawRect(xw.draw, &drawcol,
- win.hb + cx * win.cw,
- win.vb + cy * win.ch,
- 1, win.ch - 1);
- XftDrawRect(xw.draw, &drawcol,
- win.hb + (cx + 1) * win.cw - 1,
- win.vb + cy * win.ch,
- 1, win.ch - 1);
- XftDrawRect(xw.draw, &drawcol,
- win.hb + cx * win.cw,
- win.vb + (cy + 1) * win.ch - 1,
- win.cw, 1);
- }
-}
-
-void
-xsetenv(void)
-{
- char buf[sizeof(long) * 8 + 1];
-
- snprintf(buf, sizeof(buf), "%lu", xw.win);
- setenv("WINDOWID", buf, 1);
-}
-
-void
-xsettitle(char *p)
-{
- XTextProperty prop;
- DEFAULT(p, opt_title);
-
- Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
- &prop);
- XSetWMName(xw.dpy, xw.win, &prop);
- XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname);
- XFree(prop.value);
-}
-
-int
-xstartdraw(void)
-{
- return IS_SET(Wvisible);
-}
-
-void
-xdrawline(Letter *line, int x1, int y1, int x2)
-{
- int i, x, ox, numspecs;
- Letter base, new;
- XftGlyphFontSpec *specs = xw.specbuf;
-
- numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
- i = ox = 0;
- for (x = x1; x < x2 && i < numspecs; x++) {
- new = line[x];
- if (new.mode == Gwdummy)
- continue;
- if (selected(x, y1))
- new.mode ^= Greverse;
- if (i > 0 && GLYPHCMP(base, new)) {
- xdrawglyphfontspecs(specs, base, i, ox, y1);
- specs += i;
- numspecs -= i;
- i = 0;
- }
- if (i == 0) {
- ox = x;
- base = new;
- }
- i++;
- }
- if (i > 0)
- xdrawglyphfontspecs(specs, base, i, ox, y1);
-}
-
-void
-xfinishdraw(void)
-{
- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w,
- win.h, 0, 0);
- XSetForeground(xw.dpy, dc.gc,
- dc.col[IS_SET(Wreverse)?
- defaultfg : defaultbg].pixel);
-}
-
-void
-xximspot(int x, int y)
-{
- if (xw.ime.xic == nil)
- return;
-
- xw.ime.spot.x = borderpx + x * win.cw;
- xw.ime.spot.y = borderpx + (y + 1) * win.ch;
-
- XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, nil);
-}
-
-void
-expose(XEvent *ev)
-{
- redraw();
-}
-
-void
-visibility(XEvent *ev)
-{
- XVisibilityEvent *e = &ev->xvisibility;
-
- MODBIT(win.mode, e->state != VisibilityFullyObscured, Wvisible);
-}
-
-void
-unmap(XEvent *ev)
-{
- win.mode &= ~Wvisible;
-}
-
-void
-xsetpointermotion(int set)
-{
- MODBIT(xw.attrs.event_mask, set, PointerMotionMask);
- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs);
-}
-
-void
-xsetmode(int set, uint flags)
-{
- int mode = win.mode;
- MODBIT(win.mode, set, flags);
- if ((win.mode & Wreverse) != (mode & Wreverse))
- redraw();
-}
-
-int
-xsetcursor(int cursor)
-{
- if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
- return 1;
- win.cursor = cursor;
- return 0;
-}
-
-void
-xseturgency(int add)
-{
- XWMHints *h = XGetWMHints(xw.dpy, xw.win);
-
- MODBIT(h->flags, add, XUrgencyHint);
- XSetWMHints(xw.dpy, xw.win, h);
- XFree(h);
-}
-
-void
-xbell(void)
-{
- if (!(IS_SET(Wfocused)))
- xseturgency(1);
- if (bellvolume)
- XkbBell(xw.dpy, xw.win, bellvolume, (Atom)nil);
-}
-
-void
-focus(XEvent *ev)
-{
- XFocusChangeEvent *e = &ev->xfocus;
-
- if (e->mode == NotifyGrab)
- return;
-
- if (ev->type == FocusIn) {
- if (xw.ime.xic)
- XSetICFocus(xw.ime.xic);
- win.mode |= Wfocused;
- xseturgency(0);
- if (IS_SET(Wfocus))
- ttywrite("\033[I", 3, 0);
- } else {
- if (xw.ime.xic)
- XUnsetICFocus(xw.ime.xic);
- win.mode &= ~Wfocused;
- if (IS_SET(Wfocus))
- ttywrite("\033[O", 3, 0);
- }
-}
-
-int
-match(uint mask, uint state)
-{
- return mask == XK_ANY_MOD || mask == (state & ~ignoremod);
-}
-
-char*
-kmap(KeySym k, uint state)
-{
- Key *kp;
- int i;
-
- /* Check for mapped keys out of X11 function keys. */
- for (i = 0; i < arrlen(mappedkeys); i++) {
- if (mappedkeys[i] == k)
- break;
- }
- if (i == arrlen(mappedkeys)) {
- if ((k & 0xFFFF) < 0xFD00)
- return nil;
- }
-
- for (kp = key; kp < key + arrlen(key); kp++) {
- if (kp->k != k)
- continue;
-
- if (!match(kp->mask, state))
- continue;
-
- if (IS_SET(Wappkeypad) ? kp->appkey < 0 : kp->appkey > 0)
- continue;
- if (IS_SET(Wnumlock) && kp->appkey == 2)
- continue;
-
- if (IS_SET(Wappcursor) ? kp->appcursor < 0 : kp->appcursor > 0)
- continue;
-
- return kp->s;
- }
-
- return nil;
-}
-
-void
-kpress(XEvent *ev)
-{
- XKeyEvent *e = &ev->xkey;
- KeySym ksym;
- char buf[64], *customkey;
- int len;
- rune c;
- Status status;
- Shortcut *bp;
-
- if (IS_SET(Wkbdblock))
- return;
-
- if (xw.ime.xic)
- len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
- else
- len = XLookupString(e, buf, sizeof buf, &ksym, nil);
- /* 1. shortcuts */
- for (bp = shortcuts; bp < shortcuts + arrlen(shortcuts); bp++) {
- if (ksym == bp->keysym && match(bp->mod, e->state)) {
- bp->func(&(bp->arg));
- return;
- }
- }
-
- /* 2. custom keys from config.h */
- if ((customkey = kmap(ksym, e->state))) {
- ttywrite(customkey, strlen(customkey), 1);
- return;
- }
-
- /* 3. composed string from input method */
- if (len == 0)
- return;
- if (len == 1 && e->state & Mod1Mask) {
- if (IS_SET(W8bit)) {
- if (*buf < 0177) {
- c = *buf | 0x80;
- len = utf8·encode(&c, buf);
- }
- } else {
- buf[1] = buf[0];
- buf[0] = '\033';
- len = 2;
- }
- }
- ttywrite(buf, len, 1);
-}
-
-void
-cmessage(XEvent *e)
-{
- /*
- * See xembed specs
- * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
- */
- if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) {
- if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) {
- win.mode |= Wfocused;
- xseturgency(0);
- } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) {
- win.mode &= ~Wfocused;
- }
- } else if (e->xclient.data.l[0] == xw.wmdeletewin) {
- ttyhangup();
- exit(0);
- }
-}
-
-void
-resize(XEvent *e)
-{
- if (e->xconfigure.width == win.w && e->xconfigure.height == win.h)
- return;
-
- cresize(e->xconfigure.width, e->xconfigure.height);
-}
-
-void
-run(void)
-{
- XEvent ev;
- int w = win.w, h = win.h;
- fd_set rfd;
- int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing;
- struct timespec seltv, *tv, now, lastblink, trigger;
- double timeout;
-
- /* Waiting for window mapping */
- do {
- XNextEvent(xw.dpy, &ev);
- /*
- * This XFilterEvent call is required because of XOpenIM. It
- * does filter out the key event and some client message for
- * the input method too.
- */
- if (XFilterEvent(&ev, None))
- continue;
- if (ev.type == ConfigureNotify) {
- w = ev.xconfigure.width;
- h = ev.xconfigure.height;
- }
- } while (ev.type != MapNotify);
-
- ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd);
- cresize(w, h);
-
- for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) {
- FD_ZERO(&rfd);
- FD_SET(ttyfd, &rfd);
- FD_SET(xfd, &rfd);
-
- if (XPending(xw.dpy))
- timeout = 0; /* existing events might not set xfd */
-
- seltv.tv_sec = timeout / 1E3;
- seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec);
- tv = timeout >= 0 ? &seltv : nil;
-
- if (pselect(MAX(xfd, ttyfd)+1, &rfd, nil, nil, tv, nil) < 0) {
- if (errno == EINTR)
- continue;
- fatal("select failed: %s\n", strerror(errno));
- }
- clock_gettime(CLOCK_MONOTONIC, &now);
-
- if (FD_ISSET(ttyfd, &rfd))
- ttyread();
-
- xev = 0;
- while (XPending(xw.dpy)) {
- xev = 1;
- XNextEvent(xw.dpy, &ev);
- if (XFilterEvent(&ev, None))
- continue;
- if (handler[ev.type])
- (handler[ev.type])(&ev);
- }
-
- /*
- * To reduce flicker and tearing, when new content or event
- * triggers drawing, we first wait a bit to ensure we got
- * everything, and if nothing new arrives - we draw.
- * We start with trying to wait minlatency ms. If more content
- * arrives sooner, we retry with shorter and shorter periods,
- * and eventually draw even without idle after maxlatency ms.
- * Typically this results in low latency while interacting,
- * maximum latency intervals during `cat huge.txt`, and perfect
- * sync with periodic updates from animations/key-repeats/etc.
- */
- if (FD_ISSET(ttyfd, &rfd) || xev) {
- if (!drawing) {
- trigger = now;
- drawing = 1;
- }
- timeout = (maxlatency - TIMEDIFF(now, trigger)) \
- / maxlatency * minlatency;
- if (timeout > 0)
- continue; /* we have time, try to find idle */
- }
-
- /* idle detected or maxlatency exhausted -> draw */
- timeout = -1;
- if (blinktimeout && tattrset(Gblink)) {
- timeout = blinktimeout - TIMEDIFF(now, lastblink);
- if (timeout <= 0) {
- if (-timeout > blinktimeout) /* start visible */
- win.mode |= Wblink;
- win.mode ^= Wblink;
- tsetdirtattr(Gblink);
- lastblink = now;
- timeout = blinktimeout;
- }
- }
-
- draw();
- XFlush(xw.dpy);
- drawing = 0;
- }
-}
-
-void
-usage(void)
-{
- fatal("usage: %s [-aiv] [-c class] [-f font] [-A alpha] [-g geometry]"
- " [-n name] [-o file]\n"
- " [-T title] [-t title] [-w windowid]"
- " [[-e] command [args ...]]\n"
- " %s [-aiv] [-c class] [-f font] [-g geometry]"
- " [-n name] [-o file]\n"
- " [-T title] [-t title] [-w windowid] -l line"
- " [stty_args ...]\n", argv0, argv0);
-}
-
-int
-main(int argc, char *argv[])
-{
- xw.l = xw.t = 0;
- xw.isfixed = False;
- xsetcursor(cursorshape);
-
- ARGBEGIN {
- case 'a':
- allowaltscreen = 0;
- break;
- case 'A':
- opt_alpha = EARGF(usage());
- break;
- case 'c':
- opt_class = EARGF(usage());
- break;
- case 'e':
- if (argc > 0)
- --argc, ++argv;
- goto run;
- case 'f':
- opt_font = EARGF(usage());
- break;
- case 'g':
- xw.gm = XParseGeometry(EARGF(usage()),
- &xw.l, &xw.t, &cols, &rows);
- break;
- case 'i':
- xw.isfixed = 1;
- break;
- case 'o':
- opt_io = EARGF(usage());
- break;
- case 'l':
- opt_line = EARGF(usage());
- break;
- case 'n':
- opt_name = EARGF(usage());
- break;
- case 't':
- case 'T':
- opt_title = EARGF(usage());
- break;
- case 'w':
- opt_embed = EARGF(usage());
- break;
- case 'v':
- fatal("%s " VERSION "\n", argv0);
- break;
- default:
- usage();
- } ARGEND;
-
-run:
- if (argc > 0) /* eat all remaining arguments */
- opt_cmd = argv;
-
- if (!opt_title)
- opt_title = (opt_line || !opt_cmd) ? "term" : opt_cmd[0];
-
- setlocale(LC_CTYPE, "");
- XSetLocaleModifiers("");
-
- cols = MAX(cols, 1);
- rows = MAX(rows, 1);
-
- tnew(cols, rows);
- xinit(cols, rows);
- xsetenv();
- selinit();
-
- run();
-
- return 0;
-}
diff --git a/sys/cmd/walk/rules.mk b/sys/cmd/walk/rules.mk
deleted file mode 100644
index 5b9192d..0000000
--- a/sys/cmd/walk/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := $(d)/walk.c
-BINS_$(d) := $(d)/walk
-
-include share/paths.mk
-
-# Local rules
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/walk/walk.c b/sys/cmd/walk/walk.c
deleted file mode 100644
index c68d6e0..0000000
--- a/sys/cmd/walk/walk.c
+++ /dev/null
@@ -1,84 +0,0 @@
-#include <u.h>
-#include <base.h>
-
-static char buf[4*1024], *c = buf; /* should be greater or equal to PATH_MAX */
-
-static
-void
-flush(void)
-{
- *c = 0;
- puts(buf);
- c = buf;
-}
-
-static
-int
-print(void *data, char *rel, char *abs, io·Stat *info)
-{
-copy:
- while (*abs && c < (arrend(buf)-2))
- *c++ = *abs++;
-
- if (*abs) {
- flush();
- goto copy;
- }
- *c++ = '\n';
-
- return 0;
-}
-
-static
-void
-usage(void)
-{
- fprintf(stderr, "usage: walk [-dlpv] file ...\n");
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- int i, f = fs·nolinks, err, max = 0;
- char *p;
- static fs·Walker walker;
-
- ARGBEGIN{
- case 'd':
- max = atoi(ARGF());
- break;
- case 'l':
- f ^= fs·nolinks;
- break;
- case 'p':
- f |= fs·preorder;
- break;
- case 'v':
- f |= fs·verbose;
- break;
- default:
- usage();
- }ARGEND;
-
- walker.flags = f;
- walker.func = print;
- walker.data = nil;
- walker.max = max;
-
- if (argc == 0) {
- fs·init(&walker, "");
- fs·walk(&walker);
- return(err = walker.err);
- } else {
- err = 0;
- for (i=0; i<argc; i++) {
- fs·init(&walker, argv[i]);
- fs·walk(&walker);
- err += walker.err;
- }
- }
- fs·fini(&walker);
- flush();
- exit(err);
-}
diff --git a/sys/cmd/wm/arg.c b/sys/cmd/wm/arg.c
deleted file mode 100644
index e69de29..0000000
--- a/sys/cmd/wm/arg.c
+++ /dev/null
diff --git a/sys/cmd/wm/client.c b/sys/cmd/wm/client.c
deleted file mode 100644
index 5e0927a..0000000
--- a/sys/cmd/wm/client.c
+++ /dev/null
@@ -1,274 +0,0 @@
-#include "wm.h"
-
-static char broken[] = "broken";
-
-// -----------------------------------------------------------------------
-// scripts
-
-static inline
-void
-grab_client(void)
-{
- if(server.cursor.mode != CursorNormal)
- return;
- if(!(server.grab.client = client_at(server.cursor.dot->x, server.cursor.dot->y)))
- return;
-
- floating(server.grab.client, 1);
-}
-
-void
-move_client(Arg *arg)
-{
- grab_client();
- server.cursor.mode = CursorMove;
-
- server.grab.x = server.cursor.dot->x - server.grab.client->geometry.x;
- server.grab.y = server.cursor.dot->y - server.grab.client->geometry.y;
- wlr_xcursor_manager_set_cursor_image(server.cursor.manager, "fleur", server.cursor.dot);
-}
-
-void
-float_client(Arg *arg)
-{
- Client *client = selected_client();
- wlr_log(WLR_DEBUG, "client selected = %lx", (uintptr)client);
- if(!client)
- return;
-
- floating(client, client->isfloating ? 0 : 1);
-}
-
-void
-resize_client(Arg *arg)
-{
- double x, y;
- struct wlr_box geometry;
-
- grab_client();
- server.cursor.mode = CursorResize;
-
- wlr_xdg_surface_get_geometry(server.grab.client->xdg, &geometry);
-
- x = server.grab.client->geometry.x + geometry.x + geometry.width;
- y = server.grab.client->geometry.y + geometry.y + geometry.height;
-
- server.grab.x = server.cursor.dot->x - x;
- server.grab.y = server.cursor.dot->y - y;
-
- server.grab.box = geometry;
- server.grab.box.x += server.grab.client->geometry.x;
- server.grab.box.y += server.grab.client->geometry.y;
-}
-
-// -----------------------------------------------------------------------
-// core
-
-static inline
-void
-activate(struct wlr_surface *surface, int state)
-{
-}
-
-void
-focus(Client *client, int lift)
-{
- struct wlr_xdg_surface *xdg;
- struct wlr_surface *old, *new;
- struct wlr_keyboard *keyboard;
-
- if(!client) {
- wlr_seat_keyboard_notify_clear_focus(server.input.seat);
- return;
- }
-
- old = server.input.seat->keyboard_state.focused_surface;
-
- if(lift) {
- wl_list_remove(&client->stack);
- wl_list_insert(&server.client.stack, &client->stack);
- }
-
- new = client->xdg->surface;
- if(old==new)
- return;
-
- wl_list_remove(&client->focus);
- wl_list_insert(&server.client.focus, &client->focus);
- server.monitor.selected = client->monitor;
- client->isurgent = 0;
-
- if(old) {
- if(wlr_surface_is_xdg_surface(old)) {
- xdg = wlr_xdg_surface_from_wlr_surface(old);
- wlr_xdg_toplevel_set_activated(xdg, false);
- }
- }
-
- keyboard = wlr_seat_get_keyboard(server.input.seat);
-
- wlr_seat_keyboard_notify_enter(server.input.seat, new,
- keyboard->keycodes,
- keyboard->num_keycodes,
- &keyboard->modifiers
- );
-
- wlr_xdg_toplevel_set_activated(client->xdg, true);
-}
-
-Client*
-client_at(double x, double y)
-{
- Client *client;
- wl_list_for_each(client, &server.client.stack, stack)
- if(VISIBLE_ON(client, client->monitor) && wlr_box_contains_point(&client->geometry, x, y))
- return client;
- return nil;
-}
-
-static
-int
-has(Client *client, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy)
-{
- double x, y, vsx = lx - client->geometry.x, vsy = ly - client->geometry.y;
- struct wlr_surface *find = nil;
-
- find = wlr_xdg_surface_surface_at(client->xdg, vsx, vsy, &x, &y);
- if(find) {
- *sx = x;
- *sy = y;
- *surface = find;
- return true;
- }
-
- return false;
-}
-
-struct wlr_surface *
-client_surface_at(Client *client, double cx, double cy, double *sx, double *sy)
-{
- return wlr_xdg_surface_surface_at(client->xdg, cx, cy, sx, sy);
-}
-
-
-static
-void
-constrain(Client *client, struct wlr_box *box)
-{
- client->geometry.width = MAX(1, client->geometry.width);
- client->geometry.height = MAX(1, client->geometry.height);
-
- if(client->geometry.x >= box->x + box->width)
- client->geometry.x = box->x + box->width - client->geometry.width;
- if(client->geometry.y >= box->y + box->height)
- client->geometry.y = box->y + box->height - client->geometry.height;
- if(client->geometry.x + client->geometry.width + 2*client->border <= box->x)
- client->geometry.x = box->x;
- if(client->geometry.y + client->geometry.height + 2*client->border <= box->y)
- client->geometry.y = box->y;
-}
-
-void
-resize(Client *client, int x, int y, int w, int h, int interact)
-{
- struct wlr_box *box = interact ? &server.monitor.geometry : &client->monitor->window;
-
- client->geometry.x = x;
- client->geometry.y = y;
- client->geometry.width = w;
- client->geometry.height = h;
-
- constrain(client, box);
-
- client->resize = wlr_xdg_toplevel_set_size(client->xdg,
- client->geometry.width - 2*client->border,
- client->geometry.height - 2*client->border
- );
-}
-
-void
-attach(Client *client, Monitor *monitor, uint tags)
-{
- Monitor *old = client->monitor;
- if(old == monitor)
- return;
-
- client->monitor = monitor;
-
- if(old) {
- wlr_surface_send_leave(client->xdg->surface, old->output);
- arrange(old);
- }
-
- if(monitor) {
- /* make sure window actually overlaps with the monitor */
- constrain(client, &monitor->geometry);
- wlr_surface_send_enter(client->xdg->surface, monitor->output);
- client->tags = tags ? tags : monitor->tag.set[monitor->tag.selected];
- arrange(monitor);
- }
-
- focus(focused_client(server.monitor.selected), 1);
-}
-
-void
-rules(Client *client)
-{
- /* rule matching */
- Rule *rule;
- uint i, tags;
- char *id, *title;
- Monitor *monitor, *it;
-
- monitor = server.monitor.selected;
-
- if (!(id=client->xdg->toplevel->app_id))
- id = broken;
- if (!(title=client->xdg->toplevel->title))
- title = broken;
-
- for(tags=0, rule=cfg·rule; rule != cfg·endrule; ++rule) {
- if ((!rule->title || strstr(title, rule->title))
- && (!rule->id || strstr(id, rule->id))) {
- client->isfloating = rule->isfloating;
- tags |= rule->tags;
- i = 0;
- wl_list_for_each(it, &server.monitor.list, link)
- if(rule->monitor == i++)
- monitor = it;
- }
- }
-
- attach(client, monitor, tags);
-}
-
-void
-floating(Client *client, int state)
-{
- wlr_log(WLR_DEBUG, "client %lx, floating = %d", (uintptr)client, state);
- client->isfloating = state;
- arrange(client->monitor);
-}
-
-Client *
-selected_client(void)
-{
- Client *client = wl_container_of(server.client.focus.next, client, focus);
- if(wl_list_empty(&server.client.focus) || !VISIBLE_ON(client, server.monitor.selected))
- return nil;
- return client;
-}
-
-void
-request_activate(struct wl_listener *l, void *data)
-{
- struct wlr_xdg_activation_v1_request_activate_event *event = data;
- Client *client;
-
- if (!wlr_surface_is_xdg_surface(event->surface))
- return;
-
- client = wlr_xdg_surface_from_wlr_surface(event->surface)->data;
- if(client != selected_client())
- client->isurgent = 1;
-}
diff --git a/sys/cmd/wm/config.h b/sys/cmd/wm/config.h
deleted file mode 100644
index 1f5ba85..0000000
--- a/sys/cmd/wm/config.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* appearance */
-CONFIG(int, sloppyfocus, 1);
-CONFIG(int, borderpixel, 1);
-CONFIG(float, rootcolor[], {0.3, 0.3, 0.3, 1.0});
-CONFIG(float, bordercolor[], {0.5, 0.5, 0.5, 1.0});
-CONFIG(float, focuscolor[], {1.0, 0.0, 0.0, 1.0});
-
-/* sampling */
-CONFIG(int, repeat_rate, 25);
-CONFIG(int, repeat_delay, 600);
-
-/* tags */
-CONFIG(char*, tags[], { "1", "2", "3", "4", "5", "6", "7", "8", "9" });
-
-/* application specific rules */
-CONFIG(Rule, rule[], {
- /* app_id title tags mask isfloating monitor */
- /* examples:
- { "Gimp", nil, 0, 1, -1 },
- { "firefox", nil, 1 << 8, 0, -1 },
- */
-});
-CONFIG(Rule*, endrule, arrend(cfg·rule));
-
-/* commands */
-CONFIG(char*, termcommand[], { "alacritty", nil });
-CONFIG(char*, menucommand[], { "dmenu-wl_run", nil });
-
-/* layouts */
-CONFIG(Layout, layouts[], {
- /* symbol arrange */
- { "[]=", tile },
- { "><>", nil }, /* no layout function means floating behavior */
-});
-CONFIG(Layout*, endlayout, arrend(cfg·layouts));
-
-/* monitors
- * The order in which monitors are defined determines their position.
- * non-configured monitors are always added to the left. */
-CONFIG(MonitorRule, monitorrule[], {
- /* name layout, x, y, scale, transform master */
- { nil, &cfg·layouts[0], 0, 0, 1, WL_OUTPUT_TRANSFORM_NORMAL, {0.55, 1} },
-});
-CONFIG(MonitorRule*, endmonitorrule, arrend(cfg·monitorrule));
-
-/* keybindings */
-#define MODKEY WLR_MODIFIER_ALT
-#define MOD(a) WLR_MODIFIER_##a
-#define KEY(a) XKB_KEY_##a
-
-CONFIG(Key, binding[], {
- /* modifier key function argument */
- { MODKEY, KEY(Return), spawn, {.v = cfg·termcommand} },
- { MODKEY, KEY(d), spawn, {.v = cfg·menucommand} },
- { MODKEY|MOD(SHIFT), KEY(Q), quit, {.v = nil} },
-});
-CONFIG(Key*, endbinding, arrend(cfg·binding));
-
-#undef MOD
-#undef KEY
-
-/* mouse buttons */
-CONFIG(Button, button[], {
- { MODKEY, BTN_LEFT, move_client, {0} },
- { MODKEY, BTN_MIDDLE, float_client, {0} },
- { MODKEY, BTN_RIGHT, resize_client, {0} },
-});
-CONFIG(Button*, endbutton, arrend(cfg·button));
-
-#undef MODKEY
diff --git a/sys/cmd/wm/input.c b/sys/cmd/wm/input.c
deleted file mode 100644
index 4c6bfd4..0000000
--- a/sys/cmd/wm/input.c
+++ /dev/null
@@ -1,316 +0,0 @@
-#include "wm.h"
-
-// -----------------------------------------------------------------------
-// keyboard
-
-static
-void
-keymodifier(struct wl_listener *l, void *data)
-{
- Keyboard *keyboard = wl_container_of(l, keyboard, event.modify);
-
- wlr_seat_set_keyboard(server.input.seat, keyboard->device);
- wlr_seat_keyboard_notify_modifiers(server.input.seat, &keyboard->device->keyboard->modifiers);
-}
-
-static
-int
-keybinding(uint32 modifier, xkb_keysym_t sym)
-{
- Key *key;
-
- for(key=cfg·binding; key!=cfg·endbinding; ++key) {
- if(modifier == key->modifier && sym == key->sym && key->action){
- key->action(&key->arg);
- return 1;
- }
- }
- return 0;
-}
-
-static
-void
-keypress(struct wl_listener *l, void *data)
-{
- int i,h,n;
- uint32 keycode, modifier;
- const xkb_keysym_t *syms;
- struct Keyboard *keyboard = wl_container_of(l, keyboard, event.press);
- struct wlr_event_keyboard_key *event = data;
-
- keycode = event->keycode + 8;
-
- h = 0;
- n = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, keycode, &syms);
-
- modifier = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
- if(event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
- for(i=0; i<n; i++)
- h=keybinding(modifier, syms[i]);
- }
-
- if(!h) {
- wlr_seat_set_keyboard(server.input.seat, keyboard->device);
- wlr_seat_keyboard_notify_key(server.input.seat, event->time_msec, event->keycode, event->state);
- }
-}
-
-static
-void
-free_keyboard(struct wl_listener *l, void *data)
-{
- struct wlr_input_device *device = data;
- Keyboard *keyboard = device->data;
-
- /* XXX: debug
- wl_list_remove(&keyboard->link);
- wl_list_remove(&keyboard->event.modify.link);
- wl_list_remove(&keyboard->event.press.link);
- wl_list_remove(&keyboard->event.destroy.link);
-
- free(keyboard);
- */
-}
-
-static
-void
-make_keyboard(struct wlr_input_device *device)
-{
- Keyboard *keyboard;
- struct xkb_context *context;
- struct xkb_keymap *keymap;
-
- keyboard = device->data = calloc(1, sizeof(*keyboard));
- keyboard->device = device;
-
- context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- keymap = xkb_keymap_new_from_names(context, nil, XKB_KEYMAP_COMPILE_NO_FLAGS);
-
- wlr_keyboard_set_keymap(device->keyboard, keymap);
-
- xkb_keymap_unref(keymap);
- xkb_context_unref(context);
-
- wlr_keyboard_set_repeat_info(device->keyboard, cfg·repeat_rate, cfg·repeat_delay);
-
- keyboard->event.modify.notify = keymodifier;
- wl_signal_add(&device->keyboard->events.modifiers, &keyboard->event.modify);
-
- keyboard->event.press.notify = keypress;
- wl_signal_add(&device->keyboard->events.key, &keyboard->event.press);
-
- keyboard->event.destroy.notify = free_keyboard;
- wl_signal_add(&device->keyboard->events.destroy, &keyboard->event.destroy);
-
- wlr_seat_set_keyboard(server.input.seat, device);
-
- wl_list_insert(&server.input.keyboards, &keyboard->link);
-}
-
-// -----------------------------------------------------------------------
-// cursor
-
-static
-void
-focus_surface(Client *client, struct wlr_surface *surface, double sx, double sy, uint32 time)
-{
- struct timespec now;
- int lift = time;
-
- if(client && !surface)
- surface = client->xdg->surface;
-
- if(!surface){
- wlr_seat_pointer_notify_clear_focus(server.input.seat);
- return;
- }
-
- if(!time) {
- clock_gettime(CLOCK_MONOTONIC, &now);
- time = now.tv_sec * 1000 + now.tv_nsec / 1000000;
- }
-
- if(surface == server.input.seat->pointer_state.focused_surface) {
- wlr_seat_pointer_notify_motion(server.input.seat, time, sx, sy);
- return;
- }
-
- wlr_seat_pointer_notify_enter(server.input.seat, surface, sx, sy);
-
- if(cfg·sloppyfocus && lift)
- focus(client, 0);
-}
-
-void
-notify_move(uint32 time)
-{
- double sx, sy;
- Client *client;
- struct wlr_box box;
- struct wlr_surface *surface;
-
- if(time) {
- wlr_idle_notify_activity(server.input.idle, server.input.seat);
- if(cfg·sloppyfocus)
- server.monitor.selected = monitor_at(server.cursor.dot->x, server.cursor.dot->y);
- }
-
- if(server.cursor.mode == CursorMove) {
- resize(server.grab.client,
- server.cursor.dot->x - server.grab.x,
- server.cursor.dot->y - server.grab.y,
- server.grab.client->geometry.width,
- server.grab.client->geometry.height,
- 1
- );
- return;
- }
-
- if(server.cursor.mode == CursorResize) {
- wlr_xdg_surface_get_geometry(server.grab.client->xdg, &box);
- resize(server.grab.client,
- server.grab.box.x - box.x,
- server.grab.box.y - box.y,
- server.cursor.dot->x - server.grab.x - server.grab.box.x,
- server.cursor.dot->y - server.grab.y - server.grab.box.y,
- 1
- );
- return;
- }
-
- /* otherwise, find the client under the pointer and send the event along. */
- client = client_at(server.cursor.dot->x, server.cursor.dot->y);
- if(!client) {
- wlr_xcursor_manager_set_cursor_image(server.cursor.manager, "left_ptr", server.cursor.dot);
- return;
- }
-
- surface = client_surface_at(
- client,
- server.cursor.dot->x - client->geometry.x - client->border,
- server.cursor.dot->y - client->geometry.y - client->border,
- &sx, &sy
- );
-
- focus_surface(client, surface, sx, sy, time);
-}
-
-void
-cursor_move(struct wl_listener *l, void *data)
-{
- struct wlr_event_pointer_motion *event = data;
- wlr_cursor_move(server.cursor.dot, event->device, event->delta_x, event->delta_y);
- notify_move(event->time_msec);
-}
-
-void
-cursor_move_abs(struct wl_listener *l, void *data)
-{
- struct wlr_event_pointer_motion_absolute *event = data;
- wlr_cursor_warp_absolute(server.cursor.dot, event->device, event->x, event->y);
- notify_move(event->time_msec);
-}
-
-void
-cursor_button(struct wl_listener *l, void *data)
-{
- Client *client;
- uint32 modifier;
- Button *button;
- struct wlr_keyboard *keyboard;
- struct wlr_event_pointer_button *event = data;
-
- wlr_idle_notify_activity(server.input.idle, server.input.seat);
-
- switch(event->state) {
- case WLR_BUTTON_PRESSED:
- if((client=client_at(server.cursor.dot->x, server.cursor.dot->y)))
- focus(client,1);
-
- keyboard = wlr_seat_get_keyboard(server.input.seat);
- modifier = wlr_keyboard_get_modifiers(keyboard);
- for(button=cfg·button; button != cfg·endbutton; ++button) {
- if(modifier == button->modifier && event->button == button->code && button->function) {
- button->function(&button->arg);
- return;
- }
- }
- break;
- case WLR_BUTTON_RELEASED:
- if(server.cursor.mode != CursorNormal) {
- wlr_xcursor_manager_set_cursor_image(server.cursor.manager, "left_ptr", server.cursor.dot);
- server.cursor.mode = CursorNormal;
- /* Drop the window off on its new monitor */
- server.monitor.selected = monitor_at(server.cursor.dot->x, server.cursor.dot->y);
- attach(server.grab.client, server.monitor.selected, 0);
- return;
- }
- }
-
- wlr_seat_pointer_notify_button(server.input.seat, event->time_msec, event->button, event->state);
-}
-
-void
-cursor_axis(struct wl_listener *l, void *data)
-{
- struct wlr_event_pointer_axis *event = data;
- /* Notify the client with pointer focus of the axis event. */
- wlr_seat_pointer_notify_axis(server.input.seat,
- event->time_msec, event->orientation, event->delta,
- event->delta_discrete, event->source);
-}
-
-void
-cursor_frame(struct wl_listener *l, void *data)
-{
- wlr_seat_pointer_notify_frame(server.input.seat);
-}
-
-void
-request_cursor(struct wl_listener *l, void *data)
-{
- struct wlr_seat_pointer_request_set_cursor_event *event = data;
- struct wlr_seat_client *focused = server.input.seat->pointer_state.focused_client;
- if(focused == event->seat_client)
- wlr_cursor_set_surface(server.cursor.dot, event->surface, event->hotspot_x, event->hotspot_y);
-}
-
-void
-request_set_selection(struct wl_listener *l, void *data)
-{
- struct wlr_seat_request_set_selection_event *event = data;
- wlr_seat_set_selection(server.input.seat, event->source, event->serial);
-}
-
-static
-void
-make_pointer(struct wlr_input_device *device)
-{
- wlr_cursor_attach_input_device(server.cursor.dot, device);
-}
-
-// -----------------------------------------------------------------------
-// generic input
-
-void
-make_input(struct wl_listener *l, void *data)
-{
- uint32 capability;
- struct wlr_input_device *device = data;
-
- switch(device->type) {
- case WLR_INPUT_DEVICE_KEYBOARD:
- make_keyboard(device);
- break;
- case WLR_INPUT_DEVICE_POINTER:
- make_pointer(device);
- /* fallthrough */
- default:
- break;
- }
-
- capability = WL_SEAT_CAPABILITY_POINTER;
- if(!wl_list_empty(&server.input.keyboards))
- capability |= WL_SEAT_CAPABILITY_KEYBOARD;
- wlr_seat_set_capabilities(server.input.seat, capability);
-}
diff --git a/sys/cmd/wm/layer.c b/sys/cmd/wm/layer.c
deleted file mode 100644
index bfac744..0000000
--- a/sys/cmd/wm/layer.c
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "wm.h"
-
-static
-void
-map(struct wl_listener *l, void *data)
-{
- Layer *layer = wl_container_of(l, layer, event.map);
- wlr_surface_send_enter(layer->surface->surface, layer->surface->output);
- notify_move(0);
-}
-
-static
-void
-finalize(Layer *layer)
-{
- layer->surface->mapped = 0;
- if (layer->surface->surface == server.input.seat->keyboard_state.focused_surface)
- focus(selected_client(), 1);
- notify_move(0);
-}
-
-static
-void
-unmap(struct wl_listener *l, void *data)
-{
- Layer *layer = wl_container_of(l, layer, event.unmap);
- finalize(layer);
-}
-
-static
-void
-destroy(struct wl_listener *l, void *data)
-{
- Monitor *monitor;
- Layer *layer = wl_container_of(l, layer, event.destroy);
-
- if (layer->surface->mapped)
- finalize(layer);
-
- wl_list_remove(&layer->link);
- wl_list_remove(&layer->event.destroy.link);
- wl_list_remove(&layer->event.map.link);
- wl_list_remove(&layer->event.unmap.link);
- wl_list_remove(&layer->event.commit.link);
-
- if(layer->surface->output) {
- monitor = layer->surface->output->data;
- if(monitor)
- stratify(monitor);
- layer->surface->output = nil;
- }
- free(layer);
-}
-
-static
-void
-commit(struct wl_listener *l, void *data)
-{
- Monitor *monitor;
- Layer *layer = wl_container_of(l, layer, event.commit);
- struct wlr_layer_surface_v1 *surface = layer->surface;
- struct wlr_output *output = surface->output;
-
- if(!output)
- return;
-
- monitor = output->data;
- stratify(monitor);
-
- if (layer->type != surface->current.layer) {
- wl_list_remove(&layer->link);
- wl_list_insert(&monitor->layer[surface->current.layer], &layer->link);
- layer->type = surface->current.layer;
- }
-}
-
-void
-make_layer_surface(struct wl_listener *l, void *data)
-{
- Layer *layer;
- Monitor *monitor;
- struct wlr_layer_surface_v1_state state;
- struct wlr_layer_surface_v1 *surface = data;
-
- if(!surface->output)
- surface->output = server.monitor.selected->output;
-
- layer = surface->data = calloc(1, sizeof(*layer));
- layer->surface = surface;
-
- layer->event.map.notify = map;
- wl_signal_add(&surface->events.map, &layer->event.map);
- layer->event.unmap.notify = unmap;
- wl_signal_add(&surface->events.unmap, &layer->event.unmap);
- layer->event.destroy.notify = destroy;
- wl_signal_add(&surface->events.destroy, &layer->event.destroy);
- layer->event.commit.notify = commit;
- wl_signal_add(&surface->surface->events.commit, &layer->event.commit);
-
- monitor = surface->output->data;
- wl_list_insert(&monitor->layer[surface->client_pending.layer], &layer->link);
-
- state = surface->current;
- surface->current = surface->client_pending;
- stratify(monitor);
- surface->current = state;
-}
diff --git a/sys/cmd/wm/main.c b/sys/cmd/wm/main.c
deleted file mode 100644
index 2607801..0000000
--- a/sys/cmd/wm/main.c
+++ /dev/null
@@ -1,177 +0,0 @@
-#include "wm.h"
-
-Server server = {
- .event = {
- .make_input = { .notify = make_input },
- .make_monitor = { .notify = make_monitor },
- .make_xdg_surface = { .notify = make_xdg_surface },
- .make_layer_surface = { .notify = make_layer_surface },
-
- .monitor_change = { .notify = monitor_change },
- .monitor_test = { .notify = monitor_test },
- .monitor_apply = { .notify = monitor_apply },
-
- .cursor_move = { .notify = cursor_move },
- .cursor_move_abs = { .notify = cursor_move_abs },
- .cursor_button = { .notify = cursor_button },
- .cursor_axis = { .notify = cursor_axis },
- .cursor_frame = { .notify = cursor_frame },
-
- .request_activate = { .notify = request_activate },
- .request_cursor = { .notify = request_cursor },
- .request_set_selection = { .notify = request_set_selection },
- },
-};
-
-// -----------------------------------------------------------------------
-// helper functions
-
-static inline
-void
-init(void)
-{
- /* compositor initialization */
- server.display = wl_display_create();
- server.backend = wlr_backend_autocreate(server.display);
- server.renderer = wlr_backend_get_renderer(server.backend);
- server.present = wlr_presentation_create(server.display, server.backend);
-
- wlr_renderer_init_wl_display(server.renderer, server.display);
-
- wlr_compositor_create(server.display, server.renderer);
- wlr_export_dmabuf_manager_v1_create(server.display);
- wlr_screencopy_manager_v1_create(server.display);
- wlr_data_control_manager_v1_create(server.display);
- wlr_data_device_manager_create(server.display);
- wlr_gamma_control_manager_v1_create(server.display);
- wlr_primary_selection_v1_device_manager_create(server.display);
- wlr_viewporter_create(server.display);
-
- server.activate = wlr_xdg_activation_v1_create(server.display);
- wl_signal_add(&server.activate->events.request_activate, &server.event.request_activate);
-
- wlr_data_device_manager_create(server.display);
-
- server.monitor.layout = wlr_output_layout_create();
- wl_signal_add(&server.monitor.layout->events.change, &server.event.monitor_change);
- wlr_xdg_output_manager_v1_create(server.display, server.monitor.layout);
-
- wl_list_init(&server.monitor.list);
- wl_signal_add(&server.backend->events.new_output, &server.event.make_monitor);
-
- server.monitor.manager = wlr_output_manager_v1_create(server.display);
- wl_signal_add(&server.monitor.manager->events.test, &server.event.monitor_test);
- wl_signal_add(&server.monitor.manager->events.apply, &server.event.monitor_apply);
-
- /* shell initialization */
- wl_list_init(&server.client.list);
- wl_list_init(&server.client.stack);
- wl_list_init(&server.client.focus);
-
- server.shell.xdg = wlr_xdg_shell_create(server.display);
- wl_signal_add(&server.shell.xdg->events.new_surface, &server.event.make_xdg_surface);
-
- server.shell.layer = wlr_layer_shell_v1_create(server.display);
- wl_signal_add(&server.shell.layer->events.new_surface, &server.event.make_layer_surface);
-
- wlr_server_decoration_manager_set_default_mode(
- wlr_server_decoration_manager_create(server.display),
- WLR_SERVER_DECORATION_MANAGER_MODE_SERVER
- );
- wlr_xdg_decoration_manager_v1_create(server.display);
-
- /* input initialization */
- server.cursor.dot = wlr_cursor_create();
- wlr_cursor_attach_output_layout(server.cursor.dot, server.monitor.layout);
-
- server.cursor.manager = wlr_xcursor_manager_create(nil, 24);
- wlr_xcursor_manager_load(server.cursor.manager, 1);
-
- wl_signal_add(&server.cursor.dot->events.motion, &server.event.cursor_move);
- wl_signal_add(&server.cursor.dot->events.motion_absolute, &server.event.cursor_move_abs);
- wl_signal_add(&server.cursor.dot->events.button, &server.event.cursor_button);
- wl_signal_add(&server.cursor.dot->events.axis, &server.event.cursor_axis);
- wl_signal_add(&server.cursor.dot->events.frame, &server.event.cursor_frame);
-
- wl_list_init(&server.input.keyboards);
- wl_signal_add(&server.backend->events.new_input, &server.event.make_input);
-
- server.input.idle = wlr_idle_create(server.display);
- server.input.seat = wlr_seat_create(server.display, "seat0");
-
- wl_signal_add(&server.input.seat->events.request_set_cursor, &server.event.request_cursor);
- wl_signal_add(&server.input.seat->events.request_set_selection, &server.event.request_set_selection);
-}
-
-static inline
-void
-fini(void)
-{
- wl_display_destroy_clients(server.display);
-
- wlr_backend_destroy(server.backend);
- wlr_xcursor_manager_destroy(server.cursor.manager);
- wlr_output_layout_destroy(server.monitor.layout);
- wlr_seat_destroy(server.input.seat);
-
- wl_display_destroy(server.display);
-}
-
-// -----------------------------------------------------------------------
-// main point of entry
-
-int
-usage(void)
-{
- fprintf(stderr, "usage: %s [-s startup command]\n", argv0);
- return 1;
-}
-
-
-int
-main(int argc, char *argv[])
-{
- char *socket, *cmd=nil;
-
- ARGBEGIN{
- case 's':
- cmd = ARGF();
- break;
- default:
- return usage();
- } ARGEND
-
- if(argc != 0)
- return usage();
-
- wlr_log_init(WLR_DEBUG, nil);
-
- init();
-
- if(!(socket=(char*)wl_display_add_socket_auto(server.display))) {
- wlr_backend_destroy(server.backend);
- return 1;
- }
-
- if(!(wlr_backend_start(server.backend))) {
- wlr_backend_destroy(server.backend);
- wl_display_destroy(server.display);
- return 1;
- }
-
- setenv("WAYLAND_DISPLAY", socket, true);
- if(cmd) {
- if(fork()==0)
- execl("/bin/sh", "/bin/sh", "-c", cmd, nil);
- }
- wlr_log(WLR_INFO, "Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
-
- server.monitor.selected = monitor_at(server.cursor.dot->x, server.cursor.dot->y);
- wlr_cursor_warp_closest(server.cursor.dot, nil, server.cursor.dot->x, server.cursor.dot->y);
- wlr_xcursor_manager_set_cursor_image(server.cursor.manager, "left_ptr", server.cursor.dot);
-
- wl_display_run(server.display); /* event loop */
-
- fini();
- return 0;
-}
diff --git a/sys/cmd/wm/monitor.c b/sys/cmd/wm/monitor.c
deleted file mode 100644
index 93073f3..0000000
--- a/sys/cmd/wm/monitor.c
+++ /dev/null
@@ -1,386 +0,0 @@
-#include "wm.h"
-
-/* callbacks */
-void
-monitor_change(struct wl_listener *l, void *data)
-{
- Monitor *monitor;
- struct wlr_output_configuration_v1 *config;
-
- config = wlr_output_configuration_v1_create();
- server.monitor.geometry = *wlr_output_layout_get_box(server.monitor.layout, nil);
-
- wl_list_for_each(monitor, &server.monitor.list, link) {
- struct wlr_output_configuration_head_v1 *head =
- wlr_output_configuration_head_v1_create(config, monitor->output);
-
- monitor->geometry = monitor->window = *wlr_output_layout_get_box(server.monitor.layout, monitor->output);
-
- stratify(monitor);
- arrange(monitor);
-
- head->state.enabled = monitor->output->enabled;
- head->state.mode = monitor->output->current_mode;
- head->state.x = monitor->geometry.x;
- head->state.y = monitor->geometry.y;
- }
-
- wlr_output_manager_v1_set_configuration(server.monitor.manager, config);
-}
-
-static
-void
-trylayout(struct wlr_output_configuration_v1 *config, int force)
-{
- int ok;
- struct wlr_output_configuration_head_v1 *head;
-
- ok = 1;
- wl_list_for_each(head, &config->heads, link) {
- struct wlr_output *output= head->state.output;
- wlr_output_enable(output, head->state.enabled);
- if (head->state.enabled) {
- if (head->state.mode)
- wlr_output_set_mode(output, head->state.mode);
- else
- wlr_output_set_custom_mode(
- output,
- head->state.custom_mode.width,
- head->state.custom_mode.height,
- head->state.custom_mode.refresh
- );
-
- wlr_output_layout_move(server.monitor.layout, output,
- head->state.x, head->state.y);
- wlr_output_set_transform(output, head->state.transform);
- }
-
- if(!(ok=wlr_output_test(output)))
- break;
- }
-
- wl_list_for_each(head, &config->heads, link) {
- if(ok && force)
- wlr_output_commit(head->state.output);
- else
- wlr_output_rollback(head->state.output);
- }
-
- if(ok)
- wlr_output_configuration_v1_send_succeeded(config);
- else
- wlr_output_configuration_v1_send_failed(config);
-
- wlr_output_configuration_v1_destroy(config);
-}
-
-void
-monitor_apply(struct wl_listener *l, void *data)
-{
- struct wlr_output_configuration_v1 *config = data;
- trylayout(config, 1);
-}
-
-void
-monitor_test(struct wl_listener *l, void *data)
-{
- struct wlr_output_configuration_v1 *config = data;
- trylayout(config, 0);
-}
-
-void
-make_monitor(struct wl_listener *l, void *data)
-{
- int i;
- Client *client;
- Monitor *monitor;
- MonitorRule *rule;
- struct wlr_output_mode *mode;
- struct wlr_output *output = data;
-
- /*
- * XXX: needed?
- if (wl_list_empty(&output->modes))
- return;
- */
-
- monitor = output->data = calloc(1, sizeof(*monitor));
- monitor->output = output;
-
- for(i=0; i < arrlen(monitor->layer); i++)
- wl_list_init(&monitor->layer[i]);
- monitor->tag.set[0] = monitor->tag.set[1] = 1;
-
- for(rule=cfg·monitorrule; rule != cfg·endmonitorrule; ++rule) {
- if(!rule->name || strstr(output->name, rule->name)) {
- monitor->master.len = rule->master.len;
- monitor->master.frac = rule->master.frac;
-
- wlr_output_set_scale(output, rule->scale);
- wlr_xcursor_manager_load(server.cursor.manager, rule->scale);
- monitor->layouts[0] = monitor->layouts[1] = monitor->layout = rule->layout;
-
- wlr_output_set_transform(output, rule->transform);
- break;
- }
- }
-
- mode = wlr_output_preferred_mode(output);
- wlr_output_set_mode(output, mode);
- wlr_output_enable_adaptive_sync(output, true);
-
- monitor->event.render.notify = render_monitor;
- wl_signal_add(&output->events.frame, &monitor->event.render);
- monitor->event.destroy.notify = free_monitor;
- wl_signal_add(&output->events.destroy, &monitor->event.destroy);
-
- wlr_output_enable(output, true);
- if(!wlr_output_commit(output))
- return;
-
- wl_list_insert(&server.monitor.list, &monitor->link);
-
- wlr_output_layout_add(server.monitor.layout, output, rule->x, rule->y);
- server.monitor.geometry = *wlr_output_layout_get_box(server.monitor.layout, nil);
-
- /* update the geometries of all monitors */
- wl_list_for_each(monitor, &server.monitor.list, link) {
- /* first monitor in the list = most recently added */
- wl_list_for_each(client, &server.client.list, link) {
- if(client->isfloating)
- resize(client, client->geometry.x+monitor->window.width, client->geometry.y,
- client->geometry.width, client->geometry.height, 0);
- }
- return;
- }
-}
-
-void
-free_monitor(struct wl_listener *l, void *data)
-{
- int i, len;
- Client *client;
- struct wlr_output *output = data;
- Monitor *monitor = output->data;
-
- wl_list_remove(&monitor->event.destroy.link);
- wl_list_remove(&monitor->event.render.link);
- wl_list_remove(&monitor->link);
-
- wlr_output_layout_remove(server.monitor.layout, monitor->output);
-
- for(i=0, len=wl_list_length(&server.monitor.list); i < len; i++) {
- server.monitor.selected = wl_container_of(server.monitor.list.prev, server.monitor.selected, link);
- if(server.monitor.selected->output->enabled)
- break;
- }
-
- focus(focused_client(server.monitor.selected), 1);
-
- /* move closed monitor's clients to newly selected one */
- wl_list_for_each(client, &server.client.list, link) {
- if(client->isfloating && client->geometry.x > monitor->geometry.width)
- resize(client,
- client->geometry.x - monitor->window.width,
- client->geometry.y,
- client->geometry.width,
- client->geometry.height,
- 0
- );
- if(client->monitor == monitor)
- attach(client, monitor, client->tags);
- }
-
- free(monitor);
-}
-
-/* methods */
-void
-arrange(Monitor *monitor)
-{
- if(monitor->layout->arrange)
- monitor->layout->arrange(monitor);
-}
-
-void
-stratum(Monitor *monitor, struct wl_list *list, struct wlr_box *area, int exclusive)
-{
- Layer *layer;
- struct wlr_box full = monitor->geometry;
-
- wl_list_for_each(layer, list, link) {
- struct wlr_layer_surface_v1 *surface = layer->surface;
- struct wlr_layer_surface_v1_state *state = &surface->current;
- struct wlr_box bounds;
- struct wlr_box box = {
- .width = state->desired_width,
- .height = state->desired_height
- };
- const uint32 horizontal = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
- | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
- const uint32 vertical = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
- | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
-
- if (exclusive != (state->exclusive_zone > 0))
- continue;
-
- bounds = state->exclusive_zone == -1 ? full : *area;
-
- // horizontal axis
- if((state->anchor & horizontal) && box.width == 0) {
- box.x = bounds.x;
- box.width = bounds.width;
- } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
- box.x = bounds.x;
- } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
- box.x = bounds.x + (bounds.width - box.width);
- } else {
- box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
- }
-
- // vertical axis
- if((state->anchor & vertical) && box.height == 0) {
- box.y = bounds.y;
- box.height = bounds.height;
- } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
- box.y = bounds.y;
- } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
- box.y = bounds.y + (bounds.height - box.height);
- } else {
- box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
- }
-
- // margin
- if((state->anchor & horizontal) == horizontal) {
- box.x += state->margin.left;
- box.width -= state->margin.left + state->margin.right;
- } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
- box.x += state->margin.left;
- } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
- box.x -= state->margin.right;
- }
-
- if((state->anchor & vertical) == vertical) {
- box.y += state->margin.top;
- box.height -= state->margin.top + state->margin.bottom;
- } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
- box.y += state->margin.top;
- } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
- box.y -= state->margin.bottom;
- }
- if(box.width < 0 || box.height < 0) {
- wlr_layer_surface_v1_close(surface);
- continue;
- }
- layer->geometry = box;
-
- if (state->exclusive_zone > 0)
- exclude(area,
- state->anchor, state->exclusive_zone,
- state->margin.top, state->margin.right,
- state->margin.bottom, state->margin.left);
- wlr_layer_surface_v1_configure(surface, box.width, box.height);
- }
-}
-
-void
-stratify(Monitor *monitor)
-{
- int i;
- Layer *layer;
- struct wlr_box area = monitor->geometry;
- uint32_t overlays[] = {
- ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
- ZWLR_LAYER_SHELL_V1_LAYER_TOP,
- };
- struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(server.input.seat);
-
- // arrange exclusive surfaces from top->bottom
- stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &area, 1);
- stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &area, 1);
- stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &area, 1);
- stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &area, 1);
-
- if(memcmp(&area, &monitor->window, sizeof(area))) {
- monitor->window = area;
- arrange(monitor);
- }
-
- // arrange non-exlusive surfaces from top->bottom
- stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &area, 0);
- stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &area, 0);
- stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &area, 0);
- stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &area, 0);
-
- // find topmost keyboard interactive layer, if such a layer exists
- for(i = 0; i < arrlen(overlays); i++) {
- wl_list_for_each_reverse(layer, &monitor->layer[overlays[i]], link) {
- if (layer->surface->current.keyboard_interactive && layer->surface->mapped) {
- // Deactivate the focused client.
- focus(nil, 0);
- wlr_seat_keyboard_notify_enter(
- server.input.seat,
- layer->surface->surface,
- keyboard->keycodes,
- keyboard->num_keycodes,
- &keyboard->modifiers
- );
- return;
- }
- }
- }
-}
-
-Client *
-focused_client(Monitor *monitor)
-{
- Client *client;
- wl_list_for_each(client, &server.client.focus, focus) {
- if(VISIBLE_ON(client, monitor))
- return client;
- }
-
- return nil;
-}
-
-void
-tile(Monitor *monitor)
-{
- Client *client;
- uint i, n, h, mw, my, ty;
-
- n = 0;
- wl_list_for_each(client, &server.client.list, link) {
- if(VISIBLE_ON(client, monitor) && !client->isfloating)
- n++;
- }
- if(!n) return;
-
- if(n > monitor->master.len)
- mw = monitor->master.len ? monitor->window.width * monitor->master.frac : 0;
- else
- mw = monitor->window.width;
-
- i = my = ty = 0;
- wl_list_for_each(client, &server.client.list, link) {
- if(!VISIBLE_ON(client,monitor) || client->isfloating || client->isfullscreen)
- continue;
- if(i < monitor->master.len) {
- h = (monitor->window.height - my) / (MIN(n, monitor->master.len) - i);
- resize(client, monitor->window.x, monitor->window.y + my, mw, h, 0);
- my += client->geometry.height;
- } else {
- h = (monitor->window.height - ty) / (n - i);
- resize(client, monitor->window.x + mw, monitor->window.y + ty, monitor->window.width - mw, h, 0);
- ty += client->geometry.height;
- }
- i++;
- }
-}
-
-Monitor *
-monitor_at(double x, double y)
-{
- struct wlr_output *output = wlr_output_layout_output_at(server.monitor.layout, x, y);
- return output ? output->data : nil;
-}
diff --git a/sys/cmd/wm/protocol/sync b/sys/cmd/wm/protocol/sync
deleted file mode 100755
index 19a728a..0000000
--- a/sys/cmd/wm/protocol/sync
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-for base in wlr-layer-shell-unstable-v1.xml
-do
- curl https://raw.githubusercontent.com/swaywm/wlroots/master/protocol/$base --output $base
-done
diff --git a/sys/cmd/wm/render.c b/sys/cmd/wm/render.c
deleted file mode 100644
index 1f51804..0000000
--- a/sys/cmd/wm/render.c
+++ /dev/null
@@ -1,160 +0,0 @@
-#include "wm.h"
-
-struct Payload
-{
- Client *client;
- struct wlr_output *output;
- struct timespec *when;
- int x, y;
-};
-
-static
-void
-render(struct wlr_surface *surface, int sx, int sy, void *data)
-{
- float matrix[9];
- double x, y;
- struct Payload *payload;
-
- struct wlr_box box;
- struct wlr_output *output;
- struct wlr_texture *texture;
-
- enum wl_output_transform transform;
-
- payload = data;
- output = payload->output;
-
- texture = wlr_surface_get_texture(surface);
- if(!texture)
- return;
-
- x = 0, y = 0;
- wlr_output_layout_output_coords(server.monitor.layout, output, &x, &y);
-
- box = (struct wlr_box) {
- .x = x + payload->x + sx,
- .y = y + payload->y + sy,
- .width = surface->current.width,
- .height = surface->current.height,
- };
- scale_box(&box, output->scale);
-
- transform = wlr_output_transform_invert(surface->current.transform);
- wlr_matrix_project_box(matrix, &box, transform, 0, output->transform_matrix);
-
- wlr_render_texture_with_matrix(server.renderer, texture, matrix, 1);
- wlr_surface_send_frame_done(surface, payload->when);
- wlr_presentation_surface_sampled_on_output(server.present, surface, output);
-}
-
-static
-void
-render_layer(struct wl_list *list, struct timespec *now)
-{
- Layer *layer;
- wl_list_for_each(layer, list, link) {
- struct Payload payload= {
- .output = layer->surface->output,
- .x = layer->geometry.x,
- .y = layer->geometry.y,
- .when = now,
- };
-
- wlr_surface_for_each_surface(layer->surface->surface, render, &payload);
- }
-}
-
-static
-void
-render_clients(Monitor *monitor, struct timespec *now)
-{
- double x, y;
- int i, w, h, bw;
- float *color;
-
- Client *client;
- struct wlr_output *output;
- struct wlr_box *borders;
- struct wlr_surface *surface;
-
- output = monitor->output;
- wl_list_for_each_reverse(client, &server.client.stack, stack) {
- if(!VISIBLE_ON(client, client->monitor))
- continue;
- if(!wlr_output_layout_intersects(server.monitor.layout, monitor->output, &client->geometry))
- continue;
-
- surface = client->xdg->surface;
-
- x = client->geometry.x, y = client->geometry.y;
- wlr_output_layout_output_coords(server.monitor.layout, output, &x, &y);
-
- if((bw=client->border)) {
- w = surface->current.width;
- h = surface->current.height;
- borders = (struct wlr_box[4]) {
- {x, y, w+2*bw, bw}, /* top */
- {x, y+bw, bw, h}, /* left */
- {x+bw+w, y+bw, bw, h}, /* right */
- {x, y+bw+h, w+2*bw, bw}, /* bottom */
- };
-
- color = (client == server.selected) ? cfg·focuscolor : cfg·bordercolor;
- for(i=0; i<4; i++) {
- scale_box(&borders[i], output->scale);
- wlr_render_rect(server.renderer, &borders[i], color, output->transform_matrix);
- }
- }
-
- struct Payload payload = {
- .output = output,
- .when = now,
-
- .x = client->geometry.x + client->border,
- .y = client->geometry.y + client->border,
- };
-
- wlr_xdg_surface_for_each_surface(client->xdg, render, &payload);
- }
-}
-
-void
-render_monitor(struct wl_listener *l, void *data)
-{
- int w, h;
- Client *client;
- Monitor *monitor;
- struct timespec now;
-
- clock_gettime(CLOCK_MONOTONIC, &now);
- monitor = wl_container_of(l, monitor, event.render);
-
- wl_list_for_each(client, &server.client.list, link) {
- if(client->resize) {
- wlr_surface_send_frame_done(client->xdg->surface, &now);
- }
- }
-
- if(!wlr_output_attach_render(monitor->output, nil))
- return;
-
- wlr_output_effective_resolution(monitor->output, &w, &h);
-
- /* start of rendering kernel */
- wlr_renderer_begin(server.renderer, w, h);
- wlr_renderer_clear(server.renderer, cfg·rootcolor);
-
- render_layer(&monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now);
- render_layer(&monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now);
-
- render_clients(monitor, &now);
-
- render_layer(&monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now);
- render_layer(&monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now);
-
- wlr_output_render_software_cursors(monitor->output, nil);
-
- wlr_renderer_end(server.renderer);
- wlr_output_commit(monitor->output);
-}
diff --git a/sys/cmd/wm/rules.mk b/sys/cmd/wm/rules.mk
deleted file mode 100644
index 5a36b6f..0000000
--- a/sys/cmd/wm/rules.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-include share/push.mk
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := \
- $(d)/xdg-shell-protocol.c \
- $(d)/wlr-layer-shell-unstable-v1-protocol.c \
- $(d)/util.c \
- $(d)/input.c \
- $(d)/render.c \
- $(d)/layer.c \
- $(d)/xdg.c \
- $(d)/client.c \
- $(d)/monitor.c \
- $(d)/main.c
-BINS_$(d) := $(d)/wm
-
-include share/paths.mk
-
-# Local rules
-include share/dynamic.mk
-
-$(d)/xdg-shell-protocol.h:
- @echo "MK $(notdir $@)";\
- $(WL_SCAN) server-header $(WL_PROTO)/stable/xdg-shell/xdg-shell.xml $@
-
-$(d)/xdg-shell-protocol.c: $(d)/xdg-shell-protocol.h
- @echo "MK $(notdir $@)";\
- $(WL_SCAN) private-code $(WL_PROTO)/stable/xdg-shell/xdg-shell.xml $@
-
-$(d)/wlr-layer-shell-unstable-v1-protocol.h:
- @echo "MK $(notdir $@)";\
- $(WL_SCAN) server-header $(dir $@)protocol/wlr-layer-shell-unstable-v1.xml $@
-
-$(d)/wlr-layer-shell-unstable-v1-protocol.c: $(d)/wlr-layer-shell-unstable-v1-protocol.h
- @echo "MK $(notdir $@)";\
- $(WL_SCAN) private-code $(dir $@)protocol/wlr-layer-shell-unstable-v1.xml $@
-
-GENS += \
-$(d)/xdg-shell-protocol.h \
-$(d)/xdg-shell-protocol.c \
-$(d)/wlr-layer-shell-unstable-v1-protocol.h \
-$(d)/wlr-layer-shell-unstable-v1-protocol.c
-
-$(BINS_$(d)): TCINCS = \
- -I sys/cmd/wm
-
-$(BINS_$(d)): TCFLAGS = \
- `$(PKG) --cflags wlroots` \
- `$(PKG) --cflags wayland-server` \
- `$(PKG) --cflags xkbcommon`
-
-$(BINS_$(d)): TCLIBS = \
- `$(PKG) --libs wlroots` \
- `$(PKG) --libs wayland-server` \
- `$(PKG) --libs xkbcommon` \
-
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/wm/util.c b/sys/cmd/wm/util.c
deleted file mode 100644
index 7871d15..0000000
--- a/sys/cmd/wm/util.c
+++ /dev/null
@@ -1,99 +0,0 @@
-#include "wm.h"
-
-typedef struct {
- uint32 singular_anchor;
- uint32 anchor_triplet;
- int *positive_axis;
- int *negative_axis;
- int margin;
-} Edge;
-
-// -----------------------------------------------------------------------
-// general purpose function on rectangles
-
-void
-scale_box(struct wlr_box *box, float scale)
-{
- box->width = ROUND((box->x + box->width) * scale) - ROUND(box->x * scale);
- box->height = ROUND((box->y + box->height) * scale) - ROUND(box->y * scale);
- box->x = ROUND(box->x * scale);
- box->y = ROUND(box->y * scale);
-}
-
-void
-exclude(struct wlr_box *usable_area, uint32 anchor, int32 exclusive,
- int32 margin_top, int32 margin_right, int32 margin_bottom, int32 margin_left)
-{
- Edge edges[] = {
- { // Top
- .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
- .anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
- .positive_axis = &usable_area->y,
- .negative_axis = &usable_area->height,
- .margin = margin_top,
- },
- { // Bottom
- .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
- .anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
- .positive_axis = NULL,
- .negative_axis = &usable_area->height,
- .margin = margin_bottom,
- },
- { // Left
- .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT,
- .anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
- .positive_axis = &usable_area->x,
- .negative_axis = &usable_area->width,
- .margin = margin_left,
- },
- { // Right
- .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
- .anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
- .positive_axis = NULL,
- .negative_axis = &usable_area->width,
- .margin = margin_right,
- }
- };
- for(size_t i = 0; i < arrlen(edges); i++) {
- if((anchor == edges[i].singular_anchor || anchor == edges[i].anchor_triplet)
- && exclusive + edges[i].margin > 0) {
- if(edges[i].positive_axis)
- *edges[i].positive_axis += exclusive + edges[i].margin;
- if(edges[i].negative_axis)
- *edges[i].negative_axis -= exclusive + edges[i].margin;
- break;
- }
- }
-}
-
-// -----------------------------------------------------------------------
-// user facing functions
-
-void
-spawn(Arg *arg)
-{
- wlr_log(WLR_DEBUG, "spawning %s", ((char **)arg->v)[0]);
- if(!fork()) {
- dup2(2, 1);
- setsid();
- execvp(((char **)arg->v)[0], (char **)arg->v);
- }
-}
-
-void
-quit(Arg *arg)
-{
- wl_display_terminate(server.display);
-}
-
-#define CONFIG(a,b,...) a cfg·##b = __VA_ARGS__
-#include "config.h"
-#undef CONFIG
diff --git a/sys/cmd/wm/wm.h b/sys/cmd/wm/wm.h
deleted file mode 100644
index a263804..0000000
--- a/sys/cmd/wm/wm.h
+++ /dev/null
@@ -1,350 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-#include <wayland-server-core.h>
-#include <linux/input-event-codes.h>
-
-#define WLR_USE_UNSTABLE
-#include <wlr/backend.h>
-#include <wlr/render/wlr_renderer.h>
-
-#include <wlr/types/wlr_cursor.h>
-#include <wlr/types/wlr_compositor.h>
-#include <wlr/types/wlr_data_control_v1.h>
-#include <wlr/types/wlr_data_device.h>
-#include <wlr/types/wlr_export_dmabuf_v1.h>
-#include <wlr/types/wlr_gamma_control_v1.h>
-#include <wlr/types/wlr_input_device.h>
-#include <wlr/types/wlr_idle.h>
-#include <wlr/types/wlr_layer_shell_v1.h>
-#include <wlr/types/wlr_keyboard.h>
-#include <wlr/types/wlr_matrix.h>
-#include <wlr/types/wlr_output.h>
-#include <wlr/types/wlr_output_layout.h>
-#include <wlr/types/wlr_output_damage.h>
-#include <wlr/types/wlr_output_management_v1.h>
-#include <wlr/types/wlr_primary_selection.h>
-#include <wlr/types/wlr_primary_selection_v1.h>
-#include <wlr/types/wlr_pointer.h>
-#include <wlr/types/wlr_presentation_time.h>
-#include <wlr/types/wlr_screencopy_v1.h>
-#include <wlr/types/wlr_server_decoration.h>
-#include <wlr/types/wlr_seat.h>
-#include <wlr/types/wlr_viewporter.h>
-#include <wlr/types/wlr_xcursor_manager.h>
-#include <wlr/types/wlr_xdg_activation_v1.h>
-#include <wlr/types/wlr_xdg_decoration_v1.h>
-#include <wlr/types/wlr_xdg_output_v1.h>
-#include <wlr/types/wlr_xdg_shell.h>
-
-#include <wlr/util/log.h>
-
-#include <xkbcommon/xkbcommon.h>
-
-// -----------------------------------------------------------------------
-// macros
-
-#define ROUND(x) ((int)((x)+0.5))
-#define VISIBLE_ON(C,M) ((C)->monitor == (M) && ((C)->tags & (M)->tag.set[(M)->tag.selected]))
-
-// -----------------------------------------------------------------------
-// types
-
-enum
-{
- CursorNormal,
- CursorMove,
- CursorResize,
-};
-
-typedef union Arg Arg;
-typedef struct Button Button;
-typedef struct Key Key;
-typedef struct Keyboard Keyboard;
-typedef struct Layer Layer;
-typedef struct Client Client;
-typedef struct Layout Layout;
-typedef struct Monitor Monitor;
-typedef struct Server Server;
-
-typedef struct Rule Rule;
-typedef struct MonitorRule MonitorRule;
-
-struct Rectangle
-{
- int x, y;
- int w, h;
-};
-
-union Arg
-{
- int i;
- uint ui;
- float f;
- void *v;
-};
-
-struct Key
-{
- uint modifier;
- xkb_keysym_t sym;
- void (*action)(Arg *);
- Arg arg;
-};
-
-struct Button
-{
- uint modifier;
- uint code;
- void (*function)(Arg *);
- Arg arg;
-};
-
-struct Keyboard
-{
- struct wl_list link;
- struct wlr_input_device *device;
- struct {
- struct wl_listener press;
- struct wl_listener modify;
- struct wl_listener destroy;
- } event;
-};
-
-struct Layer
-{
- struct wl_list link;
- struct wlr_layer_surface_v1 *surface;
- enum zwlr_layer_shell_v1_layer type;
-
- struct wlr_box geometry;
-
- struct {
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener commit;
- struct wl_listener destroy;
- } event;
-};
-
-struct Client
-{
- struct wl_list link;
- struct wl_list stack;
- struct wl_list focus;
-
- struct wlr_xdg_surface *xdg;
-
- struct {
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener commit;
- struct wl_listener destroy;
- struct wl_listener request_move;
- struct wl_listener request_title;
- struct wl_listener request_resize;
- struct wl_listener request_fullscreen;
- } event;
-
- struct wlr_box geometry, oldgeometry;
-
- Monitor *monitor;
-
- uint tags;
- int border : 4;
- int ismapped : 1;
- int isfloating : 1;
- int isurgent : 1;
- int isfullscreen : 1;
-
- uint32 resize;
-};
-
-struct Layout
-{
- char *symbol;
- void (*arrange)(Monitor *);
-};
-
-struct Monitor
-{
- struct wl_list link;
- struct wlr_output *output;
- struct {
- struct wl_listener render;
- struct wl_listener destroy;
- } event;
-
- struct wlr_box geometry;
- struct wlr_box window;
- struct wl_list layer[4];
-
- Layout *layout, *layouts[2];
- struct {
- uint set[2];
- uint selected;
- } tag;
- struct {
- double frac;
- int len;
- } master;
-};
-
-struct MonitorRule
-{
- char *name;
- Layout *layout;
- int x, y;
- float scale;
- enum wl_output_transform transform;
- struct {
- double frac;
- int len;
- } master;
-};
-
-struct Rule
-{
- char *id;
- char *title;
- uint tags;
- int isfloating;
- int monitor;
-};
-
-struct Server
-{
- struct wl_display *display;
- struct wlr_backend *backend;
- struct wlr_renderer *renderer;
- struct wlr_presentation *present;
- struct wlr_xdg_activation_v1 *activate;
-
- struct {
- struct wlr_xdg_shell *xdg;
- struct wlr_layer_shell_v1 *layer;
- } shell;
-
- struct {
- struct wl_list list;
- struct wl_list stack;
- struct wl_list focus;
- } client;
- Client *selected;
-
- struct {
- Client *client;
- double x, y;
- struct wlr_box box;
- } grab;
- uint32 resize;
-
- struct {
- struct wlr_output_layout *layout;
- struct wl_list list;
- struct wlr_box geometry;
- struct wlr_output_manager_v1 *manager;
- Monitor *selected;
- } monitor;
-
- struct {
- struct wlr_cursor *dot;
- struct wlr_xcursor_manager *manager;
- int mode;
- } cursor;
-
- struct {
- struct wlr_seat *seat;
- struct wl_list keyboards;
- struct wlr_idle *idle;
- } input;
-
- struct {
- struct wl_listener make_input;
- struct wl_listener make_monitor;
- struct wl_listener make_xdg_surface;
- struct wl_listener make_layer_surface;
-
- struct wl_listener monitor_test;
- struct wl_listener monitor_apply;
- struct wl_listener monitor_change;
-
- struct wl_listener cursor_move;
- struct wl_listener cursor_move_abs;
- struct wl_listener cursor_button;
- struct wl_listener cursor_axis;
- struct wl_listener cursor_frame;
-
- struct wl_listener request_cursor;
- struct wl_listener request_activate;
- struct wl_listener request_set_selection;
- } event;
-};
-
-extern struct Server server;
-
-// -----------------------------------------------------------------------
-// functions
-
-/* util.c */
-void scale_box(struct wlr_box *, float);
-void exclude(struct wlr_box *, uint32, int32, int32, int32, int32, int32 );
-
-/* render.c */
-void render_monitor(struct wl_listener *, void *);
-
-/* xdg.c */
-void make_xdg_surface(struct wl_listener *, void *);
-
-/* layer.c */
-void make_layer_surface(struct wl_listener *, void *);
-
-/* input.c */
-void make_input(struct wl_listener *, void *);
-void notify_move(uint32 time);
-
-void cursor_axis(struct wl_listener *, void *);
-void cursor_frame(struct wl_listener *, void *);
-void cursor_button(struct wl_listener *, void *);
-void cursor_move(struct wl_listener *, void *);
-void cursor_move_abs(struct wl_listener *, void *);
-
-void request_cursor(struct wl_listener *, void *);
-void request_set_selection(struct wl_listener *, void *);
-
-/* client.c */
-void rules(Client *);
-void focus(Client *, int lift);
-void resize(Client *, int x, int y, int w, int h, int interact);
-void attach(Client *, Monitor *, uint tags);
-void floating(Client *, int);
-
-void move_client(Arg *arg);
-void float_client(Arg *arg);
-void resize_client(Arg *arg);
-
-void request_activate(struct wl_listener *, void *);
-
-Client *selected_client(void);
-Client *client_at(double x, double y);
-struct wlr_surface *client_surface_at(Client *, double cx, double cy, double *sx, double *sy);
-struct wlr_surface *top_surface(Client *);
-
-/* monitor.c */
-void tile(Monitor *);
-void arrange(Monitor *);
-void stratify(Monitor *);
-Client *focused_client(Monitor *);
-Monitor *monitor_at(double x, double y);
-
-void monitor_test(struct wl_listener *, void *);
-void monitor_apply(struct wl_listener *, void *);
-void monitor_change(struct wl_listener *, void *);
-
-void free_monitor(struct wl_listener *, void *);
-void make_monitor(struct wl_listener *, void *);
-
-#define CONFIG(a,b,...) extern a cfg·##b
-#include "config.h"
-#undef CONFIG
diff --git a/sys/cmd/wm/xdg.c b/sys/cmd/wm/xdg.c
deleted file mode 100644
index 6a0c2c8..0000000
--- a/sys/cmd/wm/xdg.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "wm.h"
-
-static
-void
-map(struct wl_listener *l, void *data)
-{
- Client *client = wl_container_of(l, client, event.map);
-
- wl_list_insert(&server.client.list, &client->link);
- wl_list_insert(&server.client.stack, &client->stack);
- wl_list_insert(&server.client.focus, &client->focus);
-
- wlr_xdg_surface_get_geometry(client->xdg, &client->geometry);
- client->geometry.width += 2 * client->border;
- client->geometry.height += 2 * client->border;
-
- wlr_xdg_toplevel_set_tiled(client->xdg,
- WLR_EDGE_TOP|WLR_EDGE_BOTTOM|WLR_EDGE_LEFT|WLR_EDGE_RIGHT
- );
-
- rules(client);
-}
-
-static
-void
-unmap(struct wl_listener *l, void *data)
-{
- Client *client = wl_container_of(l, client, event.unmap);
-
- wl_list_remove(&client->link);
- attach(client, nil, 0);
-
- wl_list_remove(&client->stack);
- wl_list_remove(&client->focus);
-}
-
-static
-void
-commit(struct wl_listener *l, void *data)
-{
- Client *client = wl_container_of(l, client, event.commit);
- if(client->resize && client->resize <= client->xdg->configure_serial)
- client->resize = 0;
-}
-
-static
-void
-destroy(struct wl_listener *l, void *data)
-{
- Client *client = wl_container_of(l, client, event.destroy);
- free(client);
-}
-
-static
-void
-request_move(struct wl_listener *l, void *data)
-{
- Client *client = wl_container_of(l, client, event.request_move);
-}
-
-static
-void
-request_resize(struct wl_listener *l, void *data)
-{
- struct wlr_xdg_toplevel_resize_event *event = data;
- Client *client = wl_container_of(l, client, event.request_resize);
-}
-
-
-static
-void
-request_title(struct wl_listener *l, void *data)
-{
- Client *client = wl_container_of(l, client, event.request_title);
-}
-
-static
-void
-request_fullscreen(struct wl_listener *l, void *data)
-{
- Client *client = wl_container_of(l, client, event.request_fullscreen);
- client->isfullscreen = 1;
-}
-
-void
-make_xdg_surface(struct wl_listener *l, void *data)
-{
- Client *client;
- struct wlr_xdg_toplevel *toplevel;
- struct wlr_xdg_surface *xdg = data;
-
- if(xdg->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
- return;
-
- client = xdg->surface->data = calloc(1, sizeof(*client));
- client->xdg = xdg;
- client->border = cfg·borderpixel;
-
- client->event.map.notify = map;
- wl_signal_add(&xdg->events.map, &client->event.map);
- client->event.unmap.notify = unmap;
- wl_signal_add(&xdg->events.unmap, &client->event.unmap);
- client->event.destroy.notify = destroy;
- wl_signal_add(&xdg->events.destroy, &client->event.destroy);
-
- client->event.commit.notify = commit;
- wl_signal_add(&xdg->surface->events.commit, &client->event.commit);
-
- toplevel = xdg->toplevel;
- client->event.request_move.notify = request_move;
- wl_signal_add(&toplevel->events.request_move, &client->event.request_move);
- client->event.request_title.notify = request_title;
- wl_signal_add(&toplevel->events.set_title, &client->event.request_title);
- client->event.request_resize.notify = request_resize;
- wl_signal_add(&toplevel->events.request_resize, &client->event.request_resize);
- client->event.request_fullscreen.notify = request_fullscreen;
- wl_signal_add(&toplevel->events.request_fullscreen, &client->event.request_fullscreen);
-}
diff --git a/sys/libbio/align.c b/sys/libbio/align.c
deleted file mode 100644
index 20a57df..0000000
--- a/sys/libbio/align.c
+++ /dev/null
@@ -1,178 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <libn/macro/qsort.h>
-#include <libbio.h>
-
-// -----------------------------------------------------------------------
-// globals
-
-uint64 aln·shft = (2ULL * (aln·K - 1ULL));
-uint64 aln·mask = (1ULL << (2*aln·K)) - 1ULL;
-
-// -----------------------------------------------------------------------
-// static data
-
-static uint64 nuctab[256] = {
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-};
-
-// -----------------------------------------------------------------------
-// hash functions
-
-enum
-{
- MURM641 = 0xff51afd7ed558ccd,
- MURM642 = 0xc4ceb9fe1a85ec53
-};
-
-static
-uint64
-minihash(uint64 x, uint64 mask)
-{
- x = (~x + (x << 21)) & mask;
- x = x ^ (x >> 24);
- x = (x + (x << 3) + (x << 8)) & mask;
- x = x ^ (x >> 14);
- x = (x + (x << 2) + (x << 4)) & mask;
- x = x ^ (x >> 28);
- x = (x + (x << 31));
-
- return x;
-}
-
-static
-uint64
-murmurhash(uint64 x, uint64 mask)
-{
- x = x ^ (x >> 33);
- x = (x * MURM641);
- x = x ^ (x >> 33);
- x = (x * MURM642);
- x = x ^ (x >> 33);
-
- return x;
-}
-
-// -----------------------------------------------------------------------
-// locality sensitive hashing (with spatial extent)
-
-static
-void
-sortpos(uintptr len, uint64 vals[], int locs[])
-{
- int tmpi;
- uint64 tmpu64;
-
-#define LESS(i, j) (locs[i] < locs[j])
-#define SWAP(i, j) (tmpu64 = vals[i], tmpi = locs[i], \
- vals[i] = vals[j], locs[i] = locs[j], \
- vals[j] = tmpu64 , locs[j] = tmpi)
- QSORT(len, LESS, SWAP);
-#undef LESS
-#undef SWAP
-}
-
-/*
- * sketch
- * @param seq: '0' terminated string
- * @param len: number of sequential sketches to keep
- * @param vals: buffer to store hashes of sketch.
- * @param locs: buffer to store location of sketch hashes
- */
-error
-aln·sketch(byte *seq, int len, uint64 *vals[aln·N], int *locs[aln·N])
-{
- int i, n, l, *loc;
- uint64 kmer, h[3], *val;
- int tmpi[2];
- uint64 tmpu[2];
-
- for(n = 0; n < aln·N; n++) {
- for(l = 0; l < len; l++) {
- vals[n][l] = UINT64_MAX;
- }
- }
-
- kmer = UINT64_MAX;
- for(l = 0; *seq != '\0'; seq++, l++) {
- kmer = ((kmer << 2) | nuctab[*seq]) & aln·mask;
-
- h[0] = minihash(kmer, aln·mask);
- h[1] = murmurhash(kmer, aln·mask);
-
- for(n = 0; n < aln·N; n++) {
- val = vals[n];
- loc = locs[n];
-
- h[2] = (h[0] + n * h[1]) & aln·mask;
- for (i = 0; i < len && h[2] < val[i]; i++) {
- ;
- }
-
- tmpu[1] = h[2];
- tmpi[1] = l;
- for(i -= 1; i >= 0; i--) {
- tmpu[0] = tmpu[1], tmpu[1] = val[i], val[i] = tmpu[0];
- tmpi[0] = tmpi[1], tmpi[1] = loc[i], loc[i] = tmpi[0];
- }
- }
- }
-
- for(n = 0; n < aln·N; n++) {
- sortpos(len, vals[n], locs[n]);
- }
-
- return 0;
-}
-
-static
-int
-lessarrs(int len, uint64 a[], uint64 b[])
-{
- int l;
-
- for(l = 0; l < len; l++) {
- if (a[l] < b[l]) return 1;
- if (a[l] > b[l]) return 0;
- }
-
- return 0;
-}
-
-static
-void
-swaparrs(int len, uint64 a[], uint64 b[])
-{
- int l;
- uint64 tmp;
-
- for(l = 0; l < len; l++) {
- tmp = a[l], a[l] = b[l], b[l] = tmp;
- }
-}
-
-error
-aln·sort(uintptr n, int len, uint64 *vals)
-{
-#define LESS(i, j) (lessarrs(len, vals+((i)*len), vals+((j)*len)))
-#define SWAP(i, j) (swaparrs(len, vals+((i)*len), vals+((j)*len)))
- QSORT(n, LESS, SWAP);
-#undef LESS
-#undef SWAP
- return 0;
-}
diff --git a/sys/libbio/fasta.c b/sys/libbio/fasta.c
deleted file mode 100644
index 3788544..0000000
--- a/sys/libbio/fasta.c
+++ /dev/null
@@ -1,393 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <libbio.h>
-
-#define INIT_NM_SIZE 128
-#define INIT_SQ_SIZE 4096
-
-struct SeqBuf
-{
- mem·Allocator mem;
- void *heap;
-
- int cap, off;
- byte *it, b[];
-};
-
-static
-void
-reset(struct SeqBuf *sb)
-{
- sb->off = 0;
- sb->it = sb->b;
-}
-
-static
-error
-grow(struct SeqBuf **sb, int min)
-{
- void* heap;
- mem·Allocator mem;
-
- vlong newcap;
- struct SeqBuf *old, *new;
-
- old = *sb;
- mem = old->mem;
- heap = old->heap;
-
- assert((*sb)->cap <= (SIZE_MAX - 1) / 2);
- newcap = MAX(16, MAX(1 + 2*(*sb)->cap, (*sb)->cap+min));
- assert(newcap >= (*sb)->cap+min);
-
- if(new = mem.alloc(heap, 1, sizeof(*new)+newcap), !new) {
- errorf("memory: could not allocate new buffer\n");
- return 1;
- }
-
- memcpy(new, old, sizeof(*new) + (*sb)->cap);
-
- new->cap = newcap;
- new->it = new->b + (old->it - old->b);
- mem.free(heap, old);
-
- *sb = new;
- return 0;
-}
-
-static
-error
-put(struct SeqBuf **sb, byte c)
-{
- int err;
- struct SeqBuf *sq;
-
- sq = *sb;
- if(sq->it < (sq->b + sq->cap)) {
- *sq->it++ = c;
- return 0;
- }
-
- if(err = grow(sb, 1), err) {
- errorf("memory fail: could not allocate more buffer\n");
- sq->mem.free(sq->heap, sq);
- return 1;
- }
-
- *((*sb)->it++) = c;
- return 0;
-}
-
-static
-error
-push(struct SeqBuf **sb, int n, void *buf)
-{
- int d, err;
- struct SeqBuf *seq;
-
- seq = *sb;
- if(d = (seq->cap - (seq->it - seq->b)), d < n) {
- assert(d >= 0);
- if (err = grow(sb, n-d), err) {
- errorf("memory fail: could not allocate more buffer\n");
- seq->mem.free(seq->heap, seq);
- return 1;
- }
- }
- seq = *sb;
-
- memcpy(seq->it, buf, n);
- seq->it += n;
-
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// sequence data
-
-struct bio·SeqReader {
- byte eof;
- io·Reader rdr;
- void *io;
-
- struct SeqBuf *seq;
-
- /* read buffer */
- byte *b, *bend, buf[4*4098];
-};
-
-static
-error
-fill(bio·SeqReader *rdr)
-{
- int n;
- // NOTE: This could lead to an infinite loop.
- if(rdr->eof)
- return 0;
-
- n = rdr->rdr.read(rdr->io, 1, arrlen(rdr->buf), rdr->buf);
- if(n < 0) {
- errorf("read: no data obtained from reader\n");
- return 1;
- }
- rdr->b = rdr->buf;
- rdr->bend = rdr->b + n;
- if(rdr->eof = (n < arrlen(rdr->buf)), rdr->eof)
- *rdr->bend++ = '\0';
-
- return 0;
-}
-
-bio·SeqReader*
-bio·openseq(io·Reader rdr, void *io, mem·Allocator mem, void *heap)
-{
- error err;
- bio·SeqReader *r;
-
- r = mem.alloc(heap, 1, sizeof(bio·SeqReader));
- r->rdr = rdr;
- r->io = io;
- r->eof = 0;
-
- r->seq = mem.alloc(heap, 1, sizeof(*r->seq) + INIT_NM_SIZE + INIT_SQ_SIZE);
- r->seq->mem = mem;
- r->seq->heap = heap;
- r->seq->it = r->seq->b;
- r->seq->cap = INIT_NM_SIZE + INIT_SQ_SIZE;
-
- if (err=fill(r), err) {
- errorf("fill: could not populate buffer\n");
- goto ERROR;
- }
-
- return r;
-
-ERROR:
- mem.free(heap, r->seq);
- mem.free(heap, r);
- return nil;
-}
-
-error
-bio·closeseq(bio·SeqReader *rdr)
-{
- mem·Allocator mem;
- void *heap;
-
- mem = rdr->seq->mem;
- heap = rdr->seq->heap;
-
- mem.free(heap, rdr->seq);
- mem.free(heap, rdr);
-
- return 0;
-}
-
-
-static
-error
-readfasta(bio·SeqReader *rdr, bio·Seq *seq, byte hdr, byte stop)
-{
- error err;
- byte *beg;
-
- if(rdr->eof && rdr->b == rdr->bend-1)
- return EOF;
-
- reset(rdr->seq);
-
- // NOTE: Can this case happen?
- assert(rdr->b != rdr->bend);
- if(*rdr->b++ != hdr) {
- errorf("fasta/q format: expected '%c', found '%c'\n", hdr, *rdr->b--);
- return 1;
- }
-
-NAME:
- beg = rdr->b;
- while(rdr->b != rdr->bend) {
- if(*rdr->b++ == '\n') {
- push(&rdr->seq, (rdr->b - 1) - beg, beg);
- goto SEQ;
- }
- }
- push(&rdr->seq, rdr->b - beg, beg);
-
- if(err=fill(rdr), err) {
- errorf("read: could not populate buffer\n");
- return 1;
- }
- goto NAME;
-
-SEQ:
- put(&rdr->seq, '\0');
- rdr->seq->off = rdr->seq->it - rdr->seq->b;
-
-SEQLOOP:
- beg = rdr->b;
- while(rdr->b != rdr->bend) {
- if(*rdr->b == '\n') {
- push(&rdr->seq, rdr->b - beg, beg);
- beg = rdr->b + 1;
- }
-
- if(*rdr->b == stop || *rdr->b == '\0')
- goto SUCCESS;
-
- rdr->b++;
- }
-
- push(&rdr->seq, rdr->b - beg, beg);
-
- if(err=fill(rdr), err) {
- errorf("read: could not populate buffer\n");
- return 1;
- }
- goto SEQLOOP;
-
-SUCCESS:
- push(&rdr->seq, rdr->b - beg, beg);
- put(&rdr->seq, '\0');
-
- return 0;
-}
-
-/*
- * fasta files
- */
-
-error
-bio·readfasta(bio·SeqReader *rdr, bio·Seq *seq)
-{
- error err;
-
- err = readfasta(rdr, seq, '>', '>');
- if(err && err != EOF) {
- errorf("parse fail: could not read sequence of record\n");
- return err;
- }
-
- seq->name = rdr->seq->b;
- seq->s = rdr->seq->b + rdr->seq->off;
- seq->len = rdr->seq->it - seq->s - 1; // shift by 1 as we pushed a '0' to end
- seq->q = nil;
-
- return err;
-}
-
-/*
- * fastq files
- */
-
-error
-bio·readfastq(bio·SeqReader *rdr, bio·Seq *seq)
-{
- int n;
- byte *beg;
- error err;
-
- err = readfasta(rdr, seq, '@', '+');
- if(err) {
- errorf("parse fail: could not read sequence of record\n");
- return err;
- }
-
- seq->len = rdr->seq->it - (rdr->seq->b + rdr->seq->off);
-
- if(*rdr->b++ != '+') {
- errorf("format error: no '+' character seperator found\n");
- return -1;
- }
-
-EATLN:
- while(rdr->b != rdr->bend) {
- if (*rdr->b++ == '\n') {
- n = 0;
- goto QUAL;
- }
- }
-
- if(err = fill((bio·SeqReader*)rdr), err) {
- errorf("read: could not populate buffer\n");
- return 1;
- }
- goto EATLN;
-
-QUAL:
- beg = rdr->b;
- while(rdr->b != rdr->bend) {
- if(*rdr->b == '\n') {
- push(&rdr->seq, rdr->b - beg, beg);
- beg = rdr->b + 1;
- }
-
- if(n++ == seq->len || *rdr->b == '\0') {
- err = *rdr->b == '\0' ? EOF : 0;
- goto SUCCESS;
- }
-
- rdr->b++;
- }
-
- push(&rdr->seq, rdr->b - beg, beg);
-
- if(err = fill((bio·SeqReader*)rdr), err) {
- errorf("read: could not populate buffer\n");
- return 1;
- }
- goto QUAL;
-
-
-SUCCESS:
- push(&rdr->seq, rdr->b - beg, beg);
- put(&rdr->seq, '\0');
-
- seq->name = rdr->seq->b;
- seq->s = rdr->seq->b + rdr->seq->off - 1;
- seq->q = seq->s + seq->len + 1;
-
- return err;
-}
-
-// -----------------------------------------------------------------------
-// sequence writing
-
-error
-bio·writefasta(io·Writer io, void *wtr, bio·Seq seq)
-{
- int i, j, d;
- char buf[2048], *b = buf, *e = arrend(buf);
-
- *b++ = '>';
- while(*seq.name) {
- *b++ = *seq.name++;
- if(b == e) {
- io.write(wtr, 1, arrlen(buf), buf);
- b = buf;
- }
- }
-
- for(i=0; i<seq.len; i = j) {
- j = MIN(i+70, seq.len);
- d = j - i;
- if((e-b) <= d+1) {
- io.write(wtr, 1, b-buf, buf);
- b = buf;
- }
- *b++ = '\n';
- memcpy(b, seq.s+i, d);
- b += d;
- }
-
- *b++ = '\n';
- io.write(wtr, 1, b-buf, buf);
-
- return 0;
-}
-
-error
-bio·writefastq(io·Writer io, void *wtr, bio·Seq seq)
-{
- panicf("need to implement");
- return 1;
-}
diff --git a/sys/libbio/newick.c b/sys/libbio/newick.c
deleted file mode 100644
index 5e6d30a..0000000
--- a/sys/libbio/newick.c
+++ /dev/null
@@ -1,414 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <libbio.h>
-
-// -----------------------------------------------------------------------
-// Tokens
-
-enum TokenKind
-{
- tok·nil,
- tok·eof,
- tok·space,
- tok·ident,
- tok·number,
- tok·lparen,
- tok·rparen,
- tok·lbrak,
- tok·rbrak,
- tok·comma,
- tok·semi,
- tok·colon,
-
- NUM_TOKENS,
-};
-
-
-struct Token {
- enum TokenKind kind;
- union
- {
- byte *s;
- double x;
- } lit;
-};
-
-static
-byte*
-tokstr(struct Token tok)
-{
- static byte b[50];
- switch (tok.kind) {
- case tok·nil: return "";
- case tok·eof: return nil;
- case tok·space: return " ";
- case tok·ident: return tok.lit.s;
- case tok·lparen: return "(";
- case tok·rparen: return ")";
- case tok·lbrak: return "[";
- case tok·rbrak: return "]";
- case tok·comma: return ",";
- case tok·semi: return ";";
- case tok·colon: return ":";
- case tok·number:
- snprintf(b, arrlen(b), "%f", tok.lit.x);
- return b;
- default:
- return nil;
- }
-}
-
-
-// -----------------------------------------------------------------------
-// Read
-
-// TODO: Bounds checking on buffer
-static
-struct Token
-lex(io·Peeker s, void* fp)
-{
-#define isvalidchar(C) ((C) == '!') || \
- ('\"' < (C) && (C) < '\'') || \
- (')' < (C) && (C) < '+') || \
- (',' < (C) && (C) < ':') || \
- (':' < (C) && (C) < '[') || \
- ((C) == '\\') || \
- (']' < (C) && (C) <= '~')
- byte *c;
- struct Token tok;
- static byte b[1024];
- c = b;
- *c = s.get(fp);
-
- if (isspace(*c)) {
- while (isspace(*c)) {
- *(++c) = s.get(fp);
- }
-
- s.unget(fp, *c);
- assert(c - b < 1024);
-
- *c = 0;
- tok.kind = tok·space;
- tok.lit.s = b;
- return tok;
- }
-
- switch (*c) {
- case EOF: tok.kind = tok·eof; return tok;
- case '(': tok.kind = tok·lparen; return tok;
- case ')': tok.kind = tok·rparen; return tok;
- case '[': tok.kind = tok·lbrak; return tok;
- case ']': tok.kind = tok·rbrak; return tok;
- case ',': tok.kind = tok·comma; return tok;
- case ';': tok.kind = tok·semi; return tok;
- case ':': tok.kind = tok·colon; return tok;
-
- case '.':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- while (isdigit(*c)) {
- NUM: *(++c) = s.get(fp);
- }
- if (*c == '.') goto NUM;
- if (isvalidchar(*c)) goto IDENT;
-
- s.unget(fp, *c);
- assert(c - b < 1024);
-
- *c = 0;
- tok.kind = tok·number;
- tok.lit.x = atof(b);
- return tok;
-
- case '\"':
- while ((*c) != '\"') {
- *(++c) = s.get(fp);
- }
- assert(c - b < 1024);
-
- *c = '\0';
- tok.kind = tok·ident;
- tok.lit.s = b + 1;
- return tok;
-
- default:
- IDENT:
- while (isvalidchar(*c)) {
- *(++c) = s.get(fp);
- }
- s.unget(fp, *c);
- assert(c - b < 1024);
-
- *c = '\0';
- tok.kind = tok·ident;
- tok.lit.s = b;
- return tok;
- }
-#undef isvalidchar
-}
-
-static
-struct Token
-lex_nospace(io·Peeker s, void *impl)
-{
- struct Token tok;
- tok = lex(s, impl);
- if (tok.kind == tok·space) {
- tok = lex_nospace(s, impl);
- }
-
- return tok;
-}
-
-struct Parser
-{
- int lev;
- bio·Node *root;
- struct Token tok;
-
- void *io;
- io·Peeker file;
- void *heap;
- mem·Allocator mem;
-};
-
-static
-error
-parse(struct Parser *p)
-{
- error err;
- bio·Node *node;
- bio·Node *root;
- struct Token tok;
-
- node = p->root;
- for (;;) {
- tok = lex_nospace(p->file, p->io);
-
- switch (tok.kind) {
- case tok·lparen:
- if (!p->root && p->lev > 0) {
- errorf("parse format: attempted to make root at non-zero level");
- goto ERROR;
- }
-
- node = p->mem.alloc(p->heap, 1, sizeof(*node));
- memset(node, 0, sizeof(*node));
-
- if (p->root) {
- phylo·addchild(p->root, node);
- root = p->root;
- } else {
- root = node;
- }
-
- p->lev++;
- p->root = node;
- p->tok = tok;
- err = parse(p);
- if (err) {
- goto ERROR;
- }
- if (p->tok.kind != tok·rparen) {
- errorf("incorrect format: closing parentheses expected to proceed opening");
- goto ERROR;
- }
- p->root = root;
- // NOTE(nnoll): We don't want to override the state of p->tok here!
- // Jump straight to grabbing next token.
- continue;
-
- case tok·rparen:
- p->lev--;
- goto DONE;
-
- /* Comments */
- case tok·lbrak:
- if (!node) {
- errorf("incorrect format: comment found in disallowed region");
- goto ERROR;
- }
- node->comment = str·make("");
- while (tok.kind != tok·rbrak) {
- tok = lex_nospace(p->file, p->io);
- if (tok.kind == tok·eof || tok.kind == tok·nil) {
- errorf("incorrect format: unmatched comment bracket '['");
- goto ERROR;
- }
- str·append(&node->comment, tokstr(tok));
- }
- break;
-
- case tok·rbrak:
- errorf("incorrect format: end comment token found in disallowed region");
- goto ERROR;
- break;
-
- case tok·colon:
- tok = lex_nospace(p->file, p->io);
- if (tok.kind != tok·number) {
- errorf("incorrect format: expected number after colon");
- goto ERROR;
- }
- if (node == nil) {
- errorf("parse error: attempting to set distance of nil node");
- goto ERROR;
- }
- node->dist = tok.lit.x;
- break;
-
- case tok·comma:
- node = nil;
- break;
-
- case tok·ident:
- if (p->tok.kind == tok·rparen) {
- if (!node) {
- errorf("parse error: attempting to set name of nil node");
- goto ERROR;
- }
- node->name = str·make(tok.lit.s);
- } else {
- if (p->tok.kind != tok·lparen && p->tok.kind != tok·comma) {
- errorf("format error: misplaced identifier for leaf found");
- goto ERROR;
- }
-
- if (!p->root) {
- errorf("parse error: attempting to create child for no parent");
- goto ERROR;
- }
-
- node = p->mem.alloc(p->heap, 1, sizeof(*node));
- memset(node, 0, sizeof(*node));
-
- node->name = str·make(tok.lit.s);
-
- phylo·addchild(p->root, node);
- }
- break;
-
- case tok·number:
- if (p->tok.kind == tok·rparen) {
- if (p->lev == 0) {
- errorf("format error: support value on root not supported");
- goto ERROR;
- }
- node->support = tok.lit.x;
- } else {
- errorf("format error: found number in unexpected location");
- goto ERROR;
- }
- break;
-
- case tok·semi:
- p->file.unget(p->io, ';');
- if (p->lev) {
- errorf("format error: uneven number of parentheses found at ';'");
- goto ERROR;
- }
- goto DONE;
-
- case tok·eof:
- goto DONE;
-
- default:
- errorf("parse error: unrecognized token");
- goto ERROR;
- }
-
- p->tok = tok;
- }
-
-DONE:
- p->tok = tok;
- return 0;
-ERROR:
- // TODO(nnoll): cleanup
- return 1;
-}
-
-int
-bio·readnewick(io·Peeker stream, void *s, bio·Tree *tree)
-{
- error err;
- struct Parser p;
-
- if (!tree) {
- errorf("tree pointer nil");
- return 0;
- }
-
- p = (struct Parser){
- .lev = 0,
- .root = nil,
- .tok = (struct Token){ 0 },
- .io = s,
- .file = stream,
- .mem = tree->mem,
- .heap = tree->heap,
- };
- err = parse(&p);
- if (err) {
- errorf("parsing failed\n");
- return 0;
- }
-
- tree->root = p.root;
- tree->nleaf = 0;
- tree->root->nnode = 0;
-
- phylo·countleafs(tree->root, &tree->nleaf);
- phylo·countnodes(tree->root, &tree->root->nnode);
-
- return 1;
-}
-
-// -----------------------------------------------------------------------
-// Write
-
-static
-error
-dump(bio·Node *node, void *impl, io·Putter out)
-{
- byte b[24];
-
- if (!node) {
- return 1;
- }
-
- bio·Node *child;
- if (node->nchild) {
- out.put(impl, '(');
-
- dump(node->child, impl, out);
- for (child = node->child->sibling; child != nil; child = child->sibling) {
- out.put(impl, ',');
- dump(child, impl, out);
- }
-
- out.put(impl, ')');
- }
- if (node->name) {
- out.puts(impl, node->name);
- }
-
- if (node->parent) {
- out.put(impl, ':');
- snprintf(b, arrlen(b), "%f", node->dist);
- out.puts(impl, b);
- }
-
- return 0;
-}
-
-error
-bio·writenewick(bio·Tree tree, io·Putter out, void* impl)
-{
- dump(tree.root, impl, out);
- out.put(impl, ';');
- out.put(impl, '\n');
-
- return 0;
-}
diff --git a/sys/libbio/phylo.c b/sys/libbio/phylo.c
deleted file mode 100644
index d50934f..0000000
--- a/sys/libbio/phylo.c
+++ /dev/null
@@ -1,427 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <base/macro/qsort.h>
-#include <libbio.h>
-
-// -----------------------------------------------------------------------
-// subtree manipulation methods
-// NOTE: As of now these don't update nnode & nleaf stats.
-// It is the caller's responsibility to refresh counts.
-
-error
-phylo·addchild(bio·Node* parent, bio·Node* child)
-{
- bio·Node *it, *sibling;
- if (!parent->nchild) {
- parent->child = child;
- goto SUCCESS;
- }
-
- for (it = parent->child, sibling = it; it != nil; it = it->sibling) {
- sibling = it;
- }
- sibling->sibling = child;
-
-SUCCESS:
- child->parent = parent;
- parent->nchild++;
- return 0;
-}
-
-error
-phylo·rmchild(bio·Node *parent, bio·Node *child)
-{
- bio·Node *it, *prev;
- enum {
- error·nil,
- error·notfound,
- error·nochildren,
- };
-
- prev = nil;
- for (it = parent->child; it != nil; it = it->sibling) {
- if (it == child) goto FOUND;
- prev = it;
- }
- return error·notfound;
-
-FOUND:
- if (prev == nil) {
- parent->child = child->sibling;
- } else {
- prev->sibling = child->sibling;
- }
-
- parent->nchild--;
- return error·nil;
-}
-
-// -----------------------------------------------------------------------
-// subtree statistics
-
-error
-phylo·countnodes(bio·Node *node, int *n)
-{
- int m;
- error err;
- bio·Node *child;
-
- m = *n;
- for (child = node->child; child != nil; child = child->sibling) {
- if (err = phylo·countnodes(child, n), err) {
- errorf("node count: failure at '%s'", child->name);
- return 1;
- }
- }
- node->nnode = *n - m;
- *n += 1;
-
- return 0;
-}
-
-error
-phylo·countleafs(bio·Node *node, int *n)
-{
- error err;
- bio·Node *child;
-
- if (!node->nchild) {
- *n += 1;
- }
-
- for (child = node->child; child != nil; child = child->sibling) {
- if (err = phylo·countleafs(child, n), err) {
- errorf("leaf count: failure at '%s'", child->name);
- return 1;
- }
- }
-
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// generic operations on tree
-
-void*
-phylo·postorder(bio·Node *clade, void *(*op)(bio·Node*, void*), void *ctx)
-{
- bio·Node *it;
-
- for(it = clade->child; it != nil; it = it->sibling) {
- ctx = phylo·postorder(it, op, ctx);
- }
-
- return op(clade, ctx);
-}
-
-void*
-phylo·preorder(bio·Node *clade, void *(*op)(bio·Node*, void*), void *ctx)
-{
- bio·Node *it;
-
- ctx = op(clade, ctx);
- for(it = clade->child; it != nil; it = it->sibling) {
- ctx = phylo·preorder(it, op, ctx);
- }
-
- return ctx;
-}
-
-int
-phylo·collectpostorder(bio·Node *clade, bio·Node **list)
-{
- bio·Node *it;
- int n;
-
- for(n = 0, it = clade->child; it != nil; it = it->sibling) {
- n += phylo·collectpostorder(it, list+n);
- }
-
- return n;
-}
-
-static
-inline
-void*
-appendleaf(bio·Node *node, void* list)
-{
- bio·Node **leafs;
-
- leafs = list;
- if (!node->nchild) {
- *leafs++ = node;
- }
-
- return leafs;
-}
-
-void
-phylo·getleafs(bio·Tree tree, bio·Node **leafs)
-{
- phylo·postorder(tree.root, &appendleaf, leafs);
-}
-
-// -----------------------------------------------------------------------
-// tree editing
-
-static
-void
-sortnodelist(bio·Node **head, bio·Node *next)
-{
- bio·Node tmp, *it;
-
- it = &tmp;
- tmp.sibling = *head;
-
- while (it->sibling != nil && it->sibling->nnode < next->nnode) {
- it = it->sibling;
- }
-
- next->sibling = it->sibling;
- it->sibling = next;
- *head = tmp.sibling;
-}
-
-error
-phylo·ladderize(bio·Node *root)
-{
- int i;
- error err;
- bio·Node *child, *sorted, *sibling;
-
- if (!root->nchild) return 0;
-
- // ladderize below
- for (child = root->child; child != nil; child = child->sibling) {
- if (err = phylo·ladderize(child), err) {
- errorf("ladderize: failure at '%s'", child->name);
- return 1;
- }
- }
-
- // ladderize yourself
- sorted = nil;
- child = root->child;
- while (child != nil) {
- sibling = child->sibling;
- sortnodelist(&sorted, child);
- child = sibling;
- }
- root->child = sorted;
-
- return 0;
-}
-
-/*
- * compute all distances from a given node
- * must provide a working buffer
- */
-
-struct Tuple
-{
- double *d;
- bio·Node **n;
-};
-
-static
-struct Tuple
-getdistsfrom(bio·Node *node, bio·Node *prev, double curr, double *dist, bio·Node **list)
-{
- bio·Node *it;
- struct Tuple ret;
-
- *dist++ = curr;
- *list++ = node;
-
- ret.d = dist;
- ret.n = list;
-
- if (node->parent && node->parent != prev) {
- ret = getdistsfrom(node->parent, node, curr + node->dist, dist, list);
-
- dist = ret.d;
- list = ret.n;
- }
-
- for (it = node->child; it != nil; it = it->sibling) {
- if (it != prev) {
- ret = getdistsfrom(it, node, curr + it->dist, dist, list);
-
- dist = ret.d;
- list = ret.n;
- }
- }
-
- return ret;
-}
-
-int
-phylo·getdistsfrom(bio·Node *node, int len, double *dist, bio·Node **list)
-{
- struct Tuple ret;
- // TODO: Better bounds checking.
-
- ret = getdistsfrom(node, nil, 0.0, dist, list);
-
- assert(ret.n - list == len);
- assert(ret.d - dist == len);
-
- return len;
-}
-
-/*
-static
-void
-disttoroot(bio·Node *clade, double anc, double *dists)
-{
- double d;
- bio·Node *it;
-
- *dists++ = anc + clade->dist;
- d = dists[-1];
- for (it = clade->child; it != nil; it = it->sibling) {
- disttoroot(it, d, ++dists);
- }
-}
-
-void
-phylo·disttoroot(bio·Tree tree, double *dists)
-{
- disttoroot(tree.root, 0.0, dists);
-}
-*/
-
-/*
- * compute the path constituting the tree diameter
- * returns the number of edges in the path
- */
-
-static
-void
-sort·nodedists(uintptr len, double fs[], bio·Node* ns[])
-{
- double f;
- bio·Node *n;
-#define LESS(i, j) (fs[i] < fs[j])
-#define SWAP(i, j) (n = ns[i], f = fs[i], \
- fs[i] = fs[j], ns[i] = ns[j], \
- fs[j] = f, ns[j] = n)
- QSORT(len, LESS, SWAP);
-#undef LESS
-#undef SWAP
-}
-
-#define BUFLEN 4096
-double
-phylo·diameter(bio·Tree tree, int *len, bio·Node **path)
-{
- // TODO: deal with large tree > BUFLEN gracefully
- int n;
- double fbuf[BUFLEN];
- bio·Node *nbuf[BUFLEN];
-
- n = tree.root->nnode;
-
- assert(n < BUFLEN);
-
- n = phylo·getdistsfrom(tree.root, tree.root->nnode, fbuf, nbuf);
- sort·nodedists(n, fbuf, nbuf);
-
- path[0] = nbuf[n-1];
- printf("first end '%s'\n", path[0]->name);
-
- n = phylo·getdistsfrom(path[0], n, fbuf, nbuf);
- sort·nodedists(n, fbuf, nbuf);
- printf("second end '%s'\n", nbuf[n-1]->name);
-
- *len = 0;
-
- // TODO: Traverse up the tree from each node
- // Find MRCA by intersection of nodes hit
-
- return 0.0;
-}
-#undef BUFLEN
-
-/*
- * reroot a tree on a new node
- */
-static
-error
-rotateparent(bio·Node *node, bio·Node *to)
-{
- error err;
-
- // NOTE: will this ever be taken?
- if (node->parent == to) {
- return 0;
- }
-
- if (!node->parent) {
- goto RMCHILD;
- }
-
- err = rotateparent(node->parent, node);
- if (err) {
- errorf("failure: broken tree");
- return err;
- }
-
- err = phylo·addchild(node, node->parent);
- if (err) {
- errorf("inconsistent topology: could not add parent '%s' as child of '%s'", node->parent->name, node->name);
- return err;
- }
-
-RMCHILD:
- err = phylo·rmchild(node, to);
- if (err) {
- errorf("inconsistent topology: could not remove child '%s' from '%s'", to->name, node->name);
- return err;
- }
-
- node->parent = to;
- return 0;
-}
-
-#define PREC .00000001
-error
-phylo·reroot(bio·Tree *tree, bio·Node *node, double d)
-{
- bio·Node *new;
-
- // TODO: should check that node is part of this tree?
- // TODO: should we check if node->parent != nil?
-
- if (fabs(d) < PREC) {
- new = node;
- rotateparent(node->parent, node);
- } else if (fabs(d-node->dist) < PREC) {
- new = node->parent;
- if (new->parent->parent) {
- rotateparent(new->parent->parent, new->parent);
- }
- } else {
- new = tree->mem.alloc(tree->heap, 1, sizeof(*new));
- memset(new, 0, sizeof(*new));
-
- phylo·addchild(new, node);
- node->parent = new;
-
- phylo·addchild(new, node->parent);
- if (node->parent->parent) {
- rotateparent(node->parent->parent, node->parent);
- }
- node->parent->parent = new;
- }
-
- printf("number of children on old root: %d\n", tree->root->nchild);
- tree->root = new;
- tree->nleaf = 0;
-
- phylo·countleafs(new, &tree->nleaf);
- phylo·countnodes(new, &new->nnode);
-
- return 0;
-}
-#undef PREC
diff --git a/sys/libbio/rules.mk b/sys/libbio/rules.mk
deleted file mode 100644
index cbc6887..0000000
--- a/sys/libbio/rules.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := \
- $(d)/fasta.c \
- $(d)/newick.c \
- $(d)/phylo.c
-LIBS_$(d) := $(d)/libbio.a
-BINS_$(d) :=
-# TSTS_$(d) := \
-# $(d)/test.c \
-# $(d)/simulate.c
-
-include share/paths.mk
-
-# Local rules
-# $(LIBS_$(d)) = TCFLAGS :=
-# $(LIBS_$(d)) = TCINCS :=
-# $(LIBS_$(d)) = TCLIBS :=
-
-$(LIBS_$(d)): $(OBJS_$(d)) $(OBJS_$(d)/io)
- $(ARCHIVE)
-
-$(UNTS_$(d)): TCLIBS := $(LIBS_$(d)) $(OBJ_DIR)/libn/libn.a
-$(UNTS_$(d)): $(TOBJS_$(d)) $(LIBS_$(d)) $(OBJ_DIR)/libn/libn.a
- $(LINK)
-
-include share/pop.mk
diff --git a/sys/libbio/simulate.c b/sys/libbio/simulate.c
deleted file mode 100644
index 0f5a97e..0000000
--- a/sys/libbio/simulate.c
+++ /dev/null
@@ -1,120 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <libbio.h>
-
-#define SEQLEN 2560
-static byte *SEQ =
-"GGCGGCTTCGGTGCGCTGTGTGCATTGCCGCAAAAATATCGTGAACCCGTGCTGGTTTCCGGCACTGACGGCGTAGGTAC"
-"CAAGCTGCGTCTGGCAATGGACTTAAAACGTCACGACACCATTGGTATTGATCTGGTCGCCATGTGCGTTAATGACCTGG"
-"TGGTGCAAGGTGCGGAACCGCTGTTTTTCCTCGACTATTACGCAACCGGAAAACTGGATGTTGATACCGCTTCAGCGGTG"
-"ATCAGCGGCATTGCGGAAGGTTGTCTGCAATCGGGCTGTTCTCTGGTGGGTGGCGAAACGGCAGAAATGCCGGGGATGTA"
-"TCACGGTGAAGATTACGATGTCGCGGGTTTCTGCGTGGGCGTGGTAGAAAAATCAGAAATCATCGACGGCTCTAAAGTCA"
-"GCGACGGCGATGTGCTGATTGCACTCGGTTCCAGCGGTCCGCACTCGAACGGTTATTCGCTGGTGCGCAAAATTCTTGAA"
-"GTCAGCGGTTGTGATCCGCAAACCACCGAACTTGATGGTAAGCCATTAGCCGATCATCTGCTGGCACCGACCCGCATTTA"
-"CGTGAAGTCAGTGCTGGAGTTGATTGAAAAGGTCGATGTGCATGCCATTGCGCACCTGACCGGCGGCGGCTTCTGGGAAA"
-"ACATTCCGCGCGTATTGCCAGATAATACCCAGGCAGTGATTGATGAATCTTCCTGGCAGTGGCCGGAAGTGTTCAACTGG"
-"CTGCAAACGGCAGGTAACGTTGAGCGCCATGAAATGTATCGCACCTTCAACTGCGGCGTCGGGATGATTATCGCCCTGCC"
-"TGCTCCGGAAGTGGACAAAGCCCTCGCCCTGCTCAATGCCAACGGTGAAAACGCGTGGAAAATCGGTATCATCAAAGCCT"
-"CTGATTCCGAACAACGCGTGGTTATCGAATAATGAATATTGTGGTGCTTATTTCCGGCAACGGAAGTAATTTACAGGCAA"
-"TTATTGACGCCTGTAAAACCAACAAAATTAAAGGCACCGTACGGGCAGTTTTCAGCAATAAGGCCGACGCGTTCGGCCTT"
-"GAACGCGCCCGCCAGGCGGGTATTGCAACGCATACGCTCATCGCCAGCGCGTTTGACAGTCGTGAAGCCTATGACCGGGA"
-"GTTGATTCATGAAATCGACATGTACGCACCCGATGTGGTCGTGCTGGCTGGTTTTATGCGCATTCTCAGCCCGGCGTTTG"
-"TCTCCCACTATGCCGGGCGTTTGCTGAACATTCACCCTTCTCTGCTGCCGAAATATCCCGGATTACACACCCATCGTCAA"
-"GCGCTGGAAAATGGCGATGAAGAGCACGGTACATCGGTGCATTTCGTCACCGATGAACTGGACGGTGGCCCGGTTATTTT"
-"ACAGGCGAAAGTCCCGGTATTTGCTGGTGATACGGAAGATGACGTCACCGCCCGCGTGCAAACCCAGGAACACGCCATTT"
-"ATCCACTGGTGATTAGCTGGTTTGCCGATGGTCGTCTGAAAATGCACGAAAACGCCGCGTGGCTGGATGGTCAACGTCTG"
-"CCGCCGCAGGGCTACGCTGCCGACGAGTAATGCCCCCGTAGTTAAAGCGCCAGCTCTGCCGCTGGCGTTTTTCAATTCAC"
-"CTGTAAATCGCAAGCTCCAGCAGTTTTTTTCCCCCTTTTCTGGCATAGTTGGACATCTGCCAATATTGCTCGCCATAATA"
-"TCCAGGCAGTGTCCCGTGAATAAAACGGAGTAAAAGTGGTAATGGGTCAGGAAAAGCTATACATCGAAAAAGAGCTCAGT"
-"TGGTTATCGTTCAATGAACGCGTGCTTCAGGAAGCGGCGGACAAATCTAACCCGCTGATTGAAAGGATGCGTTTCCTGGG"
-"GATCTATTCCAATAACCTTGATGAGTTCTATAAAGTCCGCTTCGCTGAACTGAAGCGACGCATCATTATTAGCGAAGAAC"
-"AAGGCTCCAACTCTCATTCCCGCCATTTACTGGGCAAAATTCAGTCCCGGGTGCTGAAAGCCGATCAGGAATTCGACGGC"
-"CTCTACAACGAGCTATTGCTGGAGATGGCGCGCAACCAGATCTTCCTGATTAATGAACGCCAGCTCTCCGTCAATCAACA"
-"AAACTGGCTGCGTCATTATTTTAAGCAGTATCTGCGTCAGCACATTACGCCGATTTTAATCAATCCTGACACTGACTTAG"
-"TGCAGTTCCTGAAAGATGATTACACCTATCTGGCGGTGGAAATTATCCGTGGCGATACCATCCGTTACGCGCTTCTGGAG"
-"ATCCCATCAGATAAAGTGCCGCGCTTTGTGAATTTACCGCCAGAAGCGCCGCGTCGACGCAAGCCGATGATTCTTCTGGA"
-"TAACATTCTGCGTTACTGCCTTGATGATATTTTCAAAGGCTTCTTTGATTATGACGCGCTGAATGCCTATTCAATGAAGA"
-"TGACCCGCGATGCCGAATACGATTTAGTGCATGAGATGGAAGCCAGCCTGATGGAGTTGATGTCTTCCAGTCTCAAGCAG"
-"CGTTTAACTGCTGAGCCGGTGCGTTTTGTTTATCAGCGCGATATGCCCAATGCGCTGGTTGAAGTTTTACGCGAAAAACT";
-
-byte*
-modify(byte *seq, int *len, double p)
-{
- byte *head, *new;
-
- head = calloc(SEQLEN+1, sizeof(byte));
- new = head;
- for (; *seq != '\0'; seq++) {
- if (rng·bernoulli(p)) {
- switch (rng·randi(5)) {
- case 0: *new++ = 'A'; break;
- case 1: *new++ = 'C'; break;
- case 2: *new++ = 'G'; break;
- case 3: *new++ = 'T'; break;
- case 4: continue;
- }
- } else {
- *new++ = *seq;
- }
- }
- *new = '\0';
- *len = new - head;
- return head;
-}
-
-#define NSEQS 20
-int
-main()
-{
- int n, i, l, lens[NSEQS];
- byte *seqs[NSEQS];
-
- int locs[aln·N][NSEQS][aln·L];
- int *loc[aln·N];
- uint64 vals[aln·N][NSEQS][aln·L];
- uint64 *val[aln·N];
-
- rng·init(0);
-
- seqs[0] = SEQ;
- lens[0] = SEQLEN;
-
- for (n = 0; n < aln·N; n++) {
- for (i = 0; i < NSEQS; i++) {
- for (l = 0; l < aln·L; l++) {
- vals[n][i][l] = 0;
- }
- }
- }
-
- for (i = 1; i < NSEQS; i++) {
- seqs[i] = modify(SEQ, lens + i, .01*i);
- }
-
- for (i = 0; i < NSEQS; i++) {
- for (n = 0; n < aln·N; n++) {
- val[n] = vals[n][i];
- loc[n] = locs[n][i];
- }
- aln·sketch(seqs[i], aln·L, val, loc);
- }
-
- // for (n = 0; n < aln·N; n++) {
- // printf("iteration %d\n", n);
- // printf("[\n");
- // for (i = 0; i < NSEQS; i++) {
- // printf(" [");
- // for (l = 0; l < aln·L; l++) {
- // printf("%lu,", vals[n][i][l]);
- // }
- // printf("],\n");
- // }
- // printf("]\n");
- // }
-
- for (n = 0; n < aln·N; n++) {
- aln·sort(NSEQS, aln·L, (uint64*)vals[n]);
- }
-
- return 0;
-}
diff --git a/sys/libbio/test.c b/sys/libbio/test.c
deleted file mode 100644
index 9926764..0000000
--- a/sys/libbio/test.c
+++ /dev/null
@@ -1,283 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <libbio.h>
-
-#include <time.h>
-
-// -----------------------------------------------------------------------
-// Global data
-
-static byte *SEQ[] = {
-"GGCGGCTTCGGTGCGCTGTGTGCATTGCCGCAAAAATATCGTGAACCCGTGCTGGTTTCCGGCACTGACGGCGTAGGTAC"
-"CAAGCTGCGTCTGGCAATGGACTTAAAACGTCACGACACCATTGGTATTGATCTGGTCGCCATGTGCGTTAATGACCTGG"
-"TGGTGCAAGGTGCGGAACCGCTGTTTTTCCTCGACTATTACGCAACCGGAAAACTGGATGTTGATACCGCTTCAGCGGTG"
-"ATCAGCGGCATTGCGGAAGGTTGTCTGCAATCGGGCTGTTCTCTGGTGGGTGGCGAAACGGCAGAAATGCCGGGGATGTA"
-"TCACGGTGAAGATTACGATGTCGCGGGTTTCTGCGTGGGCGTGGTAGAAAAATCAGAAATCATCGACGGCTCTAAAGTCA"
-"GCGACGGCGATGTGCTGATTGCACTCGGTTCCAGCGGTCCGCACTCGAACGGTTATTCGCTGGTGCGCAAAATTCTTGAA"
-"GTCAGCGGTTGTGATCCGCAAACCACCGAACTTGATGGTAAGCCATTAGCCGATCATCTGCTGGCACCGACCCGCATTTA"
-"CGTGAAGTCAGTGCTGGAGTTGATTGAAAAGGTCGATGTGCATGCCATTGCGCACCTGACCGGCGGCGGCTTCTGGGAAA"
-"ACATTCCGCGCGTATTGCCAGATAATACCCAGGCAGTGATTGATGAATCTTCCTGGCAGTGGCCGGAAGTGTTCAACTGG"
-"CTGCAAACGGCAGGTAACGTTGAGCGCCATGAAATGTATCGCACCTTCAACTGCGGCGTCGGGATGATTATCGCCCTGCC"
-"TGCTCCGGAAGTGGACAAAGCCCTCGCCCTGCTCAATGCCAACGGTGAAAACGCGTGGAAAATCGGTATCATCAAAGCCT"
-"CTGATTCCGAACAACGCGTGGTTATCGAATAATGAATATTGTGGTGCTTATTTCCGGCAACGGAAGTAATTTACAGGCAA"
-"TTATTGACGCCTGTAAAACCAACAAAATTAAAGGCACCGTACGGGCAGTTTTCAGCAATAAGGCCGACGCGTTCGGCCTT"
-"GAACGCGCCCGCCAGGCGGGTATTGCAACGCATACGCTCATCGCCAGCGCGTTTGACAGTCGTGAAGCCTATGACCGGGA"
-"GTTGATTCATGAAATCGACATGTACGCACCCGATGTGGTCGTGCTGGCTGGTTTTATGCGCATTCTCAGCCCGGCGTTTG"
-"TCTCCCACTATGCCGGGCGTTTGCTGAACATTCACCCTTCTCTGCTGCCGAAATATCCCGGATTACACACCCATCGTCAA"
-"GCGCTGGAAAATGGCGATGAAGAGCACGGTACATCGGTGCATTTCGTCACCGATGAACTGGACGGTGGCCCGGTTATTTT"
-"ACAGGCGAAAGTCCCGGTATTTGCTGGTGATACGGAAGATGACGTCACCGCCCGCGTGCAAACCCAGGAACACGCCATTT"
-"ATCCACTGGTGATTAGCTGGTTTGCCGATGGTCGTCTGAAAATGCACGAAAACGCCGCGTGGCTGGATGGTCAACGTCTG"
-"CCGCCGCAGGGCTACGCTGCCGACGAGTAATGCCCCCGTAGTTAAAGCGCCAGCTCTGCCGCTGGCGTTTTTCAATTCAC"
-"CTGTAAATCGCAAGCTCCAGCAGTTTTTTTCCCCCTTTTCTGGCATAGTTGGACATCTGCCAATATTGCTCGCCATAATA"
-"TCCAGGCAGTGTCCCGTGAATAAAACGGAGTAAAAGTGGTAATGGGTCAGGAAAAGCTATACATCGAAAAAGAGCTCAGT"
-"TGGTTATCGTTCAATGAACGCGTGCTTCAGGAAGCGGCGGACAAATCTAACCCGCTGATTGAAAGGATGCGTTTCCTGGG"
-"GATCTATTCCAATAACCTTGATGAGTTCTATAAAGTCCGCTTCGCTGAACTGAAGCGACGCATCATTATTAGCGAAGAAC"
-"AAGGCTCCAACTCTCATTCCCGCCATTTACTGGGCAAAATTCAGTCCCGGGTGCTGAAAGCCGATCAGGAATTCGACGGC"
-"CTCTACAACGAGCTATTGCTGGAGATGGCGCGCAACCAGATCTTCCTGATTAATGAACGCCAGCTCTCCGTCAATCAACA"
-"AAACTGGCTGCGTCATTATTTTAAGCAGTATCTGCGTCAGCACATTACGCCGATTTTAATCAATCCTGACACTGACTTAG"
-"TGCAGTTCCTGAAAGATGATTACACCTATCTGGCGGTGGAAATTATCCGTGGCGATACCATCCGTTACGCGCTTCTGGAG"
-"ATCCCATCAGATAAAGTGCCGCGCTTTGTGAATTTACCGCCAGAAGCGCCGCGTCGACGCAAGCCGATGATTCTTCTGGA"
-"TAACATTCTGCGTTACTGCCTTGATGATATTTTCAAAGGCTTCTTTGATTATGACGCGCTGAATGCCTATTCAATGAAGA"
-"TGACCCGCGATGCCGAATACGATTTAGTGCATGAGATGGAAGCCAGCCTGATGGAGTTGATGTCTTCCAGTCTCAAGCAG"
-"CGTTTAACTGCTGAGCCGGTGCGTTTTGTTTATCAGCGCGATATGCCCAATGCGCTGGTTGAAGTTTTACGCGAAAAACT",
-
-"GGCGGCTTCGGTGCGCTGTGTGCATTGCCGCAAAAATATCGTGAACCCGTGCTGGTTTCCGGCACTGACGGCGTAAATAC"
-"CAAGCTGCGTCTGGCAATGGACTTAAAACGTCACGACACCATTGGTATTGATCTGGTCGCCATGTGCGTTAATGACCTGG"
-"TGGTGCAAGGTGCGGAACCGCTGTTTTTCCTCGACTATTACGCACCGGAAAACTGGATGTTGATACCGCTTCAGCGGTG"
-"ATCAGCGGCATTGCGGAAGGTTGTCTGCAATCGGGCTGTTCTCTGGTGGGTGGCGAAACGGCAGAAATGCCGGGGATGTA"
-"TCACGGTGAAGATTACGATGTCGCGGGTTTCTGCGTGGGCGTGGTAGAAAAATCAGAAATCATCGACGGCAAAGTCA"
-"GCGACGGCGATGTGCTGATTGCACTCGGTTCCAGCGGTCCGCACTCGAACGGTTATTCGCTGGTGCGCAAAATTCTTGAA"
-"GTCAGCGGTTGTGATCCGCAAACCACCGAACTTGATGGTAAGCCATTAGCCGATCATCTGCTGGCACCGACCCGCATTTA"
-"ACATTCCGCGCGTATTGCCAGATAATACCCAGGCAGTGATTGATGAATCTTCCTGGCAGTGGCCGGAAGTGTTCAACTGG"
-"CTGCAAACGGCAGGTAACGTTGAGCGCCATGAAATGTATCGCACCTTCAACTGCGGCGTCGGGATGATTATCCCCTGCC"
-"TGCTCCGGAAGTGGACAAAGCCCTCGCCCTGCTCAATGCCAACGGTGAAAACGCGTGGAAAATCGGTATCATCAAAGCCT"
-"CTGATTCCGAACAACGCGTGGTTATCGAATAATGAATATTGTGTGCTTATTTCCGGCAACGGAAGTAATTTACAGGCAA"
-"TTATTGACGCCTGTAAAACCAACAAAATTAAAGGCACCGTACGGGCAGTTTTCAGCAATAAGGCCGACGCGCGGCCTT"
-"GAACGCGCCCGCCAGGCGGGTATTGCAACGCATACGCTCATCGCCAGCGCGTTTGACAGTCGTGAAGCCTATGACCGGGA"
-"GTTGATTCATGAAATCGACATGTACGCACCCGATGTGGTCGTGCTGGCTGGTTTTATGCGCATTCTCAGCCCGGCGTTTG"
-"TCTCCCACTATGCCGGGCGTTTGCTGAACATTCACCCTTCTCTGCTGCCGAAATATCCCGGATTACACACCCATCGTCAA"
-"GCGCTGGAAAATGGCGATGAAGAGCACGGTACATCGGGCATTTCGTCACCGATGAACTGGACGGTGGCCCGGTTATTTT"
-"ACAGTCGAAAGTCCCGGTATTTGCTGGTGATACGGAAGATGACGTCACCGCCCGCGTGCAAACCCAGGAACACGCCATTT"
-"ATCCTCTGGTGATTAGCTGGTTTGCCGATGGTCGTCTGAAAATGCACGAAAACGCCGCGTGGCTGGATGGTCAACGTCTG"
-"CCGCTGCAGGGCTACGCTGCCGACGAGTAATGCCCCCGTAGTTAAAGCGCCAGCTCTGCCGCTGGCGTTTTTCAATTCAC"
-"CTGTTAATCGCAAGCTCCAGCAGCCCCCCCCCCCCTTTTCTGCATAGTTGGACATCTGCCAATATTGCTCGCCATAATA"
-"TCCATGCAGTGTCCCGTGAATAAAACGGAGTAAAAGTGGTAATGGGTCAGGAAAAGCTATACATAAAAAGAGCTCAGT"
-"TGGTTATCGTTCAATGAACGCGTGCTTCAGGAAGCGGCGGACAAATCTAACCCGCTGATTGAAAGGATGCGTTTCCTGGG"
-"GATCTATTCCAATAACCTTGATGAGTTCTATAAAGTCCGCTTCGCTGAACTGAAGCGACGCATTATTAGCGAAGAAC"
-"AAGGTTCCAACTCTCATTCCCGCCATTTACTGGGAAAATTCAGTCCCGGGTGCTGAAAGCCGATCAGGAATTCGACGGC"
-"CTCTTCAACGAGCTATTGCTGGAGATGGCGCGCAACCAGATCTTCCTGATTAATGAACGCCAGCTCTCCGTCAATCAACA"
-"AAACTGGCTGCGTCATTATTTTAAGCAGTATCTGCGTCAGCACATTACGCCGATTTTAATCAATCCTGACACTGACTTAG"
-"TGCATTTCCTGAAAGATGATTACACCTATCTGGCGGTGGAAATTATCCGTGGCGATACCATCCGTTACGCGCTTCTGGAG"
-"ATCCCATCAGATAAAGTGCCGCGCTTTGTGAATTTACCGCAGAAGCGCCGCGTCGACGCAAGCCGATGATTCTTCTGGA"
-"TAACATTCTGCGTTACTGCCTTGATGATATTTTCAAAGGCTTCTTTGATTATGACGCGCTGAATGCCTATTCAATGAAGA"
-"TGACCCGCGATGCCGAATACGATTTAGTGCATGAGATGGAAGCCAGCCTGATGGAGTTGATGTCTTCCAGTCTCAAGCAG"
-"CGTTTAACTGCTGAGCCGGTGCGTTTTGTTTATCGCGCGATATGCCCAATGCGCTGGTTGAAGTTTTACGCGAAAAACT",
-};
-
-
-static
-int
-my_read(Stream *s, void *buf, int n)
-{
- return io·read(s, 1, n, buf);
-}
-
-// -----------------------------------------------------------------------
-// Point of entry for testing
-
-error
-test·newick()
-{
- error err;
- bio·Tree t;
- mem·Arena *heap;
- Stream *fd[2];
-
- io·Peeker rdr;
- io·Putter wtr;
-
- bio·Node **end, **it, **list;
-
- heap = mem·makearena(mem·sys, nil);
- rdr = (io·Peeker){.get = (byte (*)(void *))io·getbyte, .unget = (error (*)(void *, byte))io·ungetbyte};
- wtr = (io·Putter){.put = (error (*)(void *, byte))io·putbyte, .putstr = (int (*)(void *, string))io·putstring};
-
- fd[0] = io·open("/home/nolln/root/data/test/zika.nwk", "r");
- fd[1] = io·open("/home/nolln/root/data/test/zika.proc.nwk", "w");
-
- t.h = heap;
- t.heap = (mem·Allocator){ .alloc = (void *(*)(void *, uint, ulong))mem·arenaalloc, .free = nil, };
-
- if (err = bio·readnewick(rdr, fd[0], &t), err) {
- errorf("failed to read newick");
- return 1;
- }
- printf("number of children: %d\n", t.root->nchild);
-
- phylo·ladderize(t.root);
-
- list = mem·arenaalloc(heap, t.nleaf, sizeof(**list));
- phylo·getleafs(t, list);
- for (it = list, end = list + t.nleaf; it != end; ++it) {
- printf("Leaf '%s'\n", (*it)->name);
- }
-
- bio·Node *path[100];
- // phylo·diameter(t, path);
-
- printf("Loaded tree with %d leafs and %d nodes\n", t.nleaf, t.root->nnode);
- err = bio·writenewick(t, wtr, fd[1]);
-
- io·flush(fd[1]);
-
- io·close(fd[0]);
- io·close(fd[1]);
-
- mem·freearena(heap);
- return 0;
-}
-
-error
-test·fasta()
-{
- error err;
- Stream *fd;
-
- bio·Seq seq;
- bio·FastaReader *rdr;
-
- clock_t t;
-
- fd = io·open("/home/nolln/root/data/test/zika.fa", "r");
-
- /* Benchmark against Heng */
-#if 0
- int n, slen;
- kseq_t *kseq;
-
- t = clock();
- kseq = kseq_init(fd);
- while (kseq_read(kseq) >= 0) {
- ++n, slen += kseq->seq.l;
- }
- t = clock() - t;
- printf("heng's code took %f ms to execute\n", 1000.*t/CLOCKS_PER_SEC);
-
- kseq_destroy(kseq);
-
- io·seek(fd, 0, seek·set);
-#endif
-
- rdr = bio·openfasta((io·Reader){.read = (int (*)(void *, int, int, void *))io·read}, fd, mem·sys, nil);
-
- t = clock();
- err = 0;
- while (!err) {
- err = bio·readfasta(rdr, &seq);
- }
- t = clock() - t;
- printf("nick's code took %f ms to execute\n", 1000.*t/CLOCKS_PER_SEC);
- bio·closefasta(rdr);
-
-
- io·close(fd);
- return err <= 0 ? 0 : 1;
-}
-
-#define asrdr(x) (int (*)(void *, int, int, void *))(x)
-error
-test·fastq()
-{
- error err;
- Stream *fd;
-
- bio·Seq seq;
- bio·FastqReader *rdr;
-
- clock_t t;
-
- fd = io·open("/home/nolln/root/data/test/eg.fq", "r");
-
- rdr = bio·openfastq((io·Reader){.read = asrdr(io·read)}, fd, mem·sys, nil);
-
- t = clock();
- err = 0;
- while (!err) {
- err = bio·readfastq(rdr, &seq);
- }
- t = clock() - t;
- printf("nick's fastq code took %f ms to execute\n", 1000.*t/CLOCKS_PER_SEC);
- bio·closefastq(rdr);
-
-
- io·close(fd);
- return err <= 0 ? 0 : 1;
-}
-
-error
-test·align()
-{
- double f;
- error err;
- int i, l, n;
-
- uint64 mem[aln·N][arrlen(SEQ)][aln·L];
- uint64 *phi[aln·N];
- int loc[aln·N][arrlen(SEQ)][aln·L];
- int *pos[aln·N];
-
- for (i = 0; i < arrlen(SEQ); i++) {
- for (n = 0; n < aln·N; n++) {
- phi[n] = mem[n][i];
- pos[n] = loc[n][i];
- }
-
- err = aln·sketch(SEQ[i], aln·L, phi, pos);
- }
-
- f = 0;
- for (n = 0; n < aln·N; n++) {
- aln·sort(arrlen(SEQ), aln·L, (uint64*)mem[n]);
-
- if (!memcmp(mem[n][0], mem[n][1], sizeof(uint64)*aln·L)) {
- f += 1.;
- printf("True : ");
- } else {
- printf("False: ");
- }
- for (i = 0; i < arrlen(SEQ); i++) {
- printf("[");
- for (l = 0; l < aln·L; l++) {
- printf("%lu,", mem[n][i][l]);
- }
- printf("]");
- if (i == 0) printf(" ~ ");
- }
- printf("\n");
- }
-
- printf("Fraction hits %f\n", f/aln·N);
- return err;
-
-}
-
-error
-main()
-{
- error err;
-
- if (err = test·newick(), err) {
- errorf("test fail: newick");
- }
-
-#if 0
- if (err = test·fasta(), err) {
- errorf("test fail: fasta");
- }
-
- if (err = test·fastq(), err) {
- errorf("test fail: fastq");
- }
-#endif
-}
-
diff --git a/sys/libc/rules.mk b/sys/libc/rules.mk
deleted file mode 100644
index 96d4202..0000000
--- a/sys/libc/rules.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-include share/push.mk
-
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := $(wildcard $(d)/*.c)
-LIBS_$(d) := $(d)/libc_n.a
-BINS_$(d) :=
-
-include share/paths.mk
-
-# Local rules
-# $(LIBS_$(d)) = TGTINCS :=
-# $(LIBS_$(d)) = TGTLIBS :=
-
-$(LIBS_$(d)): TCFLAGS := -ffreestanding -fno-builtin -nostdlib
-$(LIBS_$(d)): $(OBJS_$(d))
- $(ARCHIVE)
-
-$(BINS_$(d)): $(OBJ_DIR)/libn/test.o
- $(LINK)
-
-include share/pop.mk
diff --git a/sys/libc/stdio.c b/sys/libc/stdio.c
deleted file mode 100644
index 8bbbe9a..0000000
--- a/sys/libc/stdio.c
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <u.h>
-#include <libc.h>
-
-int
-printf(byte* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- int nw, rem, peek, len;
- byte *str, c;
-
- while (*fmt) {
- rem = INT_MAX - nw;
-
- if (fmt[0] != '%' || fmt[1] == '%') {
- if (fmt[0] == '%') fmt++;
-
- for (peek = 1; fmt[peek] && fmt[peek] != '%'; peek++) {
- ;
- }
- if (rem < peek) return -1;
- // TODO: Print here.
- fmt += peek;
- nw += peek;
- continue;
- }
-
- str = fmt++;
-
- switch (*fmt++) {
- case 'c':
- c = va_arg(args, int);
- if (rem < 0) return -1;
- // TODO: Print here
- nw++;
- break;
-
- case 's':
- str = va_arg(args, byte*);
- len = strlen(str);
- if (rem < len) return -1;
- // TODO: Print here
- nw += len;
- break;
- default:
- fmt = str;
- len = strlen(fmt);
- if (rem < len) return -1;
- // TODO: Print here
- nw += len;
- fmt += len;
- break;
- }
- }
-
- va_end(args);
- return nw;
-}
diff --git a/sys/libc/string.c b/sys/libc/string.c
deleted file mode 100644
index 0e41efa..0000000
--- a/sys/libc/string.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include <u.h>
-#include <libc.h>
-
-void*
-memcopy(void *dst, void *src, intptr n)
-{
- byte *e, *s, *d;
-
- d = dst;
- e = d + n;
- for (s = src ; d != e; ++s, ++d) {
- *d = *s;
- }
-
- return dst;
-}
-
-void*
-memmove(void *dst, void *src, intptr n)
-{
- byte *e, *s, *d;
- s = src;
- d = dst;
-
- if (d < s) {
- e = d + n;
- for (; d != e; ++s, ++d)
- *d = *s;
-
- } else {
- e = d;
- d += n;
- s += n;
- for (; d != e; --s, --d)
- d[-1] = s[-1];
- }
-
- return dst;
-}
-
-void*
-memset(void *buf, int val, intptr n)
-{
- byte *b, *e;
- b = buf;
- e = b + n;
- for (; b != e; b++) {
- *b = (byte)val;
- }
-
- return buf;
-}
-
-int
-memcmp(void *lhs, void *rhs, intptr n)
-{
- byte *bl, *br, *e;
-
- br = rhs;
- e = br + n;
- for (bl = lhs; br != e; ++bl, ++br) {
- if (*bl < *br)
- return -1;
- else if (*bl > *br)
- return 1;
- }
-
- return 0;
-}
-
-int
-strlen(byte* s)
-{
- byte* b;
- for (b = s; *b; b++) {
- ;
- }
-
- return b - s;
-}
diff --git a/sys/libfmt/buffer.c b/sys/libfmt/buffer.c
deleted file mode 100644
index 0099e72..0000000
--- a/sys/libfmt/buffer.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "internal.h"
-
-static int
-flush(fmt·State *io)
-{
- int n;
- char *s;
-
- void *heap = io->heap;
- mem·Reallocator mem = io->mem;
-
- if(!io->buffer.beg)
- return 0;
-
- n = 2*(uintptr)io->file;
- s = io->buffer.beg;
-
- io->buffer.beg = mem.realloc(heap, io->buffer.beg, n, 1);
- if(!io->buffer.beg){
- io->file = io->buffer.cur = io->buffer.end = nil;
- mem.free(heap, s);
- return 0;
- }
- io->file = (void*)(uintptr)n;
- io->buffer.cur = io->buffer.beg + (io->buffer.cur - s);
- io->buffer.end = io->buffer.beg + n - 1;
-
- return 1;
-}
-
-int
-fmt·make(mem·Reallocator mem, void *heap, fmt·State *io)
-{
- int n;
-
- memset(io, 0, sizeof(*io));
-
- n = 32;
- io->buffer.beg = io->buffer.cur = mem.alloc(heap, n, 1);
- if(!io->buffer.beg)
- return -1;
- io->buffer.end = io->buffer.beg + n - 1;
-
- io->flush = flush;
- io->file = (void*)(uintptr)n;
- io->n = 0;
-
- fmt·setlocale(io, nil, nil, nil);
- return 0;
-}
-
-void
-fmt·free(fmt·State *io)
-{
- void *heap = io->heap;
- mem·Reallocator mem = io->mem;
-
- mem.free(heap, io->buffer.beg);
- io->buffer.beg = io->buffer.cur = io->buffer.end = nil;
-}
diff --git a/sys/libfmt/do.c b/sys/libfmt/do.c
deleted file mode 100644
index eaac0a3..0000000
--- a/sys/libfmt/do.c
+++ /dev/null
@@ -1,730 +0,0 @@
-#include "internal.h"
-#include <stdatomic.h>
-
-#define atomic _Atomic
-#define MaxFmt 128
-#define atomic·load atomic_load
-#define atomic·store atomic_store
-
-// -----------------------------------------------------------------------
-// globals
-
-/* built in verbs */
-static int fmtflag(fmt·State *);
-static int fmtpercent(fmt·State *);
-static int fmtrune(fmt·State *);
-static int fmtfloat(fmt·State *);
-static int fmtutf8(fmt·State *);
-static int fmtint(fmt·State *);
-static int fmtchar(fmt·State *);
-static int fmtcount(fmt·State *);
-static int fmtstring(fmt·State *);
-static int fmterror(fmt·State *);
-
-static int badfmt(fmt·State *);
-
-static struct
-{
- atomic int len;
- Verb verb[MaxFmt];
-} formatter =
-{
- ATOMIC_VAR_INIT(30),
- {
- {' ', fmtflag},
- {'#', fmtflag},
- {'%', fmtpercent},
- {'\'',fmtflag},
- {'+', fmtflag},
- {',', fmtflag},
- {'-', fmtflag},
- {'C', fmtrune},
- {'E', fmtfloat},
- {'F', fmtfloat},
- {'G', fmtfloat},
- {'L', fmtflag},
- {'S', fmtutf8},
- {'X', fmtint},
- {'b', fmtint},
- {'c', fmtchar},
- {'d', fmtint},
- {'e', fmtfloat},
- {'f', fmtfloat},
- {'g', fmtfloat},
- {'h', fmtflag},
- {'i', fmtint},
- {'l', fmtflag},
- {'n', fmtcount},
- {'o', fmtint},
- {'p', fmtint},
- {'r', fmterror},
- {'s', fmtstring},
- {'U', fmtflag},
- {'u', fmtint},
- {'x', fmtint},
- }
-};
-
-// -----------------------------------------------------------------------
-// internal functions
-
-static Formatter
-format(int c)
-{
- Verb *v, *e;
- e = &formatter.verb[atomic·load(&formatter.len)];
- for(v=e; v > formatter.verb; --v){
- if(v->c == c)
- return v->fmt;
- }
-
- return badfmt;
-}
-
-static char *
-dispatch(fmt·State *io, char *fmt)
-{
- rune r;
- int i, n;
-
- io->flag = 0;
- io->width = io->prec = 0;
-
- /*
- * the form of each print verb:
- * % [flags] verb
- * + the verb is a single character
- * + each flag is either
- * - a single character
- * - a decimal numeric string
- * - up to 2 decimal strings can be used
- * - [width|*].[prec|*]
- * - if missing, set to 0
- * - if *, grab from varargs
- */
- for(;;){
- fmt += utf8·decode(fmt, &r);
- io->verb = r;
- switch(r){
- case 0:
- return nil;
- case '.':
- io->flag |= fmt·Width|fmt·Prec;
- continue;
- case '0':
- if(!(io->flag & fmt·Width)){
- io->flag |= fmt·Zero;
- continue;
- }
- /* fallthrough */
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- i = 0;
- while('0' <= r && r <= '9'){
- i = 10*i + (r-'0');
- r = *fmt++;
- }
- fmt--;
- number:
- if(io->flag & fmt·Width){
- io->flag |= fmt·Prec;
- io->prec = i;
- }else{
- io->flag |= fmt·Width;
- io->width = i;
- }
- continue;
- case '*':
- i = va_arg(io->args, int);
- if(i < 0){
- if(io->flag&fmt·Prec){
- io->flag &= ~fmt·Prec;
- io->prec = 0;
- continue;
- }
- i = -i;
- io->flag |= fmt·Left;
- }
- goto number;
- }
- n = format(r)(io);
- if(n < 0)
- return nil;
- if(!n)
- return fmt;
- }
-}
-
-static char *
-flush(fmt·State *io, char *b, int len)
-{
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- if(!io->flush || !(*io->flush)(io) || io->buffer.cur + len >= io->buffer.end) {
- io->buffer.end = io->buffer.cur;
- return nil;
- }
- return io->buffer.cur;
-}
-
-static int
-pad(fmt·State *io, int n)
-{
- int i;
- char *b=io->buffer.cur, *e=io->buffer.end;
-
- for(i=0; i<n; i++){
- if(b>=e){
- if(!(b=flush(io, b, 1)))
- return -1;
- e = io->buffer.end;
- }
- *b++ = ' ';
- }
-
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- return 0;
-}
-
-static int
-copy(fmt·State *io, char *m, int sz, int n)
-{
- ulong f;
- rune r;
- int nc, w, nb;
- char *b, *e, *me;
-
- w = 0;
- f = io->flag;
- me = m + sz;
-
- if(f&fmt·Width)
- w = io->width;
- if(f&fmt·Prec && n > io->prec)
- n = io->prec;
- if(!(f&fmt·Left) && pad(io, w-n)<0)
- return -1;
-
- b = io->buffer.cur;
- e = io->buffer.end;
-
- for(nc=n; nc>0; nc--){
- r = *(uchar *)m;
- if(utf8·onebyte(r)){
- nb=1;
- m++;
- }else if((me-m) >= UTFmax || utf8·canfit(m, me-m)){
- nb=utf8·decode(m, &r);
- m+=n;
- }else
- break;
-
- if(b+n>e){
- if(!(b=flush(io, b, nb)))
- return -1;
- e = io->buffer.end;
- }
- b += utf8·encode(&r, b);
- }
-
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- if(f&fmt·Left && pad(io, w-n)<0)
- return -1;
-
- return 0;
-}
-
-static int
-copyrune(fmt·State *io, rune *m, int n)
-{
- ulong f;
- rune r, *me;
- int w, nb;
- char *b, *e;
-
- w = 0;
- f = io->flag;
-
- if(f&fmt·Width)
- w = io->width;
- if(f&fmt·Prec && n > io->prec)
- n = io->prec;
-
- if(!(f&fmt·Left) && pad(io, w-n)<0)
- return -1;
-
- b = io->buffer.cur;
- e = io->buffer.end;
-
- for(me=m+n; m < me; m++){
- r = *m;
- nb = utf8·runelen(r);
- if(b + nb > e){
- if(!(b=flush(io, b, nb)))
- return -1;
- e = io->buffer.end;
- }
- b += utf8·encode(&r, b);
- }
-
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- if(f&fmt·Left && pad(io, w-n)<0)
- return -1;
-
- return 0;
-}
-
-static int
-copystring(fmt·State *io, char *s)
-{
- rune r;
- int i,j;
-
- if(!s)
- return copy(io, "<nil>", 5, 5);
-
- if(io->flag&fmt·Prec){
- i = 0;
- for(j=0; j < io->prec && s[i]; j++)
- i += utf8·decode(s+i, &r);
-
- return copy(io, s, i, j);
- }
- return copy(io, s, strlen(s), utf8·len(s));
-}
-
-static int
-copyutf8(fmt·State *io, rune *s)
-{
- rune *e;
- int n,p;
-
- if(!s)
- return copy(io, "<nil>", 5, 5);
-
- if(io->flag & fmt·Prec){
- p = io->prec;
- for(n=0; n<p; n++)
- if(!s[n])
- break;
- }else{
- for(e=s; *e; e++)
- ;
- n = e - s;
- }
-
- return copyrune(io, s, n);
-}
-
-// -----------------------------------------------------------------------
-// format helpers
-
-static int
-needseperate(int *digits, char **groups)
-{
- int group;
-
- (*digits)++;
- group = *(uchar *)*groups;
-
- if(group == 0xFF || group == 0x7f || group == 0x00)
- return 0;
- if(*digits > group){
- if((*groups)[1] != 0)
- (*groups)++;
- *digits = 1;
- return 1;
- }
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// formatters
-
-static int
-fmtchar(fmt·State *io)
-{
- char x[1];
- x[0] = va_arg(io->args, int);
- io->prec = 1;
-
- return copy(io, x, 1, 1);
-}
-
-static int
-fmtstring(fmt·State *io)
-{
- char *s;
- s = va_arg(io->args, char *);
- return copystring(io, s);
-}
-
-static int
-fmterror(fmt·State *io)
-{
- char *s;
- s = strerror(errno);
- return copystring(io, s);
-}
-
-static int
-fmtrune(fmt·State *io)
-{
- rune x[1];
-
- x[0] = va_arg(io->args, int);
- return copyrune(io, x, 1);
-}
-
-static int
-fmtutf8(fmt·State *io)
-{
- rune *s;
-
- s = va_arg(io->args, rune *);
- return copyutf8(io, s);
-}
-
-static int
-fmtpercent(fmt·State *io)
-{
- rune x[1];
-
- x[0] = io->verb;
- io->prec = 1;
- return copyrune(io, x, 1);
-}
-
-static int
-fmtint(fmt·State *io)
-{
- union{
- ulong u;
- uvlong v;
- } val;
- int neg, base, i, n, f, w, isv;
- int digits, bytes, runes, excess;
- char *groups, *thousands;
- char *p, *conv, buf[140];
-
- f = io->flag;
- neg = 0;
- isv = 0;
- val.u = 0;
-
- switch(io->verb){
- case 'o': case 'p': case 'u': case 'x': case 'X':
- f |= fmt·Unsigned;
- f &= ~(fmt·Sign|fmt·Space);
- }
-
- /* set flags */
- if(io->verb=='p'){
- val.u = (ulong)va_arg(io->args, void*);
- io->verb = 'x';
- f |= fmt·Unsigned;
- }else if(f&fmt·Vlong){
- isv=1;
- if(f&fmt·Unsigned)
- val.v = va_arg(io->args, uvlong);
- else
- val.v = va_arg(io->args, vlong);
- }else if(f&fmt·Long){
- if(f&fmt·Unsigned)
- val.u = va_arg(io->args, ulong);
- else
- val.u = va_arg(io->args, long);
- }else if(f&fmt·Byte){
- if(f&fmt·Unsigned)
- val.u = (uchar)va_arg(io->args, int);
- else
- val.u = (char)va_arg(io->args, int);
- }else if(f&fmt·Short){
- if(f&fmt·Unsigned)
- val.u = (ushort)va_arg(io->args, int);
- else
- val.u = (short)va_arg(io->args, int);
- }else{
- if(f&fmt·Unsigned)
- val.u = va_arg(io->args, uint);
- else
- val.u = va_arg(io->args, int);
- }
-
- conv = "0123456789abcdef";
- groups = "\4";
- thousands = io->thousands;
- /* get base */
- switch(io->verb){
- case 'd': case 'i': case 'u':
- base = 10;
- groups = io->groups;
- break;
- case 'X':
- conv = "0123456789ABCDEF";
- /*fallthrough*/
- case 'x':
- base = 16;
- thousands = ":";
- break;
- case 'b':
- base = 2;
- thousands = ":";
- break;
- case 'o':
- base = 8;
- break;
- default:
- return -1;
- }
-
- /* check for negativity */
- if(!(f&fmt·Unsigned)){
- if(isv && (vlong)val.v < 0){
- val.v = -(vlong)val.v;
- neg = 1;
- }else if(!isv && (long)val.u < 0){
- val.u = -(long)val.u;
- neg = 1;
- }
- }
-
- p = buf + sizeof(buf) - 1;
- n = 0;
- digits = 0;
- excess = 0;
- runes = utf8·len(thousands);
- bytes = strlen(thousands);
-
-#define PARSE(VALUE) \
- while((VALUE)){ \
- i = (VALUE) % base; \
- (VALUE) /= base; \
- if((f&fmt·Comma) && n%4 == 3){ \
- *p-- = ','; \
- n++; \
- } \
- if((f&fmt·Apost) && needseperate(&digits, &groups)){ \
- n += runes; \
- excess += bytes - runes; \
- p -= bytes; \
- memmove(p+1, thousands, bytes); \
- } \
- *p-- = conv[i]; \
- n++; \
- }
- if(isv)
- PARSE(val.v)
- else
- PARSE(val.u)
-#undef PARSE
-
- if(!n){
- if(!(f&fmt·Prec) || io->prec != 0 || (io->verb == 'o' && (f&fmt·Sharp))){
- *p-- = '0';
- n = 1;
- if(f&fmt·Apost)
- needseperate(&digits,&groups);
- }
-
- if(io->verb == 'x' || io->verb == 'X')
- f &= ~fmt·Sharp;
- }
-
- for(w = io->prec; n < w && p > buf+3; n++){
- if((f&fmt·Apost) && needseperate(&digits, &groups)){
- n += runes;
- excess += bytes - runes;
- p -= bytes;
- memmove(p+1, thousands, bytes);
- }
- *p-- = '0';
- }
-
- if(neg || (f&(fmt·Sign|fmt·Space)))
- n++;
-
- if(f&fmt·Sharp){
- if(base==16)
- n += 2;
- else if(base == 8){
- if(p[1] == '0')
- f &= ~fmt·Sharp;
- else
- n++;
- }
- }
-
- if(f&fmt·Zero && !(f & (fmt·Left|fmt·Prec))){
- w = 0;
- if(f & fmt·Width)
- w = io->width;
- for(; n < w && p > buf+3; n++){
- if((f & fmt·Apost) && needseperate(&digits, &groups)){
- n += runes;
- excess += bytes - runes;
- p -= bytes;
- memmove(p+1, thousands, bytes);
- }
- *p-- = '0';
- }
- io->flag &= ~fmt·Width;
- }
-
- if(f&fmt·Sharp){
- if(base==16)
- *p-- = io->verb;
- if(base==16 || base == 8)
- *p-- = '0';
- }
-
- if(neg)
- *p-- = '-';
- else if(f & fmt·Sign)
- *p-- = '+';
- else if (f & fmt·Space)
- *p-- = ' ';
-
- io->flag &= ~fmt·Prec;
- return copy(io, p+1, n+excess, n);
-}
-
-static int
-fmtcount(fmt·State *io)
-{
- void *p;
- ulong f;
-
- f = io->flag;
- p = va_arg(io->args, void*);
-
- if(f&fmt·Vlong)
- *(vlong*)p = io->n;
- else if(f&fmt·Long)
- *(long*)p = io->n;
- else if(f&fmt·Byte)
- *(char*)p = io->n;
- else if(f&fmt·Short)
- *(short*)p = io->n;
- else
- *(int*)p = io->n;
-
- return 0;
-}
-
-static int
-fmtflag(fmt·State *io)
-{
- switch(io->verb){
- case ',': io->flag |= fmt·Comma; break;
- case '-': io->flag |= fmt·Left; break;
- case '+': io->flag |= fmt·Sign; break;
- case '#': io->flag |= fmt·Sharp; break;
- case '\'': io->flag |= fmt·Apost; break;
- case ' ': io->flag |= fmt·Space; break;
- case 'u': io->flag |= fmt·Unsigned; break;
- case 'L': io->flag |= fmt·Ldouble; break;
- case 'h':
- if(io->flag&fmt·Short)
- io->flag |= fmt·Byte;
- io->flag |= fmt·Short;
- break;
- case 'l':
- if(io->flag&fmt·Long)
- io->flag |= fmt·Vlong;
- io->flag |= fmt·Long;
- break;
- }
- return 1;
-}
-
-static int
-badfmt(fmt·State *io)
-{
- int n;
- char x[UTFmax+2];
-
- x[0] = '%';
- n = 1 + utf8·encode(&io->verb, x+1);
- x[n++] = '%';
- io->prec = n;
- copy(io, x, n, n);
-
- return 0;
-}
-
-#include "float.c"
-
-// -----------------------------------------------------------------------
-// exports
-
-int
-fmt·do(fmt·State *io, char *fmt)
-{
- rune r;
- int c, n;
- char *b, *e;
-
- for(;;){
- b = io->buffer.cur;
- e = io->buffer.end;
- while((c = *(uchar *)fmt) && c != '%'){
- if(utf8·onebyte(c)){
- if(b >= e){
- if(!(b=flush(io, b, 1)))
- return -1;
- e = io->buffer.end;
- }
- *b++ = *fmt++;
- }else{
- n = utf8·decode(fmt, &r);
- if(b + n > e){
- if(!(b=flush(io, b, n)))
- return -1;
- e = io->buffer.end;
- }
- while(n--)
- *b++ = *fmt++;
- }
- }
- fmt++;
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- if(!c) /* we hit our nul terminator */
- return io->n - n;
- io->buffer.end = e;
-
- if(!(fmt=dispatch(io, fmt)))
- return -1;
- }
-}
-
-int
-fmt·install(int verb, Formatter func)
-{
- Verb *v;
- int i, ret;
-
-lock:
- if(verb <= 0 || verb >= 65536){
- ret = -1;
- goto unlock;
- }
- if(!func)
- func = badfmt;
-
- if((i = atomic·load(&formatter.len))==MaxFmt)
- return -1;
-
- v = &formatter.verb[i];
- v->c = verb;
- v->fmt = func;
-
- atomic·store(&formatter.len, i+1);
- ret = 0;
-unlock:
- return ret;
-}
diff --git a/sys/libfmt/esprint.c b/sys/libfmt/esprint.c
deleted file mode 100644
index 6d97340..0000000
--- a/sys/libfmt/esprint.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "internal.h"
-
-char *
-fmt·esprint(char *buf, char *end, char *fmt, ...)
-{
- char *p;
- va_list args;
-
- va_start(args, fmt);
- p = fmt·vesprint(buf, end, fmt, args);
- va_end(args);
-
- return p;
-}
diff --git a/sys/libfmt/float.c b/sys/libfmt/float.c
deleted file mode 100644
index 63ea80f..0000000
--- a/sys/libfmt/float.c
+++ /dev/null
@@ -1,1077 +0,0 @@
-#define FDIGIT 30
-#define FDEFLT 6
-#define NSIGNIF 17
-
-static uvlong uvnan = ((uvlong)0x7FF00000<<32)|0x00000001;
-static uvlong uvinf = ((uvlong)0x7FF00000<<32)|0x00000000;
-static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000;
-
-static char *special[] = { "NaN", "NaN", "+Inf", "+Inf", "-Inf", "-Inf" };
-
-static int
-isNaN(double val)
-{
- union{
- uvlong i;
- double f;
- }x;
-
- x.f = val;
- return (x.i&uvinf) == uvinf && (x.i&~uvneginf) != 0;
-}
-
-static double
-NaN(void)
-{
- union{
- uvlong i;
- double f;
- }x;
- x.i = uvnan;
- return x.f;
-}
-
-static int
-isInf(double val, int sign)
-{
- union{
- uvlong i;
- double f;
- }x;
-
- x.f = val;
- if(sign == 0)
- return x.i == uvinf || x.i == uvneginf;
- else if(sign == 1)
- return x.i == uvinf;
- else
- return x.i == uvneginf;
-}
-
-static double pows10[] =
-{
- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
- 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
- 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
- 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
- 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
- 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
- 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
- 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
- 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89,
- 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99,
- 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
- 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
- 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
- 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
- 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
- 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
-};
-
-static double
-fpow10(int n)
-{
- double d;
- int neg;
-
- neg = 0;
- if(n < 0){
- neg = 1;
- n = -n;
- }
-
- if(n<arrlen(pows10))
- d = pows10[n];
- else{
- d = pows10[arrlen(pows10)-1];
- for(;;){
- n -= arrlen(pows10)- 1;
- if(n < arrlen(pows10)){
- d *= pows10[n];
- break;
- }
- d *= pows10[arrlen(pows10)- 1];
- }
- }
- if(neg)
- return 1./d;
- return d;
-}
-
-static int
-add1(char *a, int n)
-{
- int c;
- char *b;
-
- if(n < 0 || n > NSIGNIF)
- return 0;
-
- for(b = a+n-1; b >= a; b--){
- c = *b + 1;
- if(c <= '9'){
- *b = c;
- return 0;
- }
- *b = '0';
- }
- /*
- * need to overflow adding digit.
- * shift number down and insert 1 at beginning.
- * decimal is known to be 0s or we wouldn't
- * have gotten this far. (e.g., 99999+1 => 00000)
- */
- a[0] = '1';
- return 1;
-}
-
-static int
-sub1(char *a, int n)
-{
- int c;
- char *b;
-
- if(n < 0 || n > NSIGNIF)
- return 0;
- for(b = a+n-1; b >= a; b--){
- c = *b - 1;
- if(c >= '0'){
- if(c == '0' && b == a){
- /*
- * just zeroed the top digit; shift everyone up.
- * decimal is known to be 9s or we wouldn't
- * have gotten this far. (e.g., 10000-1 => 09999)
- */
- *b = '9';
- return 1;
- }
- *b = c;
- return 0;
- }
- *b = '9';
- }
- /*
- * can't get here. the number a is always normalized
- * so that it has a nonzero first digit.
- */
- abort();
-}
-
-// -----------------------------------------------------------------------
-// strtod
-
-#define Nbits 28
-#define Nmant 53
-#define Prec ((Nmant+Nbits+1)/Nbits)
-
-#define Sigbit (1<<(Prec*Nbits-Nmant)) /* first significant bit of Prec-th word */
-#define Ndig 1500
-#define One (ulong)(1<<Nbits)
-#define Half (ulong)(One>>1)
-#define Maxe 310
-
-#define Fsign (1<<0) /* found - */
-#define Fesign (1<<1) /* found e- */
-#define Fdpoint (1<<2) /* found . */
-
-#define S0 0 /* _ _S0 +S1 #S2 .S3 */
-#define S1 1 /* _+ #S2 .S3 */
-#define S2 2 /* _+# #S2 .S4 eS5 */
-#define S3 3 /* _+. #S4 */
-#define S4 4 /* _+#.# #S4 eS5 */
-#define S5 5 /* _+#.#e +S6 #S7 */
-#define S6 6 /* _+#.#e+ #S7 */
-#define S7 7 /* _+#.#e+# #S7 */
-
-typedef struct Tab Tab;
-struct Tab
-{
- int bp;
- int siz;
- char *cmp;
-};
-
-static ulong
-umuldiv(ulong a, ulong b, ulong c)
-{
- double d;
-
- d = ((double)a * (double)b) / (double)c;
- if(d >= 4294967295.)
- d = 4294967295.;
- return (ulong)d;
-}
-
-static void
-frnorm(ulong *f)
-{
- int i, c;
-
- c = 0;
- for(i=Prec-1; i>0; i--) {
- f[i] += c;
- c = f[i] >> Nbits;
- f[i] &= One-1;
- }
- f[0] += c;
-}
-
-static int
-fpcmp(char *a, ulong* f)
-{
- ulong tf[Prec];
- int i, d, c;
-
- for(i=0; i<Prec; i++)
- tf[i] = f[i];
-
- for(;;) {
- /* tf *= 10 */
- for(i=0; i<Prec; i++)
- tf[i] = tf[i]*10;
- frnorm(tf);
- d = (tf[0] >> Nbits) + '0';
- tf[0] &= One-1;
-
- /* compare next digit */
- c = *a;
- if(c == 0) {
- if('0' < d)
- return -1;
- if(tf[0] != 0)
- goto cont;
- for(i=1; i<Prec; i++)
- if(tf[i] != 0)
- goto cont;
- return 0;
- }
- if(c > d)
- return +1;
- if(c < d)
- return -1;
- a++;
- cont:;
-}
-}
-
-static void
-divby(char *a, int *na, int b)
-{
- int n, c;
- char *p;
-
- p = a;
- n = 0;
- while(n>>b == 0){
- c = *a++;
- if(c == 0) {
- while(n) {
- c = n*10;
- if(c>>b)
- break;
- n = c;
- }
- goto xx;
- }
- n = n*10 + c-'0';
- (*na)--;
- }
- for(;;){
- c = n>>b;
- n -= c<<b;
- *p++ = c + '0';
- c = *a++;
- if(c == 0)
- break;
- n = n*10 + c-'0';
- }
- (*na)++;
- xx:
- while(n){
- n = n*10;
- c = n>>b;
- n -= c<<b;
- *p++ = c + '0';
- (*na)++;
- }
- *p = 0;
-}
-
-static Tab tab1[] =
-{
- 1, 0, "",
- 3, 1, "7",
- 6, 2, "63",
- 9, 3, "511",
- 13, 4, "8191",
- 16, 5, "65535",
- 19, 6, "524287",
- 23, 7, "8388607",
- 26, 8, "67108863",
- 27, 9, "134217727",
-};
-
-static void
-divascii(char *a, int *na, int *dp, int *bp)
-{
- int b, d;
- Tab *t;
-
- d = *dp;
- if(d >= (int)(arrlen(tab1)))
- d = (int)(arrlen(tab1))-1;
- t = tab1 + d;
- b = t->bp;
- if(memcmp(a, t->cmp, t->siz) > 0)
- d--;
- *dp -= d;
- *bp += b;
- divby(a, na, b);
-}
-
-static void
-mulby(char *a, char *p, char *q, int b)
-{
- int n, c;
-
- n = 0;
- *p = 0;
- for(;;) {
- q--;
- if(q < a)
- break;
- c = *q - '0';
- c = (c<<b) + n;
- n = c/10;
- c -= n*10;
- p--;
- *p = c + '0';
- }
- while(n) {
- c = n;
- n = c/10;
- c -= n*10;
- p--;
- *p = c + '0';
- }
-}
-
-static Tab tab2[] =
-{
- 1, 1, "", /* dp = 0-0 */
- 3, 3, "125",
- 6, 5, "15625",
- 9, 7, "1953125",
- 13, 10, "1220703125",
- 16, 12, "152587890625",
- 19, 14, "19073486328125",
- 23, 17, "11920928955078125",
- 26, 19, "1490116119384765625",
- 27, 19, "7450580596923828125", /* dp 8-9 */
-};
-
-static void
-mulascii(char *a, int *na, int *dp, int *bp)
-{
- char *p;
- int d, b;
- Tab *t;
-
- d = -*dp;
- if(d >= (int)(arrlen(tab2)))
- d = (int)(arrlen(tab2))-1;
- t = tab2 + d;
- b = t->bp;
- if(memcmp(a, t->cmp, t->siz) < 0)
- d--;
- p = a + *na;
- *bp -= b;
- *dp += d;
- *na += d;
- mulby(a, p+d, p, b);
-}
-
-static int
-cmp(char *a, char *b)
-{
- int c1, c2;
-
- while((c1 = *b++) != '\0') {
- c2 = *a++;
- if(isupper(c2))
- c2 = tolower(c2);
- if(c1 != c2)
- return 1;
- }
- return 0;
-}
-
-double
-fmtstrtod(char *as, char **aas)
-{
- int na, ex, dp, bp, c, i, flag, state;
- ulong low[Prec], hig[Prec], mid[Prec];
- double d;
- char *s, a[Ndig];
-
- flag = 0; /* Fsign, Fesign, Fdpoint */
- na = 0; /* number of digits of a[] */
- dp = 0; /* na of decimal point */
- ex = 0; /* exonent */
-
- state = S0;
- for(s=as;;s++){
- c = *s;
- if('0' <= c && c <= '9'){
- switch(state){
- case S0: case S1: case S2:
- state = S2;
- break;
- case S3: case S4:
- state = S4;
- break;
- case S5: case S6: case S7:
- state = S7;
- ex = ex*10 + (c-'0');
- continue;
- }
-
- if(na == 0 && c == '0'){
- dp--;
- continue;
- }
- if(na < Ndig-50)
- a[na++] = c;
- continue;
- }
- switch(c){
- case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
- if(state == S0)
- continue;
- break;
- case '-':
- if(state == S0)
- flag |= Fsign;
- else
- flag |= Fesign;
- case '+':
- if(state == S0)
- state = S1;
- else
- if(state == S5)
- state = S6;
- else
- break; /* syntax */
- continue;
- case '.':
- flag |= Fdpoint;
- dp = na;
- if(state == S0 || state == S1){
- state = S3;
- continue;
- }
- if(state == S2){
- state = S4;
- continue;
- }
- break;
- case 'e': case 'E':
- if(state == S2 || state == S4){
- state = S5;
- continue;
- }
- break;
- }
- break;
- }
-
- /* clean up return char-pointer */
- switch(state) {
- case S0:
- if(cmp(s, "nan") == 0){
- if(aas != nil)
- *aas = s+3;
- goto retnan;
- }
- case S1:
- if(cmp(s, "infinity") == 0){
- if(aas != nil)
- *aas = s+8;
- goto retinf;
- }
- if(cmp(s, "inf") == 0){
- if(aas != nil)
- *aas = s+3;
- goto retinf;
- }
- case S3:
- if(aas != nil)
- *aas = as;
- goto ret0; /* no digits found */
- case S6:
- s--; /* back over +- */
- case S5:
- s--; /* back over e */
- break;
- }
- if(aas != nil)
- *aas = s;
-
- if(flag & Fdpoint)
- while(na > 0 && a[na-1] == '0')
- na--;
- if(na == 0)
- goto ret0; /* zero */
- a[na] = 0;
- if(!(flag & Fdpoint))
- dp = na;
- if(flag & Fesign)
- ex = -ex;
- dp += ex;
- if(dp < -Maxe){
- errno = ERANGE;
- goto ret0; /* underflow by exp */
- } else
- if(dp > +Maxe)
- goto retinf; /* overflow by exp */
-
- /*
- * normalize the decimal ascii number
- * to range .[5-9][0-9]* e0
- */
- bp = 0; /* binary exponent */
- while(dp > 0)
- divascii(a, &na, &dp, &bp);
- while(dp < 0 || a[0] < '5')
- mulascii(a, &na, &dp, &bp);
-
- /* close approx by naive conversion */
- mid[0] = 0;
- mid[1] = 1;
- for(i=0; (c=a[i]) != '\0'; i++) {
- mid[0] = mid[0]*10 + (c-'0');
- mid[1] = mid[1]*10;
- if(i >= 8)
- break;
- }
- low[0] = umuldiv(mid[0], One, mid[1]);
- hig[0] = umuldiv(mid[0]+1, One, mid[1]);
- for(i=1; i<Prec; i++) {
- low[i] = 0;
- hig[i] = One-1;
- }
-
- /* binary search for closest mantissa */
- for(;;) {
- /* mid = (hig + low) / 2 */
- c = 0;
- for(i=0; i<Prec; i++) {
- mid[i] = hig[i] + low[i];
- if(c)
- mid[i] += One;
- c = mid[i] & 1;
- mid[i] >>= 1;
- }
- frnorm(mid);
-
- /* compare */
- c = fpcmp(a, mid);
- if(c > 0) {
- c = 1;
- for(i=0; i<Prec; i++)
- if(low[i] != mid[i]) {
- c = 0;
- low[i] = mid[i];
- }
- if(c)
- break; /* between mid and hig */
- continue;
- }
- if(c < 0) {
- for(i=0; i<Prec; i++)
- hig[i] = mid[i];
- continue;
- }
-
- /* only hard part is if even/odd roundings wants to go up */
- c = mid[Prec-1] & (Sigbit-1);
- if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0)
- mid[Prec-1] -= c;
- break; /* exactly mid */
- }
-
- /* normal rounding applies */
- c = mid[Prec-1] & (Sigbit-1);
- mid[Prec-1] -= c;
- if(c >= Sigbit/2) {
- mid[Prec-1] += Sigbit;
- frnorm(mid);
- }
- goto out;
-
-ret0:
- return 0;
-
-retnan:
- return NaN();
-
-retinf:
- /* Unix strtod requires these. Plan 9 would return Inf(0) or Inf(-1). */
- errno = ERANGE;
- if(flag & Fsign)
- return -HUGE_VAL;
- return HUGE_VAL;
-
-out:
- d = 0;
- for(i=0; i<Prec; i++)
- d = d*One + mid[i];
- if(flag & Fsign)
- d = -d;
- d = ldexp(d, bp - Prec*Nbits);
- if(d == 0) /* underflow */
- errno = ERANGE;
-
- return d;
-}
-
-#undef Nbits
-#undef Nmant
-#undef Prec
-
-#undef Sigbit
-#undef Ndig
-#undef One
-#undef Half
-#undef Maxe
-
-#undef Fsign
-#undef Fesign
-#undef Fdpoint
-
-#undef S0
-#undef S1
-#undef S2
-#undef S3
-#undef S4
-#undef S5
-#undef S6
-#undef S7
-
-static void
-fmtexp(char *p, int e, int ucase)
-{
- int i;
- char se[9];
-
- *p++ = ucase ? 'E' : 'e';
- if(e < 0){
- *p++ = '-';
- e = -e;
- }else
- *p++ = '+';
-
- i = 0;
- while(e){
- se[i++] = e % 10 + '0';
- e /= 10;
- }
-
- while(i < 2)
- se[i++] = '0';
- while(i > 0)
- *p++ = se[--i];
-
- *p++ = '\0';
-}
-
-/*
- * compute decimal integer m, exp such that:
- * f = m*10^exp
- * m is as short as possible with losing exactness
- * assumes special cases (NaN, +Inf, -Inf) have been handled.
- */
-static void
-dtoa(double f, char *s, int *exp, int *neg, int *len)
-{
- int c, d, e2, e, ee, i, ndigit, oerrno;
- char buf[NSIGNIF+10];
- double g;
-
- oerrno = errno;
-
- *neg = 0;
- if(f < 0){
- f = -f;
- *neg = 1;
- }
-
- if(f == 0){
- *exp = 0;
- s[0] = '0';
- s[1] = 0;
- *len = 1;
- return;
- }
-
- frexp(f, &e2);
- e = (int)(e2 * .301029995664);
- g = f * fpow10(-e);
- while(g < 1) {
- e--;
- g = f * fpow10(-e);
- }
- while(g >= 10){
- e++;
- g = f * fpow10(-e);
- }
-
- /* convert nsignif digits as a first approximation */
- for(i=0; i<NSIGNIF; i++){
- d = (int)g;
- s[i] = d+'0';
- g = (g-d)*10;
- }
- s[i] = 0;
-
- e -= NSIGNIF-1;
- fmtexp(s+NSIGNIF, e, 0);
-
- for(i=0; i<10; i++) {
- g=fmtstrtod(s, nil);
- if(f > g) {
- if(add1(s, NSIGNIF)){
- /* gained a digit */
- e--;
- fmtexp(s+NSIGNIF, e, 0);
- }
- continue;
- }
- if(f < g){
- if(sub1(s, NSIGNIF)){
- /* lost a digit */
- e++;
- fmtexp(s+NSIGNIF, e, 0);
- }
- continue;
- }
- break;
- }
-
- /*
- * bump last few digits down to 0 as we can.
- */
- for(i=NSIGNIF-1; i>=NSIGNIF-3; i--){
- c = s[i];
- if(c != '0'){
- s[i] = '0';
- g=fmtstrtod(s, nil);
- if(g != f){
- s[i] = c;
- break;
- }
- }
- }
-
- /*
- * remove trailing zeros.
- */
- ndigit = NSIGNIF;
- while(ndigit > 1 && s[ndigit-1] == '0'){
- e++;
- --ndigit;
- }
- s[ndigit] = 0;
- *exp = e;
- *len = ndigit;
-
- errno = oerrno;
-}
-
-
-static int
-fmtfloat(fmt·State *io)
-{
- char buf[NSIGNIF+10], *dot, *digits, *p, *end, suf[10], *cur;
- double val;
- int c, verb, ndot, e, exp, f, ndigits, neg, newndigits;
- int npad, pt, prec, realverb, sign, nsuf, ucase, n, z1, z2;
-
- if(io->flag&fmt·Long)
- val = va_arg(io->args, long double);
- else
- val = va_arg(io->args, double);
-
- /* extract formatting flags */
- f = io->flag;
- io->flag = 0;
- prec = FDEFLT;
- if(f & fmt·Prec)
- prec = io->prec;
-
- verb = io->verb;
- ucase = 0;
- switch(verb) {
- case 'A':
- case 'E':
- case 'F':
- case 'G':
- verb += 'a'-'A';
- ucase = 1;
- break;
- }
-
- /* pick off special numbers. */
- if(isNaN(val)) {
- end = special[0+ucase];
- special:
- io->flag = f & (fmt·Width|fmt·Left);
- return copy(io, end, strlen(end), strlen(end));
- }
- if(isInf(val, 1)) {
- end = special[2+ucase];
- goto special;
- }
- if(isInf(val, -1)) {
- end = special[4+ucase];
- goto special;
- }
-
- /* get exact representation. */
- digits = buf;
- dtoa(val, digits, &exp, &neg, &ndigits);
-
- /* get locale's decimal point. */
- dot = io->decimal;
- if(dot == nil)
- dot = ".";
- ndot = utf8·len(dot);
-
- /*
- * now the formatting fun begins.
- * compute parameters for actual fmt:
- *
- * pad: number of spaces to insert before/after field.
- * z1: number of zeros to insert before digits
- * z2: number of zeros to insert after digits
- * point: number of digits to print before decimal point
- * ndigits: number of digits to use from digits[]
- * suf: trailing suffix, like "e-5"
- */
- realverb = verb;
- switch(verb){
- case 'g':
- /* convert to at most prec significant digits. (prec=0 means 1) */
- if(prec == 0)
- prec = 1;
- if(ndigits > prec) {
- if(digits[prec] >= '5' && add1(digits, prec))
- exp++;
- exp += ndigits-prec;
- ndigits = prec;
- }
-
- /*
- * extra rules for %g (implemented below):
- * trailing zeros removed after decimal unless FmtSharp.
- * decimal point only if digit follows.
- */
-
- /* fall through to %e */
- default:
- case 'e':
- /* one significant digit before decimal, no leading zeros. */
- pt = 1;
- z1 = 0;
-
- /*
- * decimal point is after ndigits digits right now.
- * slide to be after first.
- */
- e = exp + (ndigits-1);
-
- /* if this is %g, check exponent and convert prec */
- if(realverb == 'g') {
- if(-4 <= e && e < prec)
- goto casef;
- prec--; /* one digit before decimal; rest after */
- }
-
- /* compute trailing zero padding or truncate digits. */
- if(1+prec >= ndigits)
- z2 = 1+prec - ndigits;
- else {
- /* truncate digits */
- assert(realverb != 'g');
- newndigits = 1+prec;
- if(digits[newndigits] >= '5' && add1(digits, newndigits)) {
- /* had 999e4, now have 100e5 */
- e++;
- }
- ndigits = newndigits;
- z2 = 0;
- }
- fmtexp(suf, e, ucase);
- nsuf = strlen(suf);
- break;
-
- casef:
- case 'f':
- /* determine where digits go with respect to decimal point */
- if(ndigits+exp > 0) {
- pt = ndigits+exp;
- z1 = 0;
- } else {
- pt = 1;
- z1 = 1 + -(ndigits+exp);
- }
-
- /*
- * %g specifies prec = number of significant digits
- * convert to number of digits after decimal point
- */
- if(realverb == 'g')
- prec += z1 - pt;
-
- /* compute trailing zero padding or truncate digits. */
- if(pt+prec >= z1+ndigits)
- z2 = pt+prec - (z1+ndigits);
- else{
- /* truncate digits */
- assert(realverb != 'g');
- newndigits = pt+prec - z1;
- if(newndigits < 0){
- z1 += newndigits;
- newndigits = 0;
- }else if(newndigits == 0){
- /* perhaps round up */
- if(digits[0] >= '5'){
- digits[0] = '1';
- newndigits = 1;
- goto newdigit;
- }
- }else if(digits[newndigits] >= '5' && add1(digits, newndigits)){
- /* digits was 999, is now 100; make it 1000 */
- digits[newndigits++] = '0';
- newdigit:
- /* account for new digit */
- if(z1) /* 0.099 => 0.100 or 0.99 => 1.00*/
- z1--;
- else /* 9.99 => 10.00 */
- pt++;
- }
- z2 = 0;
- ndigits = newndigits;
- }
- nsuf = 0;
- break;
- }
-
- /*
- * if %g is given without FmtSharp, remove trailing zeros.
- * must do after truncation, so that e.g. print %.3g 1.001
- * produces 1, not 1.00. sorry, but them's the rules.
- */
- if(realverb == 'g' && !(f & fmt·Sharp)) {
- if(z1+ndigits+z2 >= pt) {
- if(z1+ndigits < pt)
- z2 = pt - (z1+ndigits);
- else{
- z2 = 0;
- while(z1+ndigits > pt && digits[ndigits-1] == '0')
- ndigits--;
- }
- }
- }
-
- /*
- * compute width of all digits and decimal point and suffix if any
- */
- n = z1+ndigits+z2;
- if(n > pt)
- n += ndot;
- else if(n == pt){
- if(f & fmt·Sharp)
- n += ndot;
- else
- pt++; /* do not print any decimal point */
- }
- n += nsuf;
-
- /*
- * determine sign
- */
- sign = 0;
- if(neg)
- sign = '-';
- else if(f & fmt·Sign)
- sign = '+';
- else if(f & fmt·Space)
- sign = ' ';
- if(sign)
- n++;
-
- /* compute padding */
- npad = 0;
- if((f & fmt·Width) && io->width > n)
- npad = io->width - n;
- if(npad && !(f & fmt·Left) && (f & fmt·Zero)){
- z1 += npad;
- pt += npad;
- npad = 0;
- }
-
- /* format the actual field. too bad about doing this twice. */
- if(npad && !(f & fmt·Left) && pad(io, npad < 0))
- return -1;
-
- cur = io->buffer.cur;
- end = io->buffer.end;
-
- if(sign){
- if(cur+1 > end){
- if(!(cur=flush(io,cur,1)))
- return -1;
- end = io->buffer.end;
- }
- *cur++ = sign;
- }
-
- while(z1>0 || ndigits>0 || z2>0){
- if(z1 > 0){
- z1--;
- c = '0';
- }else if(ndigits > 0){
- ndigits--;
- c = *digits++;
- }else{
- z2--;
- c = '0';
- }
-
- if(cur+1 > end){
- if(!(cur=flush(io,cur,1)))
- return -1;
- end = io->buffer.end;
- }
- *cur++ = c;
-
- if(--pt == 0)
- for(p=dot; *p; p++){
- if(cur+1 > end){
- if(!(cur=flush(io,cur,1)))
- return -1;
- end = io->buffer.end;
- }
- *cur++ = *p;
- }
- }
- io->n += cur - (char*)io->buffer.cur;
- io->buffer.cur = cur;
- if(nsuf && copy(io, suf, nsuf, nsuf) < 0)
- return -1;
- if(npad && (f & fmt·Left) && pad(io, npad < 0))
- return -1;
-
- return 0;
-}
diff --git a/sys/libfmt/fprint.c b/sys/libfmt/fprint.c
deleted file mode 100644
index 26343f7..0000000
--- a/sys/libfmt/fprint.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "internal.h"
-
-int
-fprint(int fd, char *fmt, ...)
-{
- int n;
- va_list args;
-
- va_start(args, fmt);
- n = fmt·vfprint(fd, fmt, args);
- va_end(args);
-
- return n;
-}
diff --git a/sys/libfmt/internal.h b/sys/libfmt/internal.h
deleted file mode 100644
index 725cfff..0000000
--- a/sys/libfmt/internal.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-#include <libfmt.h>
-
-typedef int (*Formatter)(fmt·State *io);
-typedef struct Verb Verb;
-
-struct Verb
-{
- int c;
- Formatter fmt;
-};
-
-void fmt·setlocale(fmt·State *io, char *decimal, char *thousands, char *groups);
diff --git a/sys/libfmt/locale.c b/sys/libfmt/locale.c
deleted file mode 100644
index 437c61e..0000000
--- a/sys/libfmt/locale.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "internal.h"
-
-void
-fmt·setlocale(fmt·State *io, char *decimal, char *thousands, char *groups)
-{
- if(decimal == nil || decimal[0] == '\0')
- decimal = ".";
- if(thousands == nil)
- thousands = ",";
- if(groups == nil)
- groups = "\3";
-
- io->groups = groups;
- io->decimal = decimal;
- io->thousands = thousands;
-}
diff --git a/sys/libfmt/nsprint.c b/sys/libfmt/nsprint.c
deleted file mode 100644
index 90489e0..0000000
--- a/sys/libfmt/nsprint.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "internal.h"
-
-int
-fmt·nsprint(int len, char *buf, char *fmt, ...)
-{
- int n;
- va_list args;
-
- va_start(args, fmt);
- n = fmt·vnsprint(len, buf, fmt, args);
- va_end(args);
-
- return n;
-}
diff --git a/sys/libfmt/open.c b/sys/libfmt/open.c
deleted file mode 100644
index 8aadef5..0000000
--- a/sys/libfmt/open.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "internal.h"
-
-static int
-flush(fmt·State *io)
-{
- int n, fd;
-
- fd = (uintptr)io->file;
- n = io->buffer.cur - io->buffer.beg;
- if(n && write(fd, io->buffer.beg, n) != n)
- return -1;
-
- io->buffer.cur = io->buffer.beg;
- return io->n;
-}
-
-int
-fmt·open(int fd, int len, char *buf, fmt·State *io)
-{
- io->buffer.beg = buf;
- io->buffer.cur = buf;
- io->buffer.end = buf+len;
- io->flush = flush;
- io->file = (void*)(uintptr)fd;
- io->flag = 0;
- io->n = 0;
- /* no heap needed */
- io->heap = nil;
- io->mem = (mem·Reallocator){ 0 };
-
- fmt·setlocale(io, nil, nil, nil);
-
- return 0;
-}
diff --git a/sys/libfmt/print.c b/sys/libfmt/print.c
deleted file mode 100644
index 20b8e00..0000000
--- a/sys/libfmt/print.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "internal.h"
-
-int
-fmt·print(char *fmt, ...)
-{
- int n;
- va_list args;
-
- va_start(args, fmt);
- n = fmt·vfprint(1, fmt, args);
- va_end(args);
- return n;
-}
diff --git a/sys/libfmt/rules.mk b/sys/libfmt/rules.mk
deleted file mode 100644
index 2b1b431..0000000
--- a/sys/libfmt/rules.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-include share/push.mk
-
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) :=\
- $(d)/buffer.c\
- $(d)/do.c\
- $(d)/esprint.c\
- $(d)/fprint.c\
- $(d)/locale.c\
- $(d)/nsprint.c\
- $(d)/open.c\
- $(d)/print.c\
- $(d)/sprint.c\
- $(d)/vesprint.c\
- $(d)/vfprint.c\
- $(d)/vnsprint.c\
- $(d)/vprint.c\
- $(d)/vwrite.c\
- $(d)/write.c
-
-LIBS_$(d) := $(d)/libfmt.a
-
-TSTS_$(d) := \
- $(d)/test.c
-
-include share/paths.mk
-
-$(LIBS_$(d)): $(OBJS_$(d))
- $(ARCHIVE)
-
-$(UNTS_$(d)): $(TOBJS_$(d)) $(LIBS_$(d)) $(OBJ_DIR)/sys/libutf/libutf.a $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/libfmt/sprint.c b/sys/libfmt/sprint.c
deleted file mode 100644
index f1be6dd..0000000
--- a/sys/libfmt/sprint.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "internal.h"
-
-int
-fmt·sprint(char *buf, char *fmt, ...)
-{
- int n;
- uint len;
- va_list args;
-
- len = 1 << 30;
- if(buf+len < buf)
- len = -(uintptr)buf-1;
-
- va_start(args, fmt);
- n = fmt·vnsprint(len, buf, fmt, args);
- va_end(args);
-
- return n;
-}
diff --git a/sys/libfmt/test.c b/sys/libfmt/test.c
deleted file mode 100644
index d81a62e..0000000
--- a/sys/libfmt/test.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-#include <libfmt.h>
-
-typedef struct Complex
-{
- double r, i;
-} Complex;
-
-int
-Xfmt(fmt·State *io)
-{
- Complex c;
- c = va_arg(io->args, Complex);
-
- return fmt·write(io, "(real=%g,imag=%g)", c.r, c.i);
-}
-
-int
-main(int argc, char *argv[])
-{
- fmt·print("basic tests\n");
- fmt·print("\tx: %x\n", 0x87654321);
- fmt·print("\tu: %u\n", 0x87654321);
- fmt·print("\td: %d\n", 0x87654321);
- fmt·print("\ts: %s\n", "hi there");
- fmt·print("\tc: %c\n", '!');
- fmt·print("\tg: %g %g %g\n", 3.14159, 3.14159e10, 3.14159e-10);
- fmt·print("\te: %e %e %e\n", 3.14159, 3.14159e10, 3.14159e-10);
- fmt·print("\tf: %f %f %f\n", 3.14159, 3.14159e10, 3.14159e-10);
- fmt·print("\tsmiley: %C\n", (rune)0x263a);
- fmt·print("\t%g %.18g\n", 2e25, 2e25);
- fmt·print("\t%2.18g\n", 1.0);
- fmt·print("\t%2.18f\n", 1.0);
- fmt·print("\t%f\n", 3.1415927/4);
- fmt·print("\t%d\n", 23);
- fmt·print("\t%i\n", 23);
- fmt·print("\t%0.10d\n", 12345);
-
- fmt·print("%%4%%d tests\n");
- fmt·print("\t%3$d %4$06d %2$d %1$d\n", 444, 333, 111, 222);
- fmt·print("\t%3$d %4$06d %2$d %1$d\n", 444, 333, 111, 222);
- fmt·print("\t%3$d %4$*5$06d %2$d %1$d\n", 444, 333, 111, 222, 20);
- fmt·print("\t%3$hd %4$*5$06d %2$d %1$d\n", 444, 333, (short)111, 222, 20);
- fmt·print("\t%3$lld %4$*5$06d %2$d %1$d\n", 444, 333, 111LL, 222, 20);
-
- /* test %'d formats */
- fmt·print("%%'%%d tests\n");
- fmt·print("\t%'d %'d %'d\n", 1, 2222, 33333333);
- fmt·print("\t%'019d\n", 0);
- fmt·print("\t%08d %08d %08d\n", 1, 2222, 33333333);
- fmt·print("\t%'08d %'08d %'08d\n", 1, 2222, 33333333);
- fmt·print("\t%'x %'X %'b\n", 0x11111111, 0xabcd1234, 12345);
- fmt·print("\t%'lld %'lld %'lld\n", 1LL, 222222222LL, 3333333333333LL);
- fmt·print("\t%019lld %019lld %019lld\n", 1LL, 222222222LL, 3333333333333LL);
- fmt·print("\t%'019lld %'019lld %'019lld\n", 1LL, 222222222LL, 3333333333333LL);
- fmt·print("\t%'020lld %'020lld %'020lld\n", 1LL, 222222222LL, 3333333333333LL);
- fmt·print("\t%'llx %'llX %'llb\n", 0x111111111111LL, 0xabcd12345678LL, 112342345LL);
-
- /* test precision */
- fmt·print("precision tests\n");
- fmt·print("%020.10d\n", 100);
-
- /* test install */
- fmt·install('X', Xfmt);
- Complex c = { 1.5, -2.3 };
- fmt·print("x = %X\n", c);
-
- return 0;
-
-}
diff --git a/sys/libfmt/vesprint.c b/sys/libfmt/vesprint.c
deleted file mode 100644
index 18f4dd2..0000000
--- a/sys/libfmt/vesprint.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "internal.h"
-
-char*
-fmt·vesprint(char *buf, char *end, char *fmt, va_list args)
-{
- fmt·State io;
-
- if(end <= buf)
- return nil;
-
- io.n = 0;
- io.buffer.beg = io.buffer.cur = buf;
- io.buffer.end = end-1;
- io.flush = nil;
- io.file = nil;
-
- va_copy(io.args, args);
-
- fmt·setlocale(&io, nil, nil, nil);
- fmt·do(&io, fmt);
-
- va_end(io.args);
-
- *(io.buffer.cur) = 0;
- return io.buffer.cur;
-}
diff --git a/sys/libfmt/vfprint.c b/sys/libfmt/vfprint.c
deleted file mode 100644
index 4306ea7..0000000
--- a/sys/libfmt/vfprint.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "internal.h"
-
-int
-fmt·vfprint(int fd, char *fmt, va_list args)
-{
- int n;
- fmt·State io;
- char buf[256];
-
- fmt·open(fd, sizeof(buf), buf, &io);
-
- va_copy(io.args, args);
- n = fmt·do(&io, fmt);
- va_end(io.args);
-
- if(n > 0 && io.flush(&io) < 0)
- return -1;
- return n;
-}
diff --git a/sys/libfmt/vnsprint.c b/sys/libfmt/vnsprint.c
deleted file mode 100644
index 7ded908..0000000
--- a/sys/libfmt/vnsprint.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "internal.h"
-
-int
-fmt·vnsprint(int len, char *buf, char *fmt, va_list args)
-{
- fmt·State io;
-
- if(len <= 0)
- return -1;
-
- io.n = 0;
- io.buffer.beg = io.buffer.cur = buf;
- io.buffer.end = buf+len-1;
- io.flush = nil;
- io.file = nil;
-
- va_copy(io.args, args);
-
- fmt·setlocale(&io, nil, nil, nil);
- fmt·do(&io, fmt);
-
- va_end(io.args);
-
- *(io.buffer.cur) = 0;
- return io.buffer.cur - io.buffer.beg;
-}
diff --git a/sys/libfmt/vprint.c b/sys/libfmt/vprint.c
deleted file mode 100644
index bb3076b..0000000
--- a/sys/libfmt/vprint.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "internal.h"
-
-int
-fmt·vprint(char *fmt, va_list args)
-{
- fmt·State io;
- int n;
- char buf[256];
-
- fmt·open(1, sizeof(buf), buf, &io);
-
- va_copy(io.args, args);
- n = fmt·do(&io, fmt);
- va_end(io.args);
-
- if(n > 0 && io.flush(&io) < 0)
- return -1;
- return n;
-}
diff --git a/sys/libfmt/vwrite.c b/sys/libfmt/vwrite.c
deleted file mode 100644
index cacdef2..0000000
--- a/sys/libfmt/vwrite.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "internal.h"
-
-int
-fmt·vwrite(fmt·State *io, char *fmt, va_list args)
-{
- int n;
- va_list tmp;
-
- io->flag = io->width = io->prec = 0;
-
- va_copy(tmp, io->args);
- va_end(io->args);
-
- va_copy(io->args,args);
- n = fmt·do(io, fmt);
- va_end(io->args);
-
- va_copy(io->args, tmp);
- va_end(tmp);
-
- io->flag = io->width = io->prec = 0;
-
- if(n >= 0)
- return 0;
- return n;
-}
diff --git a/sys/libfmt/write.c b/sys/libfmt/write.c
deleted file mode 100644
index 9a77223..0000000
--- a/sys/libfmt/write.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "internal.h"
-
-int
-fmt·write(fmt·State *io, char *fmt, ...)
-{
- int n;
- va_list args;
-
- io->flag = io->width = io->prec = 0;
-
- va_copy(args, io->args);
- va_end(io->args);
-
- va_start(io->args, fmt);
- n = fmt·do(io, fmt);
- va_end(io->args);
-
- io->flag = io->width = io->prec = 0;
- if(n >= 0)
- return 0;
- return n;
-}
diff --git a/sys/libmath/basic.c b/sys/libmath/basic.c
deleted file mode 100644
index 1341f7b..0000000
--- a/sys/libmath/basic.c
+++ /dev/null
@@ -1,531 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <libmath.h>
-
-#include <math.h>
-
-// TODO(nnoll): Replace implementations with your own.
-
-double
-math·acos(double x)
-{
- return acos(x);
-}
-
-float
-math·acosf(float x)
-{
- return acosf(x);
-}
-
-
-double
-math·acosh(double x)
-{
- return acosh(x);
-}
-
-float
-math·acoshf(float x)
-{
- return acoshf(x);
-}
-
-
-double
-math·asin(double x)
-{
- return asin(x);
-}
-
-float
-math·asinf(float x)
-{
- return asinf(x);
-}
-
-
-double
-math·asinh(double x)
-{
- return asinh(x);
-}
-
-float
-math·asinhf(float x)
-{
- return asinhf(x);
-}
-
-
-double
-math·atan(double x)
-{
- return atan(x);
-}
-
-float
-math·atanf(float x)
-{
- return atanf(x);
-}
-
-
-double
-math·atan2(double x, double y)
-{
- return atan2(x, y);
-}
-
-float
-math·atan2f(float x, float y)
-{
- return atan2f(x, y);
-}
-
-double
-math·atanh(double x)
-{
- return atanh(x);
-}
-
-float
-math·atanhf(float x)
-{
- return atanhf(x);
-}
-
-
-double
-math·cbrt(double x)
-{
- return cbrt(x);
-}
-
-float
-math·cbrtf(float x)
-{
- return cbrtf(x);
-}
-
-
-double
-math·ceil(double x)
-{
- return ceil(x);
-}
-
-float
-math·ceilf(float x)
-{
- return ceilf(x);
-}
-
-double
-math·cos(double x)
-{
- return cos(x);
-}
-
-float
-math·cosf(float x)
-{
- return cosf(x);
-}
-
-
-double
-math·cosh(double x)
-{
- return cosh(x);
-}
-
-float
-math·coshf(float x)
-{
- return coshf(x);
-}
-
-
-double
-math·erf(double x)
-{
- return erf(x);
-}
-
-float
-math·erff(float x)
-{
- return erff(x);
-}
-
-
-double
-math·erfc(double x)
-{
- return erfc(x);
-}
-
-float
-math·erfcf(float x)
-{
- return erfcf(x);
-}
-
-
-double
-math·exp(double x)
-{
- return exp(x);
-}
-
-float
-math·expf(float x)
-{
- return expf(x);
-}
-
-
-double
-math·exp2(double x)
-{
- return exp2(x);
-}
-
-float
-math·exp2f(float x)
-{
- return exp2f(x);
-}
-
-
-double
-math·expm1(double x)
-{
- return expm1(x);
-}
-
-float
-math·expm1f(float x)
-{
- return expm1f(x);
-}
-
-
-double
-math·floor(double x)
-{
- return floor(x);
-}
-
-float
-math·floorf(float x)
-{
- return floorf(x);
-}
-
-
-int
-math·ilogb(double x)
-{
- return ilogb(x);
-}
-
-int
-math·ilogbf(float x)
-{
- return ilogbf(x);
-}
-
-double
-math·lgamma(double x)
-{
- return lgamma(x);
-}
-
-float
-math·lgammaf(float x)
-{
- return lgammaf(x);
-}
-
-
-vlong
-math·llrint(double x)
-{
- return math·llrint(x);
-}
-
-vlong
-math·llrintf(float x)
-{
- return math·llrintf(x);
-}
-
-
-vlong
-math·llround(double x)
-{
- return llround(x);
-}
-
-vlong
-math·llroundf(float x)
-{
- return llroundf(x);
-}
-
-
-double
-math·log(double x)
-{
- return log(x);
-}
-
-float
-math·logf(float x)
-{
- return logf(x);
-}
-
-
-double
-math·log10(double x)
-{
- return log10(x);
-}
-
-float
-math·log10f(float x)
-{
- return log10f(x);
-}
-
-
-double
-math·log1p(double x)
-{
- return log1p(x);
-}
-
-float
-math·log1pf(float x)
-{
- return log1pf(x);
-}
-
-
-double
-math·log2(double x)
-{
- return log2(x);
-}
-
-float
-math·log2f(float x)
-{
- return log2f(x);
-}
-
-
-double
-math·logb(double x)
-{
- return logb(x);
-}
-
-float
-math·logbf(float x)
-{
- return logbf(x);
-}
-
-
-long
-math·lrint(double x)
-{
- return lrint(x);
-}
-
-long
-math·lrintf(float x)
-{
- return lrintf(x);
-}
-
-
-long
-math·lround(double x)
-{
- return lround(x);
-}
-
-long
-math·lroundf(float x)
-{
- return lroundf(x);
-}
-
-
-double math·modf(double, double *);
-float math·modff(float, float *);
-
-double
-math·nan(const char * x)
-{
- return nan(x);
-}
-
-float
-math·nanf(const char * x)
-{
- return nanf(x);
-}
-
-
-double
-math·nearbyint(double x)
-{
- return nearbyint(x);
-}
-
-float
-math·nearbyintf(float x)
-{
- return nearbyintf(x);
-}
-
-
-double
-math·pow(double x, double exp)
-{
- return pow(x, exp);
-}
-
-float
-math·powf(float x, float exp)
-{
- return powf(x, exp);
-}
-
-double
-math·rint(double x)
-{
- return rint(x);
-}
-
-float
-math·rintf(float x)
-{
- return rintf(x);
-}
-
-
-double
-math·round(double x)
-{
- return round(x);
-}
-
-float
-math·roundf(float x)
-{
- return roundf(x);
-}
-
-
-double math·scalbln(double, long);
-float math·scalblnf(float, long);
-
-double math·scalbn(double, int);
-float math·scalbnf(float, int);
-
-double
-math·sin(double x)
-{
- return sin(x);
-}
-
-float
-math·sinf(float x)
-{
- return sinf(x);
-}
-
-
-double
-math·sinh(double x)
-{
- return sinh(x);
-}
-
-float
-math·sinhf(float x)
-{
- return sinhf(x);
-}
-
-
-double
-math·sqrt(double x)
-{
- return sqrt(x);
-}
-
-float
-math·sqrtf(float x)
-{
- return sqrtf(x);
-}
-
-
-double
-math·tan(double x)
-{
- return tan(x);
-}
-
-float
-math·tanf(float x)
-{
- return tanf(x);
-}
-
-
-double
-math·tanh(double x)
-{
- return tanh(x);
-}
-
-float
-math·tanhf(float x)
-{
- return tanhf(x);
-}
-
-
-double
-math·tgamma(double x)
-{
- return tgamma(x);
-}
-
-float
-math·tgammaf(float x)
-{
- return tgammaf(x);
-}
-
-
-double
-math·trunc(double x)
-{
- return trunc(x);
-}
-
-float
-math·truncf(float x)
-{
- return truncf(x);
-}
diff --git a/sys/libmath/blas.c b/sys/libmath/blas.c
deleted file mode 100644
index 18f9760..0000000
--- a/sys/libmath/blas.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <libmath.h>
-#include <libmath/blas.h>
-#include <time.h>
-
-/* #include <vendor/blas/cblas.h> */
-
-#define NCOL 2*512
-#define NROW 2*512
-#define NSUM 2*512
-#define NIT 10
-#define INC 1
-error
-main()
-{
- int i, j, nit;
- double *x, *y, *z, *w, res[2];
-
- clock_t t;
- double tprof[2] = { 0 };
-
- rng·init(0);
-
- x = malloc(sizeof(*x)*NROW*NCOL);
- y = malloc(sizeof(*x)*NROW*NCOL);
- z = malloc(sizeof(*x)*NROW*NCOL);
- w = malloc(sizeof(*x)*NROW*NCOL);
-
-#define DO_0 t = clock(); \
- blas·dgemm(0,0,NROW,NCOL,NSUM,10.1,x,NROW,y,NROW,1.2,z,NROW);\
- t = clock() - t; \
- res[0] += blas·dasum(NROW*NCOL,z,INC); \
- tprof[0] += 1000.*t/CLOCKS_PER_SEC; \
-
-#define DO_1 t = clock(); \
- cblas_dgemm(CblasRowMajor,CblasNoTrans,CblasNoTrans,NROW,NCOL,NSUM,10.1,x,NROW,y,NROW,1.2,w,NROW);\
- t = clock() - t; \
- res[1] += cblas_dasum(NROW*NCOL,w,INC); \
- tprof[1] += 1000.*t/CLOCKS_PER_SEC;
-
- for (nit = 0; nit < NIT; nit++) {
- for (i = 0; i < NROW; i++) {
- for (j = 0; j < NCOL; j++) {
- x[j + NROW*i] = rng·random();
- y[j + NROW*i] = rng·random();
- z[j + NROW*i] = rng·random();
- w[j + NROW*i] = z[j + NROW*i];
- }
- }
-
- switch (nit % 2) {
- case 0: DO_0; DO_1; break;
- case 1: DO_1; DO_0; break;
- }
- }
- printf("mean time/iteration (mine): %fms\n", tprof[0]/NIT);
- printf("--> result (mine): %f\n", res[0]);
- printf("mean time/iteration (openblas): %fms\n", tprof[1]/NIT);
- printf("--> result (openblas): %f\n", res[1]);
-
- return 0;
-}
diff --git a/sys/libmath/blas1.c b/sys/libmath/blas1.c
deleted file mode 100644
index a8ca085..0000000
--- a/sys/libmath/blas1.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <u.h>
-#include <libmath.h>
-
-// -----------------------------------------------------------------------
-// Templates
-
-#include "loop.h"
-#define BODY_XY() \
- LOOP(UNROLL, 0, INIT); \
- n = ROUNDBY(len, UNROLL); \
- if (incx == 1 && incy == 1) { \
- for (i = 0; i < n; i+=UNROLL) { \
- LOOP(UNROLL,0,KERNEL,1,1); \
- } \
- } else { \
- for (i = 0; i < n; i+=UNROLL) { \
- LOOP(UNROLL,0,KERNEL,incx,incy);\
- } \
- } \
- \
- for (; i < len; i++) { \
- LOOP(1,0,KERNEL,incx,incy); \
- }
-
-#define BODY_X() \
- LOOP(UNROLL, 0, INIT); \
- n = ROUNDBY(len, UNROLL); \
- if (incx == 1) { \
- for (i = 0; i < n; i+=UNROLL) { \
- LOOP(UNROLL,0,KERNEL,1); \
- } \
- } else { \
- for (i = 0; i < n; i+=UNROLL) { \
- LOOP(UNROLL,0,KERNEL,incx); \
- } \
- } \
- \
- for (; i < len; i++) { \
- LOOP(1,0,KERNEL,incx); \
- }
-
-// -----------------------------------------------------------------------
-// Implementation
-
-#define UNROLL 8
-#define INT int
-
-#define FLOAT double
-#define func(name) blas·d##name
-#include "blas1body"
-
-#undef FLOAT
-#undef func
-
-#define FLOAT float
-#define func(name) blas·f##name
-#include "blas1body"
-#undef FLOAT
diff --git a/sys/libmath/blas1body b/sys/libmath/blas1body
deleted file mode 100644
index de4b637..0000000
--- a/sys/libmath/blas1body
+++ /dev/null
@@ -1,215 +0,0 @@
-/* vim: set ft=c */
-// -----------------------------------------------------------------------
-// Function implementations
-
-FLOAT
-func(dot)(INT len, FLOAT *x, INT incx, FLOAT *y, INT incy)
-{
-#define INIT(I,...) reg[I] = 0;
-#define KERNEL(I, INCX, INCY) reg[I] += x[(INCX)*(i + I)] * y[(INCY)*(i + I)];
- INT i, n;
- FLOAT reg[UNROLL];
-
- BODY_XY()
-
- for (i = 1; i < UNROLL; i++)
- reg[0] += reg[i];
-
- return reg[0];
-#undef INIT
-#undef KERNEL
-}
-
-void
-func(copy)(INT len, FLOAT *x, INT incx, FLOAT *y, INT incy)
-{
-#define INIT(I,...)
-#define KERNEL(I, INCX, INCY) y[(INCY)*(i + I)] = x[(INCX)*(i + I)];
- INT i, n;
-
- BODY_XY();
-
-#undef INIT
-#undef KERNEL
-}
-
-void
-func(swap)(INT len, FLOAT *x, INT incx, FLOAT *y, INT incy)
-{
-#define INIT(I,...)
-#define KERNEL(I, INCX, INCY) tmp[I] = x[(INCX)*(i + I)], x[(INCX)*(i + I)] = y[(INCY)*(i + I)], y[(INCY)*(i + I)] = tmp[I];
- INT i, n;
- FLOAT tmp[UNROLL];
-
- BODY_XY();
-
-#undef INIT
-#undef KERNEL
-}
-
-void
-func(axpy)(INT len, FLOAT a, FLOAT *x, INT incx, FLOAT *y, INT incy)
-{
-#define INIT(I,...)
-#define KERNEL(I, INCX, INCY) y[(INCY)*(i + I)] += a*x[(INCX)*(i + I)];
- INT i, n;
-
- BODY_XY();
-
-#undef INIT
-#undef KERNEL
-}
-
-void
-func(axpby)(INT len, FLOAT a, FLOAT *x, INT incx, FLOAT b, FLOAT *y, INT incy)
-{
-#define INIT(I,...)
-#define KERNEL(I, INCX, INCY) y[(INCY)*(i + I)] = a*x[(INCX)*(i + I)] + b*y[(INCY)*(i + I)];
- INT i, n;
-
- BODY_XY();
-
-#undef INIT
-#undef KERNEL
-}
-
-INT
-func(argmax)(INT len, FLOAT *x, INT incx)
-{
-#define INIT(I,...) max[I] = x[I], idx[I] = I;
-#define KERNEL(I, INCX) if (x[(INCX)*(i+I)] > max[I]) {max[i] = x[INCX*(i+I)]; idx[I] = i+I;}
- INT i, n;
- FLOAT max[UNROLL];
- INT idx[UNROLL];
-
- BODY_X();
-
- for (i = 1; i < UNROLL; i++)
- if (max[i] > max[0])
- idx[0] = idx[i];
-
- return idx[0];
-#undef INIT
-#undef KERNEL
-}
-
-INT
-func(argmin)(INT len, FLOAT *x, INT incx)
-{
-#define INIT(I,...) min[I] = x[I], idx[I] = I;
-#define KERNEL(I, INCX) if (x[INCX*(i+I)] < min[I]) {min[i] = x[INCX*(i+I)]; idx[I] = i+I;}
- INT i, n;
- FLOAT min[UNROLL];
- INT idx[UNROLL];
-
- BODY_X();
-
- for (i = 1; i < UNROLL; i++)
- if (min[i] < min[0])
- idx[0] = idx[i];
-
- return idx[0];
-#undef INIT
-#undef KERNEL
-}
-
-FLOAT
-func(asum)(INT len, FLOAT *x, INT incx)
-{
-#define INIT(I,...) sum[I] = 0;
-#define KERNEL(I, INCX) sum[I] += x[INCX*(i+I)] > 0 ? x[INCX*(i+I)] : -x[INCX*(i+I)];
- INT i, n;
- FLOAT sum[UNROLL];
-
- BODY_X();
-
- for (i = 1; i < UNROLL; i++)
- sum[0] += sum[i];
-
- return sum[0];
-
-#undef INIT
-#undef KERNEL
-}
-
-void
-func(scale)(INT len, FLOAT a, FLOAT *x, INT incx)
-{
-#define INIT(I, ...)
-#define KERNEL(I, INCX) x[INCX*(i+I)] *= a;
- INT i, n;
-
- BODY_X();
-
-#undef INIT
-#undef KERNEL
-}
-
-FLOAT
-func(norm)(INT len, FLOAT *x, INT incx)
-{
-#define INIT(I, ...)
-#define KERNEL(I, INCX) norm[I] += x[INCX*(i+I)] * x[INCX*(i+I)];
- INT i, n;
- FLOAT norm[UNROLL];
-
- BODY_X();
-
- for (i = 1; i < UNROLL; i++)
- norm[0] += norm[i];
-
- return math·sqrt(norm[0]);
-
-#undef INIT
-#undef KERNEL
-}
-
-void
-func(drot)(INT len, FLOAT *x, INT incx, FLOAT *y, INT incy, FLOAT cos, FLOAT sin)
-{
-#define INIT(I, ...)
-#define KERNEL(I, INCX, INCY) tmp[I] = x[INCX*(i+I)], x[INCX*(i+I)] = cos*x[INCX*(i+I)] + sin*y[INCY*(i+I)], y[INCY*(i+I)] = cos*y[INCY*(i+I)] - sin*tmp[I];
- INT i, n;
- FLOAT tmp[UNROLL];
-
- BODY_XY();
-
-#undef INIT
-#undef KERNEL
-}
-
-void
-func(rotm)(INT len, FLOAT *x, INT incx, FLOAT *y, INT incy, FLOAT H[5])
-{
-#define INIT(I, ...)
-#define KERNEL(I, INCX, INCY) tmp[I] = x[INCX*(i+I)], x[INCX*(i+I)] = H[1]*x[INCX*(i+I)] + H[2]*y[INCY*(i+I)], y[INCY*(i+I)] = H[3]*tmp[I] + H[4]*y[INCY*(i+I)];
- INT i, n, f;
- FLOAT tmp[UNROLL];
-
- f = (INT)H[0];
- switch (f) {
- case -2:
- H[1] = +1;
- H[2] = +0;
- H[3] = +0;
- H[4] = +1;
- break;
- case -1:
- break;
- case +0:
- H[1] = +1;
- H[4] = +1;
- break;
- case +1:
- H[2] = +1;
- H[3] = -1;
- break;
- default:
- return;
- }
-
- BODY_XY();
-
-#undef INIT
-#undef KERNEL
-}
diff --git a/sys/libmath/blas2.c b/sys/libmath/blas2.c
deleted file mode 100644
index 7e4b08e..0000000
--- a/sys/libmath/blas2.c
+++ /dev/null
@@ -1,222 +0,0 @@
-#include <u.h>
-#include <libmath/blas.h>
-#include "loop.h"
-
-// -----------------------------------------------------------------------
-// Templates
-
-#define BODY_RECT() \
- nr = ROUNDBY(nrow, UNROW); \
- nc = ROUNDBY(ncol, UNCOL); \
- if (incx == 1 && incy == 1) { \
- for (r = 0; r < nr; r += UNROW) { \
- LOOP(UNROW,0,INIT,1,1); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(UNROW,0,KERN,1,1,UNCOL); \
- } \
- for (; c < ncol; c++) { \
- LOOP(UNROW,0,KERN,1,1,1); \
- } \
- LOOP(UNROW,0,FINI,1,1); \
- } \
- } else { \
- for (r = 0; r < nr; r += UNROW) { \
- LOOP(UNROW,0,INIT,incx,incy); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(UNROW,0,KERN,incx,incy,UNCOL); \
- } \
- for (; c < ncol; c++) { \
- LOOP(UNROW,0,KERN,incx,incy,1); \
- } \
- LOOP(UNROW,0,FINI,incx,incy); \
- } \
- } \
- \
- for (; r < nrow; r++) { \
- LOOP(1,0,INIT,incx,incy); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(1,0,KERN,incx,incy,UNCOL); \
- } \
- for (; c < ncol; c++) { \
- LOOP(1,0,KERN,incx,incy,1); \
- } \
- LOOP(1,0,FINI,incx,incy); \
- }
-
-#define BODY_LOTRI() \
- nr = ROUNDBY(n, UNROW); \
- if (incx == 1) { \
- for (r = 0; r < nr; r += UNROW) { \
- LOOP(UNROW,0,INIT,1); \
- nc = ROUNDBY(r, UNCOL); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(UNROW,0,KERN,1,UNCOL); \
- } \
- for (; c < r; c++) { \
- LOOP(UNROW,0,KERN,1,1); \
- } \
- LOOP(UNROW,0,FINI,1); \
- } \
- } else { \
- for (r = 0; r < nr; r += UNROW) { \
- LOOP(UNROW,0,INIT,incx); \
- nc = ROUNDBY(r, UNCOL); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(UNROW,0,KERN,incx,UNCOL); \
- } \
- for (; c < r; c++) { \
- LOOP(UNROW,0,KERN,incx,1); \
- } \
- LOOP(UNROW,0,FINI,incx); \
- } \
- } \
- \
- for (; r < n; r++) { \
- LOOP(1,0,INIT,incx); \
- nc = ROUNDBY(r, UNCOL); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(1,0,KERN,incx,UNCOL); \
- } \
- for (; c < r; c++) { \
- LOOP(1,0,KERN,incx,1); \
- } \
- LOOP(1,0,FINI,incx); \
- }
-
-#define BODY_UPTRI() \
- nr = n - ROUNDBY(n, UNROW); \
- if (incx == 1) { \
- for (r = n-1; r >= nr; r -= UNROW) { \
- LOOP(UNROW,0,INIT,1); \
- nc = n - ROUNDBY(r, UNCOL); \
- for (c = n-1; c >= nc; c -= UNCOL) { \
- LOOP(UNROW,0,KERN,1,UNCOL); \
- } \
- for (; c > r; c--) { \
- LOOP(UNROW,0,KERN,1,1); \
- } \
- LOOP(UNROW,0,FINI,1); \
- } \
- } else { \
- for (r = n-1; r >= nr; r -= UNROW) { \
- LOOP(UNROW,0,INIT,incx); \
- nc = n - ROUNDBY(r, UNCOL); \
- for (c = n-1; c >= nc; c -= UNCOL) { \
- LOOP(UNROW,0,KERN,incx,UNCOL); \
- } \
- for (; c > r; c--) { \
- LOOP(UNROW,0,KERN,incx,1); \
- } \
- LOOP(UNROW,0,FINI,incx); \
- } \
- } \
- \
- for (; r >= 0; r--) { \
- LOOP(1,0,INIT,incx); \
- nc = n - ROUNDBY(r, UNCOL); \
- for (c = n-1; c >= nc; c -= UNCOL) { \
- LOOP(1,0,KERN,incx,UNCOL); \
- } \
- for (; c > r; c--) { \
- LOOP(1,0,KERN,incx,1); \
- } \
- LOOP(1,0,FINI,incx); \
- }
-
-#define BODY_LOTRI_XY() \
- nr = ROUNDBY(n, UNROW); \
- if (incx == 1 && incy == 1) { \
- for (r = 0; r < nr; r += UNROW) { \
- LOOP(UNROW,0,INIT,1,1); \
- nc = ROUNDBY(r, UNCOL); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(UNROW,0,KERN,1,1,UNCOL); \
- } \
- for (; c < r; c++) { \
- LOOP(UNROW,0,KERN,1,1,1); \
- } \
- LOOP(UNROW,0,FINI,1,1); \
- } \
- } else { \
- for (r = 0; r < nr; r += UNROW) { \
- LOOP(UNROW,0,INIT,incx,incy); \
- nc = ROUNDBY(r, UNCOL); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(UNROW,0,KERN,incx,incy,UNCOL); \
- } \
- for (; c < r; c++) { \
- LOOP(UNROW,0,KERN,incx,incy,1); \
- } \
- LOOP(UNROW,0,FINI,incx, incy); \
- } \
- } \
- \
- for (; r < n; r++) { \
- LOOP(1,0,INIT,incx,incy); \
- nc = ROUNDBY(r, UNCOL); \
- for (c = 0; c < nc; c += UNCOL) { \
- LOOP(1,0,KERN,incx,incy,UNCOL); \
- } \
- for (; c < r; c++) { \
- LOOP(1,0,KERN,incx,incy,1); \
- } \
- LOOP(1,0,FINI,incx,incy); \
- }
-
-#define BODY_UPTRI_XY() \
- nr = n - ROUNDBY(n, UNROW); \
- if (incx == 1 && incy == 1) { \
- for (r = n-1; r >= nr; r -= UNROW) { \
- LOOP(UNROW,0,INIT,1,1); \
- nc = n - ROUNDBY(r, UNCOL); \
- for (c = n-1; c >= nc; c -= UNCOL) { \
- LOOP(UNROW,0,KERN,1,1,UNCOL); \
- } \
- for (; c > r; c--) { \
- LOOP(UNROW,0,KERN,1,1,1); \
- } \
- LOOP(UNROW,0,FINI,1,1); \
- } \
- } else { \
- for (r = n-1; r >= nr; r -= UNROW) { \
- LOOP(UNROW,0,INIT,incx,incy); \
- nc = n - ROUNDBY(r, UNCOL); \
- for (c = n-1; c >= nc; c -= UNCOL) { \
- LOOP(UNROW,0,KERN,incx,incy,UNCOL); \
- } \
- for (; c > r; c--) { \
- LOOP(UNROW,0,KERN,incx,incy,1); \
- } \
- LOOP(UNROW,0,FINI,incx,incy); \
- } \
- } \
- \
- for (; r >= 0; r--) { \
- LOOP(1,0,INIT,incx,incy); \
- nc = n - ROUNDBY(r, UNCOL); \
- for (c = n-1; c >= nc; c -= UNCOL) { \
- LOOP(1,0,KERN,incx,incy,UNCOL); \
- } \
- for (; c > r; c--) { \
- LOOP(1,0,KERN,incx,incy,1); \
- } \
- LOOP(1,0,FINI,incx,incy); \
- }
-
-// -----------------------------------------------------------------------
-// implementation
-
-#define UNROW 4
-#define UNCOL 4
-
-#define INT int
-#define FLOAT double
-#define func(name) blas·d##name
-#include "blas2body"
-
-#undef FLOAT
-#undef func
-
-#define FLOAT float
-#define func(name) blas·f##name
-#include "blas2body"
diff --git a/sys/libmath/blas2body b/sys/libmath/blas2body
deleted file mode 100644
index 45baf67..0000000
--- a/sys/libmath/blas2body
+++ /dev/null
@@ -1,256 +0,0 @@
-/* general matrix multiply */
-error
-func(gemv)(uint flag, INT nrow, INT ncol, FLOAT a, FLOAT *m, INT incm, FLOAT *x, INT incx, FLOAT b, FLOAT *y, INT incy)
-{
- INT r, c, nr, nc;
- FLOAT *row[UNROW], reg[UNROW];
-#define INIT(I, INCX, INCY) row[I] = m + (r+I)*incm, reg[I] = 0;
-#define TERM(J, I, INCX, INCY) row[I][c+J] * x[INCX*(c+J)]
-#define KERN(I, INCX, INCY, LENGTH) reg[I] += EXPAND(LENGTH,0,TERM,+,I,INCX,INCY);
-#define FINI(I, INCX, INCY) y[INCY*(r+I)] = b*y[INCY*(r+I)] + a*reg[I];
-
- if (!flag) {
- BODY_RECT();
- } else {
- func(scale)(ncol, b, y, incy);
-#undef KERN
-#undef FINI
-#undef INIT
-#undef TERM
-#define INIT(I, INCX, INCY) row[I] = m + (r+I)*incm, reg[I] = a*x[INCX*(r+I)];
-#define TERM(J, I, INCX, INCY) row[I][c+J] * reg[I]
-#define KERN(I, INCX, INCY, LENGTH) y[INCY*(c+I)] += EXPAND(LENGTH,0,TERM,+,I,INCX,INCY);
-#define FINI(I, INCX, INCY)
- BODY_RECT();
- }
-
- return 0;
-#undef INIT
-#undef TERM
-#undef KERN
-#undef FINI
-}
-
-/* symmetric matrix vector multiply (different layouts) */
-void
-func(symv)(uint upper, INT n, FLOAT a, FLOAT *m, INT incm, FLOAT *x, INT incx, FLOAT b, FLOAT *y, INT incy)
-{
- INT r, c, nr, nc, i;
- FLOAT *row[UNROW], reg1[UNROW], reg2[UNROW];
-
-#define INIT(I, INCX, INCY) row[I] = m + (r XX I)*incm, reg1[I] = 0, reg2[I] = 0;
-#define TERM1(J, I, INCX, INCY) row[I][c XX J]*x[INCX*(c XX J)]
-#define TERM2(J, I, INCX, INCY) row[I][c XX J]*x[INCX*((n-c-1) XX J)]
-#define KERN(I, INCX, INCY, REPEAT) reg1[I] += EXPAND(REPEAT,0,TERM1,+,I,INCX,INCY), \
- reg2[I] += EXPAND(REPEAT,0,TERM2,+,I,INCX,INCY);
-#define FINI(I, INCX, INCY) y[INCY*(r+I)] += a*(reg1[I] + row[I][r]*x[INCX*r]), \
- y[INCY*(n-r-1+I)] += a*reg2[I];
-
- func(scale)(n, b, y, incy);
-#define XX +
- if (!upper) {
- BODY_LOTRI_XY();
- } else {
-#undef XX
-#define XX -
- BODY_UPTRI_XY();
- }
-#undef XX
-
-#undef INIT
-}
-
-void
-func(spmv)(uint upper, INT n, FLOAT a, FLOAT *m, FLOAT *x, INT incx, FLOAT b, FLOAT *y, INT incy)
-{
- INT r, c, nr, nc, i;
- FLOAT *row[UNROW], reg1[UNROW], reg2[UNROW];
-
-#define INIT(I, INCX, INCY) row[I] = m + ((r+I)*(r+I+1))*(1/2), reg1[I] = 0, reg2[I] = 0;
-
- func(scale)(n, b, y, incy);
-#define XX +
- if (!upper) {
- BODY_LOTRI_XY();
- } else {
-#undef XX
-#undef INIT
-#define INIT(I, INCX, INCY) row[I] = m + ((2*n-r-I)*(r+I+1))*(1/2), reg1[I] = 0, reg2[I] = 0;
-#define XX -
- BODY_UPTRI_XY();
- }
-#undef XX
-
-#undef TERM
-#undef INIT
-#undef KERN
-#undef FINI
-}
-
-/* triangular multiply (different layouts) */
-void
-func(trmv)(uint upper, INT n, FLOAT *m, INT incm, FLOAT *x, INT incx)
-{
- INT r, c, nr, nc, i;
- FLOAT *row[UNROW], reg[UNROW];
-#define INIT(I, INCX) row[I] = m + (r XX I)*incm, reg[I] = 0;
-#define TERM(J, I, INCX) row[I][c XX J]*x[INCX*(c XX J)]
-#define KERN(I, INCX, REPEAT) reg[I] += EXPAND(REPEAT,0,TERM,+,I,INCX);
-#define FINI(I, INCX) x[INCX*(r XX I)] = row[I][r XX I]*x[INCX*(r XX I)] + reg[I];
-
-#define XX +
- if (!upper) {
- BODY_LOTRI();
- } else {
-#undef XX
-#define XX -
- BODY_UPTRI();
- }
-#undef XX
-
-#undef INIT
-}
-
-void
-func(tpmv)(uint upper, INT n, FLOAT *m, FLOAT *x, INT incx)
-{
- INT r, c, nr, nc, i;
- FLOAT *row[UNROW], reg[UNROW];
-#define INIT(I, INCX) row[I] = m + ((r+I)*(r+I+1))*(1/2), reg[I] = 0;
-
-#define XX +
- if (!upper) {
- BODY_LOTRI();
- } else {
-#undef XX
-#undef INIT
-#define INIT(I, INCX) row[I] = m + ((2*n-r-I)*(r+I+1))*(1/2), reg[I] = 0;
-#define XX -
- BODY_UPTRI();
- }
-#undef XX
-
-#undef INIT
-#undef TERM
-#undef KERN
-#undef FINI
-}
-
-/* triangular solve (different layouts) */
-void
-func(trsv)(uint upper, INT n, FLOAT *m, INT incm, FLOAT *x, INT incx)
-{
- INT r, c, nr, nc, i;
- FLOAT *row[UNROW], reg[UNROW];
-#define INIT(I, INCX) row[I] = m + (r XX I)*incm, reg[I] = 0;
-#define TERM(J, I, INCX) row[I][c XX J]*x[c XX J]
-#define KERN(I, INCX, REPEAT) reg[I] += EXPAND(REPEAT,0,TERM,+,I,INCX);
-#define SOLN(J, I, INCX) reg[J] += row[I][r XX I]*x[INCX*(r XX I)]
-#define FINI(I, INCX) x[INCX*(r XX I)] = reg[I] / row[I][r XX I]; EXPAND_TRI(UNROW,INC(I),SOLN,;,I,INCX);
-
-#define XX +
- if (!upper) {
- BODY_LOTRI();
- } else {
-#undef XX
-#define XX -
- BODY_UPTRI();
- }
-#undef XX
-
-#undef INIT
-}
-
-void
-func(tpsv)(uint upper, INT n, FLOAT *m, FLOAT *x, INT incx)
-{
- INT r, c, nr, nc, i;
- FLOAT *row[UNROW], reg[UNROW];
-#define INIT(I, INCX) row[I] = m + ((r+I)*(r+I+1))*(1/2), reg[I] = 0;
-
-#define XX +
- if (!upper) {
- BODY_LOTRI();
- } else {
-#undef XX
-#undef INIT
-#define INIT(I, INCX) row[I] = m + ((2*n-r-I)*(r+I+1))*(1/2), reg[I] = 0;
-#define XX -
- BODY_UPTRI();
- }
-#undef XX
-
-#undef INIT
-#undef TERM
-#undef KERN
-#undef SOLN
-#undef FINI
-}
-
-/* rank 1 update */
-void
-func(ger)(INT nrow, INT ncol, FLOAT a, FLOAT *x, INT incx, FLOAT *y, INT incy, FLOAT *m, INT incm)
-{
- INT r, c, nr, nc;
- FLOAT *row[UNROW], reg[UNROW];
-#define INIT(I, INCX, INCY) row[I] = m + (r+I)*incm, reg[I] = a*x[INCX*(r+I)];
-#define TERM(J, I, INCX, INCY) row[I][c+J] += reg[I] * y[INCY*(c+J)]
-#define KERN(I, INCX, INCY, LENGTH) EXPAND(LENGTH,0,TERM,;,I,INCX, INCY);
-#define FINI(I, ...)
-
- BODY_RECT();
-
-#undef INIT
-#undef TERM
-#undef KERN
-#undef FINI
-}
-
-/* symmetric rank 1 update (different memory layouts) */
-void
-func(syr)(uint upper, INT n, FLOAT a, FLOAT *x, INT incx, FLOAT *m, INT incm)
-{
- INT r, c, nr, nc;
- FLOAT *row[UNROW], reg[UNROW];
-#define INIT(I, INCX) row[I] = m + (r XX I)*incm, reg[I] = a*x[INCX*(r XX I)];
-#define TERM(J, I, INCX) row[I][c XX J] += reg[I] * x[INCX*(c XX J)]
-#define KERN(I, INCX, LENGTH) EXPAND(LENGTH,0,TERM,;,I,INCX);
-#define FINI(I, ...)
-
-#define XX +
- if (!upper) {
- BODY_LOTRI();
- } else {
-#undef XX
-#define XX -
- BODY_UPTRI();
- }
-#undef XX
-
-#undef INIT
-}
-
-void
-func(spr)(uint upper, INT n, FLOAT a, FLOAT *x, INT incx, FLOAT *m)
-{
- INT r, c, nr, nc;
- FLOAT *row[UNROW], reg[UNROW];
-#define INIT(I, INCX) row[I] = m + ((r+I)*(r+I+1))*(1/2), reg[I] = 0;
-
-#define XX +
- if (!upper) {
- BODY_LOTRI();
- } else {
-#undef XX
-#undef INIT
-#define INIT(I, INCX) row[I] = m + ((2*n-r-I)*(r+I+1))*(1/2), reg[I] = 0;
-#define XX -
- BODY_UPTRI();
- }
-#undef XX
-
-#undef INIT
-#undef TERM
-#undef KERN
-#undef FINI
-}
diff --git a/sys/libmath/blas3.c b/sys/libmath/blas3.c
deleted file mode 100644
index b048c95..0000000
--- a/sys/libmath/blas3.c
+++ /dev/null
@@ -1,279 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <libmath.h>
-
-#define INT int
-#define FLOAT double
-#define func(name) blas·d##name
-
-#define X(i, j) x[j + incx*(i)]
-#define Y(i, j) y[j + incy*(i)]
-#define Z(i, j) z[j + incz*(i)]
-
-void
-func(gemm)(uint trm, uint trn, INT ni, INT nj, INT nk, FLOAT a, FLOAT *x, INT incx, FLOAT *y, INT incy, FLOAT b, FLOAT *z, INT incz)
-{
- INT jj, jb, kk, kb, dk, i, j, k, end;
- FLOAT r0[8], r1[8], r2[8], r3[8], pf;
-
- for (i = 0; i < ni; i++) {
- for (j = 0; j < nj; j++) {
- Z(i,j) *= b;
- }
- }
-
- jb = MIN(256, nj);
- kb = MIN(48, nk);
- for (jj = 0; jj < nj; jj += jb) {
- for (kk = 0; kk < nk; kk += kb) {
- for (i = 0; i < ni; i += 4) {
- for (j = jj; j < jj + jb; j += 8) {
- r0[0] = Z(i+0, j+0); r0[1] = Z(i+0, j+1); r0[2] = Z(i+0, j+2); r0[3] = Z(i+0, j+3);
- r1[0] = Z(i+1, j+0); r1[1] = Z(i+1, j+1); r1[2] = Z(i+1, j+2); r1[3] = Z(i+1, j+3);
- r2[0] = Z(i+2, j+0); r2[1] = Z(i+2, j+1); r2[2] = Z(i+2, j+2); r2[3] = Z(i+2, j+3);
- r3[0] = Z(i+3, j+0); r3[1] = Z(i+3, j+1); r3[2] = Z(i+3, j+2); r3[3] = Z(i+3, j+3);
- end = MIN(nk, kk+kb);
- for (k = kk; k < end; k++) {
- pf = a * X(i, k);
- r0[0] += pf * Y(k, j+0); r0[1] += pf * Y(k, j+1); r0[2] += pf * Y(k, j+2); r0[3] += pf * Y(k, j+3);
-
- pf = a * X(i+1, k);
- r1[0] += pf * Y(k, j+0); r1[1] += pf * Y(k, j+1); r1[2] += pf * Y(k, j+2); r1[3] += pf * Y(k, j+3);
-
- pf = a * X(i+2, k);
- r1[0] += pf * Y(k, j+0); r1[1] += pf * Y(k, j+1); r1[2] += pf * Y(k, j+2); r1[3] += pf * Y(k, j+3);
-
- pf = a * X(i+3, k);
- r1[0] += pf * Y(k, j+0); r1[1] += pf * Y(k, j+1); r1[2] += pf * Y(k, j+2); r1[3] += pf * Y(k, j+3);
- }
- Z(i+0, j+0) = r0[0]; Z(i+0, j+1) = r0[1]; Z(i+0, j+2) = r0[2]; Z(i+0, j+3) = r0[3];
- Z(i+1, j+0) = r1[0]; Z(i+1, j+1) = r1[1]; Z(i+1, j+2) = r1[2]; Z(i+1, j+3) = r1[3];
- Z(i+2, j+0) = r2[0]; Z(i+2, j+1) = r2[1]; Z(i+2, j+2) = r2[2]; Z(i+2, j+3) = r2[3];
- Z(i+3, j+0) = r3[0]; Z(i+3, j+1) = r3[1]; Z(i+3, j+2) = r3[2]; Z(i+3, j+3) = r3[3];
- }
- }
- }
- }
-}
-
-#if 0
-void
-func(gemm)(uint trm, uint trn, INT ni, INT nj, INT nk, FLOAT a, FLOAT *x, INT incx, FLOAT *y, INT incy, FLOAT b, FLOAT *z, INT incz)
-{
- int i, j, k;
- FLOAT w[nj*nk], acc[4][4];
-
- for (i = 0; i < ni; i++) {
- for (j = 0; j < nj; j++) {
- Z(i,j) *= b;
- W(i,j) = Y(j,i);
- }
- }
-
- for (i = 0; i < ni; i+=4) {
- for (j = 0; j < nj; j+=4) {
- memset(acc, 0, sizeof(acc));
- for (k = 0; k < nk; k+=4) {
- acc[0][0] += X(i+0,k)*W(j+0,k) + X(i+0,k+1)*W(j+0,k+1) + X(i+0,k+2)*W(j+0,k+2) + X(i+0,k+3)*W(j+0,k+3);
- acc[0][1] += X(i+0,k)*W(j+1,k) + X(i+0,k+1)*W(j+1,k+1) + X(i+0,k+2)*W(j+1,k+2) + X(i+0,k+3)*W(j+1,k+3);
- acc[0][2] += X(i+0,k)*W(j+2,k) + X(i+0,k+1)*W(j+2,k+1) + X(i+0,k+2)*W(j+2,k+2) + X(i+0,k+3)*W(j+2,k+3);
- acc[0][3] += X(i+0,k)*W(j+3,k) + X(i+0,k+1)*W(j+3,k+1) + X(i+0,k+2)*W(j+3,k+2) + X(i+0,k+3)*W(j+3,k+3);
-
- acc[1][0] += X(i+1,k)*W(j+0,k) + X(i+1,k+1)*W(j+0,k+1) + X(i+1,k+2)*W(j+0,k+2) + X(i+1,k+3)*W(j+0,k+3);
- acc[1][1] += X(i+1,k)*W(j+1,k) + X(i+1,k+1)*W(j+1,k+1) + X(i+1,k+2)*W(j+1,k+2) + X(i+1,k+3)*W(j+1,k+3);
- acc[1][2] += X(i+1,k)*W(j+2,k) + X(i+1,k+1)*W(j+2,k+1) + X(i+1,k+2)*W(j+2,k+2) + X(i+1,k+3)*W(j+2,k+3);
- acc[1][3] += X(i+1,k)*W(j+3,k) + X(i+1,k+1)*W(j+3,k+1) + X(i+1,k+2)*W(j+3,k+2) + X(i+1,k+3)*W(j+3,k+3);
-
- acc[2][0] += X(i+2,k)*W(j+0,k) + X(i+2,k+1)*W(j+0,k+1) + X(i+2,k+2)*W(j+0,k+2) + X(i+2,k+3)*W(j+0,k+3);
- acc[2][1] += X(i+2,k)*W(j+1,k) + X(i+2,k+1)*W(j+1,k+1) + X(i+2,k+2)*W(j+1,k+2) + X(i+2,k+3)*W(j+1,k+3);
- acc[2][2] += X(i+2,k)*W(j+2,k) + X(i+2,k+1)*W(j+2,k+1) + X(i+2,k+2)*W(j+2,k+2) + X(i+2,k+3)*W(j+2,k+3);
- acc[2][3] += X(i+2,k)*W(j+3,k) + X(i+2,k+1)*W(j+3,k+1) + X(i+2,k+2)*W(j+3,k+2) + X(i+2,k+3)*W(j+3,k+3);
-
- acc[2][0] += X(i+3,k)*W(j+0,k) + X(i+3,k+1)*W(j+0,k+1) + X(i+3,k+2)*W(j+0,k+2) + X(i+3,k+3)*W(j+0,k+3);
- acc[2][1] += X(i+3,k)*W(j+1,k) + X(i+3,k+1)*W(j+1,k+1) + X(i+3,k+2)*W(j+1,k+2) + X(i+3,k+3)*W(j+1,k+3);
- acc[2][2] += X(i+3,k)*W(j+2,k) + X(i+3,k+1)*W(j+2,k+1) + X(i+3,k+2)*W(j+2,k+2) + X(i+3,k+3)*W(j+2,k+3);
- acc[2][3] += X(i+3,k)*W(j+3,k) + X(i+3,k+1)*W(j+3,k+1) + X(i+3,k+2)*W(j+3,k+2) + X(i+3,k+3)*W(j+3,k+3);
- // Z(i,j) += X(i,k)*Y(k,j);
- }
- Z(i+0,j+1) = a*acc[0][0];
- Z(i+0,j+2) = a*acc[0][1];
- Z(i+0,j+3) = a*acc[0][2];
- Z(i+0,j+4) = a*acc[0][3];
-
- Z(i+1,j+1) = a*acc[1][0];
- Z(i+1,j+2) = a*acc[1][1];
- Z(i+1,j+3) = a*acc[1][2];
- Z(i+1,j+4) = a*acc[1][3];
-
- Z(i+2,j+1) = a*acc[2][0];
- Z(i+2,j+2) = a*acc[2][1];
- Z(i+2,j+3) = a*acc[2][2];
- Z(i+2,j+4) = a*acc[2][3];
-
- Z(i+3,j+1) = a*acc[3][0];
- Z(i+3,j+2) = a*acc[3][1];
- Z(i+3,j+3) = a*acc[3][2];
- Z(i+3,j+4) = a*acc[3][3];
- }
- }
-}
-#endif
-
-#if 0
-void
-func(gemm)(uint trm, uint trn, INT ni, INT nj, INT nk, FLOAT a, FLOAT *x, INT incx, FLOAT *y, INT incy, FLOAT b, FLOAT *z, INT incz)
-{
- int i, j, k, ri, rj, rk;
- FLOAT reg[4][4], *xrow[4], *yrow[4];
-
- for (i = 0; i < ni; i++) {
- for (j = 0; j < nj; j++) {
- z[j + incz*i] *= b;
- }
- }
-
- for (i = 0; i < ni; i += 4) {
- xrow[0] = x + incx*(i+0);
- xrow[1] = x + incx*(i+1);
- xrow[2] = x + incx*(i+2);
- xrow[3] = x + incx*(i+3);
- for (k = 0; k < nk; k+=4) {
- yrow[0] = y + incy*(k+0);
- yrow[1] = y + incy*(k+1);
- yrow[2] = y + incy*(k+2);
- yrow[3] = y + incy*(k+3);
- reg[0][0] = a * xrow[0][k+0]; reg[0][1] = a * xrow[0][k+1]; reg[0][2] = a * xrow[0][k+2]; reg[0][3] = a * xrow[0][k+3];
- reg[1][0] = a * xrow[1][k+0]; reg[1][1] = a * xrow[1][k+1]; reg[1][2] = a * xrow[1][k+2]; reg[1][3] = a * xrow[1][k+3];
- reg[2][0] = a * xrow[2][k+0]; reg[2][1] = a * xrow[2][k+1]; reg[2][2] = a * xrow[2][k+2]; reg[2][3] = a * xrow[2][k+3];
- reg[3][0] = a * xrow[3][k+0]; reg[3][1] = a * xrow[3][k+1]; reg[3][2] = a * xrow[3][k+2]; reg[3][3] = a * xrow[3][k+3];
- for (j = 0; j < nj; j += 1) {
- z[j + incz*(i+0)] += (reg[0][0]*yrow[0][j]+reg[0][1]*yrow[1][j]+reg[0][2]*yrow[2][j]+reg[0][3]*yrow[3][j]);
- z[j + incz*(i+1)] += (reg[1][0]*yrow[0][j]+reg[1][1]*yrow[1][j]+reg[1][2]*yrow[2][j]+reg[1][3]*yrow[3][j]);
- z[j + incz*(i+2)] += (reg[2][0]*yrow[0][j]+reg[2][1]*yrow[1][j]+reg[2][2]*yrow[2][j]+reg[2][3]*yrow[3][j]);
- z[j + incz*(i+3)] += (reg[3][0]*yrow[0][j]+reg[3][1]*yrow[1][j]+reg[3][2]*yrow[2][j]+reg[3][3]*yrow[3][j]);
- }
- }
- }
-}
-#endif
-
-#if 0
-void
-func(gemm)(uint trm, uint trn, INT ni, INT nj, INT nk, FLOAT a, FLOAT *x, INT incx, FLOAT *y, INT incy, FLOAT b, FLOAT *z, INT incz)
-{
- int i, j, k, ri, rj, rk;
- FLOAT r[4][4], *row[4];
-
- for (i = 0; i < ni; i++) {
- for (j = 0; j < nj; j++) {
- Z(i, j) *= b;
- }
- }
-
- for (i = 0; i < ni; i+=4) {
- for (j = 0; j < nj; j+=4) {
- r[0][0] = 0; r[0][1] = 0; r[0][2] = 0; r[0][3] = 0;
- r[1][0] = 0; r[1][1] = 0; r[1][2] = 0; r[1][3] = 0;
- r[2][0] = 0; r[2][1] = 0; r[2][2] = 0; r[2][3] = 0;
- r[3][0] = 0; r[3][1] = 0; r[3][2] = 0; r[3][3] = 0;
- row[0] = &X(i+0, 0);
- row[1] = &X(i+1, 0);
- row[2] = &X(i+2, 0);
- row[3] = &X(i+3, 0);
- for (k = 0; k < nk; k++) {
- r[0][0] += row[0][k]*Y(k,0); r[0][1] += row[0][k]*Y(k,1); r[0][2] += row[0][k]*Y(k,2); r[0][3] += row[0][k]*Y(k,3);
- r[1][0] += row[1][k]*Y(k,0); r[1][1] += row[1][k]*Y(k,1); r[1][2] += row[1][k]*Y(k,2); r[1][3] += row[1][k]*Y(k,3);
- r[2][0] += row[2][k]*Y(k,0); r[2][1] += row[2][k]*Y(k,1); r[2][2] += row[2][k]*Y(k,2); r[2][3] += row[2][k]*Y(k,3);
- r[3][0] += row[3][k]*Y(k,0); r[3][1] += row[3][k]*Y(k,1); r[3][2] += row[3][k]*Y(k,2); r[3][3] += row[3][k]*Y(k,3);
- }
- Z(i+0, j+0) += r[0][0]; Z(i+0, j+1) += r[0][1]; Z(i+0, j+2) += r[0][2]; Z(i+0, j+3) += r[0][3];
- Z(i+1, j+0) += r[1][0]; Z(i+1, j+1) += r[1][1]; Z(i+1, j+2) += r[1][2]; Z(i+1, j+3) += r[1][3];
- Z(i+2, j+0) += r[2][0]; Z(i+2, j+1) += r[2][1]; Z(i+2, j+2) += r[2][2]; Z(i+2, j+3) += r[2][3];
- Z(i+3, j+0) += r[3][0]; Z(i+3, j+1) += r[3][1]; Z(i+3, j+2) += r[3][2]; Z(i+3, j+3) += r[3][3];
- }
- }
-}
-#endif
-
-#if 0
-void
-func(gemm)(uint trm, uint trn, INT ni, INT nj, INT nk, FLOAT a, FLOAT *x, INT incx, FLOAT *y, INT incy, FLOAT b, FLOAT *z, INT incz)
-{
- int i, j, k, ri, rj, rk;
- FLOAT *xrow[8], *yrow[8], reg;
-
- for (i = 0; i < ni; i++) {
- for (j = 0; j < nj; j++) {
- z[j + incz*i] *= b;
- }
- }
-
- ri = ni & ~7;
- rj = nj & ~7;
- for (i = 0; i < ri; i += 8) {
- xrow[0] = x + incx*(i+0);
- xrow[1] = x + incx*(i+1);
- xrow[2] = x + incx*(i+2);
- xrow[3] = x + incx*(i+3);
- xrow[4] = x + incx*(i+4);
- xrow[5] = x + incx*(i+5);
- xrow[6] = x + incx*(i+6);
- xrow[7] = x + incx*(i+7);
- for (j = 0; j < rj; j += 8) {
- yrow[0] = y + incy*(j+0);
- yrow[1] = y + incy*(j+1);
- yrow[2] = y + incy*(j+2);
- yrow[3] = y + incy*(j+3);
- yrow[4] = y + incy*(j+4);
- yrow[5] = y + incy*(j+5);
- yrow[6] = y + incy*(j+6);
- yrow[7] = y + incy*(j+7);
- for (k = 0; k < nk; k++) {
- reg = a*(yrow[0][k] + yrow[1][k] + yrow[2][k] + yrow[3][k] + yrow[4][k] + yrow[5][k] + yrow[6][k] + yrow[7][k]);
- z[k + incz*(i+0)] += xrow[0][k]*reg;
- z[k + incz*(i+1)] += xrow[1][k]*reg;
- z[k + incz*(i+2)] += xrow[2][k]*reg;
- z[k + incz*(i+3)] += xrow[3][k]*reg;
- z[k + incz*(i+4)] += xrow[4][k]*reg;
- z[k + incz*(i+5)] += xrow[5][k]*reg;
- z[k + incz*(i+6)] += xrow[6][k]*reg;
- z[k + incz*(i+7)] += xrow[7][k]*reg;
- }
- }
- for (; j < nj; j++) {
- for (k = 0; k < nk; k++) {
- reg = a*y[k+incy*j];
- z[k + incz*(i+0)] += xrow[0][k]*reg;
- z[k + incz*(i+1)] += xrow[1][k]*reg;
- z[k + incz*(i+2)] += xrow[2][k]*reg;
- z[k + incz*(i+3)] += xrow[3][k]*reg;
- z[k + incz*(i+4)] += xrow[4][k]*reg;
- z[k + incz*(i+5)] += xrow[5][k]*reg;
- z[k + incz*(i+6)] += xrow[6][k]*reg;
- z[k + incz*(i+7)] += xrow[7][k]*reg;
- }
- }
- }
-
- for (; i < ni; i++) {
- for (j = 0; j < rj; j += 8) {
- yrow[0] = y + incy*(j+0);
- yrow[1] = y + incy*(j+1);
- yrow[2] = y + incy*(j+2);
- yrow[3] = y + incy*(j+3);
- yrow[4] = y + incy*(j+4);
- yrow[5] = y + incy*(j+5);
- yrow[6] = y + incy*(j+6);
- yrow[7] = y + incy*(j+7);
- for (k = 0; k < nk; k++) {
- z[k + incz*(i)] += a*x[k + incx*i]*(yrow[0][k] + yrow[1][k] + yrow[2][k] + yrow[3][k] + yrow[4][k] + yrow[5][k] + yrow[6][k] + yrow[7][k]);
- }
- }
- for (; j < nj; j++) {
- for (k = 0; k < nk; k++) {
- z[k + incz*i] += a*x[k + incx*i]*y[k + incy*j];
- }
- }
- }
-}
-#endif
diff --git a/sys/libmath/lapack.c b/sys/libmath/lapack.c
deleted file mode 100644
index e69de29..0000000
--- a/sys/libmath/lapack.c
+++ /dev/null
diff --git a/sys/libmath/linalg.c b/sys/libmath/linalg.c
deleted file mode 100644
index 8551ff1..0000000
--- a/sys/libmath/linalg.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <libmath.h>
-#include <libmath/blas.h>
-
-// -----------------------------------------------------------------------
-// Vector
-
-void
-linalg·normalize(math·Vector vec)
-{
- double norm;
-
- norm = blas·normd(vec.len, vec.data, 1);
- blas·scaled(vec.len, 1/norm, vec.data, 1);
-}
-// TODO: Write blas wrappers that eat vectors for convenience
-
-// -----------------------------------------------------------------------
-// Matrix
-//
-// NOTE: all matrices are row major oriented
-
-/*
- * linalg·lq
- * computes the LQ decomposition of matrix M: M = LQ
- * L is lower triangular
- * Q is orthogonal -> transp(Q) * Q = I
- *
- * m: matrix to factorize. changes in place
- * + lower triangle -> L
- * + upper triangle -> all reflection vectors stored in rows
- * w: working buffer: len = ncols!
- */
-error
-linalg·lq(math·Matrix m, math·Vector w)
-{
- int i, j, len;
- double *row, mag;
- enum {
- err·nil,
- err·baddims,
- };
-
- if (m.dim[0] > m.dim[1]) {
- return err·baddims;
- }
-
- for (i = 0; i < m.dim[0]; i++, m.data += m.dim[1]) {
- row = m.data + i;
- len = m.dim[0] - i;
-
- // TODO: Don't want to compute norm twice!!
- w.data[0] = math·sgn(row[0]) * blas·normd(len, row, 1);
- blas·axpyd(len, 1.0, row, 1, w.data, 1);
- mag = blas·normd(len, w.data, 1);
- blas·scaled(len, 1/mag, w.data, 1);
-
- blas·copyd(len - m.dim[0], w.data, 1, m.data + i, 1);
- }
-
- return err·nil;
-}
diff --git a/sys/libmath/loop.h b/sys/libmath/loop.h
deleted file mode 100644
index a877d84..0000000
--- a/sys/libmath/loop.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#pragma once
-
-/* increment operator */
-#define INC2(x) INC_##x
-#define INC1(x) INC2(x)
-#define INC(x) INC1(x)
-
-#define INC_0 1
-#define INC_1 2
-#define INC_2 3
-#define INC_3 4
-#define INC_4 5
-#define INC_5 6
-#define INC_6 7
-#define INC_7 8
-#define INC_8 9
-#define INC_9 10
-#define INC_10 11
-#define INC_11 12
-#define INC_12 13
-#define INC_13 14
-#define INC_14 15
-#define INC_15 16
-
-#define ROUNDBY(x, n) ((x) & ~((n)-1))
-
-/* subtraction tables */
-#define SUB2(x, y) SUB_##x##_##y
-#define SUB1(x, y) SUB2(x, y)
-#define SUB(x, y) SUB1(x, y)
-#define SUB_8_0 8
-#define SUB_8_1 7
-#define SUB_8_2 6
-#define SUB_8_3 5
-#define SUB_8_4 4
-#define SUB_8_5 3
-#define SUB_8_6 2
-#define SUB_8_7 1
-#define SUB_8_8 0
-#define SUB_7_0 7
-#define SUB_7_1 6
-#define SUB_7_2 5
-#define SUB_7_3 4
-#define SUB_7_4 3
-#define SUB_7_5 2
-#define SUB_7_6 1
-#define SUB_7_7 0
-#define SUB_6_0 6
-#define SUB_6_1 5
-#define SUB_6_2 4
-#define SUB_6_3 3
-#define SUB_6_4 2
-#define SUB_6_5 1
-#define SUB_6_6 0
-#define SUB_5_0 5
-#define SUB_5_1 4
-#define SUB_5_2 3
-#define SUB_5_3 2
-#define SUB_5_4 1
-#define SUB_5_5 0
-#define SUB_4_0 4
-#define SUB_4_1 3
-#define SUB_4_2 2
-#define SUB_4_3 1
-#define SUB_4_4 0
-#define SUB_3_0 3
-#define SUB_3_1 2
-#define SUB_3_2 1
-#define SUB_3_3 0
-#define SUB_2_0 2
-#define SUB_2_1 1
-#define SUB_2_2 0
-#define SUB_1_0 1
-#define SUB_1_1 0
-
-/* rounding operator */
-#define ROUNDBY(x, n) ((x) & ~((n)-1))
-
-/* loop unrolling (vertical) */
-#define LOOP1(I,STMT,...) STMT(I,__VA_ARGS__)
-#define LOOP2(I,STMT,...) STMT(I,__VA_ARGS__) LOOP1(INC(I),STMT,__VA_ARGS__)
-#define LOOP3(I,STMT,...) STMT(I,__VA_ARGS__) LOOP2(INC(I),STMT,__VA_ARGS__)
-#define LOOP4(I,STMT,...) STMT(I,__VA_ARGS__) LOOP3(INC(I),STMT,__VA_ARGS__)
-#define LOOP5(I,STMT,...) STMT(I,__VA_ARGS__) LOOP4(INC(I),STMT,__VA_ARGS__)
-#define LOOP6(I,STMT,...) STMT(I,__VA_ARGS__) LOOP5(INC(I),STMT,__VA_ARGS__)
-#define LOOP7(I,STMT,...) STMT(I,__VA_ARGS__) LOOP6(INC(I),STMT,__VA_ARGS__)
-#define LOOP8(I,STMT,...) STMT(I,__VA_ARGS__) LOOP7(INC(I),STMT,__VA_ARGS__)
-#define LOOP9(I,STMT,...) STMT(I,__VA_ARGS__) LOOP8(INC(I),STMT,__VA_ARGS__)
-#define LOOP10(I,STMT,...) STMT(I,__VA_ARGS__) LOOP9(INC(I),STMT,__VA_ARGS__)
-#define LOOP11(I,STMT,...) STMT(I,__VA_ARGS__) LOOP10(INC(I),STMT,__VA_ARGS__)
-#define LOOP12(I,STMT,...) STMT(I,__VA_ARGS__) LOOP11(INC(I),STMT,__VA_ARGS__)
-#define LOOP13(I,STMT,...) STMT(I,__VA_ARGS__) LOOP12(INC(I),STMT,__VA_ARGS__)
-#define LOOP14(I,STMT,...) STMT(I,__VA_ARGS__) LOOP13(INC(I),STMT,__VA_ARGS__)
-#define LOOP15(I,STMT,...) STMT(I,__VA_ARGS__) LOOP14(INC(I),STMT,__VA_ARGS__)
-#define LOOP16(I,STMT,...) STMT(I,__VA_ARGS__) LOOP15(INC(I),STMT,__VA_ARGS__)
-
-#define _LOOP_(n,I,STMT,...) LOOP##n(I,STMT,__VA_ARGS__)
-#define LOOP(n,I,STMT,...) _LOOP_(n,I,STMT,__VA_ARGS__)
-
-/* loop expansion (horizontal) */
-#define EXPAND0(I,TERM,OP,...)
-#define EXPAND1(I,TERM,OP,...) TERM(I,__VA_ARGS__)
-#define EXPAND2(I,TERM,OP,...) TERM(I,__VA_ARGS__) OP EXPAND1(INC(I),TERM,OP,__VA_ARGS__)
-#define EXPAND3(I,TERM,OP,...) TERM(I,__VA_ARGS__) OP EXPAND2(INC(I),TERM,OP,__VA_ARGS__)
-#define EXPAND4(I,TERM,OP,...) TERM(I,__VA_ARGS__) OP EXPAND3(INC(I),TERM,OP,__VA_ARGS__)
-#define EXPAND5(I,TERM,OP,...) TERM(I,__VA_ARGS__) OP EXPAND4(INC(I),TERM,OP,__VA_ARGS__)
-#define EXPAND6(I,TERM,OP,...) TERM(I,__VA_ARGS__) OP EXPAND5(INC(I),TERM,OP,__VA_ARGS__)
-#define EXPAND7(I,TERM,OP,...) TERM(I,__VA_ARGS__) OP EXPAND6(INC(I),TERM,OP,__VA_ARGS__)
-#define EXPAND8(I,TERM,OP,...) TERM(I,__VA_ARGS__) OP EXPAND7(INC(I),TERM,OP,__VA_ARGS__)
-
-#define _EXPAND_(n,I,TERM,OP,...) EXPAND##n(I,TERM,OP,__VA_ARGS__)
-#define EXPAND(n,I,TERM,OP,...) _EXPAND_(n,I,TERM,OP,__VA_ARGS__)
-#define EXPAND_TRI1(n,I,TERM,OP,...) EXPAND(n,I,TERM,OP,__VA_ARGS__)
-#define EXPAND_TRI(n,I,TERM,OP,...) EXPAND_TRI1(SUB(n,I),I,TERM,OP,__VA_ARGS__)
diff --git a/sys/libmath/matrix.c b/sys/libmath/matrix.c
deleted file mode 100644
index e8bca0b..0000000
--- a/sys/libmath/matrix.c
+++ /dev/null
@@ -1,176 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <libmath.h>
-
-/* TODO: replace (incrementally) with native C version! */
-#include <vendor/blas/cblas.h>
-#include <vendor/blas/lapacke.h>
-
-// -----------------------------------------------------------------------
-// level 1
-
-error
-la·vecslice(math·Vector *x, int min, int max, int inc)
-{
- if (max > x->len || min < 0) {
- errorf("out of bounds: attempted to access vector past length");
- return 1;
- }
- x->len = (max - min) / inc;
- x->d += x->inc * min;
- x->inc *= inc;
-
- return 0;
-}
-
-/* simple blas wrappers */
-void
-la·veccopy(math·Vector *dst, math·Vector *src)
-{
- return cblas_dcopy(src->len, src->d, src->inc, dst->d, dst->inc);
-}
-
-double
-la·vecnorm(math·Vector *x)
-{
- return cblas_dnrm2(x->len, x->d, x->inc);
-}
-
-void
-la·vecscale(math·Vector *x, double a)
-{
- return cblas_dscal(x->len, a, x->d, x->inc);
-}
-
-double
-la·vecdot(math·Vector *x, math·Vector *y)
-{
- return cblas_ddot(x->len, x->d, x->inc, y->d, y->inc);
-}
-
-// -----------------------------------------------------------------------
-// level 2
-
-error
-la·vecmat(math·Vector *x, math·Matrix *M)
-{
- if (M->dim[1] != x->len) {
- errorf("incompatible matrix dimensions");
- return 1;
- }
- if (M->state & ~mat·trans)
- cblas_dgemv(CblasRowMajor,CblasNoTrans,M->dim[0],M->dim[1],1.,M->d,M->inc,x->d,x->inc,0.,x->d,x->inc);
- else
- cblas_dgemv(CblasRowMajor,CblasTrans,M->dim[0],M->dim[1],1.,M->d,M->inc,x->d,x->inc,0.,x->d,x->inc);
-
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// level 3
-
-void
-la·transpose(math·Matrix *X)
-{
- int tmp;
- X->state ^= mat·trans;
- tmp = X->dim[0], X->dim[0] = X->dim[1], X->dim[1] = tmp;
-}
-
-error
-la·matrow(math·Matrix *X, int r, math·Vector *row)
-{
- if (r < 0 || r >= X->dim[0]) {
- errorf("out of bounds");
- return 1;
- }
-
- row->len = X->dim[1];
- row->inc = 1;
- row->d = X->d + X->dim[1] * r;
-
- return 0;
-}
-
-error
-la·matcol(math·Matrix *X, int c, math·Vector *col)
-{
- if (c < 0 || c >= X->dim[1]) {
- errorf("out of bounds");
- return 1;
- }
-
- col->len = X->dim[0];
- col->inc = X->dim[1];
- col->d = X->d + c;
-
- return 0;
-}
-
-error
-la·matslice(math·Matrix *X, int r[3], int c[3])
-{
- /* TODO */
- return 0;
-}
-
-error
-la·eig(math·Matrix *X)
-{
-
-}
-
-/* X = A*B */
-error
-la·matmul(math·Matrix *X, math·Matrix *A, math·Matrix *B)
-{
- if (A->dim[1] != B->dim[0]) {
- errorf("number of interior dimensions of A '%d' not equal to that of B '%d'", A->dim[1], B->dim[0]);
- return 1;
- }
- if (X->dim[0] != A->dim[0]) {
- errorf("number of exterior dimensions of X '%d' not equal to that of A '%d'", X->dim[0], A->dim[0]);
- return 1;
- }
- if (X->dim[1] != B->dim[1]) {
- errorf("number of exterior dimensions of X '%d' not equal to that of B '%d'", X->dim[1], B->dim[1]);
- return 1;
- }
-
- if (X->state & ~mat·trans)
- if (A->state & ~mat·trans)
- cblas_dgemm(CblasRowMajor,CblasNoTrans,CblasNoTrans,A->dim[0],B->dim[1],A->dim[1],1.,A->d,A->inc,B->d,B->inc,0.,X->d,X->inc);
- else
- cblas_dgemm(CblasRowMajor,CblasNoTrans,CblasTrans,A->dim[0],B->dim[1],A->dim[1],1.,A->d,A->inc,B->d,B->inc,0.,X->d,X->inc);
- else
- if (A->state & ~mat·trans)
- cblas_dgemm(CblasRowMajor,CblasTrans,CblasNoTrans,A->dim[0],B->dim[1],A->dim[1],1.,A->d,A->inc,B->d,B->inc,0.,X->d,X->inc);
- else
- cblas_dgemm(CblasRowMajor,CblasTrans,CblasTrans,A->dim[0],B->dim[1],A->dim[1],1.,A->d,A->inc,B->d,B->inc,0.,X->d,X->inc);
-
- return 0;
-}
-
-/*
- * solves A*X=B
- * pass in B via X
- */
-error
-la·solve(math·Matrix *X, math·Matrix *A)
-{
- error err;
- int n, *ipv;
- static int buf[512];
- if (n = A->dim[0], n < arrlen(buf)) {
- ipv = buf;
- n = 0;
- } else
- ipv = malloc(n*sizeof(*ipv));
-
- /* TODO: utilize more specific regimes if applicable */
- err = LAPACKE_dgesv(LAPACK_ROW_MAJOR,A->dim[0],X->dim[1],A->d,A->inc,ipv,X->d,X->inc);
-
- if (n)
- free(ipv);
- return err;
-}
diff --git a/sys/libmath/rules.mk b/sys/libmath/rules.mk
deleted file mode 100644
index 83945d7..0000000
--- a/sys/libmath/rules.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-include share/push.mk
-
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := \
- $(d)/basic.c \
- $(d)/blas1.c \
- $(d)/blas2.c \
- $(d)/blas3.c
-LIBS_$(d) := $(d)/libmath.a
-TSTS_$(d) :=
-
-include share/paths.mk
-
-$(LIBS_$(d)): $(OBJS_$(d))
- $(ARCHIVE)
-
-$(UNTS_$(d)): TCFLAGS := -D_GNU_SOURCE
-$(UNTS_$(d)): TCLIBS := -lpthread -lm $(LIB_DIR)/libblas.a $(OBJ_DIR)/sys/libn/libn.a $(LIBS_$(d))
-$(UNTS_$(d)): $(TOBJS_$(d)) $(LIBS_$(d)) $(OBJ_DIR)/sys/libn/libn.a
- $(LINK)
-
-include share/pop.mk
diff --git a/sys/libmath/test.c b/sys/libmath/test.c
deleted file mode 100644
index 66700f8..0000000
--- a/sys/libmath/test.c
+++ /dev/null
@@ -1,471 +0,0 @@
-#include <u.h>
-#include <base.h>
-/* #include <vendor/blas/cblas.h> */
-
-#include <x86intrin.h>
-
-#include <time.h>
-
-// -----------------------------------------------------------------------
-// Vectors
-
-/*
- * NOTE: I'm not sure I like stashing the header in _all_ vectors
- * The only way to fix is to have a library based allocator...
- */
-typedef struct math·Vec
-{
- struct {
- void *h;
- mem·Allocator heap;
- };
- int len;
- double *d;
-} math·Vec;
-
-math·Vec
-math·makevec(int len, mem·Allocator heap, void *h)
-{
- math·Vec v;
- v.len = len;
- v.heap = heap;
- v.h = h;
- v.d = heap.alloc(h, 1, len*sizeof(double));
-
- // memset(v.d, 0, len*sizeof(double));
-
- return v;
-}
-
-error
-math·freevec(math·Vec *v)
-{
- if (v->h == nil && v->heap.alloc == nil && v->heap.free == nil) {
- errorf("attempting to free a vector that doesn't own its data");
- return 1;
- }
- v->heap.free(v->h, v->d);
- v->d = nil;
- v->len = 0;
-
- return 0;
-}
-
-math·Vec
-math·copyvec(math·Vec v)
-{
- math·Vec cpy;
- cpy.heap = v.heap;
- cpy.h = v.h;
- cpy.len = v.len;
- cpy.d = cpy.heap.alloc(cpy.h, 1, v.len);
-
- memcpy(cpy.d, v.d, sizeof(double)*v.len);
- return cpy;
-}
-
-/*
- * Scale vector
- */
-
-static
-void
-scale_kernel8_avx2(int n, double *x, double a)
-{
- __m128d a128;
- __m256d a256;
- register int i;
-
- a128 = _mm_load_sd(&a);
- a256 = _mm256_broadcastsd_pd(a128);
- for (i = 0; i < n; i += 8) {
- _mm256_storeu_pd(x+i+0, a256 * _mm256_loadu_pd(x+i+0));
- _mm256_storeu_pd(x+i+4, a256 * _mm256_loadu_pd(x+i+4));
- }
-}
-
-static
-void
-scale_kernel8(int n, double *x, double a)
-{
- register int i;
- for (i = 0; i < n; i += 8) {
- x[i+0] *= a;
- x[i+1] *= a;
- x[i+2] *= a;
- x[i+3] *= a;
- x[i+4] *= a;
- x[i+5] *= a;
- x[i+6] *= a;
- x[i+7] *= a;
- }
-}
-
-void
-math·scalevec(math·Vec u, double a)
-{
- int n;
-
- n = u.len & ~7;
- scale_kernel8_avx2(n, u.d, a);
-
- for (; n < u.len; n++) {
- u.d[n] *= a;
- }
-}
-
-/*
- * Add scaled vector
- */
-
-static
-void
-daxpy_kernel8_avx2(int n, double *x, double *y, double a)
-{
- __m128d a128;
- __m256d a256;
- register int i;
-
- a128 = _mm_load_sd(&a);
- a256 = _mm256_broadcastsd_pd(a128);
- for (i = 0; i < n; i += 8) {
- _mm256_storeu_pd(x+i+0, _mm256_loadu_pd(x+i+0) + a256 * _mm256_loadu_pd(y+i+0));
- _mm256_storeu_pd(x+i+4, _mm256_loadu_pd(x+i+4) + a256 * _mm256_loadu_pd(y+i+4));
- }
-}
-
-static
-void
-daxpy_kernel8(int n, double *x, double *y, double a)
-{
- register int i;
- for (i = 0; i < n; i += 8) {
- x[i+0] += a*y[i+0];
- x[i+1] += a*y[i+1];
- x[i+2] += a*y[i+2];
- x[i+3] += a*y[i+3];
- x[i+4] += a*y[i+4];
- x[i+5] += a*y[i+5];
- x[i+6] += a*y[i+6];
- x[i+7] += a*y[i+7];
- }
-}
-
-/* performs u = u + a*v */
-void
-math·addvec(math·Vec u, math·Vec v, double a)
-{
- int n;
-
- n = u.len & ~7;
- daxpy_kernel8_avx2(n, u.d, v.d, a);
-
- for (; n < u.len; n++) {
- u.d[n] += a*v.d[n];
- }
-}
-
-/*
- * Dot product
- */
-
-static
-double
-dot_kernel8_avx2(int len, double *x, double *y)
-{
- register int i;
- __m256d sum[4];
- __m128d res;
-
- for (i = 0; i < arrlen(sum); i++) {
- sum[i] = _mm256_setzero_pd();
- }
-
- for (i = 0; i < len; i += 16) {
- sum[0] += _mm256_loadu_pd(x+i+0) * _mm256_loadu_pd(y+i+0);
- sum[1] += _mm256_loadu_pd(x+i+4) * _mm256_loadu_pd(y+i+4);
- sum[2] += _mm256_loadu_pd(x+i+8) * _mm256_loadu_pd(y+i+8);
- sum[3] += _mm256_loadu_pd(x+i+12) * _mm256_loadu_pd(y+i+12);
- }
-
- sum[0] += sum[1] + sum[2] + sum[3];
-
- res = _mm_add_pd(_mm256_extractf128_pd(sum[0], 0), _mm256_extractf128_pd(sum[0], 1));
- res = _mm_hadd_pd(res, res);
-
- return res[0];
-}
-
-static
-double
-dot_kernel8_fma3(int len, double *x, double *y)
-{
- register int i;
- __m256d sum[4];
- __m128d res;
-
- for (i = 0; i < arrlen(sum); i++) {
- sum[i] = _mm256_setzero_pd();
- }
-
- for (i = 0; i < len; i += 16) {
- sum[0] = _mm256_fmadd_pd(_mm256_loadu_pd(x+i+0), _mm256_loadu_pd(y+i+0), sum[0]);
- sum[1] = _mm256_fmadd_pd(_mm256_loadu_pd(x+i+4), _mm256_loadu_pd(y+i+4), sum[1]);
- sum[2] = _mm256_fmadd_pd(_mm256_loadu_pd(x+i+8), _mm256_loadu_pd(y+i+8), sum[2]);
- sum[3] = _mm256_fmadd_pd(_mm256_loadu_pd(x+i+12), _mm256_loadu_pd(y+i+12), sum[3]);
- }
-
- sum[0] += sum[1] + sum[2] + sum[3];
-
- res = _mm_add_pd(_mm256_extractf128_pd(sum[0], 0), _mm256_extractf128_pd(sum[0], 1));
- res = _mm_hadd_pd(res, res);
-
- return res[0];
-}
-
-static
-double
-dot_kernel8(int len, double *x, double *y)
-{
- double res;
- register int i;
-
- for (i = 0; i < len; i += 8) {
- res += x[i] * y[i] +
- x[i+1] * y[i+1] +
- x[i+2] * y[i+2] +
- x[i+3] * y[i+3] +
- x[i+4] * y[i+4] +
- x[i+5] * y[i+5] +
- x[i+6] * y[i+6] +
- x[i+7] * y[i+7];
- }
-
- return res;
-}
-
-double
-math·dot(math·Vec u, math·Vec v)
-{
- int i, len;
- double res;
-
- len = u.len & ~15; // neat trick
- res = dot_kernel8_fma3(len, u.d, v.d);
-
- for (i = len; i < u.len; i++) {
- res += u.d[i] * v.d[i];
- }
-
- return res;
-}
-
-// -----------------------------------------------------------------------
-// Matrix
-
-typedef struct math·Mtx
-{
- struct {
- void *h;
- mem·Allocator heap;
- };
- int dim[2];
- double *d;
-} math·Mtx;
-
-math·Mtx
-math·makemtx(int n, int m, mem·Allocator heap, void *h)
-{
- math·Mtx a;
- a.dim[0] = n;
- a.dim[1] = m;
- a.heap = heap;
- a.h = h;
- a.d = heap.alloc(h, 1, n*m*sizeof(double));
-
- // memset(a.d, 0, n*m*sizeof(double));
-
- return a;
-}
-
-error
-math·freemtx(math·Vec *m)
-{
- if (m->h == nil && m->heap.alloc == nil && m->heap.free == nil) {
- errorf("attempting to free a matrix that doesn't own its data");
- return 1;
- }
- m->heap.free(m->h, m->d);
- m->d = nil;
- m->len = 0;
-
- return 0;
-}
-
-/************************************************
- * multiply matrix to vector
- ***********************************************/
-
-/*
- * Notation: (number of rows) x (number of columns) _ unroll factor
- * N => variable we sum over
- */
-static
-void
-mtxvec_kernel4xN_4_avx2(int ncol, double **row, double *x, double *y)
-{
- int c;
- __m128d hr;
- __m256d x256, r256[4];
-
- for (c = 0; c < 4; c++) {
- r256[c] = _mm256_setzero_pd();
- }
-
- for (c = 0; c < ncol; c += 4) {
- x256 = _mm256_loadu_pd(x+c);
- r256[0] += x256 * _mm256_loadu_pd(row[0] + c);
- r256[1] += x256 * _mm256_loadu_pd(row[1] + c);
- r256[2] += x256 * _mm256_loadu_pd(row[2] + c);
- r256[3] += x256 * _mm256_loadu_pd(row[3] + c);
- }
-
- for (c = 0; c < 4; c++) {
- hr = _mm_add_pd(_mm256_extractf128_pd(r256[c], 0), _mm256_extractf128_pd(r256[c], 1));
- hr = _mm_hadd_pd(hr, hr);
- y[c] = hr[0];
- }
-}
-
-static
-void
-mtxvec_kernel4xN_4(int ncol, double **row, double *x, double *y)
-{
- int c;
- double res[4];
-
- res[0] = 0.;
- res[1] = 0.;
- res[2] = 0.;
- res[3] = 0.;
-
- for (c = 0; c < ncol; c += 4) {
- res[0] += row[0][c+0]*x[c+0] + row[0][c+1]*x[c+1] + row[0][c+2]*x[c+2] + row[0][c+3]*x[c+3];
- res[1] += row[1][c+0]*x[c+0] + row[1][c+1]*x[c+1] + row[1][c+2]*x[c+2] + row[1][c+3]*x[c+3];
- res[2] += row[2][c+0]*x[c+0] + row[2][c+1]*x[c+1] + row[2][c+2]*x[c+2] + row[2][c+3]*x[c+3];
- res[3] += row[3][c+0]*x[c+0] + row[3][c+1]*x[c+1] + row[3][c+2]*x[c+2] + row[3][c+3]*x[c+3];
- }
-
- y[0] = res[0];
- y[1] = res[1];
- y[2] = res[2];
- y[3] = res[3];
-}
-
-static
-void
-mtxvec_kernel1xN_4(int ncol, double *row, double *x, double *y)
-{
- int c;
- double res;
-
- res = 0.;
- for (c = 0; c < ncol; c += 4) {
- res += row[c+0]*x[c+0] + row[c+1]*x[c+1] + row[c+2]*x[c+2] + row[c+3]*x[c+3];
- }
-
- y[0] = res;
-}
-
-// y = a*mx + b*y
-error
-math·mtxvec(math·Mtx m, double a, math·Vec x, double b, math·Vec y)
-{
- int c, r, nrow, ncol;
- double *row[4], res[4];
-
- nrow = m.dim[0] & ~3;
- ncol = m.dim[1] & ~3;
- for (r = 0; r < nrow; r += 4) {
- row[0] = m.d + (r * (m.dim[1]+0));
- row[1] = m.d + (r * (m.dim[1]+1));
- row[2] = m.d + (r * (m.dim[1]+2));
- row[3] = m.d + (r * (m.dim[1]+3));
-
- mtxvec_kernel4xN_4_avx2(ncol, row, x.d + r, res);
-
- for (c = ncol; c < m.dim[1]; c++) {
- res[0] += row[0][c];
- res[1] += row[1][c];
- res[2] += row[2][c];
- res[3] += row[3][c];
- }
-
- y.d[r+0] = res[0] + b*y.d[r+0];
- y.d[r+1] = res[1] + b*y.d[r+1];
- y.d[r+2] = res[2] + b*y.d[r+2];
- y.d[r+3] = res[3] + b*y.d[r+3];
- }
-
- for (; r < m.dim[0]; r++) {
- mtxvec_kernel1xN_4(m.dim[0], m.d + (r * m.dim[1]), x.d + r, res);
- y.d[r] = res[0] + b*y.d[r];
- }
-
- return 0;
-}
-
-/************************************************
- * add matrix to vector outerproduct
- ***********************************************/
-
-#define NITER 50
-
-#if 0
-error
-main()
-{
- int i;
- clock_t t;
- double res;
-
- math·Mtx m;
- math·Vec x, y;
-
- openblas_set_num_threads(1);
-
- x = math·makevec(1000, mem·sys, nil);
- y = math·makevec(1000, mem·sys, nil);
- m = math·makemtx(1000, 1000, mem·sys, nil);
-
- for (i = 0; i < x.len; i++) {
- y.d[i] = i;
- }
-
- t = clock();
- for (i = 0; i < NITER; i++) {
- cblas_dgemv(CblasRowMajor, CblasNoTrans, m.dim[0], m.dim[1], 1.5, m.d, m.dim[1], x.d, 1, 2.5, y.d, 1);
- }
- t = clock() - t;
- res = math·dot(y, y);
- printf("the result is %f\n", res);
- printf("time elapsed (blas): %fms\n", 1000.*t/CLOCKS_PER_SEC);
-
- for (i = 0; i < x.len; i++) {
- y.d[i] = i;
- }
-
- t = clock();
- for (i = 0; i < NITER; i++) {
- math·mtxvec(m, 1.5, x, 2.5, y);
- }
- t = clock() - t;
- res = math·dot(y, y);
-
- printf("the dot product is %f\n", res);
- printf("time elapsed (naive): %fms\n", 1000.*t/CLOCKS_PER_SEC);
-
-
- return 0;
-}
-#endif
diff --git a/sys/libsre/lex.c b/sys/libsre/lex.c
deleted file mode 100644
index f4c6ac2..0000000
--- a/sys/libsre/lex.c
+++ /dev/null
@@ -1,246 +0,0 @@
-#include "sre.h"
-
-static
-State *
-state(Machine *m, int t)
-{
- if (m->state >= m->statestk + arrlen(m->statestk))
- panicf("regexp vm: out of state space");
-
- m->state->type = t;
- m->state->l = nil;
- m->state->r = nil;
-
- return m->state++;
-}
-
-static
-int
-poptor(Parser *p)
-{
- if (p->optor <= p->optorstk)
- panicf("regexp parser: opand stack underflow");
-
- return *--p->optor;
-}
-
-static
-void
-pushtor(Parser *p, int t)
-{
- if (p->optor >= arrend(p->optorstk))
- panicf("regexp parser: opand stack overflow");
-
- *p->optor++ = t;
-}
-
-static
-void
-pushand(Parser *p, State *beg, State *end)
-{
- if (p->node >= arrend(p->nodestk))
- panicf("regexp parser: opand stack overflow");
-
- p->node->beg = beg;
- p->node->end = end;
-
- p->node++;
-}
-
-static
-Node *
-popand(Parser *p)
-{
- if (p->node <= p->nodestk)
- panicf("regexp parser: opand stack underflow");
-
- return --p->node;
-}
-
-static
-void
-operateuntil(Parser *p, int prec)
-{
- Node *o1, *o2, *t;
- State *s1, *s2;
-
- while (prec == Trparen || p->optor[-1] >= prec) {
- switch (poptor(p)) {
- case Tor:
- o1 = popand(p);
- o2 = popand(p);
-
- s1 = state(p->mach, Tor);
- s2 = state(p->mach, Tnop);
- s1->l = o1->beg;
- s1->r = o2->beg;
-
- o1->end->out = s2;
- o2->end->out = s2;
-
- pushand(p, s1, s2);
- break;
-
- case Tcat:
- o1 = popand(p);
- o2 = popand(p);
-
- o1->end->out = o2->beg;
- pushand(p, o1->beg, o2->end);
- break;
-
- case Tstar:
- o1 = popand(p);
- s1 = state(p->mach, Tor);
- o1->end->out = s1;
- s1->l = o1->beg;
- pushand(p, s1, s1);
- break;
-
- case Tplus:
- o1 = popand(p);
- s1 = state(p->mach, Tor);
- o1->end->out = s1;
- s1->l = o1->beg;
- pushand(p, o1->beg, s1);
- break;
-
- case Tqmark:
- o1 = popand(p);
- s1 = state(p->mach, Tor);
- s2 = state(p->mach, Tnop);
- s1->l = o1->beg;
- s1->r = s2;
- o1->end->out = s2;
- pushand(p, s1, s2);
- break;
-
- default:
- panicf("unsupported regexp operator");
- }
- }
-}
-
-static
-void
-operator(Parser *p, int t)
-{
- operateuntil(p, t);
- pushtor(p, t);
- p->wasopand = (t != Tstar && t != Tqmark && t != Tplus && t != Trparen);
-}
-
-static
-void
-operand(Parser *p, int t)
-{
- State *new;
- if (p->wasopand)
- operator(p, Tcat);
-
- new = state(p->mach, t);
- pushand(p, new, new);
- p->wasopand = true;
-}
-
-#define cinc 20
-int
-lex(Parser *p)
-{
- int c, t;
- byte *class;
- long n, cap;
-
- c = *p->re++;
- switch (c) {
- case '\\':
- if (*p->re)
- if ((c = *p->re++) == '\n')
- c = '\n';
- break;
- case '\0':
- c = Tend,
- --p->re;
- break;
- case '*':
- c = Tstar;
- break;
- case '?':
- c = Tqmark;
- break;
- case '+':
- c = Tplus;
- break;
- case '|':
- c = Tor;
- break;
- case '.':
- c = Tany;
- break;
- case '(':
- c = Tlparen;
- break;
- case ')':
- c = Trparen;
- break;
- case '^':
- c = Tbol;
- break;
- case '$':
- c = Teol;
- break;
- case '[':
- goto charclass;
- default:
- ;
- }
- return c;
-
-charclass:
- panicf("to implement");
-}
-
-#undef cinc
-
-static
-State*
-optimize(State *entry)
-{
- State *curr, *next;
- for (curr=entry; curr->type != Tend; curr++) {
- next = curr->out;
- while (next->type == Tnop)
- next = next->out;
- curr->out = next;
- }
-
- return entry;
-}
-
-void
-sre·compile(Machine *mach, byte *regexp)
-{
- int tok;
- Parser p;
- Node *prog;
-
- p = (Parser) {
- .re = regexp,
- .mach = mach,
- .node = p.nodestk,
- };
-
- pushtor(&p, Tstart - 1);
- while ((tok = lex(&p)) != Tend) {
- if ((tok & isoptor) == Toperator)
- operator(&p, tok);
- else
- operand(&p, tok);
- }
- operateuntil(&p, Tstart);
- operand(&p, Tend);
- operateuntil(&p, Tstart);
-
- prog = popand(&p);
- mach->entry = optimize(prog->beg);
-}
diff --git a/sys/libsre/sre.h b/sys/libsre/sre.h
deleted file mode 100644
index a7ace1a..0000000
--- a/sys/libsre/sre.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <libn.h>
-
-enum
-{
- Toperator = RuneMask + 1,
- Tstart = Toperator,
- Trparen,
- Tlparen,
- Tor,
- Tcat,
- Tstar,
- Tplus,
- Tqmark,
-
- Tany = Toperator << 1,
- Tnop,
- Tbol,
- Teol,
- Tcclass,
- Tnclass,
- Tend,
-
- isoptor = Toperator,
- isopand = Toperator << 1,
-};
-
-typedef struct Class Class;
-typedef struct State State;
-typedef struct Patch Patch;
-typedef struct Node Node;
-
-typedef struct Parser Parser;
-typedef struct Machine Machine;
-
-struct Class
-{
- rune *end;
- rune span[64];
-};
-
-struct State
-{
- int type;
- union {
- State *l;
- };
- union {
- State *r;
- State *out;
- };
-};
-
-struct Patch
-{
- State *s;
- Patch *link;
-};
-
-struct Node
-{
- State *beg;
- State *end;
-};
-
-struct Parser
-{
- Machine *mach;
- byte *re;
- int wasopand : 1;
- int *optor, optorstk[1000];
- Node *node, nodestk[1000];
-};
-
-struct Machine
-{
- /* memory buffers */
- struct {
- void *heap;
- mem·Reallocator;
- };
- State *state, statestk[1000];
-
- struct {
- int cap;
- int len;
- Class *c;
- } class;
-
- State *entry;
-};
diff --git a/sys/libterm/term.c b/sys/libterm/term.c
deleted file mode 100644
index 11591fc..0000000
--- a/sys/libterm/term.c
+++ /dev/null
@@ -1,489 +0,0 @@
-#include "term.h"
-
-#include <signal.h>
-#include <sys/ioctl.h>
-
-struct ExtraInfo
-{
- char *enteralt;
- char *exitalt;
-
- char *entermouse;
- char *exitmouse;
-};
-
-static
-struct ExtraInfo vt200 =
-{
- .enteralt = "\e[?1049h",
- .exitalt = "\e[?1049l",
-
- .entermouse = "\e[?1049h\e[?1006l",
- .exitmouse = "\e[?1002l\e[?1006l",
-};
-
-static Term *sigwinchhead;
-
-// -----------------------------------------------------------------------
-// database lookup
-
-static
-char*
-tryinfostr(Term *t, enum unibi_string s)
-{
- char *val = (char*)unibi_get_str(t->info, s);
- /* TODO: provide fallbacks */
- return val;
-}
-
-static
-char*
-guessinfostr(Term *t, enum unibi_string s, char *guess)
-{
- char *val = (char*)unibi_get_str(t->info, s);
- if (!val)
- return guess;
- return val;
-}
-
-static
-char*
-getinfostr(Term *t, enum unibi_string s)
-{
- char *val = tryinfostr(t, s);
- if (!val)
- panicf("required term info string '%s' missing", unibi_name_str(s));
-
- return val;
-}
-
-static
-char *
-tryextrastr(Term *t, char *name)
-{
- const char *nm;
- size_t max = unibi_count_ext_str(t->info);
- for (size_t i = 0; i < max; i++) {
- nm = unibi_get_ext_str_name(t->info, i);
- if (nm && !strcmp(nm, name)) {
- return (char *)nm;
- }
- }
- return nil;
-}
-
-static
-char *
-guessextrastr(Term *t, char *name, char *guess)
-{
- char *s;
- if ((s = tryextrastr(t, name)))
- return s;
-
- return guess;
-}
-
-/* formats escape strings and writes to output */
-static void tfmt(Term *t, char *esc, int n, ...);
-static void tclear(Term *t);
-
-// -----------------------------------------------------------------------
-// exported term methods
-
-static
-char *
-ttmpbuf(Term *t, int len)
-{
- if (t->tmp.len >= len)
- return t->tmp.b;
-
- /* TODO: error handling */
- return (t->tmp.b = realloc(t->tmp.b, len));
-}
-
-void twrite(Term *t, long len, char *s);
-void tlistensigwinch(Term *t);
-
-Term*
-tmake(void)
-{
- Term *t;
-
- t = calloc(1, sizeof(*t));
-
- /* meta data */
- t->name = getenv("TERM");
- t->info = unibi_from_term(t->name);
- if (!t->info)
- panicf("could not identify terminal");
-
- t->fd = 1; // stdout
- tlistensigwinch(t);
-
- t->mode.mouse = 0;
- t->mode.cursorvis = 1;
- t->mode.altscreen = 0;
-
- t->cap.colors = unibi_get_num(t->info, unibi_max_colors);
- t->cap.bce = unibi_get_bool(t->info, unibi_back_color_erase);
-
- /* initialize root window (get current size)*/
- struct winsize ws = { 0 };
- if (ioctl(t->fd, TIOCGWINSZ, &ws) == 1)
- goto bad;
-
- t->root = wmake(nil, 0, 0, ws.ws_col, ws.ws_row, 0);
-
- t->root->curvis = 1;
- t->root->blink = 0;
-
- t->pen = (Pen){
- .state = PenNormal,
- .col = {.fg = -1, .bg = -1},
- };
-
- /* fill in output buffers */
- t->buf.c = t->buf.b;
- t->tmp.b = nil;
- t->tmp.len = 0;
-
- /* get all term info format strings */
- t->esc.cup = getinfostr(t, unibi_cursor_address);
- t->esc.vpa = tryinfostr(t, unibi_row_address);
- t->esc.hpa = tryinfostr(t, unibi_column_address);
- t->esc.cuu = getinfostr(t, unibi_parm_up_cursor);
- t->esc.cuu1 = tryinfostr(t, unibi_cursor_up);
- t->esc.cud = getinfostr(t, unibi_parm_down_cursor);
- t->esc.cud1 = tryinfostr(t, unibi_cursor_down);
- t->esc.cuf = getinfostr(t, unibi_parm_right_cursor);
- t->esc.cuf1 = tryinfostr(t, unibi_cursor_right);
- t->esc.cub = getinfostr(t, unibi_parm_left_cursor);
- t->esc.cub1 = tryinfostr(t, unibi_cursor_left);
- t->esc.ich = getinfostr(t, unibi_parm_ich);
- t->esc.ich1 = tryinfostr(t, unibi_insert_character);
- t->esc.dch = getinfostr(t, unibi_parm_dch);
- t->esc.dch1 = tryinfostr(t, unibi_delete_character);
- t->esc.il = getinfostr(t, unibi_parm_insert_line);
- t->esc.il1 = tryinfostr(t, unibi_insert_line);
- t->esc.dl = getinfostr(t, unibi_parm_delete_line);
- t->esc.dl1 = tryinfostr(t, unibi_delete_line);
- t->esc.ech = getinfostr(t, unibi_erase_chars);
- t->esc.ed2 = getinfostr(t, unibi_clear_screen);
- t->esc.stbm = getinfostr(t, unibi_change_scroll_region);
- t->esc.sgr = getinfostr(t, unibi_set_attributes);
- t->esc.sgr0 = getinfostr(t, unibi_exit_attribute_mode);
- t->esc.sgr_i0 = tryinfostr(t, unibi_exit_italics_mode);
- t->esc.sgr_i1 = tryinfostr(t, unibi_enter_italics_mode);
- t->esc.sgr_fg = getinfostr(t, unibi_set_a_foreground);
- t->esc.sgr_bg = getinfostr(t, unibi_set_a_background);
- t->esc.sm_csr = getinfostr(t, unibi_cursor_normal);
- t->esc.rm_csr = getinfostr(t, unibi_cursor_invisible);
-
- /* extensions to terminfo */
- t->esc.ext.rgbf = guessextrastr(t, "setrgbf", "\x1b[38;2;%p1%d;%p2%d;%p3%dm");
- t->esc.ext.rgbb = guessextrastr(t, "setrgbb", "\x1b[48;2;%p1%d;%p2%d;%p3%dm");
-
- return t;
-
-bad:
- panicf("failed to initialize terminal instance");
- free(t);
- return nil;
-}
-
-void
-tfree(Term *t)
-{
- if (t->mode.mouse)
- twrite(t, 0, vt200.exitmouse);
- if (!t->mode.cursorvis)
- tfmt(t, t->esc.rm_csr, 0);
- if (t->mode.altscreen)
- twrite(t, 0, vt200.exitalt);
-
- tfmt(t, t->esc.sgr0, 0);
- tclear(t);
- free(t);
-}
-
-/* handle resize events */
-void
-tresize(Term *t)
-{
- if (t->fd == -1)
- return;
-
- struct winsize ws = { 0 };
- if (ioctl(t->fd, TIOCGWINSZ, &ws) == 1)
- return;
-
- printf("[%d,%d]\n", ws.ws_col, ws.ws_row);
- if (t->root->w != ws.ws_col || t->root->h != ws.ws_row)
- wresize(t->root, ws.ws_col, ws.ws_row);
-}
-
-static
-void
-sigwinch(int num)
-{
- Term *it;
- for (it = sigwinchhead; it; it = it->link)
- tresize(it);
-}
-
-void
-tlistensigwinch(Term *t)
-{
- sigset_t new, old;
- Term *it;
-
- sigemptyset(&new);
- sigaddset(&new, SIGWINCH);
- sigprocmask(SIG_BLOCK, &new, &old);
-
- if (!sigwinchhead) {
- sigaction(SIGWINCH, &(struct sigaction){ .sa_handler = sigwinch }, nil);
- sigwinchhead = t;
- } else {
- it = sigwinchhead;
- while (it->link)
- it = it->link;
- it->link = t;
- }
-
- sigprocmask(SIG_SETMASK, &old, nil);
-}
-
-void
-tflush(Term *t)
-{
- if (t->fd != -1)
- write(t->fd, t->buf.b, t->buf.c - t->buf.b);
-
- t->buf.c = t->buf.b;
-}
-
-void
-twrite(Term *t, long len, char *s)
-{
- int n;
- if (!len)
- len = strlen(s);
-
-loop:
- n = MIN(len, arrend(t->buf.b) - t->buf.c);
- memcpy(t->buf.c, s, n);
- t->buf.c += n;
- len -= n;
- if (len) {
- tflush(t);
- goto loop;
- }
-}
-
-void
-tsetpen(Term *t, Pen new)
-{
- int c;
- ushort ic, in;
- Pen cur = t->pen;
- if (!memcmp(&new, &cur, sizeof(new)))
- return;
-
- /* attributes */
- tfmt(t, t->esc.sgr, 9,
- 0, /* standout */
- new.state & PenUnderline,
- new.state & PenReverse,
- new.state & PenBlink,
- new.state & PenDim,
- new.state & PenBold,
- new.state & PenInvis,
- 0, /* protect */
- 0); /* alt */
-
- ic = cur.state & PenItalic;
- in = new.state & PenItalic;
- if (ic & ~in)
- tfmt(t, t->esc.sgr_i0, 0);
- else if (~ic & in)
- tfmt(t, t->esc.sgr_i1, 0);
-
- /* fg/bg color */
- /* TODO: add a check for if the terminal supports true color */
- /* TODO: deal w/ negative indices properly */
- if (new.state & PenRGB) {
- tfmt(t, t->esc.ext.rgbf, 3, new.rgb.fg.r, new.rgb.fg.g, new.rgb.fg.b);
- tfmt(t, t->esc.ext.rgbb, 3, new.rgb.bg.r, new.rgb.bg.g, new.rgb.bg.b);
- } else {
- tfmt(t, t->esc.sgr_fg, 1, new.col.fg);
- tfmt(t, t->esc.sgr_bg, 1, new.col.bg);
- }
-
- t->pen = new;
-}
-
-static
-void
-tfmt(Term *t, char *esc, int n, ...)
-{
- int i;
- long len;
- va_list args;
- unibi_var_t param[9];
- char buf[64], *c = buf;
-
- if (!esc)
- panicf("no terminfo escape string given");
-
- va_start(args, n);
- for (i = 0; i < arrlen(param) && i < n; i++) {
- param[i] = unibi_var_from_num(va_arg(args, int));
- }
- va_end(args);
-
- len = unibi_run(esc, param, c, sizeof(buf));
- if (len >= arrlen(buf)) {
- c = ttmpbuf(t, len);
- unibi_run(esc, param, c, len);
- }
-
- twrite(t, len, c);
-}
-
-/* absolute move */
-static
-int
-tgoto(Term *t, int row, int col)
-{
- if (row != -1 && col != -1)
- tfmt(t, t->esc.cup, 2, row, col);
- else if (row != -1) {
- if (!t->esc.vpa)
- return 0;
- tfmt(t, t->esc.vpa, 1, row);
- } else if (col != -1) {
- if (col == 0) {
- twrite(t, 1, "\r");
- return 1;
- }
- if (t->esc.hpa)
- tfmt(t, t->esc.hpa, 1, col);
- else if (t->esc.cuf) {
- twrite(t, 1, "\r");
- tfmt(t, t->esc.cuf, 1, col);
- } else
- return 0;
- } else
- return 0; /* unreachable */
-
- return 1;
-}
-
-/* relative move */
-static
-void
-tjump(Term *t, int down, int right)
-{
- if (down == 1 && t->esc.cud1)
- tfmt(t, t->esc.cud1, 0);
- else if (down == -1 && t->esc.cuu1)
- tfmt(t, t->esc.cuu1, 0);
- else if (down > 0)
- tfmt(t, t->esc.cud, 1, down);
- else if (down < 0)
- tfmt(t, t->esc.cuu, 1, -down);
-
- if (right == 1 && t->esc.cuf1)
- tfmt(t, t->esc.cuf1, 0);
- else if (right == -1 && t->esc.cub1)
- tfmt (t, t->esc.cub1, 0);
- else if (right > 0)
- tfmt(t, t->esc.cuf, 1, right);
- else if( right < 0)
- tfmt(t, t->esc.cub, 1, -right);
-}
-
-static
-void
-tclear(Term *t)
-{
- tfmt(t, t->esc.ed2, 0);
-}
-
-void
-tblit(Term *t, Window *win)
-{
- int r, c, n, j;
- Row *row;
- char u[UTFmax+1] = {0};
-
- j = 0;
- tgoto(t, win->top, win->left);
- for (r = 0; r < win->h; r++) {
- row = win->row + r;
- if (!row->dirty) {
- j++;
- continue;
- }
-
- if (j) {
- tjump(t, j, 0);
- j = 0;
- }
-
- for (c = 0; c < win->w; c++) {
- tsetpen(t, row->cells[c].pen);
- n = utf8·runetobyte(u, &row->cells[c].txt);
- twrite(t, n, u);
- }
-
- row->dirty = 0;
- }
-
- tflush(t);
-}
-
-// -----------------------------------------------------------------------
-// testing
-
-int
-main()
-{
- int i;
- Term *t;
- Window *win;
-
- t = tmake();
- win = t->root;
- tclear(t);
-
- win->pen = (Pen){
- .state = PenNormal,
- .col = {.fg=-1, .bg=-1},
- };
- for (i = 0; i < 2000; i++)
- wputrune(win, 'a');
-
- tblit(t, win);
-
- win->cur.row = 10;
- win->cur.col = 0;
-
- win->pen = (Pen){
- .state=PenNormal|PenRGB,
- .rgb={.fg={200, 100, 100}, .bg={0, 0, 0} },
- };
-
- for (i = 0; i < 500; i++)
- wputrune(win, 'b');
-
- tblit(t, win);
-
- sleep(5);
- wscroll(win, 10);
- tblit(t, win);
- sleep(5);
-
- tfree(t);
-}
diff --git a/sys/libterm/term.h b/sys/libterm/term.h
deleted file mode 100644
index 6bd2f6b..0000000
--- a/sys/libterm/term.h
+++ /dev/null
@@ -1,270 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <libn.h>
-
-#include <termios.h>
-#include <unibilium.h>
-
-#define iota(x) 1 << (x)
-
-typedef struct RGB8 RGB8;
-typedef struct Pen Pen;
-
-typedef struct Dot Dot;
-typedef struct Cell Cell;
-typedef struct Row Row;
-typedef struct Buffer Buffer;
-typedef struct Window Window;
-
-typedef struct Node Node;
-typedef struct Key Key;
-typedef struct Input Input;
-
-typedef struct Term Term;
-
-struct RGB8
-{
- uint8 r, g, b;
-};
-
-enum
-{
- PenNormal = 0,
- PenBold = iota(0),
- PenDim = iota(1),
- PenInvis = iota(2),
- PenItalic = iota(3),
- PenReverse = iota(4),
- PenStrike = iota(5),
- PenUnderline = iota(6),
- PenBlink = iota(7),
- /* ... */
- PenRGB = iota(15),
-};
-
-struct Pen
-{
- ushort state;
- union {
- /* 256 color (legacy) */
- struct {
- sshort fg : 8, bg : 8; /* 0 - 255 or COLOUR_DEFAULT */
- } col;
- /* true color (modern) */
- struct {
- RGB8 fg, bg;
- } rgb;
- };
-};
-
-/* outputs */
-struct Cell
-{
- rune txt;
- Pen pen;
-};
-
-struct Row
-{
- Cell *cells;
- uint dirty : 1;
-};
-
-struct Dot
-{
- int row, col;
-};
-
-/*
- * scroll.top & scroll.bot are pointers into the viewport.
- *
- * scroll back buffer
- *
- * scroll.buf->+----------------+-----+
- * | | | ^ \
- * | before | | | |
- * current terminal content | viewport | | | |
- * | | | |
- * +----------------+-----+\ | | | s > scroll.above
- * ^ | | i | \ | | i | c |
- * | | | n | \ | | n | r |
- * | | v | \ | | v | o |
- * | | i | \ | | i | l /
- * | buffer | s | >|<- scroll.index | s | l \
- * h | | i | / | | i | |
- * | | b | / | after | b | s > scroll.below
- * | | l | / | viewport | l | i |
- * v | | e | / | | e | z /
- * +----------------+-----+/ | unused | | e
- * <- maxw -> | scroll back | |
- * <- w -> | buffer | | |
- * | | | |
- * | | | v
- * scroll.buf + scroll.size->+----------------+-----+
- * <- maxw ->
- * <- w ->
- */
-
-struct Buffer
-{
- int w, h; /* dimension of buffer */
- Pen pen; /* default attributes */
- int maxw; /* allocated cells (maximal cols over time) */
- Row *row; /* array of row pointers of size 'h' */
- struct {
- Row *buf;
- Row *top;
- Row *bot;
- int size;
- int index;
- int above;
- int below;
- } scroll;
- Dot cur, save; /* cursor position within buffer */
-};
-
-struct Window
-{
- struct Buffer;
- int top, left;
- uchar curvis : 1;
- uchar blink : 2;
-
- Window *parent, *child, *link;
-};
-
-/* input */
-struct Key
-{
- int type;
- int mods;
- uchar utf8[UTFmax+1];
- union {
- rune pt;
- int num;
- int sym;
- char mouse[4];
- } code;
-};
-
-struct KeyInfo
-{
- int type;
- int sym;
- int modmask;
- int modset;
-};
-
-struct Input
-{
- int fd;
- int flags;
- int wait; /* in ms */
-
- /* modifiers */
- uchar closed : 1;
- uchar started : 1;
- uchar hasold : 1;
-
- struct termios oldterm;
-
- /* buffer */
- struct {
- long off;
- uchar *b, *c, *e, bytes[256];
- } rbuf;
- struct {
- uchar *s, bytes[256];
- } ebuf;
-
- /* key data */
- Node *keys;
- struct KeyInfo c0[32];
-};
-
-
-struct Term
-{
- /* meta data */
- char *name;
- unibi_term *info;
- struct {
- uchar altscreen : 1;
- uchar cursorvis : 1;
- uchar mouse : 1;
- } mode;
- struct {
- uchar bce : 1;
- int colors;
- } cap;
-
- /* input capture */
- Input input;
-
- /* output display */
- Window *root;
- Pen pen;
-
- /* raw text to pty */
- int fd;
- struct {
- char *c, b[512];
- } buf;
-
- struct {
- int len;
- char *b;
- } tmp;
-
- /* info */
- struct {
- /* Positioning */
- char *cup; // cursor_address
- char *vpa; // row_address == vertical position absolute
- char *hpa; // column_address = horizontal position absolute
-
- /* Moving */
- char *cuu; char *cuu1; // Cursor Up
- char *cud; char *cud1; // Cursor Down
- char *cuf; char *cuf1; // Cursor Forward == Right
- char *cub; char *cub1; // Cursor Backward == Left
-
- /* Editing */
- char *ich; char *ich1; // Insert Character
- char *dch; char *dch1; // Delete Character
- char *il; char *il1; // Insert Line
- char *dl; char *dl1; // Delete Line
- char *ech; // Erase Character
- char *ed2; // Erase Data 2 == Clear screen
- char *stbm; // Set Top/Bottom Margins
-
- /* formatting */
- char *sgr; // Select Graphic Rendition
- char *sgr0; // Exit Attribute Mode
- char *sgr_i0, *sgr_i1; // SGR italic off/on
- char *sgr_fg; // SGR foreground colour
- char *sgr_bg; // SGR background colour
-
- /* Mode setting/clearing */
- char *sm_csr; char *rm_csr; // Set/reset mode: Cursor visible
-
- /* augmentations to terminfo */
- struct {
- char *rgbf; // rgb foreground
- char *rgbb; // rgb background
- char *smxx; // strikethrough
- char *smulx; // curly underline
- } ext;
- } esc;
-
- Term *link;
-};
-
-/* functions */
-void tresize(Term *t);
-
-Window *wmake(Window *root, int top, int left, int w, int h, int scroll);
-void wresize(Window *root, int w, int h);
-void wputrune(Window *win, rune r);
-void wscroll(Window *win, int s);
diff --git a/sys/libterm/window.c b/sys/libterm/window.c
deleted file mode 100644
index 5d36c8b..0000000
--- a/sys/libterm/window.c
+++ /dev/null
@@ -1,408 +0,0 @@
-#include "term.h"
-
-// -----------------------------------------------------------------------
-// buffers
-
-static
-void
-zero(Row *row, int start, int len)
-{
- int i;
- Cell cell = {
- .txt = L' ',
- .pen = {
- .state = PenNormal,
- .col.fg = -1,
- .col.bg = -1,
- },
- };
-
- for (i = start; i < len + start; i++)
- row->cells[i] = cell;
- row->dirty = 1;
-}
-
-static
-void
-roll(Row *start, Row *end, int count)
-{
- int n = end - start;
-
- /* enforce circularity */
- count %= n;
- if (count < 0)
- count += n;
-
- if (count) {
- char buf[count * sizeof(Row)]; /* XXX: remove VLA */
- memcpy(buf, start, count * sizeof(Row));
- memmove(start, start + count, (n - count) * sizeof(Row));
- memcpy(end - count, buf, count * sizeof(Row));
-
- for (Row *row = start; row < end; row++)
- row->dirty = 1;
- }
-}
-
-/* buffer operations */
-static
-void
-bclear(Buffer *b)
-{
- int i;
- Cell cell = {
- .txt = L' ',
- .pen = {
- .state = PenNormal,
- .col.fg = -1,
- .col.bg = -1,
- },
- };
-
- for (i = 0; i < b->h; i++) {
- Row *row = b->row + i;
- for (int j = 0; j < b->w; j++) {
- row->cells[j] = cell;
- row->dirty = 1;
- }
- }
-}
-
-static
-void
-bfini(Buffer *b)
-{
- int i;
-
- for (i = 0; i < b->h; i++)
- free(b->row[i].cells);
-
- free(b->row);
-
- if (b->scroll.size) {
- for (i = 0; i < b->scroll.size; i++)
- free(b->scroll.buf[i].cells);
-
- free(b->scroll.buf);
- }
-}
-
-static
-void
-bscroll(Buffer *b, int s)
-{
- Row tmp;
- int i, ssz = b->scroll.bot - b->scroll.top;
-
- /* work in quanta of screen size */
- if (s > ssz) {
- bscroll(b, ssz);
- bscroll(b, s - ssz);
- return;
- }
- if (s < -ssz) {
- bscroll(b, -ssz);
- bscroll(b, s + ssz);
- return;
- }
-
- b->scroll.above += s;
- b->scroll.above = CLAMP(b->scroll.above, 0, b->scroll.size);
-
- if (s > 0) {
- if (b->scroll.size) {
- for (i = 0; i < s; i++) {
- tmp = b->scroll.top[i];
- b->scroll.top[i] = b->scroll.buf[b->scroll.index];
- b->scroll.buf[b->scroll.index] = tmp;
-
- b->scroll.index++;
- if (b->scroll.index == b->scroll.size)
- b->scroll.index = 0;
- }
- } else
- for (i = 0; i < s; i++)
- zero(b->scroll.top+i, 0, b->maxw);
- }
-
- roll(b->scroll.top, b->scroll.bot, s);
-
- if (s < 0) {
- if (b->scroll.size) {
- for (i = (-s) - 1; i >= 0; i--) {
- b->scroll.index--;
- if (b->scroll.index == -1)
- b->scroll.index = b->scroll.size - 1;
-
- tmp = b->scroll.top[i];
-
- b->scroll.top[i] = b->scroll.buf[b->scroll.index];
- b->scroll.buf[b->scroll.index] = tmp;
- b->scroll.top[i].dirty = 1;
- }
- } else
- for (i = (-s) - 1; i >= 0; i--)
- zero(b->scroll.top+i, 0, b->maxw);
- }
-}
-
-static
-void
-bresize(Buffer *b, int nrow, int ncol)
-{
- int r, d;
- Row *row = b->row;
- Row *cur = row + b->cur.row;
-
- if (b->h != nrow) {
- /* scroll if we can */
- if (cur >= row + nrow)
- bscroll(b, b->cur.row - nrow + 1);
- while (b->h > nrow) {
- free(row[b->h - 1].cells);
- b->h--;
- }
-
- row = realloc(row, sizeof(Row) * nrow);
- }
-
- if (b->maxw < ncol) {
- /* expand each row */
- for (r = 0; r < b->h; r++) {
- row[r].cells = realloc(row[r].cells, sizeof(Cell) * ncol);
- if (b->h < ncol)
- zero(row + r, b->w, ncol - b->w);
- row[r].dirty = 1;
- }
- /* expand the scroll buffer */
- Row *sbuf = b->scroll.buf;
- for (r = 0; r < b->scroll.size; r++) {
- sbuf[r].cells = realloc(sbuf[r].cells, sizeof(Cell) * ncol);
- if (b->w < ncol)
- zero(sbuf + r, b->w, ncol - b->w);
- }
- b->maxw = b->w = ncol;
- } else if (b->w != ncol) {
- for (r = 0; r < b->h; r++)
- row[r].dirty = 1;
- b->w = ncol;
- }
-
- d = 0;
- if (b->h < nrow) {
- while (b->h < nrow) {
- row[b->h].cells = calloc(b->maxw, sizeof(Cell));
- zero(row + b->h, 0, b->maxw);
- b->h++;
- }
-
- /* prepare for backfill */
- if (cur >= b->scroll.bot - 1) {
- d = b->row + nrow - cur - 1;
- if (d > b->scroll.above)
- d = b->scroll.above;
- }
- }
-
- b->cur.row += row - b->row;
- b->scroll.top = row;
- b->scroll.bot = row + nrow;
- b->row = row;
-
- /* perform backfill */
- if (d > 0) {
- bscroll(b, -d);
- b->cur.row += d;
- }
-}
-
-static
-bool
-binit(Buffer *b, int cols, int rows, int scroll)
-{
- int size;
-
- b->pen.state = PenNormal;
- b->pen.col.fg = b->pen.col.bg = -1;
-
- size = MAX(scroll, 0);
- if (size && !(b->scroll.buf = calloc(size, sizeof(Row))))
- return false;
-
- b->scroll.size = size;
- bresize(b, rows, cols);
-
- b->cur = (Dot){0};
- b->save = b->cur;
-
- return true;
-}
-
-static
-void
-bboundary(Buffer *b, Row **bs, Row **be, Row **as, Row **ae)
-{
- if (bs)
- *bs = nil;
- if (be)
- *be = nil;
- if (as)
- *as = nil;
- if (ae)
- *ae = nil;
- if (!b->scroll.size)
- return;
-
- if (b->scroll.above) {
- if (bs)
- *bs = &b->scroll.buf[(b->scroll.index - b->scroll.above + b->scroll.size) % b->scroll.size];
- if (be)
- *be = &b->scroll.buf[(b->scroll.index-1 + b->scroll.size) % b->scroll.size];
- }
- if (b->scroll.below) {
- if (as)
- *as = &b->scroll.buf[b->scroll.index];
- if (ae)
- *ae = &b->scroll.buf[(b->scroll.index + b->scroll.below-1) % b->scroll.size];
- }
-}
-
-static
-Row *
-browfirst(Buffer *b)
-{
- Row *bstart;
- if (!b->scroll.size || !b->scroll.above)
- return b->row;
- bboundary(b, &bstart, nil, nil, nil);
- return bstart;
-}
-
-static
-Row *
-browlast(Buffer *b)
-{
- Row *aend;
- if (!b->scroll.size || !b->scroll.below)
- return b->row + b->h - 1;
- bboundary(b, nil, nil, nil, &aend);
- return aend;
-}
-
-static
-Row *
-brownext(Buffer *b, Row *row)
-{
- Row *before_start, *before_end, *after_start, *after_end;
- Row *first = b->row, *last = b->row + b->h - 1;
-
- if (!row)
- return nil;
-
- bboundary(b, &before_start, &before_end, &after_start, &after_end);
-
- if (row >= first && row < last)
- return ++row;
- if (row == last)
- return after_start;
- if (row == before_end)
- return first;
- if (row == after_end)
- return nil;
- if (row == &b->scroll.buf[b->scroll.size - 1])
- return b->scroll.buf;
- return ++row;
-}
-
-static
-Row *
-bprevrow(Buffer *b, Row *row)
-{
- Row *before_start, *before_end, *after_start, *after_end;
- Row *first = b->row, *last = b->row + b->h - 1;
-
- if (!row)
- return nil;
-
- bboundary(b, &before_start, &before_end, &after_start, &after_end);
-
- if (row > first && row <= last)
- return --row;
- if (row == first)
- return before_end;
- if (row == before_start)
- return nil;
- if (row == after_start)
- return last;
- if (row == b->scroll.buf)
- return &b->scroll.buf[b->scroll.size - 1];
- return --row;
-}
-
-// -----------------------------------------------------------------------
-// windows
-
-Window *
-wmake(Window *root, int top, int left, int w, int h, int scroll)
-{
- Window *child, *it;
-
- child = calloc(1, sizeof(*child));
- child->top = top;
- child->left = left;
- child->parent = root;
- if (root) {
- if (root->child) {
- for (it = root->child; it->link != nil; it = it->link)
- ;
- it->link = child;
- } else
- root->child = child;
-
- child->curvis = root->curvis;
- child->blink = root->blink;
- }
-
- if (!binit((Buffer*)child, w, h, scroll)) {
- free(child);
- return nil;
- }
-
- return child;
-}
-
-void
-wfree(Window *win)
-{
- free(win);
-}
-
-void
-wresize(Window *win, int w, int h)
-{
- bresize((Buffer*)win, w, h);
-}
-
-/* TODO: more sophisticated damage tracking */
-void
-wputrune(Window *win, rune r)
-{
- Row *row = win->row + win->cur.row;
- Cell *cell = row->cells + win->cur.col;
-
- cell->pen = win->pen;
- cell->txt = r;
-
- if (win->cur.col++ >= win->w) {
- win->cur.col = 0;
- if (win->cur.row++ >= win->h)
- win->cur.row = win->h-1;
- }
- row->dirty = 1;
-}
-
-void
-wscroll(Window *win, int s)
-{
- bscroll((Buffer*)win, s);
-}
diff --git a/sys/libutf/canfit.c b/sys/libutf/canfit.c
deleted file mode 100644
index 4579ab3..0000000
--- a/sys/libutf/canfit.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "internal.h"
-
-/* returns 1 if string of length n is long enough to be decoded */
-int
-utf8·canfit(byte* s, int n)
-{
- int i;
- rune c;
-
- if(n <= 0)
- return 0;
-
- c = *(ubyte*)s;
- if(c < TByte1)
- return 1;
-
- if(c < TByte3)
- return n >= 2;
- if(c < TByte4)
- return n >= 3;
-
- return n >= UTFmax;
-}
diff --git a/sys/libutf/decode.c b/sys/libutf/decode.c
deleted file mode 100644
index 01797f1..0000000
--- a/sys/libutf/decode.c
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "internal.h"
-
-#define ACCEPT 0
-#define REJECT 12
-
-static uint8 decode[] = {
- /*
- * the first part of the table maps bytes to character classes that
- * to reduce the size of the transition table and create bitmasks
- */
- 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,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
-
- /*
- * the second part is a transition table that maps a combination
- * of a state of the automaton and a character class to a state
- */
- 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
- 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
- 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
- 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
- 12,36,12,12,12,12,12,12,12,12,12,12,
-};
-
-int
-utf8·decode(char *s, rune *r)
-{
- int n;
- rune v;
- uint8 b, t, x=ACCEPT;
-
- b = ((uint8 *)s)[0];
- t = decode[b];
- v = (0xFF >> t) & b;
- x = decode[256+x+t];
-
- for(n=1; x > REJECT && n < UTFmax; n++){
- b = ((uint8 *)s)[n];
- t = decode[b];
- v = (v << 6) | (b & TMask);
- x = decode[256+x+t];
- }
-
- if(x != ACCEPT){
- *r = RuneErr;
- return 1;
- }
-
- *r = v;
- return n;
-}
-
-#if 0
-int
-utf8·decode(byte *s, rune *r)
-{
- int c[UTFmax], i;
- rune l;
-
- c[0] = *(ubyte*)(s);
- if(c[0] < Tx){
- *r = c[0];
- return 1;
- }
-
- l = c[0];
- for(i = 1; i < UTFmax; i++){
- c[i] = *(ubyte*)(s+i);
- c[i] ^= Tx;
- if(c[i] & Testx) goto bad;
-
- l = (l << Bitx) | c[i];
- if(c[0] < Tbyte(i + 2)){
- l &= RuneX(i + 1);
- if(i == 1){
- if(c[0] < Tbyte(2) || l <= Rune1)
- goto bad;
- }else if(l <= RuneX(i) || l > RuneMax)
- goto bad;
-
- if(i == 2 && SurrogateMin <= l && l <= SurrogateMax)
- goto bad;
-
- *r = l;
- return i + 1;
- }
- }
-bad:
- *r = RuneErr;
- return 1;
-}
-#endif
diff --git a/sys/libutf/decodeprev.c b/sys/libutf/decodeprev.c
deleted file mode 100644
index 27dced6..0000000
--- a/sys/libutf/decodeprev.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "internal.h"
-
-#define ACCEPT 0
-#define REJECT 12
-
-static uint8 decode[] = {
- /*
- * the first part of the table maps bytes to character classes that
- * to reduce the size of the transition table and create bitmasks.
- */
- 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,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
- /*
- * The second part is a transition table that maps a combination
- * of a state of the automaton and a character class to a state.
- */
- // 0 1 2 3 4 5 6 7 8 9 10 11
- 0,24,12,12,12,12,12,24,12,24,12,12,
- 0,24,12,12,12,12,12,24,12,24,12,12,
- 12,36, 0,12,12,12,12,48,12,36,12,12,
- 12,60,12, 0, 0,12,12,72,12,72,12,12,
- 12,60,12, 0,12,12,12,72,12,72, 0,12,
- 12,12,12,12,12, 0, 0,12,12,12,12,12,
- 12,12,12,12,12,12,12,12,12,12,12, 0
-};
-
-int
-utf8·decodeprev(byte *s, rune *r)
-{
- int n;
- rune v;
- uint8 b, t, d, x=ACCEPT;
-
- v=0, n=0, d=0;
-nextbyte:
- b = ((uint8 *)s)[-n++];
- t = decode[b];
- x = decode[256+x+t];
-
- if(x > REJECT && n < UTFmax){
- v = v | ((b & TMask) << d);
- d += 6;
- goto nextbyte;
- }
-
- if(x != ACCEPT)
- *r = RuneErr;
- else{
- v |= (((0xFFu >> t) & b) << d);
- *r = v;
- }
-
- return n;
-}
diff --git a/sys/libutf/encode.c b/sys/libutf/encode.c
deleted file mode 100644
index fa7c93e..0000000
--- a/sys/libutf/encode.c
+++ /dev/null
@@ -1,69 +0,0 @@
-#include "internal.h"
-
-int
-utf8·encode(rune *r, byte *s)
-{
- rune c;
-
- c = *r;
- if(c < Rune1Byte){ // 7 bits
- s[0] = (uint8)c;
- return 1;
- }
-
- if(c < Rune2Byte){ // 11 bits
- s[0] = TByte1 | (c >> 6);
- s[1] = Tx | (c & TMask);
- return 2;
- }
-
- if(c < Rune3Byte){ // 16 bits
- s[0] = TByte2 | ((c >> 12));
- s[1] = Tx | ((c >> 6) & TMask);
- s[2] = Tx | ((c) & TMask);
- return 3;
- }
-
- // 22 bits
- if(c > RuneMax || (RuneSurrogateMin <= c && c <= RuneSurrogateMax))
- c = RuneErr;
-
- s[0] = TByte3 | ((c >> 18));
- s[1] = Tx | ((c >> 12) & TMask);
- s[2] = Tx | ((c >> 6) & TMask);
- s[3] = Tx | ((c) & TMask);
-
- return 4;
-}
-
-#if 0
-int
-utf8·encode(rune* r, byte* s)
-{
- int i, j;
- rune c;
-
- c = *r;
- if(c <= Rune1) {
- s[0] = c;
- return 1;
- }
-
- for(i = 2; i < UTFmax + 1; i++){
- if(i == 3){
- if(c > RuneMax)
- c = RuneErr;
- if(SurrogateMin <= c && c <= SurrogateMax)
- c = RuneErr;
- }
- if(c <= RuneX(i) || i == UTFmax) {
- s[0] = Tbyte(i) | (c >> (i - 1)*Bitx);
- for(j = 1; j < i; j++)
- s[j] = Tx | ((c >> (i - j - 1)*Bitx) & Maskx);
- return i;
- }
- }
-
- return UTFmax;
-}
-#endif
diff --git a/sys/libutf/find.c b/sys/libutf/find.c
deleted file mode 100644
index d75feb8..0000000
--- a/sys/libutf/find.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "internal.h"
-
-byte*
-utf8·find(byte* s, rune c)
-{
- long c1;
- rune r;
- int n;
-
- if(c < Tx)
- return strchr(s, c);
-
- for(;;){
- c1 = *(ubyte*)s;
- if(c1 < Tx){
- if(c1 == 0) return nil;
- if(c1 == c) return s;
- s++;
- continue;
- }
-
- n = utf8·decode(s, &r);
-
- if(r == c)
- return s;
-
- s += n;
- }
-
- return nil;
-}
diff --git a/sys/libutf/findlast.c b/sys/libutf/findlast.c
deleted file mode 100644
index ab25ab2..0000000
--- a/sys/libutf/findlast.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "internal.h"
-
-byte*
-utf8·findlast(byte* s, rune c)
-{
- long c1;
- rune r;
- byte *l;
-
- if(c < Tx)
- return strrchr(s, c);
-
- l = nil;
- for(;;){
- c1 = *(ubyte*)s;
- if(c1 < Tx){
- if(c1 == 0) return l;
- if(c1 == c) l = s;
- s++;
- continue;
- }
-
- c1 = utf8·decode(s, &r);
-
- if(r == c)
- l = s;
-
- s += c1;
- }
-
- return nil;
-}
diff --git a/sys/libutf/internal.h b/sys/libutf/internal.h
deleted file mode 100644
index 9719977..0000000
--- a/sys/libutf/internal.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-
-/*
- * NOTE: we use the preprocessor to ensure we have unsigned constants.
- * UTF-8 code:
- * 1 byte:
- * 0xxxxxxx
- * 2 byte:
- * 110xxxxx 10xxxxxx
- * 3 byte:
- * 1110xxxx 10xxxxxx 10xxxxxx
- * 4 byte:
- * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- */
-
-#define Tx 0x80u // 0b10000000 transfer header
-#define TMask 0x3Fu // 0b00111111 transfer mask
-
-#define TByte1 0xC0u // 0b11000000
-#define TByte2 0xE0u // 0b11100000
-#define TByte3 0xF0u // 0b11110000
-#define TByte4 0xF8u // 0b11111000
-
-#define RuneMask 0x1FFFFFu
-
-#define Rune1Byte 0x000080u // 1 << 8 (1 byte)
-#define Rune2Byte 0x001000u // 1 << 12 (2 bytes)
-#define Rune3Byte 0x020000u // 1 << 17 (3 bytes)
-#define Rune4Byte 0x400000u // 1 << 22 (4 bytes)
-
-
-/* UTF-16 nonsense */
-#define RuneSurrogateMin 0x0D8000
-#define RuneSurrogateMax 0x0D8FFF
diff --git a/sys/libutf/len.c b/sys/libutf/len.c
deleted file mode 100644
index 8fbd679..0000000
--- a/sys/libutf/len.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "internal.h"
-
-int
-utf8·len(char *s)
-{
- int c;
- long n;
- rune r;
-
- n = 0;
- for(;;){
- c = *(uchar*)s;
- if(c < Tx){
- if(c == 0)
- return n;
- s++;
- }else
- s += utf8·decode(s, &r);
- n++;
- }
-}
diff --git a/sys/libutf/rules.mk b/sys/libutf/rules.mk
deleted file mode 100644
index 53ff8cf..0000000
--- a/sys/libutf/rules.mk
+++ /dev/null
@@ -1,76 +0,0 @@
-include share/push.mk
-
-UNICODE = 14.0.0
-
-SRCS_$(d) := \
- $(d)/encode.c \
- $(d)/decode.c \
- $(d)/decodeprev.c \
- $(d)/find.c \
- $(d)/findlast.c \
- $(d)/canfit.c \
- $(d)/runelen.c \
- $(d)/len.c \
- $(d)/runetype-$(UNICODE).c \
- $(d)/runewidth-$(UNICODE).c
-
-LIBS_$(d) := $(d)/libutf.a
-
-include share/paths.mk
-
-# ========================================================================
-# table generation
-
-$(d)/vendor/common.o: $(d)/vendor/common.c
- $(COMPILE)
-
-# rune categories
-$(d)/vendor/UnicodeData-$(UNICODE).txt:
- @echo "GET UnicodeData.txt";\
- curl https://www.unicode.org/Public/$(UNICODE)/ucd/UnicodeData.txt > $@
-
-$(d)/vendor/mkrunetype: $(d)/vendor/mkrunetype.c $(d)/vendor/common.o $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-GENS += $(d)/vendor/mkrunetype
-
-$(d)/runetype-$(UNICODE).c: $(d)/vendor/UnicodeData-$(UNICODE).txt $(d)/vendor/mkrunetype
- @$(dir $@)vendor/mkrunetype $< > $@
-
-# rune widths
-$(d)/vendor/EastAsianWidth-$(UNICODE).txt:
- @echo "GET EastAsianWidth.txt";\
- curl https://www.unicode.org/Public/$(UNICODE)/ucd/EastAsianWidth.txt > $@
-
-$(d)/vendor/EmojiData-$(UNICODE).txt:
- @echo "GET EmojiData.txt";\
- curl https://www.unicode.org/Public/$(UNICODE)/ucd/emoji/emoji-data.txt > $@
-
-$(d)/vendor/mkrunewidth: $(d)/vendor/mkrunewidth.c $(d)/vendor/common.o $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-GENS += $(d)/vendor/mkrunewidth
-
-$(d)/runewidth-$(UNICODE).c: $(d)/vendor/mkrunewidth $(d)/vendor/UnicodeData-$(UNICODE).txt $(d)/vendor/EastAsianWidth-$(UNICODE).txt $(d)/vendor/EmojiData-$(UNICODE).txt
- @$(dir $@)vendor/mkrunewidth $(filter-out $<, $^) > $@
-
-# grapheme boundaries
-$(d)/vendor/GraphemeBreakProperty-$(UNICODE).txt:
- @echo "GET GraphemeBreakProperty.txt";\
- curl https://www.unicode.org/Public/$(UNICODE)/ucd/auxiliary/GraphemeBreakProperty.txt > $@
-
-$(d)/vendor/mkgraphemedata: $(d)/vendor/mkgraphemedata.c $(d)/vendor/common.o $(OBJ_DIR)/sys/base/base.a
- $(COMPLINK)
-
-$(d)/graphemedata-$(UNICODE).c: $(d)/vendor/mkgraphemedata $(d)/vendor/GraphemeBreakProperty-$(UNICODE).txt
- $^ > $@
-
-GENS += $(d)/vendor/mkgraphemedata
-
-# ========================================================================
-# normal operations
-
-$(LIBS_$(d)): $(OBJS_$(d))
- $(ARCHIVE)
-
-include share/pop.mk
diff --git a/sys/libutf/runelen.c b/sys/libutf/runelen.c
deleted file mode 100644
index dac7f15..0000000
--- a/sys/libutf/runelen.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "internal.h"
-
-int
-utf8·runelen(rune r)
-{
- byte s[10];
- return utf8·encode(&r, s);
-}
diff --git a/sys/libutf/vendor/common.c b/sys/libutf/vendor/common.c
deleted file mode 100644
index 5a03a50..0000000
--- a/sys/libutf/vendor/common.c
+++ /dev/null
@@ -1,220 +0,0 @@
-#include "common.h"
-
-// -----------------------------------------------------------------------
-// input functions
-
-int
-parse(io·Stream *io, int nfield, char **field, int len, char *line)
-{
- int n;
- if((n=io·readln(io, len, line)) <= 0)
- return ParseEOF;
-
- if(n == len)
- panicf("line too long");
-
- if(line[n-1] != '\n')
- panicf("invalid line: expected '\n', found '%c'", line[n]);
-
- line[n-1] = 0;
-
- if(line[0] == '#' || line[0] == 0)
- return ParseSkip;
-
- /* tokenize line into fields */
- n = 0;
- field[n] = line;
- while(*line){
- if(*line == ';'){
- *line = 0;
- field[++n] = line+1;
- }
- line++;
- }
-
- if(n != nfield-1)
- panicf("expected %d number of fields, got %d: %s", nfield, n, line);
-
- return ParseOK;
-}
-
-int
-codepoint(char *s)
-{
- int c, b;
-
- c = 0;
- while((b=*s++)){
- c <<= 4;
- if(b >= '0' && b <= '9')
- c += b - '0';
- else if(b >= 'A' && b <= 'F')
- c += b - 'A' + 10;
- else
- panicf("bad codepoint char '%c'", b);
- }
-
- return c;
-}
-
-void
-codepointrange(io·Stream *utf8, char *field[NumFields], int *start, int *stop)
-{
- int e, c;
- char *other[NumFields], line[1024];
-
- // XXX: the stop variable passes in the previous stopping character
- e = *stop;
- c = codepoint(field[Fcode]);
-
- if(c >= NumRunes)
- panicf("unexpected large codepoint %x", c);
- if(c <= e)
- panicf("bad code sequence: %x then %x", e, c);
- e = c;
-
- if(strstr(field[Fname], ", First>") != nil){
- if(!parse(utf8, arrlen(other), other, arrlen(line), line))
- panicf("range start at end of file");
- if(strstr(other[Fname], ", Last>") == nil)
- panicf("range start not followed by range end");
-
- e = codepoint(other[Fcode]);
-
- if(e <= c)
- panicf("bad code sequence: %x then %x", c, e);
- if(strcmp(field[Fcategory], other[Fcategory]) != 0)
- panicf("range with mismatched category");
- }
-
- *start = c;
- *stop = e;
-}
-
-// -----------------------------------------------------------------------
-// output functions
-
-void
-putsearch(void)
-{
- puts(
- "#include <u.h>\n"
- "#include <libutf.h>\n"
- "\n"
- "static\n"
- "rune*\n"
- "rangesearch(rune c, rune *t, int n, int ne)\n"
- "{\n"
- " rune *p;\n"
- " int m;\n"
- " while(n > 1) {\n"
- " m = n >> 1;\n"
- " p = t + m*ne;\n"
- " if(c >= p[0]){\n"
- " t = p;\n"
- " n = n-m;\n"
- " }else\n"
- " n = m;\n"
- " }\n"
- " if(n && c >= t[0])\n"
- " return t;\n"
- " return 0;\n"
- "}\n"
- );
-
-}
-
-int
-putrange(char *ident, char *prop, int force)
-{
- int l, r, start;
-
- start = 0;
- for(l = 0; l < NumRunes;) {
- if(!prop[l]){
- l++;
- continue;
- }
-
- for(r = l+1; r < NumRunes; r++){
- if(!prop[r])
- break;
- prop[r] = 0;
- }
-
- if(force || r > l + 1){
- if(!start){
- printf("static rune %s[] = {\n", ident);
- start = 1;
- }
- prop[l] = 0;
- printf("\t0x%.4x, 0x%.4x,\n", l, r-1);
- }
-
- l = r;
- }
-
- if(start)
- printf("};\n\n");
-
- return start;
-}
-
-int
-putpair(char *ident, char *prop)
-{
- int l, r, start;
-
- start = 0;
- for(l=0; l+2 < NumRunes; ){
- if(!prop[l]){
- l++;
- continue;
- }
-
- for(r = l + 2; r < NumRunes; r += 2){
- if(!prop[r])
- break;
- prop[r] = 0;
- }
-
- if(r != l + 2){
- if(!start){
- printf("static rune %s[] = {\n", ident);
- start = 1;
- }
- prop[l] = 0;
- printf("\t0x%.4x, 0x%.4x,\n", l, r - 2);
- }
-
- l = r;
- }
-
- if(start)
- printf("};\n\n");
- return start;
-}
-
-int
-putsingle(char *ident, char *prop)
-{
- int i, start;
-
- start = 0;
- for(i = 0; i < NumRunes; i++) {
- if(!prop[i])
- continue;
-
- if(!start){
- printf("static rune %s[] = {\n", ident);
- start = 1;
- }
- prop[i] = 0;
- printf("\t0x%.4x,\n", i);
- }
-
- if(start)
- printf("};\n\n");
-
- return start;
-}
diff --git a/sys/libutf/vendor/common.h b/sys/libutf/vendor/common.h
deleted file mode 100644
index 62f6c5b..0000000
--- a/sys/libutf/vendor/common.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-
-enum
-{
- // Fields inside UnicodeData.txt
- Fcode,
- Fname,
- Fcategory,
- Fcombine,
- Fbidir,
- Fdecomp,
- Fdecimal,
- Fdigit,
- Fnumeric,
- Fmirror,
- Foldname,
- Fcomment,
- Fupper,
- Flower,
- Ftitle,
-
- NumFields,
- NumRunes = 1 << 21,
-};
-
-/* input functions */
-enum
-{
- ParseEOF,
- ParseOK,
- ParseSkip,
-};
-
-int parse(io·Stream *io, int nfield, char **field, int len, char *line);
-int codepoint(char *s);
-void codepointrange(io·Stream *utf8, char *field[NumFields], int *start, int *stop);
-
-/* output functions */
-void putsearch(void);
-int putrange(char *ident, char *prop, int force);
-int putpair(char *ident, char *prop);
-int putsingle(char *ident, char *prop);
diff --git a/sys/libutf/vendor/mkgraphemedata.c b/sys/libutf/vendor/mkgraphemedata.c
deleted file mode 100644
index ce5a952..0000000
--- a/sys/libutf/vendor/mkgraphemedata.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <u.h>
-#include <base.h>
-#include <libutf.h>
-
-// -----------------------------------------------------------------------
-// main point of entry
-
-static
-void
-usage(void)
-{
- fprintf(stderr, "usage: mkgraphemedata <GraphemeBreakProperty.txt>\n");
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- io·Stream *utf8;
- char line[1024];
-
- ARGBEGIN{
- }ARGEND;
-}
diff --git a/sys/libutf/vendor/mkrunetype.c b/sys/libutf/vendor/mkrunetype.c
deleted file mode 100644
index 9f939f4..0000000
--- a/sys/libutf/vendor/mkrunetype.c
+++ /dev/null
@@ -1,388 +0,0 @@
-#include "common.h"
-
-// -----------------------------------------------------------------------
-// globals
-
-#define OFFSET (1 << 20)
-#define DELTA(mapx, x) ((1 << 20) + (mapx) - (x))
-
-// TODO: use bitarrays. will reduce executable size 8x
-struct Table
-{
- /* properties */
- char isspace[NumRunes];
- char isalpha[NumRunes];
- char ismark[NumRunes];
- char isdigit[NumRunes];
- char isupper[NumRunes];
- char islower[NumRunes];
- char istitle[NumRunes];
- char ispunct[NumRunes];
- char issymbl[NumRunes];
- char iscntrl[NumRunes];
-
- char combine[NumRunes];
-
- /* transformations */
- int toupper[NumRunes];
- int tolower[NumRunes];
- int totitle[NumRunes];
-};
-
-static struct Table table;
-
-// -----------------------------------------------------------------------
-// internal functions
-
-static
-int
-isrange(char *label, char *prop, int force)
-{
- char ident[128];
- if(snprintf(ident, arrlen(ident), "is%s_range", label) == arrlen(ident))
- panicf("out of identifier space\n");
-
- return putrange(ident, prop, force);
-}
-
-static
-int
-ispair(char *label, char *prop)
-{
- char ident[128];
- if(snprintf(ident, arrlen(ident), "is%s_pair", label) == arrlen(ident))
- panicf("out of identifier space\n");
-
- return putpair(ident, prop);
-}
-
-static
-int
-issingle(char *label, char *prop)
-{
- char ident[128];
- if(snprintf(ident, arrlen(ident), "is%s_single", label) == arrlen(ident))
- panicf("out of identifier space\n");
-
- return putsingle(ident, prop);
-}
-
-static
-void
-makeis(char *label, char *table, int pairs, int onlyranges)
-{
- int hasr, hasp=0, hass=0;
-
- hasr = isrange(label, table, onlyranges);
- if(!onlyranges && pairs)
- hasp = ispair(label, table);
- if(!onlyranges)
- hass = issingle(label, table);
-
- printf(
- "int\n"
- "utf8·is%s(rune c)\n"
- "{\n"
- " rune *p;\n"
- "\n",
- label);
-
- if(hasr){
- printf(
- " p = rangesearch(c, is%s_range, arrlen(is%s_range)/2, 2);\n"
- " if(p && c >= p[0] && c <= p[1])\n"
- " return 1;\n",
- label, label);
- }
-
- if(hasp){
- printf(
- " p = rangesearch(c, is%s_pair, arrlen(is%s_pair)/2, 2);\n"
- " if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))\n"
- " return 1;\n",
- label, label);
- }
-
- if(hass)
- printf(
- " p = rangesearch(c, is%s_single, arrlen(is%s_single), 1);\n"
- " if(p && c == p[0])\n"
- " return 1;\n",
- label, label);
-
- printf(
- " return 0;\n"
- "}\n"
- "\n");
-}
-
-static
-int
-torange(char *label, int *index, int force)
-{
- int l, r, d, start = 0;
-
- for(l = 0; l < NumRunes; ){
- if(index[l] == l){
- l++;
- continue;
- }
-
- d = DELTA(index[l], l);
- if(d != (rune)d)
- panicf("bad map delta %d", d);
-
- for(r = l+1; r < NumRunes; r++){
- if(DELTA(index[r], r) != d)
- break;
- index[r] = r;
- }
-
- if(force || r != l + 1){
- if(!start){
- printf("static rune to%s_range[] = {\n", label);
- start = 1;
- }
- index[l] = l;
- printf("\t0x%.4x, 0x%.4x, %d,\n", l, r-1, d);
- }
- l = r;
- }
- if(start)
- printf("};\n\n");
-
- return start;
-}
-
-static
-int
-topair(char *label, int *index)
-{
- int l, r, d, start = 0;
-
- for(l = 0; l + 2 < NumRunes; ){
- if(index[l] == l){
- l++;
- continue;
- }
-
- d = DELTA(index[l], l);
- if(d != (rune)d)
- panicf("bad delta %d", d);
-
- for(r = l+2; r < NumRunes; r += 2){
- if(DELTA(index[r], r) != d)
- break;
- index[r] = r;
- }
-
- if(r > l+2){
- if(!start){
- printf("static rune to%s_pair[] = {\n", label);
- start = 1;
- }
- index[l] = l;
- printf("\t0x%.4x, 0x%.4x, %d,\n", l, r-2, d);
- }
-
- l = r;
- }
- if(start)
- printf("};\n\n");
-
- return start;
-}
-
-static
-int
-tosingle(char *label, int *index)
-{
- int i, d, start = 0;
-
- for(i=0; i < NumRunes; i++) {
- if(index[i] == i)
- continue;
-
- d = DELTA(index[i], i);
- if(d != (rune)d)
- panicf("bad map delta %d", d);
-
- if(!start){
- printf("static rune to%s_single[] = {\n", label);
- start = 1;
- }
- index[i] = i;
- printf("\t0x%.4x, %d,\n", i, d);
- }
- if(start)
- printf("};\n\n");
-
- return start;
-}
-
-static
-void
-mkto(char *label, int *index, int pairs, int onlyrange)
-{
- int hasr, hasp=0, hass=0;
-
- hasr = torange(label, index, !onlyrange);
- if(!onlyrange && pairs)
- hasp = topair(label, index);
- if(!onlyrange)
- hass = tosingle(label, index);
-
- printf(
- "rune\n"
- "utf8·to%s(rune c)\n"
- "{\n"
- " rune *p;\n"
- "\n",
- label);
-
- if(hasr)
- printf(
- " p = rangesearch(c, to%s_range, arrlen(to%s_range)/3, 3);\n"
- " if(p && c >= p[0] && c <= p[1])\n"
- " return c + p[2] - %d;\n",
- label, label, OFFSET);
-
- if(hasp)
- printf(
- " p = rangesearch(c, to%s_pair, arrlen(to%s_pair)/3, 3);\n"
- " if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))\n"
- " return c + p[2] - %d;\n",
- label, label, OFFSET);
-
- if(hass)
- printf(
- " p = rangesearch(c, to%s_single, arrlen(to%s_single)/2, 2);\n"
- " if(p && c == p[0])\n"
- " return c + p[1] - %d;\n",
- label, label, OFFSET);
-
-
- printf(
- " return c;\n"
- "}\n"
- "\n"
- );
-}
-
-// -----------------------------------------------------------------------
-// main point of entry
-
-static
-void
-usage(void)
-{
- fprintf(stderr, "usage: mkrunetype <UnicodeData.txt>\n");
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- int i, sc, c, ec;
- io·Stream *utf8;
- char *prop, *field[NumFields], line[1024];
-
- ARGBEGIN{
- }ARGEND;
-
- if(argc != 1)
- usage();
-
- if(!(utf8 = io·open(argv[0], "r")))
- panicf("can't open %s\n", argv[0]);
-
- /* by default each character maps to itself */
- for(i = 0; i < NumRunes; i++) {
- table.toupper[i] = i;
- table.tolower[i] = i;
- table.totitle[i] = i;
- }
-
- /* ensure all C local white space characters pass */
- table.isspace['\t'] = 1;
- table.isspace['\n'] = 1;
- table.isspace['\r'] = 1;
- table.isspace['\f'] = 1;
- table.isspace['\v'] = 1;
- table.isspace[0x85] = 1;
-
- ec = -1;
- // NOTE: we don't check for comments here: assume UnicodeData.txt doesn't have any
- while(parse(utf8, arrlen(field), field, arrlen(line), line)){
- /* parse unicode range */
- codepointrange(utf8, field, &sc, &ec);
- prop = field[Fcategory];
-
- for(c = sc; c <= ec; c++){
- /* grab properties */
- switch(prop[0]){
- case 'L':
- table.isalpha[c] = 1;
- switch(prop[1]){
- case 'u': table.isupper[c] = 1; break;
- case 'l': table.islower[c] = 1; break;
- case 't': table.istitle[c] = 1; break;
- case 'm': break; // modifier letters
- case 'o': break; // ideograph letters
- default:
- goto badproperty;
- }
- break;
-
- case 'Z':
- table.isspace[c] = 1;
- break;
-
- case 'M':
- table.ismark[c] = 1;
- break;
-
- case 'N':
- table.isdigit[c] = 1;
- break;
-
- case 'P':
- table.ispunct[c] = 1;
- break;
-
- case 'S':
- table.issymbl[c] = 1;
- break;
-
- case 'C':
- table.iscntrl[c] = 1;
- break;
-
- default: badproperty:
- panicf("unrecognized category '%s'", prop);
- }
- /* grab transformations */
- if(*field[Fupper])
- table.toupper[c] = codepoint(field[Fupper]);
- if(*field[Flower])
- table.tolower[c] = codepoint(field[Flower]);
- if(*field[Ftitle])
- table.totitle[c] = codepoint(field[Ftitle]);
- }
- }
- io·close(utf8);
-
- putsearch();
-
- makeis("space", table.isspace, 0, 1);
- makeis("digit", table.isdigit, 0, 1);
- makeis("alpha", table.isalpha, 0, 0);
- makeis("upper", table.isupper, 1, 0);
- makeis("lower", table.islower, 1, 0);
- makeis("title", table.istitle, 1, 0);
- makeis("punct", table.ispunct, 1, 0);
-
- mkto("upper", table.toupper, 1, 0);
- mkto("lower", table.tolower, 1, 0);
- mkto("title", table.totitle, 1, 0);
-}
diff --git a/sys/libutf/vendor/mkrunewidth.c b/sys/libutf/vendor/mkrunewidth.c
deleted file mode 100644
index 14e6973..0000000
--- a/sys/libutf/vendor/mkrunewidth.c
+++ /dev/null
@@ -1,325 +0,0 @@
-#include "common.h"
-
-/*
- * inspired by design choices in utf8proc/charwidths.jl
- * all widths default to 1 unless they fall within the categories:
- * 1. Mn 2. Mc 3. Me 4. Zl
- * 5. Zp 6. Cc 7. Cf 8. Cs
- * these default to zero width
- */
-enum
-{
- /* width ? */
- WidthNeutral, /* (N) practially treated like narrow but unclear ... */
- WidthAmbiguous, /* (A) sometimes wide and sometimes not... */
- /* width 1 */
- WidthHalf, /* (H) = to narrow (compatability equivalent) */
- WidthNarrow, /* (Na) ASCII width */
- /* width 2 */
- WidthWide, /* (W) 2x width */
- WidthFull, /* (F) = to wide (compatability equivalent) */
-};
-
-struct Table
-{
- char width[3][NumRunes];
-};
-
-static struct Table table;
-
-// -----------------------------------------------------------------------
-// internal functions
-
-static
-void
-parse_category(char *path)
-{
- int sc, c, ec, w;
- io·Stream *utf8;
- char *prop, *field[NumFields], line[1024];
-
- if(!(utf8 = io·open(path, "r")))
- panicf("can't open %s\n", path);
-
- // NOTE: we don't check for comments here
- ec = -1;
- while(parse(utf8, arrlen(field), field, arrlen(line), line)){
- codepointrange(utf8, field, &sc, &ec);
-
- prop = field[Fcategory];
-
- switch(prop[0]){
- case 'M':
- switch(prop[1]){
- case 'n': case 'c': case 'e':
- w = 0;
- break;
- default:
- w = 1;
- break;
- }
- break;
- case 'Z':
- switch(prop[1]){
- case 'l': case 'p':
- w = 0;
- break;
- default:
- w = 1;
- break;
- }
- break;
- case 'C':
- switch(prop[1]){
- case 'c': case 'f': case 's':
- w = 0;
- break;
- default:
- w = 1;
- break;
- }
- default:
- w = 1;
- }
-
- for(c = sc; c <= ec; c++)
- table.width[w][c] = 1;
- }
-
- io·close(utf8);
-}
-
-static
-void
-coderange(char *field, int *l, int *r)
-{
- char *s;
-
- if(!(s = strstr(field, "..")))
- *l=*r=codepoint(field);
- else{
- *s++ = 0, *s++ = 0;
- *l=codepoint(field);
- *r=codepoint(s);
- }
-}
-
-static
-void
-parse_eawidths(char *path)
-{
- int at, w;
- int l, c, r;
- io·Stream *utf8;
- char *field[2], line[1024];
-
- utf8 = io·open(path, "r");
- while((at=parse(utf8, arrlen(field), field, arrlen(line), line)) != ParseEOF){
- if(at == ParseSkip)
- continue;
-
- switch(field[1][0]){
- case 'A': continue;
- case 'N':
- if(field[1][1] != 'a')
- continue;
- /* fallthrough */
- case 'H': w = 1; break;
-
- case 'W': /* fallthrough */
- case 'F': w = 2; break;
-
- default:
- panicf("malformed east asian width class: %s\n", field[1]);
- }
-
- coderange(field[0], &l, &r);
-
- for(c=l; c <= r; c++){
- /* ensure it only exists in one table */
- table.width[w][c] = 1;
- table.width[(w+1)%3][c] = 0;
- table.width[(w+2)%3][c] = 0;
- }
- }
- io·close(utf8);
-}
-
-static
-void
-parse_emoji(char *path)
-{
- int at, w;
- int l, c, r;
- io·Stream *utf8;
- char *s, *field[2], line[1024];
-
- utf8 = io·open(path, "r");
- while((at=parse(utf8, arrlen(field), field, arrlen(line), line)) != ParseEOF){
- if(at == ParseSkip)
- continue;
-
- /* only override emoji presentation */
- if(!strstr(field[1], "Emoji_Presentation"))
- continue;
-
- /* trim trailing space */
- for(s=field[0]; *s; s++){
- if(*s == ' ')
- *s = 0;
- }
-
- coderange(field[0], &l, &r);
-
- for(c=l; c <= r; c++){
- table.width[0][c] = 0;
- table.width[1][c] = 0;
- table.width[2][c] = 1;
- }
- }
-
- io·close(utf8);
-}
-
-/* output functions */
-static
-void
-maketable(char *label, char *table, int pairs, int onlyranges)
-{
- int r, p=0, s=0;
- char ident[3][128];
-
- enum
- {
- Irange,
- Ipair,
- Isingle,
- };
-
- /* ranges */
- if(snprintf(ident[Irange], arrlen(ident[Irange]), "%s_range", label) == arrlen(ident[Irange]))
- panicf("out of identifier space\n");
- r = putrange(ident[Irange], table, onlyranges);
-
- if(!onlyranges && pairs){
- if(snprintf(ident[Ipair], arrlen(ident[Ipair]), "%s_pair", label) == arrlen(ident[Ipair]))
- panicf("out of identifier space\n");
- p = putpair(ident[Ipair], table);
- }
- if(!onlyranges){
- if(snprintf(ident[Isingle], arrlen(ident[Isingle]), "%s_single", label) == arrlen(ident[Isingle]))
- panicf("out of identifier space\n");
-
- s = putsingle(ident[Isingle], table);
- }
-
- printf(
- "static int\n"
- "is%s(rune c)\n"
- "{\n"
- " rune *p;\n"
- "\n",
- label);
-
- if(r){
- printf(
- " p = rangesearch(c, %s, arrlen(%s)/2, 2);\n"
- " if(p && c >= p[0] && c <= p[1])\n"
- " return 1;\n",
- ident[Irange], ident[Irange]);
- }
-
- if(p){
- printf(
- " p = rangesearch(c, %s, arrlen(%s)/2, 2);\n"
- " if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))\n"
- " return 1;\n",
- ident[Ipair], ident[Ipair]);
- }
-
- if(s)
- printf(
- " p = rangesearch(c, %s, arrlen(%s), 1);\n"
- " if(p && c == p[0])\n"
- " return 1;\n",
- ident[Isingle], ident[Isingle]);
-
- printf(
- " return 0;\n"
- "}\n"
- "\n");
-}
-
-// -----------------------------------------------------------------------
-// main point of entry
-
-static
-void
-usage(void)
-{
- fprintf(stderr, "usage: mkrunewidth <UnicodeData.txt> <EastAsianWidth.txt> <EmojiData.txt>\n");
- exit(1);
-}
-
-#define SETW0(c) \
- table.width[0][(c)] = 1, \
- table.width[1][(c)] = 0, \
- table.width[2][(c)] = 0;
-
-#define SETW1(c) \
- table.width[0][(c)] = 0, \
- table.width[1][(c)] = 1, \
- table.width[2][(c)] = 0;
-
-#define SETW2(c) \
- table.width[0][(c)] = 0, \
- table.width[1][(c)] = 0, \
- table.width[2][(c)] = 1;
-
-
-int
-main(int argc, char *argv[])
-{
- int c;
-
- ARGBEGIN{
- }ARGEND;
-
- if(argc != 3)
- usage();
-
- parse_category(*argv++);
- parse_eawidths(*argv++);
- parse_emoji(*argv);
-
- /* overrides */
- SETW0(0x2028);
- SETW0(0x2029);
-
- SETW1(0x00AD);
-
- /* simple checking */
- for(c=0; c<NumRunes; c++){
- if(table.width[0][c] + table.width[1][c] + table.width[2][c] > 1)
- panicf("improper table state");
- }
-
- putsearch();
-
- maketable("width0", table.width[0], 1, 0);
- maketable("width1", table.width[1], 1, 0);
- maketable("width2", table.width[2], 1, 0);
-
- puts(
- "\n"
- "int\n"
- "utf8·runewidth(rune c)\n"
- "{\n"
- " if(iswidth1(c))\n"
- " return 1;\n"
- " if(iswidth2(c))\n"
- " return 2;\n"
- " return 0;\n"
- "}"
- );
-}
diff --git a/sys/nixos/rules.mk b/sys/nixos/rules.mk
deleted file mode 100644
index e69de29..0000000
--- a/sys/nixos/rules.mk
+++ /dev/null
diff --git a/sys/rules.mk b/sys/rules.mk
deleted file mode 100644
index 6d1dfa5..0000000
--- a/sys/rules.mk
+++ /dev/null
@@ -1,41 +0,0 @@
-include share/push.mk
-
-# Iterate through subdirectory tree
-
-DIR := $(d)/cmd
-include $(DIR)/rules.mk
-
-DIR := $(d)/base
-include $(DIR)/rules.mk
-
-DIR := $(d)/libutf
-include $(DIR)/rules.mk
-
-DIR := $(d)/libfmt
-include $(DIR)/rules.mk
-
-DIR := $(d)/libmath
-include $(DIR)/rules.mk
-
-DIR := $(d)/libbio
-include $(DIR)/rules.mk
-
-# DIR := $(d)/libc
-# include $(DIR)/rules.mk
-
-# DIR := $(d)/libdraw
-# include $(DIR)/rules.mk
-
-# DIR := $(d)/libimage
-# include $(DIR)/rules.mk
-
-# DIR := $(d)/libfont
-# include $(DIR)/rules.mk
-
-# DIR := $(d)/libterm
-# include $(DIR)/rules.mk
-
-# DIR := $(d)/libsre
-# include $(DIR)/rules.mk
-
-include share/pop.mk