Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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->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->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->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->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->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);
160
	bufinsert(menu, 0, genstr.s, genstr.n);
161
	compile(r);
162
	return execute(menu, 0, menu->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->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->nc)
207
					error(Erange);
208
				if(filereadc(f, p++) == '\n')
209
					n++;
210
			}
211
			a.r.p1 = p;
212
		}
213
		while(p < f->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
}