From 5d3642b8ef920316693031d2ea34b9def0b1abc5 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Thu, 22 Apr 2021 08:55:35 -0700 Subject: chore: rm unfinished projects --- .gitignore | 1 + include/libbio.h | 31 +- rules.mk | 3 + sys/cmd/calc/calc.c | 2285 -------------------------------------------- sys/cmd/cat/cat.c | 40 - sys/cmd/cat/rules.mk | 13 - sys/cmd/cat/test.c | 8 - sys/cmd/cp/cp.c | 75 -- sys/cmd/cp/rules.mk | 26 - sys/cmd/dvtm/LICENSE | 23 - sys/cmd/dvtm/config.h | 208 ---- sys/cmd/dvtm/dvtm-editor.c | 183 ---- sys/cmd/dvtm/dvtm.c | 1810 ----------------------------------- sys/cmd/dvtm/dvtm.h | 233 ----- sys/cmd/dvtm/dvtm.info | 136 --- sys/cmd/dvtm/hook.c | 346 ------- sys/cmd/dvtm/rules.mk | 33 - sys/cmd/dvtm/vt.c | 2112 ---------------------------------------- sys/cmd/dvtm/vt.h | 48 - sys/cmd/echo/echo.c | 39 - sys/cmd/echo/rules.mk | 13 - sys/cmd/ls/ls.c | 36 - sys/cmd/ls/rules.mk | 13 - sys/cmd/mv/mv.c | 130 --- sys/cmd/mv/rules.mk | 13 - sys/cmd/rc/code.c | 335 ------- sys/cmd/rc/code.dep | 166 ---- sys/cmd/rc/exec.c | 139 --- sys/cmd/rc/glob.c | 199 ---- sys/cmd/rc/io.c | 446 --------- sys/cmd/rc/lex.c | 417 -------- sys/cmd/rc/main.c | 86 -- sys/cmd/rc/parse.c | 496 ---------- sys/cmd/rc/rc.h | 312 ------ sys/cmd/rc/rules.mk | 22 - sys/cmd/rc/simple.c | 13 - sys/cmd/rc/tree.c | 144 --- sys/cmd/rc/util.c | 40 - sys/cmd/rc/var.c | 129 --- sys/cmd/rc/word.c | 64 -- sys/cmd/rm/rm.c | 119 --- sys/cmd/rm/rules.mk | 13 - sys/cmd/rules.mk | 27 - sys/libbio/align.c | 24 +- sys/libbio/io/fasta.c | 360 ------- sys/libbio/io/newick.c | 418 -------- sys/libbio/io/rules.mk | 21 - sys/libbio/rules.mk | 13 +- sys/libfont/test.c | 192 ---- 49 files changed, 30 insertions(+), 12023 deletions(-) delete mode 100644 sys/cmd/calc/calc.c delete mode 100644 sys/cmd/cat/cat.c delete mode 100644 sys/cmd/cat/rules.mk delete mode 100644 sys/cmd/cat/test.c delete mode 100644 sys/cmd/cp/cp.c delete mode 100644 sys/cmd/cp/rules.mk delete mode 100644 sys/cmd/dvtm/LICENSE delete mode 100644 sys/cmd/dvtm/config.h delete mode 100644 sys/cmd/dvtm/dvtm-editor.c delete mode 100644 sys/cmd/dvtm/dvtm.c delete mode 100644 sys/cmd/dvtm/dvtm.h delete mode 100644 sys/cmd/dvtm/dvtm.info delete mode 100644 sys/cmd/dvtm/hook.c delete mode 100644 sys/cmd/dvtm/rules.mk delete mode 100644 sys/cmd/dvtm/vt.c delete mode 100644 sys/cmd/dvtm/vt.h delete mode 100644 sys/cmd/echo/echo.c delete mode 100644 sys/cmd/echo/rules.mk delete mode 100644 sys/cmd/ls/ls.c delete mode 100644 sys/cmd/ls/rules.mk delete mode 100644 sys/cmd/mv/mv.c delete mode 100644 sys/cmd/mv/rules.mk delete mode 100644 sys/cmd/rc/code.c delete mode 100644 sys/cmd/rc/code.dep delete mode 100644 sys/cmd/rc/exec.c delete mode 100644 sys/cmd/rc/glob.c delete mode 100644 sys/cmd/rc/io.c delete mode 100644 sys/cmd/rc/lex.c delete mode 100644 sys/cmd/rc/main.c delete mode 100644 sys/cmd/rc/parse.c delete mode 100644 sys/cmd/rc/rc.h delete mode 100644 sys/cmd/rc/rules.mk delete mode 100644 sys/cmd/rc/simple.c delete mode 100644 sys/cmd/rc/tree.c delete mode 100644 sys/cmd/rc/util.c delete mode 100644 sys/cmd/rc/var.c delete mode 100644 sys/cmd/rc/word.c delete mode 100644 sys/cmd/rm/rm.c delete mode 100644 sys/cmd/rm/rules.mk delete mode 100644 sys/libbio/io/fasta.c delete mode 100644 sys/libbio/io/newick.c delete mode 100644 sys/libbio/io/rules.mk delete mode 100644 sys/libfont/test.c 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 -#include - -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=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= 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(hrd = (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(ptrlast) - *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 -#include - -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, ""); - } 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 -#include - -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 -#include - -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 - (c) 2007-2016 Marc André Tanner - (c) 2020-???? Nicholas Noll - -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 : focus the window whose `DVTM_WINDOW_ID` is `win_id` */ - { "focus", { focusid, { NULL } } }, - /* 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 - * Copyright (c) 2017 Marc André Tanner - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -// #include -#include - -#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 -#include - -#include -#include -#include - -#include -#include - -#if defined(__linux__) || defined(__CYGWIN__) -# include -#elif defined(__FreeBSD__) || defined(__DragonFly__) -# include -#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) -# include -#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 - -#include -#include -#include - -#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 -#include - -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 -#include - -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 -#include - -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 - -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, ""); - 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 = ""; - - 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 -#include - -#include -#include - -#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 \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 -#include -#include - -/* - * 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 // ----------------------------------------------------------------------- -// 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 -#include -#include - -#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 -#include -#include - -// ----------------------------------------------------------------------- -// Tokens - -enum TokenKind -{ - tok·nil, - tok·eof, - tok·space, - tok·ident, - tok·number, - tok·lparen, - tok·rparen, - tok·lbrak, - tok·rbrak, - tok·comma, - tok·semi, - tok·colon, - - NUM_TOKENS, -}; - - -struct Token { - enum TokenKind kind; - union - { - byte *s; - double x; - } lit; -}; - -static -byte* -tokstr(struct Token tok) -{ - static byte b[50]; - switch (tok.kind) { - case tok·nil: return ""; - case tok·eof: return nil; - case tok·space: return " "; - case tok·ident: return tok.lit.s; - case tok·lparen: return "("; - case tok·rparen: return ")"; - case tok·lbrak: return "["; - case tok·rbrak: return "]"; - case tok·comma: return ","; - case tok·semi: return ";"; - case tok·colon: return ":"; - case tok·number: - snprintf(b, arrlen(b), "%f", tok.lit.x); - return b; - default: - return nil; - } -} - - -// ----------------------------------------------------------------------- -// Read - -// TODO: Bounds checking on buffer -static -struct Token -lex(io·Peeker s, void* fp) -{ -#define isvalidchar(C) ((C) == '!') || \ - ('\"' < (C) && (C) < '\'') || \ - (')' < (C) && (C) < '+') || \ - (',' < (C) && (C) < ':') || \ - (':' < (C) && (C) < '[') || \ - ((C) == '\\') || \ - (']' < (C) && (C) <= '~') - byte *c; - struct Token tok; - static byte b[1024]; - c = b; - *c = s.get(fp); - - if (isspace(*c)) { - while (isspace(*c)) { - *(++c) = s.get(fp); - } - - s.unget(fp, *c); - assert(c - b < 1024); - - *c = 0; - tok.kind = tok·space; - tok.lit.s = b; - return tok; - } - - switch (*c) { - case EOF: tok.kind = tok·eof; return tok; - case '(': tok.kind = tok·lparen; return tok; - case ')': tok.kind = tok·rparen; return tok; - case '[': tok.kind = tok·lbrak; return tok; - case ']': tok.kind = tok·rbrak; return tok; - case ',': tok.kind = tok·comma; return tok; - case ';': tok.kind = tok·semi; return tok; - case ':': tok.kind = tok·colon; return tok; - - case '.': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - while (isdigit(*c)) { - NUM: *(++c) = s.get(fp); - } - if (*c == '.') goto NUM; - if (isvalidchar(*c)) goto IDENT; - - s.unget(fp, *c); - assert(c - b < 1024); - - *c = 0; - tok.kind = tok·number; - tok.lit.x = atof(b); - return tok; - - case '\"': - while ((*c) != '\"') { - *(++c) = s.get(fp); - } - assert(c - b < 1024); - - *c = '\0'; - tok.kind = tok·ident; - tok.lit.s = b + 1; - return tok; - - default: - IDENT: - while (isvalidchar(*c)) { - *(++c) = s.get(fp); - } - s.unget(fp, *c); - assert(c - b < 1024); - - *c = '\0'; - tok.kind = tok·ident; - tok.lit.s = b; - return tok; - } -#undef isvalidchar -} - -static -struct Token -lex_nospace(io·Peeker s, void *impl) -{ - struct Token tok; - tok = lex(s, impl); - if (tok.kind == tok·space) { - tok = lex_nospace(s, impl); - } - - return tok; -} - -struct Parser -{ - int lev; - bio·Node *root; - struct Token tok; - - void *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 -#include -#include - -#include -#include -#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 -- cgit v1.2.1