40 |
#include "m4private.h" |
#include "m4private.h" |
41 |
#include "regex.h" |
#include "regex.h" |
42 |
|
|
43 |
|
#define RE_SYNTAX_BRE RE_SYNTAX_EMACS |
44 |
|
|
45 |
|
#define RE_SYNTAX_ERE \ |
46 |
|
(/* Allow char classes. */ \ |
47 |
|
RE_CHAR_CLASSES \ |
48 |
|
/* Be picky. */ \ |
49 |
|
| RE_CONTEXT_INVALID_OPS \ |
50 |
|
/* Allow intervals with `{' and `}', forbid invalid ranges. */\ |
51 |
|
| RE_INTERVALS | RE_NO_BK_BRACES | RE_NO_EMPTY_RANGES \ |
52 |
|
/* `(' and `)' are the grouping operators. */ \ |
53 |
|
| RE_NO_BK_PARENS \ |
54 |
|
/* `|' is the alternation. */ \ |
55 |
|
| RE_NO_BK_VBAR) |
56 |
|
|
57 |
#include "format.c" |
#include "format.c" |
58 |
|
|
59 |
|
|
261 |
_("Cannot set error file: %s"), M4ARG (1))); |
_("Cannot set error file: %s"), M4ARG (1))); |
262 |
} |
} |
263 |
|
|
264 |
|
|
265 |
|
/* Compile a REGEXP using the Regex SYNTAX bits return the buffer. |
266 |
|
Report errors on behalf of CALLER. */ |
267 |
|
|
268 |
|
static struct re_pattern_buffer * |
269 |
|
m4_regexp_compile (const char *caller, |
270 |
|
const char *regexp, int syntax) |
271 |
|
{ |
272 |
|
static struct re_pattern_buffer buf; /* compiled regular expression */ |
273 |
|
static boolean buf_initialized = FALSE; |
274 |
|
const char *msg; /* error message from re_compile_pattern */ |
275 |
|
|
276 |
|
if (!buf_initialized) |
277 |
|
{ |
278 |
|
buf_initialized = TRUE; |
279 |
|
buf.buffer = NULL; |
280 |
|
buf.allocated = 0; |
281 |
|
buf.fastmap = NULL; |
282 |
|
buf.translate = NULL; |
283 |
|
} |
284 |
|
|
285 |
|
re_set_syntax (syntax); |
286 |
|
msg = re_compile_pattern (regexp, strlen (regexp), &buf); |
287 |
|
|
288 |
|
if (msg != NULL) |
289 |
|
{ |
290 |
|
M4ERROR ((warning_status, 0, |
291 |
|
_("%0: bad regular expression `%s': %s"), |
292 |
|
caller, regexp, msg)); |
293 |
|
return NULL; |
294 |
|
} |
295 |
|
|
296 |
|
return &buf; |
297 |
|
} |
298 |
|
|
299 |
/* Regular expression version of index. Given two arguments, expand to the |
/* Regular expression version of index. Given two arguments, expand to the |
300 |
index of the first match of the second argument (a regexp) in the first. |
index of the first match of the second argument (a regexp) in the first. |
301 |
Expand to -1 if here is no match. Given a third argument, is changes |
Expand to -1 if here is no match. Given a third argument, is changes |
310 |
const char *regexp; /* regular expression */ |
const char *regexp; /* regular expression */ |
311 |
const char *repl; /* replacement string */ |
const char *repl; /* replacement string */ |
312 |
|
|
313 |
struct re_pattern_buffer buf; /* compiled regular expression */ |
struct re_pattern_buffer *buf;/* compiled regular expression */ |
314 |
struct re_registers regs; /* for subexpression matches */ |
struct re_registers regs; /* for subexpression matches */ |
|
const char *msg; /* error message from re_compile_pattern */ |
|
315 |
int startpos; /* start position of match */ |
int startpos; /* start position of match */ |
316 |
int length; /* length of first argument */ |
int length; /* length of first argument */ |
317 |
|
|
318 |
if (m4_bad_argc (argv[0], argc, 3, 4)) |
if (m4_bad_argc (argv[0], argc, 3, 4)) |
319 |
return; |
return; |
320 |
|
|
321 |
victim = M4_TOKEN_DATA_TEXT (argv[1]); |
victim = M4ARG (1); |
322 |
regexp = M4_TOKEN_DATA_TEXT (argv[2]); |
regexp = M4ARG (2); |
323 |
|
|
324 |
buf.buffer = NULL; |
buf = m4_regexp_compile (M4ARG(0), regexp, RE_SYNTAX_BRE); |
325 |
buf.allocated = 0; |
if (!buf) |
326 |
buf.fastmap = NULL; |
return; |
|
buf.translate = NULL; |
|
|
msg = re_compile_pattern (regexp, strlen (regexp), &buf); |
|
|
|
|
|
if (msg != NULL) |
|
|
{ |
|
|
M4ERROR ((warning_status, 0, |
|
|
_("Bad regular expression `%s': %s"), regexp, msg)); |
|
|
return; |
|
|
} |
|
327 |
|
|
328 |
length = strlen (victim); |
length = strlen (victim); |
329 |
startpos = re_search (&buf, victim, length, 0, length, ®s); |
startpos = re_search (buf, victim, length, 0, length, ®s); |
|
xfree (buf.buffer); |
|
330 |
|
|
331 |
if (startpos == -2) |
if (startpos == -2) |
332 |
{ |
{ |
339 |
m4_shipout_int (obs, startpos); |
m4_shipout_int (obs, startpos); |
340 |
else if (startpos >= 0) |
else if (startpos >= 0) |
341 |
{ |
{ |
342 |
repl = M4_TOKEN_DATA_TEXT (argv[3]); |
repl = M4ARG (3); |
343 |
substitute (obs, victim, repl, ®s); |
substitute (obs, victim, repl, ®s); |
344 |
} |
} |
345 |
|
|
359 |
const char *victim; /* first argument */ |
const char *victim; /* first argument */ |
360 |
const char *regexp; /* regular expression */ |
const char *regexp; /* regular expression */ |
361 |
|
|
362 |
struct re_pattern_buffer buf; /* compiled regular expression */ |
struct re_pattern_buffer *buf;/* compiled regular expression */ |
363 |
struct re_registers regs; /* for subexpression matches */ |
struct re_registers regs; /* for subexpression matches */ |
|
const char *msg; /* error message from re_compile_pattern */ |
|
364 |
int matchpos; /* start position of match */ |
int matchpos; /* start position of match */ |
365 |
int offset; /* current match offset */ |
int offset; /* current match offset */ |
366 |
int length; /* length of first argument */ |
int length; /* length of first argument */ |
368 |
if (m4_bad_argc (argv[0], argc, 3, 4)) |
if (m4_bad_argc (argv[0], argc, 3, 4)) |
369 |
return; |
return; |
370 |
|
|
371 |
regexp = M4_TOKEN_DATA_TEXT (argv[2]); |
regexp = M4ARG (2); |
372 |
|
victim = M4ARG (1); |
|
buf.buffer = NULL; |
|
|
buf.allocated = 0; |
|
|
buf.fastmap = NULL; |
|
|
buf.translate = NULL; |
|
|
msg = re_compile_pattern (regexp, strlen (regexp), &buf); |
|
|
|
|
|
if (msg != NULL) |
|
|
{ |
|
|
M4ERROR ((warning_status, 0, |
|
|
_("Bad regular expression `%s': %s"), regexp, msg)); |
|
|
if (buf.buffer != NULL) |
|
|
xfree (buf.buffer); |
|
|
return; |
|
|
} |
|
|
|
|
|
victim = M4_TOKEN_DATA_TEXT (argv[1]); |
|
373 |
length = strlen (victim); |
length = strlen (victim); |
374 |
|
|
375 |
|
buf = m4_regexp_compile (M4ARG(0), regexp, RE_SYNTAX_BRE); |
376 |
|
if (!buf) |
377 |
|
return; |
378 |
|
|
379 |
offset = 0; |
offset = 0; |
380 |
matchpos = 0; |
matchpos = 0; |
381 |
while (offset < length) |
while (offset < length) |
382 |
{ |
{ |
383 |
matchpos = re_search (&buf, victim, length, |
matchpos = re_search (buf, victim, length, |
384 |
offset, length - offset, ®s); |
offset, length - offset, ®s); |
385 |
if (matchpos < 0) |
if (matchpos < 0) |
386 |
{ |
{ |
391 |
|
|
392 |
if (matchpos == -2) |
if (matchpos == -2) |
393 |
M4ERROR ((warning_status, 0, |
M4ERROR ((warning_status, 0, |
394 |
_("Error matching regular expression `%s'"), regexp)); |
_("%s: error matching regular expression `%s'"), |
395 |
|
M4ARG (0), regexp)); |
396 |
else if (offset < length) |
else if (offset < length) |
397 |
obstack_grow (obs, victim + offset, length - offset); |
obstack_grow (obs, victim + offset, length - offset); |
398 |
break; |
break; |
417 |
} |
} |
418 |
obstack_1grow (obs, '\0'); |
obstack_1grow (obs, '\0'); |
419 |
|
|
|
xfree (buf.buffer); |
|
420 |
return; |
return; |
421 |
} |
} |
422 |
|
|