]> mj.ucw.cz Git - libucw.git/blob - lib/regex.c
888f36b918bb4a422f234647ae891596674f936a
[libucw.git] / lib / regex.c
1 /*
2  *      Sherlock Library -- Regular Expressions
3  *
4  *      (c) 1997 Martin Mares, <mj@atrey.karlin.mff.cuni.cz>
5  */
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <regex.h>
11
12 #include "lib.h"
13
14 #define INITIAL_MEM 1024                /* Initial space allocated for each pattern */
15
16 struct regex {
17   struct re_pattern_buffer buf;
18   struct re_registers regs;             /* Must not change between re_match() calls */
19   int len_cache;
20 };
21
22 regex *
23 rx_compile(byte *p)
24 {
25   regex *r = xmalloc(sizeof(regex));
26   const char *msg;
27
28   bzero(r, sizeof(struct regex));
29   r->buf.buffer = xmalloc(INITIAL_MEM);
30   r->buf.allocated = INITIAL_MEM;
31   msg = re_compile_pattern(p, strlen(p), &r->buf);
32   if (!msg)
33     return r;
34   die("Error parsing pattern `%s': %s", p, msg);
35 }
36
37 void
38 rx_free(regex *r)
39 {
40   free(r->buf.buffer);
41   free(r);
42 }
43
44 int
45 rx_match(regex *r, byte *s)
46 {
47   int len = strlen(s);
48
49   r->len_cache = len;
50   if (re_match(&r->buf, s, len, 0, &r->regs) < 0)
51     return 0;
52   if (r->regs.start[0] || r->regs.end[0] != len) /* XXX: Why regex doesn't enforce implicit "^...$" ? */
53     return 0;
54   return 1;
55 }
56
57 int
58 rx_subst(regex *r, byte *by, byte *src, byte *dest, uns destlen)
59 {
60   byte *end = dest + destlen - 1;
61
62   if (!rx_match(r, src))
63     return 0;
64
65   while (*by)
66     {
67       if (*by == '\\')
68         {
69           by++;
70           if (*by >= '0' && *by <= '9') /* \0 gets replaced by entire pattern */
71             {
72               uns j = *by++ - '0';
73               if (j < r->regs.num_regs)
74                 {
75                   byte *s = src + r->regs.start[j];
76                   uns i = r->regs.end[j] - r->regs.start[j];
77                   if (r->regs.start[j] > r->len_cache || r->regs.end[j] > r->len_cache)
78                     return -1;
79                   if (dest + i >= end)
80                     return -1;
81                   memcpy(dest, s, i);
82                   dest += i;
83                   continue;
84                 }
85             }
86         }
87       if (dest < end)
88         *dest++ = *by++;
89       else
90         return -1;
91     }
92   *dest = 0;
93   return 1;
94 }
95
96 #ifdef TEST
97
98 void main(int argc, char **argv)
99 {
100   regex *r;
101   byte buf1[256], buf2[256];
102
103   r = rx_compile(argv[1]);
104   while (fgets(buf1, sizeof(buf1), stdin))
105     {
106       char *p = strchr(buf1, '\n');
107       if (p)
108         *p = 0;
109       if (argc == 2)
110         {
111           if (rx_match(r, buf1))
112             puts("MATCH");
113           else
114             puts("NO MATCH");
115         }
116       else
117         {
118           int i = rx_subst(r, argv[2], buf1, buf2, sizeof(buf2));
119           if (i < 0)
120             puts("OVERFLOW");
121           else if (!i)
122             puts("NO MATCH");
123           else
124             puts(buf2);
125         }
126     }
127   rx_free(r);
128 }
129
130 #endif