| address.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| address.c (4011B) | |
| --- | |
| 1 #include "sam.h" | |
| 2 #include "parse.h" | |
| 3 | |
| 4 Address addr; | |
| 5 String lastpat; | |
| 6 int patset; | |
| 7 File *menu; | |
| 8 | |
| 9 File *matchfile(String*); | |
| 10 Address charaddr(Posn, Address, int); | |
| 11 | |
| 12 Address | |
| 13 address(Addr *ap, Address a, int sign) | |
| 14 { | |
| 15 File *f = a.f; | |
| 16 Address a1, a2; | |
| 17 | |
| 18 do{ | |
| 19 switch(ap->type){ | |
| 20 case 'l': | |
| 21 case '#': | |
| 22 a = (*(ap->type=='#'?charaddr:lineaddr))(ap->num… | |
| 23 break; | |
| 24 | |
| 25 case '.': | |
| 26 a = f->dot; | |
| 27 break; | |
| 28 | |
| 29 case '$': | |
| 30 a.r.p1 = a.r.p2 = f->b.nc; | |
| 31 break; | |
| 32 | |
| 33 case '\'': | |
| 34 a.r = f->mark; | |
| 35 break; | |
| 36 | |
| 37 case '?': | |
| 38 sign = -sign; | |
| 39 if(sign == 0) | |
| 40 sign = -1; | |
| 41 /* fall through */ | |
| 42 case '/': | |
| 43 nextmatch(f, ap->are, sign>=0? a.r.p2 : a.r.p1, … | |
| 44 a.r = sel.p[0]; | |
| 45 break; | |
| 46 | |
| 47 case '"': | |
| 48 a = matchfile(ap->are)->dot; | |
| 49 f = a.f; | |
| 50 if(f->unread) | |
| 51 load(f); | |
| 52 break; | |
| 53 | |
| 54 case '*': | |
| 55 a.r.p1 = 0, a.r.p2 = f->b.nc; | |
| 56 return a; | |
| 57 | |
| 58 case ',': | |
| 59 case ';': | |
| 60 if(ap->left) | |
| 61 a1 = address(ap->left, a, 0); | |
| 62 else | |
| 63 a1.f = a.f, a1.r.p1 = a1.r.p2 = 0; | |
| 64 if(ap->type == ';'){ | |
| 65 f = a1.f; | |
| 66 a = a1; | |
| 67 f->dot = a1; | |
| 68 } | |
| 69 if(ap->next) | |
| 70 a2 = address(ap->next, a, 0); | |
| 71 else | |
| 72 a2.f = a.f, a2.r.p1 = a2.r.p2 = f->b.nc; | |
| 73 if(a1.f != a2.f) | |
| 74 error(Eorder); | |
| 75 a.f = a1.f, a.r.p1 = a1.r.p1, a.r.p2 = a2.r.p2; | |
| 76 if(a.r.p2 < a.r.p1) | |
| 77 error(Eorder); | |
| 78 return a; | |
| 79 | |
| 80 case '+': | |
| 81 case '-': | |
| 82 sign = 1; | |
| 83 if(ap->type == '-') | |
| 84 sign = -1; | |
| 85 if(ap->next==0 || ap->next->type=='+' || ap->nex… | |
| 86 a = lineaddr(1L, a, sign); | |
| 87 break; | |
| 88 default: | |
| 89 panic("address"); | |
| 90 return a; | |
| 91 } | |
| 92 }while(ap = ap->next); /* assign = */ | |
| 93 return a; | |
| 94 } | |
| 95 | |
| 96 void | |
| 97 nextmatch(File *f, String *r, Posn p, int sign) | |
| 98 { | |
| 99 compile(r); | |
| 100 if(sign >= 0){ | |
| 101 if(!execute(f, p, INFINITY)) | |
| 102 error(Esearch); | |
| 103 if(sel.p[0].p1==sel.p[0].p2 && sel.p[0].p1==p){ | |
| 104 if(++p>f->b.nc) | |
| 105 p = 0; | |
| 106 if(!execute(f, p, INFINITY)) | |
| 107 panic("address"); | |
| 108 } | |
| 109 }else{ | |
| 110 if(!bexecute(f, p)) | |
| 111 error(Esearch); | |
| 112 if(sel.p[0].p1==sel.p[0].p2 && sel.p[0].p2==p){ | |
| 113 if(--p<0) | |
| 114 p = f->b.nc; | |
| 115 if(!bexecute(f, p)) | |
| 116 panic("address"); | |
| 117 } | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 File * | |
| 122 matchfile(String *r) | |
| 123 { | |
| 124 File *f; | |
| 125 File *match = 0; | |
| 126 int i; | |
| 127 | |
| 128 for(i = 0; i<file.nused; i++){ | |
| 129 f = file.filepptr[i]; | |
| 130 if(f == cmd) | |
| 131 continue; | |
| 132 if(filematch(f, r)){ | |
| 133 if(match) | |
| 134 error(Emanyfiles); | |
| 135 match = f; | |
| 136 } | |
| 137 } | |
| 138 if(!match) | |
| 139 error(Efsearch); | |
| 140 return match; | |
| 141 } | |
| 142 | |
| 143 int | |
| 144 filematch(File *f, String *r) | |
| 145 { | |
| 146 char *c, buf[STRSIZE+100]; | |
| 147 String *t; | |
| 148 | |
| 149 c = Strtoc(&f->name); | |
| 150 sprint(buf, "%c%c%c %s\n", " '"[f->mod], | |
| 151 "-+"[f->rasp!=0], " ."[f==curfile], c); | |
| 152 free(c); | |
| 153 t = tmpcstr(buf); | |
| 154 Strduplstr(&genstr, t); | |
| 155 freetmpstr(t); | |
| 156 /* A little dirty... */ | |
| 157 if(menu == 0) | |
| 158 menu = fileopen(); | |
| 159 bufreset(&menu->b); | |
| 160 bufinsert(&menu->b, 0, genstr.s, genstr.n); | |
| 161 compile(r); | |
| 162 return execute(menu, 0, menu->b.nc); | |
| 163 } | |
| 164 | |
| 165 Address | |
| 166 charaddr(Posn l, Address addr, int sign) | |
| 167 { | |
| 168 if(sign == 0) | |
| 169 addr.r.p1 = addr.r.p2 = l; | |
| 170 else if(sign < 0) | |
| 171 addr.r.p2 = addr.r.p1-=l; | |
| 172 else if(sign > 0) | |
| 173 addr.r.p1 = addr.r.p2+=l; | |
| 174 if(addr.r.p1<0 || addr.r.p2>addr.f->b.nc) | |
| 175 error(Erange); | |
| 176 return addr; | |
| 177 } | |
| 178 | |
| 179 Address | |
| 180 lineaddr(Posn l, Address addr, int sign) | |
| 181 { | |
| 182 int n; | |
| 183 int c; | |
| 184 File *f = addr.f; | |
| 185 Address a; | |
| 186 Posn p; | |
| 187 | |
| 188 a.f = f; | |
| 189 if(sign >= 0){ | |
| 190 if(l == 0){ | |
| 191 if(sign==0 || addr.r.p2==0){ | |
| 192 a.r.p1 = a.r.p2 = 0; | |
| 193 return a; | |
| 194 } | |
| 195 a.r.p1 = addr.r.p2; | |
| 196 p = addr.r.p2-1; | |
| 197 }else{ | |
| 198 if(sign==0 || addr.r.p2==0){ | |
| 199 p = (Posn)0; | |
| 200 n = 1; | |
| 201 }else{ | |
| 202 p = addr.r.p2-1; | |
| 203 n = filereadc(f, p++)=='\n'; | |
| 204 } | |
| 205 while(n < l){ | |
| 206 if(p >= f->b.nc) | |
| 207 error(Erange); | |
| 208 if(filereadc(f, p++) == '\n') | |
| 209 n++; | |
| 210 } | |
| 211 a.r.p1 = p; | |
| 212 } | |
| 213 while(p < f->b.nc && filereadc(f, p++)!='\n') | |
| 214 ; | |
| 215 a.r.p2 = p; | |
| 216 }else{ | |
| 217 p = addr.r.p1; | |
| 218 if(l == 0) | |
| 219 a.r.p2 = addr.r.p1; | |
| 220 else{ | |
| 221 for(n = 0; n<l; ){ /* always runs once */ | |
| 222 if(p == 0){ | |
| 223 if(++n != l) | |
| 224 error(Erange); | |
| 225 }else{ | |
| 226 c = filereadc(f, p-1); | |
| 227 if(c != '\n' || ++n != l) | |
| 228 p--; | |
| 229 } | |
| 230 } | |
| 231 a.r.p2 = p; | |
| 232 if(p > 0) | |
| 233 p--; | |
| 234 } | |
| 235 while(p > 0 && filereadc(f, p-1)!='\n') /* lines … | |
| 236 p--; | |
| 237 a.r.p1 = p; | |
| 238 } | |
| 239 return a; | |
| 240 } |