rset: rename from reset
[neatvi.git] / rset.c
blob7e3660901e8b8807e2221c39f74b88271cb6666b
1 #include <regex.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include "vi.h"
7 /* regular expression set */
8 struct rset {
9 regex_t regex; /* the combined regular expression */
10 int n; /* number of regular expressions in this set */
11 int *grp; /* the group assigned to each subgroup */
12 int *setgrpcnt; /* number of groups in each regular expression */
13 int grpcnt; /* group count */
16 static int re_groupcount(char *s)
18 int n = 0;
19 while (*s) {
20 if (s[0] == '(')
21 n++;
22 if (s[0] == '\\' && s[1])
23 s++;
24 s++;
26 return n;
29 struct rset *rset_make(int n, char **re)
31 struct rset *rs = malloc(sizeof(*rs));
32 struct sbuf *sb = sbuf_make();
33 int i;
34 memset(rs, 0, sizeof(*rs));
35 rs->grp = malloc((n + 1) * sizeof(rs->grp[0]));
36 rs->setgrpcnt = malloc((n + 1) * sizeof(rs->setgrpcnt[0]));
37 rs->grpcnt = 2;
38 rs->n = n;
39 sbuf_chr(sb, '(');
40 for (i = 0; i < n; i++) {
41 if (!re[i]) {
42 rs->grp[i] = -1;
43 rs->setgrpcnt[i] = 0;
44 continue;
46 if (sbuf_len(sb) > 1)
47 sbuf_chr(sb, '|');
48 sbuf_chr(sb, '(');
49 sbuf_str(sb, re[i]);
50 sbuf_chr(sb, ')');
51 rs->grp[i] = rs->grpcnt;
52 rs->setgrpcnt[i] = re_groupcount(re[i]);
53 rs->grpcnt += 1 + rs->setgrpcnt[i];
55 rs->grp[n] = rs->grpcnt;
56 sbuf_chr(sb, ')');
57 if (regcomp(&rs->regex, sbuf_buf(sb), REG_EXTENDED)) {
58 free(rs->grp);
59 free(rs->setgrpcnt);
60 free(rs);
61 sbuf_free(sb);
62 return NULL;
64 sbuf_free(sb);
65 return rs;
68 /* return the index of the matching regular expression or -1 if none matches */
69 int rset_find(struct rset *rs, char *s, int n, int *grps, int flg)
71 regmatch_t *subs;
72 int found, i, set = -1;
73 if (rs->grpcnt <= 2)
74 return -1;
75 subs = malloc(rs->grpcnt * sizeof(subs[0]));
76 found = !regexec(&rs->regex, s, rs->grpcnt, subs, 0);
77 for (i = 0; found && i < rs->n; i++)
78 if (rs->grp[i] >= 0 && subs[rs->grp[i]].rm_so >= 0)
79 set = i;
80 if (found && set >= 0) {
81 for (i = 0; i < n; i++) {
82 int grp = rs->grp[set] + i;
83 if (i < rs->setgrpcnt[set] + 1) {
84 grps[i * 2] = subs[grp].rm_so;
85 grps[i * 2 + 1] = subs[grp].rm_eo;
86 } else {
87 grps[i * 2 + 0] = -1;
88 grps[i * 2 + 1] = -1;
92 free(subs);
93 return set;
96 void rset_free(struct rset *rs)
98 regfree(&rs->regex);
99 free(rs->setgrpcnt);
100 free(rs->grp);
101 free(rs);