Initial revision
This commit is contained in:
parent
ed7c8e8d02
commit
76193d7cb0
223 changed files with 32479 additions and 0 deletions
508
src/cmd/sam/xec.c
Normal file
508
src/cmd/sam/xec.c
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
#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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue