|
|
1.1 ! root 1: #include "sam.h" ! 2: #include "parse.h" ! 3: ! 4: Address addr; ! 5: Address charaddr(); ! 6: String lastpat; ! 7: int patset; ! 8: File *matchfile(); ! 9: File *menu; ! 10: ! 11: Address ! 12: address(ap, a, sign) ! 13: register Addr *ap; ! 14: Address a; ! 15: { ! 16: register File *f=a.f; ! 17: Address a1, a2; ! 18: do{ ! 19: switch(ap->type){ ! 20: case 'l': ! 21: case '#': ! 22: a=(*(ap->type=='#'?charaddr:lineaddr))((Posn)ap->num, a, sign); ! 23: break; ! 24: case '.': ! 25: a=f->dot; ! 26: break; ! 27: case '$': ! 28: a.r.p1=a.r.p2=f->nbytes; ! 29: break; ! 30: case '\'': ! 31: a.r=f->mark; ! 32: break; ! 33: case '?': ! 34: sign= -sign; ! 35: if(sign==0) ! 36: sign= -1; ! 37: /* fall through */ ! 38: case '/': ! 39: nextmatch(f, ap->are, sign>=0? a.r.p2 : a.r.p1, sign); ! 40: a.r=sel; ! 41: break; ! 42: case '"': ! 43: a=matchfile(ap->are)->dot; ! 44: f=a.f; ! 45: if(f->state==Unread) ! 46: load(f); ! 47: break; ! 48: case '*': ! 49: a.r.p1=0, a.r.p2=f->nbytes; ! 50: return a; ! 51: case ',': ! 52: case ';': ! 53: if(ap->aprev) ! 54: a1=address(ap->aprev, a, 0); ! 55: else ! 56: a1.f=a.f, a1.r.p1=a1.r.p2=0; ! 57: if(ap->type==';') ! 58: f->dot=a=a1; ! 59: if(ap->next) ! 60: a2=address(ap->next, a, 0); ! 61: else ! 62: a2.f=a.f, a2.r.p1=a2.r.p2=f->nbytes; ! 63: if(a1.f!=a2.f) ! 64: error(Eorder); ! 65: a.f=a1.f, a.r.p1=a1.r.p1, a.r.p2=a2.r.p2; ! 66: if(a.r.p2<a.r.p1) ! 67: error(Eorder); ! 68: return a; ! 69: case '+': ! 70: case '-': ! 71: sign=1; ! 72: if(ap->type=='-') ! 73: sign= -1; ! 74: if(ap->next==0 || ap->next->type=='+' || ap->next->type=='-') ! 75: a=lineaddr(1L, a, sign); ! 76: break; ! 77: default: ! 78: panic("address"); ! 79: return a; ! 80: } ! 81: }while(ap=ap->next); ! 82: return a; ! 83: } ! 84: nextmatch(f, r, p, sign) ! 85: register File *f; ! 86: register Regexp *r; ! 87: register Posn p; ! 88: { ! 89: compile(r); ! 90: if(sign>=0){ ! 91: if(!execute(f, p, INFINITY)) ! 92: error(Esearch); ! 93: if(sel.p1==sel.p2 && sel.p1==p){ ! 94: if(++p>f->nbytes) ! 95: p=0; ! 96: if(!execute(f, p, INFINITY)) ! 97: panic("address"); ! 98: } ! 99: }else{ ! 100: if(!bexecute(f, p)) ! 101: error(Esearch); ! 102: if(sel.p1==sel.p2 && sel.p2==p){ ! 103: if(--p<0) ! 104: p=f->nbytes; ! 105: if(!bexecute(f, p)) ! 106: panic("address"); ! 107: } ! 108: } ! 109: } ! 110: File * ! 111: matchfile(r) ! 112: Regexp *r; ! 113: { ! 114: register File *f; ! 115: register File *match=0; ! 116: register i; ! 117: for(i=0; i<file.nused; i++){ ! 118: f=file.ptr[i]; ! 119: if(f==cmd) ! 120: continue; ! 121: if(filematch(f, r)){ ! 122: if(match) ! 123: error(Emanyfiles); ! 124: match=f; ! 125: } ! 126: } ! 127: if(!match) ! 128: error(Efsearch); ! 129: return match; ! 130: } ! 131: filematch(f, r) ! 132: register File *f; ! 133: register Regexp *r; ! 134: { ! 135: sprint(genbuf, "%c%c%c %s\n", " '"[f->state==Dirty], ! 136: "-+"[f->rasp!=0], " ."[f==curfile], f->name.s); ! 137: strdup(&genstr, genbuf); ! 138: /* A little dirty... */ ! 139: if(menu==0) ! 140: (menu=Fopen())->state=Clean; ! 141: Bdelete(menu->buf, (Posn)0, menu->buf->nbytes); ! 142: Binsert(menu->buf, &genstr, (Posn)0); ! 143: menu->nbytes=menu->buf->nbytes; ! 144: compile(r); ! 145: return execute(menu, (Posn)0, menu->nbytes); ! 146: } ! 147: Address ! 148: charaddr(l, addr, sign) ! 149: register Posn l; ! 150: Address addr; ! 151: { ! 152: if(sign==0) ! 153: addr.r.p1=addr.r.p2=l; ! 154: else if(sign<0) ! 155: addr.r.p2=addr.r.p1-=l; ! 156: else if(sign>0) ! 157: addr.r.p1=addr.r.p2+=l; ! 158: if(addr.r.p1<0 || addr.r.p2>addr.f->nbytes) ! 159: error(Erange); ! 160: return addr; ! 161: } ! 162: Address ! 163: lineaddr(l, addr, sign) ! 164: register Posn l; ! 165: Address addr; ! 166: { ! 167: register n; ! 168: register c; ! 169: register File *f=addr.f; ! 170: Address a; ! 171: a.f=f; ! 172: if(sign>=0){ ! 173: if(l==0){ ! 174: if(sign==0 || addr.r.p2==0){ ! 175: a.r.p1=a.r.p2=0; ! 176: return a; ! 177: } ! 178: a.r.p1=addr.r.p2; ! 179: Fgetcset(f, addr.r.p2-1); ! 180: }else{ ! 181: if(sign==0 || addr.r.p2==0){ ! 182: Fgetcset(f, (Posn)0); ! 183: n=1; ! 184: }else{ ! 185: Fgetcset(f, addr.r.p2-1); ! 186: n=Fgetc(f)=='\n'; ! 187: } ! 188: for(; n<l; ){ ! 189: c=Fgetc(f); ! 190: if(c==-1) ! 191: error(Erange); ! 192: else if(c=='\n') ! 193: n++; ! 194: } ! 195: a.r.p1=f->getcp; ! 196: } ! 197: do; while((c=Fgetc(f))!='\n' && c!=-1); ! 198: a.r.p2=f->getcp; ! 199: }else{ ! 200: Fbgetcset(f, addr.r.p1); ! 201: if(l==0) ! 202: a.r.p2=addr.r.p1; ! 203: else{ ! 204: for(n=0; n<l; ){ /* always runs once */ ! 205: c=Fbgetc(f); ! 206: if(c=='\n') ! 207: n++; ! 208: else if(c==-1){ ! 209: if(++n!=l) ! 210: error(Erange); ! 211: } ! 212: } ! 213: a.r.p2=f->getcp; ! 214: if(c=='\n') ! 215: a.r.p2++; /* lines start after a newline */ ! 216: } ! 217: do; while((c=Fbgetc(f))!='\n' && c!=-1); ! 218: a.r.p1=f->getcp; ! 219: if(c=='\n') ! 220: a.r.p1++; /* lines start after a newline */ ! 221: } ! 222: return a; ! 223: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.