123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- #include "sam.h"
- #include "parse.h"
- int Glooping;
- int nest;
- int append(File*, Cmd*, Posn);
- int display(File*);
- void looper(File*, Cmd*, int);
- void filelooper(Cmd*, int);
- void linelooper(File*, Cmd*);
- void
- resetxec(void)
- {
- Glooping = nest = 0;
- }
- int
- cmdexec(File *f, Cmd *cp)
- {
- int i;
- Addr *ap;
- Address a;
- if(f && f->unread)
- load(f);
- if(f==0 && (cp->addr==0 || cp->addr->type!='"') &&
- !utfrune("bBnqUXY!", cp->cmdc) &&
- cp->cmdc!=('c'|0x100) && !(cp->cmdc=='D' && cp->ctext))
- error(Enofile);
- i = lookup(cp->cmdc);
- if(i >= 0 && cmdtab[i].defaddr != aNo){
- if((ap=cp->addr)==0 && cp->cmdc!='\n'){
- cp->addr = ap = newaddr();
- ap->type = '.';
- if(cmdtab[i].defaddr == aAll)
- ap->type = '*';
- }else if(ap && ap->type=='"' && ap->next==0 && cp->cmdc!='\n'){
- ap->next = newaddr();
- ap->next->type = '.';
- if(cmdtab[i].defaddr == aAll)
- ap->next->type = '*';
- }
- if(cp->addr){ /* may be false for '\n' (only) */
- static Address none = {0,0,0};
- if(f)
- addr = address(ap, f->dot, 0);
- else /* a " */
- addr = address(ap, none, 0);
- f = addr.f;
- }
- }
- current(f);
- switch(cp->cmdc){
- case '{':
- a = cp->addr? address(cp->addr, f->dot, 0): f->dot;
- for(cp = cp->ccmd; cp; cp = cp->next){
- a.f->dot = a;
- cmdexec(a.f, cp);
- }
- break;
- default:
- i=(*cmdtab[i].fn)(f, cp);
- return i;
- }
- return 1;
- }
- int
- a_cmd(File *f, Cmd *cp)
- {
- return append(f, cp, addr.r.p2);
- }
- int
- b_cmd(File *f, Cmd *cp)
- {
- USED(f);
- f = cp->cmdc=='b'? tofile(cp->ctext) : getfile(cp->ctext);
- if(f->unread)
- load(f);
- else if(nest == 0)
- filename(f);
- return TRUE;
- }
- int
- c_cmd(File *f, Cmd *cp)
- {
- logdelete(f, addr.r.p1, addr.r.p2);
- f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p2;
- return append(f, cp, addr.r.p2);
- }
- int
- d_cmd(File *f, Cmd *cp)
- {
- USED(cp);
- logdelete(f, addr.r.p1, addr.r.p2);
- f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p1;
- return TRUE;
- }
- int
- D_cmd(File *f, Cmd *cp)
- {
- closefiles(f, cp->ctext);
- return TRUE;
- }
- int
- e_cmd(File *f, Cmd *cp)
- {
- if(getname(f, cp->ctext, cp->cmdc=='e')==0)
- error(Enoname);
- edit(f, cp->cmdc);
- return TRUE;
- }
- int
- f_cmd(File *f, Cmd *cp)
- {
- getname(f, cp->ctext, TRUE);
- filename(f);
- return TRUE;
- }
- int
- g_cmd(File *f, Cmd *cp)
- {
- if(f!=addr.f)panic("g_cmd f!=addr.f");
- compile(cp->re);
- if(execute(f, addr.r.p1, addr.r.p2) ^ cp->cmdc=='v'){
- f->dot = addr;
- return cmdexec(f, cp->ccmd);
- }
- return TRUE;
- }
- int
- i_cmd(File *f, Cmd *cp)
- {
- return append(f, cp, addr.r.p1);
- }
- int
- k_cmd(File *f, Cmd *cp)
- {
- USED(cp);
- f->mark = addr.r;
- return TRUE;
- }
- int
- m_cmd(File *f, Cmd *cp)
- {
- Address addr2;
- addr2 = address(cp->caddr, f->dot, 0);
- if(cp->cmdc=='m')
- move(f, addr2);
- else
- copy(f, addr2);
- return TRUE;
- }
- int
- n_cmd(File *f, Cmd *cp)
- {
- int i;
- USED(f);
- USED(cp);
- for(i = 0; i<file.nused; i++){
- if(file.filepptr[i] == cmd)
- continue;
- f = file.filepptr[i];
- Strduplstr(&genstr, &f->name);
- filename(f);
- }
- return TRUE;
- }
- int
- p_cmd(File *f, Cmd *cp)
- {
- USED(cp);
- return display(f);
- }
- int
- q_cmd(File *f, Cmd *cp)
- {
- USED(cp);
- USED(f);
- trytoquit();
- if(downloaded){
- outT0(Hexit);
- return TRUE;
- }
- return FALSE;
- }
- int
- s_cmd(File *f, Cmd *cp)
- {
- int i, j, c, n;
- Posn p1, op, didsub = 0, delta = 0;
- n = cp->num;
- op= -1;
- compile(cp->re);
- for(p1 = addr.r.p1; p1<=addr.r.p2 && execute(f, p1, addr.r.p2); ){
- if(sel.p[0].p1==sel.p[0].p2){ /* empty match? */
- if(sel.p[0].p1==op){
- p1++;
- continue;
- }
- p1 = sel.p[0].p2+1;
- }else
- p1 = sel.p[0].p2;
- op = sel.p[0].p2;
- if(--n>0)
- continue;
- Strzero(&genstr);
- for(i = 0; i<cp->ctext->n; i++)
- if((c = cp->ctext->s[i])=='\\' && i<cp->ctext->n-1){
- c = cp->ctext->s[++i];
- if('1'<=c && c<='9') {
- j = c-'0';
- if(sel.p[j].p2-sel.p[j].p1>BLOCKSIZE)
- error(Elongtag);
- bufread(f, sel.p[j].p1, genbuf, sel.p[j].p2-sel.p[j].p1);
- Strinsert(&genstr, tmprstr(genbuf, (sel.p[j].p2-sel.p[j].p1)), genstr.n);
- }else
- Straddc(&genstr, c);
- }else if(c!='&')
- Straddc(&genstr, c);
- else{
- if(sel.p[0].p2-sel.p[0].p1>BLOCKSIZE)
- error(Elongrhs);
- bufread(f, sel.p[0].p1, genbuf, sel.p[0].p2-sel.p[0].p1);
- Strinsert(&genstr,
- tmprstr(genbuf, (int)(sel.p[0].p2-sel.p[0].p1)),
- genstr.n);
- }
- if(sel.p[0].p1!=sel.p[0].p2){
- logdelete(f, sel.p[0].p1, sel.p[0].p2);
- delta-=sel.p[0].p2-sel.p[0].p1;
- }
- if(genstr.n){
- loginsert(f, sel.p[0].p2, genstr.s, genstr.n);
- delta+=genstr.n;
- }
- didsub = 1;
- if(!cp->flag)
- break;
- }
- if(!didsub && nest==0)
- error(Enosub);
- f->ndot.r.p1 = addr.r.p1, f->ndot.r.p2 = addr.r.p2+delta;
- return TRUE;
- }
- int
- u_cmd(File *f, Cmd *cp)
- {
- int n;
- USED(f);
- USED(cp);
- n = cp->num;
- if(n >= 0)
- while(n-- && undo(TRUE))
- ;
- else
- while(n++ && undo(FALSE))
- ;
- return TRUE;
- }
- int
- w_cmd(File *f, Cmd *cp)
- {
- int fseq;
- fseq = f->seq;
- if(getname(f, cp->ctext, FALSE)==0)
- error(Enoname);
- if(fseq == seq)
- error_s(Ewseq, genc);
- writef(f);
- return TRUE;
- }
- int
- x_cmd(File *f, Cmd *cp)
- {
- if(cp->re)
- looper(f, cp, cp->cmdc=='x');
- else
- linelooper(f, cp);
- return TRUE;
- }
- int
- X_cmd(File *f, Cmd *cp)
- {
- USED(f);
- filelooper(cp, cp->cmdc=='X');
- return TRUE;
- }
- int
- plan9_cmd(File *f, Cmd *cp)
- {
- plan9(f, cp->cmdc, cp->ctext, nest);
- return TRUE;
- }
- int
- eq_cmd(File *f, Cmd *cp)
- {
- int charsonly;
- switch(cp->ctext->n){
- case 1:
- charsonly = FALSE;
- break;
- case 2:
- if(cp->ctext->s[0]=='#'){
- charsonly = TRUE;
- break;
- }
- default:
- SET(charsonly);
- error(Enewline);
- }
- printposn(f, charsonly);
- return TRUE;
- }
- int
- nl_cmd(File *f, Cmd *cp)
- {
- Address a;
- if(cp->addr == 0){
- /* First put it on newline boundaries */
- addr = lineaddr((Posn)0, f->dot, -1);
- a = lineaddr((Posn)0, f->dot, 1);
- addr.r.p2 = a.r.p2;
- if(addr.r.p1==f->dot.r.p1 && addr.r.p2==f->dot.r.p2)
- addr = lineaddr((Posn)1, f->dot, 1);
- display(f);
- }else if(downloaded)
- moveto(f, addr.r);
- else
- display(f);
- return TRUE;
- }
- int
- cd_cmd(File *f, Cmd *cp)
- {
- USED(f);
- cd(cp->ctext);
- return TRUE;
- }
- int
- append(File *f, Cmd *cp, Posn p)
- {
- if(cp->ctext->n>0 && cp->ctext->s[cp->ctext->n-1]==0)
- --cp->ctext->n;
- if(cp->ctext->n>0)
- loginsert(f, p, cp->ctext->s, cp->ctext->n);
- f->ndot.r.p1 = p;
- f->ndot.r.p2 = p+cp->ctext->n;
- return TRUE;
- }
- int
- display(File *f)
- {
- Posn p1, p2;
- int np;
- char *c;
- p1 = addr.r.p1;
- p2 = addr.r.p2;
- if(p2 > f->nc){
- fprint(2, "bad display addr p1=%ld p2=%ld f->nc=%d\n", p1, p2, f->nc); /*ZZZ should never happen, can remove */
- p2 = f->nc;
- }
- while(p1 < p2){
- np = p2-p1;
- if(np>BLOCKSIZE-1)
- np = BLOCKSIZE-1;
- bufread(f, p1, genbuf, np);
- genbuf[np] = 0;
- c = Strtoc(tmprstr(genbuf, np+1));
- if(downloaded)
- termwrite(c);
- else
- Write(1, c, strlen(c));
- free(c);
- p1 += np;
- }
- f->dot = addr;
- return TRUE;
- }
- void
- looper(File *f, Cmd *cp, int xy)
- {
- Posn p, op;
- Range r;
- r = addr.r;
- op= xy? -1 : r.p1;
- nest++;
- compile(cp->re);
- for(p = r.p1; p<=r.p2; ){
- if(!execute(f, p, r.p2)){ /* no match, but y should still run */
- if(xy || op>r.p2)
- break;
- f->dot.r.p1 = op, f->dot.r.p2 = r.p2;
- p = r.p2+1; /* exit next loop */
- }else{
- if(sel.p[0].p1==sel.p[0].p2){ /* empty match? */
- if(sel.p[0].p1==op){
- p++;
- continue;
- }
- p = sel.p[0].p2+1;
- }else
- p = sel.p[0].p2;
- if(xy)
- f->dot.r = sel.p[0];
- else
- f->dot.r.p1 = op, f->dot.r.p2 = sel.p[0].p1;
- }
- op = sel.p[0].p2;
- cmdexec(f, cp->ccmd);
- compile(cp->re);
- }
- --nest;
- }
- void
- linelooper(File *f, Cmd *cp)
- {
- Posn p;
- Range r, linesel;
- Address a, a3;
- nest++;
- r = addr.r;
- a3.f = f;
- a3.r.p1 = a3.r.p2 = r.p1;
- for(p = r.p1; p<r.p2; p = a3.r.p2){
- a3.r.p1 = a3.r.p2;
- /*pjw if(p!=r.p1 || (linesel = lineaddr((Posn)0, a3, 1)).r.p2==p)*/
- if(p!=r.p1 || (a = lineaddr((Posn)0, a3, 1), linesel = a.r, linesel.p2==p)){
- a = lineaddr((Posn)1, a3, 1);
- linesel = a.r;
- }
- if(linesel.p1 >= r.p2)
- break;
- if(linesel.p2 >= r.p2)
- linesel.p2 = r.p2;
- if(linesel.p2 > linesel.p1)
- if(linesel.p1>=a3.r.p2 && linesel.p2>a3.r.p2){
- f->dot.r = linesel;
- cmdexec(f, cp->ccmd);
- a3.r = linesel;
- continue;
- }
- break;
- }
- --nest;
- }
- void
- filelooper(Cmd *cp, int XY)
- {
- File *f, *cur;
- int i;
- if(Glooping++)
- error(EnestXY);
- nest++;
- settempfile();
- cur = curfile;
- for(i = 0; i<tempfile.nused; i++){
- f = tempfile.filepptr[i];
- if(f==cmd)
- continue;
- if(cp->re==0 || filematch(f, cp->re)==XY)
- cmdexec(f, cp->ccmd);
- }
- if(cur && whichmenu(cur)>=0) /* check that cur is still a file */
- current(cur);
- --Glooping;
- --nest;
- }
|