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, a, sign); 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, sign); 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->next->type=='-') 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 start after a newline */ 236 p--; 237 a.r.p1 = p; 238 } 239 return a; 240 }