]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/sam/xec.c
merge
[plan9front.git] / sys / src / cmd / sam / xec.c
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!='\n'){
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-1){
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>BLOCKSIZE)
233                                                 error(Elongtag);
234                                         bufread(f, sel.p[j].p1, genbuf, sel.p[j].p2-sel.p[j].p1);
235                                         Strinsert(&genstr, tmprstr(genbuf, (sel.p[j].p2-sel.p[j].p1)), genstr.n);
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, sel.p[0].p1, genbuf, sel.p[0].p2-sel.p[0].p1);
244                                 Strinsert(&genstr,
245                                         tmprstr(genbuf, (int)(sel.p[0].p2-sel.p[0].p1)),
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->nc){
394                 fprint(2, "bad display addr p1=%ld p2=%ld f->nc=%d\n", p1, p2, f->nc); /*ZZZ should never happen, can remove */
395                 p2 = f->nc;
396         }
397         while(p1 < p2){
398                 np = p2-p1;
399                 if(np>BLOCKSIZE-1)
400                         np = BLOCKSIZE-1;
401                 bufread(f, 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 still run */
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 match? */
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].p1;
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)).r.p2==p)*/
466                 if(p!=r.p1 || (a = lineaddr((Posn)0, a3, 1), linesel = a.r, linesel.p2==p)){
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 file */
505                 current(cur);
506         --Glooping;
507         --nest;
508 }