Blob


1 #include "sam.h"
2 #include "parse.h"
4 Address addr;
5 String lastpat;
6 int patset;
7 File *menu;
9 File *matchfile(String*);
10 Address charaddr(Posn, Address, int);
12 Address
13 address(Addr *ap, Address a, int sign)
14 {
15 File *f = a.f;
16 Address a1, a2;
18 do{
19 switch(ap->type){
20 case 'l':
21 case '#':
22 a = (*(ap->type=='#'?charaddr:lineaddr))(ap->num, a, sign);
23 break;
25 case '.':
26 a = f->dot;
27 break;
29 case '$':
30 a.r.p1 = a.r.p2 = f->b.nc;
31 break;
33 case '\'':
34 a.r = f->mark;
35 break;
37 case '?':
38 sign = -sign;
39 if(sign == 0)
40 sign = -1;
41 /* fall through */
42 case '/':
43 nextmatch(f, ap->are, sign>=0? a.r.p2 : a.r.p1, sign);
44 a.r = sel.p[0];
45 break;
47 case '"':
48 a = matchfile(ap->are)->dot;
49 f = a.f;
50 if(f->unread)
51 load(f);
52 break;
54 case '*':
55 a.r.p1 = 0, a.r.p2 = f->b.nc;
56 return a;
58 case ',':
59 case ';':
60 if(ap->left)
61 a1 = address(ap->left, a, 0);
62 else
63 a1.f = a.f, a1.r.p1 = a1.r.p2 = 0;
64 if(ap->type == ';'){
65 f = a1.f;
66 a = a1;
67 f->dot = a1;
68 }
69 if(ap->next)
70 a2 = address(ap->next, a, 0);
71 else
72 a2.f = a.f, a2.r.p1 = a2.r.p2 = f->b.nc;
73 if(a1.f != a2.f)
74 error(Eorder);
75 a.f = a1.f, a.r.p1 = a1.r.p1, a.r.p2 = a2.r.p2;
76 if(a.r.p2 < a.r.p1)
77 error(Eorder);
78 return a;
80 case '+':
81 case '-':
82 sign = 1;
83 if(ap->type == '-')
84 sign = -1;
85 if(ap->next==0 || ap->next->type=='+' || ap->next->type=='-')
86 a = lineaddr(1L, a, sign);
87 break;
88 default:
89 panic("address");
90 return a;
91 }
92 }while(ap = ap->next); /* assign = */
93 return a;
94 }
96 void
97 nextmatch(File *f, String *r, Posn p, int sign)
98 {
99 compile(r);
100 if(sign >= 0){
101 if(!execute(f, p, INFINITY))
102 error(Esearch);
103 if(sel.p[0].p1==sel.p[0].p2 && sel.p[0].p1==p){
104 if(++p>f->b.nc)
105 p = 0;
106 if(!execute(f, p, INFINITY))
107 panic("address");
109 }else{
110 if(!bexecute(f, p))
111 error(Esearch);
112 if(sel.p[0].p1==sel.p[0].p2 && sel.p[0].p2==p){
113 if(--p<0)
114 p = f->b.nc;
115 if(!bexecute(f, p))
116 panic("address");
121 File *
122 matchfile(String *r)
124 File *f;
125 File *match = 0;
126 int i;
128 for(i = 0; i<file.nused; i++){
129 f = file.filepptr[i];
130 if(f == cmd)
131 continue;
132 if(filematch(f, r)){
133 if(match)
134 error(Emanyfiles);
135 match = f;
138 if(!match)
139 error(Efsearch);
140 return match;
143 int
144 filematch(File *f, String *r)
146 char *c, buf[STRSIZE+100];
147 String *t;
149 c = Strtoc(&f->name);
150 sprint(buf, "%c%c%c %s\n", " '"[f->mod],
151 "-+"[f->rasp!=0], " ."[f==curfile], c);
152 free(c);
153 t = tmpcstr(buf);
154 Strduplstr(&genstr, t);
155 freetmpstr(t);
156 /* A little dirty... */
157 if(menu == 0)
158 menu = fileopen();
159 bufreset(&menu->b);
160 bufinsert(&menu->b, 0, genstr.s, genstr.n);
161 compile(r);
162 return execute(menu, 0, menu->b.nc);
165 Address
166 charaddr(Posn l, Address addr, int sign)
168 if(sign == 0)
169 addr.r.p1 = addr.r.p2 = l;
170 else if(sign < 0)
171 addr.r.p2 = addr.r.p1-=l;
172 else if(sign > 0)
173 addr.r.p1 = addr.r.p2+=l;
174 if(addr.r.p1<0 || addr.r.p2>addr.f->b.nc)
175 error(Erange);
176 return addr;
179 Address
180 lineaddr(Posn l, Address addr, int sign)
182 int n;
183 int c;
184 File *f = addr.f;
185 Address a;
186 Posn p;
188 a.f = f;
189 if(sign >= 0){
190 if(l == 0){
191 if(sign==0 || addr.r.p2==0){
192 a.r.p1 = a.r.p2 = 0;
193 return a;
195 a.r.p1 = addr.r.p2;
196 p = addr.r.p2-1;
197 }else{
198 if(sign==0 || addr.r.p2==0){
199 p = (Posn)0;
200 n = 1;
201 }else{
202 p = addr.r.p2-1;
203 n = filereadc(f, p++)=='\n';
205 while(n < l){
206 if(p >= f->b.nc)
207 error(Erange);
208 if(filereadc(f, p++) == '\n')
209 n++;
211 a.r.p1 = p;
213 while(p < f->b.nc && filereadc(f, p++)!='\n')
215 a.r.p2 = p;
216 }else{
217 p = addr.r.p1;
218 if(l == 0)
219 a.r.p2 = addr.r.p1;
220 else{
221 for(n = 0; n<l; ){ /* always runs once */
222 if(p == 0){
223 if(++n != l)
224 error(Erange);
225 }else{
226 c = filereadc(f, p-1);
227 if(c != '\n' || ++n != l)
228 p--;
231 a.r.p2 = p;
232 if(p > 0)
233 p--;
235 while(p > 0 && filereadc(f, p-1)!='\n') /* lines start after a newline */
236 p--;
237 a.r.p1 = p;
239 return a;