]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/acme/addr.c
rio, kbdfs: increase read buffer for high latency kbdfs support
[plan9front.git] / sys / src / cmd / acme / addr.c
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                                 nc = (*getc)(a, q++);
219                                 if(nc<'0' || '9'<nc){
220                                         q--;
221                                         break;
222                                 }
223                                 n = n*10+(nc-'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 }