aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-04-22 08:55:35 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-04-22 08:55:35 -0700
commit5d3642b8ef920316693031d2ea34b9def0b1abc5 (patch)
tree8100890ed5b2e4ecdbde09615e0820346ccc3f41
parente30f8b22069bec1a3fb68f089a9a7198671eb09a (diff)
chore: rm unfinished projects
-rw-r--r--.gitignore1
-rw-r--r--include/libbio.h31
-rw-r--r--rules.mk3
-rw-r--r--sys/cmd/calc/calc.c2285
-rw-r--r--sys/cmd/cat/cat.c40
-rw-r--r--sys/cmd/cat/rules.mk13
-rw-r--r--sys/cmd/cat/test.c8
-rw-r--r--sys/cmd/cp/cp.c75
-rw-r--r--sys/cmd/cp/rules.mk26
-rw-r--r--sys/cmd/dvtm/LICENSE23
-rw-r--r--sys/cmd/dvtm/config.h208
-rw-r--r--sys/cmd/dvtm/dvtm-editor.c183
-rw-r--r--sys/cmd/dvtm/dvtm.c1810
-rw-r--r--sys/cmd/dvtm/dvtm.h233
-rw-r--r--sys/cmd/dvtm/dvtm.info136
-rw-r--r--sys/cmd/dvtm/hook.c346
-rw-r--r--sys/cmd/dvtm/rules.mk33
-rw-r--r--sys/cmd/dvtm/vt.c2112
-rw-r--r--sys/cmd/dvtm/vt.h48
-rw-r--r--sys/cmd/echo/echo.c39
-rw-r--r--sys/cmd/echo/rules.mk13
-rw-r--r--sys/cmd/ls/ls.c36
-rw-r--r--sys/cmd/ls/rules.mk13
-rw-r--r--sys/cmd/mv/mv.c130
-rw-r--r--sys/cmd/mv/rules.mk13
-rw-r--r--sys/cmd/rc/code.c335
-rw-r--r--sys/cmd/rc/code.dep166
-rw-r--r--sys/cmd/rc/exec.c139
-rw-r--r--sys/cmd/rc/glob.c199
-rw-r--r--sys/cmd/rc/io.c446
-rw-r--r--sys/cmd/rc/lex.c417
-rw-r--r--sys/cmd/rc/main.c86
-rw-r--r--sys/cmd/rc/parse.c496
-rw-r--r--sys/cmd/rc/rc.h312
-rw-r--r--sys/cmd/rc/rules.mk22
-rw-r--r--sys/cmd/rc/simple.c13
-rw-r--r--sys/cmd/rc/tree.c144
-rw-r--r--sys/cmd/rc/util.c40
-rw-r--r--sys/cmd/rc/var.c129
-rw-r--r--sys/cmd/rc/word.c64
-rw-r--r--sys/cmd/rm/rm.c119
-rw-r--r--sys/cmd/rm/rules.mk13
-rw-r--r--sys/cmd/rules.mk27
-rw-r--r--sys/libbio/align.c24
-rw-r--r--sys/libbio/io/fasta.c360
-rw-r--r--sys/libbio/io/newick.c418
-rw-r--r--sys/libbio/io/rules.mk21
-rw-r--r--sys/libbio/rules.mk13
-rw-r--r--sys/libfont/test.c192
49 files changed, 30 insertions, 12023 deletions
diff --git a/.gitignore b/.gitignore
index 66f0063..0c4c0df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
bin/
lib/
+src/
build/
data/
share/
diff --git a/include/libbio.h b/include/libbio.h
index f802e22..7b28a55 100644
--- a/include/libbio.h
+++ b/include/libbio.h
@@ -52,32 +52,19 @@ error bio·writenewick(bio·Tree tree, io·Putter out, void*);
// Sequences
/* i/o */
-typedef struct bio·FastaReader bio·FastaReader;
-typedef struct bio·FastqReader bio·FastqReader;
+typedef struct bio·SeqReader bio·SeqReader;
+typedef struct bio·SeqWriter bio·SeqWriter;
typedef struct bio·Seq
{
int len;
- byte *name;
- byte *s;
- byte *q;
+ char *name;
+ char *s;
+ char *q;
} bio·Seq;
-bio·FastaReader *bio·openfasta(io·Reader stream, void *s, mem·Allocator heap, void *h);
-error bio·readfasta(bio·FastaReader *rdr, bio·Seq *seq);
-error bio·closefasta(bio·FastaReader *rdr);
+bio·SeqReader *bio·open(io·Reader io, void *rdr, mem·Allocator mem, void *heap);
+error bio·close(bio·SeqReader *rdr);
-bio·FastqReader *bio·openfastq(io·Reader stream, void *s, mem·Allocator heap, void *h);
-error bio·readfastq(bio·FastqReader *rdr, bio·Seq *seq);
-error bio·closefastq(bio·FastqReader *rdr);
-
-/* alignment */
-enum
-{
- aln·K = 20, // kmer size (k <= 32)
- aln·L = 3, // number of kmers / hash
- aln·N = 10, // number of hashes
-};
-
-error aln·sketch(byte *seq, int l, uint64 *phi[aln·N], int *locs[aln·N]);
-error aln·sort(uintptr len, int l, uint64 *vals);
+error bio·readfasta(bio·SeqReader *rdr, bio·Seq *seq);
+error bio·readfastq(bio·SeqReader *rdr, bio·Seq *seq);
diff --git a/rules.mk b/rules.mk
index 0004eb2..1a7b87a 100644
--- a/rules.mk
+++ b/rules.mk
@@ -23,6 +23,9 @@ UNTS :=
DIR := sys
include $(DIR)/rules.mk
+DIR := src
+include $(DIR)/rules.mk
+
# Generic rules
%.a: %.o
$(ARCHIVE)
diff --git a/sys/cmd/calc/calc.c b/sys/cmd/calc/calc.c
deleted file mode 100644
index dd99e37..0000000
--- a/sys/cmd/calc/calc.c
+++ /dev/null
@@ -1,2285 +0,0 @@
-#include <u.h>
-#include <libn.h>
-
-typedef void* pointer;
-
-#define div dcdiv
-
-#define FATAL 0
-#define NFATAL 1
-#define BLK sizeof(Blk)
-#define PTRSZ sizeof(int*)
-#define HEADSZ 1024
-#define STKSZ 100
-#define RDSKSZ 100
-#define TBLSZ 256
-#define ARRAYST 221
-#define MAXIND 2048
-#define NL 1
-#define NG 2
-#define NE 3
-#define length(p) ((p)->wt-(p)->beg)
-#define rewind(p) (p)->rd=(p)->beg
-#undef create
-#define create(p) (p)->rd = (p)->wt = (p)->beg
-#define fsfile(p) (p)->rd = (p)->wt
-#define truncate(p) (p)->wt = (p)->rd
-#define sfeof(p) (((p)->rd==(p)->wt)?1:0)
-#define sfbeg(p) (((p)->rd==(p)->beg)?1:0)
-#define sungetc(p,c) *(--(p)->rd)=c
-#define sgetc(p) (((p)->rd==(p)->wt)?-1:*(p)->rd++)
-#define skipc(p) {if((p)->rd<(p)->wt)(p)->rd++;}
-#define slookc(p) (((p)->rd==(p)->wt)?-1:*(p)->rd)
-#define sbackc(p) (((p)->rd==(p)->beg)?-1:*(--(p)->rd))
-#define backc(p) {if((p)->rd>(p)->beg) --(p)->rd;}
-#define sputc(p,c) {if((p)->wt==(p)->last)more(p);\
- *(p)->wt++ = c; }
-#define salterc(p,c) {if((p)->rd==(p)->last)more(p);\
- *(p)->rd++ = c;\
- if((p)->rd>(p)->wt)(p)->wt=(p)->rd;}
-#define sunputc(p) (*((p)->rd = --(p)->wt))
-#define sclobber(p) ((p)->rd = --(p)->wt)
-#define zero(p) for(pp=(p)->beg;pp<(p)->last;)\
- *pp++='\0'
-#define OUTC(x) {Bputc(&bout,x); if(--count == 0){Bprint(&bout,"\\\n"); count=ll;} }
-#define TEST2 {if((count -= 2) <=0){Bprint(&bout,"\\\n");count=ll;}}
-#define EMPTY if(stkerr != 0){Bprint(&bout,"stack empty\n"); continue; }
-#define EMPTYR(x) if(stkerr!=0){pushp(x);Bprint(&bout,"stack empty\n");continue;}
-#define EMPTYS if(stkerr != 0){Bprint(&bout,"stack empty\n"); return(1);}
-#define EMPTYSR(x) if(stkerr !=0){Bprint(&bout,"stack empty\n");pushp(x);return(1);}
-#define error(p) {Bprint(&bout,p); continue; }
-#define errorrt(p) {Bprint(&bout,p); return(1); }
-#define LASTFUN 026
-
-typedef struct Blk Blk;
-struct Blk
-{
- char *rd;
- char *wt;
- char *beg;
- char *last;
-};
-typedef struct Sym Sym;
-struct Sym
-{
- Sym *next;
- Blk *val;
-};
-typedef struct Wblk Wblk;
-struct Wblk
-{
- Blk **rdw;
- Blk **wtw;
- Blk **begw;
- Blk **lastw;
-};
-
-Blk *arg1, *arg2;
-uchar savk;
-int dbg;
-int ifile;
-Blk *scalptr, *basptr, *tenptr, *inbas;
-Blk *sqtemp, *chptr, *strptr, *divxyz;
-Blk *stack[STKSZ];
-Blk **stkptr,**stkbeg;
-Blk **stkend;
-Blk *hfree;
-int stkerr;
-int lastchar;
-Blk *readstk[RDSKSZ];
-Blk **readptr;
-Blk *rem;
-int k;
-Blk *irem;
-int skd,skr;
-int neg;
-Sym symlst[TBLSZ];
-Sym *stable[TBLSZ];
-Sym *sptr, *sfree;
-long rel;
-long nbytes;
-long all;
-long headmor;
-long obase;
-int fw,fw1,ll;
-void (*outdit)(Blk *p, int flg);
-int logo;
-int logten;
-int count;
-char *pp;
-char *dummy;
-long longest, maxsize, active;
-int lall, lrel, lcopy, lmore, lbytes;
-int inside;
-Biobuf bin;
-Biobuf bout;
-
-void main(int argc, char *argv[]);
-void commnds(void);
-Blk* readin(void);
-Blk* div(Blk *ddivd, Blk *ddivr);
-int dscale(void);
-Blk* removr(Blk *p, int n);
-Blk* dcsqrt(Blk *p);
-void init(int argc, char *argv[]);
-void onintr(void);
-void pushp(Blk *p);
-Blk* pop(void);
-Blk* readin(void);
-Blk* add0(Blk *p, int ct);
-Blk* mult(Blk *p, Blk *q);
-void chsign(Blk *p);
-int readc(void);
-void unreadc(char c);
-void binop(char c);
-void dcprint(Blk *hptr);
-Blk* dcexp(Blk *base, Blk *ex);
-Blk* getdec(Blk *p, int sc);
-void tenot(Blk *p, int sc);
-void oneot(Blk *p, int sc, char ch);
-void hexot(Blk *p, int flg);
-void bigot(Blk *p, int flg);
-Blk* add(Blk *a1, Blk *a2);
-int eqk(void);
-Blk* removc(Blk *p, int n);
-Blk* scalint(Blk *p);
-Blk* scale(Blk *p, int n);
-int subt(void);
-int command(void);
-int cond(char c);
-void load(void);
-#define log2 dclog2
-int log2(long n);
-Blk* salloc(int size);
-Blk* morehd(void);
-Blk* copy(Blk *hptr, int size);
-void sdump(char *s1, Blk *hptr);
-void seekc(Blk *hptr, int n);
-void salterwd(Blk *hptr, Blk *n);
-void more(Blk *hptr);
-void ospace(char *s);
-void garbage(char *s);
-void release(Blk *p);
-Blk* dcgetwd(Blk *p);
-void putwd(Blk *p, Blk *c);
-Blk* lookwd(Blk *p);
-int getstk(void);
-
-/********debug only**/
-void
-tpr(char *cp, Blk *bp)
-{
- print("%s-> ", cp);
- print("beg: %lx rd: %lx wt: %lx last: %lx\n", bp->beg, bp->rd,
- bp->wt, bp->last);
- for (cp = bp->beg; cp != bp->wt; cp++) {
- print("%d", *cp);
- if (cp != bp->wt-1)
- print("/");
- }
- print("\n");
-}
-/************/
-
-void
-main(int argc, char *argv[])
-{
- Binit(&bin, 0, OREAD);
- Binit(&bout, 1, OWRITE);
- init(argc,argv);
- commnds();
- exits(0);
-}
-
-void
-commnds(void)
-{
- Blk *p, *q, **ptr, *s, *t;
- long l;
- Sym *sp;
- int sk, sk1, sk2, c, sign, n, d;
-
- while(1) {
- Bflush(&bout);
- if(((c = readc())>='0' && c <= '9') ||
- (c>='A' && c <='F') || c == '.') {
- unreadc(c);
- p = readin();
- pushp(p);
- continue;
- }
- switch(c) {
- case ' ':
- case '\n':
- case -1:
- continue;
- case 'Y':
- sdump("stk",*stkptr);
- Bprint(&bout, "all %ld rel %ld headmor %ld\n",all,rel,headmor);
- Bprint(&bout, "nbytes %ld\n",nbytes);
- Bprint(&bout, "longest %ld active %ld maxsize %ld\n", longest,
- active, maxsize);
- Bprint(&bout, "new all %d rel %d copy %d more %d lbytes %d\n",
- lall, lrel, lcopy, lmore, lbytes);
- lall = lrel = lcopy = lmore = lbytes = 0;
- continue;
- case '_':
- p = readin();
- savk = sunputc(p);
- chsign(p);
- sputc(p,savk);
- pushp(p);
- continue;
- case '-':
- subt();
- continue;
- case '+':
- if(eqk() != 0)
- continue;
- binop('+');
- continue;
- case '*':
- arg1 = pop();
- EMPTY;
- arg2 = pop();
- EMPTYR(arg1);
- sk1 = sunputc(arg1);
- sk2 = sunputc(arg2);
- savk = sk1+sk2;
- binop('*');
- p = pop();
- if(savk>k && savk>sk1 && savk>sk2) {
- sclobber(p);
- sk = sk1;
- if(sk<sk2)
- sk = sk2;
- if(sk<k)
- sk = k;
- p = removc(p,savk-sk);
- savk = sk;
- sputc(p,savk);
- }
- pushp(p);
- continue;
- case '/':
- casediv:
- if(dscale() != 0)
- continue;
- binop('/');
- if(irem != 0)
- release(irem);
- release(rem);
- continue;
- case '%':
- if(dscale() != 0)
- continue;
- binop('/');
- p = pop();
- release(p);
- if(irem == 0) {
- sputc(rem,skr+k);
- pushp(rem);
- continue;
- }
- p = add0(rem,skd-(skr+k));
- q = add(p,irem);
- release(p);
- release(irem);
- sputc(q,skd);
- pushp(q);
- continue;
- case 'v':
- p = pop();
- EMPTY;
- savk = sunputc(p);
- if(length(p) == 0) {
- sputc(p,savk);
- pushp(p);
- continue;
- }
- if(sbackc(p)<0) {
- error("sqrt of neg number\n");
- }
- if(k<savk)
- n = savk;
- else {
- n = k*2-savk;
- savk = k;
- }
- arg1 = add0(p,n);
- arg2 = dcsqrt(arg1);
- sputc(arg2,savk);
- pushp(arg2);
- continue;
-
- case '^':
- neg = 0;
- arg1 = pop();
- EMPTY;
- if(sunputc(arg1) != 0)
- error("exp not an integer\n");
- arg2 = pop();
- EMPTYR(arg1);
- if(sfbeg(arg1) == 0 && sbackc(arg1)<0) {
- neg++;
- chsign(arg1);
- }
- if(length(arg1)>=3) {
- error("exp too big\n");
- }
- savk = sunputc(arg2);
- p = dcexp(arg2,arg1);
- release(arg2);
- rewind(arg1);
- c = sgetc(arg1);
- if(c == -1)
- c = 0;
- else
- if(sfeof(arg1) == 0)
- c = sgetc(arg1)*100 + c;
- d = c*savk;
- release(arg1);
- /* if(neg == 0) { removed to fix -exp bug*/
- if(k>=savk)
- n = k;
- else
- n = savk;
- if(n<d) {
- q = removc(p,d-n);
- sputc(q,n);
- pushp(q);
- } else {
- sputc(p,d);
- pushp(p);
- }
- /* } else { this is disaster for exp <-127 */
- /* sputc(p,d); */
- /* pushp(p); */
- /* } */
- if(neg == 0)
- continue;
- p = pop();
- q = salloc(2);
- sputc(q,1);
- sputc(q,0);
- pushp(q);
- pushp(p);
- goto casediv;
- case 'z':
- p = salloc(2);
- n = stkptr - stkbeg;
- if(n >= 100) {
- sputc(p,n/100);
- n %= 100;
- }
- sputc(p,n);
- sputc(p,0);
- pushp(p);
- continue;
- case 'Z':
- p = pop();
- EMPTY;
- n = (length(p)-1)<<1;
- fsfile(p);
- backc(p);
- if(sfbeg(p) == 0) {
- if((c = sbackc(p))<0) {
- n -= 2;
- if(sfbeg(p) == 1)
- n++;
- else {
- if((c = sbackc(p)) == 0)
- n++;
- else
- if(c > 90)
- n--;
- }
- } else
- if(c < 10)
- n--;
- }
- release(p);
- q = salloc(1);
- if(n >= 100) {
- sputc(q,n%100);
- n /= 100;
- }
- sputc(q,n);
- sputc(q,0);
- pushp(q);
- continue;
- case 'i':
- p = pop();
- EMPTY;
- p = scalint(p);
- release(inbas);
- inbas = p;
- continue;
- case 'I':
- p = copy(inbas,length(inbas)+1);
- sputc(p,0);
- pushp(p);
- continue;
- case 'o':
- p = pop();
- EMPTY;
- p = scalint(p);
- sign = 0;
- n = length(p);
- q = copy(p,n);
- fsfile(q);
- l = c = sbackc(q);
- if(n != 1) {
- if(c<0) {
- sign = 1;
- chsign(q);
- n = length(q);
- fsfile(q);
- l = c = sbackc(q);
- }
- if(n != 1) {
- while(sfbeg(q) == 0)
- l = l*100+sbackc(q);
- }
- }
- logo = log2(l);
- obase = l;
- release(basptr);
- if(sign == 1)
- obase = -l;
- basptr = p;
- outdit = bigot;
- if(n == 1 && sign == 0) {
- if(c <= 16) {
- outdit = hexot;
- fw = 1;
- fw1 = 0;
- ll = 70;
- release(q);
- continue;
- }
- }
- n = 0;
- if(sign == 1)
- n++;
- p = salloc(1);
- sputc(p,-1);
- t = add(p,q);
- n += length(t)*2;
- fsfile(t);
- if(sbackc(t)>9)
- n++;
- release(t);
- release(q);
- release(p);
- fw = n;
- fw1 = n-1;
- ll = 70;
- if(fw>=ll)
- continue;
- ll = (70/fw)*fw;
- continue;
- case 'O':
- p = copy(basptr,length(basptr)+1);
- sputc(p,0);
- pushp(p);
- continue;
- case '[':
- n = 0;
- p = salloc(0);
- for(;;) {
- if((c = readc()) == ']') {
- if(n == 0)
- break;
- n--;
- }
- sputc(p,c);
- if(c == '[')
- n++;
- }
- pushp(p);
- continue;
- case 'k':
- p = pop();
- EMPTY;
- p = scalint(p);
- if(length(p)>1) {
- error("scale too big\n");
- }
- rewind(p);
- k = 0;
- if(!sfeof(p))
- k = sgetc(p);
- release(scalptr);
- scalptr = p;
- continue;
- case 'K':
- p = copy(scalptr,length(scalptr)+1);
- sputc(p,0);
- pushp(p);
- continue;
- case 'X':
- p = pop();
- EMPTY;
- fsfile(p);
- n = sbackc(p);
- release(p);
- p = salloc(2);
- sputc(p,n);
- sputc(p,0);
- pushp(p);
- continue;
- case 'Q':
- p = pop();
- EMPTY;
- if(length(p)>2) {
- error("Q?\n");
- }
- rewind(p);
- if((c = sgetc(p))<0) {
- error("neg Q\n");
- }
- release(p);
- while(c-- > 0) {
- if(readptr == &readstk[0]) {
- error("readstk?\n");
- }
- if(*readptr != 0)
- release(*readptr);
- readptr--;
- }
- continue;
- case 'q':
- if(readptr <= &readstk[1])
- exits(0);
- if(*readptr != 0)
- release(*readptr);
- readptr--;
- if(*readptr != 0)
- release(*readptr);
- readptr--;
- continue;
- case 'f':
- if(stkptr == &stack[0])
- Bprint(&bout,"empty stack\n");
- else {
- for(ptr = stkptr; ptr > &stack[0];) {
- dcprint(*ptr--);
- }
- }
- continue;
- case 'p':
- if(stkptr == &stack[0])
- Bprint(&bout,"empty stack\n");
- else {
- dcprint(*stkptr);
- }
- continue;
- case 'P':
- p = pop();
- EMPTY;
- sputc(p,0);
- Bprint(&bout,"%s",p->beg);
- release(p);
- continue;
- case 'd':
- if(stkptr == &stack[0]) {
- Bprint(&bout,"empty stack\n");
- continue;
- }
- q = *stkptr;
- n = length(q);
- p = copy(*stkptr,n);
- pushp(p);
- continue;
- case 'c':
- while(stkerr == 0) {
- p = pop();
- if(stkerr == 0)
- release(p);
- }
- continue;
- case 'S':
- if(stkptr == &stack[0]) {
- error("save: args\n");
- }
- c = getstk() & 0377;
- sptr = stable[c];
- sp = stable[c] = sfree;
- sfree = sfree->next;
- if(sfree == 0)
- goto sempty;
- sp->next = sptr;
- p = pop();
- EMPTY;
- if(c >= ARRAYST) {
- q = copy(p,length(p)+PTRSZ);
- for(n = 0;n < PTRSZ;n++) {
- sputc(q,0);
- }
- release(p);
- p = q;
- }
- sp->val = p;
- continue;
- sempty:
- error("symbol table overflow\n");
- case 's':
- if(stkptr == &stack[0]) {
- error("save:args\n");
- }
- c = getstk() & 0377;
- sptr = stable[c];
- if(sptr != 0) {
- p = sptr->val;
- if(c >= ARRAYST) {
- rewind(p);
- while(sfeof(p) == 0)
- release(dcgetwd(p));
- }
- release(p);
- } else {
- sptr = stable[c] = sfree;
- sfree = sfree->next;
- if(sfree == 0)
- goto sempty;
- sptr->next = 0;
- }
- p = pop();
- sptr->val = p;
- continue;
- case 'l':
- load();
- continue;
- case 'L':
- c = getstk() & 0377;
- sptr = stable[c];
- if(sptr == 0) {
- error("L?\n");
- }
- stable[c] = sptr->next;
- sptr->next = sfree;
- sfree = sptr;
- p = sptr->val;
- if(c >= ARRAYST) {
- rewind(p);
- while(sfeof(p) == 0) {
- q = dcgetwd(p);
- if(q != 0)
- release(q);
- }
- }
- pushp(p);
- continue;
- case ':':
- p = pop();
- EMPTY;
- q = scalint(p);
- fsfile(q);
- c = 0;
- if((sfbeg(q) == 0) && ((c = sbackc(q))<0)) {
- error("neg index\n");
- }
- if(length(q)>2) {
- error("index too big\n");
- }
- if(sfbeg(q) == 0)
- c = c*100+sbackc(q);
- if(c >= MAXIND) {
- error("index too big\n");
- }
- release(q);
- n = getstk() & 0377;
- sptr = stable[n];
- if(sptr == 0) {
- sptr = stable[n] = sfree;
- sfree = sfree->next;
- if(sfree == 0)
- goto sempty;
- sptr->next = 0;
- p = salloc((c+PTRSZ)*PTRSZ);
- zero(p);
- } else {
- p = sptr->val;
- if(length(p)-PTRSZ < c*PTRSZ) {
- q = copy(p,(c+PTRSZ)*PTRSZ);
- release(p);
- p = q;
- }
- }
- seekc(p,c*PTRSZ);
- q = lookwd(p);
- if(q!=0)
- release(q);
- s = pop();
- EMPTY;
- salterwd(p, s);
- sptr->val = p;
- continue;
- case ';':
- p = pop();
- EMPTY;
- q = scalint(p);
- fsfile(q);
- c = 0;
- if((sfbeg(q) == 0) && ((c = sbackc(q))<0)) {
- error("neg index\n");
- }
- if(length(q)>2) {
- error("index too big\n");
- }
- if(sfbeg(q) == 0)
- c = c*100+sbackc(q);
- if(c >= MAXIND) {
- error("index too big\n");
- }
- release(q);
- n = getstk() & 0377;
- sptr = stable[n];
- if(sptr != 0){
- p = sptr->val;
- if(length(p)-PTRSZ >= c*PTRSZ) {
- seekc(p,c*PTRSZ);
- s = dcgetwd(p);
- if(s != 0) {
- q = copy(s,length(s));
- pushp(q);
- continue;
- }
- }
- }
- q = salloc(1); /*so uninitialized array elt prints as 0*/
- sputc(q, 0);
- pushp(q);
- continue;
- case 'x':
- execute:
- p = pop();
- EMPTY;
- if((readptr != &readstk[0]) && (*readptr != 0)) {
- if((*readptr)->rd == (*readptr)->wt)
- release(*readptr);
- else {
- if(readptr++ == &readstk[RDSKSZ]) {
- error("nesting depth\n");
- }
- }
- } else
- readptr++;
- *readptr = p;
- if(p != 0)
- rewind(p);
- else {
- if((c = readc()) != '\n')
- unreadc(c);
- }
- continue;
- case '?':
- if(++readptr == &readstk[RDSKSZ]) {
- error("nesting depth\n");
- }
- *readptr = 0;
- fsave = curfile;
- curfile = &bin;
- while((c = readc()) == '!')
- command();
- p = salloc(0);
- sputc(p,c);
- while((c = readc()) != '\n') {
- sputc(p,c);
- if(c == '\\')
- sputc(p,readc());
- }
- curfile = fsave;
- *readptr = p;
- continue;
- case '!':
- if(command() == 1)
- goto execute;
- continue;
- case '<':
- case '>':
- case '=':
- if(cond(c) == 1)
- goto execute;
- continue;
- default:
- Bprint(&bout,"%o is unimplemented\n",c);
- }
- }
-}
-
-Blk*
-div(Blk *ddivd, Blk *ddivr)
-{
- int divsign, remsign, offset, divcarry,
- carry, dig, magic, d, dd, under, first;
- long c, td, cc;
- Blk *ps, *px, *p, *divd, *divr;
-
- dig = 0;
- under = 0;
- divcarry = 0;
- rem = 0;
- p = salloc(0);
- if(length(ddivr) == 0) {
- pushp(ddivr);
- Bprint(&bout,"divide by 0\n");
- return(p);
- }
- divsign = remsign = first = 0;
- divr = ddivr;
- fsfile(divr);
- if(sbackc(divr) == -1) {
- divr = copy(ddivr,length(ddivr));
- chsign(divr);
- divsign = ~divsign;
- }
- divd = copy(ddivd,length(ddivd));
- fsfile(divd);
- if(sfbeg(divd) == 0 && sbackc(divd) == -1) {
- chsign(divd);
- divsign = ~divsign;
- remsign = ~remsign;
- }
- offset = length(divd) - length(divr);
- if(offset < 0)
- goto ddone;
- seekc(p,offset+1);
- sputc(divd,0);
- magic = 0;
- fsfile(divr);
- c = sbackc(divr);
- if(c < 10)
- magic++;
- c = c * 100 + (sfbeg(divr)?0:sbackc(divr));
- if(magic>0){
- c = (c * 100 +(sfbeg(divr)?0:sbackc(divr)))*2;
- c /= 25;
- }
- while(offset >= 0) {
- first++;
- fsfile(divd);
- td = sbackc(divd) * 100;
- dd = sfbeg(divd)?0:sbackc(divd);
- td = (td + dd) * 100;
- dd = sfbeg(divd)?0:sbackc(divd);
- td = td + dd;
- cc = c;
- if(offset == 0)
- td++;
- else
- cc++;
- if(magic != 0)
- td = td<<3;
- dig = td/cc;
- under=0;
- if(td%cc < 8 && dig > 0 && magic) {
- dig--;
- under=1;
- }
- rewind(divr);
- rewind(divxyz);
- carry = 0;
- while(sfeof(divr) == 0) {
- d = sgetc(divr)*dig+carry;
- carry = d / 100;
- salterc(divxyz,d%100);
- }
- salterc(divxyz,carry);
- rewind(divxyz);
- seekc(divd,offset);
- carry = 0;
- while(sfeof(divd) == 0) {
- d = slookc(divd);
- d = d-(sfeof(divxyz)?0:sgetc(divxyz))-carry;
- carry = 0;
- if(d < 0) {
- d += 100;
- carry = 1;
- }
- salterc(divd,d);
- }
- divcarry = carry;
- backc(p);
- salterc(p,dig);
- backc(p);
- fsfile(divd);
- d=sbackc(divd);
- if((d != 0) && /*!divcarry*/ (offset != 0)) {
- d = sbackc(divd) + 100;
- salterc(divd,d);
- }
- if(--offset >= 0)
- divd->wt--;
- }
- if(under) { /* undershot last - adjust*/
- px = copy(divr,length(divr)); /*11/88 don't corrupt ddivr*/
- chsign(px);
- ps = add(px,divd);
- fsfile(ps);
- if(length(ps) > 0 && sbackc(ps) < 0) {
- release(ps); /*only adjust in really undershot*/
- } else {
- release(divd);
- salterc(p, dig+1);
- divd=ps;
- }
- }
- if(divcarry != 0) {
- salterc(p,dig-1);
- salterc(divd,-1);
- ps = add(divr,divd);
- release(divd);
- divd = ps;
- }
-
- rewind(p);
- divcarry = 0;
- while(sfeof(p) == 0){
- d = slookc(p)+divcarry;
- divcarry = 0;
- if(d >= 100){
- d -= 100;
- divcarry = 1;
- }
- salterc(p,d);
- }
- if(divcarry != 0)salterc(p,divcarry);
- fsfile(p);
- while(sfbeg(p) == 0) {
- if(sbackc(p) != 0)
- break;
- truncate(p);
- }
- if(divsign < 0)
- chsign(p);
- fsfile(divd);
- while(sfbeg(divd) == 0) {
- if(sbackc(divd) != 0)
- break;
- truncate(divd);
- }
-ddone:
- if(remsign<0)
- chsign(divd);
- if(divr != ddivr)
- release(divr);
- rem = divd;
- return(p);
-}
-
-int
-dscale(void)
-{
- Blk *dd, *dr, *r;
- int c;
-
- dr = pop();
- EMPTYS;
- dd = pop();
- EMPTYSR(dr);
- fsfile(dd);
- skd = sunputc(dd);
- fsfile(dr);
- skr = sunputc(dr);
- if(sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)) {
- sputc(dr,skr);
- pushp(dr);
- Bprint(&bout,"divide by 0\n");
- return(1);
- }
- if(sfbeg(dd) == 1 || (sfbeg(dd) == 0 && sbackc(dd) == 0)) {
- sputc(dd,skd);
- pushp(dd);
- return(1);
- }
- c = k-skd+skr;
- if(c < 0)
- r = removr(dd,-c);
- else {
- r = add0(dd,c);
- irem = 0;
- }
- arg1 = r;
- arg2 = dr;
- savk = k;
- return(0);
-}
-
-Blk*
-removr(Blk *p, int n)
-{
- int nn, neg;
- Blk *q, *s, *r;
-
- fsfile(p);
- neg = sbackc(p);
- if(neg < 0)
- chsign(p);
- rewind(p);
- nn = (n+1)/2;
- q = salloc(nn);
- while(n>1) {
- sputc(q,sgetc(p));
- n -= 2;
- }
- r = salloc(2);
- while(sfeof(p) == 0)
- sputc(r,sgetc(p));
- release(p);
- if(n == 1){
- s = div(r,tenptr);
- release(r);
- rewind(rem);
- if(sfeof(rem) == 0)
- sputc(q,sgetc(rem));
- release(rem);
- if(neg < 0){
- chsign(s);
- chsign(q);
- irem = q;
- return(s);
- }
- irem = q;
- return(s);
- }
- if(neg < 0) {
- chsign(r);
- chsign(q);
- irem = q;
- return(r);
- }
- irem = q;
- return(r);
-}
-
-Blk*
-dcsqrt(Blk *p)
-{
- Blk *t, *r, *q, *s;
- int c, n, nn;
-
- n = length(p);
- fsfile(p);
- c = sbackc(p);
- if((n&1) != 1)
- c = c*100+(sfbeg(p)?0:sbackc(p));
- n = (n+1)>>1;
- r = salloc(n);
- zero(r);
- seekc(r,n);
- nn=1;
- while((c -= nn)>=0)
- nn+=2;
- c=(nn+1)>>1;
- fsfile(r);
- backc(r);
- if(c>=100) {
- c -= 100;
- salterc(r,c);
- sputc(r,1);
- } else
- salterc(r,c);
- for(;;){
- q = div(p,r);
- s = add(q,r);
- release(q);
- release(rem);
- q = div(s,sqtemp);
- release(s);
- release(rem);
- s = copy(r,length(r));
- chsign(s);
- t = add(s,q);
- release(s);
- fsfile(t);
- nn = sfbeg(t)?0:sbackc(t);
- if(nn>=0)
- break;
- release(r);
- release(t);
- r = q;
- }
- release(t);
- release(q);
- release(p);
- return(r);
-}
-
-Blk*
-dcexp(Blk *base, Blk *ex)
-{
- Blk *r, *e, *p, *e1, *t, *cp;
- int temp, c, n;
-
- r = salloc(1);
- sputc(r,1);
- p = copy(base,length(base));
- e = copy(ex,length(ex));
- fsfile(e);
- if(sfbeg(e) != 0)
- goto edone;
- temp=0;
- c = sbackc(e);
- if(c<0) {
- temp++;
- chsign(e);
- }
- while(length(e) != 0) {
- e1=div(e,sqtemp);
- release(e);
- e = e1;
- n = length(rem);
- release(rem);
- if(n != 0) {
- e1=mult(p,r);
- release(r);
- r = e1;
- }
- t = copy(p,length(p));
- cp = mult(p,t);
- release(p);
- release(t);
- p = cp;
- }
- if(temp != 0) {
- if((c = length(base)) == 0) {
- goto edone;
- }
- if(c>1)
- create(r);
- else {
- rewind(base);
- if((c = sgetc(base))<=1) {
- create(r);
- sputc(r,c);
- } else
- create(r);
- }
- }
-edone:
- release(p);
- release(e);
- return(r);
-}
-
-void
-init(int argc, char *argv[])
-{
- Sym *sp;
- Dir *d;
-
- ARGBEGIN {
- default:
- dbg = 1;
- break;
- } ARGEND
- ifile = 1;
- curfile = &bin;
- if(*argv){
- d = dirstat(*argv);
- if(d == nil) {
- fprint(2, "dc: can't open file %s\n", *argv);
- exits("open");
- }
- if(d->mode & DMDIR) {
- fprint(2, "dc: file %s is a directory\n", *argv);
- exits("open");
- }
- free(d);
- if((curfile = Bopen(*argv, OREAD)) == 0) {
- fprint(2,"dc: can't open file %s\n", *argv);
- exits("open");
- }
- }
-/* dummy = malloc(0); *//* prepare for garbage-collection */
- scalptr = salloc(1);
- sputc(scalptr,0);
- basptr = salloc(1);
- sputc(basptr,10);
- obase=10;
- logten=log2(10L);
- ll=70;
- fw=1;
- fw1=0;
- tenptr = salloc(1);
- sputc(tenptr,10);
- obase=10;
- inbas = salloc(1);
- sputc(inbas,10);
- sqtemp = salloc(1);
- sputc(sqtemp,2);
- chptr = salloc(0);
- strptr = salloc(0);
- divxyz = salloc(0);
- stkbeg = stkptr = &stack[0];
- stkend = &stack[STKSZ];
- stkerr = 0;
- readptr = &readstk[0];
- k=0;
- sp = sptr = &symlst[0];
- while(sptr < &symlst[TBLSZ-1]) {
- sptr->next = ++sp;
- sptr++;
- }
- sptr->next=0;
- sfree = &symlst[0];
-}
-
-void
-pushp(Blk *p)
-{
- if(stkptr == stkend) {
- Bprint(&bout,"out of stack space\n");
- return;
- }
- stkerr=0;
- *++stkptr = p;
- return;
-}
-
-Blk*
-pop(void)
-{
- if(stkptr == stack) {
- stkerr=1;
- return(0);
- }
- return(*stkptr--);
-}
-
-Blk*
-readin(void)
-{
- Blk *p, *q;
- int dp, dpct, c;
-
- dp = dpct=0;
- p = salloc(0);
- for(;;){
- c = readc();
- switch(c) {
- case '.':
- if(dp != 0)
- goto gotnum;
- dp++;
- continue;
- case '\\':
- readc();
- continue;
- default:
- if(c >= 'A' && c <= 'F')
- c = c - 'A' + 10;
- else
- if(c >= '0' && c <= '9')
- c -= '0';
- else
- goto gotnum;
- if(dp != 0) {
- if(dpct >= 99)
- continue;
- dpct++;
- }
- create(chptr);
- if(c != 0)
- sputc(chptr,c);
- q = mult(p,inbas);
- release(p);
- p = add(chptr,q);
- release(q);
- }
- }
-gotnum:
- unreadc(c);
- if(dp == 0) {
- sputc(p,0);
- return(p);
- } else {
- q = scale(p,dpct);
- return(q);
- }
-}
-
-/*
- * returns pointer to struct with ct 0's & p
- */
-Blk*
-add0(Blk *p, int ct)
-{
- Blk *q, *t;
-
- q = salloc(length(p)+(ct+1)/2);
- while(ct>1) {
- sputc(q,0);
- ct -= 2;
- }
- rewind(p);
- while(sfeof(p) == 0) {
- sputc(q,sgetc(p));
- }
- release(p);
- if(ct == 1) {
- t = mult(tenptr,q);
- release(q);
- return(t);
- }
- return(q);
-}
-
-Blk*
-mult(Blk *p, Blk *q)
-{
- Blk *mp, *mq, *mr;
- int sign, offset, carry;
- int cq, cp, mt, mcr;
-
- offset = sign = 0;
- fsfile(p);
- mp = p;
- if(sfbeg(p) == 0) {
- if(sbackc(p)<0) {
- mp = copy(p,length(p));
- chsign(mp);
- sign = ~sign;
- }
- }
- fsfile(q);
- mq = q;
- if(sfbeg(q) == 0){
- if(sbackc(q)<0) {
- mq = copy(q,length(q));
- chsign(mq);
- sign = ~sign;
- }
- }
- mr = salloc(length(mp)+length(mq));
- zero(mr);
- rewind(mq);
- while(sfeof(mq) == 0) {
- cq = sgetc(mq);
- rewind(mp);
- rewind(mr);
- mr->rd += offset;
- carry=0;
- while(sfeof(mp) == 0) {
- cp = sgetc(mp);
- mcr = sfeof(mr)?0:slookc(mr);
- mt = cp*cq + carry + mcr;
- carry = mt/100;
- salterc(mr,mt%100);
- }
- offset++;
- if(carry != 0) {
- mcr = sfeof(mr)?0:slookc(mr);
- salterc(mr,mcr+carry);
- }
- }
- if(sign < 0) {
- chsign(mr);
- }
- if(mp != p)
- release(mp);
- if(mq != q)
- release(mq);
- return(mr);
-}
-
-void
-chsign(Blk *p)
-{
- int carry;
- char ct;
-
- carry=0;
- rewind(p);
- while(sfeof(p) == 0) {
- ct=100-slookc(p)-carry;
- carry=1;
- if(ct>=100) {
- ct -= 100;
- carry=0;
- }
- salterc(p,ct);
- }
- if(carry != 0) {
- sputc(p,-1);
- fsfile(p);
- backc(p);
- ct = sbackc(p);
- if(ct == 99 /*&& !sfbeg(p)*/) {
- truncate(p);
- sputc(p,-1);
- }
- } else{
- fsfile(p);
- ct = sbackc(p);
- if(ct == 0)
- truncate(p);
- }
- return;
-}
-
-int
-readc(void)
-{
-loop:
- if((readptr != &readstk[0]) && (*readptr != 0)) {
- if(sfeof(*readptr) == 0)
- return(lastchar = sgetc(*readptr));
- release(*readptr);
- readptr--;
- goto loop;
- }
- lastchar = Bgetc(curfile);
- if(lastchar != -1)
- return(lastchar);
- if(readptr != &readptr[0]) {
- readptr--;
- if(*readptr == 0)
- curfile = &bin;
- goto loop;
- }
- if(curfile != &bin) {
- Bterm(curfile);
- curfile = &bin;
- goto loop;
- }
- exits(0);
- return 0; /* shut up ken */
-}
-
-void
-unreadc(char c)
-{
-
- if((readptr != &readstk[0]) && (*readptr != 0)) {
- sungetc(*readptr,c);
- } else
- Bungetc(curfile);
- return;
-}
-
-void
-binop(char c)
-{
- Blk *r;
-
- r = 0;
- switch(c) {
- case '+':
- r = add(arg1,arg2);
- break;
- case '*':
- r = mult(arg1,arg2);
- break;
- case '/':
- r = div(arg1,arg2);
- break;
- }
- release(arg1);
- release(arg2);
- sputc(r,savk);
- pushp(r);
-}
-
-void
-dcprint(Blk *hptr)
-{
- Blk *p, *q, *dec;
- int dig, dout, ct, sc;
-
- rewind(hptr);
- while(sfeof(hptr) == 0) {
- if(sgetc(hptr)>99) {
- rewind(hptr);
- while(sfeof(hptr) == 0) {
- Bprint(&bout,"%c",sgetc(hptr));
- }
- Bprint(&bout,"\n");
- return;
- }
- }
- fsfile(hptr);
- sc = sbackc(hptr);
- if(sfbeg(hptr) != 0) {
- Bprint(&bout,"0\n");
- return;
- }
- count = ll;
- p = copy(hptr,length(hptr));
- sclobber(p);
- fsfile(p);
- if(sbackc(p)<0) {
- chsign(p);
- OUTC('-');
- }
- if((obase == 0) || (obase == -1)) {
- oneot(p,sc,'d');
- return;
- }
- if(obase == 1) {
- oneot(p,sc,'1');
- return;
- }
- if(obase == 10) {
- tenot(p,sc);
- return;
- }
- /* sleazy hack to scale top of stack - divide by 1 */
- pushp(p);
- sputc(p, sc);
- p=salloc(0);
- create(p);
- sputc(p, 1);
- sputc(p, 0);
- pushp(p);
- if(dscale() != 0)
- return;
- p = div(arg1, arg2);
- release(arg1);
- release(arg2);
- sc = savk;
-
- create(strptr);
- dig = logten*sc;
- dout = ((dig/10) + dig) / logo;
- dec = getdec(p,sc);
- p = removc(p,sc);
- while(length(p) != 0) {
- q = div(p,basptr);
- release(p);
- p = q;
- (*outdit)(rem,0);
- }
- release(p);
- fsfile(strptr);
- while(sfbeg(strptr) == 0)
- OUTC(sbackc(strptr));
- if(sc == 0) {
- release(dec);
- Bprint(&bout,"\n");
- return;
- }
- create(strptr);
- OUTC('.');
- ct=0;
- do {
- q = mult(basptr,dec);
- release(dec);
- dec = getdec(q,sc);
- p = removc(q,sc);
- (*outdit)(p,1);
- } while(++ct < dout);
- release(dec);
- rewind(strptr);
- while(sfeof(strptr) == 0)
- OUTC(sgetc(strptr));
- Bprint(&bout,"\n");
-}
-
-Blk*
-getdec(Blk *p, int sc)
-{
- int cc;
- Blk *q, *t, *s;
-
- rewind(p);
- if(length(p)*2 < sc) {
- q = copy(p,length(p));
- return(q);
- }
- q = salloc(length(p));
- while(sc >= 1) {
- sputc(q,sgetc(p));
- sc -= 2;
- }
- if(sc != 0) {
- t = mult(q,tenptr);
- s = salloc(cc = length(q));
- release(q);
- rewind(t);
- while(cc-- > 0)
- sputc(s,sgetc(t));
- sputc(s,0);
- release(t);
- t = div(s,tenptr);
- release(s);
- release(rem);
- return(t);
- }
- return(q);
-}
-
-void
-tenot(Blk *p, int sc)
-{
- int c, f;
-
- fsfile(p);
- f=0;
- while((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)) {
- c = sbackc(p);
- if((c<10) && (f == 1))
- Bprint(&bout,"0%d",c);
- else
- Bprint(&bout,"%d",c);
- f=1;
- TEST2;
- }
- if(sc == 0) {
- Bprint(&bout,"\n");
- release(p);
- return;
- }
- if((p->rd-p->beg)*2 > sc) {
- c = sbackc(p);
- Bprint(&bout,"%d.",c/10);
- TEST2;
- OUTC(c%10 +'0');
- sc--;
- } else {
- OUTC('.');
- }
- while(sc>(p->rd-p->beg)*2) {
- OUTC('0');
- sc--;
- }
- while(sc > 1) {
- c = sbackc(p);
- if(c<10)
- Bprint(&bout,"0%d",c);
- else
- Bprint(&bout,"%d",c);
- sc -= 2;
- TEST2;
- }
- if(sc == 1) {
- OUTC(sbackc(p)/10 +'0');
- }
- Bprint(&bout,"\n");
- release(p);
-}
-
-void
-oneot(Blk *p, int sc, char ch)
-{
- Blk *q;
-
- q = removc(p,sc);
- create(strptr);
- sputc(strptr,-1);
- while(length(q)>0) {
- p = add(strptr,q);
- release(q);
- q = p;
- OUTC(ch);
- }
- release(q);
- Bprint(&bout,"\n");
-}
-
-void
-hexot(Blk *p, int flg)
-{
- int c;
-
- USED(flg);
- rewind(p);
- if(sfeof(p) != 0) {
- sputc(strptr,'0');
- release(p);
- return;
- }
- c = sgetc(p);
- release(p);
- if(c >= 16) {
- Bprint(&bout,"hex digit > 16");
- return;
- }
- sputc(strptr,c<10?c+'0':c-10+'a');
-}
-
-void
-bigot(Blk *p, int flg)
-{
- Blk *t, *q;
- int neg, l;
-
- if(flg == 1) {
- t = salloc(0);
- l = 0;
- } else {
- t = strptr;
- l = length(strptr)+fw-1;
- }
- neg=0;
- if(length(p) != 0) {
- fsfile(p);
- if(sbackc(p)<0) {
- neg=1;
- chsign(p);
- }
- while(length(p) != 0) {
- q = div(p,tenptr);
- release(p);
- p = q;
- rewind(rem);
- sputc(t,sfeof(rem)?'0':sgetc(rem)+'0');
- release(rem);
- }
- }
- release(p);
- if(flg == 1) {
- l = fw1-length(t);
- if(neg != 0) {
- l--;
- sputc(strptr,'-');
- }
- fsfile(t);
- while(l-- > 0)
- sputc(strptr,'0');
- while(sfbeg(t) == 0)
- sputc(strptr,sbackc(t));
- release(t);
- } else {
- l -= length(strptr);
- while(l-- > 0)
- sputc(strptr,'0');
- if(neg != 0) {
- sclobber(strptr);
- sputc(strptr,'-');
- }
- }
- sputc(strptr,' ');
-}
-
-Blk*
-add(Blk *a1, Blk *a2)
-{
- Blk *p;
- int carry, n, size, c, n1, n2;
-
- size = length(a1)>length(a2)?length(a1):length(a2);
- p = salloc(size);
- rewind(a1);
- rewind(a2);
- carry=0;
- while(--size >= 0) {
- n1 = sfeof(a1)?0:sgetc(a1);
- n2 = sfeof(a2)?0:sgetc(a2);
- n = n1 + n2 + carry;
- if(n>=100) {
- carry=1;
- n -= 100;
- } else
- if(n<0) {
- carry = -1;
- n += 100;
- } else
- carry = 0;
- sputc(p,n);
- }
- if(carry != 0)
- sputc(p,carry);
- fsfile(p);
- if(sfbeg(p) == 0) {
- c = 0;
- while(sfbeg(p) == 0 && (c = sbackc(p)) == 0)
- ;
- if(c != 0)
- salterc(p,c);
- truncate(p);
- }
- fsfile(p);
- if(sfbeg(p) == 0 && sbackc(p) == -1) {
- while((c = sbackc(p)) == 99) {
- if(c == -1)
- break;
- }
- skipc(p);
- salterc(p,-1);
- truncate(p);
- }
- return(p);
-}
-
-int
-eqk(void)
-{
- Blk *p, *q;
- int skp, skq;
-
- p = pop();
- EMPTYS;
- q = pop();
- EMPTYSR(p);
- skp = sunputc(p);
- skq = sunputc(q);
- if(skp == skq) {
- arg1=p;
- arg2=q;
- savk = skp;
- return(0);
- }
- if(skp < skq) {
- savk = skq;
- p = add0(p,skq-skp);
- } else {
- savk = skp;
- q = add0(q,skp-skq);
- }
- arg1=p;
- arg2=q;
- return(0);
-}
-
-Blk*
-removc(Blk *p, int n)
-{
- Blk *q, *r;
-
- rewind(p);
- while(n>1) {
- skipc(p);
- n -= 2;
- }
- q = salloc(2);
- while(sfeof(p) == 0)
- sputc(q,sgetc(p));
- if(n == 1) {
- r = div(q,tenptr);
- release(q);
- release(rem);
- q = r;
- }
- release(p);
- return(q);
-}
-
-Blk*
-scalint(Blk *p)
-{
- int n;
-
- n = sunputc(p);
- p = removc(p,n);
- return(p);
-}
-
-Blk*
-scale(Blk *p, int n)
-{
- Blk *q, *s, *t;
-
- t = add0(p,n);
- q = salloc(1);
- sputc(q,n);
- s = dcexp(inbas,q);
- release(q);
- q = div(t,s);
- release(t);
- release(s);
- release(rem);
- sputc(q,n);
- return(q);
-}
-
-int
-subt(void)
-{
- arg1=pop();
- EMPTYS;
- savk = sunputc(arg1);
- chsign(arg1);
- sputc(arg1,savk);
- pushp(arg1);
- if(eqk() != 0)
- return(1);
- binop('+');
- return(0);
-}
-
-int
-command(void)
-{
- char line[100], *sl;
- int pid, p, c;
-
- switch(c = readc()) {
- case '<':
- return(cond(NL));
- case '>':
- return(cond(NG));
- case '=':
- return(cond(NE));
- default:
- sl = line;
- *sl++ = c;
- while((c = readc()) != '\n')
- *sl++ = c;
- *sl = 0;
- if((pid = fork()) == 0) {
- execl("/bin/rc","rc","-c",line,0);
- exits("shell");
- }
- for(;;) {
- if((p = waitpid()) < 0)
- break;
- if(p== pid)
- break;
- }
- Bprint(&bout,"!\n");
- return(0);
- }
-}
-
-int
-cond(char c)
-{
- Blk *p;
- int cc;
-
- if(subt() != 0)
- return(1);
- p = pop();
- sclobber(p);
- if(length(p) == 0) {
- release(p);
- if(c == '<' || c == '>' || c == NE) {
- getstk();
- return(0);
- }
- load();
- return(1);
- }
- if(c == '='){
- release(p);
- getstk();
- return(0);
- }
- if(c == NE) {
- release(p);
- load();
- return(1);
- }
- fsfile(p);
- cc = sbackc(p);
- release(p);
- if((cc<0 && (c == '<' || c == NG)) ||
- (cc >0) && (c == '>' || c == NL)) {
- getstk();
- return(0);
- }
- load();
- return(1);
-}
-
-void
-load(void)
-{
- int c;
- Blk *p, *q, *t, *s;
-
- c = getstk() & 0377;
- sptr = stable[c];
- if(sptr != 0) {
- p = sptr->val;
- if(c >= ARRAYST) {
- q = salloc(length(p));
- rewind(p);
- while(sfeof(p) == 0) {
- s = dcgetwd(p);
- if(s == 0) {
- putwd(q, (Blk*)0);
- } else {
- t = copy(s,length(s));
- putwd(q,t);
- }
- }
- pushp(q);
- } else {
- q = copy(p,length(p));
- pushp(q);
- }
- } else {
- q = salloc(1);
- if(c <= LASTFUN) {
- Bprint(&bout,"function %c undefined\n",c+'a'-1);
- sputc(q,'c');
- sputc(q,'0');
- sputc(q,' ');
- sputc(q,'1');
- sputc(q,'Q');
- }
- else
- sputc(q,0);
- pushp(q);
- }
-}
-
-int
-log2(long n)
-{
- int i;
-
- if(n == 0)
- return(0);
- i=31;
- if(n<0)
- return(i);
- while((n= n<<1) >0)
- i--;
- return i-1;
-}
-
-Blk*
-salloc(int size)
-{
- Blk *hdr;
- char *ptr;
-
- all++;
- lall++;
- if(all - rel > active)
- active = all - rel;
- nbytes += size;
- lbytes += size;
- if(nbytes >maxsize)
- maxsize = nbytes;
- if(size > longest)
- longest = size;
- ptr = malloc((unsigned)size);
- if(ptr == 0){
- garbage("salloc");
- if((ptr = malloc((unsigned)size)) == 0)
- ospace("salloc");
- }
- if((hdr = hfree) == 0)
- hdr = morehd();
- hfree = (Blk *)hdr->rd;
- hdr->rd = hdr->wt = hdr->beg = ptr;
- hdr->last = ptr+size;
- return(hdr);
-}
-
-Blk*
-morehd(void)
-{
- Blk *h, *kk;
-
- headmor++;
- nbytes += HEADSZ;
- hfree = h = (Blk *)malloc(HEADSZ);
- if(hfree == 0) {
- garbage("morehd");
- if((hfree = h = (Blk*)malloc(HEADSZ)) == 0)
- ospace("headers");
- }
- kk = h;
- while(h<hfree+(HEADSZ/BLK))
- (h++)->rd = (char*)++kk;
- (h-1)->rd=0;
- return(hfree);
-}
-
-Blk*
-copy(Blk *hptr, int size)
-{
- Blk *hdr;
- unsigned sz;
- char *ptr;
-
- all++;
- lall++;
- lcopy++;
- nbytes += size;
- lbytes += size;
- if(size > longest)
- longest = size;
- if(size > maxsize)
- maxsize = size;
- sz = length(hptr);
- ptr = malloc(size);
- if(ptr == 0) {
- Bprint(&bout,"copy size %d\n",size);
- ospace("copy");
- }
- memmove(ptr, hptr->beg, sz);
- memset(ptr+sz, 0, size-sz);
- if((hdr = hfree) == 0)
- hdr = morehd();
- hfree = (Blk *)hdr->rd;
- hdr->rd = hdr->beg = ptr;
- hdr->last = ptr+size;
- hdr->wt = ptr+sz;
- ptr = hdr->wt;
- while(ptr<hdr->last)
- *ptr++ = '\0';
- return(hdr);
-}
-
-void
-sdump(char *s1, Blk *hptr)
-{
- char *p;
-
- Bprint(&bout,"%s %lx rd %lx wt %lx beg %lx last %lx\n",
- s1,hptr,hptr->rd,hptr->wt,hptr->beg,hptr->last);
- p = hptr->beg;
- while(p < hptr->wt)
- Bprint(&bout,"%d ",*p++);
- Bprint(&bout,"\n");
-}
-
-void
-seekc(Blk *hptr, int n)
-{
- char *nn,*p;
-
- nn = hptr->beg+n;
- if(nn > hptr->last) {
- nbytes += nn - hptr->last;
- if(nbytes > maxsize)
- maxsize = nbytes;
- lbytes += nn - hptr->last;
- if(n > longest)
- longest = n;
-/* free(hptr->beg); */
- p = realloc(hptr->beg, n);
- if(p == 0) {
-/* hptr->beg = realloc(hptr->beg, hptr->last-hptr->beg);
-** garbage("seekc");
-** if((p = realloc(hptr->beg, n)) == 0)
-*/ ospace("seekc");
- }
- hptr->beg = p;
- hptr->wt = hptr->last = hptr->rd = p+n;
- return;
- }
- hptr->rd = nn;
- if(nn>hptr->wt)
- hptr->wt = nn;
-}
-
-void
-salterwd(Blk *ahptr, Blk *n)
-{
- Wblk *hptr;
-
- hptr = (Wblk*)ahptr;
- if(hptr->rdw == hptr->lastw)
- more(ahptr);
- *hptr->rdw++ = n;
- if(hptr->rdw > hptr->wtw)
- hptr->wtw = hptr->rdw;
-}
-
-void
-more(Blk *hptr)
-{
- unsigned size;
- char *p;
-
- if((size=(hptr->last-hptr->beg)*2) == 0)
- size=2;
- nbytes += size/2;
- if(nbytes > maxsize)
- maxsize = nbytes;
- if(size > longest)
- longest = size;
- lbytes += size/2;
- lmore++;
-/* free(hptr->beg);*/
- p = realloc(hptr->beg, size);
-
- if(p == 0) {
-/* hptr->beg = realloc(hptr->beg, (hptr->last-hptr->beg));
-** garbage("more");
-** if((p = realloc(hptr->beg,size)) == 0)
-*/ ospace("more");
- }
- hptr->rd = p + (hptr->rd - hptr->beg);
- hptr->wt = p + (hptr->wt - hptr->beg);
- hptr->beg = p;
- hptr->last = p+size;
-}
-
-void
-ospace(char *s)
-{
- Bprint(&bout,"out of space: %s\n",s);
- Bprint(&bout,"all %ld rel %ld headmor %ld\n",all,rel,headmor);
- Bprint(&bout,"nbytes %ld\n",nbytes);
- sdump("stk",*stkptr);
- abort();
-}
-
-void
-garbage(char *s)
-{
- USED(s);
-}
-
-void
-release(Blk *p)
-{
- rel++;
- lrel++;
- nbytes -= p->last - p->beg;
- p->rd = (char*)hfree;
- hfree = p;
- free(p->beg);
-}
-
-Blk*
-dcgetwd(Blk *p)
-{
- Wblk *wp;
-
- wp = (Wblk*)p;
- if(wp->rdw == wp->wtw)
- return(0);
- return(*wp->rdw++);
-}
-
-void
-putwd(Blk *p, Blk *c)
-{
- Wblk *wp;
-
- wp = (Wblk*)p;
- if(wp->wtw == wp->lastw)
- more(p);
- *wp->wtw++ = c;
-}
-
-Blk*
-lookwd(Blk *p)
-{
- Wblk *wp;
-
- wp = (Wblk*)p;
- if(wp->rdw == wp->wtw)
- return(0);
- return(*wp->rdw);
-}
-
-int
-getstk(void)
-{
- int n;
- uchar c;
-
- c = readc();
- if(c != '<')
- return c;
- n = 0;
- while(1) {
- c = readc();
- if(c == '>')
- break;
- n = n*10+c-'0';
- }
- return n;
-}
diff --git a/sys/cmd/cat/cat.c b/sys/cmd/cat/cat.c
deleted file mode 100644
index a82cfe4..0000000
--- a/sys/cmd/cat/cat.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <u.h>
-#include <libn.h>
-
-static
-void
-cat(Stream *f, byte *name)
-{
- long n;
- static byte buf[8192];
-
- while(n = io·read(f, 1, arrlen(buf), buf), n > 0) {
- if (io·write(stdout, 1, n, buf) != n) {
- panicf("failed to write while copying stream '%s'", name);
- }
- }
-
- if (n < 0) {
- panicf("failed to read from buffer '%s'", name);
- }
-}
-
-
-int
-main(int argc, char *argv[])
-{
- int i;
- Stream *f;
-
- if (argc == 1) {
- f = stdin;
- cat(f, "<stdin>");
- } else for (i = 1; i < argc; i++) {
- if (f = io·open(argv[i], "r"), f == nil)
- panicf("can't open %s", argv[i]);
- cat(f, argv[i]);
- io·close(f);
- }
-
- exit(0);
-}
diff --git a/sys/cmd/cat/rules.mk b/sys/cmd/cat/rules.mk
deleted file mode 100644
index 27eac26..0000000
--- a/sys/cmd/cat/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := $(d)/cat.c
-BINS_$(d) := $(d)/cat
-
-include share/paths.mk
-
-$(BINS_$(d)): TCLIBS := $(OBJ_DIR)/libn/libn.a
-$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/libn/libn.a
- $(LINK)
-
-include share/pop.mk
diff --git a/sys/cmd/cat/test.c b/sys/cmd/cat/test.c
deleted file mode 100644
index c1b850e..0000000
--- a/sys/cmd/cat/test.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <u.h>
-#include <libn.h>
-
-error
-main()
-{
- return 0;
-}
diff --git a/sys/cmd/cp/cp.c b/sys/cmd/cp/cp.c
deleted file mode 100644
index dfe2922..0000000
--- a/sys/cmd/cp/cp.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <u.h>
-#include <libn.h>
-
-static struct Flags {
- uchar a : 1;
- uchar f : 1;
- uchar p : 1;
- uchar v : 1;
- uchar r : 1;
-} flag;
-static char follow;
-
-static
-int
-cp(char *from, char *to)
-{
-
-}
-
-/*
- * P -> never dereference
- * L -> dereference links
- * H -> dereference links on the first level
- */
-static
-void
-usage(void)
-{
- fputs("usage: cp [-afpv] [-[r|R] [-H | -L | -P]] source ... dest", stderr);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- io·Stat info;
-
- ARGBEGIN {
- case 'a':
- follow = 'P';
- flag.a = flag.p = flag.r = 1;
- break;
- case 'f':
- flag.f = 1;
- break;
- case 'p':
- flag.p = 1;
- break;
- case 'r':
- /* fallthrough */
- case 'R':
- flag.r = 1;
- break;
- case 'H':
- case 'L':
- case 'P':
- follow = ARGC();
- break;
- default:
- usage();
- } ARGEND;
-
- if (argc < 2)
- usage();
-
- if (!follow)
- follow = flag.r ? 'P' : 'L';
-
- if (argc > 2) {
- if (stat(argv[argc-1], &info) < 0)
- errorf("stat %s: %s", argv[argc-1], strerror(errno));
- if (!S_ISDIR(info.st_mode))
- errorf("%s: is not a directory", argv[argc-1]);
- }
-}
diff --git a/sys/cmd/cp/rules.mk b/sys/cmd/cp/rules.mk
deleted file mode 100644
index 500b001..0000000
--- a/sys/cmd/cp/rules.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-include share/push.mk
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) :=
-LIBS_$(d) :=
-BINS_$(d) :=
-TSTS_$(d) :=
-
-include share/paths.mk
-
-# Local rules
-# $(LIBS_$(d)) = TCFLAGS :=
-# $(LIBS_$(d)) = TCINCS :=
-# $(LIBS_$(d)) = TCLIBS :=
-
-$(LIBS_$(d)): $(OBJS_$(d))
- $(ARCHIVE)
-
-$(BINS_$(d)): $(OBJS_$(d))
- $(LINK)
-
-$(UNTS_$(d)): $(TOBJS_$(d)) $(LIBS_$(d))
- $(LINK)
-
-include share/pop.mk
diff --git a/sys/cmd/dvtm/LICENSE b/sys/cmd/dvtm/LICENSE
deleted file mode 100644
index 8afe5bf..0000000
--- a/sys/cmd/dvtm/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-MIT/X Consortium License
-
- (c) 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
- (c) 2007-2016 Marc André Tanner <mat at brain-dump dot org>
- (c) 2020-???? Nicholas Noll <nbnoll at eml dot cc>
-
-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/dvtm/config.h b/sys/cmd/dvtm/config.h
deleted file mode 100644
index ec70596..0000000
--- a/sys/cmd/dvtm/config.h
+++ /dev/null
@@ -1,208 +0,0 @@
-#define VERSION "1.0"
-
-/* valid curses attributes are listed below they can be ORed
- *
- * A_NORMAL Normal display (no highlight)
- * A_STANDOUT Best highlighting mode of the terminal.
- * A_UNDERLINE Underlining
- * A_REVERSE Reverse video
- * A_BLINK Blinking
- * A_DIM Half bright
- * A_BOLD Extra bright or bold
- * A_PROTECT Protected mode
- * A_INVIS Invisible or blank mode
- */
-
-enum {
- DEFAULT,
- BLUE,
- GREEN,
-};
-
-static Color colors[] = {
- [DEFAULT] = { .fg = -1, .bg = -1, .fg256 = -1, .bg256 = -1, },
- [BLUE] = { .fg = COLOR_BLUE, .bg = -1, .fg256 = 68, .bg256 = -1, },
- [GREEN] = { .fg = COLOR_GREEN, .bg = -1, .fg256 = 65, .bg256 = -1, },
-};
-
-#define COLOR(c) COLOR_PAIR(colors[c].pair)
-/* curses attributes for the currently focused window */
-#define SELECTED_ATTR (COLOR(GREEN) | A_NORMAL)
-/* curses attributes for normal (not selected) windows */
-#define NORMAL_ATTR (COLOR(DEFAULT) | A_NORMAL)
-/* curses attributes for a window with pending urgent flag */
-#define URGENT_ATTR NORMAL_ATTR
-/* curses attributes for the status bar */
-#define BAR_ATTR (COLOR(GREEN) | A_NORMAL)
-/* characters for beginning and end of status bar message */
-#define BAR_BEGIN '['
-#define BAR_END ']'
-/* status bar (command line option -s) position */
-#define BAR_POS BAR_TOP /* BAR_BOTTOM, BAR_OFF */
-/* whether status bar should be hidden if only one client exists */
-#define BAR_AUTOHIDE false
-/* master width factor [0.1 .. 0.9] */
-#define MFACT 0.5
-/* number of clients in master area */
-#define NMASTER 1
-/* scroll back buffer size in lines */
-#define SCROLL_HISTORY 500
-/* printf format string for the tag in the status bar */
-#define TAG_SYMBOL "[%s]"
-/* curses attributes for the currently selected tags */
-#define TAG_SEL (COLOR(GREEN) | A_BOLD)
-/* curses attributes for not selected tags which contain no windows */
-#define TAG_NORMAL (COLOR(DEFAULT) | A_NORMAL)
-/* curses attributes for not selected tags which contain windows */
-#define TAG_OCCUPIED (COLOR(GREEN) | A_NORMAL)
-/* curses attributes for not selected tags which with urgent windows */
-#define TAG_URGENT (COLOR(GREEN) | A_NORMAL | A_BLINK)
-
-static const char tags[][8] = { "1", "2", "3", "4", "5" };
-
-/* by default the first layout entry is used */
-static Layout layouts[] = {
- { "[]=", tile },
- { "+++", grid },
- { "TTT", bstack },
- { "[ ]", fullscreen },
-};
-
-#define MOD ('`')
-#define TAGKEYS(KEY,TAG) \
- { { MOD, 'v', KEY, }, { view, { tags[TAG] } } }, \
- { { MOD, 't', KEY, }, { tag, { tags[TAG] } } }, \
- { { MOD, 'V', KEY, }, { toggleview, { tags[TAG] } } }, \
- { { MOD, 'T', KEY, }, { toggletag, { tags[TAG] } } },
-
-/* you can specifiy at most 3 arguments */
-static KeyBinding bindings[] = {
- { { MOD, 'c', }, { create, { NULL } } },
- { { MOD, 'C', }, { create, { NULL, NULL, "$CWD" } } },
- { { MOD, 'x', 'x', }, { killclient, { NULL } } },
- { { MOD, 'j', }, { focusnext, { NULL } } },
- { { MOD, 'J', }, { focusdown, { NULL } } },
- { { MOD, 'K', }, { focusup, { NULL } } },
- { { MOD, 'H', }, { focusleft, { NULL } } },
- { { MOD, 'L', }, { focusright, { NULL } } },
- { { MOD, 'k', }, { focusprev, { NULL } } },
- { { MOD, 'f', }, { setlayout, { "[]=" } } },
- { { MOD, 'g', }, { setlayout, { "+++" } } },
- { { MOD, 'b', }, { setlayout, { "TTT" } } },
- { { MOD, 'm', }, { setlayout, { "[ ]" } } },
- { { MOD, ' ', }, { setlayout, { NULL } } },
- { { MOD, 'i', }, { incnmaster, { "+1" } } },
- { { MOD, 'd', }, { incnmaster, { "-1" } } },
- { { MOD, 'h', }, { setmfact, { "-0.05" } } },
- { { MOD, 'l', }, { setmfact, { "+0.05" } } },
- { { MOD, '.', }, { toggleminimize, { NULL } } },
- { { MOD, 's', }, { togglebar, { NULL } } },
- { { MOD, 'S', }, { togglebarpos, { NULL } } },
- { { MOD, 'M', }, { togglemouse, { NULL } } },
- { { MOD, '\n', }, { zoom , { NULL } } },
- { { MOD, '\r', }, { zoom , { NULL } } },
- { { MOD, '1', }, { focusn, { "1" } } },
- { { MOD, '2', }, { focusn, { "2" } } },
- { { MOD, '3', }, { focusn, { "3" } } },
- { { MOD, '4', }, { focusn, { "4" } } },
- { { MOD, '5', }, { focusn, { "5" } } },
- { { MOD, '6', }, { focusn, { "6" } } },
- { { MOD, '7', }, { focusn, { "7" } } },
- { { MOD, '8', }, { focusn, { "8" } } },
- { { MOD, '9', }, { focusn, { "9" } } },
- { { MOD, '\t', }, { focuslast, { NULL } } },
- { { MOD, 'q', 'q', }, { quit, { NULL } } },
- { { MOD, 'a', }, { togglerunall, { NULL } } },
- { { MOD, CTRL('L'), }, { redraw, { NULL } } },
- { { MOD, 'r', }, { redraw, { NULL } } },
- { { MOD, 'e', }, { copymode, { "dvtm-editor" } } },
- { { MOD, 'E', }, { copymode, { "dvtm-pager" } } },
- { { MOD, '/', }, { copymode, { "dvtm-pager", "/" } } },
- { { MOD, 'p', }, { paste, { NULL } } },
- { { MOD, KEY_PPAGE, }, { scrollback, { "-1" } } },
- { { MOD, KEY_NPAGE, }, { scrollback, { "1" } } },
- { { MOD, '?', }, { create, { "man dvtm", "dvtm help" } } },
- { { MOD, MOD, }, { send, { (const char []){MOD, 0} } } },
- { { KEY_SPREVIOUS, }, { scrollback, { "-1" } } },
- { { KEY_SNEXT, }, { scrollback, { "1" } } },
- { { MOD, '0', }, { view, { NULL } } },
- { { MOD, KEY_F(1), }, { view, { tags[0] } } },
- { { MOD, KEY_F(2), }, { view, { tags[1] } } },
- { { MOD, KEY_F(3), }, { view, { tags[2] } } },
- { { MOD, KEY_F(4), }, { view, { tags[3] } } },
- { { MOD, KEY_F(5), }, { view, { tags[4] } } },
- { { MOD, 'v', '0' }, { view, { NULL } } },
- { { MOD, 'v', '\t', }, { viewprevtag, { NULL } } },
- { { MOD, 't', '0' }, { tag, { NULL } } },
- TAGKEYS( '1', 0)
- TAGKEYS( '2', 1)
- TAGKEYS( '3', 2)
- TAGKEYS( '4', 3)
- TAGKEYS( '5', 4)
-};
-
-static const ColorRule colorrules[] = {
- { "", A_NORMAL, &colors[DEFAULT] }, /* default */
-};
-
-/* possible values for the mouse buttons are listed below:
- *
- * BUTTON1_PRESSED mouse button 1 down
- * BUTTON1_RELEASED mouse button 1 up
- * BUTTON1_CLICKED mouse button 1 clicked
- * BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked
- * BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked
- * BUTTON2_PRESSED mouse button 2 down
- * BUTTON2_RELEASED mouse button 2 up
- * BUTTON2_CLICKED mouse button 2 clicked
- * BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked
- * BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked
- * BUTTON3_PRESSED mouse button 3 down
- * BUTTON3_RELEASED mouse button 3 up
- * BUTTON3_CLICKED mouse button 3 clicked
- * BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked
- * BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked
- * BUTTON4_PRESSED mouse button 4 down
- * BUTTON4_RELEASED mouse button 4 up
- * BUTTON4_CLICKED mouse button 4 clicked
- * BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked
- * BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked
- * BUTTON_SHIFT shift was down during button state change
- * BUTTON_CTRL control was down during button state change
- * BUTTON_ALT alt was down during button state change
- * ALL_MOUSE_EVENTS report all button state changes
- * REPORT_MOUSE_POSITION report mouse movement
- */
-
-#ifdef NCURSES_MOUSE_VERSION
-# define CONFIG_MOUSE /* compile in mouse support if we build against ncurses */
-#endif
-
-#define ENABLE_MOUSE true /* whether to enable mouse events by default */
-
-#ifdef CONFIG_MOUSE
-static Button buttons[] = {
- { BUTTON1_CLICKED, { mouse_focus, { NULL } } },
- { BUTTON1_DOUBLE_CLICKED, { mouse_fullscreen, { "[ ]" } } },
- { BUTTON2_CLICKED, { mouse_zoom, { NULL } } },
- { BUTTON3_CLICKED, { mouse_minimize, { NULL } } },
-};
-#endif /* CONFIG_MOUSE */
-
-static Cmd commands[] = {
- /* create [cmd]: create a new window, run `cmd` in the shell if specified */
- { "create", { create, { NULL } } },
- /* focus <win_id>: focus the window whose `DVTM_WINDOW_ID` is `win_id` */
- { "focus", { focusid, { NULL } } },
- /* tag <win_id> <tag> [tag ...]: add +tag, remove -tag or set tag of the window with the given identifier */
- { "tag", { tagid, { NULL } } },
-};
-
-/* gets executed when dvtm is started */
-static Action actions[] = {
- { create, { NULL } },
-};
-
-static char const * const keytable[] = {
- /* add your custom key escape sequences */
-};
diff --git a/sys/cmd/dvtm/dvtm-editor.c b/sys/cmd/dvtm/dvtm-editor.c
deleted file mode 100644
index e8685e9..0000000
--- a/sys/cmd/dvtm/dvtm-editor.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Invoke $EDITOR as a filter.
- *
- * Copyright (c) 2016 Dmitry Bogatov <KAction@gnu.org>
- * Copyright (c) 2017 Marc André Tanner <mat@brain-dump.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-static
-void
-error(const char *msg, ...) {
- va_list ap;
- va_start(ap, msg);
- vfprintf(stderr, msg, ap);
- va_end(ap);
- if (errno)
- fprintf(stderr, ": %s", strerror(errno));
- fprintf(stderr, "\n");
-}
-
-int
-main(int argc, char *argv[])
-{
- int exit_status = EXIT_FAILURE, tmp_write = -1;
-
- const char *editor = getenv("DVTM_EDITOR");
- if (!editor)
- editor = getenv("VISUAL");
- if (!editor)
- editor = getenv("EDITOR");
- if (!editor)
- editor = "vi";
-
- char tempname[] = "/tmp/dvtm-editor.XXXXXX";
- if ((tmp_write = mkstemp(tempname)) == -1) {
- error("failed to open temporary file `%s'", tempname);
- goto err;
- }
-
- /* POSIX does not mandates modes of temporary file. */
- if (fchmod(tmp_write, 0600) == -1) {
- error("failed to change mode of temporary file `%s'", tempname);
- goto err;
- }
-
- char buffer[2048];
- ssize_t bytes;
- while ((bytes = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0) {
- do {
- ssize_t written = write(tmp_write, buffer, bytes);
- if (written == -1) {
- error("failed to write data to temporary file `%s'",
- tempname);
- goto err;
- }
- bytes -= written;
- } while (bytes > 0);
- }
-
- if (fsync(tmp_write) == -1) {
- error("failed to fsync temporary file `%s'", tempname);
- goto err;
- }
-
- struct stat stat_before;
- if (fstat(tmp_write, &stat_before) == -1) {
- error("failed to stat newly created temporary file `%s'", tempname);
- goto err;
- }
-
- if (close(tmp_write) == -1) {
- error("failed to close temporary file `%s'", tempname);
- goto err;
- }
-
- pid_t pid = fork();
- if (pid == -1) {
- error("failed to fork editor process");
- goto err;
- } else if (pid == 0) {
- int tty = open("/dev/tty", O_RDWR);
- if (tty == -1) {
- error("failed to open /dev/tty");
- _exit(1);
- }
-
- if (dup2(tty, STDIN_FILENO) == -1) {
- error("failed to set tty as stdin");
- _exit(1);
- }
-
- if (dup2(tty, STDOUT_FILENO) == -1) {
- error("failed to set tty as stdout");
- _exit(1);
- }
-
- if (dup2(tty, STDERR_FILENO) == -1) {
- error("failed to set tty as stderr");
- _exit(1);
- }
-
- close(tty);
-
- const char *editor_argv[argc+2];
- editor_argv[0] = editor;
- for (int i = 1; i < argc; i++)
- editor_argv[i] = argv[i];
- editor_argv[argc] = tempname;
- editor_argv[argc+1] = NULL;
-
- execvp(editor, (char* const*)editor_argv);
- error("failed to exec editor process `%s'", editor);
- _exit(127);
- }
-
- int status;
- if (waitpid(pid, &status, 0) == -1) {
- error("waitpid failed");
- goto err;
- }
- if (!WIFEXITED(status)) {
- error("editor invocation failed");
- goto err;
- }
- if ((status = WEXITSTATUS(status)) != 0) {
- error("editor terminated with exit status: %d", status);
- goto err;
- }
-
- int tmp_read = open(tempname, O_RDONLY);
- if (tmp_read == -1) {
- error("failed to open for reading of edited temporary file `%s'",
- tempname);
- goto err;
- }
-
- struct stat stat_after;
- if (fstat(tmp_read, &stat_after) == -1) {
- error("failed to stat edited temporary file `%s'", tempname);
- goto err;
- }
-
- if (stat_before.st_mtime == stat_after.st_mtime)
- goto ok; /* no modifications */
-
- while ((bytes = read(tmp_read, buffer, sizeof(buffer))) > 0) {
- do {
- ssize_t written = write(STDOUT_FILENO, buffer, bytes);
- if (written == -1) {
- error("failed to write data to stdout");
- goto err;
- }
- bytes -= written;
- } while (bytes > 0);
- }
-
-ok:
- exit_status = EXIT_SUCCESS;
-err:
- if (tmp_write != -1)
- unlink(tempname);
- return exit_status;
-}
diff --git a/sys/cmd/dvtm/dvtm.c b/sys/cmd/dvtm/dvtm.c
deleted file mode 100644
index 3c0f52b..0000000
--- a/sys/cmd/dvtm/dvtm.c
+++ /dev/null
@@ -1,1810 +0,0 @@
-#include "dvtm.h"
-
-/* global variables */
-uint waw, wah, wax, way;
-Client *clients = nil;
-char *title;
-const char *dvtm_name = "dvtm";
-Screen screen = { .mfact = MFACT, .nmaster = NMASTER, .history = SCROLL_HISTORY };
-static Client *stack = nil;
-static Client *sel = nil;
-static Client *lastsel = nil;
-static Client *msel = nil;
-
-static uint seltags;
-static uint tagset[2] = { 1, 1 };
-static bool mouse_events_enabled = ENABLE_MOUSE;
-static Layout *layout = layouts;
-
-static StatusBar bar = { .fd = -1, .lastpos = BAR_POS, .pos = BAR_POS, .autohide = BAR_AUTOHIDE, .h = 1 };
-static CmdFifo cmdfifo = { .fd = -1 };
-static const char *shell;
-static Register copyreg;
-static volatile sig_atomic_t running = true;
-static bool runinall = false;
-
-/* function implementations */
-
-static
-void
-eprint(const char *errstr, ...)
-{
- va_list ap;
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
-}
-
-static
-void
-fatal(const char *errstr, ...)
-{
- va_list ap;
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
- exit(EXIT_FAILURE);
-}
-
-static
-bool
-isarrange(void (*func)())
-{
- return func == layout->arrange;
-}
-
-static
-bool
-isvisible(Client *c)
-{
- return c->tags & tagset[seltags];
-}
-
-static
-bool
-is_content_visible(Client *c)
-{
- if (!c)
- return false;
- if (isarrange(fullscreen))
- return sel == c;
- return isvisible(c) && !c->minimized;
-}
-
-Client*
-nextvisible(Client *c)
-{
- for (; c && !isvisible(c); c = c->next);
- return c;
-}
-
-static
-void
-updatebarpos(void)
-{
- bar.y = 0;
- wax = 0;
- way = 0;
- wah = screen.h;
- waw = screen.w;
- if (bar.pos == BAR_TOP) {
- wah -= bar.h;
- way += bar.h;
- } else if (bar.pos == BAR_BOTTOM) {
- wah -= bar.h;
- bar.y = wah;
- }
-}
-
-static
-void
-hidebar(void)
-{
- if (bar.pos != BAR_OFF) {
- bar.lastpos = bar.pos;
- bar.pos = BAR_OFF;
- }
-}
-
-static
-void
-showbar(void)
-{
- if (bar.pos == BAR_OFF)
- bar.pos = bar.lastpos;
-}
-
-static
-void
-drawbar(void)
-{
- int sx, sy, x, y, width;
- uint occupied = 0, urgent = 0;
- if (bar.pos == BAR_OFF)
- return;
-
- for (Client *c = clients; c; c = c->next) {
- occupied |= c->tags;
- if (c->urgent)
- urgent |= c->tags;
- }
-
- getyx(stdscr, sy, sx);
- attrset(BAR_ATTR);
- move(bar.y, 0);
-
- for (uint i = 0; i < arrlen(tags); i++){
- if (tagset[seltags] & (1 << i))
- attrset(TAG_SEL);
- else if (urgent & (1 << i))
- attrset(TAG_URGENT);
- else if (occupied & (1 << i))
- attrset(TAG_OCCUPIED);
- else
- attrset(TAG_NORMAL);
- printw(TAG_SYMBOL, tags[i]);
- }
-
- attrset(runinall ? TAG_SEL : TAG_NORMAL);
- addstr(layout->symbol);
- attrset(TAG_NORMAL);
-
- getyx(stdscr, y, x);
- (void)y;
- int maxwidth = screen.w - x - 2;
-
- addch(BAR_BEGIN);
- attrset(BAR_ATTR);
-
- wchar_t wbuf[sizeof bar.text];
- size_t numchars = mbstowcs(wbuf, bar.text, sizeof bar.text);
-
- if (numchars != (size_t)-1 && (width = wcswidth(wbuf, maxwidth)) != -1) {
- int pos;
- for (pos = 0; pos + width < maxwidth; pos++)
- addch(' ');
-
- for (size_t i = 0; i < numchars; i++) {
- pos += wcwidth(wbuf[i]);
- if (pos > maxwidth)
- break;
- addnwstr(wbuf+i, 1);
- }
-
- clrtoeol();
- }
-
- attrset(TAG_NORMAL);
- mvaddch(bar.y, screen.w - 1, BAR_END);
- attrset(NORMAL_ATTR);
- move(sy, sx);
- wnoutrefresh(stdscr);
-}
-
-static
-int
-show_border(void) {
- return (bar.pos != BAR_OFF) || (clients && clients->next);
-}
-
-static void
-draw_border(Client *c) {
- char t = '\0';
- int x, y, maxlen, attrs = NORMAL_ATTR;
-
- if (!show_border())
- return;
- if (sel != c && c->urgent)
- attrs = URGENT_ATTR;
- if (sel == c || (runinall && !c->minimized))
- attrs = SELECTED_ATTR;
-
- wattrset(c->window, attrs);
- getyx(c->window, y, x);
- mvwhline(c->window, 0, 0, ACS_HLINE, c->w);
- maxlen = c->w - 10;
- if (maxlen < 0)
- maxlen = 0;
- if ((size_t)maxlen < sizeof(c->title)) {
- t = c->title[maxlen];
- c->title[maxlen] = '\0';
- }
-
- mvwprintw(c->window, 0, 2, "[%s%s#%d]",
- *c->title ? c->title : "",
- *c->title ? " | " : "",
- c->order);
- if (t)
- c->title[maxlen] = t;
- wmove(c->window, y, x);
-}
-
-static void
-draw_content(Client *c) {
- vt_draw(c->term, c->window, c->has_title_line, 0);
-}
-
-static void
-draw(Client *c) {
- if (is_content_visible(c)) {
- redrawwin(c->window);
- draw_content(c);
- }
- if (!isarrange(fullscreen) || sel == c)
- draw_border(c);
- wnoutrefresh(c->window);
-}
-
-static void
-draw_all(void) {
- if (!nextvisible(clients)) {
- sel = nil;
- curs_set(0);
- erase();
- drawbar();
- doupdate();
- return;
- }
-
- if (!isarrange(fullscreen)) {
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c != sel)
- draw(c);
- }
- }
- /* as a last step the selected window is redrawn,
- * this has the effect that the cursor position is
- * accurate
- */
- if (sel)
- draw(sel);
-}
-
-static void
-arrange(void) {
- uint m = 0, n = 0;
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- c->order = ++n;
- if (c->minimized)
- m++;
- }
- erase();
- attrset(NORMAL_ATTR);
- if (bar.fd == -1 && bar.autohide) {
- if ((!clients || !clients->next) && n == 1)
- hidebar();
- else
- showbar();
- updatebarpos();
- }
- if (m && !isarrange(fullscreen))
- wah--;
- layout->arrange();
- if (m && !isarrange(fullscreen)) {
- uint i = 0, nw = waw / m, nx = wax;
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized) {
- resize(c, nx, way+wah, ++i == m ? waw - nx : nw, 1);
- nx += nw;
- }
- }
- wah++;
- }
- focus(nil);
- wnoutrefresh(stdscr);
- drawbar();
- draw_all();
-}
-
-static void
-attach(Client *c) {
- if (clients)
- clients->prev = c;
- c->next = clients;
- c->prev = nil;
- clients = c;
- for (int o = 1; c; c = nextvisible(c->next), o++)
- c->order = o;
-}
-
-static void
-attachafter(Client *c, Client *a) { /* attach c after a */
- if (c == a)
- return;
- if (!a)
- for (a = clients; a && a->next; a = a->next);
-
- if (a) {
- if (a->next)
- a->next->prev = c;
- c->next = a->next;
- c->prev = a;
- a->next = c;
- for (int o = a->order; c; c = nextvisible(c->next))
- c->order = ++o;
- }
-}
-
-static void
-attachstack(Client *c) {
- c->snext = stack;
- stack = c;
-}
-
-static void
-detach(Client *c) {
- Client *d;
- if (c->prev)
- c->prev->next = c->next;
- if (c->next) {
- c->next->prev = c->prev;
- for (d = nextvisible(c->next); d; d = nextvisible(d->next))
- --d->order;
- }
- if (c == clients)
- clients = c->next;
- c->next = c->prev = nil;
-}
-
-static void
-settitle(Client *c) {
- char *term, *t = title;
- if (!t && sel == c && *c->title)
- t = c->title;
- if (t && (term = getenv("TERM")) && !strstr(term, "linux")) {
- printf("\033]0;%s\007", t);
- fflush(stdout);
- }
-}
-
-static void
-detachstack(Client *c) {
- Client **tc;
- for (tc = &stack; *tc && *tc != c; tc = &(*tc)->snext);
- *tc = c->snext;
-}
-
-void
-focus(Client *c) {
- if (!c)
- for (c = stack; c && !isvisible(c); c = c->snext);
- if (sel == c)
- return;
- lastsel = sel;
- sel = c;
- if (lastsel) {
- lastsel->urgent = false;
- if (!isarrange(fullscreen)) {
- draw_border(lastsel);
- wnoutrefresh(lastsel->window);
- }
- }
-
- if (c) {
- detachstack(c);
- attachstack(c);
- settitle(c);
- c->urgent = false;
- if (isarrange(fullscreen)) {
- draw(c);
- } else {
- draw_border(c);
- wnoutrefresh(c->window);
- }
- }
- curs_set(c && !c->minimized && vt_cursor_visible(c->term));
-}
-
-static
-void
-applycolorrules(Client *c)
-{
- const ColorRule *r = colorrules;
- int fg = r->color->fg, bg = r->color->bg;
- attr_t attrs = r->attrs;
-
- for (uint i = 1; i < arrlen(colorrules); i++) {
- r = &colorrules[i];
- if (strstr(c->title, r->title)) {
- attrs = r->attrs;
- fg = r->color->fg;
- bg = r->color->bg;
- break;
- }
- }
-
- vt_default_colors_set(c->term, attrs, fg, bg);
-}
-
-static
-void
-term_title_handler(Vt *term, const char *title) {
- Client *c = (Client *)vt_data_get(term);
- if (title)
- strncpy(c->title, title, sizeof(c->title) - 1);
- c->title[title ? sizeof(c->title) - 1 : 0] = '\0';
- settitle(c);
- if (!isarrange(fullscreen) || sel == c)
- draw_border(c);
- applycolorrules(c);
-}
-
-static
-void
-term_urgent_handler(Vt *term) {
- Client *c = (Client *)vt_data_get(term);
- c->urgent = true;
- printf("\a");
- fflush(stdout);
- drawbar();
- if (!isarrange(fullscreen) && sel != c && isvisible(c))
- draw_border(c);
-}
-
-static
-void
-move_client(Client *c, int x, int y)
-{
- if (c->x == x && c->y == y)
- return;
- debug("moving, x: %d y: %d\n", x, y);
- if (mvwin(c->window, y, x) == ERR) {
- eprint("error moving, x: %d y: %d\n", x, y);
- } else {
- c->x = x;
- c->y = y;
- }
-}
-
-static
-void
-resize_client(Client *c, int w, int h)
-{
- bool has_title_line = show_border();
- bool resize_window = c->w != w || c->h != h;
- if (resize_window) {
- debug("resizing, w: %d h: %d\n", w, h);
- if (wresize(c->window, h, w) == ERR) {
- eprint("error resizing, w: %d h: %d\n", w, h);
- } else {
- c->w = w;
- c->h = h;
- }
- }
- if (resize_window || c->has_title_line != has_title_line) {
- c->has_title_line = has_title_line;
- vt_resize(c->app, h - has_title_line, w);
- if (c->editor)
- vt_resize(c->editor, h - has_title_line, w);
- }
-}
-
-void
-resize(Client *c, int x, int y, int w, int h)
-{
- resize_client(c, w, h);
- move_client(c, x, y);
-}
-
-static
-Client*
-get_client_by_coord(uint x, unsigned int y) {
- if (y < way || y >= way+wah)
- return nil;
- if (isarrange(fullscreen))
- return sel;
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (x >= c->x && x < c->x + c->w && y >= c->y && y < c->y + c->h) {
- debug("mouse event, x: %d y: %d client: %d\n", x, y, c->order);
- return c;
- }
- }
- return nil;
-}
-
-static
-void
-sigchld_handler(int sig) {
- int errsv = errno;
- int status;
- pid_t pid;
-
- while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
- if (pid == -1) {
- if (errno == ECHILD) {
- /* no more child processes */
- break;
- }
- eprint("waitpid: %s\n", strerror(errno));
- break;
- }
-
- debug("child with pid %d died\n", pid);
-
- for (Client *c = clients; c; c = c->next) {
- if (c->pid == pid) {
- c->died = true;
- break;
- }
- if (c->editor && vt_pid_get(c->editor) == pid) {
- c->editor_died = true;
- break;
- }
- }
- }
-
- errno = errsv;
-}
-
-static
-void
-sigwinch_handler(int sig) {
- screen.need_resize = true;
-}
-
-static
-void
-sigterm_handler(int sig) {
- running = false;
-}
-
-static
-void
-resize_screen(void)
-{
- struct winsize ws;
-
- if (ioctl(0, TIOCGWINSZ, &ws) == -1) {
- getmaxyx(stdscr, screen.h, screen.w);
- } else {
- screen.w = ws.ws_col;
- screen.h = ws.ws_row;
- }
-
- debug("resize_screen(), w: %d h: %d\n", screen.w, screen.h);
-
- resizeterm(screen.h, screen.w);
- wresize(stdscr, screen.h, screen.w);
- updatebarpos();
- clear();
- arrange();
-}
-
-static
-KeyBinding*
-keybinding(KeyCombo keys, uint keycount)
-{
- for (uint b = 0; b < arrlen(bindings); b++) {
- for (uint k = 0; k < keycount; k++) {
- if (keys[k] != bindings[b].keys[k])
- break;
- if (k == keycount - 1)
- return &bindings[b];
- }
- }
- return nil;
-}
-
-static
-uint
-bitoftag(const char *tag)
-{
- uint i;
- if (!tag)
- return ~0;
- for (i = 0; (i < arrlen(tags)) && strcmp(tags[i], tag); i++);
- return (i < arrlen(tags)) ? (1 << i) : 0;
-}
-
-static void
-tagschanged() {
- bool allminimized = true;
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (!c->minimized) {
- allminimized = false;
- break;
- }
- }
- if (allminimized && nextvisible(clients)) {
- focus(nil);
- toggleminimize(nil);
- }
- arrange();
-}
-
-void
-tag(const char *args[])
-{
- if (!sel)
- return;
- sel->tags = bitoftag(args[0]) & TAGMASK;
- tagschanged();
-}
-
-void
-tagid(const char *args[])
-{
- if (!args[0] || !args[1])
- return;
-
- const int win_id = atoi(args[0]);
- for (Client *c = clients; c; c = c->next) {
- if (c->id == win_id) {
- uint ntags = c->tags;
- for (uint i = 1; i < MAX_ARGS && args[i]; i++) {
- if (args[i][0] == '+')
- ntags |= bitoftag(args[i]+1);
- else if (args[i][0] == '-')
- ntags &= ~bitoftag(args[i]+1);
- else
- ntags = bitoftag(args[i]);
- }
- ntags &= TAGMASK;
- if (ntags) {
- c->tags = ntags;
- tagschanged();
- }
- return;
- }
- }
-}
-
-void
-toggletag(const char *args[])
-{
- if (!sel)
- return;
- uint newtags = sel->tags ^ (bitoftag(args[0]) & TAGMASK);
- if (newtags) {
- sel->tags = newtags;
- tagschanged();
- }
-}
-
-void
-toggleview(const char *args[])
-{
- uint newtagset = tagset[seltags] ^ (bitoftag(args[0]) & TAGMASK);
- if (newtagset) {
- tagset[seltags] = newtagset;
- tagschanged();
- }
-}
-
-void
-view(const char *args[])
-{
- uint newtagset = bitoftag(args[0]) & TAGMASK;
- if (tagset[seltags] != newtagset && newtagset) {
- seltags ^= 1; /* toggle sel tagset */
- tagset[seltags] = newtagset;
- tagschanged();
- }
-}
-
-void
-viewprevtag(const char *args[])
-{
- seltags ^= 1;
- tagschanged();
-}
-
-static
-void
-keypress(int code)
-{
- int key = -1;
- uint len = 1;
- char buf[8] = { '\e' };
-
- if (code == '\e') {
- /* pass characters following escape to the underlying app */
- nodelay(stdscr, TRUE);
- for (int t; len < sizeof(buf) && (t = getch()) != ERR; len++) {
- if (t > 255) {
- key = t;
- break;
- }
- buf[len] = t;
- }
- nodelay(stdscr, FALSE);
- }
-
- for (Client *c = runinall ? nextvisible(clients) : sel; c; c = nextvisible(c->next)) {
- if (is_content_visible(c)) {
- c->urgent = false;
- if (code == '\e')
- vt_write(c->term, buf, len);
- else
- vt_keypress(c->term, code);
-
- if (key != -1)
- vt_keypress(c->term, key);
- }
- if (!runinall)
- break;
- }
-}
-
-static
-void
-mouse_setup(void)
-{
-#ifdef CONFIG_MOUSE
- mmask_t mask = 0;
-
- if (mouse_events_enabled) {
- mask = BUTTON1_CLICKED | BUTTON2_CLICKED;
- for (uint i = 0; i < arrlen(buttons); i++)
- mask |= buttons[i].mask;
- }
- mousemask(mask, nil);
-#endif /* CONFIG_MOUSE */
-}
-
-static bool
-checkshell(const char *shell) {
- if (shell == nil || *shell == '\0' || *shell != '/')
- return false;
- if (!strcmp(strrchr(shell, '/')+1, dvtm_name))
- return false;
- if (access(shell, X_OK))
- return false;
- return true;
-}
-
-static const char *
-getshell(void) {
- const char *shell = getenv("SHELL");
- struct passwd *pw;
-
- if (checkshell(shell))
- return shell;
- if ((pw = getpwuid(getuid())) && checkshell(pw->pw_shell))
- return pw->pw_shell;
- return "/bin/sh";
-}
-
-static
-void
-setup(void)
-{
- shell = getshell();
- setlocale(LC_CTYPE, "");
- initscr();
- start_color();
- noecho();
- nonl();
- keypad(stdscr, TRUE);
- mouse_setup();
- raw();
- vt_init();
- vt_keytable_set(keytable, arrlen(keytable));
- for (uint i = 0; i < arrlen(colors); i++) {
- if (COLORS == 256) {
- if (colors[i].fg256)
- colors[i].fg = colors[i].fg256;
- if (colors[i].bg256)
- colors[i].bg = colors[i].bg256;
- }
- colors[i].pair = vt_color_reserve(colors[i].fg, colors[i].bg);
- }
- resize_screen();
-
- struct sigaction sa;
- memset(&sa, 0, sizeof sa);
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = sigwinch_handler;
- sigaction(SIGWINCH, &sa, nil);
- sa.sa_handler = sigchld_handler;
- sigaction(SIGCHLD, &sa, nil);
- sa.sa_handler = sigterm_handler;
- sigaction(SIGTERM, &sa, nil);
- sa.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &sa, nil);
-}
-
-static
-void
-destroy(Client *c) {
- if (sel == c)
- focusnextnm(nil);
- detach(c);
- detachstack(c);
- if (sel == c) {
- Client *next = nextvisible(clients);
- if (next) {
- focus(next);
- toggleminimize(nil);
- } else {
- sel = nil;
- }
- }
- if (lastsel == c)
- lastsel = nil;
- werase(c->window);
- wnoutrefresh(c->window);
- vt_destroy(c->term);
- delwin(c->window);
- if (!clients && arrlen(actions)) {
- if (!strcmp(c->cmd, shell))
- quit(nil);
- else
- create(nil);
- }
- free(c);
- arrange();
-}
-
-static
-void
-cleanup(void) {
- while (clients)
- destroy(clients);
- vt_shutdown();
- endwin();
- free(copyreg.data);
- if (bar.fd > 0)
- close(bar.fd);
- if (bar.file)
- unlink(bar.file);
- if (cmdfifo.fd > 0)
- close(cmdfifo.fd);
- if (cmdfifo.file)
- unlink(cmdfifo.file);
-}
-
-static
-char *getcwd_by_pid(Client *c) {
- if (!c)
- return nil;
- char buf[32];
- snprintf(buf, sizeof buf, "/proc/%d/cwd", c->pid);
- return realpath(buf, nil);
-}
-
-void
-create(const char *args[])
-{
- const char *pargs[4] = { shell, nil };
- char buf[8], *cwd = nil;
- const char *env[] = {
- "DVTM_WINDOW_ID", buf,
- nil
- };
-
- if (args && args[0]) {
- pargs[1] = "-c";
- pargs[2] = args[0];
- pargs[3] = nil;
- }
- Client *c = calloc(1, sizeof(Client));
- if (!c)
- return;
- c->tags = tagset[seltags];
- c->id = ++cmdfifo.id;
- snprintf(buf, sizeof buf, "%d", c->id);
-
- if (!(c->window = newwin(wah, waw, way, wax))) {
- free(c);
- return;
- }
-
- c->term = c->app = vt_create(screen.h, screen.w, screen.history);
- if (!c->term) {
- delwin(c->window);
- free(c);
- return;
- }
-
- if (args && args[0]) {
- c->cmd = args[0];
- char name[PATH_MAX];
- strncpy(name, args[0], sizeof(name));
- name[sizeof(name)-1] = '\0';
- strncpy(c->title, basename(name), sizeof(c->title));
- } else {
- c->cmd = shell;
- }
-
- if (args && args[1])
- strncpy(c->title, args[1], sizeof(c->title));
- c->title[sizeof(c->title)-1] = '\0';
-
- if (args && args[2])
- cwd = !strcmp(args[2], "$CWD") ? getcwd_by_pid(sel) : (char*)args[2];
- c->pid = vt_forkpty(c->term, shell, pargs, cwd, env, nil, nil);
- if (args && args[2] && !strcmp(args[2], "$CWD"))
- free(cwd);
- vt_data_set(c->term, c);
- vt_title_handler_set(c->term, term_title_handler);
- vt_urgent_handler_set(c->term, term_urgent_handler);
- applycolorrules(c);
- c->x = wax;
- c->y = way;
- debug("client with pid %d forked\n", c->pid);
- attach(c);
- focus(c);
- arrange();
-}
-
-void
-copymode(const char *args[])
-{
- if (!args || !args[0] || !sel || sel->editor)
- return;
-
- bool colored = strstr(args[0], "pager") != nil;
-
- if (!(sel->editor = vt_create(sel->h - sel->has_title_line, sel->w, 0)))
- return;
-
- int *to = &sel->editor_fds[0];
- int *from = strstr(args[0], "editor") ? &sel->editor_fds[1] : nil;
- sel->editor_fds[0] = sel->editor_fds[1] = -1;
-
- const char *argv[3] = { args[0], nil, nil };
- char argline[32];
- int line = vt_content_start(sel->app);
- snprintf(argline, sizeof(argline), "+%d", line);
- argv[1] = argline;
-
- if (vt_forkpty(sel->editor, args[0], argv, nil, nil, to, from) < 0) {
- vt_destroy(sel->editor);
- sel->editor = nil;
- return;
- }
-
- sel->term = sel->editor;
-
- if (sel->editor_fds[0] != -1) {
- char *buf = nil;
- size_t len = vt_content_get(sel->app, &buf, colored);
- char *cur = buf;
- while (len > 0) {
- ssize_t res = write(sel->editor_fds[0], cur, len);
- if (res < 0) {
- if (errno == EAGAIN || errno == EINTR)
- continue;
- break;
- }
- cur += res;
- len -= res;
- }
- free(buf);
- close(sel->editor_fds[0]);
- sel->editor_fds[0] = -1;
- }
-
- if (args[1])
- vt_write(sel->editor, args[1], strlen(args[1]));
-}
-
-void
-focusn(const char *args[])
-{
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->order == atoi(args[0])) {
- focus(c);
- if (c->minimized)
- toggleminimize(nil);
- return;
- }
- }
-}
-
-void
-focusid(const char *args[])
-{
- if (!args[0])
- return;
-
- const int win_id = atoi(args[0]);
- for (Client *c = clients; c; c = c->next) {
- if (c->id == win_id) {
- focus(c);
- if (c->minimized)
- toggleminimize(nil);
- if (!isvisible(c)) {
- c->tags |= tagset[seltags];
- tagschanged();
- }
- return;
- }
- }
-}
-
-void
-focusnext(const char *args[])
-{
- Client *c;
- if (!sel)
- return;
- for (c = sel->next; c && !isvisible(c); c = c->next);
- if (!c)
- for (c = clients; c && !isvisible(c); c = c->next);
- if (c)
- focus(c);
-}
-
-void
-focusnextnm(const char *args[])
-{
- if (!sel)
- return;
- Client *c = sel;
- do {
- c = nextvisible(c->next);
- if (!c)
- c = nextvisible(clients);
- } while (c->minimized && c != sel);
- focus(c);
-}
-
-void
-focusprev(const char *args[])
-{
- Client *c;
- if (!sel)
- return;
- for (c = sel->prev; c && !isvisible(c); c = c->prev);
- if (!c) {
- for (c = clients; c && c->next; c = c->next);
- for (; c && !isvisible(c); c = c->prev);
- }
- if (c)
- focus(c);
-}
-
-void
-focusprevnm(const char *args[])
-{
- if (!sel)
- return;
- Client *c = sel;
- do {
- for (c = c->prev; c && !isvisible(c); c = c->prev);
- if (!c) {
- for (c = clients; c && c->next; c = c->next);
- for (; c && !isvisible(c); c = c->prev);
- }
- } while (c && c != sel && c->minimized);
- focus(c);
-}
-
-void
-focuslast(const char *args[])
-{
- if (lastsel)
- focus(lastsel);
-}
-
-void
-focusup(const char *args[])
-{
- if (!sel)
- return;
- /* avoid vertical separator, hence +1 in x direction */
- Client *c = get_client_by_coord(sel->x + 1, sel->y - 1);
- if (c)
- focus(c);
- else
- focusprev(args);
-}
-
-void
-focusdown(const char *args[])
-{
- if (!sel)
- return;
- Client *c = get_client_by_coord(sel->x, sel->y + sel->h);
- if (c)
- focus(c);
- else
- focusnext(args);
-}
-
-void
-focusleft(const char *args[])
-{
- if (!sel)
- return;
- Client *c = get_client_by_coord(sel->x - 2, sel->y);
- if (c)
- focus(c);
- else
- focusprev(args);
-}
-
-void
-focusright(const char *args[])
-{
- if (!sel)
- return;
- Client *c = get_client_by_coord(sel->x + sel->w + 1, sel->y);
- if (c)
- focus(c);
- else
- focusnext(args);
-}
-
-void
-killclient(const char *args[])
-{
- if (!sel)
- return;
- debug("killing client with pid: %d\n", sel->pid);
- kill(-sel->pid, SIGKILL);
-}
-
-void
-paste(const char *args[])
-{
- if (sel && copyreg.data)
- vt_write(sel->term, copyreg.data, copyreg.len);
-}
-
-void
-quit(const char *args[])
-{
- cleanup();
- exit(EXIT_SUCCESS);
-}
-
-void
-redraw(const char *args[])
-{
- for (Client *c = clients; c; c = c->next) {
- if (!c->minimized) {
- vt_dirty(c->term);
- wclear(c->window);
- wnoutrefresh(c->window);
- }
- }
- resize_screen();
-}
-
-void
-scrollback(const char *args[])
-{
- if (!is_content_visible(sel))
- return;
-
- if (!args[0] || atoi(args[0]) < 0)
- vt_scroll(sel->term, -sel->h/2);
- else
- vt_scroll(sel->term, sel->h/2);
-
- draw(sel);
- curs_set(vt_cursor_visible(sel->term));
-}
-
-void
-send(const char *args[])
-{
- if (sel && args && args[0])
- vt_write(sel->term, args[0], strlen(args[0]));
-}
-
-void
-setlayout(const char *args[])
-{
- uint i;
-
- if (!args || !args[0]) {
- if (++layout == &layouts[arrlen(layouts)])
- layout = &layouts[0];
- } else {
- for (i = 0; i < arrlen(layouts); i++)
- if (!strcmp(args[0], layouts[i].symbol))
- break;
- if (i == arrlen(layouts))
- return;
- layout = &layouts[i];
- }
- arrange();
-}
-
-void
-incnmaster(const char *args[])
-{
- int delta;
-
- if (isarrange(fullscreen) || isarrange(grid))
- return;
- /* arg handling, manipulate nmaster */
- if (args[0] == nil) {
- screen.nmaster = NMASTER;
- } else if (sscanf(args[0], "%d", &delta) == 1) {
- if (args[0][0] == '+' || args[0][0] == '-')
- screen.nmaster += delta;
- else
- screen.nmaster = delta;
- if (screen.nmaster < 1)
- screen.nmaster = 1;
- }
- arrange();
-}
-
-void
-setmfact(const char *args[])
-{
- float delta;
-
- if (isarrange(fullscreen) || isarrange(grid))
- return;
- /* arg handling, manipulate mfact */
- if (args[0] == nil) {
- screen.mfact = MFACT;
- } else if (sscanf(args[0], "%f", &delta) == 1) {
- if (args[0][0] == '+' || args[0][0] == '-')
- screen.mfact += delta;
- else
- screen.mfact = delta;
- if (screen.mfact < 0.1)
- screen.mfact = 0.1;
- else if (screen.mfact > 0.9)
- screen.mfact = 0.9;
- }
- arrange();
-}
-
-void
-startup(const char *args[])
-{
- for (uint i = 0; i < arrlen(actions); i++)
- actions[i].cmd(actions[i].args);
-}
-
-void
-togglebar(const char *args[])
-{
- if (bar.pos == BAR_OFF)
- showbar();
- else
- hidebar();
- bar.autohide = false;
- updatebarpos();
- redraw(nil);
-}
-
-void
-togglebarpos(const char *args[])
-{
- switch (bar.pos == BAR_OFF ? bar.lastpos : bar.pos) {
- case BAR_TOP:
- bar.pos = BAR_BOTTOM;
- break;
- case BAR_BOTTOM:
- bar.pos = BAR_TOP;
- break;
- }
- updatebarpos();
- redraw(nil);
-}
-
-void
-toggleminimize(const char *args[])
-{
- Client *c, *m, *t;
- uint n;
- if (!sel)
- return;
- /* the last window can't be minimized */
- if (!sel->minimized) {
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
- if (n == 1)
- return;
- }
- sel->minimized = !sel->minimized;
- m = sel;
- /* check whether the master client was minimized */
- if (sel == nextvisible(clients) && sel->minimized) {
- c = nextvisible(sel->next);
- detach(c);
- attach(c);
- focus(c);
- detach(m);
- for (; c && (t = nextvisible(c->next)) && !t->minimized; c = t);
- attachafter(m, c);
- } else if (m->minimized) {
- /* non master window got minimized move it above all other
- * minimized ones */
- focusnextnm(nil);
- detach(m);
- for (c = nextvisible(clients); c && (t = nextvisible(c->next)) && !t->minimized; c = t);
- attachafter(m, c);
- } else { /* window is no longer minimized, move it to the master area */
- vt_dirty(m->term);
- detach(m);
- attach(m);
- }
- arrange();
-}
-
-void
-togglemouse(const char *args[])
-{
- mouse_events_enabled = !mouse_events_enabled;
- mouse_setup();
-}
-
-void
-togglerunall(const char *args[])
-{
- runinall = !runinall;
- drawbar();
- draw_all();
-}
-
-void
-zoom(const char *args[])
-{
- Client *c;
-
- if (!sel)
- return;
- if (args && args[0])
- focusn(args);
- if ((c = sel) == nextvisible(clients))
- if (!(c = nextvisible(c->next)))
- return;
- detach(c);
- attach(c);
- focus(c);
- if (c->minimized)
- toggleminimize(nil);
- arrange();
-}
-
-/* commands for use by mouse bindings */
-void
-mouse_focus(const char *args[])
-{
- focus(msel);
- if (msel->minimized)
- toggleminimize(nil);
-}
-
-void
-mouse_fullscreen(const char *args[])
-{
- mouse_focus(nil);
- setlayout(isarrange(fullscreen) ? nil : args);
-}
-
-void
-mouse_minimize(const char *args[])
-{
- focus(msel);
- toggleminimize(nil);
-}
-
-void
-mouse_zoom(const char *args[])
-{
- focus(msel);
- zoom(nil);
-}
-
-static
-Cmd *
-get_cmd_by_name(const char *name) {
- for (uint i = 0; i < arrlen(commands); i++) {
- if (!strcmp(name, commands[i].name))
- return &commands[i];
- }
- return nil;
-}
-
-static
-void
-handle_cmdfifo(void) {
- int r;
- char *p, *s, cmdbuf[512], c;
- Cmd *cmd;
-
- r = read(cmdfifo.fd, cmdbuf, sizeof cmdbuf - 1);
- if (r <= 0) {
- cmdfifo.fd = -1;
- return;
- }
-
- cmdbuf[r] = '\0';
- p = cmdbuf;
- while (*p) {
- /* find the command name */
- for (; *p == ' ' || *p == '\n'; p++);
- for (s = p; *p && *p != ' ' && *p != '\n'; p++);
- if ((c = *p))
- *p++ = '\0';
- if (*s && (cmd = get_cmd_by_name(s)) != nil) {
- bool quote = false;
- int argc = 0;
- const char *args[MAX_ARGS], *arg;
- memset(args, 0, sizeof(args));
- /* if arguments were specified in config.h ignore the one given via
- * the named pipe and thus skip everything until we find a new line
- */
- if (cmd->action.args[0] || c == '\n') {
- debug("execute %s", s);
- cmd->action.cmd(cmd->action.args);
- while (*p && *p != '\n')
- p++;
- continue;
- }
- /* no arguments were given in config.h so we parse the command line */
- while (*p == ' ')
- p++;
- arg = p;
- for (; (c = *p); p++) {
- switch (*p) {
- case '\\':
- /* remove the escape character '\\' move every
- * following character to the left by one position
- */
- switch (p[1]) {
- case '\\':
- case '\'':
- case '\"': {
- char *t = p+1;
- do {
- t[-1] = *t;
- } while (*t++);
- }
- }
- break;
- case '\'':
- case '\"':
- quote = !quote;
- break;
- case ' ':
- if (!quote) {
- case '\n':
- /* remove trailing quote if there is one */
- if (*(p - 1) == '\'' || *(p - 1) == '\"')
- *(p - 1) = '\0';
- *p++ = '\0';
- /* remove leading quote if there is one */
- if (*arg == '\'' || *arg == '\"')
- arg++;
- if (argc < MAX_ARGS)
- args[argc++] = arg;
-
- while (*p == ' ')
- ++p;
- arg = p--;
- }
- break;
- }
-
- if (c == '\n' || *p == '\n') {
- if (!*p)
- p++;
- debug("execute %s", s);
- for(int i = 0; i < argc; i++)
- debug(" %s", args[i]);
- debug("\n");
- cmd->action.cmd(args);
- break;
- }
- }
- }
- }
-}
-
-static void
-handle_mouse(void) {
-#ifdef CONFIG_MOUSE
- MEVENT event;
- uint i;
- if (getmouse(&event) != OK)
- return;
- msel = get_client_by_coord(event.x, event.y);
-
- if (!msel)
- return;
-
- debug("mouse x:%d y:%d cx:%d cy:%d mask:%d\n", event.x, event.y, event.x - msel->x, event.y - msel->y, event.bstate);
-
- vt_mouse(msel->term, event.x - msel->x, event.y - msel->y, event.bstate);
-
- for (i = 0; i < arrlen(buttons); i++) {
- if (event.bstate & buttons[i].mask)
- buttons[i].action.cmd(buttons[i].action.args);
- }
-
- msel = nil;
-#endif /* CONFIG_MOUSE */
-}
-
-static void
-handle_statusbar(void) {
- char *p;
- int r;
- switch (r = read(bar.fd, bar.text, sizeof bar.text - 1)) {
- case -1:
- strncpy(bar.text, strerror(errno), sizeof bar.text - 1);
- bar.text[sizeof bar.text - 1] = '\0';
- bar.fd = -1;
- break;
- case 0:
- bar.fd = -1;
- break;
- default:
- bar.text[r] = '\0';
- p = bar.text + r - 1;
- for (; p >= bar.text && *p == '\n'; *p-- = '\0');
- for (; p >= bar.text && *p != '\n'; --p);
- if (p >= bar.text)
- memmove(bar.text, p + 1, strlen(p));
- drawbar();
- }
-}
-
-static void
-handle_editor(Client *c) {
- if (!copyreg.data && (copyreg.data = malloc(screen.history)))
- copyreg.size = screen.history;
- copyreg.len = 0;
- while (c->editor_fds[1] != -1 && copyreg.len < copyreg.size) {
- ssize_t len = read(c->editor_fds[1], copyreg.data + copyreg.len, copyreg.size - copyreg.len);
- if (len == -1) {
- if (errno == EINTR)
- continue;
- break;
- }
- if (len == 0)
- break;
- copyreg.len += len;
- if (copyreg.len == copyreg.size) {
- copyreg.size *= 2;
- if (!(copyreg.data = realloc(copyreg.data, copyreg.size))) {
- copyreg.size = 0;
- copyreg.len = 0;
- }
- }
- }
- c->editor_died = false;
- c->editor_fds[1] = -1;
- vt_destroy(c->editor);
- c->editor = nil;
- c->term = c->app;
- vt_dirty(c->term);
- draw_content(c);
- wnoutrefresh(c->window);
-}
-
-static int
-open_or_create_fifo(const char *name, const char **name_created) {
- struct stat info;
- int fd;
-
- do {
- if ((fd = open(name, O_RDWR|O_NONBLOCK)) == -1) {
- if (errno == ENOENT && !mkfifo(name, S_IRUSR|S_IWUSR)) {
- *name_created = name;
- continue;
- }
- fatal("%s\n", strerror(errno));
- }
- } while (fd == -1);
-
- if (fstat(fd, &info) == -1)
- fatal("%s\n", strerror(errno));
- if (!S_ISFIFO(info.st_mode))
- fatal("%s is not a named pipe\n", name);
- return fd;
-}
-
-static
-void
-usage(void) {
- cleanup();
- eprint("usage: dvtm [-v] [-M] [-m mod] [-d delay] [-h lines] [-t title] "
- "[-s status-fifo] [-c cmd-fifo] [cmd...]\n");
- exit(EXIT_FAILURE);
-}
-
-static
-bool
-parse_args(int argc, char *argv[]) {
- bool init = false;
- const char *name = argv[0];
-
- if (name && (name = strrchr(name, '/')))
- dvtm_name = name + 1;
- if (!getenv("ESCDELAY"))
- set_escdelay(100);
- for (int arg = 1; arg < argc; arg++) {
- if (argv[arg][0] != '-') {
- const char *args[] = { argv[arg], nil, nil };
- if (!init) {
- setup();
- init = true;
- }
- create(args);
- continue;
- }
- if (argv[arg][1] != 'v' && argv[arg][1] != 'M' && (arg + 1) >= argc)
- usage();
- switch (argv[arg][1]) {
- case 'v':
- puts("dvtm-"VERSION);
- exit(EXIT_SUCCESS);
- case 'M':
- mouse_events_enabled = !mouse_events_enabled;
- break;
- case 'm': {
- char *mod = argv[++arg];
- if (mod[0] == '^' && mod[1])
- *mod = CTRL(mod[1]);
- for (uint b = 0; b < arrlen(bindings); b++)
- if (bindings[b].keys[0] == MOD)
- bindings[b].keys[0] = *mod;
- break;
- }
- case 'd':
- set_escdelay(atoi(argv[++arg]));
- if (ESCDELAY < 50)
- set_escdelay(50);
- else if (ESCDELAY > 1000)
- set_escdelay(1000);
- break;
- case 'h':
- screen.history = atoi(argv[++arg]);
- break;
- case 't':
- title = argv[++arg];
- break;
- case 's':
- bar.fd = open_or_create_fifo(argv[++arg], &bar.file);
- updatebarpos();
- break;
- case 'c': {
- const char *fifo;
- cmdfifo.fd = open_or_create_fifo(argv[++arg], &cmdfifo.file);
- if (!(fifo = realpath(argv[arg], nil)))
- fatal("%s\n", strerror(errno));
- setenv("DVTM_CMD_FIFO", fifo, 1);
- break;
- }
- default:
- usage();
- }
- }
- return init;
-}
-
-int
-main(int argc, char *argv[])
-{
- KeyCombo keys;
- uint key_index = 0;
- memset(keys, 0, sizeof(keys));
- sigset_t emptyset, blockset;
-
- setenv("DVTM", VERSION, 1);
- if (!parse_args(argc, argv)) {
- setup();
- startup(nil);
- }
-
- sigemptyset(&emptyset);
- sigemptyset(&blockset);
- sigaddset(&blockset, SIGWINCH);
- sigaddset(&blockset, SIGCHLD);
- sigprocmask(SIG_BLOCK, &blockset, nil);
-
- while (running) {
- int r, nfds = 0;
- fd_set rd;
-
- if (screen.need_resize) {
- resize_screen();
- screen.need_resize = false;
- }
-
- FD_ZERO(&rd);
- FD_SET(STDIN_FILENO, &rd);
-
- if (cmdfifo.fd != -1) {
- FD_SET(cmdfifo.fd, &rd);
- nfds = cmdfifo.fd;
- }
-
- if (bar.fd != -1) {
- FD_SET(bar.fd, &rd);
- nfds = MAX(nfds, bar.fd);
- }
-
- for (Client *c = clients; c;) {
- if (c->editor && c->editor_died)
- handle_editor(c);
- if (!c->editor && c->died) {
- Client *t = c->next;
- destroy(c);
- c = t;
- continue;
- }
- int pty = c->editor ? vt_pty_get(c->editor) : vt_pty_get(c->app);
- FD_SET(pty, &rd);
- nfds = MAX(nfds, pty);
- c = c->next;
- }
-
- doupdate();
- r = pselect(nfds + 1, &rd, nil, nil, nil, &emptyset);
-
- if (r < 0) {
- if (errno == EINTR)
- continue;
- perror("select()");
- exit(EXIT_FAILURE);
- }
-
- if (FD_ISSET(STDIN_FILENO, &rd)) {
- /* NOTE: this is the input handling step */
- int code = getch();
- if (code >= 0) {
- keys[key_index++] = code;
- KeyBinding *binding = nil;
-
- if (code == KEY_MOUSE) {
- key_index = 0;
- handle_mouse();
- } else if ((binding = keybinding(keys, key_index))) {
- uint key_length = MAX_KEYS;
- while (key_length > 1 && !binding->keys[key_length-1])
- key_length--;
- if (key_index == key_length) {
- binding->action.cmd(binding->action.args);
- key_index = 0;
- memset(keys, 0, sizeof(keys));
- }
- } else {
- key_index = 0;
- memset(keys, 0, sizeof(keys));
- keypress(code);
- }
- }
- if (r == 1) /* no data available on pty's */
- continue;
- }
-
- if (cmdfifo.fd != -1 && FD_ISSET(cmdfifo.fd, &rd))
- handle_cmdfifo();
-
- if (bar.fd != -1 && FD_ISSET(bar.fd, &rd))
- handle_statusbar();
-
- for (Client *c = clients; c; c = c->next) {
- if (FD_ISSET(vt_pty_get(c->term), &rd)) {
- if (vt_process(c->term) < 0 && errno == EIO) {
- if (c->editor)
- c->editor_died = true;
- else
- c->died = true;
- continue;
- }
- }
-
- if (c != sel && is_content_visible(c)) {
- draw_content(c);
- wnoutrefresh(c->window);
- }
- }
-
- if (is_content_visible(sel)) {
- draw_content(sel);
- curs_set(vt_cursor_visible(sel->term));
- wnoutrefresh(sel->window);
- }
- }
-
- cleanup();
- return 0;
-}
diff --git a/sys/cmd/dvtm/dvtm.h b/sys/cmd/dvtm/dvtm.h
deleted file mode 100644
index a777e18..0000000
--- a/sys/cmd/dvtm/dvtm.h
+++ /dev/null
@@ -1,233 +0,0 @@
- /* See LICENSE for details. */
-#pragma once
-#include <u.h>
-#include <libn.h>
-
-#include <locale.h>
-#include <libgen.h>
-
-#include <sys/select.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-// #include <vendor/curses.h>
-#include <termios.h>
-
-#include "vt.h"
-
-/* types */
-typedef struct Layout Layout;
-typedef struct Client Client;
-typedef struct Screen Screen;
-
-typedef struct Cmd Cmd;
-typedef struct CmdFifo CmdFifo;
-typedef struct Register Register;
-typedef struct Editor Editor;
-
-typedef struct Button Button;
-typedef struct KeyBinding KeyBinding;
-typedef struct StatusBar StatusBar;
-
-struct Screen
-{
- float mfact;
- uint nmaster;
- int history;
- int w, h;
- volatile sig_atomic_t need_resize;
-};
-
-struct Layout
-{
- const char *symbol;
- void (*arrange)(void);
-} ;
-
-struct Client
-{
- WINDOW *window;
- Vt *term;
- Vt *editor, *app;
- /* meta data */
- int editor_fds[2];
- volatile sig_atomic_t editor_died;
- const char *cmd;
- char title[255];
- int order;
- pid_t pid;
- ushort id;
- ushort x, y, w, h;
- bool has_title_line;
- bool minimized;
- bool urgent;
- volatile sig_atomic_t died;
- Client *next, *prev, *snext;
- uint tags;
-};
-
-typedef struct {
- int fg;
- int bg;
- int fg256;
- int bg256;
- int pair;
-} Color;
-
-typedef struct {
- const char *title;
- attr_t attrs;
- Color *color;
-} ColorRule;
-
-#define ALT(k) ((k) + (161 - 'a'))
-
-#if defined CTRL && defined _AIX
-#undef CTRL
-#endif
-
-#ifndef CTRL
-#define CTRL(k) ((k) & 0x1F)
-#endif
-#define CTRL_ALT(k) ((k) + (129 - 'a'))
-
-#define MAX_ARGS 8
-
-typedef struct
-{
- void (*cmd)(const char *args[]);
- const char *args[3];
-} Action;
-
-#define MAX_KEYS 3
-
-typedef uint KeyCombo[MAX_KEYS];
-
-struct KeyBinding
-{
- KeyCombo keys;
- Action action;
-};
-
-struct Button
-{
- mmask_t mask;
- Action action;
-};
-
-struct Cmd
-{
- const char *name;
- Action action;
-} ;
-
-enum { BAR_TOP, BAR_BOTTOM, BAR_OFF };
-
-struct StatusBar
-{
- int fd;
- int pos, lastpos;
- bool autohide;
- ushort h;
- ushort y;
- char text[512];
- const char *file;
-};
-
-struct CmdFifo
-{
- int fd;
- const char *file;
- ushort id;
-};
-
-struct Register
-{
- char *data;
- size_t len;
- size_t size;
-};
-
-struct Editor
-{
- char *name;
- const char *argv[4];
- bool filter;
- bool color;
-};
-
-#define TAGMASK ((1 << arrlen(tags)) - 1)
-
-#ifdef NDEBUG
- #define debug(format, args...)
-#else
- #define debug eprint
-#endif
-
-/* commands for use by keybindings */
-void create(const char *args[]);
-void copymode(const char *args[]);
-void focusn(const char *args[]);
-void focusid(const char *args[]);
-void focusnext(const char *args[]);
-void focusnextnm(const char *args[]);
-void focusprev(const char *args[]);
-void focusprevnm(const char *args[]);
-void focuslast(const char *args[]);
-void focusup(const char *args[]);
-void focusdown(const char *args[]);
-void focusleft(const char *args[]);
-void focusright(const char *args[]);
-void killclient(const char *args[]);
-void paste(const char *args[]);
-void quit(const char *args[]);
-void redraw(const char *args[]);
-void scrollback(const char *args[]);
-void send(const char *args[]);
-void setlayout(const char *args[]);
-void incnmaster(const char *args[]);
-void setmfact(const char *args[]);
-void startup(const char *args[]);
-void tag(const char *args[]);
-void tagid(const char *args[]);
-void togglebar(const char *args[]);
-void togglebarpos(const char *args[]);
-void toggleminimize(const char *args[]);
-void togglemouse(const char *args[]);
-void togglerunall(const char *args[]);
-void toggletag(const char *args[]);
-void toggleview(const char *args[]);
-void viewprevtag(const char *args[]);
-void view(const char *args[]);
-void zoom(const char *args[]);
-
-/* commands for use by mouse bindings */
-void mouse_focus(const char *args[]);
-void mouse_fullscreen(const char *args[]);
-void mouse_minimize(const char *args[]);
-void mouse_zoom(const char *args[]);
-
-/* functions and variables available to layouts via config.h */
-Client* nextvisible(Client *c);
-void focus(Client *c);
-void resize(Client *c, int x, int y, int w, int h);
-
-extern Screen screen;
-extern uint waw, wah, wax, way;
-extern Client *clients;
-extern char *title;
-
-void fibonacci(int s);
-void spiral(void);
-void dwindle(void);
-void fullscreen(void);
-void grid(void);
-void tile(void);
-void tstack(void);
-void bstack(void);
-void vstack(void);
-
-#include "config.h"
diff --git a/sys/cmd/dvtm/dvtm.info b/sys/cmd/dvtm/dvtm.info
deleted file mode 100644
index cafc0fe..0000000
--- a/sys/cmd/dvtm/dvtm.info
+++ /dev/null
@@ -1,136 +0,0 @@
-dvtm|dynamic virtual terminal manager,
- am,
- eo,
- mir,
- msgr,
- xenl,
- colors#8,
- cols#80,
- it#8,
- lines#24,
- ncv@,
- pairs#64,
- acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
- bel=^G,
- blink=\E[5m,
- bold=\E[1m,
- civis=\E[?25l,
- clear=\E[H\E[2J,
- cnorm=\E[?25h,
- cr=^M,
- csr=\E[%i%p1%d;%p2%dr,
- cub=\E[%p1%dD,
- cub1=^H,
- cud=\E[%p1%dB,
- cud1=^J,
- cuf=\E[%p1%dC,
- cuf1=\E[C,
- cup=\E[%i%p1%d;%p2%dH,
- cuu=\E[%p1%dA,
- cuu1=\E[A,
- dl=\E[%p1%dM,
- dl1=\E[M,
- ed=\E[J,
- el=\E[K,
- el1=\E[1K,
- enacs=\E(B\E)0,
- home=\E[H,
- hpa=\E[%i%p1%dG,
- ht=^I,
- hts=\EH,
- ich=\E[%p1%d@,
- ich1=\E[@,
- il=\E[%p1%dL,
- il1=\E[L,
- ind=^J,
- is1=\E[?47l\E=\E[?1l,
- is2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l,
- kDC=\E[3$,
- kEND=\E[8$,
- kHOM=\E[7$,
- kIC=\E[2$,
- kLFT=\E[d,
- kNXT=\E[6$,
- kPRV=\E[5$,
- kRIT=\E[c,
- ka1=\EOw,
- ka3=\EOy,
- kb2=\EOu,
- kbs=\177,
- kc1=\EOq,
- kc3=\EOs,
- kcbt=\E[Z,
- kcub1=\E[D,
- kcud1=\E[B,
- kcuf1=\E[C,
- kcuu1=\E[A,
- kdch1=\E[3~,
- kel=\E[8\^,
- kend=\E[8~,
- kent=\EOM,
- kf0=\E[21~,
- kf1=\E[11~,
- kf2=\E[12~,
- kf3=\E[13~,
- kf4=\E[14~,
- 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[25~,
- kf14=\E[26~,
- kf15=\E[28~,
- kf16=\E[29~,
- kf17=\E[31~,
- kf18=\E[32~,
- kf19=\E[33~,
- kf20=\E[34~,
- kf21=\E[23$,
- kf22=\E[24$
- kfnd=\E[1~,
- khome=\E[7~,
- kich1=\E[2~,
- kind=\E[a,
- kmous=\E[M,
- knp=\E[6~,
- kpp=\E[5~,
- kri=\E[b,
- kslt=\E[4~,
- op=\E[39;49m,
- rc=\E8,
- rev=\E[7m,
- ri=\EM,
- ritm=\E[23m,
- rmacs=^O,
- rmcup=\E[2J\E[?47l\E8,
- rmir=\E[4l,
- rmso=\E[27m,
- rmul=\E[24m,
- rs1=\E>\E[?1;3;4;5;6l\E[?7h\E[m\E[r\E[2J\E[H,
- rs2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l\E>\E[?1000l\E[?25h,
- s0ds=\E(B,
- s1ds=\E(0,
- sc=\E7,
- setab=\E[4%p1%dm,
- setaf=\E[3%p1%dm,
- sgr=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;,
- sgr0=\E[m\017,
- sitm=\E[3m,
- smacs=^N,
- smcup=\E7\E[?47h,
- smir=\E[4h,
- smso=\E[7m,
- smul=\E[4m,
- tbc=\E[3g,
- vpa=\E[%i%p1%dd,
-
-dvtm-256color|dynamic virtual terminal manager with 256 colors,
- use=dvtm,
- colors#256,
- pairs#32767,
- 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,
diff --git a/sys/cmd/dvtm/hook.c b/sys/cmd/dvtm/hook.c
deleted file mode 100644
index 6865f87..0000000
--- a/sys/cmd/dvtm/hook.c
+++ /dev/null
@@ -1,346 +0,0 @@
-#include "dvtm.h"
-
-void
-fibonacci(int s)
-{
- unsigned int nx, ny, nw, nnw, nh, nnh, i, n, mod;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- /* initial position and dimensions */
- nx = wax;
- ny = way;
- nw = (n == 1) ? waw : screen.mfact * waw;
- /* don't waste space dviding by 2 doesn't work for odd numbers
- * plus we need space for the border too. therefore set up these
- * variables for the next new width/height
- */
- nnw = waw - nw - 1;
- nnh = nh = wah;
-
- /* set the mod factor, 2 for dwindle, 4 for spiral */
- mod = s ? 4 : 2;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- /* dwindle: even case, spiral: case 0 */
- if (i % mod == 0) {
- if (i) {
- if (s) {
- nh = nnh;
- ny -= nh;
- } else {
- ny += nh;
- nh = nnh;
- }
- /* don't adjust the width for the last client */
- if (i < n - 1) {
- nw /= 2;
- nnw -= nw + 1;
- }
- mvaddch(ny, nx - 1, ACS_LTEE);
- }
- } else if (i % mod == 1) { /* dwindle: odd case, spiral: case 1 */
- nx += nw;
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- ++nx;
- nw = nnw;
- /* don't adjust the height for the last client */
- if (i < n - 1) {
- nh /= 2;
- nnh -= nh;
- }
- } else if (i % mod == 2 && s) { /* spiral: case 2 */
- ny += nh;
- nh = nnh;
- /* don't adjust the width for the last client */
- if (i < n - 1) {
- nw /= 2;
- nnw -= nw + 1;
- nx += nnw;
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- ++nx;
- } else {
- mvaddch(ny, nx - 1, ACS_LTEE);
- }
- } else if (s) { /* spiral: case 3 */
- nw = nnw;
- nx -= nw + 1; /* border */
- /* don't adjust the height for the last client */
- if (i < n - 1) {
- nh /= 2;
- nnh -= nh;
- ny += nnh;
- }
- mvaddch(ny, nx - 1, ACS_LTEE);
- }
-
- resize(c, nx, ny, nw, nh);
- i++;
- }
-}
-
-
-void
-spiral(void)
-{
- fibonacci(1);
-}
-
-void
-dwindle(void)
-{
- fibonacci(0);
-}
-
-void
-fullscreen(void)
-{
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next))
- resize(c, wax, way, waw, wah);
-}
-
-void
-grid(void)
-{
- unsigned int i, n, nx, ny, nw, nh, aw, ah, cols, rows;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
- /* grid dimensions */
- for (cols = 0; cols <= n / 2; cols++)
- if (cols * cols >= n)
- break;
- rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols;
- /* window geoms (cell height/width) */
- nh = wah / (rows ? rows : 1);
- nw = waw / (cols ? cols : 1);
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- /* if there are less clients in the last row than normal adjust the
- * split rate to fill the empty space */
- if (rows > 1 && i == (rows * cols) - cols && (n - i) <= (n % cols))
- nw = waw / (n - i);
- nx = (i % cols) * nw + wax;
- ny = (i / cols) * nh + way;
- /* adjust height/width of last row/column's windows */
- ah = (i >= cols * (rows - 1)) ? wah - nh * rows : 0;
- /* special case if there are less clients in the last row */
- if (rows > 1 && i == n - 1 && (n - i) < (n % cols))
- /* (n % cols) == number of clients in the last row */
- aw = waw - nw * (n % cols);
- else
- aw = ((i + 1) % cols == 0) ? waw - nw * cols : 0;
- if (i % cols) {
- mvvline(ny, nx, ACS_VLINE, nh + ah);
- /* if we are on the first row, or on the last one and there are fewer clients
- * than normal whose border does not match the line above, print a top tree char
- * otherwise a plus sign. */
- if (i <= cols
- || (i >= rows * cols - cols && n % cols
- && (cols - (n % cols)) % 2))
- mvaddch(ny, nx, ACS_TTEE);
- else
- mvaddch(ny, nx, ACS_PLUS);
- nx++, aw--;
- }
- resize(c, nx, ny, nw + aw, nh + ah);
- i++;
- }
-}
-
-void
-tile(void)
-{
- unsigned int i, n, nx, ny, nw, nh, m, mw, mh, th;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- m = MAX(1, MIN(n, screen.nmaster));
- mw = n == m ? waw : screen.mfact * waw;
- mh = wah / m;
- th = n == m ? 0 : wah / (n - m);
- nx = wax;
- ny = way;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- if (i < m) { /* master */
- nw = mw;
- nh = (i < m - 1) ? mh : (way + wah) - ny;
- } else { /* tile window */
- if (i == m) {
- ny = way;
- nx += mw;
- mvvline(ny, nx, ACS_VLINE, wah);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- nw = waw - mw -1;
- }
- nh = (i < n - 1) ? th : (way + wah) - ny;
- if (i > m)
- mvaddch(ny, nx - 1, ACS_LTEE);
- }
- resize(c, nx, ny, nw, nh);
- ny += nh;
- i++;
- }
-
- /* Fill in nmaster intersections */
- if (n > m) {
- ny = way + mh;
- for (i = 1; i < m; i++) {
- mvaddch(ny, nx - 1, ((ny - 1) % th ? ACS_RTEE : ACS_PLUS));
- ny += mh;
- }
- }
-}
-
-void
-tstack(void)
-{
- unsigned int i, n, nx, ny, nw, nh, m, mw, mh, tw;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- m = MAX(1, MIN(n, screen.nmaster));
- mh = n == m ? wah : screen.mfact * wah;
- mw = waw / m;
- tw = n == m ? 0 : waw / (n - m);
- nx = wax;
- ny = way + wah - mh;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- if (i < m) { /* master */
- if (i > 0) {
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- }
- nh = mh;
- nw = (i < m - 1) ? mw : (wax + waw) - nx;
- } else { /* tile window */
- if (i == m) {
- nx = wax;
- ny = way;
- nh = (way + wah) - ny - mh;
- }
- if (i > m) {
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- }
- nw = (i < n - 1) ? tw : (wax + waw) - nx;
- }
- resize(c, nx, ny, nw, nh);
- nx += nw;
- i++;
- }
-}
-
-void
-bstack(void)
-{
- unsigned int i, n, nx, ny, nw, nh, m, mw, mh, tw;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- m = MAX(1, MIN(n, screen.nmaster));
- mh = n == m ? wah : screen.mfact * wah;
- mw = waw / m;
- tw = n == m ? 0 : waw / (n - m);
- nx = wax;
- ny = way;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- if (i < m) { /* master */
- if (i > 0) {
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- }
- nh = mh;
- nw = (i < m - 1) ? mw : (wax + waw) - nx;
- } else { /* tile window */
- if (i == m) {
- nx = wax;
- ny += mh;
- nh = (way + wah) - ny;
- }
- if (i > m) {
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- }
- nw = (i < n - 1) ? tw : (wax + waw) - nx;
- }
- resize(c, nx, ny, nw, nh);
- nx += nw;
- i++;
- }
-
- /* Fill in nmaster intersections */
- if (n > m) {
- nx = wax;
- for (i = 0; i < m; i++) {
- if (i > 0) {
- mvaddch(ny, nx, ACS_PLUS);
- nx++;
- }
- nw = (i < m - 1) ? mw : (wax + waw) - nx;
- nx += nw;
- }
- }
-}
-
-/* a vertical stack layout, all windows have the full screen width. */
-void
-vstack(void)
-{
- unsigned int i, n, ny, nh, m, mh, th;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- m = MAX(1, MIN(n, screen.nmaster));
- mh = (n == m ? wah : screen.mfact * wah);
- th = n == m ? 0 : (wah - mh) / (n - m);
- ny = way;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- if (i < m) /* master */
- nh = (i < m - 1) ? mh / m : (way + mh) - ny;
- else /* tile window */
- nh = (i < n - 1) ? th : (way + wah) - ny;
- resize(c, wax, ny, waw, nh);
- ny += nh;
- i++;
- }
-}
diff --git a/sys/cmd/dvtm/rules.mk b/sys/cmd/dvtm/rules.mk
deleted file mode 100644
index f12aa17..0000000
--- a/sys/cmd/dvtm/rules.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := \
-$(d)/hook.c \
-$(d)/vt.c \
-$(d)/dvtm.c
-
-# needed for additional editor target
-AUX := $(d)/dvtm-editor.o
-AUX := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(AUX))
-
-DVTM := $(d)/dvtm
-DVTM-ED := $(d)/dvtm-editor
-
-DVTM := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(DVTM))
-DVTM-ED := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(DVTM-ED))
-
-BINS_$(d) := $(DVTM) $(DVTM-ED)
-
-include share/paths.mk
-
-$(DVTM): TCFLAGS = -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED -DNDEBUG
-$(DVTM): TCLIBS = -lncursesw $(OBJ_DIR)/libn/libn.a
-$(DVTM): $(OBJS_$(d))
- $(COMPLINK)
-
-$(DVTM-ED): TCFLAGS = -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED
-$(DVTM-ED): TCLIBS = -lncursesw -lutil -lc
-$(DVTM-ED): $(AUX)
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/dvtm/vt.c b/sys/cmd/dvtm/vt.c
deleted file mode 100644
index aff4ab0..0000000
--- a/sys/cmd/dvtm/vt.c
+++ /dev/null
@@ -1,2112 +0,0 @@
-/* See license for details */
-#include <u.h>
-#include <libn.h>
-
-#include <langinfo.h>
-#include <signal.h>
-#include <termios.h>
-
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#if defined(__linux__) || defined(__CYGWIN__)
-# include <pty.h>
-#elif defined(__FreeBSD__) || defined(__DragonFly__)
-# include <libutil.h>
-#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
-# include <util.h>
-#endif
-
-#include "vt.h"
-
-#ifndef NCURSES_ATTR_SHIFT
-# define NCURSES_ATTR_SHIFT 8
-#endif
-
-#ifndef NCURSES_ACS
-# ifdef PDCURSES
-# define NCURSES_ACS(c) (acs_map[(uchar)(c)])
-# else /* BSD curses */
-# define NCURSES_ACS(c) (_acs_map[(uchar)(c)])
-# endif
-#endif
-
-#ifdef NCURSES_VERSION
-
-#ifndef NCURSES_EXT_COLORS
-# define NCURSES_EXT_COLORS 0
-#endif
-
-#if !NCURSES_EXT_COLORS
-# define MAX_COLOR_PAIRS MIN(COLOR_PAIRS, 256)
-#endif
-
-#endif
-
-#ifndef MAX_COLOR_PAIRS
-# define MAX_COLOR_PAIRS COLOR_PAIRS
-#endif
-
-#if defined _AIX && defined CTRL
-# undef CTRL
-#endif
-#ifndef CTRL
-# define CTRL(k) ((k) & 0x1F)
-#endif
-
-#define IS_CONTROL(ch) !((ch) & 0xffffff60UL)
-
-static bool is_utf8, has_default_colors;
-static int color_pairs_reserved, color_pairs_max, color_pair_current;
-static short *color2palette, default_fg, default_bg;
-static char vt_term[32];
-
-typedef struct {
- wchar_t text;
- attr_t attr;
- union {
- struct {
- short fg;
- short bg;
- };
- struct {
- uint8 r;
- uint8 g;
- uint8 b;
- };
- };
-} Cell;
-
-typedef struct {
- Cell *cells;
- uint dirty:1;
-} Row;
-
-/* Buffer holding the current terminal window content (as an array) as well
- * as the scroll back buffer content (as a circular/ring buffer).
- *
- * If new content is added to terminal the view port slides down and the
- * previously top most line is moved into the scroll back buffer at postion
- * scroll_index. This index will eventually wrap around and thus overwrite
- * the oldest lines.
- *
- * In the scenerio below a scroll up has been performed. That is 'scroll_above'
- * lines still lie above the current view port. Further scrolling up will show
- * them. Similarly 'scroll_below' is the amount of lines below the current
- * viewport.
- *
- * The function buffer_boundary sets the row pointers to the start/end range
- * of the section delimiting the region before/after the viewport. The functions
- * buffer_row_{first,last} return the first/last logical row. And
- * buffer_row_{next,prev} allows to iterate over the logical lines in either
- * direction.
- *
- * scroll back buffer
- *
- * scroll_buf->+----------------+-----+
- * | | | ^ \
- * | before | | | |
- * current terminal content | viewport | | | |
- * | | | |
- * +----------------+-----+\ | | | s > scroll_above
- * ^ | | i | \ | | i | c |
- * | | | n | \ | | n | r |
- * | | v | \ | | v | o |
- * r | | i | \ | | i | l /
- * o | viewport | s | >|<- scroll_index | s | l \
- * w | | i | / | | i | |
- * s | | b | / | after | b | s > scroll_below
- * | | l | / | viewport | l | i |
- * v | | e | / | | e | z /
- * +----------------+-----+/ | unused | | e
- * <- maxcols -> | scroll back | |
- * <- cols -> | buffer | | |
- * | | | |
- * | | | v
- * scroll_buf + scroll_size->+----------------+-----+
- * <- maxcols ->
- * <- cols ->
- */
-typedef struct {
- Row *lines; /* array of Row pointers of size 'rows' */
- Row *curs_row; /* row on which the cursor currently resides */
- Row *scroll_buf; /* a ring buffer holding the scroll back content */
- Row *scroll_top; /* row in lines where scrolling region starts */
- Row *scroll_bot; /* row in lines where scrolling region ends */
- bool *tabs; /* a boolean flag for each column whether it is a tab */
- int scroll_size; /* maximal capacity of scroll back buffer (in lines) */
- int scroll_index; /* current index into the ring buffer */
- int scroll_above; /* number of lines above current viewport */
- int scroll_below; /* number of lines below current viewport */
- int rows, cols; /* current dimension of buffer */
- int maxcols; /* allocated cells (maximal cols over time) */
- attr_t curattrs, savattrs; /* current and saved attributes for cells */
- int curs_col; /* current cursor column (zero based) */
- int curs_srow, curs_scol; /* saved cursor row/colmn (zero based) */
- short curfg, curbg; /* current fore and background colors */
- short savfg, savbg; /* saved colors */
-} Buffer;
-
-struct Vt {
- Buffer buffer_normal; /* normal screen buffer */
- Buffer buffer_alternate; /* alternate screen buffer */
- Buffer *buffer; /* currently active buffer (one of the above) */
- attr_t defattrs; /* attributes to use for normal/empty cells */
- int deffg, defbg; /* colors to use for back normal/empty cells (white/black) */
- int pty; /* master side pty file descriptor */
- pid_t pid; /* process id of the process running in this vt */
- /* flags */
- uint seen_input:1;
- uint insert:1;
- uint escaped:1;
- uint curshid:1;
- uint curskeymode:1;
- uint bell:1;
- uint relposmode:1;
- uint mousetrack:1;
- uint graphmode:1;
- uint savgraphmode:1;
- bool charsets[2];
- /* buffers and parsing state */
- char rbuf[BUFSIZ];
- char ebuf[BUFSIZ];
- uint rlen, elen;
- int srow, scol; /* last known offset to display start row, start column */
- char title[256]; /* xterm style window title */
- vt_title_handler_t title_handler; /* hook which is called when title changes */
- vt_urgent_handler_t urgent_handler; /* hook which is called upon bell */
- void *data; /* user supplied data */
-};
-
-static const char *keytable[KEY_MAX+1] = {
- [KEY_ENTER] = "\r",
- ['\n'] = "\n",
- /* for the arrow keys the CSI / SS3 sequences are not stored here
- * because they depend on the current cursor terminal mode
- */
- [KEY_UP] = "A",
- [KEY_DOWN] = "B",
- [KEY_RIGHT] = "C",
- [KEY_LEFT] = "D",
-#ifdef KEY_SUP
- [KEY_SUP] = "\e[1;2A",
-#endif
-#ifdef KEY_SDOWN
- [KEY_SDOWN] = "\e[1;2B",
-#endif
- [KEY_SRIGHT] = "\e[1;2C",
- [KEY_SLEFT] = "\e[1;2D",
- [KEY_BACKSPACE] = "\177",
- [KEY_IC] = "\e[2~",
- [KEY_DC] = "\e[3~",
- [KEY_PPAGE] = "\e[5~",
- [KEY_NPAGE] = "\e[6~",
- [KEY_HOME] = "\e[7~",
- [KEY_END] = "\e[8~",
- [KEY_BTAB] = "\e[Z",
- [KEY_SUSPEND] = "\x1A", /* Ctrl+Z gets mapped to this */
- [KEY_F(1)] = "\e[11~",
- [KEY_F(2)] = "\e[12~",
- [KEY_F(3)] = "\e[13~",
- [KEY_F(4)] = "\e[14~",
- [KEY_F(5)] = "\e[15~",
- [KEY_F(6)] = "\e[17~",
- [KEY_F(7)] = "\e[18~",
- [KEY_F(8)] = "\e[19~",
- [KEY_F(9)] = "\e[20~",
- [KEY_F(10)] = "\e[21~",
- [KEY_F(11)] = "\e[23~",
- [KEY_F(12)] = "\e[24~",
- [KEY_F(13)] = "\e[23~",
- [KEY_F(14)] = "\e[24~",
- [KEY_F(15)] = "\e[25~",
- [KEY_F(16)] = "\e[26~",
- [KEY_F(17)] = "\e[28~",
- [KEY_F(18)] = "\e[29~",
- [KEY_F(19)] = "\e[31~",
- [KEY_F(20)] = "\e[32~",
- [KEY_F(21)] = "\e[33~",
- [KEY_F(22)] = "\e[34~",
- [KEY_RESIZE] = "",
-#ifdef KEY_EVENT
- [KEY_EVENT] = "",
-#endif
-};
-
-static void puttab(Vt *t, int count);
-static void process_nonprinting(Vt *t, wchar_t wc);
-static void send_curs(Vt *t);
-
-const static
-attr_t
-build_attrs(attr_t curattrs)
-{
- return ((curattrs & ~A_COLOR) | COLOR_PAIR(curattrs & 0xff)) >> NCURSES_ATTR_SHIFT;
-}
-
-static
-void
-row_set(Row *row, int start, int len, Buffer *t)
-{
- Cell cell = {
- .text = L'\0',
- .attr = t ? build_attrs(t->curattrs) : 0,
- .fg = t ? t->curfg : -1,
- .bg = t ? t->curbg : -1,
- };
-
- for (int i = start; i < len + start; i++)
- row->cells[i] = cell;
- row->dirty = true;
-}
-
-static
-void
-row_roll(Row *start, Row *end, int count)
-{
- int n = end - start;
-
- count %= n;
- if (count < 0)
- count += n;
-
- if (count) {
- char buf[count * sizeof(Row)];
- 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 = true;
- }
-}
-
-static
-void
-buffer_clear(Buffer *b)
-{
- Cell cell = {
- .text = L'\0',
- .attr = A_NORMAL,
- .fg = -1,
- .bg = -1,
- };
-
- for (int i = 0; i < b->rows; i++) {
- Row *row = b->lines + i;
- for (int j = 0; j < b->cols; j++) {
- row->cells[j] = cell;
- row->dirty = true;
- }
- }
-}
-
-static
-void
-buffer_free(Buffer *b)
-{
- for (int i = 0; i < b->rows; i++)
- free(b->lines[i].cells);
- free(b->lines);
- for (int i = 0; i < b->scroll_size; i++)
- free(b->scroll_buf[i].cells);
- free(b->scroll_buf);
- free(b->tabs);
-}
-
-static
-void
-buffer_scroll(Buffer *b, int s)
-{
- /* work in screenfuls */
- int ssz = b->scroll_bot - b->scroll_top;
- if (s > ssz) {
- buffer_scroll(b, ssz);
- buffer_scroll(b, s - ssz);
- return;
- }
- if (s < -ssz) {
- buffer_scroll(b, -ssz);
- buffer_scroll(b, s + ssz);
- return;
- }
-
- b->scroll_above += s;
- if (b->scroll_above >= b->scroll_size)
- b->scroll_above = b->scroll_size;
-
- if (s > 0 && b->scroll_size) {
- for (int i = 0; i < s; i++) {
- Row 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;
- }
- }
- row_roll(b->scroll_top, b->scroll_bot, s);
- if (s < 0 && b->scroll_size) {
- for (int i = (-s) - 1; i >= 0; i--) {
- b->scroll_index--;
- if (b->scroll_index == -1)
- b->scroll_index = b->scroll_size - 1;
-
- Row 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 = true;
- }
- }
-}
-
-static
-void
-buffer_resize(Buffer *b, int rows, int cols)
-{
- Row *lines = b->lines;
-
- if (b->rows != rows) {
- if (b->curs_row >= lines + rows) {
- /* scroll up instead of simply chopping off bottom */
- buffer_scroll(b, (b->curs_row - b->lines) - rows + 1);
- }
- while (b->rows > rows) {
- free(lines[b->rows - 1].cells);
- b->rows--;
- }
-
- lines = realloc(lines, sizeof(Row) * rows);
- }
-
- if (b->maxcols < cols) {
- for (int row = 0; row < b->rows; row++) {
- lines[row].cells = realloc(lines[row].cells, sizeof(Cell) * cols);
- if (b->cols < cols)
- row_set(lines + row, b->cols, cols - b->cols, nil);
- lines[row].dirty = true;
- }
- Row *sbuf = b->scroll_buf;
- for (int row = 0; row < b->scroll_size; row++) {
- sbuf[row].cells = realloc(sbuf[row].cells, sizeof(Cell) * cols);
- if (b->cols < cols)
- row_set(sbuf + row, b->cols, cols - b->cols, nil);
- }
- b->tabs = realloc(b->tabs, sizeof(*b->tabs) * cols);
- for (int col = b->cols; col < cols; col++)
- b->tabs[col] = !(col & 7);
- b->maxcols = cols;
- b->cols = cols;
- } else if (b->cols != cols) {
- for (int row = 0; row < b->rows; row++)
- lines[row].dirty = true;
- b->cols = cols;
- }
-
- int deltarows = 0;
- if (b->rows < rows) {
- while (b->rows < rows) {
- lines[b->rows].cells = calloc(b->maxcols, sizeof(Cell));
- row_set(lines + b->rows, 0, b->maxcols, b);
- b->rows++;
- }
-
- /* prepare for backfill */
- if (b->curs_row >= b->scroll_bot - 1) {
- deltarows = b->lines + rows - b->curs_row - 1;
- if (deltarows > b->scroll_above)
- deltarows = b->scroll_above;
- }
- }
-
- b->curs_row += lines - b->lines;
- b->scroll_top = lines;
- b->scroll_bot = lines + rows;
- b->lines = lines;
-
- /* perform backfill */
- if (deltarows > 0) {
- buffer_scroll(b, -deltarows);
- b->curs_row += deltarows;
- }
-}
-
-static
-bool
-buffer_init(Buffer *b, int rows, int cols, int scroll_size)
-{
- b->curattrs = A_NORMAL; /* white text over black background */
- b->curfg = b->curbg = -1;
- if (scroll_size < 0)
- scroll_size = 0;
- if (scroll_size && !(b->scroll_buf = calloc(scroll_size, sizeof(Row))))
- return false;
- b->scroll_size = scroll_size;
- buffer_resize(b, rows, cols);
- return true;
-}
-
-static
-void
-buffer_boundry(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 *
-buffer_row_first(Buffer *b) {
- Row *bstart;
- if (!b->scroll_size || !b->scroll_above)
- return b->lines;
- buffer_boundry(b, &bstart, nil, nil, nil);
- return bstart;
-}
-
-static
-Row *
-buffer_row_last(Buffer *b) {
- Row *aend;
- if (!b->scroll_size || !b->scroll_below)
- return b->lines + b->rows - 1;
- buffer_boundry(b, nil, nil, nil, &aend);
- return aend;
-}
-
-static
-Row *
-buffer_row_next(Buffer *b, Row *row)
-{
- Row *before_start, *before_end, *after_start, *after_end;
- Row *first = b->lines, *last = b->lines + b->rows - 1;
-
- if (!row)
- return nil;
-
- buffer_boundry(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 *
-buffer_row_prev(Buffer *b, Row *row)
-{
- Row *before_start, *before_end, *after_start, *after_end;
- Row *first = b->lines, *last = b->lines + b->rows - 1;
-
- if (!row)
- return nil;
-
- buffer_boundry(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;
-}
-
-static
-void
-cursor_clamp(Vt *t)
-{
- Buffer *b = t->buffer;
- Row *lines = t->relposmode ? b->scroll_top : b->lines;
- int rows = t->relposmode ? b->scroll_bot - b->scroll_top : b->rows;
-
- if (b->curs_row < lines)
- b->curs_row = lines;
- if (b->curs_row >= lines + rows)
- b->curs_row = lines + rows - 1;
- if (b->curs_col < 0)
- b->curs_col = 0;
- if (b->curs_col >= b->cols)
- b->curs_col = b->cols - 1;
-}
-
-static
-void
-cursor_line_down(Vt *t)
-{
- Buffer *b = t->buffer;
- row_set(b->curs_row, b->cols, b->maxcols - b->cols, nil);
- b->curs_row++;
- if (b->curs_row < b->scroll_bot)
- return;
-
- vt_noscroll(t);
-
- b->curs_row = b->scroll_bot - 1;
- buffer_scroll(b, 1);
- row_set(b->curs_row, 0, b->cols, b);
-}
-
-static
-void
-cursor_save(Vt *t)
-{
- Buffer *b = t->buffer;
- b->curs_srow = b->curs_row - b->lines;
- b->curs_scol = b->curs_col;
-}
-
-static
-void
-cursor_restore(Vt *t)
-{
- Buffer *b = t->buffer;
- b->curs_row = b->lines + b->curs_srow;
- b->curs_col = b->curs_scol;
- cursor_clamp(t);
-}
-
-static
-void
-attributes_save(Vt *t)
-{
- Buffer *b = t->buffer;
- b->savattrs = b->curattrs;
- b->savfg = b->curfg;
- b->savbg = b->curbg;
- t->savgraphmode = t->graphmode;
-}
-
-static
-void
-attributes_restore(Vt *t)
-{
- Buffer *b = t->buffer;
- b->curattrs = b->savattrs;
- b->curfg = b->savfg;
- b->curbg = b->savbg;
- t->graphmode = t->savgraphmode;
-}
-
-static
-void
-new_escape_sequence(Vt *t)
-{
- t->escaped = true;
- t->elen = 0;
- t->ebuf[0] = '\0';
-}
-
-static
-void
-cancel_escape_sequence(Vt *t)
-{
- t->escaped = false;
- t->elen = 0;
- t->ebuf[0] = '\0';
-}
-
-static
-bool
-is_valid_csi_ender(int c)
-{
- return (c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c == '@' || c == '`');
-}
-
-/* interprets a 'set attribute' (SGR) CSI escape sequence */
-static
-void
-interpret_csi_sgr(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- if (pcount == 0) {
- /* special case: reset attributes */
- b->curattrs = A_NORMAL;
- b->curfg = b->curbg = -1;
- return;
- }
-
- for (int i = 0; i < pcount; i++) {
- switch (param[i]) {
- case 0:
- b->curattrs = A_NORMAL;
- b->curfg = b->curbg = -1;
- break;
- case 1:
- b->curattrs |= A_BOLD;
- break;
- case 2:
- b->curattrs |= A_DIM;
- break;
-#ifdef A_ITALIC
- case 3:
- b->curattrs |= A_ITALIC;
- break;
-#endif
- case 4:
- b->curattrs |= A_UNDERLINE;
- break;
- case 5:
- b->curattrs |= A_BLINK;
- break;
- case 7:
- b->curattrs |= A_REVERSE;
- break;
- case 8:
- b->curattrs |= A_INVIS;
- break;
- case 22:
- b->curattrs &= ~(A_BOLD | A_DIM);
- break;
-#ifdef A_ITALIC
- case 23:
- b->curattrs &= ~A_ITALIC;
- break;
-#endif
- case 24:
- b->curattrs &= ~A_UNDERLINE;
- break;
- case 25:
- b->curattrs &= ~A_BLINK;
- break;
- case 27:
- b->curattrs &= ~A_REVERSE;
- break;
- case 28:
- b->curattrs &= ~A_INVIS;
- break;
- case 30 ... 37: /* fg */
- b->curfg = param[i] - 30;
- break;
- case 38:
- if ((i + 2) < pcount && param[i + 1] == 5) {
- b->curfg = param[i + 2];
- i += 2;
- }
- break;
- case 39:
- b->curfg = -1;
- break;
- case 40 ... 47: /* bg */
- b->curbg = param[i] - 40;
- break;
- case 48:
- if ((i + 2) < pcount && param[i + 1] == 5) {
- b->curbg = param[i + 2];
- i += 2;
- }
- break;
- case 49:
- b->curbg = -1;
- break;
- case 90 ... 97: /* hi fg */
- b->curfg = param[i] - 82;
- break;
- case 100 ... 107: /* hi bg */
- b->curbg = param[i] - 92;
- break;
- default:
- break;
- }
- }
-}
-
-/* interprets an 'erase display' (ED) escape sequence */
-static
-void
-interpret_csi_ed(Vt *t, int param[], int pcount)
-{
- Row *row, *start, *end;
- Buffer *b = t->buffer;
-
- attributes_save(t);
- b->curattrs = A_NORMAL;
- b->curfg = b->curbg = -1;
-
- if (pcount && param[0] == 2) {
- start = b->lines;
- end = b->lines + b->rows;
- } else if (pcount && param[0] == 1) {
- start = b->lines;
- end = b->curs_row;
- row_set(b->curs_row, 0, b->curs_col + 1, b);
- } else {
- row_set(b->curs_row, b->curs_col, b->cols - b->curs_col, b);
- start = b->curs_row + 1;
- end = b->lines + b->rows;
- }
-
- for (row = start; row < end; row++)
- row_set(row, 0, b->cols, b);
-
- attributes_restore(t);
-}
-
-/* interprets a 'move cursor' (CUP) escape sequence */
-static
-void
-interpret_csi_cup(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- Row *lines = t->relposmode ? b->scroll_top : b->lines;
-
- if (pcount == 0) {
- b->curs_row = lines;
- b->curs_col = 0;
- } else if (pcount == 1) {
- b->curs_row = lines + param[0] - 1;
- b->curs_col = 0;
- } else {
- b->curs_row = lines + param[0] - 1;
- b->curs_col = param[1] - 1;
- }
-
- cursor_clamp(t);
-}
-
-/* Interpret the 'relative mode' sequences: CUU, CUD, CUF, CUB, CNL,
- * CPL, CHA, HPR, VPA, VPR, HPA */
-static
-void
-interpret_csi_c(Vt *t, char verb, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- switch (verb) {
- case 'A':
- b->curs_row -= n;
- break;
- case 'B':
- case 'e':
- b->curs_row += n;
- break;
- case 'C':
- case 'a':
- b->curs_col += n;
- break;
- case 'D':
- b->curs_col -= n;
- break;
- case 'E':
- b->curs_row += n;
- b->curs_col = 0;
- break;
- case 'F':
- b->curs_row -= n;
- b->curs_col = 0;
- break;
- case 'G':
- case '`':
- b->curs_col = n - 1;
- break;
- case 'd':
- b->curs_row = b->lines + n - 1;
- break;
- }
-
- cursor_clamp(t);
-}
-
-/* Interpret the 'erase line' escape sequence */
-static
-void
-interpret_csi_el(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- switch (pcount ? param[0] : 0) {
- case 1:
- row_set(b->curs_row, 0, b->curs_col + 1, b);
- break;
- case 2:
- row_set(b->curs_row, 0, b->cols, b);
- break;
- default:
- row_set(b->curs_row, b->curs_col, b->cols - b->curs_col, b);
- break;
- }
-}
-
-/* Interpret the 'insert blanks' sequence (ICH) */
-static
-void
-interpret_csi_ich(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- Row *row = b->curs_row;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_col + n > b->cols)
- n = b->cols - b->curs_col;
-
- for (int i = b->cols - 1; i >= b->curs_col + n; i--)
- row->cells[i] = row->cells[i - n];
-
- row_set(row, b->curs_col, n, b);
-}
-
-/* Interpret the 'delete chars' sequence (DCH) */
-static
-void
-interpret_csi_dch(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- Row *row = b->curs_row;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_col + n > b->cols)
- n = b->cols - b->curs_col;
-
- for (int i = b->curs_col; i < b->cols - n; i++)
- row->cells[i] = row->cells[i + n];
-
- row_set(row, b->cols - n, n, b);
-}
-
-/* Interpret an 'insert line' sequence (IL) */
-static
-void
-interpret_csi_il(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_row + n >= b->scroll_bot) {
- for (Row *row = b->curs_row; row < b->scroll_bot; row++)
- row_set(row, 0, b->cols, b);
- } else {
- row_roll(b->curs_row, b->scroll_bot, -n);
- for (Row *row = b->curs_row; row < b->curs_row + n; row++)
- row_set(row, 0, b->cols, b);
- }
-}
-
-/* Interpret a 'delete line' sequence (DL) */
-static
-void
-interpret_csi_dl(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_row + n >= b->scroll_bot) {
- for (Row *row = b->curs_row; row < b->scroll_bot; row++)
- row_set(row, 0, b->cols, b);
- } else {
- row_roll(b->curs_row, b->scroll_bot, n);
- for (Row *row = b->scroll_bot - n; row < b->scroll_bot; row++)
- row_set(row, 0, b->cols, b);
- }
-}
-
-/* Interpret an 'erase characters' (ECH) sequence */
-static
-void
-interpret_csi_ech(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_col + n > b->cols)
- n = b->cols - b->curs_col;
-
- row_set(b->curs_row, b->curs_col, n, b);
-}
-
-/* Interpret a 'set scrolling region' (DECSTBM) sequence */
-static
-void
-interpret_csi_decstbm(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int new_top, new_bot;
-
- switch (pcount) {
- case 0:
- b->scroll_top = b->lines;
- b->scroll_bot = b->lines + b->rows;
- break;
- case 2:
- new_top = param[0] - 1;
- new_bot = param[1];
-
- /* clamp to bounds */
- if (new_top < 0)
- new_top = 0;
- if (new_top >= b->rows)
- new_top = b->rows - 1;
- if (new_bot < 0)
- new_bot = 0;
- if (new_bot >= b->rows)
- new_bot = b->rows;
-
- /* check for range validity */
- if (new_top < new_bot) {
- b->scroll_top = b->lines + new_top;
- b->scroll_bot = b->lines + new_bot;
- }
- break;
- default:
- return; /* malformed */
- }
- b->curs_row = b->scroll_top;
- b->curs_col = 0;
-}
-
-static
-void
-interpret_csi_mode(Vt *t, int param[], int pcount, bool set)
-{
- for (int i = 0; i < pcount; i++) {
- switch (param[i]) {
- case 4: /* insert/replace mode */
- t->insert = set;
- break;
- }
- }
-}
-
-static
-void
-interpret_csi_priv_mode(Vt *t, int param[], int pcount, bool set)
-{
- for (int i = 0; i < pcount; i++) {
- switch (param[i]) {
- case 1: /* set application/normal cursor key mode (DECCKM) */
- t->curskeymode = set;
- break;
- case 6: /* set origin to relative/absolute (DECOM) */
- t->relposmode = set;
- break;
- case 25: /* make cursor visible/invisible (DECCM) */
- t->curshid = !set;
- break;
- case 1049: /* combine 1047 + 1048 */
- case 47: /* use alternate/normal screen buffer */
- case 1047:
- if (!set)
- buffer_clear(&t->buffer_alternate);
- t->buffer = set ? &t->buffer_alternate : &t->buffer_normal;
- vt_dirty(t);
- if (param[i] != 1049)
- break;
- /* fall through */
- case 1048: /* save/restore cursor */
- if (set)
- cursor_save(t);
- else
- cursor_restore(t);
- break;
- case 1000: /* enable/disable normal mouse tracking */
- t->mousetrack = set;
- break;
- }
- }
-}
-
-static
-void
-interpret_csi(Vt *t)
-{
- Buffer *b = t->buffer;
- int csiparam[16];
- uint param_count = 0;
- const char *p = t->ebuf + 1;
- char verb = t->ebuf[t->elen - 1];
-
- /* parse numeric parameters */
- for (p += (t->ebuf[1] == '?'); *p; p++) {
- if (IS_CONTROL(*p)) {
- process_nonprinting(t, *p);
- } else if (*p == ';') {
- if (param_count >= arrlen(csiparam))
- return; /* too long! */
- csiparam[param_count++] = 0;
- } else if (isdigit((uchar)*p)) {
- if (param_count == 0)
- csiparam[param_count++] = 0;
- csiparam[param_count - 1] *= 10;
- csiparam[param_count - 1] += *p - '0';
- }
- }
-
- if (t->ebuf[1] == '?') {
- switch (verb) {
- case 'h':
- case 'l': /* private set/reset mode */
- interpret_csi_priv_mode(t, csiparam, param_count, verb == 'h');
- break;
- }
- return;
- }
-
- /* delegate handling depending on command character (verb) */
- switch (verb) {
- case 'h':
- case 'l': /* set/reset mode */
- interpret_csi_mode(t, csiparam, param_count, verb == 'h');
- break;
- case 'm': /* set attribute */
- interpret_csi_sgr(t, csiparam, param_count);
- break;
- case 'J': /* erase display */
- interpret_csi_ed(t, csiparam, param_count);
- break;
- case 'H':
- case 'f': /* move cursor */
- interpret_csi_cup(t, csiparam, param_count);
- break;
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'e':
- case 'a':
- case 'd':
- case '`': /* relative move */
- interpret_csi_c(t, verb, csiparam, param_count);
- break;
- case 'K': /* erase line */
- interpret_csi_el(t, csiparam, param_count);
- break;
- case '@': /* insert characters */
- interpret_csi_ich(t, csiparam, param_count);
- break;
- case 'P': /* delete characters */
- interpret_csi_dch(t, csiparam, param_count);
- break;
- case 'L': /* insert lines */
- interpret_csi_il(t, csiparam, param_count);
- break;
- case 'M': /* delete lines */
- interpret_csi_dl(t, csiparam, param_count);
- break;
- case 'X': /* erase chars */
- interpret_csi_ech(t, csiparam, param_count);
- break;
- case 'S': /* SU: scroll up */
- vt_scroll(t, param_count ? -csiparam[0] : -1);
- break;
- case 'T': /* SD: scroll down */
- vt_scroll(t, param_count ? csiparam[0] : 1);
- break;
- case 'Z': /* CBT: cursor backward tabulation */
- puttab(t, param_count ? -csiparam[0] : -1);
- break;
- case 'g': /* TBC: tabulation clear */
- switch (param_count ? csiparam[0] : 0) {
- case 0:
- b->tabs[b->curs_col] = false;
- break;
- case 3:
- memset(b->tabs, 0, sizeof(*b->tabs) * b->maxcols);
- break;
- }
- break;
- case 'r': /* set scrolling region */
- interpret_csi_decstbm(t, csiparam, param_count);
- break;
- case 's': /* save cursor location */
- cursor_save(t);
- break;
- case 'u': /* restore cursor location */
- cursor_restore(t);
- break;
- case 'n': /* query cursor location */
- if (param_count == 1 && csiparam[0] == 6)
- send_curs(t);
- break;
- default:
- break;
- }
-}
-
-/* Interpret an 'index' (IND) sequence */
-static
-void
-interpret_csi_ind(Vt *t)
-{
- Buffer *b = t->buffer;
- if (b->curs_row < b->lines + b->rows - 1)
- b->curs_row++;
-}
-
-/* Interpret a 'reverse index' (RI) sequence */
-static
-void
-interpret_csi_ri(Vt *t)
-{
- Buffer *b = t->buffer;
- if (b->curs_row > b->scroll_top)
- b->curs_row--;
- else {
- row_roll(b->scroll_top, b->scroll_bot, -1);
- row_set(b->scroll_top, 0, b->cols, b);
- }
-}
-
-/* Interpret a 'next line' (NEL) sequence */
-static
-void
-interpret_csi_nel(Vt *t)
-{
- Buffer *b = t->buffer;
- if (b->curs_row < b->lines + b->rows - 1) {
- b->curs_row++;
- b->curs_col = 0;
- }
-}
-
-/* Interpret a 'select character set' (SCS) sequence */
-static
-void
-interpret_csi_scs(Vt *t)
-{
- /* ESC ( sets G0, ESC ) sets G1 */
- t->charsets[!!(t->ebuf[0] == ')')] = (t->ebuf[1] == '0');
- t->graphmode = t->charsets[0];
-}
-
-/* Interpret an 'operating system command' (OSC) sequence */
-static
-void
-interpret_osc(Vt *t)
-{
- /* ESC ] command ; data BEL
- * ESC ] command ; data ESC \\
- * Note that BEL or ESC \\ have already been replaced with NUL.
- */
- char *data = nil;
- int command = strtoul(t->ebuf + 1, &data, 10);
- if (data && *data == ';') {
- switch (command) {
- case 0: /* icon name and window title */
- case 2: /* window title */
- if (t->title_handler)
- t->title_handler(t, data+1);
- break;
- case 1: /* icon name */
- break;
- default:
-#ifndef NDEBUG
- fprintf(stderr, "unknown OSC command: %d\n", command);
-#endif
- break;
- }
- }
-}
-
-static
-void
-try_interpret_escape_seq(Vt *t)
-{
- char lastchar = t->ebuf[t->elen - 1];
-
- if (!*t->ebuf)
- return;
-
- switch (*t->ebuf) {
- case '#': /* ignore DECDHL, DECSWL, DECDWL, DECHCP, DECFPP */
- if (t->elen == 2) {
- if (lastchar == '8') { /* DECALN */
- interpret_csi_ed(t, (int []){ 2 }, 1);
- goto handled;
- }
- goto cancel;
- }
- break;
- case '(':
- case ')':
- if (t->elen == 2) {
- interpret_csi_scs(t);
- goto handled;
- }
- break;
- case ']': /* OSC - operating system command */
- if (lastchar == '\a' ||
- (lastchar == '\\' && t->elen >= 2 && t->ebuf[t->elen - 2] == '\e')) {
- t->elen -= lastchar == '\a' ? 1 : 2;
- t->ebuf[t->elen] = '\0';
- interpret_osc(t);
- goto handled;
- }
- break;
- case '[': /* CSI - control sequence introducer */
- if (is_valid_csi_ender(lastchar)) {
- interpret_csi(t);
- goto handled;
- }
- break;
- case '7': /* DECSC: save cursor and attributes */
- attributes_save(t);
- cursor_save(t);
- goto handled;
- case '8': /* DECRC: restore cursor and attributes */
- attributes_restore(t);
- cursor_restore(t);
- goto handled;
- case 'D': /* IND: index */
- interpret_csi_ind(t);
- goto handled;
- case 'M': /* RI: reverse index */
- interpret_csi_ri(t);
- goto handled;
- case 'E': /* NEL: next line */
- interpret_csi_nel(t);
- goto handled;
- case 'H': /* HTS: horizontal tab set */
- t->buffer->tabs[t->buffer->curs_col] = true;
- goto handled;
- default:
- goto cancel;
- }
-
- if (t->elen + 1 >= sizeof(t->ebuf)) {
-cancel:
-#ifndef NDEBUG
- fprintf(stderr, "cancelled: \\033");
- for (uint i = 0; i < t->elen; i++) {
- if (isprint(t->ebuf[i])) {
- fputc(t->ebuf[i], stderr);
- } else {
- fprintf(stderr, "\\%03o", t->ebuf[i]);
- }
- }
- fputc('\n', stderr);
-#endif
-handled:
- cancel_escape_sequence(t);
- }
-}
-
-static
-void
-puttab(Vt *t, int count)
-{
- Buffer *b = t->buffer;
- int direction = count >= 0 ? 1 : -1;
- for (int col = b->curs_col + direction; count; col += direction) {
- if (col < 0) {
- b->curs_col = 0;
- break;
- }
- if (col >= b->cols) {
- b->curs_col = b->cols - 1;
- break;
- }
- if (b->tabs[col]) {
- b->curs_col = col;
- count -= direction;
- }
- }
-}
-
-static
-void
-process_nonprinting(Vt *t, wchar_t wc)
-{
- Buffer *b = t->buffer;
- switch (wc) {
- case '\e': /* ESC */
- new_escape_sequence(t);
- break;
- case '\a': /* BEL */
- if (t->urgent_handler)
- t->urgent_handler(t);
- break;
- case '\b': /* BS */
- if (b->curs_col > 0)
- b->curs_col--;
- break;
- case '\t': /* HT */
- puttab(t, 1);
- break;
- case '\r': /* CR */
- b->curs_col = 0;
- break;
- case '\v': /* VT */
- case '\f': /* FF */
- case '\n': /* LF */
- cursor_line_down(t);
- break;
- case '\016': /* SO: shift out, invoke the G1 character set */
- t->graphmode = t->charsets[1];
- break;
- case '\017': /* SI: shift in, invoke the G0 character set */
- t->graphmode = t->charsets[0];
- break;
- }
-}
-
-static
-void
-is_utf8_locale(void)
-{
- const char *cset = nl_langinfo(CODESET);
- if (!cset)
- cset = "ANSI_X3.4-1968";
- is_utf8 = !strcmp(cset, "UTF-8");
-}
-
-static
-wchar_t
-get_vt100_graphic(char c)
-{
- static char vt100_acs[] = "`afgjklmnopqrstuvwxyz{|}~";
-
- /*
- * 5f-7e standard vt100
- * 40-5e rxvt extension for extra curses acs chars
- */
- static uint16_t const vt100_utf8[62] = {
- 0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259a, 0x2603, // 41-47
- 0, 0, 0, 0, 0, 0, 0, 0, // 48-4f
- 0, 0, 0, 0, 0, 0, 0, 0, // 50-57
- 0, 0, 0, 0, 0, 0, 0, 0x0020, // 58-5f
- 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1, // 60-67
- 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba, // 68-6f
- 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c, // 70-77
- 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, // 78-7e
- };
-
- if (is_utf8)
- return vt100_utf8[c - 0x41];
- else if (strchr(vt100_acs, c))
- return NCURSES_ACS(c);
- return '\0';
-}
-
-static
-void
-put_wc(Vt *t, wchar_t wc)
-{
- int width = 0;
-
- if (!t->seen_input) {
- t->seen_input = 1;
- kill(-t->pid, SIGWINCH);
- }
-
- if (t->escaped) {
- if (t->elen + 1 < sizeof(t->ebuf)) {
- t->ebuf[t->elen] = wc;
- t->ebuf[++t->elen] = '\0';
- try_interpret_escape_seq(t);
- } else {
- cancel_escape_sequence(t);
- }
- } else if (IS_CONTROL(wc)) {
- process_nonprinting(t, wc);
- } else {
- if (t->graphmode) {
- if (wc >= 0x41 && wc <= 0x7e) {
- wchar_t gc = get_vt100_graphic(wc);
- if (gc)
- wc = gc;
- }
- width = 1;
- } else if ((width = wcwidth(wc)) < 1) {
- width = 1;
- }
- Buffer *b = t->buffer;
- Cell blank_cell = { L'\0', build_attrs(b->curattrs), b->curfg, b->curbg };
- if (width == 2 && b->curs_col == b->cols - 1) {
- b->curs_row->cells[b->curs_col++] = blank_cell;
- b->curs_row->dirty = true;
- }
-
- if (b->curs_col >= b->cols) {
- b->curs_col = 0;
- cursor_line_down(t);
- }
-
- if (t->insert) {
- Cell *src = b->curs_row->cells + b->curs_col;
- Cell *dest = src + width;
- size_t len = b->cols - b->curs_col - width;
- memmove(dest, src, len * sizeof *dest);
- }
-
- b->curs_row->cells[b->curs_col] = blank_cell;
- b->curs_row->cells[b->curs_col++].text = wc;
- b->curs_row->dirty = true;
- if (width == 2)
- b->curs_row->cells[b->curs_col++] = blank_cell;
- }
-}
-
-int
-vt_process(Vt *t)
-{
- int res;
- uint pos = 0;
- mbstate_t ps;
- memset(&ps, 0, sizeof(ps));
-
- if (t->pty < 0) {
- errno = EINVAL;
- return -1;
- }
-
- /* read from the pty */
- res = read(t->pty, t->rbuf + t->rlen, sizeof(t->rbuf) - t->rlen);
- if (res < 0)
- return -1;
-
- /* process the bytes you read */
- t->rlen += res;
- while (pos < t->rlen) {
- wchar_t wc;
- ssize_t len;
-
- len = (ssize_t)mbrtowc(&wc, t->rbuf + pos, t->rlen - pos, &ps);
- if (len == -2) {
- t->rlen -= pos;
- memmove(t->rbuf, t->rbuf + pos, t->rlen);
- return 0;
- }
-
- if (len == -1) {
- len = 1;
- wc = t->rbuf[pos];
- }
-
- pos += len ? len : 1;
- put_wc(t, wc);
- }
-
- t->rlen -= pos;
- memmove(t->rbuf, t->rbuf + pos, t->rlen);
- return 0;
-}
-
-void
-vt_default_colors_set(Vt *t, attr_t attrs, short fg, short bg)
-{
- t->defattrs = attrs;
- t->deffg = fg;
- t->defbg = bg;
-}
-
-Vt *
-vt_create(int rows, int cols, int scroll_size)
-{
- if (rows <= 0 || cols <= 0)
- return nil;
-
- Vt *t = calloc(1, sizeof(Vt));
- if (!t)
- return nil;
-
- t->pty = -1;
- t->deffg = t->defbg = -1;
- t->buffer = &t->buffer_normal;
-
- if (!buffer_init(&t->buffer_normal, rows, cols, scroll_size) ||
- !buffer_init(&t->buffer_alternate, rows, cols, 0)) {
- free(t);
- return nil;
- }
-
- return t;
-}
-
-void
-vt_resize(Vt *t, int rows, int cols)
-{
- struct winsize ws = { .ws_row = rows, .ws_col = cols };
-
- if (rows <= 0 || cols <= 0)
- return;
-
- vt_noscroll(t);
- buffer_resize(&t->buffer_normal, rows, cols);
- buffer_resize(&t->buffer_alternate, rows, cols);
- cursor_clamp(t);
- ioctl(t->pty, TIOCSWINSZ, &ws);
- kill(-t->pid, SIGWINCH);
-}
-
-void
-vt_destroy(Vt *t)
-{
- if (!t)
- return;
- buffer_free(&t->buffer_normal);
- buffer_free(&t->buffer_alternate);
- close(t->pty);
- free(t);
-}
-
-void
-vt_dirty(Vt *t)
-{
- Buffer *b = t->buffer;
- for (Row *row = b->lines, *end = row + b->rows; row < end; row++)
- row->dirty = true;
-}
-
-void
-vt_draw(Vt *t, WINDOW *win, int srow, int scol)
-{
- Buffer *b = t->buffer;
-
- if (srow != t->srow || scol != t->scol) {
- vt_dirty(t);
- t->srow = srow;
- t->scol = scol;
- }
-
- for (int i = 0; i < b->rows; i++) {
- Row *row = b->lines + i;
-
- if (!row->dirty)
- continue;
-
- wmove(win, srow + i, scol);
- Cell *cell = nil;
- for (int j = 0; j < b->cols; j++) {
- Cell *prev_cell = cell;
- cell = row->cells + j;
- if (!prev_cell || cell->attr != prev_cell->attr
- || cell->fg != prev_cell->fg
- || cell->bg != prev_cell->bg) {
- if (cell->attr == A_NORMAL)
- cell->attr = t->defattrs;
- if (cell->fg == -1)
- cell->fg = t->deffg;
- if (cell->bg == -1)
- cell->bg = t->defbg;
- wattrset(win, cell->attr << NCURSES_ATTR_SHIFT);
- wcolor_set(win, vt_color_get(t, cell->fg, cell->bg), nil);
- }
-
- if (is_utf8 && cell->text >= 128) {
- char buf[MB_CUR_MAX + 1];
- size_t len = wcrtomb(buf, cell->text, nil);
- if (len > 0) {
- waddnstr(win, buf, len);
- if (wcwidth(cell->text) > 1)
- j++;
- }
- } else {
- waddch(win, cell->text > ' ' ? cell->text : ' ');
- }
- }
-
- int x, y;
- getyx(win, y, x);
- (void)y;
- if (x && x < b->cols - 1)
- whline(win, ' ', b->cols - x);
-
- row->dirty = false;
- }
-
- wmove(win, srow + b->curs_row - b->lines, scol + b->curs_col);
-}
-
-void
-vt_scroll(Vt *t, int rows)
-{
- Buffer *b = t->buffer;
- if (!b->scroll_size)
- return;
- if (rows < 0) { /* scroll back */
- if (rows < -b->scroll_above)
- rows = -b->scroll_above;
- } else { /* scroll forward */
- if (rows > b->scroll_below)
- rows = b->scroll_below;
- }
- buffer_scroll(b, rows);
- b->scroll_below -= rows;
-}
-
-void
-vt_noscroll(Vt *t)
-{
- int scroll_below = t->buffer->scroll_below;
- if (scroll_below)
- vt_scroll(t, scroll_below);
-}
-
-pid_t
-vt_forkpty(Vt *t, const char *p, const char *argv[], const char *cwd, const char *env[], int *to, int *from)
-{
- int vt2ed[2], ed2vt[2];
- struct winsize ws;
- ws.ws_row = t->buffer->rows;
- ws.ws_col = t->buffer->cols;
- ws.ws_xpixel = ws.ws_ypixel = 0;
-
- if (to && pipe(vt2ed)) {
- *to = -1;
- to = nil;
- }
- if (from && pipe(ed2vt)) {
- *from = -1;
- from = nil;
- }
-
- pid_t pid = forkpty(&t->pty, nil, nil, &ws);
- if (pid < 0)
- return -1;
-
- if (pid == 0) {
- setsid();
-
- sigset_t emptyset;
- sigemptyset(&emptyset);
- sigprocmask(SIG_SETMASK, &emptyset, nil);
-
- if (to) {
- close(vt2ed[1]);
- dup2(vt2ed[0], STDIN_FILENO);
- close(vt2ed[0]);
- }
-
- if (from) {
- close(ed2vt[0]);
- dup2(ed2vt[1], STDOUT_FILENO);
- close(ed2vt[1]);
- }
-
- int maxfd = sysconf(_SC_OPEN_MAX);
- for (int fd = 3; fd < maxfd; fd++)
- if (close(fd) == -1 && errno == EBADF)
- break;
-
- for (const char **envp = env; envp && envp[0]; envp += 2)
- setenv(envp[0], envp[1], 1);
- setenv("TERM", vt_term, 1);
-
- if (cwd)
- chdir(cwd);
-
- execvp(p, (char *const *)argv);
- fprintf(stderr, "\nexecv() failed.\nCommand: '%s'\n", argv[0]);
- exit(1);
- }
-
- if (to) {
- close(vt2ed[0]);
- *to = vt2ed[1];
- }
-
- if (from) {
- close(ed2vt[1]);
- *from = ed2vt[0];
- }
-
- return t->pid = pid;
-}
-
-int
-vt_pty_get(Vt *t)
-{
- return t->pty;
-}
-
-ssize_t
-vt_write(Vt *t, const char *buf, size_t len)
-{
- ssize_t ret = len;
-
- while (len > 0) {
- ssize_t res = write(t->pty, buf, len);
- if (res < 0) {
- if (errno != EAGAIN && errno != EINTR)
- return -1;
- continue;
- }
- buf += res;
- len -= res;
- }
-
- return ret;
-}
-
-static
-void
-send_curs(Vt *t)
-{
- Buffer *b = t->buffer;
- char keyseq[16];
- snprintf(keyseq, sizeof keyseq, "\e[%d;%dR", (int)(b->curs_row - b->lines), b->curs_col);
- vt_write(t, keyseq, strlen(keyseq));
-}
-
-void
-vt_keypress(Vt *t, int keycode)
-{
- vt_noscroll(t);
-
- if (keycode >= 0 && keycode <= KEY_MAX && keytable[keycode]) {
- switch (keycode) {
- case KEY_UP:
- case KEY_DOWN:
- case KEY_RIGHT:
- case KEY_LEFT: {
- char keyseq[3] = { '\e', (t->curskeymode ? 'O' : '['), keytable[keycode][0] };
- vt_write(t, keyseq, sizeof keyseq);
- break;
- }
- default:
- vt_write(t, keytable[keycode], strlen(keytable[keycode]));
- }
- } else if (keycode <= UCHAR_MAX) {
- char c = keycode;
- vt_write(t, &c, 1);
- } else {
-#ifndef NDEBUG
- fprintf(stderr, "unhandled key %#o\n", keycode);
-#endif
- }
-}
-
-void
-vt_mouse(Vt *t, int x, int y, mmask_t mask)
-{
-#ifdef NCURSES_MOUSE_VERSION
- char seq[6] = { '\e', '[', 'M' }, state = 0, button = 0;
-
- if (!t->mousetrack)
- return;
-
- if (mask & (BUTTON1_PRESSED | BUTTON1_CLICKED))
- button = 0;
- else if (mask & (BUTTON2_PRESSED | BUTTON2_CLICKED))
- button = 1;
- else if (mask & (BUTTON3_PRESSED | BUTTON3_CLICKED))
- button = 2;
- else if (mask & (BUTTON1_RELEASED | BUTTON2_RELEASED | BUTTON3_RELEASED))
- button = 3;
-
- if (mask & BUTTON_SHIFT)
- state |= 4;
- if (mask & BUTTON_ALT)
- state |= 8;
- if (mask & BUTTON_CTRL)
- state |= 16;
-
- seq[3] = 32 + button + state;
- seq[4] = 32 + x;
- seq[5] = 32 + y;
-
- vt_write(t, seq, sizeof seq);
-
- if (mask & (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED)) {
- /* send a button release event */
- button = 3;
- seq[3] = 32 + button + state;
- vt_write(t, seq, sizeof seq);
- }
-#endif /* NCURSES_MOUSE_VERSION */
-}
-
-static
-uint
-color_hash(short fg, short bg)
-{
- if (fg == -1)
- fg = COLORS;
- if (bg == -1)
- bg = COLORS + 1;
- return fg * (COLORS + 2) + bg;
-}
-
-int
-vt_rgb_get(Vt *t, uint8 r, uint8 g, uint8 b)
-{
- return 0;
-}
-
-
-int
-vt_color_get(Vt *t, short fg, short bg)
-{
- if (fg >= COLORS)
- fg = (t ? t->deffg : default_fg);
- if (bg >= COLORS)
- bg = (t ? t->defbg : default_bg);
-
- if (!has_default_colors) {
- if (fg == -1)
- fg = (t && t->deffg != -1 ? t->deffg : default_fg);
- if (bg == -1)
- bg = (t && t->defbg != -1 ? t->defbg : default_bg);
- }
-
- if (!color2palette || (fg == -1 && bg == -1))
- return 0;
- uint index = color_hash(fg, bg);
- if (color2palette[index] == 0) {
- short oldfg, oldbg;
- for (;;) {
- if (++color_pair_current >= color_pairs_max)
- color_pair_current = color_pairs_reserved + 1;
- pair_content(color_pair_current, &oldfg, &oldbg);
- uint old_index = color_hash(oldfg, oldbg);
- if (color2palette[old_index] >= 0) {
- if (init_pair(color_pair_current, fg, bg) == OK) {
- color2palette[old_index] = 0;
- color2palette[index] = color_pair_current;
- }
- break;
- }
- }
- }
-
- int color_pair = color2palette[index];
- return color_pair >= 0 ? color_pair : -color_pair;
-}
-
-int
-vt_color_reserve(short fg, short bg)
-{
- if (!color2palette || fg >= COLORS || bg >= COLORS)
- return 0;
-
- if (!has_default_colors && fg == -1)
- fg = default_fg;
- if (!has_default_colors && bg == -1)
- bg = default_bg;
- if (fg == -1 && bg == -1)
- return 0;
-
- uint index = color_hash(fg, bg);
- if (color2palette[index] >= 0) {
- if (init_pair(color_pairs_reserved + 1, fg, bg) == OK)
- color2palette[index] = -(++color_pairs_reserved);
- }
- int color_pair = color2palette[index];
- return color_pair >= 0 ? color_pair : -color_pair;
-}
-
-int
-vt_rgb_reserve(short fg, short bg)
-{
- if (!color2palette || fg >= COLORS || bg >= COLORS)
- return 0;
-
- if (!has_default_colors && fg == -1)
- fg = default_fg;
- if (!has_default_colors && bg == -1)
- bg = default_bg;
- if (fg == -1 && bg == -1)
- return 0;
-
- uint index = color_hash(fg, bg);
- if (color2palette[index] >= 0) {
- if (init_pair(color_pairs_reserved + 1, fg, bg) == OK)
- color2palette[index] = -(++color_pairs_reserved);
- }
- int color_pair = color2palette[index];
- return color_pair >= 0 ? color_pair : -color_pair;
-}
-
-static
-void
-init_colors(void)
-{
- pair_content(0, &default_fg, &default_bg);
- if (default_fg == -1)
- default_fg = COLOR_WHITE;
- if (default_bg == -1)
- default_bg = COLOR_BLACK;
- has_default_colors = (use_default_colors() == OK);
- color_pairs_max = MIN(MAX_COLOR_PAIRS, SHRT_MAX);
-
- if (COLORS)
- color2palette = calloc((COLORS + 2) * (COLORS + 2), sizeof(int));
- /*
- * XXX: On undefined color-pairs NetBSD curses pair_content() set fg
- * and bg to default colors while ncurses set them respectively to
- * 0 and 0. Initialize all color-pairs in order to have consistent
- * behaviour despite the implementation used.
- */
- for (short i = 1; i < color_pairs_max; i++)
- init_extended_pair(i, 0, 0);
-
- vt_color_reserve(COLOR_WHITE, COLOR_BLACK);
-}
-
-void
-vt_init(void)
-{
- init_colors();
- is_utf8_locale();
- char *term = getenv("DVTM_TERM");
- if (!term)
- term = "dvtm";
-
- snprintf(vt_term, sizeof vt_term, "%s%s", term, COLORS >= 256 ? "-256color" : "");
-}
-
-void
-vt_keytable_set(const char * const keytable_overlay[], int count)
-{
- for (int k = 0; k < count && k < KEY_MAX; k++) {
- const char *keyseq = keytable_overlay[k];
- if (keyseq)
- keytable[k] = keyseq;
- }
-}
-
-void
-vt_shutdown(void)
-{
- free(color2palette);
-}
-
-void
-vt_title_handler_set(Vt *t, vt_title_handler_t handler)
-{
- t->title_handler = handler;
-}
-
-void
-vt_urgent_handler_set(Vt *t, vt_urgent_handler_t handler)
-{
- t->urgent_handler = handler;
-}
-
-void
-vt_data_set(Vt *t, void *data)
-{
- t->data = data;
-}
-
-void *
-vt_data_get(Vt *t)
-{
- return t->data;
-}
-
-bool
-vt_cursor_visible(Vt *t)
-{
- return t->buffer->scroll_below ? false : !t->curshid;
-}
-
-pid_t
-vt_pid_get(Vt *t)
-{
- return t->pid;
-}
-
-size_t
-vt_content_get(Vt *t, char **buf, bool colored)
-{
- Buffer *b = t->buffer;
- int lines = b->scroll_above + b->scroll_below + b->rows + 1;
- size_t size = lines * ((b->cols + 1) * ((colored ? 64 : 0) + MB_CUR_MAX));
- mbstate_t ps;
- memset(&ps, 0, sizeof(ps));
-
- if (!(*buf = malloc(size)))
- return 0;
-
- char *s = *buf;
- Cell *prev_cell = nil;
-
- for (Row *row = buffer_row_first(b); row; row = buffer_row_next(b, row)) {
- size_t len = 0;
- char *last_non_space = s;
- for (int col = 0; col < b->cols; col++) {
- Cell *cell = row->cells + col;
- if (colored) {
- int esclen = 0;
- if (!prev_cell || cell->attr != prev_cell->attr) {
- attr_t attr = cell->attr << NCURSES_ATTR_SHIFT;
- esclen = sprintf(s, "\033[0%s%s%s%s%s%sm",
- attr & A_BOLD ? ";1" : "",
- attr & A_DIM ? ";2" : "",
- attr & A_UNDERLINE ? ";4" : "",
- attr & A_BLINK ? ";5" : "",
- attr & A_REVERSE ? ";7" : "",
- attr & A_INVIS ? ";8" : "");
- if (esclen > 0)
- s += esclen;
- }
- if (!prev_cell || cell->fg != prev_cell->fg || cell->attr != prev_cell->attr) {
- if (cell->fg == -1)
- esclen = sprintf(s, "\033[39m");
- else
- esclen = sprintf(s, "\033[38;5;%dm", cell->fg);
- if (esclen > 0)
- s += esclen;
- }
- if (!prev_cell || cell->bg != prev_cell->bg || cell->attr != prev_cell->attr) {
- if (cell->bg == -1)
- esclen = sprintf(s, "\033[49m");
- else
- esclen = sprintf(s, "\033[48;5;%dm", cell->bg);
- if (esclen > 0)
- s += esclen;
- }
- prev_cell = cell;
- }
- if (cell->text) {
- len = wcrtomb(s, cell->text, &ps);
- if (len > 0)
- s += len;
- last_non_space = s;
- } else if (len) {
- len = 0;
- } else {
- *s++ = ' ';
- }
- }
-
- s = last_non_space;
- *s++ = '\n';
- }
-
- return s - *buf;
-}
-
-int
-vt_content_start(Vt *t)
-{
- return t->buffer->scroll_above;
-}
diff --git a/sys/cmd/dvtm/vt.h b/sys/cmd/dvtm/vt.h
deleted file mode 100644
index dfc94b3..0000000
--- a/sys/cmd/dvtm/vt.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* see LICENSE for details */
-#pragma once
-#include <u.h>
-
-#include <vendor/curses.h>
-#include <stdbool.h>
-#include <sys/types.h>
-
-#ifndef NCURSES_MOUSE_VERSION
-#define mmask_t ulong
-#endif
-
-typedef struct Vt Vt;
-typedef void (*vt_title_handler_t)(Vt*, const char *title);
-typedef void (*vt_urgent_handler_t)(Vt*);
-
-void vt_init(void);
-void vt_shutdown(void);
-
-void vt_keytable_set(char const * const keytable_overlay[], int count);
-void vt_default_colors_set(Vt*, attr_t attrs, short fg, short bg);
-void vt_title_handler_set(Vt*, vt_title_handler_t);
-void vt_urgent_handler_set(Vt*, vt_urgent_handler_t);
-void vt_data_set(Vt*, void *);
-void *vt_data_get(Vt*);
-
-Vt *vt_create(int rows, int cols, int scroll_buf_sz);
-void vt_resize(Vt*, int rows, int cols);
-void vt_destroy(Vt*);
-pid_t vt_forkpty(Vt*, const char *p, const char *argv[], const char *cwd, const char *env[], int *to, int *from);
-int vt_pty_get(Vt*);
-bool vt_cursor_visible(Vt*);
-
-int vt_process(Vt *);
-void vt_keypress(Vt *, int keycode);
-ssize_t vt_write(Vt*, const char *buf, size_t len);
-void vt_mouse(Vt*, int x, int y, mmask_t mask);
-void vt_dirty(Vt*);
-void vt_draw(Vt*, WINDOW *win, int startrow, int startcol);
-int vt_color_get(Vt*, short fg, short bg);
-int vt_color_reserve(short fg, short bg);
-
-void vt_scroll(Vt*, int rows);
-void vt_noscroll(Vt*);
-
-pid_t vt_pid_get(Vt*);
-size_t vt_content_get(Vt*, char **s, bool colored);
-int vt_content_start(Vt*);
diff --git a/sys/cmd/echo/echo.c b/sys/cmd/echo/echo.c
deleted file mode 100644
index adac611..0000000
--- a/sys/cmd/echo/echo.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <u.h>
-#include <libn.h>
-
-int
-main(int argc, char *argv[])
-{
- char *s, *b, *c;
- int i, nnl, len;
- static char buf[2*1024];
-
- nnl = (argc>1) && strcmp(argv[1], "-n")==0;
-
- len = 1;
- for(i = 1+nnl; i < argc; i++)
- len += strlen(argv[i])+1;
-
- if (len >= arrlen(buf)) {
- s = b = calloc(len, sizeof *s);
- if (!s)
- exits("no memory");
- } else
- s = b = buf;
-
- for (i = 1+nnl; i < argc; i++) {
- c = argv[i];
- while(*c)
- *b++ = *c++;
- if (i < argc-1)
- *b++ = ' ';
- }
-
- if (!nnl)
- *b++ = '\n';
-
- if (write(1, s, b-s) < 0)
- exits("write error");
-
- exit(0);
-}
diff --git a/sys/cmd/echo/rules.mk b/sys/cmd/echo/rules.mk
deleted file mode 100644
index 5f531ff..0000000
--- a/sys/cmd/echo/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := $(d)/echo.c
-BINS_$(d) := $(d)/echo
-
-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/ls/ls.c b/sys/cmd/ls/ls.c
deleted file mode 100644
index 86aaa48..0000000
--- a/sys/cmd/ls/ls.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <u.h>
-#include <libn.h>
-
-static struct Flags {
- uchar a : 1; /* show all files */
- uchar r : 1; /* reverse sort */
- uchar v : 1; /* print detailed information */
- uchar h : 1; /* human readable */
- uchar s : 1; /* sort by size */
-} flag;
-
-static
-void
-usage(void)
-{
- fputs("usage: ls [-ahsrv] [file ...]\n", stderr);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- int i;
- ARGBEGIN{
- case 'a': flag.a++; break;
- default:
- usage();
- }ARGEND;
-
- switch(argc) {
- case 0:
- *--argv = ".", ++argc;
- /* fallthrough */
- case 1:
- }
-}
diff --git a/sys/cmd/ls/rules.mk b/sys/cmd/ls/rules.mk
deleted file mode 100644
index d2990f0..0000000
--- a/sys/cmd/ls/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := $(d)/ls.c
-BINS_$(d) := $(d)/ls
-
-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/mv/mv.c b/sys/cmd/mv/mv.c
deleted file mode 100644
index 0d19248..0000000
--- a/sys/cmd/mv/mv.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <u.h>
-#include <libn.h>
-
-static struct Flags
-{
- uchar f : 1;
- uchar i : 1;
- uchar v : 1;
-} flag;
-
-static
-char *
-strcpyn(char *dst, char *src, int n)
-{
- while(*src && n-->0)
- *dst++ = *src++;
-
- *dst = 0;
- return dst;
-}
-
-static
-int
-mv(char *from, char *to)
-{
- io·Stat src, dst;
-
- if(lstat(from, &src)) {
- errorf("%s", from);
- return 1;
- }
-
- if(!flag.f && !access(to, F_OK)) {
- int ask = 1;
- int ch, first;
-
- if(flag.i && !access(from, F_OK))
- fprintf(stderr, "overwrite %s? ", to);
- else
- ask = 0;
-
- if (ask) {
- first = ch = getchar();
- while (ch != '\n' && ch != EOF)
- ch = getchar();
-
- if (first != 'y' || first != 'Y')
- return 0;
- }
- }
-
- if(!rename(from, to)) {
- if (flag.v)
- fprintf(stdout, "%s -> %s\n", from, to);
- return 0;
- }
-
- /* TODO: errno = EXDEV */
- errorf("rename: %s to %s: %s", from, to, strerror(errno));
- return 1;
-}
-
-static
-void
-usage(void)
-{
- fputs("usage: mv [-fiv] source ... dest\n", stderr);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- int err, len;
- io·Stat info;
- char *arg, *nm, *e, path[4096];
-
- ARGBEGIN{
- case 'f':
- flag.f++;
- break;
- case 'i':
- flag.i++;
- break;
- case 'v':
- flag.v++;
- break;
- default:
- usage();
- }ARGEND;
-
- if(argc < 2)
- usage();
-
- if(stat(argv[argc-1],&info) || !S_ISDIR(info.st_mode)) {
- if (argc > 2)
- usage();
- exit(mv(argv[0], argv[1]));
- }
-
- /* we know the last argument is a directory */
- e = strcpyn(path, argv[argc-1], sizeof path-1);
- *e++ = '/';
-
- for(err=0; --argc; ++argv) {
- arg = argv[0];
-
- if ((nm = strrchr(arg, '/')) == nil)
- nm = arg;
- else {
- /* case: name/ */
- if (!nm[1]) {
- while(nm >= arg && nm[0] == '/')
- nm--;
- while(nm >= arg && nm[0] != '/')
- nm--;
- }
- nm++;
- }
-
- if ((len = strlen(nm)) >= arrend(path)-e) {
- errorf("%s: path name overflow\n", arg);
- err++;
- continue;
- }
- memmove(e, nm, len+1);
- err += mv(arg, path);
- }
- exit(err);
-}
diff --git a/sys/cmd/mv/rules.mk b/sys/cmd/mv/rules.mk
deleted file mode 100644
index f282ed8..0000000
--- a/sys/cmd/mv/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := $(d)/mv.c
-BINS_$(d) := $(d)/mv
-
-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/rc/code.c b/sys/cmd/rc/code.c
deleted file mode 100644
index edf47cf..0000000
--- a/sys/cmd/rc/code.c
+++ /dev/null
@@ -1,335 +0,0 @@
-#include "rc.h"
-
-#define delcode 100
-#define c0 t->child[0]
-#define c1 t->child[1]
-#define c2 t->child[2]
-
-#define emitf(x) ((code.ip!=code.end || morecode()), code.ip++->f = (x), code.ip)
-#define emiti(x) ((code.ip!=code.end || morecode()), code.ip++->i = (x), code.ip)
-#define emits(x) ((code.ip!=code.end || morecode()), code.ip++->s = (x), code.ip)
-
-static struct
-{
- int cap;
- Code *buf, *ip, *end;
-} code;
-
-static
-int
-morecode(void)
-{
- code.cap += delcode;
- code.buf = erealloc(code.buf, code.cap*sizeof(*code.buf));
- code.end = code.ip + delcode;
- memset(code.ip, 0, delcode*sizeof(*code.buf));
-
- return 0;
-}
-
-static
-void
-stuffdot(Code *p)
-{
- int a;
-
- a = p - code.buf;
- if (code.ip <= p || p < code.buf)
- panic("bad address %d in stuffdot", a);
- code.buf[a].i = code.ip-code.buf;
-}
-
-static
-void
-rcc(Tree *t, int eflag)
-{
- Code *p, *q;
- Tree *tt;
-
- if (!t)
- return;
-
- switch(t->type) {
- default:
- pfmt(errio, "bad type %d in rc compiler\n", t->type);
- break;
- case Tdol:
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xdol);
- break;
- case Tquote:
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xflatten);
- break;
- case Tsub:
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xmark);
- rcc(c1, eflag);
- emitf(Xsub);
- break;
- case Tand:
- emitf(Xasync);
- p = emiti(0);
- rcc(c0, eflag);
- emitf(Xexit);
- stuffdot(p);
- break;
- case Tsemi:
- rcc(c0, eflag);
- rcc(c1, eflag);
- break;
- case Tcarot:
- emitf(Xmark);
- rcc(c1, eflag);
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xcat);
- break;
- case Ttick:
- emitf(Xcmdsub);
- p = emiti(0);
- rcc(c0, 0);
- emitf(Xexit);
- stuffdot(p);
- break;
- case Tandand:
- rcc(c0, 0);
- emitf(Xtrue);
- p = emiti(0);
- rcc(c1, eflag);
- stuffdot(p);
- break;
- case Targs:
- rcc(c1, eflag);
- rcc(c0, eflag);
- break;
- case Tbang:
- rcc(c0, eflag);
- emitf(Xnegate);
- break;
- case Tparen:
- case Tbrace:
- rcc(c0, eflag);
- break;
- case Tcount:
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xcount);
- break;
- case Tfunc:
- emitf(Xmark);
- rcc(c0, eflag);
- if(c1){
- emitf(Xfunc);
- p = emiti(0);
- emits(fnstr(c1));
- rcc(c1, eflag);
- emitf(Xunlocal); /* get rid of $* */
- emitf(Xkill);
- stuffdot(p);
- } else
- emitf(Xunfunc);
- break;
- case Tif:
- rcc(c0, 0);
- emitf(Xif);
- p = emiti(0);
- rcc(c1, eflag);
- // emitf(Xwastrue);
- stuffdot(p);
- break;
- // case Telse:
- // if(!runq->iflast)
- // rcerror("`else' does not follow `if(...)'");
- // emitf(Xelse);
- // p = emiti(0);
- // rcc(c0, eflag);
- // stuffdot(p);
- // break;
- case Toror:
- rcc(c0, 0);
- emitf(Xfalse);
- p = emiti(0);
- rcc(c1, eflag);
- stuffdot(p);
- break;
- case Tpcmd:
- rcc(c0, eflag);
- break;
- case Tsimple:
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xsimple);
- if(eflag)
- emitf(Xeflag);
- break;
- case Tsubshell:
- emitf(Xsubshell);
- p = emiti(0);
- rcc(c0, eflag);
- emitf(Xexit);
- stuffdot(p);
- if(eflag)
- emitf(Xeflag);
- break;
- case Tswitch:
- codeswitch(t, eflag);
- break;
- case Ttwiddle:
- emitf(Xmark);
- rcc(c1, eflag);
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xmatch);
- if(eflag)
- emitf(Xeflag);
- break;
- case Twhile:
- q = code.ip;
- rcc(c0, 0);
- if(q==code.ip)
- emitf(Xsettrue); /* empty condition == while(true) */
- emitf(Xtrue);
- p = emiti(0);
- rcc(c1, eflag);
- emitf(Xjump);
- emiti(q-code.buf);
- stuffdot(p);
- break;
- case Twords:
- rcc(c1, eflag);
- rcc(c0, eflag);
- break;
- case Tfor:
- emitf(Xmark);
- if(c1){
- rcc(c1, eflag);
- emitf(Xglob);
- } else{
- emitf(Xmark);
- emitf(Xword);
- emits(strdup("*"));
- emitf(Xdol);
- }
- emitf(Xmark); /* dummy value for Xlocal */
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xlocal);
- p = emitf(Xfor);
- q = emiti(0);
- rcc(c2, eflag);
- emitf(Xjump);
- emiti(p-code.buf);
- stuffdot(q);
- emitf(Xunlocal);
- break;
- case Tword:
- emitf(Xword);
- emits(strdup(t->str));
- break;
- case Tdup:
- if(t->redir.type == Rdupfd){
- emitf(Xdup);
- emiti(t->redir.fd[0]);
- emiti(t->redir.fd[1]);
- } else{
- emitf(Xclose);
- emiti(t->redir.fd[0]);
- }
- rcc(c1, eflag);
- emitf(Xpopredir);
- break;
- case Tpipefd:
- emitf(Xpipefd);
- emiti(t->redir.type);
- p = emiti(0);
- rcc(c0, eflag);
- emitf(Xexit);
- stuffdot(p);
- break;
- case Tredir:
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xglob);
- switch(t->redir.type){
- case Rappend:
- emitf(Xappend);
- break;
- case Rwrite:
- emitf(Xwrite);
- break;
- case Rread:
- case Rhere:
- emitf(Xread);
- break;
- case Rrdwr:
- emitf(Xrdwr);
- break;
- }
- emiti(t->redir.fd[0]);
- rcc(c1, eflag);
- emitf(Xpopredir);
- break;
- case Teq:
- tt = t;
- for(;t && t->type==Teq;t = c2);
- if(t){
- for(t = tt;t->type==Teq;t = c2){
- emitf(Xmark);
- rcc(c1, eflag);
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xlocal);
- }
- rcc(t, eflag);
- for(t = tt; t->type==Teq; t = c2)
- emitf(Xunlocal);
- } else{
- for(t = tt;t;t = c2){
- emitf(Xmark);
- rcc(c1, eflag);
- emitf(Xmark);
- rcc(c0, eflag);
- emitf(Xassign);
- }
- }
- t = tt; /* so tests below will work */
- break;
- case Tpipe:
- emitf(Xpipe);
- emiti(t->redir.fd[0]);
- emiti(t->redir.fd[1]);
- p = emiti(0);
- q = emiti(0);
- rcc(c0, eflag);
- emitf(Xexit);
- stuffdot(p);
- rcc(c1, eflag);
- emitf(Xkill);
- stuffdot(q);
- emitf(Xpipewait);
- break;
- }
- if(t->type!=Telse && t->type!=Tsemi)
- shell->iflast = t->type==Tif;
- else if (c0)
- shell->iflast = c0->type==Tif;
-}
-
-Code*
-compile(Tree *t)
-{
- code.cap = delcode;
- code.buf = code.ip = emalloc(code.cap*sizeof *code.buf);
- code.end = code.ip + code.cap;
-
- emiti(0);
- rcc(t, 0);
- emitf(Xkill);
- emitf(nil);
-
- return code.buf;
-}
diff --git a/sys/cmd/rc/code.dep b/sys/cmd/rc/code.dep
deleted file mode 100644
index 7fdd4bc..0000000
--- a/sys/cmd/rc/code.dep
+++ /dev/null
@@ -1,166 +0,0 @@
-#if 0
-// simple example code
-error
-cd(Args args)
-{
- switch (args.len) {
- case 0:
- errorf("reached cd with no arguments!");
- return 1;
- case 1:
- one:
- errorf("sh: expected argument to command 'cd'");
- return 1;
- case 2:
- if (args.a[1] == nil)
- goto one;
- break;
- default:
- errorf("sh: too many arguments to command 'cd'");
- return 1;
- }
- if (chdir(args.a[1]))
- errorf("cd fail: %s", strerror(errno));
-
- return 0;
-}
-
-error
-quit(Args args)
-{
- exit(0);
-}
-
-Builtin builtins[] = {
- { "cd", cd },
- { "exit", quit },
-};
-
-void
-clear(Header *arr)
-{
- arr->len = 0;
-}
-
-int
-readline(Code *code)
-{
- int n, b;
-
- n = code->len;
-getchar:
- if (code->len >= code->cap) {
- code->cap += 100;
- code->s = realloc(code->s, code->cap);
- }
- /* TODO: unicode? */
- switch ((b = getchar())) {
- case EOF:
- n = -1;
- goto null;
- case '\n':
- n = code->len - n;
- null:
- code->s[code->len] = '\0';
- break;
- default:
- code->s[code->len++] = b;
- goto getchar;
- }
-
- return n;
-}
-
-/* TODO: unicode */
-int
-readargs(Code code, Args *args)
-{
- if (args->a)
- clear(&args->hdr);
- else {
- args->cap += 20;
- args->a = realloc(args->a, args->cap);
- }
-
- args->a[args->len++] = code.s;
- while (*code.s) {
- if (!isspace(*code.s++))
- continue;
-
- code.s[-1] = '\0';
- /* consume all remaining space */
- while (isspace(*code.s))
- code.s++;
-
- if (args->len >= args->cap-1) {
- args->cap += 20;
- args->a = realloc(args->a, args->cap);
- }
- args->a[args->len++] = code.s;
- }
- /* nil acts as a sentinel value */
- args->a[args->len] = nil;
-
- return args->len;
-}
-
-error
-execute(Args args)
-{
- int i, status;
- pid_t cid, wid;
-
- for (i = 0; i < arrlen(builtins); i++) {
- if (strcmp(args.a[0], builtins[i].cmd) == 0)
- return builtins[i].func(args);
- }
-
- if ((cid = fork()) == 0) {
- if (execvp(args.a[0], args.a) == -1)
- errorf("exec failed: %s", strerror(errno));
- exit(1);
- } else if (cid > 0)
- do
- wid = waitpid(cid, &status, WUNTRACED);
- while (!WIFEXITED(status) && !WIFSIGNALED(status));
- else
- errorf("fork failed: %s", strerror(errno));
-
- return status;
-}
-
-static
-void
-flush(void)
-{
- io·flush(stdout);
-}
-
-static
-void
-prompt(void)
-{
- printf(";");
- flush();
-}
-
-int
-main(int argc, char *argv[])
-{
- int i, err, n;
- Code code = {0};
- Args args = {0};
-
- ARGBEGIN {
- } ARGEND;
-
- do {
- clear(&code.hdr);
- prompt();
-
- n = readline(&code);
- readargs(code, &args);
- err = execute(args);
- } while (!err && n > 0);
-}
-#endif
diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c
deleted file mode 100644
index d4822a7..0000000
--- a/sys/cmd/rc/exec.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include "rc.h"
-
-#define W0 shell->stack->words
-// -----------------------------------------------------------------------
-// helper functions
-
-static
-void
-setstatus(char *s)
-{
- setvar("status", newword(s, nil));
-}
-
-static
-void
-pushredir(int type, int from, int to)
-{
- Redir *r;
-
- alloc(r);
- r->type = type;
- r->from = from;
- r->to = to;
- r->link = shell->redir, shell->redir = r;
-}
-
-// -----------------------------------------------------------------------
-// interpreter functions
-
-void
-Xerror(char *s)
-{
- if(!strcmp(argv0, "rc")||!strcmp(argv0, "/bin/rc"))
- pfmt(errio, "rc: %s: %r\n", s);
- else
- pfmt(errio, "rc (%s): %s: %r\n", argv0, s);
- flush(&errio);
-
- setstatus("error");
- while(!shell->interactive)
- Xkill();
-}
-
-void
-Xappend(void)
-{
- int fd;
- char *path;
-
- switch(count(W0)) {
- default:
- Xerror(">> requires a singleton list");
- return;
- case 0:
- Xerror(">> requires one file");
- return;
- case 1:
- ;
- }
-
- path = shell->stack->words->word;
- if ((fd=open(path, 1))< 0 && (fd=creat(path, 0666L))<0) {
- pfmt(errio, "%s: ", path);
- Xerror("can't open");
- return;
- }
- lseek(fd, 0L, 2);
- pushredir(Fopen, fd, shell->ip++->i);
- poplist();
-}
-
-void
-Xassign(void)
-{
- Var *v;
- if(count(W0)!=1) {
- Xerror("variable name not singleton");
- return;
- }
- unglob(W0->word);
- v = vlookup(W0->word);
- poplist();
- globlist();
- freelist(v->val);
-
- v->val = W0;
- if(v->update)
- v->update(v);
- W0 = nil;
- poplist();
-}
-
-void
-Xmark(void)
-{
- pushlist();
-}
-
-void
-Xword(void)
-{
- pushword(shell->ip++->s);
-}
-
-void Xasync(void);
-void Xcat(void);
-void Xclose(void);
-void Xcmdsub(void);
-void Xcount(void);
-void Xdol(void);
-void Xdup(void);
-void Xexit(void);
-void Xfalse(void);
-void Xflatten(void);
-void Xfor(void);
-void Xfunc(void);
-void Xglob(void);
-void Xif(void);
-void Xjump(void);
-void Xkill(void);
-void Xlocal(void);
-void Xmark(void);
-void Xmatch(void);
-void Xnegate(void);
-void Xpipe(void);
-void Xpipefd(void);
-void Xpipewait(void);
-void Xpop(void);
-void Xpopredir(void);
-void Xrdwr(void);
-void Xread(void);
-void Xsub(void);
-void Xsimple(void);
-void Xsubshell(void);
-void Xtrue(void);
-void Xunfunc(void);
-void Xunlocal(void);
-void Xword(void);
-void Xwrite(void);
diff --git a/sys/cmd/rc/glob.c b/sys/cmd/rc/glob.c
deleted file mode 100644
index 95b2ef3..0000000
--- a/sys/cmd/rc/glob.c
+++ /dev/null
@@ -1,199 +0,0 @@
-#include "rc.h"
-#include <dirent.h>
-
-static Word *matches;
-static char buffer[6*1024];
-
-// -----------------------------------------------------------------------
-// main exports
-
-void
-unglob(char *s)
-{
- char *t = s;
- do {
- if(*t==GLOB)
- t++;
- *s++ = *t;
- } while(*t++);
-}
-
-/*
- * inspiration from rsc's blog post
- * modified for utf8 sequences and character classes
- * returns 1 if string matches pattern is found, 0 otherwise
- */
-static
-int
-match(char *s, char *p)
-{
- int c, ns, np;
- rune sr, pr, lo, tr, hi;
- char *sb = s, *ss = s, *pp = p;
- while(*s || *p){
- if(*p){
- ns = utf8·bytetorune(&sr, s);
- np = utf8·bytetorune(&pr, p);
-
- if(pr==GLOB){
- np = utf8·bytetorune(&pr, ++p);
- switch(pr){
- case '?': /* single match */
- if(*s){
- p+=np, s+=ns;
- continue;
- }
- case '[': /* class match */
- np = utf8·bytetorune(&pr, ++p);
- if((c = (pr == '~')))
- np = utf8·bytetorune(&pr, ++p);
-
- lo = pr;
- while(lo != ']' && *p){
- utf8·bytetorune(&tr, p+np); /* peek ahead */
- if(tr != '-')
- hi = lo;
- else {
- p += np + 1, np = utf8·bytetorune(&hi, p);
- if(!hi) /* we hit a syntax error */
- return 0;
- if(hi < lo)
- tr = hi, hi = lo, lo = tr;
- }
- if(c ^ (lo<=sr && sr<= hi))
- goto match;
- p += np, np = utf8·bytetorune(&lo, p);
- }
- return 0;
- match:
- while (*p++ != ']' && *p); /* just iterate byte-wise */
- s += ns;
- continue;
- case '*': /* zero-or-more match */
- pp = p-1, ss = s+ns;
- p++;
- continue;
- case GLOB:
- if (sr != GLOB)
- return 0;
- s++, p++;
- continue;
- default:
- panic("unrecognized glob operation", pr);
- }
- }
-
- if (sr==pr){
- s+=ns, p+=np;
- continue;
- }
- }
- /* hit end of pattern with no match, restart at last star */
- if (ss > sb) {
- if (!*ss) /* hit end of string while matching a star */
- return 1;
-
- s = ss, p = pp;
- continue;
- }
- /* mismatch */
- return 0;
- }
- return 1;
-}
-
-static
-void
-globdir(char *p, char *path, int fd)
-{
- DIR *d = nil;
- char *g; /* pattern offset (base of new GLOB) */
- char *b; /* pointer into path */
- int i, j;
- struct dirent *e;
-
- if(!*p) {
- printf("making path %s\n", path);
- matches = newword(buffer, matches);
- return;
- }
-
- if((fd = openat(fd, path[0]?path:".", O_RDONLY|O_CLOEXEC|O_DIRECTORY)) < 0)
- return;
- d = fdopendir(fd);
-
- for(g = p, b = path; *g; b++) {
- if(*g==GLOB)
- break;
- *b=*g++;
- if(*b == '/') {
- *b = 0;
- /* open new directory (close if we have opened another already */
- if ((fd = openat(fd, path, O_RDONLY|O_CLOEXEC|O_DIRECTORY)) < 0)
- goto cleanup;
- closedir(d);
- d = fdopendir(fd);
- *b = '/';
- path = b, p = g;
- }
- }
-
- /* if we are at the end of the pattern, check if name exists */
- if(!*g) {
- *b = 0;
- if(faccessat(fd, path, F_OK, AT_SYMLINK_NOFOLLOW) == 0)
- matches = newword(buffer, matches);
- goto cleanup;
- }
-
- /* we have a non-trivial pattern to match */
- /* partition on the next directory */
- while(*g && *g!='/')
- g++;
-
- if(*g){
- j = 1;
- *g = 0;
- } else
- j = 0;
-
- while((e = readdir(d))) {
- if (e->d_name[0] == '.')
- if (e->d_name[1] == 0 || /* . */
- (e->d_name[1] == '.' && e->d_name[2] == 0)) /* .. */
- continue;
-
- for(i=0;e->d_name[i];i++)
- b[i]=e->d_name[i];
- b[i]=0;
-
- if(match(path, p))
- globdir(g+j, b, fd);
- }
-
- printf("successful\n");
-cleanup:
- printf("cleaning up\n");
- /* NOTE: a successful closedir also closes the file descriptor */
- closedir(d);
- return;
-}
-
-void
-glob(char *p)
-{
- char *path = buffer;
-
- globdir(p, path, AT_FDCWD);
-}
-
-#if 0
-int
-main()
-{
- errio = openfd(2);
- glob("\x01*");
- pval(errio, matches);
- flush(&errio);
-}
-#endif
diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c
deleted file mode 100644
index e06bfcc..0000000
--- a/sys/cmd/rc/io.c
+++ /dev/null
@@ -1,446 +0,0 @@
-#include "rc.h"
-
-#define c0 t->child[0]
-#define c1 t->child[1]
-#define c2 t->child[2]
-
-#undef bufsize
-#define bufsize 512
-#define strsize 100
-
-//------------------------------------------------------------------------
-// buffer operations
-
-/* open file */
-Io*
-openfd(int fd)
-{
- Io *f;
-
- f = emalloc(sizeof *f + bufsize);
- f->fd = fd;
- f->b = f->e = f->buf;
- return f;
-}
-
-/* open string */
-Io*
-openstr(void)
-{
- Io *f;
-
- f = emalloc(sizeof *f + strsize + 1);
- f->fd = -1;
- f->b = f->buf;
- f->e = f->buf+strsize;
- memset(f->b, 0, strsize+1);
-
- return f;
-}
-
-/* open core (not nil terminated) */
-Io*
-opencore(int len, char *s)
-{
- Io *f;
-
- f = emalloc(sizeof *f + len);
- f->fd = -1;
- f->b = f->buf;
- f->e = f->buf+len;
- memcpy(f->b, s, len);
-
- return f;
-}
-
-void
-rewindio(Io *f)
-{
- if (f->fd < 0)
- f->b = f->buf;
- else {
- f->b = f->e = f->buf;
- lseek(f->fd, 0, 0);
- }
-}
-
-void
-closeio(Io *f)
-{
- if (f->fd >= 0)
- close(f->fd);
-
- efree(f);
-}
-
-/* has the chance to realloc */
-void
-flush(Io **fp)
-{
- int n;
- char *s;
- Io *f;
-
- f = *fp;
- if (f->fd < 0) {
- n = f->e - f->b;
- f = erealloc(f, sizeof *f + n + strsize + 1);
- if (!f)
- panic("can't realloc %d bytes in flush", n+strsize+1);
- f->b = f->buf+n;
- f->e = f->buf+n+strsize;
- memset(f->b, 0, strsize+1);
- } else {
- n = f->b - f->buf;
- if (n && write(f->fd, f->buf, n) < 0) {
- write(3, "write error\n", 12);
- // if (ntrap)
- // dotrap();
- }
- f->b = f->buf;
- f->e = f->buf + bufsize;
- }
-
- *fp = f;
-}
-
-//------------------------------------------------------------------------
-// read from io
-
-int
-rchr(Io *f)
-{
- int n;
- if (f->b == f->e) {
- if (f->fd < 0 || (n = read(f->fd, f->buf, bufsize)) <= 0)
- return EOF;
-
- f->b = f->buf;
- f->e = f->b + n;
- }
-
- return *f->b++&0xFF;
-}
-
-//------------------------------------------------------------------------
-// printf functionality
-
-/* character literal */
-int
-pchr(Io *f, int c)
-{
- if (f->b == f->e)
- flush(&f);
-
- return *f->b++=c;
-}
-
-/* quote */
-void
-pquo(Io *f, char *s)
-{
- pchr(f, '\'');
- for (; *s; s++)
- if (*s == '\'')
- pfmt(f, "''");
- else
- pchr(f, *s);
- pchr(f, '\'');
-}
-
-/* word */
-void
-pwrd(Io *f, char *s)
-{
- char *t;
- for(t = s; *t; t++)
- if(!wordchr(*t))
- break;
- if(t == s || *t)
- pquo(f, s);
- else
- pstr(f, s);
-}
-
-/* pointer */
-void
-pptr(Io *f, void *v)
-{
- int n;
- uintptr p;
-
- if (!v) {
- pstr(f, "<nil>");
- return;
- }
-
- p = (uintptr)v;
- if ((sizeof(uintptr) == sizeof(uvlong)) && p >>32)
- for (n = 60; n >= 32; n-=4)
- pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
- for (n = 28; n >= 0; n-=4)
- pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
-}
-
-/* string */
-void
-pstr(Io *f, char *s)
-{
- if(!s || !s[0])
- s = "<null>";
-
- while(*s)
- pchr(f, *s++);
-}
-
-/* decimal */
-void
-pdec(Io *f, int n)
-{
- if (n < 0) {
- n = -n;
- pchr(f, '-');
- if (n >= 0) {
- pdec(f, n);
- return;
- }
- n = 1 - n;
- pdec(f, n/10);
- pchr(f, n%10+'1');
- return;
- }
-
- if (n > 9)
- pdec(f, n/10);
- pchr(f, n%10+'0');
-}
-
-/* octal */
-void
-poct(Io *f, uint n)
-{
- if (n > 7)
- poct(f, n>>3);
- pchr(f, (n&7)+'0');
-}
-
-/* value */
-void
-pval(Io *f, Word *a)
-{
- if(a) {
- while(a->link && a->link->word) {
- pwrd(f, a->word);
- pchr(f, ' ');
- a = a->link;
- }
- pwrd(f, a->word);
- }
-}
-
-/* tree */
-static
-void
-pdeglob(Io *f, char *s)
-{
- while(*s){
- if(*s==GLOB)
- s++;
- pchr(f, *s++);
- }
-}
-
-void
-pcmd(Io *f, Tree *t)
-{
- if(!t)
- return;
-
- switch(t->type){
- default: pfmt(f, "bad<%d> %p %p %p", t->type, c0, c1, c2);
- break;
- case Tdol: pfmt(f, "$%t", c0);
- break;
- case Tquote: pfmt(f, "$\"%t", c0);
- break;
- case Tand: pfmt(f, "%t&", c0);
- break;
- case Tcarot: pfmt(f, "%t^%t", c0, c1);
- break;
- case Ttick: pfmt(f, "`%t", c0);
- break;
- case Tandand: pfmt(f, "%t && %t", c0, c1);
- break;
- case Tbang: pfmt(f, "! %t", c0);
- break;
- case Tbrace: pfmt(f, "{%t}", c0);
- break;
- case Tcount: pfmt(f, "$#%t", c0);
- break;
- case Tfunc: pfmt(f, "func %t %t", c0, c1);
- break;
- case Tif: (c2) ? pfmt(f, "if%t%t else %t", c0, c1, c2): pfmt(f, "if%t%t", c0, c1);
- break;
- case Toror: pfmt(f, "%t || %t", c0, c1);
- break;
- case Tpcmd: /* fallthrough */
- case Tparen: pfmt(f, "(%t)", c0);
- break;
- case Tsub: pfmt(f, "$%t(%t)", c0, c1);
- break;
- case Tsimple: pfmt(f, "%t", c0);
- break;
- case Tsubshell: pfmt(f, "@ %t", c0);
- break;
- case Tswitch: pfmt(f, "switch %t %t", c0, c1);
- break;
- case Tcase: pfmt(f, "case %t:\n%t", c0, c1);
- break;
- case Ttwiddle: pfmt(f, "~ %t %t", c0, c1);
- break;
- case Twhile: pfmt(f, "while %t%t", c0, c1);
- break;
- case Targs:
- if(c0==0)
- pfmt(f, "%t", c1);
- else if(c1==0)
- pfmt(f, "%t", c0);
- else
- pfmt(f, "%t %t", c0, c1);
- break;
- case Tsemi:
- if(c0) {
- if(c1)
- pfmt(f, "%t%c%t", c0, '\n', c1);
- else
- pfmt(f, "%t", c0);
- } else
- pfmt(f, "%t", c1);
- break;
- case Twords:
- if(c0)
- pfmt(f, "%t ", c0);
- pfmt(f, "%t", c1);
- break;
- case Tfor:
- pfmt(f, "for(%t", c0);
- if(c1)
- pfmt(f, " in %t", c1);
- pfmt(f, ")%t", c2);
- break;
- case Tword:
- if(t->quoted)
- pfmt(f, "%Q", t->str);
- else
- pdeglob(f, t->str);
- break;
- case Tdup:
- if(t->redir.type==Rdupfd)
- pfmt(f, ">[%d=%d]", t->redir.fd[1], t->redir.fd[0]); /* yes, fd1, then fd0; read lex.c */
- else
- pfmt(f, ">[%d=]", t->redir.fd[0]);
- pfmt(f, "%t", c1);
- break;
- case Tpipefd:
- case Tredir:
- switch(t->redir.type){
- case Rhere:
- pchr(f, '<');
- case Rread:
- case Rrdwr:
- pchr(f, '<');
- if(t->redir.type==Rrdwr)
- pchr(f, '>');
- if(t->redir.fd[0]!=0)
- pfmt(f, "[%d]", t->redir.fd[0]);
- break;
- case Rappend:
- pchr(f, '>');
- case Rwrite:
- pchr(f, '>');
- if(t->redir.fd[0]!=1)
- pfmt(f, "[%d]", t->redir.fd[0]);
- break;
- }
- pfmt(f, "%t", c0);
- if(c1)
- pfmt(f, " %t", c1);
- break;
- case Teq:
- pfmt(f, "%t=%t", c0, c1);
- if(c2)
- pfmt(f, " %t", c2);
- break;
- case Tpipe:
- pfmt(f, "%t|", c0);
- if(t->redir.fd[1]==0){
- if(t->redir.fd[0]!=1)
- pfmt(f, "[%d]", t->redir.fd[0]);
- }
- else pfmt(f, "[%d=%d]", t->redir.fd[0], t->redir.fd[1]);
- pfmt(f, "%t", c1);
- break;
- }
-}
-
-/* rc specific printf */
-static int pfmtlev;
-
-void
-vpfmt(Io *f, char *fmt, va_list args)
-{
- char err[124];
-
- pfmtlev++;
- for (; *fmt; fmt++)
- if (*fmt!='%')
- pchr(f, *fmt);
- else switch(*++fmt) {
- case '\0':
- break;
- case 'c':
- pchr(f, va_arg(args, int));
- break;
- case 'd':
- pdec(f, va_arg(args, int));
- break;
- case 'o':
- poct(f, va_arg(args, uint));
- break;
- case 'p':
- pptr(f, va_arg(args, void*));
- break;
- case 'Q':
- pquo(f, va_arg(args, char*));
- break;
- case 'q':
- pwrd(f, va_arg(args, char*));
- break;
- case 'r':
- pstr(f, strerror(errno));
- break;
- case 's':
- pstr(f, va_arg(args, char*));
- break;
- case 't':
- pcmd(f, va_arg(args, Tree*));
- break;
- case 'v':
- pval(f, va_arg(args, Word*));
- break;
- }
-
- if (--pfmtlev==0)
- flush(&f);
-}
-
-void
-pfmt(Io *f, char *fmt, ...)
-{
- va_list args;
- char err[124];
-
- va_start(args, fmt);
- vpfmt(f, fmt, args);
- va_end(args);
-}
diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c
deleted file mode 100644
index f6e2b4e..0000000
--- a/sys/cmd/rc/lex.c
+++ /dev/null
@@ -1,417 +0,0 @@
-#include "rc.h"
-
-#define onebyte(c) ((c&0x80)==0x00)
-#define twobyte(c) ((c&0xe0)==0xc0)
-#define threebyte(c) ((c&0xf0)==0xe0)
-#define fourbyte(c) ((c&0xf8)==0xf0)
-
-// -----------------------------------------------------------------------
-// globals
-
-static int lastc, nextc=EOF, lastdol, lastword, doprompt = 1;
-static char buf[8*1024];
-
-// -----------------------------------------------------------------------
-// utilities
-
-static uchar nwordc[256] =
-{
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 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, 1, 0,
- 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, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-int
-wordchr(int c)
-{
- return !nwordc[c] && c!=EOF;
-}
-
-
-static uchar nquotec[256] =
-{
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 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, 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, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-int
-quotechr(char c)
-{
- return !nquotec[c] && c!=EOF;
-}
-
-static uchar nvarc[256] =
-{
- 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, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
- 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, 1, 1, 1, 1, 0,
- 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, 1, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-int
-varchr(char c)
-{
- return !nvarc[c] && c!=EOF;
-}
-
-static
-void
-prompt(void)
-{
- shell->cmd.line++;
- doprompt = 0;
-}
-
-/* lookahead one byte */
-static
-int
-lookahead(void)
-{
- int c;
-
- if(nextc != EOF)
- return nextc;
- if(shell->cmd.eof)
- return EOF;
-
- if(doprompt)
- prompt();
-
- c = rchr(shell->cmd.io);
- doprompt = c == '\n' || c == EOF;
-
- if(c == EOF)
- shell->cmd.eof++;
-
- return nextc = c;
-}
-
-/* consumes the lookahead */
-static
-int
-advance(void)
-{
- int c = lookahead();
- lastc = nextc, nextc = EOF;
-
- return c;
-}
-
-/*
- * advance until we no longer hit horizontal space
- * consumes all comments
- */
-static
-void
-skipws(void)
-{
- int c;
- for(;;) {
- c = lookahead();
- if(c=='#'){
- for(;;){
- c = lookahead();
- if(c=='\n' || c==EOF)
- break;
- advance();
- }
- }
- if(c==' ' || c=='\t')
- advance();
- else
- return;
- }
-}
-
-/* advance until we no longer hit any space */
-void
-skipnl(void)
-{
- int c;
- for(;;) {
- skipws();
- if ((c = lookahead()) != '\n')
- return;
- advance();
- }
-}
-
-/* advance if next char is equal to c */
-static
-int
-nextis(int c)
-{
- if(lookahead()==c) {
- advance();
- return 1;
- }
- return 0;
-}
-
-/* functions to append to our write buffer */
-static
-char*
-putbyte(char *s, int c)
-{
- if(!s)
- return s;
- if(s == arrend(buf)){
- *s = 0;
- rcerror("out of buffer space");
- return nil;
- }
- *s++ = c;
- return s;
-}
-
-static
-char*
-putrune(char *s, int c)
-{
- s = putbyte(s, c);
- if (onebyte(c))
- return s;
- if (twobyte(c))
- return putbyte(s, advance());
- if (threebyte(c)) {
- putbyte(s, advance());
- return putbyte(s, advance());
- }
- if (fourbyte(c)) {
- putbyte(s, advance());
- putbyte(s, advance());
- return putbyte(s, advance());
- }
- rcerror("malformed utf8 stream");
- return nil;
-}
-
-// -----------------------------------------------------------------------
-// main exports
-
-void
-rcerror(char *fmt, ...)
-{
- va_list args;
-
- pfmt(errio, "rc:");
- if (shell->cmd.io)
- pfmt(errio, "%s:%d ", shell->cmd.name, shell->cmd.line);
-
- va_start(args, fmt);
- vpfmt(errio, fmt, args);
- va_end(args);
-
- pfmt(errio, "\n");
-
- flush(&errio);
- lastword = lastdol = 0;
- while (lastc != '\n' && lastc != EOF)
- advance();
- /* for debugging only */
- abort();
-}
-
-/* word is only modified in the event of a lexed word */
-int
-lex(Tree **node)
-{
- int c;
- char *w = buf;
- /*
- * NOTE:
- * we inject tokens into the lexer based on context if last token = word:
- * if we see a (, then we interpret that as a subscript
- * otherwise, if the next character is the first char of a word, we return a ^ operator.
- */
- if(lastword){
- lastword=0;
- c = lookahead();
- if(c=='('){
- advance();
- return Tlparen;
- }
- if(quotechr(c))
- return Tcarot;
- }
-
- skipws();
- switch(c=advance()) {
- case EOF:
- lastdol = 0;
- return EOF;
- case '$':
- lastdol = 1;
- if(nextis('#'))
- return Tcount;
- if (nextis('"'))
- return Tquote;
- return Tdol;
- case '&':
- lastdol = 0;
- if(nextis('&'))
- return Tandand;
- return Tand;
-
- case '!':
- return Tbang;
- case '@':
- return Tsubshell;
- case '~':
- return Ttwiddle;
-
- case '|':
- lastdol = 0;
- if(nextis('|')){
- skipnl();
- return Toror;
- }
- (*node) = newtree();
- (*node)->type = Tpipe;
- (*node)->redir.fd[0] = 0;
- (*node)->redir.fd[1] = 1;
- goto redir;
- case '>':
- (*node) = newtree();
- (*node)->type = Tredir;
- if (nextis(c))
- (*node)->redir.type = Rappend;
- else
- (*node)->redir.type = Rwrite;
- (*node)->redir.fd[0] = 1;
- goto redir;
- case '<':
- (*node) = newtree();
- (*node)->type = Tredir;
- if(nextis(c))
- (*node)->redir.type = Rhere;
- else if(nextis('>'))
- (*node)->redir.type = Rrdwr;
- else
- (*node)->redir.type = Rread;
- (*node)->redir.fd[0] = 0;
- /* fallthrough */
- redir:
- if(nextis('[')) {
- c = advance();
- if(c < '0' || '9' < c) {
- redirerr:
- rcerror("incorrect redirection syntax");
- return EOF;
- }
- (*node)->redir.fd[0] = 0;
- do {
- (*node)->redir.fd[0] = 10*(*node)->redir.fd[0]+(c-'0');
- c = advance();
- } while('0'<=c && c<='9');
-
- if(c == '=') {
- if((*node)->type == Tredir)
- (*node)->type = Tdup;
- c = advance();
- if('0'<=c && c<='9') {
- (*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');
- c = advance();
- } while('0'<=c && c<='9');
- } else {
- if((*node)->type == Tpipe)
- goto redirerr;
- (*node)->redir.type = Rclose;
- }
- }
- if (c != ']'
- ||(*node)->type==Tdup && ((*node)->redir.type==Rhere || (*node)->redir.type==Rappend))
- goto redirerr;
- }
- if ((c = ((*node)->type)) == Tpipe)
- skipnl();
- return c;
-
- case '\'':
- lastdol = 0;
- lastword = 1;
- for(;;){
- c = advance();
- if(c==EOF)
- break;
- if(c=='\''){
- if(lookahead()!='\'')
- break;
- advance();
- }
- w = putrune(w, c);
- }
- *w = 0;
- *node = wordnode(buf);
- (*node)->quoted = 1;
- return Tword;
- }
- if (!wordchr(c)) {
- lastdol = 0;
- return c;
- }
- for(;;){
- if(c=='*'||c=='['||c=='?'||c==GLOB)
- w = putbyte(w, GLOB);
- w = putrune(w, c);
- c = lookahead();
- if(lastdol?!varchr(c):!wordchr(c))
- break;
- advance();
- }
- *w = 0;
-
- if ((c = kwlookup(buf)) == -1) {
- (*node) = wordnode(buf);
- (*node)->type = c = Tword;
- (*node)->quoted = 0;
- lastword = 1;
- }
-
- lastdol = 0;
- return c;
-}
diff --git a/sys/cmd/rc/main.c b/sys/cmd/rc/main.c
deleted file mode 100644
index b4a355e..0000000
--- a/sys/cmd/rc/main.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "rc.h"
-
-/* globals */
-Thread *shell = nil;
-int ntrap = 0;
-Io *errio;
-
-/* main execution */
-
-void
-dotrap(void)
-{
- exit(1);
-}
-
-void
-bootup(Code *c, int off, Var *vars)
-{
- Thread *sh;
-
- alloc(sh);
- sh->code = c, c->i++;
- sh->ip = sh->code + off;
- sh->local = vars;
- sh->stack = nil;
-
- sh->link = shell, shell = sh;
-}
-
-int
-main(int argc, char *argv[])
-{
- int i;
- Code *ip, sh[32];
-
- ARGBEGIN {
- } ARGEND;
-
- errio = openfd(2);
-
- initkw();
-
- ip = sh;
- memset(sh, 0, sizeof(sh));
- /*
- * NOTE: first element of code is a reference count
- * bootup runs:
- * 1. *=argv[1:]
- * 2. . rcmain $*
- */
-#if 0
- ip++->i = 1;
- ip++->f = Xmark;
- ip++->f = Xword;
- ip++->s = "*";
- ip++->f = Xassign;
- ip++->f = Xmark;
- ip++->f = Xmark;
- ip++->s = "*";
- ip++->f = Xdol;
- ip++->s = "rcmain";
- ip++->f = Xword;
- ip++->s = ".";
- ip++->f = Xsimple;
- ip++->f = Xexit;
- ip++->i = 0;
-
- bootup(sh, 1, nil);
- pushlist();
- for (i = argc-1; i != 0; i--)
- pushword(argv[i]);
-
- for (;;) {
- shell->ip++->f();
- if (ntrap)
- dotrap();
- }
-#else
- bootup(sh, 1, nil);
- shell->cmd.io = openfd(0);
- while (parse())
- ;
-
-#endif
- exit(0);
-}
diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c
deleted file mode 100644
index b61ac3c..0000000
--- a/sys/cmd/rc/parse.c
+++ /dev/null
@@ -1,496 +0,0 @@
-#include "rc.h"
-
-/* TODO: better error messages */
-
-// -----------------------------------------------------------------------
-// global data
-
-static int lastt, nextt=EOF;
-static Tree *node; /* if token was lexed as a tree node (redirs and words), its here */
-
-/* anything that is not listed will automatically terminate parsing the given command */
-static uchar prectab[256] = {
- [Tif] = 1, [Tfor] = 1, [Tswitch] = 1, /* NOTE: we give else lower precedence than if [Telse] = 1, */
- [Tandand] = 2, [Toror] = 2,
- [Tbang] = 3, [Tsubshell] = 3,
- [Tpipe] = 4,
- [Tcarot] = 5,
- [Tdol] = 6, [Tcount] = 6, [Tquote] = 6,
- [Tsub] = 7,
-};
-
-// -----------------------------------------------------------------------
-// helpers
-
-static
-int
-lookahead(void)
-{
- int tok;
-
- if (nextt != EOF)
- return nextt;
-
- tok = lex(&node);
- return nextt = tok;
-}
-
-static
-int
-advance(void)
-{
- int tok = lookahead();
- lastt = nextt, nextt = EOF;
- node = nil;
-
- return tok;
-}
-
-static
-int
-nextis(int tok)
-{
- if (lookahead() == tok) {
- advance();
- return 1;
- }
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// subparsers
-
-/* forward declarations */
-static Tree *word(void);
-static Tree *words(void);
-static Tree* body(int c);
-static Tree *comword(void);
-static Tree *cmd(int prec);
-
-/* implementations */
-
-/*
- * TODO:
- * i don't like all this branching.
- * think of a better way
- */
-
-static
-Tree*
-case_or_cmd(int c)
-{
- Tree *t;
- if (!c || !nextis(Tcase))
- return cmd(1);
-
- t = words();
- if (!nextis(';') && !nextis('\n'))
- rcerror("case: missing terminator: recieved %d", nextt);
-
- t = tree2(Tcase, t, body(0));
- pfmt(errio, "%t\n", t);
-
- return t;
-}
-
-static
-Tree*
-body(int c)
-{
- int tok;
- Tree *l, *r;
-
- skipnl();
- l = case_or_cmd(c);
-loop:
- switch((tok=lookahead())){
- case '&':
- l = tree1('&', l);
- /* fallthrough */
- case ';': case '\n':
- advance();
- /* fallthrough */
- case Tcase:
- if ((r = case_or_cmd(c))) {
- l = tree2(';', l, r);
- goto loop;
- }
- /* fallthrough */
- default:
- ;
- }
-
- return l;
-}
-
-static
-Tree*
-brace(int c)
-{
- Tree *t;
-
- if (!nextis('{'))
- rcerror("brace: expected { found: %c", nextt);
- t = tree1(Tbrace, body(c));
- if (!nextis('}'))
- rcerror("brace: expected } found: %c", nextt);
-
- return t;
-}
-
-static
-Tree*
-paren(void)
-{
- Tree *t;
-
- if (!nextis('('))
- rcerror("not a paren");
- t = tree1(Tparen, body(0));
- if (!nextis(')'))
- rcerror("unmatched paren");
-
- return t;
-}
-
-/* TODO: fill in */
-static
-Tree*
-heredoc(Tree* t)
-{
- return t;
-}
-
-static
-Tree*
-redir(void)
-{
- int tok;
- Tree *t;
-
- switch (tok = lookahead()) {
- case Tdup:
- t = node;
- advance();
- break;
- case Tredir:
- t = node;
- advance();
- t = hang1(t, (t->redir.type == Rhere) ? heredoc(word()) : word());
- break;
- default:
- t = nil;
- }
-
- return t;
-}
-
-static
-Tree*
-epilog(void)
-{
- Tree *t, *tt;
-
- t = redir();
- while((tt = redir()))
- t = hang2(t, t->child[0], tt);
-
- return t;
-}
-
-static
-Tree*
-sword(void)
-{
- int tok;
- if (Kstart < (tok=lookahead()) && tok < Kend)
- return node;
-
- return comword();
-}
-
-static
-Tree*
-word(void)
-{
- int tok;
- Tree *t;
-
- t = sword();
- while(nextis('^'))
- t = tree2('^', t, sword());
-
- return t;
-}
-
-
-static
-Tree*
-words(void)
-{
- Tree *t, *tt;
- t = word();
- while((tt=word()))
- t = tree2(Twords, t, tt);
-
- return t;
-}
-
-/*
- * NOTE: we divergence from Duff's yacc grammar here.
- * he has [dol|count|"]->word, we have [dol|count]->sword
- * calling sword ensures we don't cat strings
- * this was done in Tom's version by setting precedence
- */
-static
-Tree*
-comword(void)
-{
- int tok;
- Tree *t, *tt;
-
- switch(tok=lookahead()){
- case Tdol:
- advance();
- t = sword();
- if(nextis('(')) {
- t = tree2(Tsub, t, words());
- if (!nextis(')'))
- rcerror("malformed index expression");
- }
- return tree1(Tdol, t);
- case Tquote:
- return tree1(Tquote, sword());
- case Tcount:
- advance();
- return tree1(Tcount, sword());
- case Ttick:
- advance();
- return tree1(Ttick, brace(0));
- case Tlparen:
- return paren();
- case Tredir:
- advance();
- t = hang1(node, brace(0));
- t->type = Tpipefd;
- return t;
- case Tword:
- t = node;
- advance();
- return t;
- }
- return nil;
-}
-
-static
-Tree*
-first(void)
-{
- int tok;
- Tree *t;
-
- t = comword();
- while(nextis('^')) {
- t = tree2('^', t, word());
- }
-
- return t;
-}
-
-/* simple _or_ assignment */
-static
-Tree*
-simple_or_assign(void)
-{
- int tok;
- Tree *t, *tt;
-
- /* can't continue */
- if (!(t = first()))
- return nil;
-
- /* is an assignment */
-assign:
- if(nextis('=')) {
- tt = word();
- return tree3(Teq, t, tt, cmd(prectab[Tbang]));
- }
-
- /* is a 'simple' */
-simple:
- switch ((tok=lookahead())) {
- case Tredir:
- case Tdup:
- t = tree2(Targs, t, redir());
- goto simple;
- default:
- if ((tt = word())) {
- t = tree2(Targs, t, tt);
- goto simple;
- }
- /* fallthrough */
- }
-
- return simplehang(t);
-}
-
-static
-Tree*
-opand(void)
-{
- int tok;
- Tree *t, *tt;
-
- switch(tok=lookahead()) {
- case Tif:
- advance();
- t = paren();
- skipnl();
- tt = cmd(prectab[Tif]);
- if (nextis(Telse)) {
- skipnl();
- t = tree3(Tif, t, tt, cmd(prectab[Tif]));
- } else
- t = tree3(Tif, t, tt, nil);
- return t;
- case Telse:
- rcerror("invalid hanging else");
- break;
-
- case Tswitch:
- advance();
- t = word();
- skipnl();
- tt = brace(1);
- t = tree2(Tswitch, t, tt);
- return t;
-
- case Tfor:
- advance();
-
- if (!nextis('('))
- rcerror("for: missing opening paren");
- t = word();
- if (nextis(Tin)) {
- advance();
- tt = words();
- t = tree3(Tfor, t, tt, nil);
- } else
- t = tree3(Tfor, t, nil, nil);
- if (!nextis(')'))
- rcerror("for: missing closing paren");
-
- skipnl();
- tt = cmd(prectab[Tfor]);
- t->child[2] = tt;
- return t;
-
- case Twhile:
- advance();
- t = paren();
- skipnl();
- tt = cmd(1);
- return tree2(Twhile, t, tt);
-
- case Tfunc:
- advance();
- t = words();
- if ((tok=lookahead()) == '{') {
- tt = brace(0);
- t = tree2(Tfunc, t, tt);
- } else
- t = tree1(Tfunc, t);
- return t;
-
- case Tsubshell:
- advance();
- t = tree1(Tsubshell, cmd(prectab[Tsubshell]));
- return t;
-
- case Tbang:
- advance();
- t = tree1(Tbang, cmd(prectab[Tbang]));
- return t;
-
- case Ttwiddle:
- advance();
- tt = word();
- t = tree2(Ttwiddle, tt, words());
- return t;
-
- case Tlbrace:
- t = brace(0);
- tt = epilog();
- return epihang(t, tt);
-
- case Tredir: /* fallthrough */
- case Tdup:
- t = redir();
- tt = cmd(prectab[Tbang]);
- t = hang2(t, t->child[0], tt);
- return t;
- }
-
- return simple_or_assign();
-}
-
-static
-Tree *
-cmd(int prec)
-{
- int np, tok;
- Tree *l, *r, *p;
-
- if (!(l = opand()))
- return nil;
-
- for(;;) {
- tok = lookahead();
- np = prectab[tok];
- if (np < prec)
- break;
- p = node;
- advance();
- r = cmd(np+1);
- if (tok == Tpipe)
- l = hang2(p, l, r);
- else
- l = tree2(tok, l, r);
- }
-
- return l;
-}
-
-// -----------------------------------------------------------------------
-// main function
-
-int
-parse(void)
-{
- int tok;
- Tree *t, *tt;
-
- t = cmd(1);
-loop:
- switch(tok=lookahead()) {
- case '&':
- t = tree1('&', t);
- /* fallthrough */
- case ';':
- advance();
- tt = cmd(1);
- t = tree2(';', t, tt);
- goto loop;
- case '\n':
- advance();
- case EOF:
- pfmt(errio, "%t\n", t);
- break;
- default:
- if (tok > 0x20)
- rcerror("unrecognized token: %c[%d]", tok, tok);
- else
- rcerror("unrecognized token: %d", tok, tok);
- }
- return tok != EOF;
-}
diff --git a/sys/cmd/rc/rc.h b/sys/cmd/rc/rc.h
deleted file mode 100644
index f32a737..0000000
--- a/sys/cmd/rc/rc.h
+++ /dev/null
@@ -1,312 +0,0 @@
-#pragma once
-
-#include <u.h>
-#include <libn.h>
-
-#include <errno.h>
-#include <sys/wait.h>
-
-#define alloc(ptr) ptr = emalloc(sizeof(*ptr))
-
-// -----------------------------------------------------------------------
-// main enums
-
-#define GLOB 0x01
-
-enum
-{
- /* keywords */
- Kstart = 11,
- Tfor, Tin, Twhile, Tif, Telse,
- Tswitch, Tcase, Tfunc, Ttwiddle,
- Tbang, Tsubshell,
- Kend,
-
- /* tokens */
- Tword='w', Tredir='r', Tdup='d', Tsimple='s',
- Targs='A', Twords='W', Tbrace='b', Tparen='p', Tsub='S',
- Tpcmd='c', Tpipefd='-', Tandand='%', Toror='@', Tcount='#',
-
- Ttick='`', Tpipe = '|', Tdol='$', Tquote='"', Tand='&',
- Tlparen = '(', Trparen = ')', Tlbrace='{', Trbrace='}',
- Tsemi=';', Tcarot='^', Teq='=',
-};
-
-enum
-{
- Rappend = 1,
- Rwrite = 2,
- Rread = 3,
- Rhere = 4,
- Rdupfd = 5,
- Rclose = 6,
- Rrdwr = 7,
-};
-
-enum
-{
- Fopen = 1,
- Fdup = 2,
- Fclose = 3,
-};
-
-// -----------------------------------------------------------------------
-// main types
-
-typedef union Code Code;
-typedef struct Word Word;
-typedef struct List List;
-typedef struct Var Var;
-typedef struct Redir Redir;
-typedef struct Tree Tree;
-typedef struct Builtin Builtin;
-typedef struct Thread Thread;
-typedef struct Io Io;
-
-union Code
-{
- int i;
- char *s;
- void (*f)(void);
-};
-
-struct Word
-{
- char *word;
- Word *link;
-};
-
-struct List
-{
- Word *words;
- List *link;
-};
-
-struct Redir
-{
- uchar type;
- short from, to;
- Redir *link;
-};
-
-struct Var
-{
- string name;
- Word *val;
- struct {
- Code *func, *ip;
- uint funcnew : 1;
- };
- struct {
- uint new : 1;
- void (*update)(Var*);
- };
- Var *link;
-};
-
-struct Tree
-{
- ushort type;
- uchar quoted : 1;
- union {
- char *str;
- struct {
- ushort type;
- int fd[2];
- } redir;
- };
-
- Tree *child[3], *link;
-};
-
-struct Builtin
-{
- char *cmd;
- void (*func)(void);
-};
-
-struct Thread
-{
- Code *code, *ip;
- List *stack;
- Redir *redir, *root;
- Var *local;
- uchar interactive : 1;
- struct {
- uchar eof : 1;
- int line;
- char *name;
- Io *io;
- } cmd;
-
- int pid;
- Tree *nodes;
- Thread *link; /* continuation */
-};
-
-struct Io
-{
- int fd;
- uchar *b, *e, buf[];
-};
-
-// -----------------------------------------------------------------------
-// global interpreter variables
-
-extern Thread *shell;
-extern int ntrap;
-extern int status;
-
-extern Io *errio;
-
-extern Builtin builtins[];
-extern Var *globals[1021]; /* for now must be prime */
-
-// -----------------------------------------------------------------------
-// interpreter functions (defined in exec.c)
-
-/*
- * notation:
- * (var1, var2, ...) : items from stack
- * [var1, var2, ...] : items from code stream
- * {var1, var2, ...} : jump block from code stream
- * -> moves value (stack) [code stream]
- */
-extern void Xappend(void); /* Xappend(file)[fd]: open file to append */
-extern void Xassign(void); /* Xassign(name, val): assign name to val */
-extern void Xasync(void); /* Xasync(cmd): run command asynchronously */
-extern void Xcat(void); /* Xcat(list1, list2): concatenate strings */
-extern void Xclose(void); /* Xclose[fd]: close file descriptor */
-extern void Xcmdsub(void); /* Xcmdsub(cmd): use output of command as input to other */
-extern void Xcount(void); /* Xcount(name) -> (number): count items in list*/
-extern void Xdol(void); /* Xdol(name): get variable value */
-extern void Xdup(void); /* Xdup[i, j]: duplicate file descriptor */
-extern void Xexit(void); /* Xexit: exit with status */
-extern void Xfalse(void); /* Xfalse{...}: run only if $status=1 */
-extern void Xflatten(void); /* Xflatten(list) -> (string): flatten list */
-extern void Xfor(void); /* Xfor(list): flatten list */
-extern void Xfunc(void); /* Xfunc(name){... Xreturn}: define function */
-extern void Xglob(void); /* Xglob(list): globs value */
-extern void Xif(void); /* Xif: execute if $status */
-extern void Xjump(void); /* Xjump[addr]: jump to address */
-extern void Xkill(void); /* Xkill kill thread */
-extern void Xlocal(void); /* Xlocal(name, val): define local variable */
-extern void Xmark(void); /* Xmark: delimit stack with new list */
-extern void Xmatch(void); /* Xmatch(pat, str): sets status with result */
-extern void Xnegate(void); /* Xnegate: negate condition */
-extern void Xpipe(void); /* Xpipe[i j]{... Xkill}{... Xkill}: construct a pipe between 2 threads*/
-extern void Xpipefd(void); /* Xpipe[type]{... Xkill}: connect {} to a pipe */
-extern void Xpipewait(void); /* Xpipewait: wait on a pipe */
-extern void Xpop(void); /* Xpop(value): pops value from stack */
-extern void Xpopredir(void); /* Xpopredir(value): pops redir from redir stack */
-extern void Xrdwr(void); /* Xrdwr(file)[fd]: open file for reads/writes */
-extern void Xread(void); /* Xread(file)[fd]: open file for reads */
-extern void Xsub(void); /* Xsub(list, index): subscript list */
-extern void Xsimple(void); /* Xsimple(args): run command */
-extern void Xsubshell(void); /* Xsubshell(args): run command in a subshell */
-extern void Xtrue(void); /* Xtrue{...}: run only if $status=0 */
-extern void Xunfunc(void); /* Xunfunc(name) undefine function */
-extern void Xunlocal(void); /* Xunlocal(name) undefine local */
-extern void Xword(void); /* Xword[val] -> (val) */
-extern void Xwrite(void); /* Xwrite(file)[fd]: open file to write */
-
-extern void Xerror(char *s); /* Xerror report an error */
-
-// -----------------------------------------------------------------------
-// shell functions
-
-/*
- * util.c
- */
-void *emalloc(uintptr size);
-void *erealloc(void *ptr, uintptr size);
-void efree(void *);
-void panic(char *msg, int n);
-
-/*
- * io.c
- */
-Io *openfd(int fd);
-Io *openstr(void);
-Io *opencore(int len, char *s);
-void rewindio(Io *f);
-void closeio(Io *f);
-void flush(Io **fp);
-
-/* reads */
-int rchr(Io *f);
-
-/* writes */
-int pchr(Io *f, int c);
-void pquo(Io *f, char *s);
-void pwrd(Io *f, char *s);
-void pptr(Io *f, void *v);
-void pstr(Io *f, char *s);
-void pdec(Io *f, int n);
-void poct(Io *f, uint n);
-void pval(Io *f, Word *a);
-void pcmd(Io *f, Tree *t);
-void pfmt(Io *f, char *fmt, ...);
-void vpfmt(Io *f, char *fmt, va_list args);
-
-/*
- * word.c
- */
-void pushlist(void);
-void freelist(Word *w);
-void poplist(void);
-
-int count(Word *w);
-Word *newword(char *w, Word *link);
-void pushword(char *w);
-
-/*
- * tree.c
- */
-
-Tree *newtree(void);
-void freetree(Tree *t);
-Tree *tree3(int type, Tree *c0, Tree *c1, Tree *c2);
-Tree *tree2(int type, Tree *c0, Tree *c1);
-Tree *tree1(int type, Tree *c0);
-
-Tree *hang1(Tree *p, Tree *c0);
-Tree *hang2(Tree *p, Tree *c0, Tree *c1);
-Tree *hang3(Tree *p, Tree *c0, Tree *c1, Tree *c2);
-Tree *epihang(Tree *c, Tree *epi);
-Tree *simplehang(Tree *t);
-Tree *wordnode(char *w);
-
-/*
- * var.c
- */
-
-Var *newvar(char *name, Var *link);
-Var *gvlookup(char *name);
-Var *vlookup(char *name);
-void setvar(char *name, Word *val);
-
-int kwlookup(char *name);
-void initkw(void);
-
-/*
- * lex.c
- */
-
-void skipnl(void);
-int wordchr(int c);
-
-void rcerror(char *msg, ...);
-int lex(Tree **node);
-
-/*
- * parse.c
- */
-
-int parse(void);
-
-/*
- * main.c
- */
-
-void dotrap(void);
diff --git a/sys/cmd/rc/rules.mk b/sys/cmd/rc/rules.mk
deleted file mode 100644
index 654a44e..0000000
--- a/sys/cmd/rc/rules.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := \
- $(d)/glob.c \
- $(d)/word.c \
- $(d)/util.c \
- $(d)/io.c \
- $(d)/var.c \
- $(d)/tree.c \
- $(d)/lex.c \
- $(d)/parse.c \
- $(d)/main.c
-BINS_$(d) := $(d)/rc
-
-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/rc/simple.c b/sys/cmd/rc/simple.c
deleted file mode 100644
index f934aa1..0000000
--- a/sys/cmd/rc/simple.c
+++ /dev/null
@@ -1,13 +0,0 @@
-void
-Xsimple(void)
-{
- Word *a;
- Var *v;
-
- a = shell->stack->words;
- if (!a) {
- Xerror("empty argument list");
- return;
- }
- v = vlookup(a->word);
-}
diff --git a/sys/cmd/rc/tree.c b/sys/cmd/rc/tree.c
deleted file mode 100644
index 14049e5..0000000
--- a/sys/cmd/rc/tree.c
+++ /dev/null
@@ -1,144 +0,0 @@
-#include "rc.h"
-
-// -----------------------------------------------------------------------
-// globals
-
-static Tree *nodes;
-
-// -----------------------------------------------------------------------
-// exported funcs
-
-Tree*
-newtree(void)
-{
- Tree *t;
-
- alloc(t);
- t->str = nil;
- t->child[0] = t->child[1] = t->child[2] = nil;
- t->redir.fd[0] = t->redir.fd[1] = t->redir.type = 0;
-
- t->link = nodes, nodes = t;
- return t;
-}
-
-void
-freetree(Tree *t)
-{
- if (!t)
- return;
-
- freetree(t->child[0]);
- freetree(t->child[1]);
- freetree(t->child[2]);
-
- if (t->str)
- efree(t->str);
- efree(t);
-}
-
-void
-freenodes(void)
-{
- Tree *t, *u;
-
- for (t = nodes;t;t = u) {
- u = t->link;
- if (t->str)
- efree(t->str);
- efree(t);
- }
- nodes = nil;
-}
-
-/* tree creation */
-Tree*
-tree3(int type, Tree *c0, Tree *c1, Tree *c2)
-{
- Tree *t;
-
- t = newtree();
- t->type = type;
- t->child[0] = c0;
- t->child[1] = c1;
- t->child[2] = c2;
-
- return t;
-}
-
-Tree*
-tree2(int type, Tree *c0, Tree *c1)
-{
- return tree3(type, c0, c1, nil);
-}
-
-Tree*
-tree1(int type, Tree *c0)
-{
- return tree3(type, c0, nil, nil);
-}
-
-/* tree hang */
-Tree*
-hang1(Tree *p, Tree *c0)
-{
- p->child[0] = c0;
- return p;
-}
-
-Tree*
-hang2(Tree *p, Tree *c0, Tree *c1)
-{
- p->child[0] = c0;
- p->child[1] = c1;
- return p;
-}
-
-Tree*
-hang3(Tree *p, Tree *c0, Tree *c1, Tree *c2)
-{
- p->child[0] = c0;
- p->child[1] = c1;
- p->child[2] = c2;
- return p;
-}
-
-/* hangs the cmd underneath the epilogue */
-Tree*
-epihang(Tree *c, Tree *epi)
-{
- Tree *p;
- if(!epi)
- return c;
- for(p=epi;p->child[1];p = p->child[1])
- ;
- p->child[1] = c;
- return epi;
-}
-
-/* hangs tree t from a new simple node. percolates redirections to root */
-Tree*
-simplehang(Tree *t)
-{
- Tree *u;
- t = tree1(Tsimple, t);
- for(u = t->child[0];u->type==Targs;u=u->child[0]) {
- if (u->child[1]->type==Tdup
- || u->child[1]->type==Tredir){
- u->child[1]->child[1] = t;
- t = u->child[1];
- u->child[1] = nil;
- }
- }
- return t;
-}
-
-Tree*
-wordnode(char *w)
-{
- Tree *t = newtree();
- t->type = Tword;
- t->str = strdup(w);
-
- return t;
-}
diff --git a/sys/cmd/rc/util.c b/sys/cmd/rc/util.c
deleted file mode 100644
index 02b3611..0000000
--- a/sys/cmd/rc/util.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "rc.h"
-
-void *
-emalloc(uintptr n)
-{
- void *p = malloc(n);
- if (!p)
- panic("can't malloc %d bytes", n);
-
- return p;
-}
-
-void *
-erealloc(void *p, uintptr n)
-{
- void *new = realloc(p, n);
- if (!new)
- panic("can't realloc %d bytes", n);
-
- return new;
-}
-
-void
-efree(void *p)
-{
- if (p)
- free(p);
- else
- pfmt(errio, "free <nil>\n");
-}
-
-void
-panic(char *s, int n)
-{
- pfmt(errio, "rc: ");
- pfmt(errio, s, n);
- pchr(errio, '\n');
- flush(&errio);
- abort();
-}
diff --git a/sys/cmd/rc/var.c b/sys/cmd/rc/var.c
deleted file mode 100644
index d442369..0000000
--- a/sys/cmd/rc/var.c
+++ /dev/null
@@ -1,129 +0,0 @@
-#include "rc.h"
-
-Var *globals[1021] = { 0 };
-
-struct Keyword {
- ushort type;
- char *name;
- struct Keyword *link;
-} *keywords[41];
-
-// -----------------------------------------------------------------------
-// utility
-
-static
-int
-hash(char *s, int n)
-{
- int i = 1, h = 0;
- while (*s)
- h += *s++*i++;
- h %= n;
- return (h<0)?h+n:h;
-}
-
-// -----------------------------------------------------------------------
-// keywords
-
-static
-void
-putkw(int type, char *name)
-{
- struct Keyword *kw;
- int h = hash(name, arrlen(keywords));
-
- alloc(kw);
- kw->type = type;
- kw->name = name;
- kw->link = keywords[h];
-
- keywords[h] = kw;
-}
-
-void
-initkw(void)
-{
- putkw(Tfor, "for");
- putkw(Tin, "in");
- putkw(Twhile, "while");
- putkw(Tif, "if");
- putkw(Telse, "else");
- putkw(Tswitch, "switch");
- putkw(Tcase, "case");
- putkw(Tfunc, "func");
-}
-
-int
-kwlookup(char *name)
-{
- int t;
- struct Keyword *it;
- for(t=-1,it = keywords[hash(name, arrlen(keywords))];it;it = it->link)
- if(!strcmp(it->name, name))
- t = it->type;
- return t;
-}
-
-// -----------------------------------------------------------------------
-// variables
-
-Var *
-newvar(char *name, Var *link)
-{
- Var *v;
-
- alloc(v);
- v->name = name;
- v->val = 0;
- v->func = nil;
- v->funcnew = 0;
- v->new = 0;
- v->update = nil;
- v->link = link;
-
- return v;
-}
-
-/* only global lookup */
-
-Var *
-gvlookup(char *name)
-{
- Var *v;
- int h = hash(name, arrlen(globals));
- for (v = globals[h]; v; v = v->link)
- if (!strcmp(v->name, name))
- return v;
-
- return globals[h] = newvar(strdup(name), globals[h]);
-}
-
-/* local + global lookup */
-Var *
-vlookup(char *name)
-{
- Var *v;
- if (shell)
- for (v = shell->local; v; v = v->link)
- if (!strcmp(v->name, name))
- return v;
- return gvlookup(name);
-}
-
-static
-void
-set(char *name, Word *val, int call)
-{
- Var *v = vlookup(name);
- freelist(v->val);
- v->val = val;
- v->new = 1;
- if (call && v->update)
- v->update(v);
-}
-
-void
-setvar(char *name, Word *val)
-{
- set(name, val, 1);
-}
diff --git a/sys/cmd/rc/word.c b/sys/cmd/rc/word.c
deleted file mode 100644
index 84ff40c..0000000
--- a/sys/cmd/rc/word.c
+++ /dev/null
@@ -1,64 +0,0 @@
-#include "rc.h"
-
-void
-pushlist(void)
-{
- List *ls;
-
- alloc(ls);
- ls->words = nil;
- ls->link = shell->stack, shell->stack = ls;
-}
-
-void
-freelist(Word *w)
-{
- Word *it;
- while (w) {
- it = w->link;
- efree(w->word);
- efree(w);
- w = it;
- }
-}
-
-void
-poplist(void)
-{
- List *ls = shell->stack;
- if (!ls)
- panicf("shell stack underflow");
-
- freelist(ls->words);
- shell->stack = ls->link;
- efree(ls);
-}
-
-int
-count(Word *w)
-{
- int n;
- for (n=0; w; n++)
- w = w->link;
- return n;
-}
-
-Word*
-newword(char *w, Word *link)
-{
- Word *wd;
-
- alloc(wd);
- wd->word = strdup(w);
- wd->link = link;
-
- return wd;
-}
-
-void
-pushword(char *w)
-{
- if (shell->stack == nil)
- panicf("no active stack");
- shell->stack->words = newword(w, shell->stack->words);
-}
diff --git a/sys/cmd/rm/rm.c b/sys/cmd/rm/rm.c
deleted file mode 100644
index 7e83f5f..0000000
--- a/sys/cmd/rm/rm.c
+++ /dev/null
@@ -1,119 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <sys/stat.h>
-
-/*
- * globals
- */
-
-static char errbuf[1024];
-static int numerrs;
-static struct
-{
- uchar i : 1;
- uchar f : 1;
- uchar r : 1;
-} flag;
-
-/*
- * utilities
- */
-
-static
-void
-errors(char *fmt, ...)
-{
- va_list args;
-
- if(flag.f)
- return;
-
- va_start(args, fmt);
- vsnprintf(errbuf, arrlen(errbuf), fmt, args);
- va_end(args);
-
- fprintf(stderr, "rm: %s\n", errbuf);
- numerrs++;
-}
-
-static
-int
-yes(void)
-{
- int i, b;
- i = b = getchar();
- while(b != '\n' && b != EOF)
- b = getchar();
-
- return(i== 'y');
-}
-
-static
-int
-rm(char *path, int level)
-{
- int d;
- struct stat buf;
- if(stat(path, &buf)) {
- errors("%s: non-existent", path);
- return 1;
- }
-
- if((buf.st_mode&S_IFMT) == S_IFDIR) {
- if(!flag.r) {
- errors("%s: is directory", path);
- return 1;
- }
- if(access(path, 02) < 0) {
- errors("%s: not permitted", path);
- return 1;
- }
- if(flag.i && level != 0) {
- printf("directory %s: ", path);
- if(!yes())
- return 0;
- }
- if((d=
- }
-}
-
-/*
- * main point of entry
- */
-
-static
-void
-usage(void)
-{
- fprintf(stderr, "usage: rm [-ifr] file ...\n");
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- int i;
- char *s;
-
- ARGBEGIN{
- case 'i':
- flag.i = 1;
- break;
- case 'r':
- flag.r = 1;
- break;
- case 'f':
- flag.f = 1;
- break;
- default:
- usage();
- }ARGEND;
-
- for(i = 0; i < argc; i++){
- s = argv[i];
- if (rm(s, 0) != -1)
- continue;
- }
-
- exit(numerrs);
-}
diff --git a/sys/cmd/rm/rules.mk b/sys/cmd/rm/rules.mk
deleted file mode 100644
index 9cb4e92..0000000
--- a/sys/cmd/rm/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := $(d)/rm.c
-BINS_$(d) := $(d)/rm
-
-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/rules.mk b/sys/cmd/rules.mk
index 8e83e57..bd9d232 100644
--- a/sys/cmd/rules.mk
+++ b/sys/cmd/rules.mk
@@ -2,45 +2,18 @@ include share/push.mk
# Iterate through subdirectory tree
-DIR := $(d)/cat
-include $(DIR)/rules.mk
-
# DIR := $(d)/cc
# include $(DIR)/rules.mk
-# DIR := $(d)/cp
-# include $(DIR)/rules.mk
-
-# DIR := $(d)/dvtm
-# include $(DIR)/rules.mk
-
DIR := $(d)/dwm
include $(DIR)/rules.mk
-DIR := $(d)/echo
-include $(DIR)/rules.mk
-
-# DIR := $(d)/edo
-# include $(DIR)/rules.mk
-
DIR := $(d)/filter
include $(DIR)/rules.mk
-DIR := $(d)/ic
-include $(DIR)/rules.mk
-
-# DIR := $(d)/ls
-# include $(DIR)/rules.mk
-
DIR := $(d)/menu
include $(DIR)/rules.mk
-DIR := $(d)/mv
-include $(DIR)/rules.mk
-
-DIR := $(d)/rc
-include $(DIR)/rules.mk
-
DIR := $(d)/term
include $(DIR)/rules.mk
diff --git a/sys/libbio/align.c b/sys/libbio/align.c
index 0f00fce..20a57df 100644
--- a/sys/libbio/align.c
+++ b/sys/libbio/align.c
@@ -4,13 +4,13 @@
#include <libbio.h>
// -----------------------------------------------------------------------
-// Temporary globals
+// globals
uint64 aln·shft = (2ULL * (aln·K - 1ULL));
uint64 aln·mask = (1ULL << (2*aln·K)) - 1ULL;
// -----------------------------------------------------------------------
-// Static data
+// static data
static uint64 nuctab[256] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
@@ -32,7 +32,7 @@ static uint64 nuctab[256] = {
};
// -----------------------------------------------------------------------
-// Hash functions
+// hash functions
enum
{
@@ -69,7 +69,7 @@ murmurhash(uint64 x, uint64 mask)
}
// -----------------------------------------------------------------------
-// Locality sensitive hashing (with spatial extent)
+// locality sensitive hashing (with spatial extent)
static
void
@@ -102,20 +102,20 @@ aln·sketch(byte *seq, int len, uint64 *vals[aln·N], int *locs[aln·N])
int tmpi[2];
uint64 tmpu[2];
- for (n = 0; n < aln·N; n++) {
- for (l = 0; l < len; l++) {
+ 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++) {
+ 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++) {
+ for(n = 0; n < aln·N; n++) {
val = vals[n];
loc = locs[n];
@@ -126,14 +126,14 @@ aln·sketch(byte *seq, int len, uint64 *vals[aln·N], int *locs[aln·N])
tmpu[1] = h[2];
tmpi[1] = l;
- for (i -= 1; i >= 0; i--) {
+ 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++) {
+ for(n = 0; n < aln·N; n++) {
sortpos(len, vals[n], locs[n]);
}
@@ -146,7 +146,7 @@ lessarrs(int len, uint64 a[], uint64 b[])
{
int l;
- for (l = 0; l < len; l++) {
+ for(l = 0; l < len; l++) {
if (a[l] < b[l]) return 1;
if (a[l] > b[l]) return 0;
}
@@ -161,7 +161,7 @@ swaparrs(int len, uint64 a[], uint64 b[])
int l;
uint64 tmp;
- for (l = 0; l < len; l++) {
+ for(l = 0; l < len; l++) {
tmp = a[l], a[l] = b[l], b[l] = tmp;
}
}
diff --git a/sys/libbio/io/fasta.c b/sys/libbio/io/fasta.c
deleted file mode 100644
index 28c9ca4..0000000
--- a/sys/libbio/io/fasta.c
+++ /dev/null
@@ -1,360 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <libbio.h>
-
-#define INIT_NM_SIZE 128
-#define INIT_SQ_SIZE 4096
-
-struct Seqbuf
-{
- mem·Allocator heap;
- void *h;
-
- int len;
- int off;
- byte *it;
- byte b[];
-};
-
-static
-void
-reset(struct Seqbuf *sb)
-{
- sb->off = 0;
- sb->it = sb->b;
-}
-
-static
-error
-grow(struct Seqbuf **sb, int min)
-{
- struct Seqbuf *old, *new;
- vlong newlen;
-
- old = *sb;
- assert((*sb)->len <= (SIZE_MAX - 1) / 2);
- newlen = MAX(16, MAX(1 + 2*(*sb)->len, (*sb)->len+min));
- assert(newlen >= (*sb)->len+min);
-
- if (new = old->heap.alloc(old->h, 1, sizeof(*new)+newlen), !new) {
- errorf("memory: could not allocate new buffer");
- return 1;
- }
-
- memcpy(new, old, sizeof(*sb) + (*sb)->len);
- new->len = newlen;
- new->it = new->b + (old->len);
- old->heap.free(old->h, 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->len)) {
- *sq->it++ = c;
- return 0;
- }
-
- if (err = grow(sb, 1), err) {
- errorf("memory fail: could not allocate more buffer");
- sq->heap.free(sq->h, 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->len - (seq->it - seq->b), d < n) {
- assert(d > 0);
- if (err = grow(sb, n-d), err) {
- errorf("memory fail: could not allocate more buffer");
- seq->heap.free(seq->h, seq);
- return 1;
- }
- }
-
- memcpy((*sb)->it, buf, n);
- (*sb)->it += n;
-
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// Fasta files
-
-struct bio·FastaReader {
- byte eof;
- io·Reader file;
- void *f;
-
- struct Seqbuf *seq;
-
- /* read buffer */
- byte *b, *bend;
- byte buf[4*4098];
-};
-
-static
-error
-fill(bio·FastaReader *rdr)
-{
- int n;
- // NOTE: This could lead to an infinite loop.
- if (rdr->eof) {
- return 0;
- }
-
- n = rdr->file.read(rdr->f, 1, arrlen(rdr->buf), rdr->buf);
- if (n < 0) {
- errorf("read: no data obtained from reader");
- 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·FastaReader*
-bio·openfasta(io·Reader file, void *f, mem·Allocator heap, void *h)
-{
- error err;
- bio·FastaReader *rdr;
-
- rdr = heap.alloc(h, 1, sizeof(bio·FastaReader));
- rdr->file = file;
- rdr->f = f;
- rdr->eof = 0;
-
- rdr->seq = heap.alloc(h, 1, sizeof(*rdr->seq) + INIT_NM_SIZE + INIT_SQ_SIZE);
- rdr->seq->heap = heap;
- rdr->seq->h = h;
- rdr->seq->it = rdr->seq->b;
- rdr->seq->len = INIT_NM_SIZE + INIT_SQ_SIZE;
-
- if (err = fill(rdr), err) {
- errorf("fill: could not populate buffer");
- goto ERROR;
- }
-
- return rdr;
-
-ERROR:
- heap.free(h, rdr->seq);
- heap.free(h, rdr);
- return nil;
-}
-
-static
-error
-readfasta(bio·FastaReader *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'", 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");
- return 1;
- }
- goto NAME;
-
-SEQ:
- put(&rdr->seq, '\0');
- rdr->seq->off = rdr->seq->it - rdr->seq->b;
-
-SEQL:
- 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");
- return 1;
- }
- goto SEQL;
-
-SUCCESS:
- push(&rdr->seq, rdr->b - beg, beg);
- put(&rdr->seq, '\0');
-
- return 0;
-}
-
-error
-bio·readfasta(bio·FastaReader *rdr, bio·Seq *seq)
-{
- error err;
-
- err = readfasta(rdr, seq, '>', '>');
- if (err && err != EOF) {
- errorf("parse fail: could not read sequence of record");
- return err;
- }
-
- seq->name = rdr->seq->b;
- seq->s = rdr->seq->b + rdr->seq->off;
- seq->len = rdr->seq->it - seq->s;
- seq->q = nil;
-
- return err;
-}
-
-error
-bio·closefasta(bio·FastaReader *rdr)
-{
- mem·Allocator heap;
- void *h;
-
- heap = rdr->seq->heap;
- h = rdr->seq->h;
-
- heap.free(h, rdr->seq);
- heap.free(h, rdr);
-
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// Fastq files
-
-struct bio·FastqReader {
- struct bio·FastaReader;
-};
-
-bio·FastqReader*
-bio·openfastq(io·Reader file, void *f, mem·Allocator heap, void *h)
-{
- return (bio·FastqReader*)bio·openfasta(file, f, heap, h);
-}
-
-error
-bio·closefastq(bio·FastqReader *rdr)
-{
- return bio·closefasta((bio·FastaReader*)rdr);
-}
-
-error
-bio·readfastq(bio·FastqReader *rdr, bio·Seq *seq)
-{
- int n;
- byte *beg;
- error err;
-
- err = readfasta((bio·FastaReader*)rdr, seq, '@', '+');
- if (err) {
- errorf("parse fail: could not read sequence of record");
- return err;
- }
-
- seq->len = rdr->seq->it - (rdr->seq->b + rdr->seq->off);
-
- if (*rdr->b++ != '+') {
- errorf("format error: no '+' character seperator found");
- return -1;
- }
-
-EATLN:
- while (rdr->b != rdr->bend) {
- if (*rdr->b++ == '\n') {
- n = 0;
- goto QUAL;
- }
- }
-
- if (err = fill((bio·FastaReader*)rdr), err) {
- errorf("read: could not populate buffer");
- 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·FastaReader*)rdr), err) {
- errorf("read: could not populate buffer");
- 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;
- seq->q = seq->s + seq->len + 1;
-
- return err;
-}
diff --git a/sys/libbio/io/newick.c b/sys/libbio/io/newick.c
deleted file mode 100644
index 164516f..0000000
--- a/sys/libbio/io/newick.c
+++ /dev/null
@@ -1,418 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <libbio.h>
-
-// -----------------------------------------------------------------------
-// Tokens
-
-enum TokenKind
-{
- tok·nil,
- tok·eof,
- tok·space,
- tok·ident,
- tok·number,
- tok·lparen,
- tok·rparen,
- tok·lbrak,
- tok·rbrak,
- tok·comma,
- tok·semi,
- tok·colon,
-
- NUM_TOKENS,
-};
-
-
-struct Token {
- enum TokenKind kind;
- union
- {
- byte *s;
- double x;
- } lit;
-};
-
-static
-byte*
-tokstr(struct Token tok)
-{
- static byte b[50];
- switch (tok.kind) {
- case tok·nil: return "";
- case tok·eof: return nil;
- case tok·space: return " ";
- case tok·ident: return tok.lit.s;
- case tok·lparen: return "(";
- case tok·rparen: return ")";
- case tok·lbrak: return "[";
- case tok·rbrak: return "]";
- case tok·comma: return ",";
- case tok·semi: return ";";
- case tok·colon: return ":";
- case tok·number:
- snprintf(b, arrlen(b), "%f", tok.lit.x);
- return b;
- default:
- return nil;
- }
-}
-
-
-// -----------------------------------------------------------------------
-// Read
-
-// TODO: Bounds checking on buffer
-static
-struct Token
-lex(io·Peeker s, void* fp)
-{
-#define isvalidchar(C) ((C) == '!') || \
- ('\"' < (C) && (C) < '\'') || \
- (')' < (C) && (C) < '+') || \
- (',' < (C) && (C) < ':') || \
- (':' < (C) && (C) < '[') || \
- ((C) == '\\') || \
- (']' < (C) && (C) <= '~')
- byte *c;
- struct Token tok;
- static byte b[1024];
- c = b;
- *c = s.get(fp);
-
- if (isspace(*c)) {
- while (isspace(*c)) {
- *(++c) = s.get(fp);
- }
-
- s.unget(fp, *c);
- assert(c - b < 1024);
-
- *c = 0;
- tok.kind = tok·space;
- tok.lit.s = b;
- return tok;
- }
-
- switch (*c) {
- case EOF: tok.kind = tok·eof; return tok;
- case '(': tok.kind = tok·lparen; return tok;
- case ')': tok.kind = tok·rparen; return tok;
- case '[': tok.kind = tok·lbrak; return tok;
- case ']': tok.kind = tok·rbrak; return tok;
- case ',': tok.kind = tok·comma; return tok;
- case ';': tok.kind = tok·semi; return tok;
- case ':': tok.kind = tok·colon; return tok;
-
- case '.':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- while (isdigit(*c)) {
- NUM: *(++c) = s.get(fp);
- }
- if (*c == '.') goto NUM;
- if (isvalidchar(*c)) goto IDENT;
-
- s.unget(fp, *c);
- assert(c - b < 1024);
-
- *c = 0;
- tok.kind = tok·number;
- tok.lit.x = atof(b);
- return tok;
-
- case '\"':
- while ((*c) != '\"') {
- *(++c) = s.get(fp);
- }
- assert(c - b < 1024);
-
- *c = '\0';
- tok.kind = tok·ident;
- tok.lit.s = b + 1;
- return tok;
-
- default:
- IDENT:
- while (isvalidchar(*c)) {
- *(++c) = s.get(fp);
- }
- s.unget(fp, *c);
- assert(c - b < 1024);
-
- *c = '\0';
- tok.kind = tok·ident;
- tok.lit.s = b;
- return tok;
- }
-#undef isvalidchar
-}
-
-static
-struct Token
-lex_nospace(io·Peeker s, void *impl)
-{
- struct Token tok;
- tok = lex(s, impl);
- if (tok.kind == tok·space) {
- tok = lex_nospace(s, impl);
- }
-
- return tok;
-}
-
-struct Parser
-{
- int lev;
- bio·Node *root;
- struct Token tok;
-
- void *fimpl;
- io·Peeker file;
- void *himpl;
- mem·Allocator heap;
-};
-
-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->fimpl);
-
- 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->heap.alloc(p->himpl, 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->fimpl);
- 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->fimpl);
- 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->heap.alloc(p->himpl, 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->fimpl, ';');
- 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;
-}
-
-error
-bio·readnewick(io·Peeker stream, void *s, bio·Tree *tree)
-{
- error err;
- struct Parser p;
- enum
- {
- error·nil,
- error·notree,
- error·parse,
- };
-
- if (!tree) {
- return error·notree;
- }
-
- p = (struct Parser){
- .lev = 0,
- .root = nil,
- .tok = (struct Token){ 0 },
- .fimpl = s,
- .file = stream,
- .himpl = tree->h,
- .heap = tree->heap,
- };
- err = parse(&p);
- if (err) {
- errorf("parsing failed\n");
- return error·parse;
- }
-
- 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 error·nil;
-}
-
-// -----------------------------------------------------------------------
-// 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.putstr(impl, node->name);
- }
-
- if (node->parent) {
- out.put(impl, ':');
- snprintf(b, arrlen(b), "%f", node->dist);
- out.putstr(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/io/rules.mk b/sys/libbio/io/rules.mk
deleted file mode 100644
index a4277fc..0000000
--- a/sys/libbio/io/rules.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-include share/push.mk
-
-# Iterate through subdirectory tree
-
-# Local sources
-SRCS_$(d) := $(wildcard $(d)/*.c)
-LIBS_$(d) :=
-BINS_$(d) :=
-TSTS_$(d) :=
-
-include share/paths.mk
-
-$(LIBS_$(d)): $(OBJS_$(d))
- $(ARCHIVE)
-
-# $(BINS_$(d)): TCLIBS := $(OBJ_DIR)/libn/libn.a
-$(BINS_$(d)): $(OBJS_$(d))
- $(LINK)
-
-# ---- Pop off stack ----
-include share/pop.mk
diff --git a/sys/libbio/rules.mk b/sys/libbio/rules.mk
index 6a029b1..cbc6887 100644
--- a/sys/libbio/rules.mk
+++ b/sys/libbio/rules.mk
@@ -1,18 +1,15 @@
include share/push.mk
-# Iterate through subdirectory tree
-DIR := $(d)/io
-include $(DIR)/rules.mk
-
# Local sources
SRCS_$(d) := \
- $(d)/align.c \
+ $(d)/fasta.c \
+ $(d)/newick.c \
$(d)/phylo.c
LIBS_$(d) := $(d)/libbio.a
BINS_$(d) :=
-TSTS_$(d) := \
- $(d)/test.c \
- $(d)/simulate.c
+# TSTS_$(d) := \
+# $(d)/test.c \
+# $(d)/simulate.c
include share/paths.mk
diff --git a/sys/libfont/test.c b/sys/libfont/test.c
deleted file mode 100644
index 5097009..0000000
--- a/sys/libfont/test.c
+++ /dev/null
@@ -1,192 +0,0 @@
-#include <u.h>
-#include <libn.h>
-#include <libfont.h>
-
-#include <fontconfig/fontconfig.h>
-#include <freetype2/ft2build.h>
-#include FT_FREETYPE_H /* ugh */
-
-#define STB_IMAGE_WRITE_IMPLEMENTATION
-#include "stb_image_write.h"
-
-#define DIV 2
-#define W 1920/DIV
-#define H 1080/2
-#define L H/35
-
-static char *phrase = "abcdefghijklmnopqrstuvwxyx";
-static byte *fontpath = "/home/nolln/root/data/Inconsolata-Regular.ttf";
-
-static FT_Library lib;
-static FT_Face face;
-
-static
-void
-loadfonts(int size)
-{
- FT_New_Face(lib, (const byte*)fontpath, 0, &face);
- FT_Set_Char_Size(face, 0, size << 6, 72, 72);
-}
-
-int
-main()
-{
- int i, x, y, x0, y0, c, r, err;
- FT_GlyphSlot slot;
- FT_Bitmap bitmap;
- FT_UInt index;
- uchar *pixel;
- font·Info *info;
-
- pixel = calloc(H,W);
- mmap·Reader fontfile;
-
- err = 0;
- fontfile = mmap·open(fontpath);
- if (!fontfile.len) {
- panicf("fail");
- }
-
- // info = font·make(fontfile.ubuf, 0, mem·sys, nil);
- if (!info)
- panicf("failed to load info");
-
- if (!FcInit())
- panicf("could not initialize fontconfig");
- if (FT_Init_FreeType(&lib))
- panicf("could not initialize freetype");
-
- loadfonts(14);
-
- x0 = 10, y0 = 100;
- slot = face->glyph;
- for (i = 0; i < strlen(phrase); i++) {
- printf("phrase[i]='%c'\n", phrase[i]);
- err = FT_Load_Char(face, (rune)phrase[i], FT_LOAD_RENDER);
- if (err)
- panicf("failed to load font face");
-
- x = x0 + slot->bitmap_left;
- y = y0 - slot->bitmap_top;
- printf("buffer size: [%d, %d]\n", slot->bitmap.rows, slot->bitmap.width);
- for (c = 0; c < slot->bitmap.width; c++) {
- for (r = 0; r < slot->bitmap.rows; r++) {
- if (x+c < 0 || x+c > W || y+r < 0 || y+r > H)
- continue;
- pixel[(x+c)+W*(y+r)] += slot->bitmap.buffer[c + slot->bitmap.width*r];
- }
- }
- x0 += slot->advance.x >> 6;
- y0 += slot->advance.y >> 6;
- }
-
- // {
- // float x = 0.;
- // float dy = 0., dx;
- // float scale;
- // int ascent, descent, baseln;
- // int adv, lsb, off, r0[2] = {0}, r1[2] = {0}, w, h, i, j, k ;
-
- // uchar *work;
-
- // font·vmetrics(info, &ascent, &descent, &baseln);
- // scale = font·scaleheightto(info, L);
- // for (i = 0; i < strlen(phrase); i++) {
- // dx = x - (float)floor(x);
- // font·code_hmetrics(info, phrase[i], &adv, &lsb);
- // font·code_bbox_subpixel(info, phrase[i], scale, scale, dx, 0, r0, r0+1, r1, r1+1);
-
- // y = ascent + r0[1];
- // dy = y - (float)floor(y);
-
- // w = r1[0]-r0[0];
- // h = r1[1]-r0[1];
-
- // work = calloc(w, h);
- // font·code_fillbitmap_subpixel(info, work, w, h, w, scale, scale, dx, 0, phrase[i]);
-
- // off = (int)floor(x+10) + r0[0] + ((int)y-100) * W;
- // for (j = 0; j < h; j++) {
- // for (k = 0; k < w; k++) {
- // pixel[off + k + W*j] += work[k + w*j];
- // }
- // }
- // free(work);
-
- // x += scale * adv;
- // if (phrase[i+1])
- // x += scale * font·code_kernadvance(info, phrase[i], phrase[i+1]);
- // }
- // }
- stbi_write_png("out.png", W, H, 1, pixel, W);
-
- exit(0);
-}
-
-#if 0
-int
-main()
-{
- int i, j, k, err;
- float x, dx, dy, scale, sx, sy;
- uchar *bitmap, *work;
- font·Info *info;
- mmap·Reader fontfile;
- int w, h, off, y, ascent, descent, baseln;
- int adv, lsb, r0[2], r1[2];
-
- err = 0;
- fontfile = mmap·open("/home/nolln/root/data/Inconsolata-Regular.ttf");
- if (!fontfile.len) {
- err = 1;
- goto end;
- }
-
- info = font·make(fontfile.ubuf, 0, mem·sys, nil);
- if (!info)
- panicf("failed to load info");
-
- bitmap = calloc(W*H, sizeof(*bitmap));
- scale = font·scaleheightto(info, L);
-
- font·vmetrics(info, &ascent, &descent, &baseln);
- ascent *= scale;
-
- x = 0.;
- dy = 0.;
- for (i = 0; i < strlen(phrase); i++) {
- dx = x - (float)floor(x);
- font·code_hmetrics(info, phrase[i], &adv, &lsb);
- font·code_bbox_subpixel(info, phrase[i], scale, scale, dx, 0, r0, r0+1, r1, r1+1);
-
- y = ascent + r0[1];
- dy = y - (float)floor(y);
-
- w = r1[0]-r0[0];
- h = r1[1]-r0[1];
-
- work = calloc(w*h, sizeof(*bitmap));
- font·code_fillbitmap_subpixel_prefilter(info, work, w, h, w, scale, scale, dx, 0, 1, 1, &sx, &sy, phrase[i]);
-
- off = (int)floor(x+sx) + r0[0] + ((int)floor(sy)+y) * W;
- for (j = 0; j < h; j++) {
- for (k = 0; k < w; k++) {
- bitmap[off + W*j + k] += work[k + w*j];
- }
- }
- free(work);
-
- x += scale * adv;
- if (phrase[i+1])
- x += scale * font·code_kernadvance(info, phrase[i], phrase[i+1]);
- }
-
- stbi_write_png("out.png", W, H, 1, bitmap, W);
-
- font·free(info);
- free(bitmap);
-end:
- mmap·close(fontfile);
- return err;
-}
-#endif