]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/sam/xec.c
webfs(4): document -d and -D flags
[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         moveto(f, f->dot.r);
281         return TRUE;
282 }
283
284 int
285 w_cmd(File *f, Cmd *cp)
286 {
287         int fseq;
288
289         fseq = f->seq;
290         if(getname(f, cp->ctext, FALSE)==0)
291                 error(Enoname);
292         if(fseq == seq)
293                 error_s(Ewseq, genc);
294         writef(f);
295         return TRUE;
296 }
297
298 int
299 x_cmd(File *f, Cmd *cp)
300 {
301         if(cp->re)
302                 looper(f, cp, cp->cmdc=='x');
303         else
304                 linelooper(f, cp);
305         return TRUE;
306 }
307
308 int
309 X_cmd(File *f, Cmd *cp)
310 {
311         USED(f);
312         filelooper(cp, cp->cmdc=='X');
313         return TRUE;
314 }
315
316 int
317 plan9_cmd(File *f, Cmd *cp)
318 {
319         plan9(f, cp->cmdc, cp->ctext, nest);
320         return TRUE;
321 }
322
323 int
324 eq_cmd(File *f, Cmd *cp)
325 {
326         int charsonly;
327
328         switch(cp->ctext->n){
329         case 1:
330                 charsonly = FALSE;
331                 break;
332         case 2:
333                 if(cp->ctext->s[0]=='#'){
334                         charsonly = TRUE;
335                         break;
336                 }
337         default:
338                 SET(charsonly);
339                 error(Enewline);
340         }
341         printposn(f, charsonly);
342         return TRUE;
343 }
344
345 int
346 nl_cmd(File *f, Cmd *cp)
347 {
348         Address a;
349
350         if(cp->addr == 0){
351                 /* First put it on newline boundaries */
352                 addr = lineaddr((Posn)0, f->dot, -1);
353                 a = lineaddr((Posn)0, f->dot, 1);
354                 addr.r.p2 = a.r.p2;
355                 if(addr.r.p1==f->dot.r.p1 && addr.r.p2==f->dot.r.p2)
356                         addr = lineaddr((Posn)1, f->dot, 1);
357                 display(f);
358         }else if(downloaded)
359                 moveto(f, addr.r);
360         else
361                 display(f);
362         return TRUE;
363 }
364
365 int
366 cd_cmd(File *f, Cmd *cp)
367 {
368         USED(f);
369         cd(cp->ctext);
370         return TRUE;
371 }
372
373 int
374 append(File *f, Cmd *cp, Posn p)
375 {
376         if(cp->ctext->n>0 && cp->ctext->s[cp->ctext->n-1]==0)
377                 --cp->ctext->n;
378         if(cp->ctext->n>0)
379                 loginsert(f, p, cp->ctext->s, cp->ctext->n);
380         f->ndot.r.p1 = p;
381         f->ndot.r.p2 = p+cp->ctext->n;
382         return TRUE;
383 }
384
385 int
386 display(File *f)
387 {
388         Posn p1, p2;
389         int np;
390         char *c;
391
392         p1 = addr.r.p1;
393         p2 = addr.r.p2;
394         if(p2 > f->nc){
395                 fprint(2, "bad display addr p1=%ld p2=%ld f->nc=%d\n", p1, p2, f->nc); /*ZZZ should never happen, can remove */
396                 p2 = f->nc;
397         }
398         while(p1 < p2){
399                 np = p2-p1;
400                 if(np>BLOCKSIZE-1)
401                         np = BLOCKSIZE-1;
402                 bufread(f, p1, genbuf, np);
403                 genbuf[np] = 0;
404                 c = Strtoc(tmprstr(genbuf, np+1));
405                 if(downloaded)
406                         termwrite(c);
407                 else
408                         Write(1, c, strlen(c));
409                 free(c);
410                 p1 += np;
411         }
412         f->dot = addr;
413         return TRUE;
414 }
415
416 void
417 looper(File *f, Cmd *cp, int xy)
418 {
419         Posn p, op;
420         Range r;
421
422         r = addr.r;
423         op= xy? -1 : r.p1;
424         nest++;
425         compile(cp->re);
426         for(p = r.p1; p<=r.p2; ){
427                 if(!execute(f, p, r.p2)){ /* no match, but y should still run */
428                         if(xy || op>r.p2)
429                                 break;
430                         f->dot.r.p1 = op, f->dot.r.p2 = r.p2;
431                         p = r.p2+1;     /* exit next loop */
432                 }else{
433                         if(sel.p[0].p1==sel.p[0].p2){   /* empty match? */
434                                 if(sel.p[0].p1==op){
435                                         p++;
436                                         continue;
437                                 }
438                                 p = sel.p[0].p2+1;
439                         }else
440                                 p = sel.p[0].p2;
441                         if(xy)
442                                 f->dot.r = sel.p[0];
443                         else
444                                 f->dot.r.p1 = op, f->dot.r.p2 = sel.p[0].p1;
445                 }
446                 op = sel.p[0].p2;
447                 cmdexec(f, cp->ccmd);
448                 compile(cp->re);
449         }
450         --nest;
451 }
452
453 void
454 linelooper(File *f, Cmd *cp)
455 {
456         Posn p;
457         Range r, linesel;
458         Address a, a3;
459
460         nest++;
461         r = addr.r;
462         a3.f = f;
463         a3.r.p1 = a3.r.p2 = r.p1;
464         for(p = r.p1; p<r.p2; p = a3.r.p2){
465                 a3.r.p1 = a3.r.p2;
466 /*pjw           if(p!=r.p1 || (linesel = lineaddr((Posn)0, a3, 1)).r.p2==p)*/
467                 if(p!=r.p1 || (a = lineaddr((Posn)0, a3, 1), linesel = a.r, linesel.p2==p)){
468                         a = lineaddr((Posn)1, a3, 1);
469                         linesel = a.r;
470                 }
471                 if(linesel.p1 >= r.p2)
472                         break;
473                 if(linesel.p2 >= r.p2)
474                         linesel.p2 = r.p2;
475                 if(linesel.p2 > linesel.p1)
476                         if(linesel.p1>=a3.r.p2 && linesel.p2>a3.r.p2){
477                                 f->dot.r = linesel;
478                                 cmdexec(f, cp->ccmd);
479                                 a3.r = linesel;
480                                 continue;
481                         }
482                 break;
483         }
484         --nest;
485 }
486
487 void
488 filelooper(Cmd *cp, int XY)
489 {
490         File *f, *cur;
491         int i;
492
493         if(Glooping++)
494                 error(EnestXY);
495         nest++;
496         settempfile();
497         cur = curfile;
498         for(i = 0; i<tempfile.nused; i++){
499                 f = tempfile.filepptr[i];
500                 if(f==cmd)
501                         continue;
502                 if(cp->re==0 || filematch(f, cp->re)==XY)
503                         cmdexec(f, cp->ccmd);
504         }
505         if(cur && whichmenu(cur)>=0)    /* check that cur is still a file */
506                 current(cur);
507         --Glooping;
508         --nest;
509 }