addr.c 5.2 KB

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