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 <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <thread.h>
5
#include <cursor.h>
6
#include <mouse.h>
7
#include <keyboard.h>
8
#include <frame.h>
9
#include <fcall.h>
10
#include <plumb.h>
11
#include "dat.h"
12
#include "fns.h"
13
 
14
enum
15
{
16
	None = 0,
17
	Fore = '+',
18
	Back = '-',
19
};
20
 
21
enum
22
{
23
	Char,
24
	Line,
25
};
26
 
27
int
28
isaddrc(int r)
29
{
30
	if(r && utfrune("0123456789+-/$.#,;", r)!=nil)
31
		return TRUE;
32
	return FALSE;
33
}
34
 
35
/*
36
 * quite hard: could be almost anything but white space, but we are a little conservative,
37
 * aiming for regular expressions of alphanumerics and no white space
38
 */
39
int
40
isregexc(int r)
41
{
42
	if(r == 0)
43
		return FALSE;
44
	if(isalnum(r))
45
		return TRUE;
46
	if(utfrune("^+-.*?#,;[]()$", r)!=nil)
47
		return TRUE;
48
	return FALSE;
49
}
50
 
51
Range
52
number(Mntdir *md, Text *t, Range r, int line, int dir, int size, int *evalp)
53
{
54
	uint q0, q1;
55
 
56
	if(size == Char){
57
		if(dir == Fore)
58
			line = r.q1+line;
59
		else if(dir == Back){
60
			if(r.q0==0 && line>0)
61
				r.q0 = t->file->nc;
62
			line = r.q0 - line;
63
		}
64
		if(line<0 || line>t->file->nc)
65
			goto Rescue;
66
		*evalp = TRUE;
67
		return (Range){line, line};
68
	}
69
	q0 = r.q0;
70
	q1 = r.q1;
71
	switch(dir){
72
	case None:
73
		q0 = 0;
74
		q1 = 0;
75
	Forward:
76
		while(line>0 && q1<t->file->nc)
77
			if(textreadc(t, q1++) == '\n' || q1==t->file->nc)
78
				if(--line > 0)
79
					q0 = q1;
80
		if(line > 0)
81
			goto Rescue;
82
		break;
83
	case Fore:
84
		if(q1 > 0)
85
			while(q1<t->file->nc && textreadc(t, q1-1) != '\n')
86
				q1++;
87
		q0 = q1;
88
		goto Forward;
89
	case Back:
90
		if(q0 < t->file->nc)
91
			while(q0>0 && textreadc(t, q0-1)!='\n')
92
				q0--;
93
		q1 = q0;
94
		while(line>0 && q0>0){
95
			if(textreadc(t, q0-1) == '\n'){
96
				if(--line >= 0)
97
					q1 = q0;
98
			}
99
			--q0;
100
		}
101
		/* :1-1 is :0 = #0, but :1-2 is an error */
102
		if(line > 1)
103
			goto Rescue;
104
		while(q0>0 && textreadc(t, q0-1)!='\n')
105
			--q0;
106
	}
107
	*evalp = TRUE;
108
	return (Range){q0, q1};
109
 
110
    Rescue:
111
	if(md != nil)
112
		warning(nil, "address out of range\n");
113
	*evalp = FALSE;
114
	return r;
115
}
116
 
117
 
118
Range
119
regexp(Mntdir *md, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp)
120
{
121
	int found;
122
	Rangeset sel;
123
	int q;
124
 
125
	if(pat[0] == '\0' && rxnull()){
126
		warning(md, "no previous regular expression\n");
127
		*foundp = FALSE;
128
		return r;
129
	}
130
	if(pat[0] && rxcompile(pat) == FALSE){
131
		*foundp = FALSE;
132
		return r;
133
	}
134
	if(dir == Back)
135
		found = rxbexecute(t, r.q0, &sel);
136
	else{
137
		if(lim.q0 < 0)
138
			q = Infinity;
139
		else
140
			q = lim.q1;
141
		found = rxexecute(t, nil, r.q1, q, &sel);
142
	}
143
	if(!found && md==nil)
144
		warning(nil, "no match for regexp\n");
145
	*foundp = found;
146
	return sel.r[0];
147
}
148
 
