|
|
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.