addr.c 4.7 KB

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