]> mj.ucw.cz Git - libucw.git/blob - lib/regex.c
31a13845d500d16d03d38579ee635cab28d65d3f
[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 };
20
21 regex *
22 rx_compile(byte *p)
23 {
24   regex *r = xmalloc(sizeof(regex));
25   const char *msg;
26
27   bzero(r, sizeof(*r));
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   free(r->buf.buffer);
40   free(r);
41 }
42
43 int
44 rx_match(regex *r, byte *s)
45 {
46   uns len = strlen(s);
47
48   if (re_match(&r->buf, s, len, 0, &r->regs) < 0)
49     return 0;
50   if (r->regs.start[0] || r->regs.end[0] != len) /* XXX: Why regex doesn't enforce implicit "^...$" ? */
51     return 0;
52   return 1;
53 }
54
55 int
56 rx_subst(regex *r, byte *by, byte *src, byte *dest, uns destlen)
57 {
58   byte *end = dest + destlen - 1;
59
60   if (!rx_match(r, src))
61     return 0;
62
63   while (*by)
64     {
65       if (*by == '\\')
66         {
67           by++;
68           if (*by >= '0' && *by <= '9') /* \0 gets replaced by entire pattern */
69             {
70               int j = *by++ - '0';
71               byte *s = src + r->regs.start[j];
72               int i = r->regs.end[j] - r->regs.start[j];
73               if (dest + i >= end)
74                 return -1;
75               memcpy(dest, s, i);
76               dest += i;
77               continue;
78             }
79         }
80       if (dest < end)
81         *dest++ = *by++;
82       else
83         return -1;
84     }
85   *dest = 0;
86   return 1;
87 }
88
89 #ifdef TEST
90
91 void main(int argc, char **argv)
92 {
93   regex *r;
94   byte buf1[256], buf2[256];
95
96   r = rx_compile(argv[1]);
97   while (fgets(buf1, sizeof(buf1), stdin))
98     {
99       char *p = strchr(buf1, '\n');
100       if (p)
101         *p = 0;
102       if (argc == 2)
103         {
104           if (rx_match(r, buf1))
105             puts("MATCH");
106           else
107             puts("NO MATCH");
108         }
109       else
110         {
111           int i = rx_subst(r, argv[2], buf1, buf2, sizeof(buf2));
112           if (i < 0)
113             puts("OVERFLOW");
114           else if (!i)
115             puts("NO MATCH");
116           else
117             puts(buf2);
118         }
119     }
120   rx_free(r);
121 }
122
123 #endif