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