taddress.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
taddress.c (4011B) | |
--- | |
1 #include "sam.h" | |
2 #include "parse.h" | |
3 | |
4 Address addr; | |
5 String lastpat; | |
6 int patset; | |
7 File *menu; | |
8 | |
9 File *matchfile(String*); | |
10 Address charaddr(Posn, Address, int); | |
11 | |
12 Address | |
13 address(Addr *ap, Address a, int sign) | |
14 { | |
15 File *f = a.f; | |
16 Address a1, a2; | |
17 | |
18 do{ | |
19 switch(ap->type){ | |
20 case 'l': | |
21 case '#': | |
22 a = (*(ap->type=='#'?charaddr:lineaddr))(ap->num… | |
23 break; | |
24 | |
25 case '.': | |
26 a = f->dot; | |
27 break; | |
28 | |
29 case '$': | |
30 a.r.p1 = a.r.p2 = f->b.nc; | |
31 break; | |
32 | |
33 case '\'': | |
34 a.r = f->mark; | |
35 break; | |
36 | |
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, … | |
44 a.r = sel.p[0]; | |
45 break; | |
46 | |
47 case '"': | |
48 a = matchfile(ap->are)->dot; | |
49 f = a.f; | |
50 if(f->unread) | |
51 load(f); | |
52 break; | |
53 | |
54 case '*': | |
55 a.r.p1 = 0, a.r.p2 = f->b.nc; | |
56 return a; | |
57 | |
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; | |
79 | |
80 case '+': | |
81 case '-': | |
82 sign = 1; | |
83 if(ap->type == '-') | |
84 sign = -1; | |
85 if(ap->next==0 || ap->next->type=='+' || ap->nex… | |
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 } | |
95 | |
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"); | |
108 } | |
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"); | |
117 } | |
118 } | |
119 } | |
120 | |
121 File * | |
122 matchfile(String *r) | |
123 { | |
124 File *f; | |
125 File *match = 0; | |
126 int i; | |
127 | |
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; | |
136 } | |
137 } | |
138 if(!match) | |
139 error(Efsearch); | |
140 return match; | |
141 } | |
142 | |
143 int | |
144 filematch(File *f, String *r) | |
145 { | |
146 char *c, buf[STRSIZE+100]; | |
147 String *t; | |
148 | |
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); | |
163 } | |
164 | |
165 Address | |
166 charaddr(Posn l, Address addr, int sign) | |
167 { | |
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; | |
177 } | |
178 | |
179 Address | |
180 lineaddr(Posn l, Address addr, int sign) | |
181 { | |
182 int n; | |
183 int c; | |
184 File *f = addr.f; | |
185 Address a; | |
186 Posn p; | |
187 | |
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; | |
194 } | |
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'; | |
204 } | |
205 while(n < l){ | |
206 if(p >= f->b.nc) | |
207 error(Erange); | |
208 if(filereadc(f, p++) == '\n') | |
209 n++; | |
210 } | |
211 a.r.p1 = p; | |
212 } | |
213 while(p < f->b.nc && filereadc(f, p++)!='\n') | |
214 ; | |
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--; | |
229 } | |
230 } | |
231 a.r.p2 = p; | |
232 if(p > 0) | |
233 p--; | |
234 } | |
235 while(p > 0 && filereadc(f, p-1)!='\n') /* lines … | |
236 p--; | |
237 a.r.p1 = p; | |
238 } | |
239 return a; | |
240 } |