maint: bump copyright year
[m4.git] / modules / gnu.c
blob334ab67dcb24936fddf35aa8574a8ae38a50d824
1 /* GNU m4 -- A simple macro processor
2 Copyright (C) 2000, 2004-2010, 2013-2014, 2017 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"
32 #include "quotearg.h"
33 #include "spawn-pipe.h"
34 #include "wait-process.h"
36 /* Maintain each of the builtins implemented in this modules along
37 with their details in a single table for easy maintenance.
39 function macros blind side minargs maxargs */
40 #define builtin_functions \
41 BUILTIN (__file__, false, false, false, 0, 0 ) \
42 BUILTIN (__line__, false, false, false, 0, 0 ) \
43 BUILTIN (__program__, false, false, false, 0, 0 ) \
44 BUILTIN (builtin, true, true, false, 1, -1 ) \
45 BUILTIN (changeresyntax,false,true, false, 1, 1 ) \
46 BUILTIN (changesyntax,false, true, false, 1, -1 ) \
47 BUILTIN (debugfile, false, false, false, 0, 1 ) \
48 BUILTIN (debuglen, false, true, false, 1, 1 ) \
49 BUILTIN (debugmode, false, false, false, 0, 1 ) \
50 BUILTIN (esyscmd, false, true, true, 1, 1 ) \
51 BUILTIN (format, false, true, false, 1, -1 ) \
52 BUILTIN (indir, true, true, false, 1, -1 ) \
53 BUILTIN (mkdtemp, false, true, false, 1, 1 ) \
54 BUILTIN (patsubst, false, true, true, 2, 4 ) \
55 BUILTIN (regexp, false, true, true, 2, 4 ) \
56 BUILTIN (renamesyms, false, true, false, 2, 3 ) \
57 BUILTIN (m4modules, false, false, false, 0, 0 ) \
58 BUILTIN (m4symbols, true, false, false, 0, -1 ) \
59 BUILTIN (syncoutput, false, true, false, 1, 1 ) \
62 /* Generate prototypes for each builtin handler function. */
63 #define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler)
64 builtin_functions
65 #undef BUILTIN
68 /* Generate a table for mapping m4 symbol names to handler functions. */
69 static const m4_builtin m4_builtin_table[] =
71 #define BUILTIN(handler, macros, blind, side, min, max) \
72 M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
74 builtin_functions
75 #undef BUILTIN
77 { NULL, NULL, 0, 0, 0 },
81 /* A table for mapping m4 symbol names to simple expansion text. */
82 static const m4_macro m4_macro_table[] =
84 /* name text min max */
85 #if UNIX
86 { "__unix__", "", 0, 0 },
87 #endif
88 #if W32_NATIVE
89 { "__windows__", "", 0, 0 },
90 #endif
91 #if OS2
92 { "__os2__", "", 0, 0 },
93 #endif
94 { "__gnu__", "", 0, 0 },
95 { "__m4_version__", VERSION,0, 0 },
97 { NULL, NULL, 0, 0 },
101 void
102 include_gnu (m4 *context, m4_module *module, m4_obstack *obs)
104 m4_install_builtins (context, module, m4_builtin_table);
105 m4_install_macros (context, module, m4_macro_table);
110 /* Regular expressions. Reuse re_registers among multiple
111 re_pattern_buffer allocations to reduce malloc usage. */
113 /* Maybe this is worth making runtime tunable. Too small, and nothing
114 gets cached because the working set of active regex is larger than
115 the cache, and we are always swapping out entries. Too large, and
116 the time spent searching the cache for a match overtakes the time
117 saved by caching. For now, this size proved reasonable for the
118 typical working set of Autoconf 2.62. */
119 #define REGEX_CACHE_SIZE 16
121 /* Structure for using a compiled regex, as well as making it easier
122 to cache frequently used expressions. */
123 typedef struct {
124 unsigned count; /* usage counter */
125 int resyntax; /* flavor of regex */
126 size_t len; /* length of string */
127 char *str; /* copy of compiled string */
128 struct re_pattern_buffer *pat; /* compiled regex, allocated */
129 struct re_registers regs; /* match registers, reused */
130 } m4_pattern_buffer;
132 /* Storage for the cache of regular expressions. */
133 static m4_pattern_buffer regex_cache[REGEX_CACHE_SIZE];
135 /* Compile a REGEXP of length LEN using the RESYNTAX flavor, and
136 return the buffer. On error, report the problem on behalf of
137 CALLER, and return NULL. */
139 static m4_pattern_buffer *
140 regexp_compile (m4 *context, const m4_call_info *caller, const char *regexp,
141 size_t len, int resyntax)
143 /* regex_cache is guaranteed to start life 0-initialized, which
144 works in the algorithm below.
146 FIXME - this method is not reentrant, since re_compile_pattern
147 mallocs memory, depends on the global variable re_syntax_options
148 for its syntax (but at least the compiled regex remembers its
149 syntax even if the global variable changes later), and since we
150 use a static variable. To be reentrant, we would need a mutex in
151 this method, and move the storage for regex_cache into context. */
153 const char *msg; /* error message from re_compile_pattern */
154 int i; /* iterator */
155 m4_pattern_buffer *victim; /* cache slot to replace */
156 unsigned victim_count; /* track which victim to replace */
157 struct re_pattern_buffer *pat;/* newly compiled regex */
159 /* First, check if REGEXP is already cached with the given RESYNTAX.
160 If so, increase its use count and return it. */
161 for (i = 0; i < REGEX_CACHE_SIZE; i++)
162 if (len == regex_cache[i].len && resyntax == regex_cache[i].resyntax
163 && regex_cache[i].str && memcmp (regexp, regex_cache[i].str, len) == 0)
165 regex_cache[i].count++;
166 return &regex_cache[i];
169 /* Next, check if REGEXP can be compiled. */
170 pat = (struct re_pattern_buffer *) xzalloc (sizeof *pat);
171 re_set_syntax (resyntax);
172 msg = re_compile_pattern (regexp, len, pat);
174 if (msg != NULL)
176 m4_warn (context, 0, caller, _("bad regular expression %s: %s"),
177 quotearg_style_mem (locale_quoting_style, regexp, len), msg);
178 regfree (pat);
179 free (pat);
180 return NULL;
182 /* Use a fastmap for speed; it is freed by regfree. */
183 pat->fastmap = xcharalloc (UCHAR_MAX + 1);
185 /* Now, find a victim slot. Decrease the count of all entries, then
186 prime the count of the victim slot at REGEX_CACHE_SIZE. This
187 way, frequently used entries and newly created entries are least
188 likely to be victims next time we have a cache miss. */
189 victim = regex_cache;
190 victim_count = victim->count;
191 if (victim_count)
192 victim->count--;
193 for (i = 1; i < REGEX_CACHE_SIZE; i++)
195 if (regex_cache[i].count < victim_count)
197 victim_count = regex_cache[i].count;
198 victim = &regex_cache[i];
200 if (regex_cache[i].count)
201 regex_cache[i].count--;
203 victim->count = REGEX_CACHE_SIZE;
204 victim->resyntax = resyntax;
205 victim->len = len;
206 if (victim->str)
208 free (victim->str);
209 regfree (victim->pat);
210 free (victim->pat);
212 victim->str = xstrdup (regexp);
213 victim->pat = pat;
214 re_set_registers (pat, &victim->regs, victim->regs.num_regs,
215 victim->regs.start, victim->regs.end);
216 return victim;
220 /* Wrap up GNU Regex re_search call to work with an m4_pattern_buffer.
221 If NO_SUB, then storing matches in buf->regs is not necessary. */
223 static regoff_t
224 regexp_search (m4_pattern_buffer *buf, const char *string, const int size,
225 const int start, const int range, bool no_sub)
227 return re_search (buf->pat, string, size, start, range,
228 no_sub ? NULL : &buf->regs);
232 /* Function to perform substitution by regular expressions. Used by
233 the builtins regexp, patsubst and renamesyms. The changed text is
234 placed on the obstack OBS. The substitution is REPL of length
235 REPL_LEN, with \& substituted by this part of VICTIM matched by the
236 last whole regular expression, and \N substituted by the text
237 matched by the Nth parenthesized sub-expression in BUF. Any
238 warnings are issued on behalf of CALLER. BUF may be NULL for the
239 empty regex. */
241 static void
242 substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller,
243 const char *victim, const char *repl, size_t repl_len,
244 m4_pattern_buffer *buf)
246 int ch;
247 while (1)
249 const char *backslash = (char *) memchr (repl, '\\', repl_len);
250 if (!backslash)
252 obstack_grow (obs, repl, repl_len);
253 return;
255 obstack_grow (obs, repl, backslash - repl);
256 repl_len -= backslash - repl + 1;
257 if (!repl_len)
259 m4_warn (context, 0, caller,
260 _("trailing \\ ignored in replacement"));
261 return;
263 repl = backslash + 1;
264 ch = *repl++;
265 repl_len--;
266 switch (ch)
268 case '&':
269 if (buf)
270 obstack_grow (obs, victim + buf->regs.start[0],
271 buf->regs.end[0] - buf->regs.start[0]);
272 break;
274 case '1': case '2': case '3': case '4': case '5': case '6':
275 case '7': case '8': case '9':
276 ch -= '0';
277 if (!buf || buf->pat->re_nsub < ch)
278 m4_warn (context, 0, caller, _("sub-expression %d not present"),
279 ch);
280 else if (buf->regs.end[ch] > 0)
281 obstack_grow (obs, victim + buf->regs.start[ch],
282 buf->regs.end[ch] - buf->regs.start[ch]);
283 break;
285 default:
286 obstack_1grow (obs, ch);
287 break;
293 /* For each match against REGEXP of length REGEXP_LEN (precompiled in
294 BUF as returned by regexp_compile) in VICTIM of length LEN,
295 substitute REPLACE of length REPL_LEN. Non-matching characters are
296 copied verbatim, and the result copied to the obstack. Errors are
297 reported on behalf of CALLER. Return true if a substitution was
298 made. If OPTIMIZE is set, don't worry about copying the input if
299 no changes are made. */
301 static bool
302 regexp_substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller,
303 const char *victim, size_t len, const char *regexp,
304 size_t regexp_len, m4_pattern_buffer *buf,
305 const char *replace, size_t repl_len, bool optimize)
307 regoff_t matchpos = 0; /* start position of match */
308 size_t offset = 0; /* current match offset */
309 bool subst = !optimize; /* if a substitution has been made */
311 while (offset <= len)
313 matchpos = regexp_search (buf, victim, len, offset, len - offset,
314 false);
316 if (matchpos < 0)
319 /* Match failed -- either error or there is no match in the
320 rest of the string, in which case the rest of the string is
321 copied verbatim. */
323 if (matchpos == -2)
324 m4_error (context, 0, 0, caller,
325 _("problem matching regular expression %s"),
326 quotearg_style_mem (locale_quoting_style, regexp,
327 regexp_len));
328 else if (offset < len && subst)
329 obstack_grow (obs, victim + offset, len - offset);
330 break;
333 /* Copy the part of the string that was skipped by re_search (). */
335 if (matchpos > offset)
336 obstack_grow (obs, victim + offset, matchpos - offset);
338 /* Handle the part of the string that was covered by the match. */
340 substitute (context, obs, caller, victim, replace, repl_len, buf);
341 subst = true;
343 /* Update the offset to the end of the match. If the regexp
344 matched a null string, advance offset one more, to avoid
345 infinite loops. */
347 offset = buf->regs.end[0];
348 if (buf->regs.start[0] == buf->regs.end[0])
350 if (offset < len)
351 obstack_1grow (obs, victim[offset]);
352 offset++;
356 return subst;
362 * __file__
364 M4BUILTIN_HANDLER (__file__)
366 m4_shipout_string (context, obs, m4_get_current_file (context), SIZE_MAX,
367 true);
372 * __line__
374 M4BUILTIN_HANDLER (__line__)
376 m4_shipout_int (obs, m4_get_current_line (context));
381 * __program__
383 M4BUILTIN_HANDLER (__program__)
385 m4_shipout_string (context, obs, m4_get_program_name (), SIZE_MAX, true);
389 /* The builtin "builtin" allows calls to builtin macros, even if their
390 definition has been overridden or shadowed. It is thus possible to
391 redefine builtins, and still access their original definition. A
392 special form allows one to retrieve the special token that defn
393 would normally return, even if that builtin is not currently
394 defined and hence can't be passed to defn. */
397 * builtin(MACRO, [...])
398 * builtin(defn(`builtin'), MACRO)
400 M4BUILTIN_HANDLER (builtin)
402 const m4_call_info *me = m4_arg_info (argv);
403 const char *name;
404 size_t len;
405 m4_symbol_value *value = NULL;
407 if (!m4_is_arg_text (argv, 1))
409 assert (m4_is_arg_func (argv, 1));
410 if (m4_arg_func (argv, 1) == builtin_builtin)
412 if (m4_bad_argc (context, argc, me, 2, 2, false))
413 return;
414 if (!m4_is_arg_text (argv, 2))
416 m4_warn (context, 0, me, _("invalid macro name ignored"));
417 return;
419 name = M4ARG (2);
420 len = M4ARGLEN (2);
421 if (len == strlen (name))
422 value = m4_builtin_find_by_name (context, NULL, name);
423 if (value)
425 m4_push_builtin (context, obs, value);
426 free (value);
428 else if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
429 m4_warn (context, 0, me, _("undefined builtin %s"),
430 quotearg_style_mem (locale_quoting_style, name, len));
432 else
433 m4_warn (context, 0, me, _("invalid macro name ignored"));
435 else
437 name = M4ARG (1);
438 len = M4ARGLEN (1);
439 if (len == strlen (name))
440 value = m4_builtin_find_by_name (context, NULL, name);
441 if (value == NULL)
443 if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
444 m4_warn (context, 0, me, _("undefined builtin %s"),
445 quotearg_style_mem (locale_quoting_style, name, len));
447 else
449 const m4_builtin *bp = m4_get_symbol_value_builtin (value);
450 m4_macro_args *new_argv;
451 bool flatten = (bp->flags & M4_BUILTIN_FLATTEN_ARGS) != 0;
452 new_argv = m4_make_argv_ref (context, argv, name, len, flatten,
453 false);
454 if (!m4_bad_argc (context, argc - 1, m4_arg_info (new_argv),
455 bp->min_args, bp->max_args,
456 (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
457 bp->func (context, obs, argc - 1, new_argv);
458 free (value);
464 /* Change the current regexp syntax to SPEC of length LEN, or report
465 failure on behalf of CALLER. Currently this affects the builtins:
466 `patsubst', `regexp' and `renamesyms'. */
468 static int
469 m4_resyntax_encode_safe (m4 *context, const m4_call_info *caller,
470 const char *spec, size_t len)
472 int resyntax;
474 if (strlen (spec) < len)
475 resyntax = -1;
476 else
477 resyntax = m4_regexp_syntax_encode (spec);
479 if (resyntax < 0)
480 m4_warn (context, 0, caller, _("bad syntax-spec: %s"),
481 quotearg_style_mem (locale_quoting_style, spec, len));
483 return resyntax;
488 * changeresyntax(RESYNTAX-SPEC)
490 M4BUILTIN_HANDLER (changeresyntax)
492 int resyntax = m4_resyntax_encode_safe (context, m4_arg_info (argv),
493 M4ARG (1), M4ARGLEN (1));
495 if (resyntax >= 0)
496 m4_set_regexp_syntax_opt (context, resyntax);
500 /* Change the current input syntax. The function m4_set_syntax ()
501 lives in syntax.c. Any changes to comment delimiters and quotes
502 made here will be overridden by a call to `changecom' or
503 `changequote'. */
506 * changesyntax(SYNTAX-SPEC, ...)
508 M4BUILTIN_HANDLER (changesyntax)
510 const m4_call_info *me = m4_arg_info (argv);
511 M4_MODULE_IMPORT (m4, m4_expand_ranges);
513 if (m4_expand_ranges)
515 size_t i;
516 for (i = 1; i < argc; i++)
518 size_t len = M4ARGLEN (i);
519 const char *spec;
520 char key;
521 char action;
523 if (!len)
525 m4_reset_syntax (M4SYNTAX);
526 continue;
528 spec = M4ARG (i);
529 key = *spec++;
530 len--;
531 action = len ? *spec : '\0';
532 switch (action)
534 case '-':
535 case '+':
536 case '=':
537 spec++;
538 len--;
539 break;
540 case '\0':
541 if (!len)
542 break;
543 /* fall through */
544 default:
545 action = '=';
546 break;
548 if (len)
549 spec = m4_expand_ranges (spec, &len, m4_arg_scratch (context));
550 if (m4_set_syntax (M4SYNTAX, key, action, spec, len) < 0)
551 m4_warn (context, 0, me, _("undefined syntax code: %s"),
552 quotearg_style_mem (locale_quoting_style, &key, 1));
555 else
556 assert (!"Unable to import from m4 module");
560 /* Specify the destination of the debugging output. With one argument, the
561 argument is taken as a file name, with no arguments, revert to stderr. */
564 * debugfile([FILENAME])
566 M4BUILTIN_HANDLER (debugfile)
568 const m4_call_info *me = m4_arg_info (argv);
570 if (argc == 1)
571 m4_debug_set_output (context, me, NULL);
572 else if (m4_get_safer_opt (context) && !m4_arg_empty (argv, 1))
573 m4_error (context, 0, 0, me, _("disabled by --safer"));
574 else
576 const char *str = M4ARG (1);
577 size_t len = M4ARGLEN (1);
578 if (strlen (str) < len)
579 m4_warn (context, 0, me, _("argument %s truncated"),
580 quotearg_style_mem (locale_quoting_style, str, len));
581 if (!m4_debug_set_output (context, me, str))
582 m4_warn (context, errno, me, _("cannot set debug file %s"),
583 quotearg_style (locale_quoting_style, str));
588 /* On-the-fly control of debug length. It takes one integer
589 argument. */
592 * debuglen(LEN)
594 M4BUILTIN_HANDLER (debuglen)
596 int i;
597 size_t s;
598 if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1),
599 &i))
600 return;
601 /* FIXME - make m4_numeric_arg more powerful - we want to accept
602 suffixes, and limit the result to size_t. */
603 s = i <= 0 ? SIZE_MAX : i;
604 m4_set_max_debug_arg_length_opt (context, s);
607 /* On-the-fly control of the format of the tracing output. It takes one
608 argument, which is a character string like given to the -d option, or
609 none in which case the debug_level is zeroed. */
612 * debugmode([FLAGS])
614 M4BUILTIN_HANDLER (debugmode)
616 const char* mode = M4ARG (1);
617 size_t len = M4ARGLEN (1);
618 if (argc == 1)
619 m4_set_debug_level_opt (context, 0);
620 else if (m4_debug_decode (context, mode, len) < 0)
621 m4_warn (context, 0, m4_arg_info (argv),
622 _("bad debug flags: %s"),
623 quotearg_style_mem (locale_quoting_style, mode, len));
627 /* Same as the sysymd builtin from m4.c module, but expand to the
628 output of SHELL-COMMAND. */
631 * esyscmd(SHELL-COMMAND)
634 M4BUILTIN_HANDLER (esyscmd)
636 const m4_call_info *me = m4_arg_info (argv);
637 const char *cmd = M4ARG (1);
638 size_t len = M4ARGLEN (1);
639 M4_MODULE_IMPORT (m4, m4_set_sysval);
640 M4_MODULE_IMPORT (m4, m4_sysval_flush);
642 if (m4_set_sysval && m4_sysval_flush)
644 pid_t child;
645 int fd;
646 FILE *pin;
647 int status;
648 int sig_status;
649 const char *prog_args[4] = { "sh", "-c" };
650 const char *caller;
652 if (m4_get_safer_opt (context))
654 m4_error (context, 0, 0, me, _("disabled by --safer"));
655 return;
657 if (strlen (cmd) != len)
658 m4_warn (context, 0, me, _("argument %s truncated"),
659 quotearg_style_mem (locale_quoting_style, cmd, len));
661 /* Optimize the empty command. */
662 if (!*cmd)
664 m4_set_sysval (0);
665 return;
668 m4_sysval_flush (context, false);
669 #if W32_NATIVE
670 if (strstr (M4_SYSCMD_SHELL, "cmd"))
672 prog_args[0] = "cmd";
673 prog_args[1] = "/c";
675 #endif
676 prog_args[2] = cmd;
677 caller = m4_info_name (me);
678 errno = 0;
679 child = create_pipe_in (caller, M4_SYSCMD_SHELL, (char **) prog_args,
680 NULL, false, true, false, &fd);
681 if (child == -1)
683 m4_error (context, 0, errno, me, _("cannot run command %s"),
684 quotearg_style (locale_quoting_style, cmd));
685 m4_set_sysval (127);
686 return;
688 #if OS2
689 /* On OS/2 kLIBC, fdopen() creates a stream in a mode of a file
690 descriptor. So incldue "t" to open stream in a text mode explicitly. */
691 pin = fdopen (fd, "rt");
692 #else
693 pin = fdopen (fd, "r");
694 #endif
695 if (!pin)
697 m4_error (context, 0, errno, me, _("cannot run command %s"),
698 quotearg_style (locale_quoting_style, cmd));
699 m4_set_sysval (127);
700 close (fd);
701 return;
703 while (1)
705 size_t avail = obstack_room (obs);
706 if (!avail)
708 int ch = getc (pin);
709 if (ch == EOF)
710 break;
711 obstack_1grow (obs, ch);
713 else
715 size_t len = fread (obstack_next_free (obs), 1, avail, pin);
716 if (len <= 0)
717 break;
718 obstack_blank_fast (obs, len);
721 if (ferror (pin) || fclose (pin))
722 m4_error (context, EXIT_FAILURE, errno, me,
723 _("cannot read pipe to command %s"),
724 quotearg_style (locale_quoting_style, cmd));
725 errno = 0;
726 status = wait_subprocess (child, caller, false, true, true, false,
727 &sig_status);
728 if (sig_status)
730 assert (status == 127);
731 m4_set_sysval (sig_status << 8);
733 else
735 if (status == 127 && errno)
736 m4_error (context, 0, errno, me, _("cannot run command %s"),
737 quotearg_style (locale_quoting_style, cmd));
738 m4_set_sysval (status);
741 else
742 assert (!"Unable to import from m4 module");
746 /* Frontend for printf like formatting. The function format () lives in
747 the file format.c. */
749 #include "format.c"
752 * format(FORMAT-STRING, [...])
754 M4BUILTIN_HANDLER (format)
756 format (context, obs, argc, argv);
760 /* The builtin "indir" allows indirect calls to macros, even if their name
761 is not a proper macro name. It is thus possible to define macros with
762 ill-formed names for internal use in larger macro packages. */
765 * indir(MACRO, [...])
767 M4BUILTIN_HANDLER (indir)
769 const m4_call_info *me = m4_arg_info (argv);
770 if (!m4_is_arg_text (argv, 1))
771 m4_warn (context, 0, me, _("invalid macro name ignored"));
772 else
774 const char *name = M4ARG (1);
775 size_t len = M4ARGLEN (1);
776 m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name, len);
778 if (symbol == NULL)
780 if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
781 m4_warn (context, 0, me, _("undefined macro %s"),
782 quotearg_style_mem (locale_quoting_style, name, len));
784 else
786 m4_macro_args *new_argv;
787 m4_symbol_value *value = m4_get_symbol_value (symbol);
788 new_argv = m4_make_argv_ref (context, argv, name, len,
789 m4_symbol_flatten_args (symbol),
790 m4_get_symbol_traced (symbol));
791 m4_trace_prepare (context, m4_arg_info (new_argv), value);
792 m4_macro_call (context, value, obs, new_argv);
798 /* The builtin "mkdtemp" allows creation of temporary directories. */
801 * mkdtemp(TEMPLATE)
803 M4BUILTIN_HANDLER (mkdtemp)
805 M4_MODULE_IMPORT (m4, m4_make_temp);
807 if (m4_make_temp)
808 m4_make_temp (context, obs, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1),
809 true);
810 else
811 assert (!"Unable to import from m4 module");
815 /* Substitute all matches of a regexp occurring in a string. Each
816 match of the second argument (a regexp) in the first argument is
817 changed to the optional third argument, with \& substituted by the
818 matched text, and \N substituted by the text matched by the Nth
819 parenthesized sub-expression. The optional fourth argument changes
820 the regex flavor. */
823 * patsubst(VICTIM, REGEXP, [REPLACEMENT], [RESYNTAX])
825 M4BUILTIN_HANDLER (patsubst)
827 const m4_call_info *me = m4_arg_info (argv);
828 const char *pattern; /* regular expression */
829 const char *replace; /* replacement */
830 m4_pattern_buffer *buf; /* compiled regular expression */
831 int resyntax;
833 resyntax = m4_get_regexp_syntax_opt (context);
834 if (argc >= 5) /* additional args ignored */
836 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (4),
837 M4ARGLEN (4));
838 if (resyntax < 0)
839 return;
842 /* The empty regex matches everywhere, but if there is no
843 replacement, we need not waste time with it. */
844 if (m4_arg_empty (argv, 2) && m4_arg_empty (argv, 3))
846 m4_push_arg (context, obs, argv, 1);
847 return;
850 pattern = M4ARG (2);
851 replace = M4ARG (3);
853 buf = regexp_compile (context, me, pattern, M4ARGLEN (2), resyntax);
854 if (!buf)
855 return;
857 regexp_substitute (context, obs, me, M4ARG (1), M4ARGLEN (1), pattern,
858 M4ARGLEN (2), buf, replace, M4ARGLEN (3), false);
862 /* Regular expression version of index. Given two arguments, expand
863 to the index of the first match of the second argument (a regexp)
864 in the first. Expand to -1 if there is no match. Given a third
865 argument, a match is substituted according to this argument. The
866 optional fourth argument changes the regex flavor. */
869 * regexp(VICTIM, REGEXP, RESYNTAX)
870 * regexp(VICTIM, REGEXP, [REPLACEMENT], [RESYNTAX])
872 M4BUILTIN_HANDLER (regexp)
874 const m4_call_info *me = m4_arg_info (argv);
875 const char *victim; /* string to search */
876 const char *pattern; /* regular expression */
877 const char *replace; /* optional replacement string */
878 m4_pattern_buffer *buf; /* compiled regular expression */
879 regoff_t startpos; /* start position of match */
880 size_t len; /* length of first argument */
881 int resyntax;
883 pattern = M4ARG (2);
884 replace = M4ARG (3);
885 resyntax = m4_get_regexp_syntax_opt (context);
887 if (argc == 4)
889 resyntax = m4_regexp_syntax_encode (replace);
891 /* The first case is the most difficult, because the empty string
892 is a valid RESYNTAX, yet we want `regexp(aab, a*, )' to return
893 an empty string as per M4 1.4.x. */
895 if (m4_arg_empty (argv, 3) || (resyntax < 0))
896 /* regexp(VICTIM, REGEXP, REPLACEMENT) */
897 resyntax = m4_get_regexp_syntax_opt (context);
898 else
899 /* regexp(VICTIM, REGEXP, RESYNTAX) */
900 replace = NULL;
902 else if (argc >= 5)
904 /* regexp(VICTIM, REGEXP, REPLACEMENT, RESYNTAX) */
905 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (4),
906 M4ARGLEN (4));
907 if (resyntax < 0)
908 return;
910 else
911 /* regexp(VICTIM, REGEXP) */
912 replace = NULL;
914 if (m4_arg_empty (argv, 2))
916 /* The empty regex matches everything. */
917 if (replace)
918 substitute (context, obs, me, M4ARG (1), replace, M4ARGLEN (3), NULL);
919 else
920 m4_shipout_int (obs, 0);
921 return;
924 buf = regexp_compile (context, me, pattern, M4ARGLEN (2), resyntax);
925 if (!buf)
926 return;
928 victim = M4ARG (1);
929 len = M4ARGLEN (1);
930 startpos = regexp_search (buf, victim, len, 0, len, replace == NULL);
932 if (startpos == -2)
934 m4_error (context, 0, 0, me, _("problem matching regular expression %s"),
935 quotearg_style_mem (locale_quoting_style, pattern,
936 M4ARGLEN (2)));
937 return;
940 if (replace == NULL)
941 m4_shipout_int (obs, startpos);
942 else if (startpos >= 0)
943 substitute (context, obs, me, victim, replace, M4ARGLEN (3), buf);
947 /* Rename all current symbols that match REGEXP according to the
948 REPLACEMENT specification. */
951 * renamesyms(REGEXP, REPLACEMENT, [RESYNTAX])
953 M4BUILTIN_HANDLER (renamesyms)
955 M4_MODULE_IMPORT (m4, m4_dump_symbols);
957 if (m4_dump_symbols)
959 const m4_call_info *me = m4_arg_info (argv);
960 const char *regexp; /* regular expression string */
961 size_t regexp_len;
962 const char *replace; /* replacement expression string */
963 size_t replace_len;
965 m4_pattern_buffer *buf; /* compiled regular expression */
967 m4_dump_symbol_data data;
969 int resyntax;
971 regexp = M4ARG (1);
972 regexp_len = M4ARGLEN (1);
973 replace = M4ARG (2);
974 replace_len = M4ARGLEN (2);
976 resyntax = m4_get_regexp_syntax_opt (context);
977 if (argc >= 4)
979 resyntax = m4_resyntax_encode_safe (context, me, M4ARG (3),
980 M4ARGLEN (3));
981 if (resyntax < 0)
982 return;
985 buf = regexp_compile (context, me, regexp, regexp_len, resyntax);
986 if (!buf)
987 return;
989 data.obs = m4_arg_scratch (context);
990 m4_dump_symbols (context, &data, 1, argv, false);
992 for (; data.size > 0; --data.size, data.base++)
994 const m4_string *key = &data.base[0];
996 if (regexp_substitute (context, data.obs, me, key->str, key->len,
997 regexp, regexp_len, buf, replace, replace_len,
998 true))
1000 size_t newlen = obstack_object_size (data.obs);
1001 m4_symbol_rename (M4SYMTAB, key->str, key->len,
1002 (char *) obstack_finish (data.obs), newlen);
1006 else
1007 assert (!"Unable to import from m4 module");
1012 * m4modules()
1014 M4BUILTIN_HANDLER (m4modules)
1016 /* The expansion of this builtin is a comma separated list of
1017 loaded modules. */
1018 m4_module *module = m4_module_next (context, NULL);
1020 if (module)
1023 m4_shipout_string (context, obs, m4_get_module_name (module), SIZE_MAX,
1024 true);
1026 if ((module = m4_module_next (context, module)))
1027 obstack_1grow (obs, ',');
1029 while (module);
1033 /* Implementation of "m4symbols". It builds up a table of pointers to
1034 symbols, sorts it and ships out the symbol names. */
1037 * m4symbols([...])
1039 M4BUILTIN_HANDLER (m4symbols)
1041 M4_MODULE_IMPORT (m4, m4_dump_symbols);
1043 if (m4_dump_symbols)
1045 m4_dump_symbol_data data;
1047 data.obs = m4_arg_scratch (context);
1048 m4_dump_symbols (context, &data, argc, argv, false);
1050 for (; data.size > 0; --data.size, data.base++)
1052 m4_shipout_string (context, obs, data.base->str, data.base->len,
1053 true);
1054 if (data.size > 1)
1055 obstack_1grow (obs, ',');
1058 else
1059 assert (!"Unable to import from m4 module");
1063 /* This contains macro which implements syncoutput() which takes one arg
1064 1, on, yes - turn on sync lines
1065 0, off, no, blank - turn off sync lines
1066 everything else is silently ignored */
1069 * syncoutput(TRUTH)
1071 M4BUILTIN_HANDLER (syncoutput)
1073 bool value = m4_get_syncoutput_opt (context);
1074 value = m4_parse_truth_arg (context, m4_arg_info (argv), M4ARG (1),
1075 M4ARGLEN (1), value);
1076 m4_set_syncoutput_opt (context, value);