source: trunk/src/oldsed/sed/regexp.c

Last change on this file was 599, checked in by bird, 19 years ago

GNU sed 4.1.5.

File size: 6.3 KB
Line 
1/* GNU SED, a batch stream editor.
2 Copyright (C) 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include "sed.h"
19
20#include <ctype.h>
21#include <stdio.h>
22#ifdef HAVE_STDLIB_H
23# include <stdlib.h>
24#endif
25
26#ifdef gettext_noop
27# define N_(String) gettext_noop(String)
28#else
29# define N_(String) (String)
30#endif
31
32extern bool use_extended_syntax_p;
33
34static const char errors[] =
35 "no previous regular expression\0"
36 "cannot specify modifiers on empty regexp";
37
38#define NO_REGEX (errors)
39#define BAD_MODIF (NO_REGEX + sizeof(N_("no previous regular expression")))
40#define END_ERRORS (BAD_MODIF + sizeof(N_("cannot specify modifiers on empty regexp")))
41
42
43
44
45static void
46compile_regex_1 (new_regex, needed_sub)
47 struct regex *new_regex;
48 int needed_sub;
49{
50#ifdef REG_PERL
51 int errcode;
52 errcode = regncomp(&new_regex->pattern, new_regex->re, new_regex->sz,
53 (needed_sub ? 0 : REG_NOSUB)
54 | new_regex->flags
55 | extended_regexp_flags);
56
57 if (errcode)
58 {
59 char errorbuf[200];
60 regerror(errcode, NULL, errorbuf, 200);
61 bad_prog(gettext(errorbuf));
62 }
63#else
64 const char *error;
65 int syntax = ((extended_regexp_flags & REG_EXTENDED)
66 ? RE_SYNTAX_POSIX_EXTENDED
67 : RE_SYNTAX_POSIX_BASIC)
68 & ~RE_UNMATCHED_RIGHT_PAREN_ORD;
69
70 syntax |= RE_NO_POSIX_BACKTRACKING;
71#ifdef RE_ICASE
72 syntax |= (new_regex->flags & REG_ICASE) ? RE_ICASE : 0;
73#endif
74#ifdef RE_NO_SUB
75 syntax |= needed_sub ? 0 : RE_NO_SUB;
76#endif
77
78 new_regex->pattern.fastmap = malloc (1 << (sizeof (char) * 8));
79
80 /* If REG_NEWLINE is set, newlines are treated differently. */
81 if (new_regex->flags & REG_NEWLINE)
82 {
83 /* REG_NEWLINE implies neither . nor [^...] match newline. */
84 syntax &= ~RE_DOT_NEWLINE;
85 syntax |= RE_HAT_LISTS_NOT_NEWLINE;
86 }
87
88 re_set_syntax (syntax);
89 error = re_compile_pattern (new_regex->re, new_regex->sz,
90 &new_regex->pattern);
91 new_regex->pattern.newline_anchor = (new_regex->flags & REG_NEWLINE) != 0;
92
93 new_regex->pattern.translate = NULL;
94#ifndef RE_ICASE
95 if (new_regex->flags & REG_ICASE)
96 {
97 static char translate[1 << (sizeof(char) * 8)];
98 int i;
99 for (i = 0; i < sizeof(translate) / sizeof(char); i++)
100 translate[i] = tolower (i);
101
102 new_regex->pattern.translate = translate;
103 }
104#endif
105
106 if (error)
107 bad_prog(error);
108#endif
109
110 /* Just to be sure, I mark this as not POSIXLY_CORRECT behavior */
111 if (needed_sub
112 && new_regex->pattern.re_nsub < needed_sub - 1
113 && posixicity == POSIXLY_EXTENDED)
114 {
115 char buf[200];
116 sprintf(buf, _("invalid reference \\%d on `s' command's RHS"),
117 needed_sub - 1);
118 bad_prog(buf);
119 }
120}
121
122struct regex *
123compile_regex(b, flags, needed_sub)
124 struct buffer *b;
125 int flags;
126 int needed_sub;
127{
128 struct regex *new_regex;
129 size_t re_len;
130
131 /* // matches the last RE */
132 if (size_buffer(b) == 0)
133 {
134 if (flags > 0)
135 bad_prog(_(BAD_MODIF));
136 return NULL;
137 }
138
139 re_len = size_buffer(b);
140 new_regex = ck_malloc(sizeof (struct regex) + re_len - 1);
141 new_regex->flags = flags;
142 memcpy (new_regex->re, get_buffer(b), re_len);
143
144#ifdef REG_PERL
145 new_regex->sz = re_len;
146#else
147 /* GNU regex does not process \t & co. */
148 new_regex->sz = normalize_text(new_regex->re, re_len, TEXT_REGEX);
149#endif
150
151 compile_regex_1 (new_regex, needed_sub);
152 return new_regex;
153}
154
155#ifdef REG_PERL
156static void
157copy_regs (regs, pmatch, nregs)
158 struct re_registers *regs;
159 regmatch_t *pmatch;
160 int nregs;
161{
162 int i;
163 int need_regs = nregs + 1;
164 /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
165 uses. */
166
167 /* Have the register data arrays been allocated? */
168 if (!regs->start)
169 { /* No. So allocate them with malloc. */
170 regs->start = MALLOC (need_regs, regoff_t);
171 regs->end = MALLOC (need_regs, regoff_t);
172 regs->num_regs = need_regs;
173 }
174 else if (need_regs > regs->num_regs)
175 { /* Yes. We also need more elements than were already
176 allocated, so reallocate them. */
177 regs->start = REALLOC (regs->start, need_regs, regoff_t);
178 regs->end = REALLOC (regs->end, need_regs, regoff_t);
179 regs->num_regs = need_regs;
180 }
181
182 /* Copy the regs. */
183 for (i = 0; i < nregs; ++i)
184 {
185 regs->start[i] = pmatch[i].rm_so;
186 regs->end[i] = pmatch[i].rm_eo;
187 }
188 for ( ; i < regs->num_regs; ++i)
189 regs->start[i] = regs->end[i] = -1;
190}
191#endif
192
193int
194match_regex(regex, buf, buflen, buf_start_offset, regarray, regsize)
195 struct regex *regex;
196 char *buf;
197 size_t buflen;
198 size_t buf_start_offset;
199 struct re_registers *regarray;
200 int regsize;
201{
202 int ret;
203 static struct regex *regex_last;
204#ifdef REG_PERL
205 regmatch_t rm[10], *regmatch = rm;
206 if (regsize > 10)
207 regmatch = (regmatch_t *) alloca (sizeof (regmatch_t) * regsize);
208#endif
209
210 /* printf ("Matching from %d/%d\n", buf_start_offset, buflen); */
211
212 /* Keep track of the last regexp matched. */
213 if (!regex)
214 {
215 regex = regex_last;
216 if (!regex_last)
217 bad_prog(_(NO_REGEX));
218 }
219 else
220 regex_last = regex;
221
222#ifdef REG_PERL
223 regmatch[0].rm_so = CAST(int)buf_start_offset;
224 regmatch[0].rm_eo = CAST(int)buflen;
225 ret = regexec (&regex->pattern, buf, regsize, regmatch, REG_STARTEND);
226
227 if (regsize)
228 copy_regs (regarray, regmatch, regsize);
229
230 return (ret == 0);
231#else
232 if (regex->pattern.no_sub && regsize)
233 compile_regex_1 (regex, regsize);
234
235 regex->pattern.regs_allocated = REGS_REALLOCATE;
236
237 ret = re_search (&regex->pattern, buf, buflen, buf_start_offset,
238 buflen - buf_start_offset,
239 regsize ? regarray : NULL);
240
241 return (ret > -1);
242#endif
243}
244
245
246#ifdef DEBUG_LEAKS
247void
248release_regex(regex)
249 struct regex *regex;
250{
251 regfree(&regex->pattern);
252 FREE(regex);
253}
254#endif /*DEBUG_LEAKS*/
Note: See TracBrowser for help on using the repository browser.