Introduction
Introduction Statistics Contact Development Disclaimer Help
xec.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
xec.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 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.