From ce05175372a9ddca1a225db0765ace1127a39293 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Fri, 12 Nov 2021 09:22:01 -0800 Subject: chore: simplified organizational structure --- sys/base/arg.c | 71 -- sys/base/bufio/dump.c | 66 - sys/base/bufio/get.c | 17 - sys/base/bufio/internal.h | 4 - sys/base/bufio/read.c | 36 - sys/base/bufio/reader.c | 28 - sys/base/bufio/refill.h | 28 - sys/base/bufio/rules.mk | 5 - sys/base/bufio/unget.c | 18 - sys/base/coro/coro.c | 43 - sys/base/coro/internal.h | 15 - sys/base/coro/rules.mk | 3 - sys/base/coro/unix_x64.s | 113 -- sys/base/error/errorf.c | 13 - sys/base/error/exits.c | 11 - sys/base/error/internal.h | 3 - sys/base/error/panicf.c | 16 - sys/base/error/rules.mk | 6 - sys/base/error/verrorf.c | 9 - sys/base/error/vpanicf.c | 11 - sys/base/flate/internal.h | 39 - sys/base/flate/read.c | 41 - sys/base/flate/reader.c | 59 - sys/base/flate/rules.mk | 6 - sys/base/flate/write.c | 48 - sys/base/flate/writer.c | 57 - sys/base/fs/internal.h | 18 - sys/base/fs/rules.mk | 3 - sys/base/fs/walk.c | 119 -- sys/base/fs/walker.c | 39 - sys/base/gz/flush.c | 7 - sys/base/gz/get.c | 17 - sys/base/gz/interface.c | 12 - sys/base/gz/internal.h | 6 - sys/base/gz/open.c | 13 - sys/base/gz/printf.c | 15 - sys/base/gz/put.c | 7 - sys/base/gz/putstring.c | 8 - sys/base/gz/read.c | 16 - sys/base/gz/rules.mk | 11 - sys/base/gz/seek.c | 7 - sys/base/gz/write.c | 7 - sys/base/io/fd.c | 7 - sys/base/io/flush.c | 7 - sys/base/io/get.c | 7 - sys/base/io/interface.c | 70 -- sys/base/io/internal.h | 4 - sys/base/io/open.c | 13 - sys/base/io/putbyte.c | 7 - sys/base/io/putstring.c | 7 - sys/base/io/read.c | 7 - sys/base/io/readln.c | 12 - sys/base/io/rules.mk | 14 - sys/base/io/seek.c | 7 - sys/base/io/stat.c | 7 - sys/base/io/tell.c | 7 - sys/base/io/unget.c | 7 - sys/base/io/write.c | 7 - sys/base/mem/arena.c | 119 -- sys/base/mem/buffer.c | 45 - sys/base/mem/interface.c | 36 - sys/base/mem/internal.h | 4 - sys/base/mem/rules.mk | 5 - sys/base/mem/set64.c | 13 - sys/base/mmap/internal.h | 5 - sys/base/mmap/mmap.c | 39 - sys/base/mmap/rules.mk | 2 - sys/base/os/basename.c | 10 - sys/base/os/exists.c | 7 - sys/base/os/internal.h | 4 - sys/base/os/rules.mk | 4 - sys/base/os/sep.c | 14 - sys/base/rng/base.c | 24 - sys/base/rng/bernoulli.c | 7 - sys/base/rng/exponential.c | 11 - sys/base/rng/internal.h | 19 - sys/base/rng/normal.c | 77 -- sys/base/rng/poisson.c | 126 -- sys/base/rng/random.c | 33 - sys/base/rng/rules.mk | 7 - sys/base/rules.mk | 36 - sys/base/sort/double.c | 12 - sys/base/sort/float.c | 12 - sys/base/sort/int.c | 12 - sys/base/sort/int16.c | 12 - sys/base/sort/int32.c | 12 - sys/base/sort/int64.c | 12 - sys/base/sort/int8.c | 12 - sys/base/sort/internal.h | 5 - sys/base/sort/rules.mk | 14 - sys/base/sort/string.c | 12 - sys/base/sort/uint.c | 12 - sys/base/sort/uint16.c | 12 - sys/base/sort/uint32.c | 12 - sys/base/sort/uint64.c | 12 - sys/base/sort/uint8.c | 12 - sys/base/string/append.c | 53 - sys/base/string/appendf.c | 31 - sys/base/string/clear.c | 9 - sys/base/string/copyn.c | 11 - sys/base/string/equals.c | 12 - sys/base/string/find.c | 11 - sys/base/string/fit.c | 20 - sys/base/string/free.c | 8 - sys/base/string/grow.c | 33 - sys/base/string/internal.h | 12 - sys/base/string/join.c | 16 - sys/base/string/len.c | 17 - sys/base/string/lower.c | 12 - sys/base/string/make.c | 53 - sys/base/string/makef.c | 25 - sys/base/string/read.c | 12 - sys/base/string/replace.c | 26 - sys/base/string/rules.mk | 19 - sys/base/string/split.c | 39 - sys/base/string/upper.c | 12 - sys/base/test.c | 170 --- sys/cmd/cc/ast.c | 2139 ------------------------------- sys/cmd/cc/bits.c | 114 -- sys/cmd/cc/cc.c | 409 ------ sys/cmd/cc/cc.h | 806 ------------ sys/cmd/cc/lex.c | 873 ------------- sys/cmd/cc/pp.c | 1125 ----------------- sys/cmd/cc/rules.mk | 23 - sys/cmd/cc/scratch.c | 7 - sys/cmd/cc/util.c | 21 - sys/cmd/dwm/LICENSE | 37 - sys/cmd/dwm/client.c | 657 ---------- sys/cmd/dwm/config.h | 141 --- sys/cmd/dwm/drw.c | 376 ------ sys/cmd/dwm/dwm.c | 1185 ------------------ sys/cmd/dwm/dwm.h | 384 ------ sys/cmd/dwm/hook.c | 489 -------- sys/cmd/dwm/rules.mk | 28 - sys/cmd/dwm/util.c | 66 - sys/cmd/filter/filter.c | 104 -- sys/cmd/filter/rules.mk | 13 - sys/cmd/ic/LICENSE | 23 - sys/cmd/ic/ic.1 | 100 -- sys/cmd/ic/ic.c | 878 ------------- sys/cmd/ic/rules.mk | 14 - sys/cmd/ic/strlcpy.c | 32 - sys/cmd/menu/LICENSE | 30 - sys/cmd/menu/config.h | 25 - sys/cmd/menu/drw.c | 428 ------- sys/cmd/menu/drw.h | 57 - sys/cmd/menu/menu.c | 765 ------------ sys/cmd/menu/menu.h | 40 - sys/cmd/menu/rules.mk | 25 - sys/cmd/menu/util.c | 30 - sys/cmd/rc/code.c | 277 ----- sys/cmd/rc/exec.c | 1267 ------------------- sys/cmd/rc/exec.h | 47 - sys/cmd/rc/input.c | 1679 ------------------------- sys/cmd/rc/io.c | 437 ------- sys/cmd/rc/job.c | 91 -- sys/cmd/rc/lex.c | 394 ------ sys/cmd/rc/main.c | 66 - sys/cmd/rc/parse.c | 2059 ------------------------------ sys/cmd/rc/parse.h | 141 --- sys/cmd/rc/prompt.c | 36 - sys/cmd/rc/rc.h | 263 ---- sys/cmd/rc/rules.mk | 31 - sys/cmd/rc/syntax.y | 147 --- sys/cmd/rc/sys.c | 137 -- sys/cmd/rc/tree.c | 111 -- sys/cmd/rc/util.c | 65 - sys/cmd/rc/var.c | 336 ----- sys/cmd/rc/wait.c | 247 ---- sys/cmd/rules.mk | 38 - sys/cmd/term/LICENSE | 34 - sys/cmd/term/config.h | 474 ------- sys/cmd/term/hb.c | 147 --- sys/cmd/term/nonspacing.h | 89 -- sys/cmd/term/rules.mk | 24 - sys/cmd/term/term.c | 2417 ------------------------------------ sys/cmd/term/term.h | 316 ----- sys/cmd/term/term.info | 250 ---- sys/cmd/term/util.c | 30 - sys/cmd/term/wide.h | 65 - sys/cmd/term/x.c | 2070 ------------------------------ sys/cmd/walk/rules.mk | 13 - sys/cmd/walk/walk.c | 84 -- sys/cmd/wm/arg.c | 0 sys/cmd/wm/client.c | 274 ---- sys/cmd/wm/config.h | 70 -- sys/cmd/wm/input.c | 316 ----- sys/cmd/wm/layer.c | 107 -- sys/cmd/wm/main.c | 177 --- sys/cmd/wm/monitor.c | 386 ------ sys/cmd/wm/protocol/sync | 6 - sys/cmd/wm/render.c | 160 --- sys/cmd/wm/rules.mk | 61 - sys/cmd/wm/util.c | 99 -- sys/cmd/wm/wm.h | 350 ------ sys/cmd/wm/xdg.c | 118 -- sys/libbio/align.c | 178 --- sys/libbio/fasta.c | 393 ------ sys/libbio/newick.c | 414 ------ sys/libbio/phylo.c | 427 ------- sys/libbio/rules.mk | 28 - sys/libbio/simulate.c | 120 -- sys/libbio/test.c | 283 ----- sys/libc/rules.mk | 23 - sys/libc/stdio.c | 59 - sys/libc/string.c | 80 -- sys/libfmt/buffer.c | 60 - sys/libfmt/do.c | 730 ----------- sys/libfmt/esprint.c | 14 - sys/libfmt/float.c | 1077 ---------------- sys/libfmt/fprint.c | 14 - sys/libfmt/internal.h | 17 - sys/libfmt/locale.c | 16 - sys/libfmt/nsprint.c | 14 - sys/libfmt/open.c | 34 - sys/libfmt/print.c | 13 - sys/libfmt/rules.mk | 36 - sys/libfmt/sprint.c | 19 - sys/libfmt/test.c | 72 -- sys/libfmt/vesprint.c | 26 - sys/libfmt/vfprint.c | 19 - sys/libfmt/vnsprint.c | 26 - sys/libfmt/vprint.c | 19 - sys/libfmt/vwrite.c | 26 - sys/libfmt/write.c | 22 - sys/libmath/basic.c | 531 -------- sys/libmath/blas.c | 63 - sys/libmath/blas1.c | 58 - sys/libmath/blas1body | 215 ---- sys/libmath/blas2.c | 222 ---- sys/libmath/blas2body | 256 ---- sys/libmath/blas3.c | 279 ----- sys/libmath/lapack.c | 0 sys/libmath/linalg.c | 63 - sys/libmath/loop.h | 114 -- sys/libmath/matrix.c | 176 --- sys/libmath/rules.mk | 24 - sys/libmath/test.c | 471 ------- sys/libsre/lex.c | 246 ---- sys/libsre/sre.h | 93 -- sys/libterm/term.c | 489 -------- sys/libterm/term.h | 270 ---- sys/libterm/window.c | 408 ------ sys/libutf/canfit.c | 23 - sys/libutf/decode.c | 98 -- sys/libutf/decodeprev.c | 60 - sys/libutf/encode.c | 69 - sys/libutf/find.c | 31 - sys/libutf/findlast.c | 32 - sys/libutf/internal.h | 38 - sys/libutf/len.c | 21 - sys/libutf/rules.mk | 76 -- sys/libutf/runelen.c | 8 - sys/libutf/vendor/common.c | 220 ---- sys/libutf/vendor/common.h | 46 - sys/libutf/vendor/mkgraphemedata.c | 24 - sys/libutf/vendor/mkrunetype.c | 388 ------ sys/libutf/vendor/mkrunewidth.c | 325 ----- sys/nixos/rules.mk | 0 sys/rules.mk | 41 - 260 files changed, 39871 deletions(-) delete mode 100644 sys/base/arg.c delete mode 100644 sys/base/bufio/dump.c delete mode 100644 sys/base/bufio/get.c delete mode 100644 sys/base/bufio/internal.h delete mode 100644 sys/base/bufio/read.c delete mode 100644 sys/base/bufio/reader.c delete mode 100644 sys/base/bufio/refill.h delete mode 100644 sys/base/bufio/rules.mk delete mode 100644 sys/base/bufio/unget.c delete mode 100644 sys/base/coro/coro.c delete mode 100644 sys/base/coro/internal.h delete mode 100644 sys/base/coro/rules.mk delete mode 100644 sys/base/coro/unix_x64.s delete mode 100644 sys/base/error/errorf.c delete mode 100644 sys/base/error/exits.c delete mode 100644 sys/base/error/internal.h delete mode 100644 sys/base/error/panicf.c delete mode 100644 sys/base/error/rules.mk delete mode 100644 sys/base/error/verrorf.c delete mode 100644 sys/base/error/vpanicf.c delete mode 100644 sys/base/flate/internal.h delete mode 100644 sys/base/flate/read.c delete mode 100644 sys/base/flate/reader.c delete mode 100644 sys/base/flate/rules.mk delete mode 100644 sys/base/flate/write.c delete mode 100644 sys/base/flate/writer.c delete mode 100644 sys/base/fs/internal.h delete mode 100644 sys/base/fs/rules.mk delete mode 100644 sys/base/fs/walk.c delete mode 100644 sys/base/fs/walker.c delete mode 100644 sys/base/gz/flush.c delete mode 100644 sys/base/gz/get.c delete mode 100644 sys/base/gz/interface.c delete mode 100644 sys/base/gz/internal.h delete mode 100644 sys/base/gz/open.c delete mode 100644 sys/base/gz/printf.c delete mode 100644 sys/base/gz/put.c delete mode 100644 sys/base/gz/putstring.c delete mode 100644 sys/base/gz/read.c delete mode 100644 sys/base/gz/rules.mk delete mode 100644 sys/base/gz/seek.c delete mode 100644 sys/base/gz/write.c delete mode 100644 sys/base/io/fd.c delete mode 100644 sys/base/io/flush.c delete mode 100644 sys/base/io/get.c delete mode 100644 sys/base/io/interface.c delete mode 100644 sys/base/io/internal.h delete mode 100644 sys/base/io/open.c delete mode 100644 sys/base/io/putbyte.c delete mode 100644 sys/base/io/putstring.c delete mode 100644 sys/base/io/read.c delete mode 100644 sys/base/io/readln.c delete mode 100644 sys/base/io/rules.mk delete mode 100644 sys/base/io/seek.c delete mode 100644 sys/base/io/stat.c delete mode 100644 sys/base/io/tell.c delete mode 100644 sys/base/io/unget.c delete mode 100644 sys/base/io/write.c delete mode 100644 sys/base/mem/arena.c delete mode 100644 sys/base/mem/buffer.c delete mode 100644 sys/base/mem/interface.c delete mode 100644 sys/base/mem/internal.h delete mode 100644 sys/base/mem/rules.mk delete mode 100644 sys/base/mem/set64.c delete mode 100644 sys/base/mmap/internal.h delete mode 100644 sys/base/mmap/mmap.c delete mode 100644 sys/base/mmap/rules.mk delete mode 100644 sys/base/os/basename.c delete mode 100644 sys/base/os/exists.c delete mode 100644 sys/base/os/internal.h delete mode 100644 sys/base/os/rules.mk delete mode 100644 sys/base/os/sep.c delete mode 100644 sys/base/rng/base.c delete mode 100644 sys/base/rng/bernoulli.c delete mode 100644 sys/base/rng/exponential.c delete mode 100644 sys/base/rng/internal.h delete mode 100644 sys/base/rng/normal.c delete mode 100644 sys/base/rng/poisson.c delete mode 100644 sys/base/rng/random.c delete mode 100644 sys/base/rng/rules.mk delete mode 100644 sys/base/rules.mk delete mode 100644 sys/base/sort/double.c delete mode 100644 sys/base/sort/float.c delete mode 100644 sys/base/sort/int.c delete mode 100644 sys/base/sort/int16.c delete mode 100644 sys/base/sort/int32.c delete mode 100644 sys/base/sort/int64.c delete mode 100644 sys/base/sort/int8.c delete mode 100644 sys/base/sort/internal.h delete mode 100644 sys/base/sort/rules.mk delete mode 100644 sys/base/sort/string.c delete mode 100644 sys/base/sort/uint.c delete mode 100644 sys/base/sort/uint16.c delete mode 100644 sys/base/sort/uint32.c delete mode 100644 sys/base/sort/uint64.c delete mode 100644 sys/base/sort/uint8.c delete mode 100644 sys/base/string/append.c delete mode 100644 sys/base/string/appendf.c delete mode 100644 sys/base/string/clear.c delete mode 100644 sys/base/string/copyn.c delete mode 100644 sys/base/string/equals.c delete mode 100644 sys/base/string/find.c delete mode 100644 sys/base/string/fit.c delete mode 100644 sys/base/string/free.c delete mode 100644 sys/base/string/grow.c delete mode 100644 sys/base/string/internal.h delete mode 100644 sys/base/string/join.c delete mode 100644 sys/base/string/len.c delete mode 100644 sys/base/string/lower.c delete mode 100644 sys/base/string/make.c delete mode 100644 sys/base/string/makef.c delete mode 100644 sys/base/string/read.c delete mode 100644 sys/base/string/replace.c delete mode 100644 sys/base/string/rules.mk delete mode 100644 sys/base/string/split.c delete mode 100644 sys/base/string/upper.c delete mode 100644 sys/base/test.c delete mode 100644 sys/cmd/cc/ast.c delete mode 100644 sys/cmd/cc/bits.c delete mode 100644 sys/cmd/cc/cc.c delete mode 100644 sys/cmd/cc/cc.h delete mode 100644 sys/cmd/cc/lex.c delete mode 100644 sys/cmd/cc/pp.c delete mode 100644 sys/cmd/cc/rules.mk delete mode 100644 sys/cmd/cc/scratch.c delete mode 100644 sys/cmd/cc/util.c delete mode 100644 sys/cmd/dwm/LICENSE delete mode 100644 sys/cmd/dwm/client.c delete mode 100644 sys/cmd/dwm/config.h delete mode 100644 sys/cmd/dwm/drw.c delete mode 100644 sys/cmd/dwm/dwm.c delete mode 100644 sys/cmd/dwm/dwm.h delete mode 100644 sys/cmd/dwm/hook.c delete mode 100644 sys/cmd/dwm/rules.mk delete mode 100644 sys/cmd/dwm/util.c delete mode 100644 sys/cmd/filter/filter.c delete mode 100644 sys/cmd/filter/rules.mk delete mode 100644 sys/cmd/ic/LICENSE delete mode 100644 sys/cmd/ic/ic.1 delete mode 100644 sys/cmd/ic/ic.c delete mode 100644 sys/cmd/ic/rules.mk delete mode 100644 sys/cmd/ic/strlcpy.c delete mode 100644 sys/cmd/menu/LICENSE delete mode 100644 sys/cmd/menu/config.h delete mode 100644 sys/cmd/menu/drw.c delete mode 100644 sys/cmd/menu/drw.h delete mode 100644 sys/cmd/menu/menu.c delete mode 100644 sys/cmd/menu/menu.h delete mode 100644 sys/cmd/menu/rules.mk delete mode 100644 sys/cmd/menu/util.c delete mode 100644 sys/cmd/rc/code.c delete mode 100644 sys/cmd/rc/exec.c delete mode 100644 sys/cmd/rc/exec.h delete mode 100644 sys/cmd/rc/input.c delete mode 100644 sys/cmd/rc/io.c delete mode 100644 sys/cmd/rc/job.c delete mode 100644 sys/cmd/rc/lex.c delete mode 100644 sys/cmd/rc/main.c delete mode 100644 sys/cmd/rc/parse.c delete mode 100644 sys/cmd/rc/parse.h delete mode 100644 sys/cmd/rc/prompt.c delete mode 100644 sys/cmd/rc/rc.h delete mode 100644 sys/cmd/rc/rules.mk delete mode 100644 sys/cmd/rc/syntax.y delete mode 100644 sys/cmd/rc/sys.c delete mode 100644 sys/cmd/rc/tree.c delete mode 100644 sys/cmd/rc/util.c delete mode 100644 sys/cmd/rc/var.c delete mode 100644 sys/cmd/rc/wait.c delete mode 100644 sys/cmd/rules.mk delete mode 100644 sys/cmd/term/LICENSE delete mode 100644 sys/cmd/term/config.h delete mode 100644 sys/cmd/term/hb.c delete mode 100644 sys/cmd/term/nonspacing.h delete mode 100644 sys/cmd/term/rules.mk delete mode 100644 sys/cmd/term/term.c delete mode 100644 sys/cmd/term/term.h delete mode 100644 sys/cmd/term/term.info delete mode 100644 sys/cmd/term/util.c delete mode 100644 sys/cmd/term/wide.h delete mode 100644 sys/cmd/term/x.c delete mode 100644 sys/cmd/walk/rules.mk delete mode 100644 sys/cmd/walk/walk.c delete mode 100644 sys/cmd/wm/arg.c delete mode 100644 sys/cmd/wm/client.c delete mode 100644 sys/cmd/wm/config.h delete mode 100644 sys/cmd/wm/input.c delete mode 100644 sys/cmd/wm/layer.c delete mode 100644 sys/cmd/wm/main.c delete mode 100644 sys/cmd/wm/monitor.c delete mode 100755 sys/cmd/wm/protocol/sync delete mode 100644 sys/cmd/wm/render.c delete mode 100644 sys/cmd/wm/rules.mk delete mode 100644 sys/cmd/wm/util.c delete mode 100644 sys/cmd/wm/wm.h delete mode 100644 sys/cmd/wm/xdg.c delete mode 100644 sys/libbio/align.c delete mode 100644 sys/libbio/fasta.c delete mode 100644 sys/libbio/newick.c delete mode 100644 sys/libbio/phylo.c delete mode 100644 sys/libbio/rules.mk delete mode 100644 sys/libbio/simulate.c delete mode 100644 sys/libbio/test.c delete mode 100644 sys/libc/rules.mk delete mode 100644 sys/libc/stdio.c delete mode 100644 sys/libc/string.c delete mode 100644 sys/libfmt/buffer.c delete mode 100644 sys/libfmt/do.c delete mode 100644 sys/libfmt/esprint.c delete mode 100644 sys/libfmt/float.c delete mode 100644 sys/libfmt/fprint.c delete mode 100644 sys/libfmt/internal.h delete mode 100644 sys/libfmt/locale.c delete mode 100644 sys/libfmt/nsprint.c delete mode 100644 sys/libfmt/open.c delete mode 100644 sys/libfmt/print.c delete mode 100644 sys/libfmt/rules.mk delete mode 100644 sys/libfmt/sprint.c delete mode 100644 sys/libfmt/test.c delete mode 100644 sys/libfmt/vesprint.c delete mode 100644 sys/libfmt/vfprint.c delete mode 100644 sys/libfmt/vnsprint.c delete mode 100644 sys/libfmt/vprint.c delete mode 100644 sys/libfmt/vwrite.c delete mode 100644 sys/libfmt/write.c delete mode 100644 sys/libmath/basic.c delete mode 100644 sys/libmath/blas.c delete mode 100644 sys/libmath/blas1.c delete mode 100644 sys/libmath/blas1body delete mode 100644 sys/libmath/blas2.c delete mode 100644 sys/libmath/blas2body delete mode 100644 sys/libmath/blas3.c delete mode 100644 sys/libmath/lapack.c delete mode 100644 sys/libmath/linalg.c delete mode 100644 sys/libmath/loop.h delete mode 100644 sys/libmath/matrix.c delete mode 100644 sys/libmath/rules.mk delete mode 100644 sys/libmath/test.c delete mode 100644 sys/libsre/lex.c delete mode 100644 sys/libsre/sre.h delete mode 100644 sys/libterm/term.c delete mode 100644 sys/libterm/term.h delete mode 100644 sys/libterm/window.c delete mode 100644 sys/libutf/canfit.c delete mode 100644 sys/libutf/decode.c delete mode 100644 sys/libutf/decodeprev.c delete mode 100644 sys/libutf/encode.c delete mode 100644 sys/libutf/find.c delete mode 100644 sys/libutf/findlast.c delete mode 100644 sys/libutf/internal.h delete mode 100644 sys/libutf/len.c delete mode 100644 sys/libutf/rules.mk delete mode 100644 sys/libutf/runelen.c delete mode 100644 sys/libutf/vendor/common.c delete mode 100644 sys/libutf/vendor/common.h delete mode 100644 sys/libutf/vendor/mkgraphemedata.c delete mode 100644 sys/libutf/vendor/mkrunetype.c delete mode 100644 sys/libutf/vendor/mkrunewidth.c delete mode 100644 sys/nixos/rules.mk delete mode 100644 sys/rules.mk (limited to 'sys') 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 -#include - -// 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 -#include 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 -#include - -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 -#include - 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 -#include - -#include - -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 -#include -#include -#include - -/* - * 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 -#include - -#include 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 -#include 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 -#include 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 -#include -#include 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 -#include 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 -#include - -#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=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); zs; - 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 -#include -#include 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 -#include - -#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 -#include -#include - -#include - -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 - -// ----------------------------------------------------------------------- -// 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 = "", - }, - .end = { - .col = 0, - .line = 0, - .path = "", - }, - }, - .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) ? "" : 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 -#include - -#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,"") \ - TOK(Aident,"") \ - TOK(Akeywd,"") \ - -#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 - -// ----------------------------------------------------------------------- -// 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 = ""; -} - -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 -© 2006-2009 Jukka Salmi -© 2006-2007 Sander van Dijk -© 2007-2011 Peter Hartlich -© 2007-2009 Szabolcs Nagy -© 2007-2009 Christof Musik -© 2007-2009 Premysl Hruby -© 2007-2008 Enno Gottox Boland -© 2008 Martin Hurton -© 2008 Neale Pickett -© 2009 Mate Nagy -© 2010-2016 Hiltjo Posthuma -© 2010-2012 Connor Lane Smith -© 2011 Christoph Lohmann <20h@r-36.net> -© 2015-2016 Quentin Rameau -© 2015-2016 Eric Pruitt -© 2016-2017 Markus Teich - -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[] = ""; -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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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 -#include - -#include -#include - -#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 -(C)opyright 2005-2006 Anselm R. Garbe -(C)opyright 2005-2011 Nico Golde - -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 " []" -mark yourself as away -.TP -.BI /j " #channel/nickname []" -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 -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -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 ] [-p ] " - "[-u ] [-n ] [-k ] " - "[-f ]\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 -#include - -/* - * 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 -© 2006-2008 Sander van Dijk -© 2006-2007 Michał Janeczek -© 2007 Kris Maglione -© 2009 Gottox -© 2009 Markus Schnalke -© 2009 Evan Gates -© 2010-2012 Connor Lane Smith -© 2014-2019 Hiltjo Posthuma -© 2015-2019 Quentin Rameau - -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 -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#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 - -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 -#include - -/* 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 -#include - -// ----------------------------------------------------------------------- -// 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 -#include - -// ----------------------------------------------------------------------- -// 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 . */ - -/* 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 (Val) -# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (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 - and (if available) are included - so that the code can choose integer types of a good width. */ - -#ifndef __PTRDIFF_MAX__ -# include /* INFRINGES ON USER NAME SPACE */ -# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* 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 - . */ -#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 /* 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 /* 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 /* 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 /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* 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 /* 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 /* 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 . */ - -/* 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 -#include -#include - -// ----------------------------------------------------------------------- -// 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=$( line cmds cmdsln body paren block ifbody casebody case assign epilog redir; -%type cmd basic executable nonkeyword keyword word words wordsnl atom; -%type Tfor Tin Twhile Tif Telse Tswitch Tcase Ttwiddle Tbang Tsubshell Tfunc; -%type 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 - -// ----------------------------------------------------------------------- -// 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; iwait.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; iwait.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 -© 2018 Devin J. Pohly -© 2014-2017 Quentin Rameau -© 2009-2012 Aurélien APTEL -© 2008-2017 Anselm R Garbe -© 2012-2017 Roberto E. Vargas Caballero -© 2012-2016 Christoph Lohmann <20h at r-36 dot net> -© 2013 Eon S. Jeon -© 2013 Alexander Sedov -© 2013 Mark Edgar -© 2013-2014 Eric Pruitt -© 2013 Michael Forney -© 2013-2014 Markus Teich -© 2014-2015 Laslo Hunhold - -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 -#include - -#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 -#include -#if defined(__linux) - #include -#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) - #include -#elif defined(__FreeBSD__) || defined(__DragonFly__) - #include -#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 blank char */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblank(csiescseq.arg[0]); - break; - case 'A': /* CUU -- Cursor Up */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); - break; - case 'B': /* CUD -- Cursor Down */ - case 'e': /* VPR --Cursor 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 more times */ - DEFAULT(csiescseq.arg[0], 1); - if (term.lastc) - while (csiescseq.arg[0]-- > 0) - tputc(term.lastc); - break; - case 'C': /* CUF -- Cursor Forward */ - case 'a': /* HPR -- Cursor Forward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x+csiescseq.arg[0], term.c.y); - break; - case 'D': /* CUB -- Cursor Backward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x-csiescseq.arg[0], term.c.y); - break; - case 'E': /* CNL -- Cursor Down and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y+csiescseq.arg[0]); - break; - case 'F': /* CPL -- Cursor 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 */ - case '`': /* HPA */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(csiescseq.arg[0]-1, term.c.y); - break; - case 'H': /* CUP -- Move to */ - 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 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 line up */ - DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); - break; - case 'T': /* SD -- Scroll line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0]); - break; - case 'L': /* IL -- Insert 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 lines */ - DEFAULT(csiescseq.arg[0], 1); - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase 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 char */ - DEFAULT(csiescseq.arg[0], 1); - tdeletechar(csiescseq.arg[0]); - break; - case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(-csiescseq.arg[0]); - break; - case 'd': /* VPA -- Move to */ - 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 -#include -#include - -#include -#include -#include -#include -#include - -#include - -// ----------------------------------------------------------------------- -// 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 '[' [[ [] [;]] []] */ -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 [[ [] [;]] ] 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 - -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 -#include - -#include -#include -#include -#include -#include -#include - -/* 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 Buttonmask for Button - 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 -#include - -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; ix, 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; idevice); - 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 -#include -#include -#include - -#define WLR_USE_UNSTABLE -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -// ----------------------------------------------------------------------- -// 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 -#include -#include -#include - -// ----------------------------------------------------------------------- -// 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 -#include -#include - -#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 -#include -#include - -// ----------------------------------------------------------------------- -// 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 -#include -#include -#include - -// ----------------------------------------------------------------------- -// 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 -#include -#include - -#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 -#include -#include - -#include - -// ----------------------------------------------------------------------- -// 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 -#include - -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 -#include - -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 - -#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=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, "", 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, "", 5, 5); - - if(io->flag & fmt·Prec){ - p = io->prec; - for(n=0; n 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 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<>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> 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 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; - n -= c<= (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<= (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>= 1; - } - frnorm(mid); - - /* compare */ - c = fpcmp(a, mid); - if(c > 0) { - c = 1; - for(i=0; i= 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 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 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 -#include -#include -#include - -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 -#include -#include -#include - -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 -#include -#include - -#include - -// 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 -#include -#include -#include -#include - -/* #include */ - -#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 -#include - -// ----------------------------------------------------------------------- -// 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 -#include -#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 -#include -#include - -#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 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 -#include -#include -#include - -// ----------------------------------------------------------------------- -// 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 -#include -#include - -/* TODO: replace (incrementally) with native C version! */ -#include -#include - -// ----------------------------------------------------------------------- -// 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 -#include -/* #include */ - -#include - -#include - -// ----------------------------------------------------------------------- -// 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 -#include - -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 -#include - -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 -#include - -#include -#include - -#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 -#include -#include - -/* - * 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 \n" - "#include \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 -#include -#include - -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 -#include -#include - -// ----------------------------------------------------------------------- -// main point of entry - -static -void -usage(void) -{ - fprintf(stderr, "usage: mkgraphemedata \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 \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 \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 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 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 -- cgit v1.2.1