xec.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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!='\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->b, 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->b, 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->b.nc){
          394                 fprint(2, "bad display addr p1=%ld p2=%ld f->b.nc=%d\n", p1, p2, f->b.nc); /*ZZZ should never happen, can remove */
          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 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 }