txec.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
txec.c (8529B) | |
--- | |
1 #include "sam.h" | |
2 #include "parse.h" | |
3 | |
4 int Glooping; | |
5 int nest; | |
6 | |
7 int append(File*, Cmd*, Posn); | |
8 int display(File*); | |
9 void looper(File*, Cmd*, int); | |
10 void filelooper(Cmd*, int); | |
11 void linelooper(File*, Cmd*); | |
12 | |
13 void | |
14 resetxec(void) | |
15 { | |
16 Glooping = nest = 0; | |
17 } | |
18 | |
19 int | |
20 cmdexec(File *f, Cmd *cp) | |
21 { | |
22 int i; | |
23 Addr *ap; | |
24 Address a; | |
25 | |
26 if(f && f->unread) | |
27 load(f); | |
28 if(f==0 && (cp->addr==0 || cp->addr->type!='"') && | |
29 !utfrune("bBnqUXY!", cp->cmdc) && | |
30 cp->cmdc!=('c'|0x100) && !(cp->cmdc=='D' && cp->ctext)) | |
31 error(Enofile); | |
32 i = lookup(cp->cmdc); | |
33 if(i >= 0 && cmdtab[i].defaddr != aNo){ | |
34 if((ap=cp->addr)==0 && cp->cmdc!='\n'){ | |
35 cp->addr = ap = newaddr(); | |
36 ap->type = '.'; | |
37 if(cmdtab[i].defaddr == aAll) | |
38 ap->type = '*'; | |
39 }else if(ap && ap->type=='"' && ap->next==0 && cp->cmdc!… | |
40 ap->next = newaddr(); | |
41 ap->next->type = '.'; | |
42 if(cmdtab[i].defaddr == aAll) | |
43 ap->next->type = '*'; | |
44 } | |
45 if(cp->addr){ /* may be false for '\n' (only) */ | |
46 static Address none = {0,0,0}; | |
47 if(f) | |
48 addr = address(ap, f->dot, 0); | |
49 else /* a " */ | |
50 addr = address(ap, none, 0); | |
51 f = addr.f; | |
52 } | |
53 } | |
54 current(f); | |
55 switch(cp->cmdc){ | |
56 case '{': | |
57 a = cp->addr? address(cp->addr, f->dot, 0): f->dot; | |
58 for(cp = cp->ccmd; cp; cp = cp->next){ | |
59 a.f->dot = a; | |
60 cmdexec(a.f, cp); | |
61 } | |
62 break; | |
63 default: | |
64 i=(*cmdtab[i].fn)(f, cp); | |
65 return i; | |
66 } | |
67 return 1; | |
68 } | |
69 | |
70 | |
71 int | |
72 a_cmd(File *f, Cmd *cp) | |
73 { | |
74 return append(f, cp, addr.r.p2); | |
75 } | |
76 | |
77 int | |
78 b_cmd(File *f, Cmd *cp) | |
79 { | |
80 USED(f); | |
81 f = cp->cmdc=='b'? tofile(cp->ctext) : getfile(cp->ctext); | |
82 if(f->unread) | |
83 load(f); | |
84 else if(nest == 0) | |
85 filename(f); | |
86 return TRUE; | |
87 } | |
88 | |
89 int | |
90 c_cmd(File *f, Cmd *cp) | |
91 { | |
92 logdelete(f, addr.r.p1, addr.r.p2); | |
93 f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p2; | |
94 return append(f, cp, addr.r.p2); | |
95 } | |
96 | |
97 int | |
98 d_cmd(File *f, Cmd *cp) | |
99 { | |
100 USED(cp); | |
101 logdelete(f, addr.r.p1, addr.r.p2); | |
102 f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p1; | |
103 return TRUE; | |
104 } | |
105 | |
106 int | |
107 D_cmd(File *f, Cmd *cp) | |
108 { | |
109 closefiles(f, cp->ctext); | |
110 return TRUE; | |
111 } | |
112 | |
113 int | |
114 e_cmd(File *f, Cmd *cp) | |
115 { | |
116 if(getname(f, cp->ctext, cp->cmdc=='e')==0) | |
117 error(Enoname); | |
118 edit(f, cp->cmdc); | |
119 return TRUE; | |
120 } | |
121 | |
122 int | |
123 f_cmd(File *f, Cmd *cp) | |
124 { | |
125 getname(f, cp->ctext, TRUE); | |
126 filename(f); | |
127 return TRUE; | |
128 } | |
129 | |
130 int | |
131 g_cmd(File *f, Cmd *cp) | |
132 { | |
133 if(f!=addr.f)panic("g_cmd f!=addr.f"); | |
134 compile(cp->re); | |
135 if(execute(f, addr.r.p1, addr.r.p2) ^ cp->cmdc=='v'){ | |
136 f->dot = addr; | |
137 return cmdexec(f, cp->ccmd); | |
138 } | |
139 return TRUE; | |
140 } | |
141 | |
142 int | |
143 i_cmd(File *f, Cmd *cp) | |
144 { | |
145 return append(f, cp, addr.r.p1); | |
146 } | |
147 | |
148 int | |
149 k_cmd(File *f, Cmd *cp) | |
150 { | |
151 USED(cp); | |
152 f->mark = addr.r; | |
153 return TRUE; | |
154 } | |
155 | |
156 int | |
157 m_cmd(File *f, Cmd *cp) | |
158 { | |
159 Address addr2; | |
160 | |
161 addr2 = address(cp->caddr, f->dot, 0); | |
162 if(cp->cmdc=='m') | |
163 move(f, addr2); | |
164 else | |
165 copy(f, addr2); | |
166 return TRUE; | |
167 } | |
168 | |
169 int | |
170 n_cmd(File *f, Cmd *cp) | |
171 { | |
172 int i; | |
173 USED(f); | |
174 USED(cp); | |
175 for(i = 0; i<file.nused; i++){ | |
176 if(file.filepptr[i] == cmd) | |
177 continue; | |
178 f = file.filepptr[i]; | |
179 Strduplstr(&genstr, &f->name); | |
180 filename(f); | |
181 } | |
182 return TRUE; | |
183 } | |
184 | |
185 int | |
186 p_cmd(File *f, Cmd *cp) | |
187 { | |
188 USED(cp); | |
189 return display(f); | |
190 } | |
191 | |
192 int | |
193 q_cmd(File *f, Cmd *cp) | |
194 { | |
195 USED(cp); | |
196 USED(f); | |
197 trytoquit(); | |
198 if(downloaded){ | |
199 outT0(Hexit); | |
200 return TRUE; | |
201 } | |
202 return FALSE; | |
203 } | |
204 | |
205 int | |
206 s_cmd(File *f, Cmd *cp) | |
207 { | |
208 int i, j, c, n; | |
209 Posn p1, op, didsub = 0, delta = 0; | |
210 | |
211 n = cp->num; | |
212 op= -1; | |
213 compile(cp->re); | |
214 for(p1 = addr.r.p1; p1<=addr.r.p2 && execute(f, p1, addr.r.p2); … | |
215 if(sel.p[0].p1==sel.p[0].p2){ /* empty match? */ | |
216 if(sel.p[0].p1==op){ | |
217 p1++; | |
218 continue; | |
219 } | |
220 p1 = sel.p[0].p2+1; | |
221 }else | |
222 p1 = sel.p[0].p2; | |
223 op = sel.p[0].p2; | |
224 if(--n>0) | |
225 continue; | |
226 Strzero(&genstr); | |
227 for(i = 0; i<cp->ctext->n; i++) | |
228 if((c = cp->ctext->s[i])=='\\' && i<cp->ctext->n… | |
229 c = cp->ctext->s[++i]; | |
230 if('1'<=c && c<='9') { | |
231 j = c-'0'; | |
232 if(sel.p[j].p2-sel.p[j].p1>BLOCK… | |
233 error(Elongtag); | |
234 bufread(&f->b, sel.p[j].p1, genb… | |
235 Strinsert(&genstr, tmprstr(genbu… | |
236 }else | |
237 Straddc(&genstr, c); | |
238 }else if(c!='&') | |
239 Straddc(&genstr, c); | |
240 else{ | |
241 if(sel.p[0].p2-sel.p[0].p1>BLOCKSIZE) | |
242 error(Elongrhs); | |
243 bufread(&f->b, sel.p[0].p1, genbuf, sel.… | |
244 Strinsert(&genstr, | |
245 tmprstr(genbuf, (int)(sel.p[0].p… | |
246 genstr.n); | |
247 } | |
248 if(sel.p[0].p1!=sel.p[0].p2){ | |
249 logdelete(f, sel.p[0].p1, sel.p[0].p2); | |
250 delta-=sel.p[0].p2-sel.p[0].p1; | |
251 } | |
252 if(genstr.n){ | |
253 loginsert(f, sel.p[0].p2, genstr.s, genstr.n); | |
254 delta+=genstr.n; | |
255 } | |
256 didsub = 1; | |
257 if(!cp->flag) | |
258 break; | |
259 } | |
260 if(!didsub && nest==0) | |
261 error(Enosub); | |
262 f->ndot.r.p1 = addr.r.p1, f->ndot.r.p2 = addr.r.p2+delta; | |
263 return TRUE; | |
264 } | |
265 | |
266 int | |
267 u_cmd(File *f, Cmd *cp) | |
268 { | |
269 int n; | |
270 | |
271 USED(f); | |
272 USED(cp); | |
273 n = cp->num; | |
274 if(n >= 0) | |
275 while(n-- && undo(TRUE)) | |
276 ; | |
277 else | |
278 while(n++ && undo(FALSE)) | |
279 ; | |
280 return TRUE; | |
281 } | |
282 | |
283 int | |
284 w_cmd(File *f, Cmd *cp) | |
285 { | |
286 int fseq; | |
287 | |
288 fseq = f->seq; | |
289 if(getname(f, cp->ctext, FALSE)==0) | |
290 error(Enoname); | |
291 if(fseq == seq) | |
292 error_s(Ewseq, genc); | |
293 writef(f); | |
294 return TRUE; | |
295 } | |
296 | |
297 int | |
298 x_cmd(File *f, Cmd *cp) | |
299 { | |
300 if(cp->re) | |
301 looper(f, cp, cp->cmdc=='x'); | |
302 else | |
303 linelooper(f, cp); | |
304 return TRUE; | |
305 } | |
306 | |
307 int | |
308 X_cmd(File *f, Cmd *cp) | |
309 { | |
310 USED(f); | |
311 filelooper(cp, cp->cmdc=='X'); | |
312 return TRUE; | |
313 } | |
314 | |
315 int | |
316 plan9_cmd(File *f, Cmd *cp) | |
317 { | |
318 plan9(f, cp->cmdc, cp->ctext, nest); | |
319 return TRUE; | |
320 } | |
321 | |
322 int | |
323 eq_cmd(File *f, Cmd *cp) | |
324 { | |
325 int charsonly; | |
326 | |
327 switch(cp->ctext->n){ | |
328 case 1: | |
329 charsonly = FALSE; | |
330 break; | |
331 case 2: | |
332 if(cp->ctext->s[0]=='#'){ | |
333 charsonly = TRUE; | |
334 break; | |
335 } | |
336 default: | |
337 SET(charsonly); | |
338 error(Enewline); | |
339 } | |
340 printposn(f, charsonly); | |
341 return TRUE; | |
342 } | |
343 | |
344 int | |
345 nl_cmd(File *f, Cmd *cp) | |
346 { | |
347 Address a; | |
348 | |
349 if(cp->addr == 0){ | |
350 /* First put it on newline boundaries */ | |
351 addr = lineaddr((Posn)0, f->dot, -1); | |
352 a = lineaddr((Posn)0, f->dot, 1); | |
353 addr.r.p2 = a.r.p2; | |
354 if(addr.r.p1==f->dot.r.p1 && addr.r.p2==f->dot.r.p2) | |
355 addr = lineaddr((Posn)1, f->dot, 1); | |
356 display(f); | |
357 }else if(downloaded) | |
358 moveto(f, addr.r); | |
359 else | |
360 display(f); | |
361 return TRUE; | |
362 } | |
363 | |
364 int | |
365 cd_cmd(File *f, Cmd *cp) | |
366 { | |
367 USED(f); | |
368 cd(cp->ctext); | |
369 return TRUE; | |
370 } | |
371 | |
372 int | |
373 append(File *f, Cmd *cp, Posn p) | |
374 { | |
375 if(cp->ctext->n>0 && cp->ctext->s[cp->ctext->n-1]==0) | |
376 --cp->ctext->n; | |
377 if(cp->ctext->n>0) | |
378 loginsert(f, p, cp->ctext->s, cp->ctext->n); | |
379 f->ndot.r.p1 = p; | |
380 f->ndot.r.p2 = p+cp->ctext->n; | |
381 return TRUE; | |
382 } | |
383 | |
384 int | |
385 display(File *f) | |
386 { | |
387 Posn p1, p2; | |
388 int np; | |
389 char *c; | |
390 | |
391 p1 = addr.r.p1; | |
392 p2 = addr.r.p2; | |
393 if(p2 > f->b.nc){ | |
394 fprint(2, "bad display addr p1=%ld p2=%ld f->b.nc=%d\n",… | |
395 p2 = f->b.nc; | |
396 } | |
397 while(p1 < p2){ | |
398 np = p2-p1; | |
399 if(np>BLOCKSIZE-1) | |
400 np = BLOCKSIZE-1; | |
401 bufread(&f->b, p1, genbuf, np); | |
402 genbuf[np] = 0; | |
403 c = Strtoc(tmprstr(genbuf, np+1)); | |
404 if(downloaded) | |
405 termwrite(c); | |
406 else | |
407 Write(1, c, strlen(c)); | |
408 free(c); | |
409 p1 += np; | |
410 } | |
411 f->dot = addr; | |
412 return TRUE; | |
413 } | |
414 | |
415 void | |
416 looper(File *f, Cmd *cp, int xy) | |
417 { | |
418 Posn p, op; | |
419 Range r; | |
420 | |
421 r = addr.r; | |
422 op= xy? -1 : r.p1; | |
423 nest++; | |
424 compile(cp->re); | |
425 for(p = r.p1; p<=r.p2; ){ | |
426 if(!execute(f, p, r.p2)){ /* no match, but y should stil… | |
427 if(xy || op>r.p2) | |
428 break; | |
429 f->dot.r.p1 = op, f->dot.r.p2 = r.p2; | |
430 p = r.p2+1; /* exit next loop */ | |
431 }else{ | |
432 if(sel.p[0].p1==sel.p[0].p2){ /* empty ma… | |
433 if(sel.p[0].p1==op){ | |
434 p++; | |
435 continue; | |
436 } | |
437 p = sel.p[0].p2+1; | |
438 }else | |
439 p = sel.p[0].p2; | |
440 if(xy) | |
441 f->dot.r = sel.p[0]; | |
442 else | |
443 f->dot.r.p1 = op, f->dot.r.p2 = sel.p[0]… | |
444 } | |
445 op = sel.p[0].p2; | |
446 cmdexec(f, cp->ccmd); | |
447 compile(cp->re); | |
448 } | |
449 --nest; | |
450 } | |
451 | |
452 void | |
453 linelooper(File *f, Cmd *cp) | |
454 { | |
455 Posn p; | |
456 Range r, linesel; | |
457 Address a, a3; | |
458 | |
459 nest++; | |
460 r = addr.r; | |
461 a3.f = f; | |
462 a3.r.p1 = a3.r.p2 = r.p1; | |
463 for(p = r.p1; p<r.p2; p = a3.r.p2){ | |
464 a3.r.p1 = a3.r.p2; | |
465 /*pjw if(p!=r.p1 || (linesel = lineaddr((Posn)0, a3, 1)).… | |
466 if(p!=r.p1 || (a = lineaddr((Posn)0, a3, 1), linesel = a… | |
467 a = lineaddr((Posn)1, a3, 1); | |
468 linesel = a.r; | |
469 } | |
470 if(linesel.p1 >= r.p2) | |
471 break; | |
472 if(linesel.p2 >= r.p2) | |
473 linesel.p2 = r.p2; | |
474 if(linesel.p2 > linesel.p1) | |
475 if(linesel.p1>=a3.r.p2 && linesel.p2>a3.r.p2){ | |
476 f->dot.r = linesel; | |
477 cmdexec(f, cp->ccmd); | |
478 a3.r = linesel; | |
479 continue; | |
480 } | |
481 break; | |
482 } | |
483 --nest; | |
484 } | |
485 | |
486 void | |
487 filelooper(Cmd *cp, int XY) | |
488 { | |
489 File *f, *cur; | |
490 int i; | |
491 | |
492 if(Glooping++) | |
493 error(EnestXY); | |
494 nest++; | |
495 settempfile(); | |
496 cur = curfile; | |
497 for(i = 0; i<tempfile.nused; i++){ | |
498 f = tempfile.filepptr[i]; | |
499 if(f==cmd) | |
500 continue; | |
501 if(cp->re==0 || filematch(f, cp->re)==XY) | |
502 cmdexec(f, cp->ccmd); | |
503 } | |
504 if(cur && whichmenu(cur)>=0) /* check that cur is still a… | |
505 current(cur); | |
506 --Glooping; | |
507 --nest; | |
508 } |