Initial revision
This commit is contained in:
parent
ed7c8e8d02
commit
76193d7cb0
223 changed files with 32479 additions and 0 deletions
240
src/cmd/sam/address.c
Normal file
240
src/cmd/sam/address.c
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
#include "sam.h"
|
||||
#include "parse.h"
|
||||
|
||||
Address addr;
|
||||
String lastpat;
|
||||
int patset;
|
||||
File *menu;
|
||||
|
||||
File *matchfile(String*);
|
||||
Address charaddr(Posn, Address, int);
|
||||
|
||||
Address
|
||||
address(Addr *ap, Address a, int sign)
|
||||
{
|
||||
File *f = a.f;
|
||||
Address a1, a2;
|
||||
|
||||
do{
|
||||
switch(ap->type){
|
||||
case 'l':
|
||||
case '#':
|
||||
a = (*(ap->type=='#'?charaddr:lineaddr))(ap->num, a, sign);
|
||||
break;
|
||||
|
||||
case '.':
|
||||
a = f->dot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
a.r.p1 = a.r.p2 = f->_.nc;
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
a.r = f->mark;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
sign = -sign;
|
||||
if(sign == 0)
|
||||
sign = -1;
|
||||
/* fall through */
|
||||
case '/':
|
||||
nextmatch(f, ap->are, sign>=0? a.r.p2 : a.r.p1, sign);
|
||||
a.r = sel.p[0];
|
||||
break;
|
||||
|
||||
case '"':
|
||||
a = matchfile(ap->are)->dot;
|
||||
f = a.f;
|
||||
if(f->unread)
|
||||
load(f);
|
||||
break;
|
||||
|
||||
case '*':
|
||||
a.r.p1 = 0, a.r.p2 = f->_.nc;
|
||||
return a;
|
||||
|
||||
case ',':
|
||||
case ';':
|
||||
if(ap->left)
|
||||
a1 = address(ap->left, a, 0);
|
||||
else
|
||||
a1.f = a.f, a1.r.p1 = a1.r.p2 = 0;
|
||||
if(ap->type == ';'){
|
||||
f = a1.f;
|
||||
a = a1;
|
||||
f->dot = a1;
|
||||
}
|
||||
if(ap->next)
|
||||
a2 = address(ap->next, a, 0);
|
||||
else
|
||||
a2.f = a.f, a2.r.p1 = a2.r.p2 = f->_.nc;
|
||||
if(a1.f != a2.f)
|
||||
error(Eorder);
|
||||
a.f = a1.f, a.r.p1 = a1.r.p1, a.r.p2 = a2.r.p2;
|
||||
if(a.r.p2 < a.r.p1)
|
||||
error(Eorder);
|
||||
return a;
|
||||
|
||||
case '+':
|
||||
case '-':
|
||||
sign = 1;
|
||||
if(ap->type == '-')
|
||||
sign = -1;
|
||||
if(ap->next==0 || ap->next->type=='+' || ap->next->type=='-')
|
||||
a = lineaddr(1L, a, sign);
|
||||
break;
|
||||
default:
|
||||
panic("address");
|
||||
return a;
|
||||
}
|
||||
}while(ap = ap->next); /* assign = */
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
nextmatch(File *f, String *r, Posn p, int sign)
|
||||
{
|
||||
compile(r);
|
||||
if(sign >= 0){
|
||||
if(!execute(f, p, INFINITY))
|
||||
error(Esearch);
|
||||
if(sel.p[0].p1==sel.p[0].p2 && sel.p[0].p1==p){
|
||||
if(++p>f->_.nc)
|
||||
p = 0;
|
||||
if(!execute(f, p, INFINITY))
|
||||
panic("address");
|
||||
}
|
||||
}else{
|
||||
if(!bexecute(f, p))
|
||||
error(Esearch);
|
||||
if(sel.p[0].p1==sel.p[0].p2 && sel.p[0].p2==p){
|
||||
if(--p<0)
|
||||
p = f->_.nc;
|
||||
if(!bexecute(f, p))
|
||||
panic("address");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File *
|
||||
matchfile(String *r)
|
||||
{
|
||||
File *f;
|
||||
File *match = 0;
|
||||
int i;
|
||||
|
||||
for(i = 0; i<file.nused; i++){
|
||||
f = file.filepptr[i];
|
||||
if(f == cmd)
|
||||
continue;
|
||||
if(filematch(f, r)){
|
||||
if(match)
|
||||
error(Emanyfiles);
|
||||
match = f;
|
||||
}
|
||||
}
|
||||
if(!match)
|
||||
error(Efsearch);
|
||||
return match;
|
||||
}
|
||||
|
||||
int
|
||||
filematch(File *f, String *r)
|
||||
{
|
||||
char *c, buf[STRSIZE+100];
|
||||
String *t;
|
||||
|
||||
c = Strtoc(&f->name);
|
||||
sprint(buf, "%c%c%c %s\n", " '"[f->mod],
|
||||
"-+"[f->rasp!=0], " ."[f==curfile], c);
|
||||
free(c);
|
||||
t = tmpcstr(buf);
|
||||
Strduplstr(&genstr, t);
|
||||
freetmpstr(t);
|
||||
/* A little dirty... */
|
||||
if(menu == 0)
|
||||
menu = fileopen();
|
||||
bufreset(menu);
|
||||
bufinsert(menu, 0, genstr.s, genstr.n);
|
||||
compile(r);
|
||||
return execute(menu, 0, menu->_.nc);
|
||||
}
|
||||
|
||||
Address
|
||||
charaddr(Posn l, Address addr, int sign)
|
||||
{
|
||||
if(sign == 0)
|
||||
addr.r.p1 = addr.r.p2 = l;
|
||||
else if(sign < 0)
|
||||
addr.r.p2 = addr.r.p1-=l;
|
||||
else if(sign > 0)
|
||||
addr.r.p1 = addr.r.p2+=l;
|
||||
if(addr.r.p1<0 || addr.r.p2>addr.f->_.nc)
|
||||
error(Erange);
|
||||
return addr;
|
||||
}
|
||||
|
||||
Address
|
||||
lineaddr(Posn l, Address addr, int sign)
|
||||
{
|
||||
int n;
|
||||
int c;
|
||||
File *f = addr.f;
|
||||
Address a;
|
||||
Posn p;
|
||||
|
||||
a.f = f;
|
||||
if(sign >= 0){
|
||||
if(l == 0){
|
||||
if(sign==0 || addr.r.p2==0){
|
||||
a.r.p1 = a.r.p2 = 0;
|
||||
return a;
|
||||
}
|
||||
a.r.p1 = addr.r.p2;
|
||||
p = addr.r.p2-1;
|
||||
}else{
|
||||
if(sign==0 || addr.r.p2==0){
|
||||
p = (Posn)0;
|
||||
n = 1;
|
||||
}else{
|
||||
p = addr.r.p2-1;
|
||||
n = filereadc(f, p++)=='\n';
|
||||
}
|
||||
while(n < l){
|
||||
if(p >= f->_.nc)
|
||||
error(Erange);
|
||||
if(filereadc(f, p++) == '\n')
|
||||
n++;
|
||||
}
|
||||
a.r.p1 = p;
|
||||
}
|
||||
while(p < f->_.nc && filereadc(f, p++)!='\n')
|
||||
;
|
||||
a.r.p2 = p;
|
||||
}else{
|
||||
p = addr.r.p1;
|
||||
if(l == 0)
|
||||
a.r.p2 = addr.r.p1;
|
||||
else{
|
||||
for(n = 0; n<l; ){ /* always runs once */
|
||||
if(p == 0){
|
||||
if(++n != l)
|
||||
error(Erange);
|
||||
}else{
|
||||
c = filereadc(f, p-1);
|
||||
if(c != '\n' || ++n != l)
|
||||
p--;
|
||||
}
|
||||
}
|
||||
a.r.p2 = p;
|
||||
if(p > 0)
|
||||
p--;
|
||||
}
|
||||
while(p > 0 && filereadc(f, p-1)!='\n') /* lines start after a newline */
|
||||
p--;
|
||||
a.r.p1 = p;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue