Stage 28a: Warn on embedded NUL in numeric arguments.
[m4.git] / modules / gnu.c
blobce14532b053826734406001136fe05efa1b7522e
1 /* GNU m4 -- A simple macro processor
2 Copyright (C) 2000, 2004, 2005, 2006, 2007, 2008, 2009 Free
3 Software Foundation, Inc.
5 This file is part of GNU M4.
7 GNU M4 is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU M4 is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
23 /* Build using only the exported interfaces, unles NDEBUG is set, in
24 which case use private symbols to speed things up as much as possible. */
25 #ifndef NDEBUG
26 # include <m4/m4module.h>
27 #else
28 # include "m4private.h"
29 #endif
31 #include "modules/m4.h"
32 #include "quotearg.h"
34 /* Rename exported symbols for dlpreload()ing. */
35 #define m4_builtin_table gnu_LTX_m4_builtin_table
36 #define m4_macro_table gnu_LTX_m4_macro_table
39 /* Maintain each of the builtins implemented in this modules along
40 with their details in a single table for easy maintenance.
42 function macros blind side minargs maxargs */
43 #define builtin_functions \
44 BUILTIN (__file__, false, false, false, 0, 0 ) \
45 BUILTIN (__line__, false, false, false, 0, 0 ) \
46 BUILTIN (__program__, false, false, false, 0, 0 ) \
47 BUILTIN (builtin, true, true, false, 1, -1 ) \
48 BUILTIN (changeresyntax,false,true, false, 1, 1 ) \
49 BUILTIN (changesyntax,false, true, false, 1, -1 ) \
50 BUILTIN (debugfile, false, false, false, 0, 1 ) \
51 BUILTIN (debuglen, false, true, false, 1, 1 ) \
52 BUILTIN (debugmode, false, false, false, 0, 1 ) \
53 BUILTIN (esyscmd, false, true, true, 1, 1 ) \
54 BUILTIN (format, false, true, false, 1, -1 ) \
55 BUILTIN (indir, true, true, false, 1, -1 ) \
56 BUILTIN (mkdtemp, false, true, false, 1, 1 ) \
57 BUILTIN (patsubst, false, true, true, 2, 4 ) \
58 BUILTIN (regexp, false, true, true, 2, 4 ) \
59 BUILTIN (renamesyms, false, true, false, 2, 3 ) \
60 BUILTIN (m4symbols, true, false, false, 0, -1 ) \
61 BUILTIN (syncoutput, false, true, false, 1, 1 ) \
64 /* Generate prototypes for each builtin handler function. */
65 #define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler)
66 builtin_functions
67 #undef BUILTIN
70 /* Generate a table for mapping m4 symbol names to handler functions. */
71 const m4_builtin m4_builtin_table[] =
73 #define BUILTIN(handler, macros, blind, side, min, max) \
74 M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
76 builtin_functions
77 #undef BUILTIN
79 { NULL, NULL, 0, 0, 0 },
83 /* A table for mapping m4 symbol names to simple expansion text. */
84 const m4_macro m4_macro_table[] =
86 /* name text min max */
87 #if UNIX
88 { "__unix__", "", 0, 0 },
89 #endif
90 #if W32_NATIVE
91 { "__windows__", "", 0, 0 },
92 #endif
93 #if OS2
94 { "__os2__", "", 0, 0 },
95 #endif
96 { "__gnu__", "", 0, 0 },
97 { "__m4_version__", VERSION,0, 0 },
99 { NULL, NULL, 0, 0 },
104 /* Regular expressions. Reuse re_registers among multiple
105 re_pattern_buffer allocations to reduce malloc usage. */
107 /* Maybe this is worth making runtime tunable. Too small, and nothing
108 gets cached because the working set of active regex is larger than
109 the cache, and we are always swapping out entries. Too large, and
110 the time spent searching the cache for a match overtakes the time
111 saved by caching. For now, this size proved reasonable for the
112 typical working set of Autoconf 2.62. */
113 #define REGEX_CACHE_SIZE 16
115 /* Structure for using a compiled regex, as well as making it easier
116 to cache frequently used expressions. */
117 typedef struct {
118 unsigned count; /* usage counter */
119 int resyntax; /* flavor of regex */
120 size_t len; /* length of string */
121 char *str; /* copy of compiled string */
122 struct re_pattern_buffer *pat; /* compiled regex, allocated */
123 struct re_registers regs; /* match registers, reused */
124 } m4_pattern_buffer;
126 /* Storage for the cache of regular expressions. */
127 static m4_pattern_buffer regex_cache[REGEX_CACHE_SIZE];
129 /* Compile a REGEXP of length LEN using the RESYNTAX flavor, and
130 return the buffer. On error, report the problem on behalf of
131 CALLER, and return NULL. */
133 static m4_pattern_buffer *
134 regexp_compile (m4 *context, const m4_call_info *caller, const char *regexp,
135 size_t len, int resyntax)
137 /* regex_cache is guaranteed to start life 0-initialized, which
138 works in the algorithm below.
140 FIXME - this method is not reentrant, since re_compile_pattern
141 mallocs memory, depends on the global variable re_syntax_options
142 for its syntax (but at least the compiled regex remembers its
143 syntax even if the global variable changes later), and since we
144 use a static variable. To be reentrant, we would need a mutex in
145 this method, and move the storage for regex_cache into context. */
147 const char *msg; /* error message from re_compile_pattern */
148 int i; /* iterator */
149 m4_pattern_buffer *victim; /* cache slot to replace */
150 unsigned victim_count; /* track which victim to replace */
151 struct re_pattern_buffer *pat;/* newly compiled regex */
153 /* First, check if REGEXP is already cached with the given RESYNTAX.
154 If so, increase its use count and return it. */
155 for (i = 0; i < REGEX_CACHE_SIZE; i++)
156 if (len == regex_cache[i].len && resyntax == regex_cache[i].resyntax
157 && regex_cache[i].str && memcmp (regexp, regex_cache[i].str, len) == 0)
159 regex_cache[i].count++;
160 return &regex_cache[i];
163 /* Next, check if REGEXP can be compiled. */
164 pat = (struct re_pattern_buffer *) xzalloc (sizeof *pat);
165 re_set_syntax (resyntax);
166 msg = re_compile_pattern (regexp, len, pat);
168 if (msg != NULL)
170 m4_warn (context, 0, caller, _("bad regular expression %s: %s"),
171 quotearg_style_mem (locale_quoting_style, regexp, len), msg);
172 regfree (pat);
173 free (pat);
174 return NULL;
176 /* Use a fastmap for speed; it is freed by regfree. */
177 pat->fastmap = xcharalloc (UCHAR_MAX + 1);
179 /* Now, find a victim slot. Decrease the count of all entries, then
180 prime the count of the victim slot at REGEX_CACHE_SIZE. This
181 way, frequently used entries and newly created entries are least
182 likely to be victims next time we have a cache miss. */
183 victim = regex_cache;
184 victim_count = victim->count;
185 if (victim_count)
186 victim->count--;
187 for (i = 1; i < REGEX_CACHE_SIZE; i++)
189 if (regex_cache[i].count < victim_count)
191 victim_count = regex_cache[i].count;
192 victim = &regex_cache[i];
194 if (regex_cache[i].count)
195 regex_cache[i].count--;
197 victim->count = REGEX_CACHE_SIZE;
198 victim->resyntax = resyntax;
199 victim->len = len;
200 if (victim->str)
202 free (victim->str);
203 regfree (victim->pat);
204 free (victim->pat);
206 victim->str = xstrdup (regexp);
207 victim->pat = pat;
208 re_set_registers (pat, &victim->regs, victim->regs.num_regs,
209 victim->regs.start, victim->regs.end);
210 return victim;
214 /* Wrap up GNU Regex re_search call to work with an m4_pattern_buffer.
215 If NO_SUB, then storing matches in buf->regs is not necessary. */
217 static regoff_t
218 regexp_search (m4_pattern_buffer *buf, const char *string, const int size,
219 const int start, const int range, bool no_sub)
221 return re_search (buf->pat, string, size, start, range,
222 no_sub ? NULL : &buf->regs);
226 /* Function to perform substitution by regular expressions. Used by
227 the builtins regexp, patsubst and renamesyms. The changed text is
228 placed on the obstack OBS. The substitution is REPL of length
229 REPL_LEN, with \& substituted by this part of VICTIM matched by the
230 last whole regular expression, and \N substituted by the text
231 matched by the Nth parenthesized sub-expression in BUF. Any
232 warnings are issued on behalf of CALLER. BUF may be NULL for the
233 empty regex. */
235 static void
236 substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller,
237 const char *victim, const char *repl, size_t repl_len,
238 m4_pattern_buffer *buf)
240 int ch;
242 while (repl_len--)
244 ch = *repl++;
245 if (ch != '\\')
247 obstack_1grow (obs, ch);
248 continue;
250 if (!repl_len)
252 m4_warn (context, 0, caller,
253 _("trailing \\ ignored in replacement"));
254 return;
257 ch = *repl++;
258 repl_len--;
259 switch (ch)
261 case '&':
262 if (buf)
263 obstack_grow (obs, victim + buf->regs.start[0],
264 buf->regs.end[0] - buf->regs.start[0]);
265 break;
267 case '1': case '2': case '3': case '4': case '5': case '6':
268 case '7': case '8': case '9':
269 ch -= '0';
270 if (!buf || buf->pat->re_nsub < ch)
271 m4_warn (context, 0, caller, _("sub-expression %d not present"),
272 ch);
273 else if (buf->regs.end[ch] > 0)
274 obstack_grow (obs, victim + buf->regs.start[ch],
275 buf->regs.end[ch] - buf->regs.start[ch]);
276 break;
278 default:
279 obstack_1grow (obs, ch);
280 break;
286 /* For each match against REGEXP of length REGEXP_LEN (precompiled in
287 BUF as returned by regexp_compile) in VICTIM of length LEN,
288 substitute REPLACE of length REPL_LEN. Non-matching characters are
289 copied verbatim, and the result copied to the obstack. Errors are
290 reported on behalf of CALLER. Return true if a substitution was
291 made. If OPTIMIZE is set, don't worry about copying the input if
292 no changes are made. */
294 static bool
295 regexp_substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller,
296 const char *victim, size_t len, const char *regexp,
297 size_t regexp_len, m4_pattern_buffer *buf,
298 const char *replace, size_t repl_len, bool optimize)
300 regoff_t matchpos = 0; /* start position of match */
301 size_t offset = 0; /* current match offset */
302 bool subst = !optimize; /* if a substitution has been made */
304 while (offset <= len)
306 matchpos = regexp_search (buf, victim, len, offset, len - offset,
307 false);
309 if (matchpos < 0)
312 /* Match failed -- either error or there is no match in the
313 rest of the string, in which case the rest of the string is
314 copied verbatim. */
316 if (matchpos == -2)
317 m4_error (context, 0, 0, caller,
318 _("problem matching regular expression %s"),
319 quotearg_style_mem (locale_quoting_style, regexp,
320 regexp_len));
321 else if (offset < len && subst)
322 obstack_grow (obs, victim + offset, len - offset);
323 break;
326 /* Copy the part of the string that was skipped by re_search (). */
328 if (matchpos > offset)
329 obstack_grow (obs, victim + offset, matchpos - offset);
331 /* Handle the part of the string that was covered by the match. */
333 substitute (context, obs, caller, victim, replace, repl_len, buf);
334 subst = true;
336 /* Update the offset to the end of the match. If the regexp
337 matched a null string, advance offset one more, to avoid
338 infinite loops. */
340 offset = buf->regs.end[0];
341 if (buf->regs.start[0] == buf->regs.end[0])
343 if (offset < len)
344 obstack_1grow (obs, victim[offset]);
345 offset++;
349 return subst;
353 /* Reclaim memory used by this module. */
354 M4FINISH_HANDLER(gnu)
356 int i;
357 for (i = 0; i < REGEX_CACHE_SIZE; i++)
358 if (regex_cache[i].str)
360 free (regex_cache[i].str);
361 regfree (regex_cache[i].pat);
362 free (regex_cache[i].pat);
363 free (regex_cache[i].regs.start);
364 free (regex_cache[i].regs.end);
366 /* If this module was preloaded, then we need to explicitly reset
367 the memory in case it gets reloaded. */
368 memset (&regex_cache, 0, sizeof regex_cache);
374 * __file__
376 M4BUILTIN_HANDLER (__file__)
378 m4_shipout_string (context, obs, m4_get_current_file (context), SIZE_MAX,
379 true);
384 * __line__
386 M4BUILTIN_HANDLER (__line__)
388 m4_shipout_int (obs, m4_get_current_line (context));
393 * __program__
395 M4BUILTIN_HANDLER (__program__)
397 m4_shipout_string (context, obs, m4_get_program_name (), SIZE_MAX, true);
401 /* The builtin "builtin" allows calls to builtin macros, even if their
402 definition has been overridden or shadowed. It is thus possible to
403 redefine builtins, and still access their original definition. A
404 special form allows one to retrieve the special token that defn
405 would normally return, even if that builtin is not currently
406 defined and hence can't be passed to defn. */
409 * builtin(MACRO, [...])
410 * builtin(defn(`builtin'), MACRO)
412 M4BUILTIN_HANDLER (builtin)
414 const m4_call_info *me = m4_arg_info (argv);
415 const char *name;
416 size_t len;
417 m4_symbol_value *value = NULL;
419 if (!m4_is_arg_text (argv, 1))
421 assert (m4_is_arg_func (argv, 1));
422 if (m4_arg_func (argv, 1) == builtin_builtin)
424 if (m4_bad_argc (context, argc, me, 2, 2, false))
425 return;
426 if (!m4_is_arg_text (argv, 2))
428 m4_warn (context, 0, me, _("invalid macro name ignored"));
429 return;
431 name = M4ARG (2);
432 len = M4ARGLEN (2);
433 if (len == strlen (name))
434 value = m4_builtin_find_by_name (NULL, name);
435 if (value)
437 m4_push_builtin (context, obs, value);
438 free (value);
440 else if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
441 m4_warn (context, 0, me, _("undefined builtin %s"),
442 quotearg_style_mem (locale_quoting_style, name, len));
444 else
445 m4_warn (context, 0, me, _("invalid macro name ignored"));
447 else
449 name = M4ARG (1);
450 len = M4ARGLEN (1);
451 if (len == strlen (name))
452 value = m4_builtin_find_by_name (NULL, name);
453 if (value == NULL)
455 if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
456 m4_warn (context, 0, me, _("undefined builtin %s"),
457 quotearg_style_mem (locale_quoting_style, name, len));
459 else
461 const m4_builtin *bp = m4_get_symbol_value_builtin (value);
462 m4_macro_args *new_argv;
463 bool flatten = (bp->flags & M4_BUILTIN_FLATTEN_ARGS) != 0;
464 new_argv = m4_make_argv_ref (context, argv, name, len, flatten,
465 false);
466 if (!m4_bad_argc (context, argc - 1, m4_arg_info (new_argv),
467 bp->min_args, bp->max_args,
468 (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
469 bp->func (context, obs, argc - 1, new_argv);
470 free (value);
476 /* Change the current regexp syntax to SPEC of length LEN, or report
477 failure on behalf of CALLER. Currently this affects the builtins:
478 `patsubst', `regexp' and `renamesyms'. */
480 static int
481 m4_resyntax_encode_safe (m4 *context, const m4_call_info *caller,
482 const char *spec, size_t len)
484 int resyntax;
486 if (strlen (spec) < len)
487 resyntax = -1;
488 else
489 resyntax = m4_regexp_syntax_encode (spec);
491 if (resyntax < 0)
492 m4_warn (context, 0, caller, _("bad syntax-spec: %s"),
493 quotearg_style_mem (locale_quoting_style, spec, len));
495 return resyntax;
500 * changeresyntax(RESYNTAX-SPEC)
502 M4BUILTIN_HANDLER (changeresyntax)
504 int resyntax = m4_resyntax_encode_safe (context, m4_arg_info (argv),
505 M4ARG (1), M4ARGLEN (1));
507 if (resyntax >= 0)
508 m4_set_regexp_syntax_opt (context, resyntax);
512 /* Change the current input syntax. The function m4_set_syntax ()
513 lives in syntax.c. Any changes to comment delimiters and quotes
514 made here will be overridden by a call to `changecom' or
515 `changequote'. */
518 * changesyntax(SYNTAX-SPEC, ...)
520 M4BUILTIN_HANDLER (changesyntax)
522 const m4_call_info *me = m4_arg_info (argv);
523 M4_MODULE_IMPORT (m4, m4_expand_ranges);
525 if (m4_expand_ranges)
527 size_t i;
528 for (i = 1; i < argc; i++)
530 size_t len = M4ARGLEN (i);
531 const char *spec;
532 char key;
533 char action;
535 if (!len)
537 m4_reset_syntax (M4SYNTAX);
538 continue;
540 spec = M4ARG (i);
541 key = *spec++;
542 len--;
543 action = len ? *spec : '\0';
544 switch (action)
546 case '-':
547 case '+':
548 case '=':
549 spec++;
550 len--;
551 break;
552 case '\0':
553 if (!len)
554 break;
555 /* fall through */
556 default:
557 action = '=';
558 break;
560 if (len)
561 spec = m4_expand_ranges (spec, &len, m4_arg_scratch (context));
562 if (m4_set_syntax (M4SYNTAX, key, action, spec, len) < 0)
563 m4_warn (context, 0, me, _("undefined syntax code: %s"),
564 quotearg_style_mem (locale_quoting_style, &key, 1));
567 else
568 assert (!"Unable to import from m4 module");
572 /* Specify the destination of the debugging output. With one argument, the
573 argument is taken as a file name, with no arguments, revert to stderr. */
576 * debugfile([FILENAME])
578 M4BUILTIN_HANDLER (debugfile)
580 const m4_call_info *me = m4_arg_info (argv);
582 if (argc == 1)
583 m4_debug_set_output (context, me, NULL);
584 else if (m4_get_safer_opt (context) && !m4_arg_empty (argv, 1))
585 m4_error (context, 0, 0, me, _("disabled by --safer"));
586 else if (!m4_debug_set_output (context, me, M4ARG (1)))
587 m4_error (context, 0, errno, me, _("cannot set debug file %s"),
588 quotearg_style (locale_quoting_style, M4ARG (1)));
592 /* On-the-fly control of debug length. It takes one integer
593 argument. */
596 * debuglen(LEN)
598 M4BUILTIN_HANDLER (debuglen)
600 int i;
601 size_t s;
602 if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1),
603 &i))
604 return;
605 /* FIXME - make m4_numeric_arg more powerful - we want to accept
606 suffixes, and limit the result to size_t. */
607 s = i <= 0 ? SIZE_MAX : i;
608 m4_set_max_debug_arg_length_opt (context, s);
611 /* On-the-fly control of the format of the tracing output. It takes one
612 argument, which is a character string like given to the -d option, or
613 none in which case the debug_level is zeroed. */
616 * debugmode([FLAGS])
618 M4BUILTIN_HANDLER (debugmode)
620 if (argc == 1)
621 m4_set_debug_level_opt (context, 0);
622 else if (m4_debug_decode (context, M4ARG (1)) < 0)
623 m4_error (context, 0, 0, m4_arg_info (argv),
624 _("bad debug flags: `%s'"), M4ARG (1));
628 /* Same as the sysymd builtin from m4.c module, but expand to the
629 output of SHELL-COMMAND. */
632 * esyscmd(SHELL-COMMAND)
635 M4BUILTIN_HANDLER (esyscmd)
637 const m4_call_info *me = m4_arg_info (argv);
638 M4_MODULE_IMPORT (m4, m4_set_sysval);
639 M4_MODULE_IMPORT (m4, m4_sysval_flush);
641 if (m4_set_sysval && m4_sysval_flush)
643 FILE *pin;
644 int ch;
646 if (m4_get_safer_opt (context))
648 m4_error (context, 0, 0, me, _("disabled by --safer"));
649 return;
652 /* Optimize the empty command. */
653 if (m4_arg_empty (argv, 1))
655 m4_set_sysval (0);
656 return;
659 m4_sysval_flush (context, false);
660 errno = 0;
661 pin = popen (M4ARG (1), "r");
662 if (pin == NULL)
664 m4_error (context, 0, errno, me,
665 _("cannot open pipe to command `%s'"), M4ARG (1));
666 m4_set_sysval (-1);
668 else
670 while ((ch = getc (pin)) != EOF)
671 obstack_1grow (obs, ch);
672 m4_set_sysval (pclose (pin));
675 else
676 assert (!"Unable to import from m4 module");
680 /* Frontend for printf like formatting. The function format () lives in
681 the file format.c. */
683 #include "format.c"
686 * format(FORMAT-STRING, [...])
688 M4BUILTIN_HANDLER (format)
690 format (context, obs, argc, argv);
694 /* The builtin "indir" allows indirect calls to macros, even if their name
695 is not a proper macro name. It is thus possible to define macros with
696 ill-formed names for internal use in larger macro packages. */
699 * indir(MACRO, [...])
701 M4BUILTIN_HANDLER (indir)
703 const m4_call_info *me = m4_arg_info (argv);
704 if (!m4_is_arg_text (argv, 1))
705 m4_warn (context, 0, me, _("invalid macro name ignored"));
706 else
708 const char *name = M4ARG (1);
709 size_t len = M4ARGLEN (1);
710 m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name, len);
712 if (symbol == NULL)
714 if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
715 m4_warn (context, 0, me, _("undefined macro %s"),
716 quotearg_style_mem (locale_quoting_style, name, len));
718 else
720 m4_macro_args *new_argv;
721 m4_symbol_value *value = m4_get_symbol_value (symbol);
722 new_argv = m4_make_argv_ref (context, argv, name, len,
723 m4_symbol_flatten_args (symbol),
724 m4_get_symbol_traced (symbol));
725 m4_trace_prepare (context, m4_arg_info (new_argv), value);
726 m4_macro_call (context, value, obs, new_argv);
732 /* The builtin "mkdtemp" allows creation of temporary directories. */
735 * mkdtemp(TEMPLATE)
737 M4BUILTIN_HANDLER (mkdtemp)
739 M4_MODULE_IMPORT (m4, m4_make_temp);
741 if (m4_make_temp)
742 m4_make_temp (context, obs, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1),
743 true);
744 else
745 assert (!"Unable to import from m4 module");
749 /* Substitute all matches of a regexp occurring in a string. Each
750 match of the second argument (a regexp) in the first argument is
751 changed to the optional third argument, with \& substituted by the
752 matched text, and \N substituted by the text matched by the Nth
753 parenthesized sub-expression. The optional fourth argument changes
754 the regex flavor. */
757 * patsubst(VICTIM, REGEXP, [REPLACEMENT], [RESYNTAX])
759 M4BUILTIN_HANDLER (patsubst)
761 const m4_call_info *me = m4_arg_info (argv);
762 const char *pattern; /* regular expression */
763 const char *replace; /* replacement */
764 m4_pattern_buffer *buf; /* compiled regular expression */
765 int resyntax;
767 resyntax = m4_get_regexp_syntax_opt (context);
768 if (argc >= 5) /* additional args ignored */
770 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (4),
771 M4ARGLEN (4));
772 if (resyntax < 0)
773 return;
776 /* The empty regex matches everywhere, but if there is no
777 replacement, we need not waste time with it. */
778 if (m4_arg_empty (argv, 2) && m4_arg_empty (argv, 3))
780 m4_push_arg (context, obs, argv, 1);
781 return;
784 pattern = M4ARG (2);
785 replace = M4ARG (3);
787 buf = regexp_compile (context, me, pattern, M4ARGLEN (2), resyntax);
788 if (!buf)
789 return;
791 regexp_substitute (context, obs, me, M4ARG (1), M4ARGLEN (1), pattern,
792 M4ARGLEN (2), buf, replace, M4ARGLEN (3), false);
796 /* Regular expression version of index. Given two arguments, expand
797 to the index of the first match of the second argument (a regexp)
798 in the first. Expand to -1 if there is no match. Given a third
799 argument, a match is substituted according to this argument. The
800 optional fourth argument changes the regex flavor. */
803 * regexp(VICTIM, REGEXP, RESYNTAX)
804 * regexp(VICTIM, REGEXP, [REPLACEMENT], [RESYNTAX])
806 M4BUILTIN_HANDLER (regexp)
808 const m4_call_info *me = m4_arg_info (argv);
809 const char *victim; /* string to search */
810 const char *pattern; /* regular expression */
811 const char *replace; /* optional replacement string */
812 m4_pattern_buffer *buf; /* compiled regular expression */
813 regoff_t startpos; /* start position of match */
814 size_t len; /* length of first argument */
815 int resyntax;
817 pattern = M4ARG (2);
818 replace = M4ARG (3);
819 resyntax = m4_get_regexp_syntax_opt (context);
821 if (argc == 4)
823 resyntax = m4_regexp_syntax_encode (replace);
825 /* The first case is the most difficult, because the empty string
826 is a valid RESYNTAX, yet we want `regexp(aab, a*, )' to return
827 an empty string as per M4 1.4.x. */
829 if (m4_arg_empty (argv, 3) || (resyntax < 0))
830 /* regexp(VICTIM, REGEXP, REPLACEMENT) */
831 resyntax = m4_get_regexp_syntax_opt (context);
832 else
833 /* regexp(VICTIM, REGEXP, RESYNTAX) */
834 replace = NULL;
836 else if (argc >= 5)
838 /* regexp(VICTIM, REGEXP, REPLACEMENT, RESYNTAX) */
839 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (4),
840 M4ARGLEN (4));
841 if (resyntax < 0)
842 return;
844 else
845 /* regexp(VICTIM, REGEXP) */
846 replace = NULL;
848 if (m4_arg_empty (argv, 2))
850 /* The empty regex matches everything. */
851 if (replace)
852 substitute (context, obs, me, M4ARG (1), replace, M4ARGLEN (3), NULL);
853 else
854 m4_shipout_int (obs, 0);
855 return;
858 buf = regexp_compile (context, me, pattern, M4ARGLEN (2), resyntax);
859 if (!buf)
860 return;
862 victim = M4ARG (1);
863 len = M4ARGLEN (1);
864 startpos = regexp_search (buf, victim, len, 0, len, replace == NULL);
866 if (startpos == -2)
868 m4_error (context, 0, 0, me, _("problem matching regular expression %s"),
869 quotearg_style_mem (locale_quoting_style, pattern,
870 M4ARGLEN (2)));
871 return;
874 if (replace == NULL)
875 m4_shipout_int (obs, startpos);
876 else if (startpos >= 0)
877 substitute (context, obs, me, victim, replace, M4ARGLEN (3), buf);
881 /* Rename all current symbols that match REGEXP according to the
882 REPLACEMENT specification. */
885 * renamesyms(REGEXP, REPLACEMENT, [RESYNTAX])
887 M4BUILTIN_HANDLER (renamesyms)
889 M4_MODULE_IMPORT (m4, m4_dump_symbols);
891 if (m4_dump_symbols)
893 const m4_call_info *me = m4_arg_info (argv);
894 const char *regexp; /* regular expression string */
895 size_t regexp_len;
896 const char *replace; /* replacement expression string */
897 size_t replace_len;
899 m4_pattern_buffer *buf; /* compiled regular expression */
901 m4_dump_symbol_data data;
903 int resyntax;
905 regexp = M4ARG (1);
906 regexp_len = M4ARGLEN (1);
907 replace = M4ARG (2);
908 replace_len = M4ARGLEN (2);
910 resyntax = m4_get_regexp_syntax_opt (context);
911 if (argc >= 4)
913 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (3),
914 M4ARGLEN (3));
915 if (resyntax < 0)
916 return;
919 buf = regexp_compile (context, me, regexp, regexp_len, resyntax);
920 if (!buf)
921 return;
923 data.obs = m4_arg_scratch (context);
924 m4_dump_symbols (context, &data, 1, argv, false);
926 for (; data.size > 0; --data.size, data.base++)
928 const m4_string *key = &data.base[0];
930 if (regexp_substitute (context, data.obs, me, key->str, key->len,
931 regexp, regexp_len, buf, replace, replace_len,
932 true))
934 size_t newlen = obstack_object_size (data.obs);
935 m4_symbol_rename (M4SYMTAB, key->str, key->len,
936 (char *) obstack_finish (data.obs), newlen);
940 else
941 assert (!"Unable to import from m4 module");
945 /* Implementation of "m4symbols". It builds up a table of pointers to
946 symbols, sorts it and ships out the symbol names. */
949 * m4symbols([...])
951 M4BUILTIN_HANDLER (m4symbols)
953 M4_MODULE_IMPORT (m4, m4_dump_symbols);
955 if (m4_dump_symbols)
957 m4_dump_symbol_data data;
959 data.obs = m4_arg_scratch (context);
960 m4_dump_symbols (context, &data, argc, argv, false);
962 for (; data.size > 0; --data.size, data.base++)
964 m4_shipout_string (context, obs, data.base->str, data.base->len,
965 true);
966 if (data.size > 1)
967 obstack_1grow (obs, ',');
970 else
971 assert (!"Unable to import from m4 module");
975 /* This contains macro which implements syncoutput() which takes one arg
976 1, on, yes - turn on sync lines
977 0, off, no, blank - turn off sync lines
978 everything else is silently ignored */
981 * syncoutput(TRUTH)
983 M4BUILTIN_HANDLER (syncoutput)
985 bool value = m4_get_syncoutput_opt (context);
986 value = m4_parse_truth_arg (context, m4_arg_info (argv), M4ARG (1), value);
987 m4_set_syncoutput_opt (context, value);