blob: a3c04991f1a59a6dea6b99d658a6c25d6323f51f [file] [log] [blame]
rscb3994ec2003-12-11 17:50:28 +00001#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
14enum
15{
16 None = 0,
17 Fore = '+',
rsccbeb0b22006-04-01 19:24:03 +000018 Back = '-'
rscb3994ec2003-12-11 17:50:28 +000019};
20
21enum
22{
23 Char,
rsccbeb0b22006-04-01 19:24:03 +000024 Line
rscb3994ec2003-12-11 17:50:28 +000025};
26
27int
28isaddrc(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 */
39int
40isregexc(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
51Range
rsc012a8a02004-10-22 17:11:30 +000052number(uint showerr, Text *t, Range r, int line, int dir, int size, int *evalp)
rscb3994ec2003-12-11 17:50:28 +000053{
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->b.nc;
62 line = r.q0 - line;
63 }
64 if(line<0 || line>t->file->b.nc)
65 goto Rescue;
66 *evalp = TRUE;
rscbe22ae22004-03-26 01:59:35 +000067 return range(line, line);
rscb3994ec2003-12-11 17:50:28 +000068 }
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->b.nc)
77 if(textreadc(t, q1++) == '\n' || q1==t->file->b.nc)
78 if(--line > 0)
79 q0 = q1;
80 if(line > 0)
81 goto Rescue;
82 break;
83 case Fore:
84 if(q1 > 0)
rsc012a8a02004-10-22 17:11:30 +000085 while(q1<t->file->b.nc && textreadc(t, q1-1) != '\n')
rscb3994ec2003-12-11 17:50:28 +000086 q1++;
87 q0 = q1;
88 goto Forward;
89 case Back:
90 if(q0 < t->file->b.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 }
rsca5841352007-03-26 13:26:22 +0000101 /* :1-1 is :0 = #0, but :1-2 is an error */
102 if(line > 1)
rscb3994ec2003-12-11 17:50:28 +0000103 goto Rescue;
104 while(q0>0 && textreadc(t, q0-1)!='\n')
105 --q0;
106 }
107 *evalp = TRUE;
rscbe22ae22004-03-26 01:59:35 +0000108 return range(q0, q1);
rscb3994ec2003-12-11 17:50:28 +0000109
110 Rescue:
rsc012a8a02004-10-22 17:11:30 +0000111 if(showerr)
rscb3994ec2003-12-11 17:50:28 +0000112 warning(nil, "address out of range\n");
113 *evalp = FALSE;
114 return r;
115}
116
117
118Range
rsc012a8a02004-10-22 17:11:30 +0000119regexp(uint showerr, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp)
rscb3994ec2003-12-11 17:50:28 +0000120{
121 int found;
122 Rangeset sel;
123 int q;
124
125 if(pat[0] == '\0' && rxnull()){
rsc012a8a02004-10-22 17:11:30 +0000126 if(showerr)
127 warning(nil, "no previous regular expression\n");
rscb3994ec2003-12-11 17:50:28 +0000128 *foundp = FALSE;
129 return r;
130 }
131 if(pat[0] && rxcompile(pat) == FALSE){
132 *foundp = FALSE;
133 return r;
134 }
135 if(dir == Back)
136 found = rxbexecute(t, r.q0, &sel);
137 else{
138 if(lim.q0 < 0)
139 q = Infinity;
140 else
141 q = lim.q1;
142 found = rxexecute(t, nil, r.q1, q, &sel);
143 }
rsc012a8a02004-10-22 17:11:30 +0000144 if(!found && showerr)
rscb3994ec2003-12-11 17:50:28 +0000145 warning(nil, "no match for regexp\n");
146 *foundp = found;
147 return sel.r[0];
148}
149
150Range
rsc012a8a02004-10-22 17:11:30 +0000151address(uint showerr, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, int (*getc)(void*, uint), int *evalp, uint *qp)
rscb3994ec2003-12-11 17:50:28 +0000152{
153 int dir, size, npat;
154 int prevc, c, nc, n;
155 uint q;
156 Rune *pat;
157 Range r, nr;
158
159 r = ar;
160 q = q0;
161 dir = None;
162 size = Line;
163 c = 0;
164 while(q < q1){
165 prevc = c;
166 c = (*getc)(a, q++);
167 switch(c){
168 default:
169 *qp = q-1;
170 return r;
171 case ';':
172 ar = r;
173 /* fall through */
174 case ',':
175 if(prevc == 0) /* lhs defaults to 0 */
176 r.q0 = 0;
177 if(q>=q1 && t!=nil && t->file!=nil) /* rhs defaults to $ */
178 r.q1 = t->file->b.nc;
179 else{
rsc012a8a02004-10-22 17:11:30 +0000180 nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q);
rscb3994ec2003-12-11 17:50:28 +0000181 r.q1 = nr.q1;
182 }
183 *qp = q;
184 return r;
185 case '+':
186 case '-':
187 if(*evalp && (prevc=='+' || prevc=='-'))
188 if((nc=(*getc)(a, q))!='#' && nc!='/' && nc!='?')
rsc012a8a02004-10-22 17:11:30 +0000189 r = number(showerr, t, r, 1, prevc, Line, evalp); /* do previous one */
rscb3994ec2003-12-11 17:50:28 +0000190 dir = c;
191 break;
192 case '.':
193 case '$':
194 if(q != q0+1){
195 *qp = q-1;
196 return r;
197 }
198 if(*evalp)
199 if(c == '.')
200 r = ar;
201 else
rscbe22ae22004-03-26 01:59:35 +0000202 r = range(t->file->b.nc, t->file->b.nc);
rscb3994ec2003-12-11 17:50:28 +0000203 if(q < q1)
204 dir = Fore;
205 else
206 dir = None;
207 break;
208 case '#':
209 if(q==q1 || (c=(*getc)(a, q++))<'0' || '9'<c){
210 *qp = q-1;
211 return r;
212 }
213 size = Char;
214 /* fall through */
215 case '0': case '1': case '2': case '3': case '4':
216 case '5': case '6': case '7': case '8': case '9':
217 n = c -'0';
218 while(q<q1){
219 c = (*getc)(a, q++);
220 if(c<'0' || '9'<c){
221 q--;
222 break;
223 }
224 n = n*10+(c-'0');
225 }
226 if(*evalp)
rsc012a8a02004-10-22 17:11:30 +0000227 r = number(showerr, t, r, n, dir, size, evalp);
rscb3994ec2003-12-11 17:50:28 +0000228 dir = None;
229 size = Line;
230 break;
231 case '?':
232 dir = Back;
233 /* fall through */
234 case '/':
235 npat = 0;
236 pat = nil;
237 while(q<q1){
238 c = (*getc)(a, q++);
239 switch(c){
240 case '\n':
241 --q;
242 goto out;
243 case '\\':
244 pat = runerealloc(pat, npat+1);
245 pat[npat++] = c;
246 if(q == q1)
247 goto out;
248 c = (*getc)(a, q++);
249 break;
250 case '/':
251 goto out;
252 }
253 pat = runerealloc(pat, npat+1);
254 pat[npat++] = c;
255 }
256 out:
257 pat = runerealloc(pat, npat+1);
258 pat[npat] = 0;
259 if(*evalp)
rsc012a8a02004-10-22 17:11:30 +0000260 r = regexp(showerr, t, lim, r, pat, dir, evalp);
rscb3994ec2003-12-11 17:50:28 +0000261 free(pat);
262 dir = None;
263 size = Line;
264 break;
265 }
266 }
267 if(*evalp && dir != None)
rsc012a8a02004-10-22 17:11:30 +0000268 r = number(showerr, t, r, 1, dir, Line, evalp); /* do previous one */
rscb3994ec2003-12-11 17:50:28 +0000269 *qp = q;
270 return r;
271}