diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/acme/addr.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/acme/addr.c')
-rwxr-xr-x | sys/src/cmd/acme/addr.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/sys/src/cmd/acme/addr.c b/sys/src/cmd/acme/addr.c new file mode 100755 index 000000000..29c9c1cfc --- /dev/null +++ b/sys/src/cmd/acme/addr.c @@ -0,0 +1,270 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <thread.h> +#include <cursor.h> +#include <mouse.h> +#include <keyboard.h> +#include <frame.h> +#include <fcall.h> +#include <plumb.h> +#include "dat.h" +#include "fns.h" + +enum +{ + None = 0, + Fore = '+', + Back = '-', +}; + +enum +{ + Char, + Line, +}; + +int +isaddrc(int r) +{ + if(r && utfrune("0123456789+-/$.#,;", r)!=nil) + return TRUE; + return FALSE; +} + +/* + * quite hard: could be almost anything but white space, but we are a little conservative, + * aiming for regular expressions of alphanumerics and no white space + */ +int +isregexc(int r) +{ + if(r == 0) + return FALSE; + if(isalnum(r)) + return TRUE; + if(utfrune("^+-.*?#,;[]()$", r)!=nil) + return TRUE; + return FALSE; +} + +Range +number(Mntdir *md, Text *t, Range r, int line, int dir, int size, int *evalp) +{ + uint q0, q1; + + if(size == Char){ + if(dir == Fore) + line = r.q1+line; + else if(dir == Back){ + if(r.q0==0 && line>0) + r.q0 = t->file->nc; + line = r.q0 - line; + } + if(line<0 || line>t->file->nc) + goto Rescue; + *evalp = TRUE; + return (Range){line, line}; + } + q0 = r.q0; + q1 = r.q1; + switch(dir){ + case None: + q0 = 0; + q1 = 0; + Forward: + while(line>0 && q1<t->file->nc) + if(textreadc(t, q1++) == '\n' || q1==t->file->nc) + if(--line > 0) + q0 = q1; + if(line > 0) + goto Rescue; + break; + case Fore: + if(q1 > 0) + while(q1<t->file->nc && textreadc(t, q1-1) != '\n') + q1++; + q0 = q1; + goto Forward; + case Back: + if(q0 < t->file->nc) + while(q0>0 && textreadc(t, q0-1)!='\n') + q0--; + q1 = q0; + while(line>0 && q0>0){ + if(textreadc(t, q0-1) == '\n'){ + if(--line >= 0) + q1 = q0; + } + --q0; + } + /* :1-1 is :0 = #0, but :1-2 is an error */ + if(line > 1) + goto Rescue; + while(q0>0 && textreadc(t, q0-1)!='\n') + --q0; + } + *evalp = TRUE; + return (Range){q0, q1}; + + Rescue: + if(md != nil) + warning(nil, "address out of range\n"); + *evalp = FALSE; + return r; +} + + +Range +regexp(Mntdir *md, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp) +{ + int found; + Rangeset sel; + int q; + + if(pat[0] == '\0' && rxnull()){ + warning(md, "no previous regular expression\n"); + *foundp = FALSE; + return r; + } + if(pat[0] && rxcompile(pat) == FALSE){ + *foundp = FALSE; + return r; + } + if(dir == Back) + found = rxbexecute(t, r.q0, &sel); + else{ + if(lim.q0 < 0) + q = Infinity; + else + q = lim.q1; + found = rxexecute(t, nil, r.q1, q, &sel); + } + if(!found && md==nil) + warning(nil, "no match for regexp\n"); + *foundp = found; + return sel.r[0]; +} + +Range +address(Mntdir *md, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, int (*getc)(void*, uint), int *evalp, uint *qp) +{ + int dir, size, npat; + int prevc, c, nc, n; + uint q; + Rune *pat; + Range r, nr; + + r = ar; + q = q0; + dir = None; + size = Line; + c = 0; + while(q < q1){ + prevc = c; + c = (*getc)(a, q++); + switch(c){ + default: + *qp = q-1; + return r; + case ';': + ar = r; + /* fall through */ + case ',': + if(prevc == 0) /* lhs defaults to 0 */ + r.q0 = 0; + if(q>=q1 && t!=nil && t->file!=nil) /* rhs defaults to $ */ + r.q1 = t->file->nc; + else{ + nr = address(md, t, lim, ar, a, q, q1, getc, evalp, &q); + r.q1 = nr.q1; + } + *qp = q; + return r; + case '+': + case '-': + if(*evalp && (prevc=='+' || prevc=='-')) + if((nc=(*getc)(a, q))!='#' && nc!='/' && nc!='?') + r = number(md, t, r, 1, prevc, Line, evalp); /* do previous one */ + dir = c; + break; + case '.': + case '$': + if(q != q0+1){ + *qp = q-1; + return r; + } + if(*evalp) + if(c == '.') + r = ar; + else + r = (Range){t->file->nc, t->file->nc}; + if(q < q1) + dir = Fore; + else + dir = None; + break; + case '#': + if(q==q1 || (c=(*getc)(a, q++))<'0' || '9'<c){ + *qp = q-1; + return r; + } + size = Char; + /* fall through */ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = c -'0'; + while(q<q1){ + c = (*getc)(a, q++); + if(c<'0' || '9'<c){ + q--; + break; + } + n = n*10+(c-'0'); + } + if(*evalp) + r = number(md, t, r, n, dir, size, evalp); + dir = None; + size = Line; + break; + case '?': + dir = Back; + /* fall through */ + case '/': + npat = 0; + pat = nil; + while(q<q1){ + c = (*getc)(a, q++); + switch(c){ + case '\n': + --q; + goto out; + case '\\': + pat = runerealloc(pat, npat+1); + pat[npat++] = c; + if(q == q1) + goto out; + c = (*getc)(a, q++); + break; + case '/': + goto out; + } + pat = runerealloc(pat, npat+1); + pat[npat++] = c; + } + out: + pat = runerealloc(pat, npat+1); + pat[npat] = 0; + if(*evalp) + r = regexp(md, t, lim, r, pat, dir, evalp); + free(pat); + dir = None; + size = Line; + break; + } + } + if(*evalp && dir != None) + r = number(md, t, r, 1, dir, Line, evalp); /* do previous one */ + *qp = q; + return r; +} |