URI:
       taddr.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       taddr.c (5500B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <draw.h>
            4 #include <thread.h>
            5 #include <cursor.h>
            6 #include <mouse.h>
            7 #include <keyboard.h>
            8 #include <frame.h>
            9 #include <fcall.h>
           10 #include <plumb.h>
           11 #include <libsec.h>
           12 #include "dat.h"
           13 #include "fns.h"
           14 
           15 enum
           16 {
           17         None = 0,
           18         Fore = '+',
           19         Back = '-'
           20 };
           21 
           22 enum
           23 {
           24         Char,
           25         Line
           26 };
           27 
           28 int
           29 isaddrc(int r)
           30 {
           31         if(r && utfrune("0123456789+-/$.#,;?", r)!=nil)
           32                 return TRUE;
           33         return FALSE;
           34 }
           35 
           36 /*
           37  * quite hard: could be almost anything but white space, but we are a little conservative,
           38  * aiming for regular expressions of alphanumerics and no white space
           39  */
           40 int
           41 isregexc(int r)
           42 {
           43         if(r == 0)
           44                 return FALSE;
           45         if(isalnum(r))
           46                 return TRUE;
           47         if(utfrune("^+-.*?#,;[]()$", r)!=nil)
           48                 return TRUE;
           49         return FALSE;
           50 }
           51 
           52 // nlcounttopos starts at q0 and advances nl lines,
           53 // being careful not to walk past the end of the text,
           54 // and then nr chars, being careful not to walk past
           55 // the end of the current line.
           56 // It returns the final position.
           57 long
           58 nlcounttopos(Text *t, long q0, long nl, long nr)
           59 {
           60         while(nl > 0 && q0 < t->file->b.nc) {
           61                 if(textreadc(t, q0++) == '\n')
           62                         nl--;
           63         }
           64         if(nl > 0)
           65                 return q0;
           66         while(nr > 0 && q0 < t->file->b.nc && textreadc(t, q0) != '\n') {
           67                 q0++;
           68                 nr--;
           69         }
           70         return q0;
           71 }
           72 
           73 Range
           74 number(uint showerr, Text *t, Range r, int line, int dir, int size, int *evalp)
           75 {
           76         uint q0, q1;
           77 
           78         if(size == Char){
           79                 if(dir == Fore)
           80                         line = r.q1+line;
           81                 else if(dir == Back){
           82                         if(r.q0==0 && line>0)
           83                                 r.q0 = t->file->b.nc;
           84                         line = r.q0 - line;
           85                 }
           86                 if(line<0 || line>t->file->b.nc)
           87                         goto Rescue;
           88                 *evalp = TRUE;
           89                 return range(line, line);
           90         }
           91         q0 = r.q0;
           92         q1 = r.q1;
           93         switch(dir){
           94         case None:
           95                 q0 = 0;
           96                 q1 = 0;
           97         Forward:
           98                 while(line>0 && q1<t->file->b.nc)
           99                         if(textreadc(t, q1++) == '\n' || q1==t->file->b.nc)
          100                                 if(--line > 0)
          101                                         q0 = q1;
          102                 if(line==1 && q1==t->file->b.nc) // 6 goes to end of 5-line file
          103                         break;
          104                 if(line > 0)
          105                         goto Rescue;
          106                 break;
          107         case Fore:
          108                 if(q1 > 0)
          109                         while(q1<t->file->b.nc && textreadc(t, q1-1) != '\n')
          110                                 q1++;
          111                 q0 = q1;
          112                 goto Forward;
          113         case Back:
          114                 if(q0 < t->file->b.nc)
          115                         while(q0>0 && textreadc(t, q0-1)!='\n')
          116                                 q0--;
          117                 q1 = q0;
          118                 while(line>0 && q0>0){
          119                         if(textreadc(t, q0-1) == '\n'){
          120                                 if(--line >= 0)
          121                                         q1 = q0;
          122                         }
          123                         --q0;
          124                 }
          125                 /* :1-1 is :0 = #0, but :1-2 is an error */
          126                 if(line > 1)
          127                         goto Rescue;
          128                 while(q0>0 && textreadc(t, q0-1)!='\n')
          129                         --q0;
          130         }
          131         *evalp = TRUE;
          132         return range(q0, q1);
          133 
          134     Rescue:
          135         if(showerr)
          136                 warning(nil, "address out of range\n");
          137         *evalp = FALSE;
          138         return r;
          139 }
          140 
          141 
          142 Range
          143 regexp(uint showerr, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp)
          144 {
          145         int found;
          146         Rangeset sel;
          147         int q;
          148 
          149         if(pat[0] == '\0' && rxnull()){
          150                 if(showerr)
          151                         warning(nil, "no previous regular expression\n");
          152                 *foundp = FALSE;
          153                 return r;
          154         }
          155         if(pat[0] && rxcompile(pat) == FALSE){
          156                 *foundp = FALSE;
          157                 return r;
          158         }
          159         if(dir == Back)
          160                 found = rxbexecute(t, r.q0, &sel);
          161         else{
          162                 if(lim.q0 < 0)
          163                         q = Infinity;
          164                 else
          165                         q = lim.q1;
          166                 found = rxexecute(t, nil, r.q1, q, &sel);
          167         }
          168         if(!found && showerr)
          169                 warning(nil, "no match for regexp\n");
          170         *foundp = found;
          171         return sel.r[0];
          172 }
          173 
          174 Range
          175 address(uint showerr, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, int (*getc)(void*, uint),  int *evalp, uint *qp)
          176 {
          177         int dir, size, npat;
          178         int prevc, c, nc, n;
          179         uint q;
          180         Rune *pat;
          181         Range r, nr;
          182 
          183         r = ar;
          184         q = q0;
          185         dir = None;
          186         size = Line;
          187         c = 0;
          188         while(q < q1){
          189                 prevc = c;
          190                 c = (*getc)(a, q++);
          191                 switch(c){
          192                 default:
          193                         *qp = q-1;
          194                         return r;
          195                 case ';':
          196                         ar = r;
          197                         /* fall through */
          198                 case ',':
          199                         if(prevc == 0)        /* lhs defaults to 0 */
          200                                 r.q0 = 0;
          201                         if(q>=q1 && t!=nil && t->file!=nil)        /* rhs defaults to $ */
          202                                 r.q1 = t->file->b.nc;
          203                         else{
          204                                 nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q);
          205                                 r.q1 = nr.q1;
          206                         }
          207                         *qp = q;
          208                         return r;
          209                 case '+':
          210                 case '-':
          211                         if(*evalp && (prevc=='+' || prevc=='-'))
          212                                 if((nc=(*getc)(a, q))!='#' && nc!='/' && nc!='?')
          213                                         r = number(showerr, t, r, 1, prevc, Line, evalp);        /* do previous one */
          214                         dir = c;
          215                         break;
          216                 case '.':
          217                 case '$':
          218                         if(q != q0+1){
          219                                 *qp = q-1;
          220                                 return r;
          221                         }
          222                         if(*evalp)
          223                                 if(c == '.')
          224                                         r = ar;
          225                                 else
          226                                         r = range(t->file->b.nc, t->file->b.nc);
          227                         if(q < q1)
          228                                 dir = Fore;
          229                         else
          230                                 dir = None;
          231                         break;
          232                 case '#':
          233                         if(q==q1 || (c=(*getc)(a, q++))<'0' || '9'<c){
          234                                 *qp = q-1;
          235                                 return r;
          236                         }
          237                         size = Char;
          238                         /* fall through */
          239                 case '0': case '1': case '2': case '3': case '4':
          240                 case '5': case '6': case '7': case '8': case '9':
          241                         n = c -'0';
          242                         while(q<q1){
          243                                 nc = (*getc)(a, q++);
          244                                 if(nc<'0' || '9'<nc){
          245                                         q--;
          246                                         break;
          247                                 }
          248                                 n = n*10+(nc-'0');
          249                         }
          250                         if(*evalp)
          251                                 r = number(showerr, t, r, n, dir, size, evalp);
          252                         dir = None;
          253                         size = Line;
          254                         break;
          255                 case '?':
          256                         dir = Back;
          257                         /* fall through */
          258                 case '/':
          259                         npat = 0;
          260                         pat = nil;
          261                         while(q<q1){
          262                                 c = (*getc)(a, q++);
          263                                 switch(c){
          264                                 case '\n':
          265                                         --q;
          266                                         goto out;
          267                                 case '\\':
          268                                         pat = runerealloc(pat, npat+1);
          269                                         pat[npat++] = c;
          270                                         if(q == q1)
          271                                                 goto out;
          272                                         c = (*getc)(a, q++);
          273                                         break;
          274                                 case '/':
          275                                         goto out;
          276                                 }
          277                                 pat = runerealloc(pat, npat+1);
          278                                 pat[npat++] = c;
          279                         }
          280                     out:
          281                         pat = runerealloc(pat, npat+1);
          282                         pat[npat] = 0;
          283                         if(*evalp)
          284                                 r = regexp(showerr, t, lim, r, pat, dir, evalp);
          285                         free(pat);
          286                         dir = None;
          287                         size = Line;
          288                         break;
          289                 }
          290         }
          291         if(*evalp && dir != None)
          292                 r = number(showerr, t, r, 1, dir, Line, evalp);        /* do previous one */
          293         *qp = q;
          294         return r;
          295 }