Blob
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"14 enum15 {16 None = 0,17 Fore = '+',18 Back = '-',19 };21 enum22 {23 Char,24 Line,25 };27 int28 isaddrc(int r)29 {30 if(r && utfrune("0123456789+-/$.#,;", r)!=nil)31 return TRUE;32 return FALSE;33 }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 space38 */39 int40 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 }51 Range52 number(uint showerr, Text *t, Range r, int line, int dir, int size, int *evalp)53 {54 uint q0, q1;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;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->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)85 while(q1<t->file->b.nc && textreadc(t, q1-1) != '\n')86 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 }101 if(line > 0)102 goto Rescue;103 while(q0>0 && textreadc(t, q0-1)!='\n')104 --q0;105 }106 *evalp = TRUE;107 return range(q0, q1);109 Rescue:110 if(showerr)111 warning(nil, "address out of range\n");112 *evalp = FALSE;113 return r;114 }117 Range118 regexp(uint showerr, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp)119 {120 int found;121 Rangeset sel;122 int q;124 if(pat[0] == '\0' && rxnull()){125 if(showerr)126 warning(nil, "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 else140 q = lim.q1;141 warning(nil, "searching %d-%d\n", r.q1, q);142 found = rxexecute(t, nil, r.q1, q, &sel);143 }144 if(!found && showerr)145 warning(nil, "no match for regexp\n");146 *foundp = found;147 return sel.r[0];148 }150 Range151 address(uint showerr, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, int (*getc)(void*, uint), int *evalp, uint *qp)152 {153 int dir, size, npat;154 int prevc, c, nc, n;155 uint q;156 Rune *pat;157 Range r, nr;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{180 nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q);181 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!='?')189 r = number(showerr, t, r, 1, prevc, Line, evalp); /* do previous one */190 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 else202 r = range(t->file->b.nc, t->file->b.nc);203 if(q < q1)204 dir = Fore;205 else206 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)227 r = number(showerr, t, r, n, dir, size, evalp);228 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)260 r = regexp(showerr, t, lim, r, pat, dir, evalp);261 free(pat);262 dir = None;263 size = Line;264 break;265 }266 }267 if(*evalp && dir != None)268 r = number(showerr, t, r, 1, dir, Line, evalp); /* do previous one */269 *qp = q;270 return r;271 }