Stage 24a: Use full call context in error reporting.
[m4.git] / modules / gnu.c
blob78c69b509aa2e8be7252f388779befd0d22ac47e
1 /* GNU m4 -- A simple macro processor
2 Copyright (C) 2000, 2004, 2005, 2006, 2007, 2008 Free Software
3 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"
33 /* Rename exported symbols for dlpreload()ing. */
34 #define m4_builtin_table gnu_LTX_m4_builtin_table
35 #define m4_macro_table gnu_LTX_m4_macro_table
38 /* Maintain each of the builtins implemented in this modules along
39 with their details in a single table for easy maintenance.
41 function macros blind side minargs maxargs */
42 #define builtin_functions \
43 BUILTIN (__file__, false, false, false, 0, 0 ) \
44 BUILTIN (__line__, false, false, false, 0, 0 ) \
45 BUILTIN (__program__, false, false, false, 0, 0 ) \
46 BUILTIN (builtin, true, true, false, 1, -1 ) \
47 BUILTIN (changeresyntax,false,true, false, 1, 1 ) \
48 BUILTIN (changesyntax,false, true, false, 1, -1 ) \
49 BUILTIN (debugfile, false, false, false, 0, 1 ) \
50 BUILTIN (debuglen, false, true, false, 1, 1 ) \
51 BUILTIN (debugmode, false, false, false, 0, 1 ) \
52 BUILTIN (esyscmd, false, true, true, 1, 1 ) \
53 BUILTIN (format, false, true, false, 1, -1 ) \
54 BUILTIN (indir, true, true, false, 1, -1 ) \
55 BUILTIN (mkdtemp, false, true, false, 1, 1 ) \
56 BUILTIN (patsubst, false, true, true, 2, 4 ) \
57 BUILTIN (regexp, false, true, true, 2, 4 ) \
58 BUILTIN (renamesyms, false, true, false, 2, 3 ) \
59 BUILTIN (m4symbols, true, false, false, 0, -1 ) \
60 BUILTIN (syncoutput, false, true, false, 1, 1 ) \
63 /* Generate prototypes for each builtin handler function. */
64 #define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler)
65 builtin_functions
66 #undef BUILTIN
69 /* Generate a table for mapping m4 symbol names to handler functions. */
70 m4_builtin m4_builtin_table[] =
72 #define BUILTIN(handler, macros, blind, side, min, max) \
73 M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
75 builtin_functions
76 #undef BUILTIN
78 { NULL, NULL, 0, 0, 0 },
82 /* A table for mapping m4 symbol names to simple expansion text. */
83 m4_macro m4_macro_table[] =
85 /* name text min max */
86 #if UNIX
87 { "__unix__", "", 0, 0 },
88 #endif
89 #if W32_NATIVE
90 { "__windows__", "", 0, 0 },
91 #endif
92 #if OS2
93 { "__os2__", "", 0, 0 },
94 #endif
95 { "__gnu__", "", 0, 0 },
96 { "__m4_version__", VERSION,0, 0 },
98 { NULL, NULL, 0, 0 },
103 /* Regular expressions. Reuse re_registers among multiple
104 re_pattern_buffer allocations to reduce malloc usage. */
106 /* Maybe this is worth making runtime tunable. Too small, and nothing
107 gets cached because the working set of active regex is larger than
108 the cache, and we are always swapping out entries. Too large, and
109 the time spent searching the cache for a match overtakes the time
110 saved by caching. For now, this size proved reasonable for the
111 typical working set of Autoconf 2.62. */
112 #define REGEX_CACHE_SIZE 16
114 /* Structure for using a compiled regex, as well as making it easier
115 to cache frequently used expressions. */
116 typedef struct {
117 unsigned count; /* usage counter */
118 int resyntax; /* flavor of regex */
119 size_t len; /* length of string */
120 char *str; /* copy of compiled string */
121 struct re_pattern_buffer *pat; /* compiled regex, allocated */
122 struct re_registers regs; /* match registers, reused */
123 } m4_pattern_buffer;
125 /* Storage for the cache of regular expressions. */
126 static m4_pattern_buffer regex_cache[REGEX_CACHE_SIZE];
128 /* Compile a REGEXP of length LEN using the RESYNTAX flavor, and
129 return the buffer. On error, report the problem on behalf of
130 CALLER, and return NULL. */
132 static m4_pattern_buffer *
133 regexp_compile (m4 *context, const m4_call_info *caller, const char *regexp,
134 size_t len, int resyntax)
136 /* regex_cache is guaranteed to start life 0-initialized, which
137 works in the algorithm below.
139 FIXME - this method is not reentrant, since re_compile_pattern
140 mallocs memory, depends on the global variable re_syntax_options
141 for its syntax (but at least the compiled regex remembers its
142 syntax even if the global variable changes later), and since we
143 use a static variable. To be reentrant, we would need a mutex in
144 this method, and move the storage for regex_cache into context. */
146 const char *msg; /* error message from re_compile_pattern */
147 int i; /* iterator */
148 m4_pattern_buffer *victim; /* cache slot to replace */
149 unsigned victim_count; /* track which victim to replace */
150 struct re_pattern_buffer *pat;/* newly compiled regex */
152 /* First, check if REGEXP is already cached with the given RESYNTAX.
153 If so, increase its use count and return it. */
154 for (i = 0; i < REGEX_CACHE_SIZE; i++)
155 if (len == regex_cache[i].len && resyntax == regex_cache[i].resyntax
156 && regex_cache[i].str && memcmp (regexp, regex_cache[i].str, len) == 0)
158 regex_cache[i].count++;
159 return &regex_cache[i];
162 /* Next, check if REGEXP can be compiled. */
163 pat = (struct re_pattern_buffer *) xzalloc (sizeof *pat);
164 re_set_syntax (resyntax);
165 msg = re_compile_pattern (regexp, len, pat);
167 if (msg != NULL)
169 m4_error (context, 0, 0, caller, _("bad regular expression `%s': %s"),
170 regexp, msg);
171 regfree (pat);
172 free (pat);
173 return NULL;
175 /* Use a fastmap for speed; it is freed by regfree. */
176 pat->fastmap = xcharalloc (UCHAR_MAX + 1);
178 /* Now, find a victim slot. Decrease the count of all entries, then
179 prime the count of the victim slot at REGEX_CACHE_SIZE. This
180 way, frequently used entries and newly created entries are least
181 likely to be victims next time we have a cache miss. */
182 victim = regex_cache;
183 victim_count = victim->count;
184 if (victim_count)
185 victim->count--;
186 for (i = 1; i < REGEX_CACHE_SIZE; i++)
188 if (regex_cache[i].count < victim_count)
190 victim_count = regex_cache[i].count;
191 victim = &regex_cache[i];
193 if (regex_cache[i].count)
194 regex_cache[i].count--;
196 victim->count = REGEX_CACHE_SIZE;
197 victim->resyntax = resyntax;
198 victim->len = len;
199 if (victim->str)
201 free (victim->str);
202 regfree (victim->pat);
203 free (victim->pat);
205 victim->str = xstrdup (regexp);
206 victim->pat = pat;
207 re_set_registers (pat, &victim->regs, victim->regs.num_regs,
208 victim->regs.start, victim->regs.end);
209 return victim;
213 /* Wrap up GNU Regex re_search call to work with an m4_pattern_buffer.
214 If NO_SUB, then storing matches in buf->regs is not necessary. */
216 static regoff_t
217 regexp_search (m4_pattern_buffer *buf, const char *string, const int size,
218 const int start, const int range, bool no_sub)
220 return re_search (buf->pat, string, size, start, range,
221 no_sub ? NULL : &buf->regs);
225 /* Function to perform substitution by regular expressions. Used by
226 the builtins regexp, patsubst and renamesyms. The changed text is
227 placed on the obstack OBS. The substitution is REPL, with \&
228 substituted by this part of VICTIM matched by the last whole
229 regular expression, and \N substituted by the text matched by the
230 Nth parenthesized sub-expression in BUF. Any warnings are issued
231 on behalf of CALLER. BUF may be NULL for the empty regex. */
233 static void
234 substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller,
235 const char *victim, const char *repl, m4_pattern_buffer *buf)
237 int ch;
239 for (;;)
241 while ((ch = *repl++) != '\\')
243 if (ch == '\0')
244 return;
245 obstack_1grow (obs, ch);
248 switch ((ch = *repl++))
250 case '&':
251 if (buf)
252 obstack_grow (obs, victim + buf->regs.start[0],
253 buf->regs.end[0] - buf->regs.start[0]);
254 break;
256 case '1': case '2': case '3': case '4': case '5': case '6':
257 case '7': case '8': case '9':
258 ch -= '0';
259 if (!buf || buf->pat->re_nsub < ch)
260 m4_warn (context, 0, caller, _("sub-expression %d not present"),
261 ch);
262 else if (buf->regs.end[ch] > 0)
263 obstack_grow (obs, victim + buf->regs.start[ch],
264 buf->regs.end[ch] - buf->regs.start[ch]);
265 break;
267 case '\0':
268 m4_warn (context, 0, caller,
269 _("trailing \\ ignored in replacement"));
270 return;
272 default:
273 obstack_1grow (obs, ch);
274 break;
280 /* For each match against compiled REGEXP (held in BUF -- as returned
281 by regexp_compile) in VICTIM, substitute REPLACE. Non-matching
282 characters are copied verbatim, and the result copied to the
283 obstack. Errors are reported on behalf of CALLER. Return true if
284 a substitution was made. If OPTIMIZE is set, don't worry about
285 copying the input if no changes are made. */
287 static bool
288 regexp_substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller,
289 const char *victim, size_t len, const char *regexp,
290 m4_pattern_buffer *buf, const char *replace,
291 bool optimize)
293 regoff_t matchpos = 0; /* start position of match */
294 size_t offset = 0; /* current match offset */
295 bool subst = !optimize; /* if a substitution has been made */
297 while (offset <= len)
299 matchpos = regexp_search (buf, victim, len, offset, len - offset,
300 false);
302 if (matchpos < 0)
305 /* Match failed -- either error or there is no match in the
306 rest of the string, in which case the rest of the string is
307 copied verbatim. */
309 if (matchpos == -2)
310 m4_error (context, 0, 0, caller,
311 _("error matching regular expression `%s'"), regexp);
312 else if (offset < len && subst)
313 obstack_grow (obs, victim + offset, len - offset);
314 break;
317 /* Copy the part of the string that was skipped by re_search (). */
319 if (matchpos > offset)
320 obstack_grow (obs, victim + offset, matchpos - offset);
322 /* Handle the part of the string that was covered by the match. */
324 substitute (context, obs, caller, victim, replace, buf);
325 subst = true;
327 /* Update the offset to the end of the match. If the regexp
328 matched a null string, advance offset one more, to avoid
329 infinite loops. */
331 offset = buf->regs.end[0];
332 if (buf->regs.start[0] == buf->regs.end[0])
334 if (offset < len)
335 obstack_1grow (obs, victim[offset]);
336 offset++;
340 return subst;
344 /* Reclaim memory used by this module. */
345 M4FINISH_HANDLER(gnu)
347 int i;
348 for (i = 0; i < REGEX_CACHE_SIZE; i++)
349 if (regex_cache[i].str)
351 free (regex_cache[i].str);
352 regfree (regex_cache[i].pat);
353 free (regex_cache[i].pat);
354 free (regex_cache[i].regs.start);
355 free (regex_cache[i].regs.end);
357 /* If this module was preloaded, then we need to explicitly reset
358 the memory in case it gets reloaded. */
359 memset (&regex_cache, 0, sizeof regex_cache);
365 * __file__
367 M4BUILTIN_HANDLER (__file__)
369 m4_shipout_string (context, obs, m4_get_current_file (context), SIZE_MAX,
370 true);
375 * __line__
377 M4BUILTIN_HANDLER (__line__)
379 m4_shipout_int (obs, m4_get_current_line (context));
384 * __program__
386 M4BUILTIN_HANDLER (__program__)
388 m4_shipout_string (context, obs, m4_get_program_name (), SIZE_MAX, true);
392 /* The builtin "builtin" allows calls to builtin macros, even if their
393 definition has been overridden or shadowed. It is thus possible to
394 redefine builtins, and still access their original definition. A
395 special form allows one to retrieve the special token that defn
396 would normally return, even if that builtin is not currently
397 defined and hence can't be passed to defn. */
400 * builtin(MACRO, [...])
401 * builtin(defn(`builtin'), MACRO)
403 M4BUILTIN_HANDLER (builtin)
405 const m4_call_info *me = m4_arg_info (argv);
406 const char *name;
407 m4_symbol_value *value;
409 if (!m4_is_arg_text (argv, 1))
411 assert (m4_is_arg_func (argv, 1));
412 if (m4_arg_func (argv, 1) == builtin_builtin)
414 if (m4_bad_argc (context, argc, me, 2, 2, false))
415 return;
416 if (!m4_is_arg_text (argv, 2))
418 m4_warn (context, 0, me, _("invalid macro name ignored"));
419 return;
421 name = M4ARG (2);
422 value = m4_builtin_find_by_name (NULL, name);
423 if (value == NULL)
424 m4_warn (context, 0, me, _("undefined builtin `%s'"), name);
425 else
427 m4_push_builtin (context, obs, value);
428 free (value);
431 else
432 m4_warn (context, 0, me, _("invalid macro name ignored"));
434 else
436 name = M4ARG (1);
437 value = m4_builtin_find_by_name (NULL, name);
438 if (value == NULL)
439 m4_warn (context, 0, me, _("undefined builtin `%s'"), name);
440 else
442 const m4_builtin *bp = m4_get_symbol_value_builtin (value);
443 m4_macro_args *new_argv;
444 bool flatten = (bp->flags & M4_BUILTIN_FLATTEN_ARGS) != 0;
445 new_argv = m4_make_argv_ref (context, argv, name, M4ARGLEN (1),
446 flatten, false);
447 if (!m4_bad_argc (context, argc - 1, m4_arg_info (new_argv),
448 bp->min_args, bp->max_args,
449 (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
450 bp->func (context, obs, argc - 1, new_argv);
451 free (value);
457 /* Change the current regexp syntax to SPEC, or report failure on
458 behalf of CALLER. Currently this affects the builtins: `patsubst',
459 `regexp' and `renamesyms'. */
461 static int
462 m4_resyntax_encode_safe (m4 *context, const m4_call_info *caller,
463 const char *spec)
465 int resyntax = m4_regexp_syntax_encode (spec);
467 if (resyntax < 0)
468 m4_warn (context, 0, caller, _("bad syntax-spec: `%s'"), spec);
470 return resyntax;
475 * changeresyntax(RESYNTAX-SPEC)
477 M4BUILTIN_HANDLER (changeresyntax)
479 int resyntax = m4_resyntax_encode_safe (context, m4_arg_info (argv),
480 M4ARG (1));
482 if (resyntax >= 0)
483 m4_set_regexp_syntax_opt (context, resyntax);
487 /* Change the current input syntax. The function m4_set_syntax ()
488 lives in syntax.c. Any changes to comment delimiters and quotes
489 made here will be overridden by a call to `changecom' or
490 `changequote'. */
493 * changesyntax(SYNTAX-SPEC, ...)
495 M4BUILTIN_HANDLER (changesyntax)
497 const m4_call_info *me = m4_arg_info (argv);
498 M4_MODULE_IMPORT (m4, m4_expand_ranges);
500 if (m4_expand_ranges)
502 size_t i;
503 for (i = 1; i < argc; i++)
505 const char *spec = M4ARG (i);
506 char key = *spec++;
507 char action = key ? *spec : '\0';
508 switch (action)
510 case '-':
511 case '+':
512 case '=':
513 spec++;
514 break;
515 case '\0':
516 break;
517 default:
518 action = '=';
519 break;
521 if (m4_set_syntax (M4SYNTAX, key, action,
522 key ? m4_expand_ranges (spec, obs) : "") < 0)
523 m4_warn (context, 0, me, _("undefined syntax code: `%c'"),
524 key);
527 else
528 assert (!"Unable to import from m4 module");
532 /* Specify the destination of the debugging output. With one argument, the
533 argument is taken as a file name, with no arguments, revert to stderr. */
536 * debugfile([FILENAME])
538 M4BUILTIN_HANDLER (debugfile)
540 const m4_call_info *me = m4_arg_info (argv);
542 if (argc == 1)
543 m4_debug_set_output (context, me, NULL);
544 else if (m4_get_safer_opt (context) && !m4_arg_empty (argv, 1))
545 m4_error (context, 0, 0, me, _("disabled by --safer"));
546 else if (!m4_debug_set_output (context, me, M4ARG (1)))
547 m4_error (context, 0, errno, me, _("cannot set debug file `%s'"),
548 M4ARG (1));
552 /* On-the-fly control of debug length. It takes one integer
553 argument. */
556 * debuglen(LEN)
558 M4BUILTIN_HANDLER (debuglen)
560 int i;
561 size_t s;
562 if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i))
563 return;
564 /* FIXME - make m4_numeric_arg more powerful - we want to accept
565 suffixes, and limit the result to size_t. */
566 s = i <= 0 ? SIZE_MAX : i;
567 m4_set_max_debug_arg_length_opt (context, s);
570 /* On-the-fly control of the format of the tracing output. It takes one
571 argument, which is a character string like given to the -d option, or
572 none in which case the debug_level is zeroed. */
575 * debugmode([FLAGS])
577 M4BUILTIN_HANDLER (debugmode)
579 int debug_level = m4_get_debug_level_opt (context);
580 int new_debug_level;
582 if (argc == 1)
583 m4_set_debug_level_opt (context, 0);
584 else
586 new_debug_level = m4_debug_decode (context, debug_level, M4ARG (1));
587 if (new_debug_level < 0)
588 m4_error (context, 0, 0, m4_arg_info (argv),
589 _("bad debug flags: `%s'"), M4ARG (1));
590 else
591 m4_set_debug_level_opt (context, new_debug_level);
596 /* Same as the sysymd builtin from m4.c module, but expand to the
597 output of SHELL-COMMAND. */
600 * esyscmd(SHELL-COMMAND)
603 M4BUILTIN_HANDLER (esyscmd)
605 const m4_call_info *me = m4_arg_info (argv);
606 M4_MODULE_IMPORT (m4, m4_set_sysval);
607 M4_MODULE_IMPORT (m4, m4_sysval_flush);
609 if (m4_set_sysval && m4_sysval_flush)
611 FILE *pin;
612 int ch;
614 if (m4_get_safer_opt (context))
616 m4_error (context, 0, 0, me, _("disabled by --safer"));
617 return;
620 /* Optimize the empty command. */
621 if (m4_arg_empty (argv, 1))
623 m4_set_sysval (0);
624 return;
627 m4_sysval_flush (context, false);
628 errno = 0;
629 pin = popen (M4ARG (1), "r");
630 if (pin == NULL)
632 m4_error (context, 0, errno, me,
633 _("cannot open pipe to command `%s'"), M4ARG (1));
634 m4_set_sysval (-1);
636 else
638 while ((ch = getc (pin)) != EOF)
639 obstack_1grow (obs, ch);
640 m4_set_sysval (pclose (pin));
643 else
644 assert (!"Unable to import from m4 module");
648 /* Frontend for printf like formatting. The function format () lives in
649 the file format.c. */
651 #include "format.c"
654 * format(FORMAT-STRING, [...])
656 M4BUILTIN_HANDLER (format)
658 format (context, obs, argc, argv);
662 /* The builtin "indir" allows indirect calls to macros, even if their name
663 is not a proper macro name. It is thus possible to define macros with
664 ill-formed names for internal use in larger macro packages. */
667 * indir(MACRO, [...])
669 M4BUILTIN_HANDLER (indir)
671 const m4_call_info *me = m4_arg_info (argv);
672 if (!m4_is_arg_text (argv, 1))
673 m4_warn (context, 0, me, _("invalid macro name ignored"));
674 else
676 const char *name = M4ARG (1);
677 m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name);
679 if (symbol == NULL)
680 m4_warn (context, 0, me, _("undefined macro `%s'"), name);
681 else
683 m4_macro_args *new_argv;
684 m4_symbol_value *value = m4_get_symbol_value (symbol);
685 new_argv = m4_make_argv_ref (context, argv, name, M4ARGLEN (1),
686 m4_symbol_flatten_args (symbol),
687 m4_get_symbol_traced (symbol));
688 m4_trace_prepare (context, m4_arg_info (new_argv), value);
689 m4_macro_call (context, value, obs, new_argv);
695 /* The builtin "mkdtemp" allows creation of temporary directories. */
698 * mkdtemp(TEMPLATE)
700 M4BUILTIN_HANDLER (mkdtemp)
702 M4_MODULE_IMPORT (m4, m4_make_temp);
704 if (m4_make_temp)
705 m4_make_temp (context, obs, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1),
706 true);
707 else
708 assert (!"Unable to import from m4 module");
712 /* Substitute all matches of a regexp occurring in a string. Each
713 match of the second argument (a regexp) in the first argument is
714 changed to the optional third argument, with \& substituted by the
715 matched text, and \N substituted by the text matched by the Nth
716 parenthesized sub-expression. The optional fourth argument changes
717 the regex flavor. */
720 * patsubst(VICTIM, REGEXP, [REPLACEMENT], [RESYNTAX])
722 M4BUILTIN_HANDLER (patsubst)
724 const m4_call_info *me = m4_arg_info (argv);
725 const char *pattern; /* regular expression */
726 const char *replace; /* replacement */
727 m4_pattern_buffer *buf; /* compiled regular expression */
728 int resyntax;
730 pattern = M4ARG (2);
731 replace = M4ARG (3);
733 resyntax = m4_get_regexp_syntax_opt (context);
734 if (argc >= 5) /* additional args ignored */
736 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (4));
737 if (resyntax < 0)
738 return;
741 /* The empty regex matches everywhere, but if there is no
742 replacement, we need not waste time with it. */
743 if (!*pattern && !*replace)
745 m4_push_arg (context, obs, argv, 1);
746 return;
749 buf = regexp_compile (context, me, pattern, M4ARGLEN (2), resyntax);
750 if (!buf)
751 return;
753 regexp_substitute (context, obs, me, M4ARG (1), M4ARGLEN (1),
754 pattern, buf, replace, false);
758 /* Regular expression version of index. Given two arguments, expand
759 to the index of the first match of the second argument (a regexp)
760 in the first. Expand to -1 if there is no match. Given a third
761 argument, a match is substituted according to this argument. The
762 optional fourth argument changes the regex flavor. */
765 * regexp(VICTIM, REGEXP, RESYNTAX)
766 * regexp(VICTIM, REGEXP, [REPLACEMENT], [RESYNTAX])
768 M4BUILTIN_HANDLER (regexp)
770 const m4_call_info *me = m4_arg_info (argv);
771 const char *victim; /* string to search */
772 const char *pattern; /* regular expression */
773 const char *replace; /* optional replacement string */
774 m4_pattern_buffer *buf; /* compiled regular expression */
775 regoff_t startpos; /* start position of match */
776 size_t len; /* length of first argument */
777 int resyntax;
779 pattern = M4ARG (2);
780 replace = M4ARG (3);
781 resyntax = m4_get_regexp_syntax_opt (context);
783 if (argc == 4)
785 resyntax = m4_regexp_syntax_encode (replace);
787 /* The first case is the most difficult, because the empty string
788 is a valid RESYNTAX, yet we want `regexp(aab, a*, )' to return
789 an empty string as per M4 1.4.x. */
791 if ((*replace == '\0') || (resyntax < 0))
792 /* regexp(VICTIM, REGEXP, REPLACEMENT) */
793 resyntax = m4_get_regexp_syntax_opt (context);
794 else
795 /* regexp(VICTIM, REGEXP, RESYNTAX) */
796 replace = NULL;
798 else if (argc >= 5)
800 /* regexp(VICTIM, REGEXP, REPLACEMENT, RESYNTAX) */
801 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (4));
802 if (resyntax < 0)
803 return;
805 else
806 /* regexp(VICTIM, REGEXP) */
807 replace = NULL;
809 if (!*pattern)
811 /* The empty regex matches everything. */
812 if (replace)
813 substitute (context, obs, me, M4ARG (1), replace, NULL);
814 else
815 m4_shipout_int (obs, 0);
816 return;
819 buf = regexp_compile (context, me, pattern, M4ARGLEN (2), resyntax);
820 if (!buf)
821 return;
823 victim = M4ARG (1);
824 len = M4ARGLEN (1);
825 startpos = regexp_search (buf, victim, len, 0, len, replace == NULL);
827 if (startpos == -2)
829 m4_error (context, 0, 0, me, _("error matching regular expression `%s'"),
830 pattern);
831 return;
834 if (replace == NULL)
835 m4_shipout_int (obs, startpos);
836 else if (startpos >= 0)
837 substitute (context, obs, me, victim, replace, buf);
841 /* Rename all current symbols that match REGEXP according to the
842 REPLACEMENT specification. */
845 * renamesyms(REGEXP, REPLACEMENT, [RESYNTAX])
847 M4BUILTIN_HANDLER (renamesyms)
849 M4_MODULE_IMPORT (m4, m4_dump_symbols);
851 if (m4_dump_symbols)
853 const m4_call_info *me = m4_arg_info (argv);
854 const char *regexp; /* regular expression string */
855 const char *replace; /* replacement expression string */
857 m4_pattern_buffer *buf; /* compiled regular expression */
859 m4_dump_symbol_data data;
861 int resyntax;
863 regexp = M4ARG (1);
864 replace = M4ARG (2);
866 resyntax = m4_get_regexp_syntax_opt (context);
867 if (argc >= 4)
869 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (3));
870 if (resyntax < 0)
871 return;
874 buf = regexp_compile (context, me, regexp, M4ARGLEN (1), resyntax);
875 if (!buf)
876 return;
878 data.obs = m4_arg_scratch (context);
879 m4_dump_symbols (context, &data, 1, argv, false);
881 for (; data.size > 0; --data.size, data.base++)
883 const char *name = data.base[0];
885 if (regexp_substitute (context, data.obs, me, name, strlen (name),
886 regexp, buf, replace, true))
888 obstack_1grow (data.obs, '\0');
889 m4_symbol_rename (M4SYMTAB, name,
890 (char *) obstack_finish (data.obs));
894 else
895 assert (!"Unable to import from m4 module");
899 /* Implementation of "m4symbols". It builds up a table of pointers to
900 symbols, sorts it and ships out the symbol names. */
903 * m4symbols([...])
905 M4BUILTIN_HANDLER (m4symbols)
907 M4_MODULE_IMPORT (m4, m4_dump_symbols);
909 if (m4_dump_symbols)
911 m4_dump_symbol_data data;
913 data.obs = m4_arg_scratch (context);
914 m4_dump_symbols (context, &data, argc, argv, false);
916 for (; data.size > 0; --data.size, data.base++)
918 m4_shipout_string (context, obs, data.base[0], SIZE_MAX, true);
919 if (data.size > 1)
920 obstack_1grow (obs, ',');
923 else
924 assert (!"Unable to import from m4 module");
928 /* This contains macro which implements syncoutput() which takes one arg
929 1, on, yes - turn on sync lines
930 0, off, no, blank - turn off sync lines
931 everything else is silently ignored */
934 * syncoutput(TRUTH)
936 M4BUILTIN_HANDLER (syncoutput)
938 bool value = m4_get_syncoutput_opt (context);
939 value = m4_parse_truth_arg (context, m4_arg_info (argv), M4ARG (1), value);
940 m4_set_syncoutput_opt (context, value);