trstr.c - neatvi - [fork] simple vi-type editor with UTF-8 support
(HTM) git clone git://src.adamsgaard.dk/neatvi
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
trstr.c (2419B)
---
1 #include <ctype.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include "vi.h"
6
7 struct rstr {
8 struct rset *rs; /* only for regex patterns */
9 char *str; /* for simple, non-regex patterns */
10 int icase; /* ignore case */
11 int lbeg, lend; /* match line beg/end */
12 int wbeg, wend; /* match word beg/end */
13 };
14
15 /* return zero if a simple pattern is given */
16 static int rstr_simple(struct rstr *rs, char *re)
17 {
18 char *beg;
19 char *end;
20 rs->lbeg = re[0] == '^';
21 if (rs->lbeg)
22 re++;
23 rs->wbeg = re[0] == '\\' && re[1] == '<';
24 if (rs->wbeg)
25 re += 2;
26 beg = re;
27 while (re[0] && !strchr("\\.*+?[]{}()$", (unsigned char) re[0]))
28 re++;
29 end = re;
30 rs->wend = re[0] == '\\' && re[1] == '>';
31 if (rs->wend)
32 re += 2;
33 rs->lend = re[0] == '$';
34 if (rs->lend)
35 re++;
36 if (!re[0]) {
37 int len = end - beg;
38 rs->str = malloc(len + 1);
39 memcpy(rs->str, beg, len);
40 rs->str[len] = '\0';
41 return 0;
42 }
43 return 1;
44 }
45
46 struct rstr *rstr_make(char *re, int flg)
47 {
48 struct rstr *rs = malloc(sizeof(*rs));
49 memset(rs, 0, sizeof(*rs));
50 rs->icase = flg & RE_ICASE;
51 if (rstr_simple(rs, re))
52 rs->rs = rset_make(1, &re, flg);
53 if (!rs->rs && !rs->str) {
54 free(rs);
55 return NULL;
56 }
57 return rs;
58 }
59
60 static int isword(char *s)
61 {
62 int c = (unsigned char) s[0];
63 return isalnum(c) || c == '_' || c > 127;
64 }
65
66 static int match_case(char *s, char *r, int icase)
67 {
68 for (; *r && *s; s++, r++) {
69 if (!icase && *s != *r)
70 return 1;
71 if (icase && tolower((unsigned char) *s) != tolower((unsigned char) *r))
72 return 1;
73 }
74 return *r;
75 }
76
77 /* return zero if an occurrence is found */
78 int rstr_find(struct rstr *rs, char *s, int n, int *grps, int flg)
79 {
80 int len;
81 char *beg, *end;
82 char *r;
83 if (rs->rs)
84 return rset_find(rs->rs, s, n, grps, flg);
85 if ((rs->lbeg && (flg & RE_NOTBOL)) || (rs->lend && (flg & RE_NOTEOL)))
86 return -1;
87 len = strlen(rs->str);
88 beg = s;
89 end = s + strlen(s) - len - 1;
90 if (end < beg)
91 return -1;
92 if (rs->lend)
93 beg = end;
94 if (rs->lbeg)
95 end = s;
96 for (r = beg; r <= end; r++) {
97 if (rs->wbeg && r > s && (isword(r - 1) || !isword(r)))
98 continue;
99 if (rs->wend && r[len] && (!isword(r + len - 1) || isword(r + len)))
100 continue;
101 if (!match_case(r, rs->str, rs->icase)) {
102 if (n >= 1) {
103 grps[0] = r - s;
104 grps[1] = r - s + len;
105 }
106 return 0;
107 }
108 }
109 return -1;
110 }
111
112 void rstr_free(struct rstr *rs)
113 {
114 if (rs->rs)
115 rset_free(rs->rs);
116 free(rs->str);
117 free(rs);
118 }