149
Range
150
address(Mntdir *md, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, int (*getc)(void*, uint),  int *evalp, uint *qp)
151
{
152
	int dir, size, npat;
153
	int prevc, c, nc, n;
154
	uint q;
155
	Rune *pat;
156
	Range r, nr;
157
 
158
	r = ar;
159
	q = q0;
160
	dir = None;
161
	size = Line;
162
	c = 0;
163
	while(q < q1){
164
		prevc = c;
165
		c = (*getc)(a, q++);
166
		switch(c){
167
		default:
168
			*qp = q-1;
169
			return r;
170
		case ';':
171
			ar = r;
172
			/* fall through */
173
		case ',':
174
			if(prevc == 0)	/* lhs defaults to 0 */
175
				r.q0 = 0;
176
			if(q>=q1 && t!=nil && t->file!=nil)	/* rhs defaults to $ */
177
				r.q1 = t->file->nc;
178
			else{
179
				nr = address(md, t, lim, ar, a, q, q1, getc, evalp, &q);
180
				r.q1 = nr.q1;
181
			}
182
			*qp = q;
183
			return r;
184
		case '+':
185
		case '-':
186
			if(*evalp && (prevc=='+' || prevc=='-'))
187
				if((nc=(*getc)(a, q))!='#' && nc!='/' && nc!='?')
188
					r = number(md, t, r, 1, prevc, Line, evalp);	/* do previous one */
189
			dir = c;
190
			break;
191
		case '.':
192
		case '$':
193
			if(q != q0+1){
194
				*qp = q-1;
195
				return r;
196
			}
197
			if(*evalp)
198
				if(c == '.')
199
					r = ar;
200
				else
201
					r = (Range){t->file->nc, t->file->nc};
202
			if(q < q1)
203
				dir = Fore;
204
			else
205
				dir = None;
206
			break;
207
		case '#':
208
			if(q==q1 || (c=(*getc)(a, q++))<'0' || '9'<c){
209
				*qp = q-1;
210
				return r;
211
			}
212
			size = Char;
213
			/* fall through */
214
		case '0': case '1': case '2': case '3': case '4':
215
		case '5': case '6': case '7': case '8': case '9':
216
			n = c -'0';
217
			while(q<q1){
218
				c = (*getc)(a, q++);
219
				if(c<'0' || '9'<c){
220
					q--;
221
					break;
222
				}
223
				n = n*10+(c-'0');
224
			}
225
			if(*evalp)
226
				r = number(md, t, r, n, dir, size, evalp);
227
			dir = None;
228
			size = Line;
229
			break;
230
		case '?':
231
			dir = Back;
232
			/* fall through */
233
		case '/':
234
			npat = 0;
235
			pat = nil;
236
			while(q<q1){
237
				c = (*getc)(a, q++);
238
				switch(c){
239
				case '\n':
240
					--q;
241
					goto out;
242
				case '\\':
243
					pat = runerealloc(pat, npat+1);
244
					pat[npat++] = c;
245
					if(q == q1)
246
						goto out;
247
					c = (*getc)(a, q++);
248
					break;
249
				case '/':
250
					goto out;
251
				}
252
				pat = runerealloc(pat, npat+1);
253
				pat[npat++] = c;
254
			}
255
		    out:
256
			pat = runerealloc(pat, npat+1);
257
			pat[npat] = 0;
258
			if(*evalp)
259
				r = regexp(md, t, lim, r, pat, dir, evalp);
260
			free(pat);
261
			dir = None;
262
			size = Line;
263
			break;
264
		}
265
	}
266
	if(*evalp && dir != None)
267
		r = number(md, t, r, 1, dir, Line, evalp);	/* do previous one */
268
	*qp = q;
269
	return r;
270
}