|
|
1.1 root 1: #include "sam.h"
2: /*
3: * GROWDATASIZE must be big enough that all errors go out as Hgrowdata's,
4: * so they will be scrolled into visibility in the ~~sam~~ window (yuck!).
5: */
6: #define GROWDATASIZE 50 /* if size is < this, send data with grow */
7:
8: toterminal(f, toterm)
9: register File *f;
10: {
11: register Buffer *t=f->transcript;
12: register Posn n, p0, p1, p2, nbytes, delta=0, deltacmd=0;
13: Range r;
14: uchar buf[16+GROWDATASIZE];
15: if(f->rasp==0)
16: return;
17: nbytes=f->nbytes;
18: if(f->marked)
19: p0=f->markp+sizeof(Mark);
20: else
21: p0=0;
22: while(Bread(t, buf, sizeof buf, p0)>0){
23: switch(buf[0]){
24: default:
25: panic("unknown in toterminal");
26: case 'd':
27: GETPOSN(p1, buf+1);
28: GETPOSN(p2, buf+1+sizeof(Posn));
29: p1+=delta, p2+=delta;
30: if(p2<=p1)
31: panic("toterminal delete 0");
32: if(f==cmd && p1<cmdpt){
33: if(p2<=cmdpt)
34: deltacmd-=(p2-p1);
35: else
36: deltacmd-=cmdpt-p1;
37: }
38: p0+=1+2*sizeof(Posn);
39: if(toterm)
40: outTsll(Hcut, f->tag, p1, p2-p1);
41: rcut(f->rasp, p1, p2);
42: delta-=p2-p1;
43: nbytes-=p2-p1;
44: break;
45: case 'f':
46: n=buf[1]&0xFF;
47: n|=buf[2]<<8;
48: p0+=1+SS+n;
49: break;
50: case 'i':
51: n=buf[1]&0xFF;
52: n|=buf[2]<<8;
53: if(n<=0)
54: panic("toterminal insert 0");
55: GETPOSN(p1, (buf+1+SS));
56: p1+=delta;
57: p0+=1+SS+sizeof(Posn)+n;
58: if(f==cmd && p1<cmdpt)
59: deltacmd+=n;
60: if(toterm){
61: if(n>GROWDATASIZE || !rterm(f->rasp, p1)){
62: rgrow(f->rasp, p1, n);
63: outTsll(Hgrow, f->tag, p1, n);
64: }else{
65: uchar *s=buf+1+SS+sizeof(Posn);
66: rgrow(f->rasp, p1, n);
67: r=rdata(f->rasp, p1, n);
68: if(r.p1!=p1 || r.p2!=p1+n)
69: panic("rdata in toterminal");
70: s[n]=0;
71: outTsllS(Hgrowdata, f->tag, p1, n, s);
72: }
73: }else{
74: rgrow(f->rasp, p1, n);
75: r=rdata(f->rasp, p1, n);
76: if(r.p1!=p1 || r.p2!=p1+n)
77: panic("rdata in toterminal");
78: }
79: delta+=n;
80: nbytes+=n;
81: break;
82: }
83: }
84: if(toterm)
85: outTs(Hcheck0, f->tag);
86: if(f==cmd){
87: cmdpt+=deltacmd+cmdptadv;
88: cmdptadv=0;
89: }
90: }
91: #define M 0x80000000L
92: #define P(i) r->ptr[i]
93: #define T(i) (P(i)&M) /* in terminal */
94: #define L(i) (P(i)&~M) /* length of this piece */
95: rcut(r, p1, p2)
96: register List *r;
97: register Posn p1, p2;
98: {
99: register Posn p, x;
100: register i;
101: if(p1==p2)
102: panic("rcut 0");
103: for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
104: ;
105: if(i==r->nused)
106: panic("rcut 1");
107: if(p<p1){ /* chop this piece */
108: if(p+L(i)<p2){
109: x=p1-p;
110: p+=L(i);
111: }else{
112: x=L(i)-(p2-p1);
113: p=p2;
114: }
115: if(T(i))
116: P(i)=x|M;
117: else
118: P(i)=x;
119: i++;
120: }
121: while(i<r->nused && p+L(i)<=p2){
122: p+=L(i);
123: dellist(r, i);
124: }
125: if(p<p2){
126: if(i==r->nused)
127: panic("rcut 2");
128: x=L(i)-(p2-p);
129: if(T(i))
130: P(i)=x|M;
131: else
132: P(i)=x;
133: }
134: /* can we merge i and i-1 ? */
135: if(i>0 && i<r->nused && T(i-1)==T(i)){
136: x=L(i-1)+L(i);
137: dellist(r, i--);
138: if(T(i))
139: P(i)=x|M;
140: else
141: P(i)=x;
142: }
143: }
144: rgrow(r, p1, n)
145: register List *r;
146: register Posn p1, n;
147: {
148: register Posn p;
149: register i;
150: if(n==0)
151: panic("rgrow 0");
152: for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
153: ;
154: if(i==r->nused){ /* stick on end of file */
155: if(p!=p1)
156: panic("rgrow 1");
157: if(i>0 && !T(i-1))
158: P(i-1)+=n;
159: else
160: inslist(r, i, n);
161: }else if(!T(i)) /* goes in this empty piece */
162: P(i)+=n;
163: else if(p==p1 && i>0 && !T(i-1)) /* special case; simplifies life */
164: P(i-1)+=n;
165: else if(p==p1)
166: inslist(r, i, n);
167: else{ /* must break piece in terminal */
168: inslist(r, i+1, (L(i)-(p1-p))|M);
169: inslist(r, i+1, n);
170: P(i)=(p1-p)|M;
171: }
172: }
173: rterm(r, p1)
174: register List *r;
175: register Posn p1;
176: {
177: register Posn p;
178: register i;
179: for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
180: ;
181: if(i==r->nused && (i==0 || !T(i-1)))
182: return 0;
183: return T(i);
184: }
185: Range
186: rdata(r, p1, n)
187: register List *r;
188: register Posn p1, n;
189: {
190: register Posn p;
191: register i;
192: Range rg;
193: if(n==0)
194: panic("rdata 0");
195: for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
196: ;
197: if(i==r->nused)
198: panic("rdata 1");
199: if(T(i)){
200: n-=L(i)-(p1-p);
201: if(n<=0){
202: rg.p1=rg.p2=p1;
203: return rg;
204: }
205: p+=L(i++);
206: p1=p;
207: }
208: if(T(i) || i==r->nused)
209: panic("rdata 2");
210: if(p+L(i)<p1+n)
211: n=L(i)-(p1-p);
212: rg.p1=p1;
213: rg.p2=p1+n;
214: if(p!=p1){
215: inslist(r, i+1, L(i)-(p1-p));
216: P(i)=p1-p;
217: i++;
218: }
219: if(L(i)!=n){
220: inslist(r, i+1, L(i)-n);
221: P(i)=n;
222: }
223: P(i)|=M;
224: /* now i is set; can we merge? */
225: if(i<r->nused-1 && T(i+1)){
226: P(i)=(n+=L(i+1))|M;
227: dellist(r, i+1);
228: }
229: if(i>0 && T(i-1)){
230: P(i)=(n+L(i-1))|M;
231: dellist(r, i-1);
232: }
233: return rg;
234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.