1 /* GNU m4 -- A simple macro processor
2 Copyright (C) 2000, 2004-2010, 2013-2014, 2017 Free Software
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/>.
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. */
26 # include <m4/m4module.h>
28 # include "m4private.h"
31 #include "modules/m4.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)
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)
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 */
86 { "__unix__", "", 0, 0 },
89 { "__windows__", "", 0, 0 },
92 { "__os2__", "", 0, 0 },
94 { "__gnu__", "", 0, 0 },
95 { "__m4_version__", VERSION
,0, 0 },
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. */
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 */
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 ®ex_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
);
176 m4_warn (context
, 0, caller
, _("bad regular expression %s: %s"),
177 quotearg_style_mem (locale_quoting_style
, regexp
, len
), msg
);
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
;
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
= ®ex_cache
[i
];
200 if (regex_cache
[i
].count
)
201 regex_cache
[i
].count
--;
203 victim
->count
= REGEX_CACHE_SIZE
;
204 victim
->resyntax
= resyntax
;
209 regfree (victim
->pat
);
212 victim
->str
= xstrdup (regexp
);
214 re_set_registers (pat
, &victim
->regs
, victim
->regs
.num_regs
,
215 victim
->regs
.start
, victim
->regs
.end
);
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. */
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
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
)
249 const char *backslash
= (char *) memchr (repl
, '\\', repl_len
);
252 obstack_grow (obs
, repl
, repl_len
);
255 obstack_grow (obs
, repl
, backslash
- repl
);
256 repl_len
-= backslash
- repl
+ 1;
259 m4_warn (context
, 0, caller
,
260 _("trailing \\ ignored in replacement"));
263 repl
= backslash
+ 1;
270 obstack_grow (obs
, victim
+ buf
->regs
.start
[0],
271 buf
->regs
.end
[0] - buf
->regs
.start
[0]);
274 case '1': case '2': case '3': case '4': case '5': case '6':
275 case '7': case '8': case '9':
277 if (!buf
|| buf
->pat
->re_nsub
< ch
)
278 m4_warn (context
, 0, caller
, _("sub-expression %d not present"),
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
]);
286 obstack_1grow (obs
, ch
);
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. */
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
,
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
324 m4_error (context
, 0, 0, caller
,
325 _("problem matching regular expression %s"),
326 quotearg_style_mem (locale_quoting_style
, regexp
,
328 else if (offset
< len
&& subst
)
329 obstack_grow (obs
, victim
+ offset
, len
- offset
);
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
);
343 /* Update the offset to the end of the match. If the regexp
344 matched a null string, advance offset one more, to avoid
347 offset
= buf
->regs
.end
[0];
348 if (buf
->regs
.start
[0] == buf
->regs
.end
[0])
351 obstack_1grow (obs
, victim
[offset
]);
364 M4BUILTIN_HANDLER (__file__
)
366 m4_shipout_string (context
, obs
, m4_get_current_file (context
), SIZE_MAX
,
374 M4BUILTIN_HANDLER (__line__
)
376 m4_shipout_int (obs
, m4_get_current_line (context
));
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
);
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))
414 if (!m4_is_arg_text (argv
, 2))
416 m4_warn (context
, 0, me
, _("invalid macro name ignored"));
421 if (len
== strlen (name
))
422 value
= m4_builtin_find_by_name (context
, NULL
, name
);
425 m4_push_builtin (context
, obs
, 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
));
433 m4_warn (context
, 0, me
, _("invalid macro name ignored"));
439 if (len
== strlen (name
))
440 value
= m4_builtin_find_by_name (context
, NULL
, name
);
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
));
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
,
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
);
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'. */
469 m4_resyntax_encode_safe (m4
*context
, const m4_call_info
*caller
,
470 const char *spec
, size_t len
)
474 if (strlen (spec
) < len
)
477 resyntax
= m4_regexp_syntax_encode (spec
);
480 m4_warn (context
, 0, caller
, _("bad syntax-spec: %s"),
481 quotearg_style_mem (locale_quoting_style
, spec
, len
));
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));
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
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
)
516 for (i
= 1; i
< argc
; i
++)
518 size_t len
= M4ARGLEN (i
);
525 m4_reset_syntax (M4SYNTAX
);
531 action
= len
? *spec
: '\0';
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));
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
);
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"));
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
594 M4BUILTIN_HANDLER (debuglen
)
598 if (!m4_numeric_arg (context
, m4_arg_info (argv
), M4ARG (1), M4ARGLEN (1),
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. */
614 M4BUILTIN_HANDLER (debugmode
)
616 const char* mode
= M4ARG (1);
617 size_t len
= M4ARGLEN (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
)
649 const char *prog_args
[4] = { "sh", "-c" };
652 if (m4_get_safer_opt (context
))
654 m4_error (context
, 0, 0, me
, _("disabled by --safer"));
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. */
668 m4_sysval_flush (context
, false);
670 if (strstr (M4_SYSCMD_SHELL
, "cmd"))
672 prog_args
[0] = "cmd";
677 caller
= m4_info_name (me
);
679 child
= create_pipe_in (caller
, M4_SYSCMD_SHELL
, (char **) prog_args
,
680 NULL
, false, true, false, &fd
);
683 m4_error (context
, 0, errno
, me
, _("cannot run command %s"),
684 quotearg_style (locale_quoting_style
, cmd
));
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");
693 pin
= fdopen (fd
, "r");
697 m4_error (context
, 0, errno
, me
, _("cannot run command %s"),
698 quotearg_style (locale_quoting_style
, cmd
));
705 size_t avail
= obstack_room (obs
);
711 obstack_1grow (obs
, ch
);
715 size_t len
= fread (obstack_next_free (obs
), 1, avail
, pin
);
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
));
726 status
= wait_subprocess (child
, caller
, false, true, true, false,
730 assert (status
== 127);
731 m4_set_sysval (sig_status
<< 8);
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
);
742 assert (!"Unable to import from m4 module");
746 /* Frontend for printf like formatting. The function format () lives in
747 the file 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"));
774 const char *name
= M4ARG (1);
775 size_t len
= M4ARGLEN (1);
776 m4_symbol
*symbol
= m4_symbol_lookup (M4SYMTAB
, name
, len
);
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
));
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. */
803 M4BUILTIN_HANDLER (mkdtemp
)
805 M4_MODULE_IMPORT (m4
, m4_make_temp
);
808 m4_make_temp (context
, obs
, m4_arg_info (argv
), M4ARG (1), M4ARGLEN (1),
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
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 */
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),
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);
853 buf
= regexp_compile (context
, me
, pattern
, M4ARGLEN (2), resyntax
);
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 */
885 resyntax
= m4_get_regexp_syntax_opt (context
);
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
);
899 /* regexp(VICTIM, REGEXP, RESYNTAX) */
904 /* regexp(VICTIM, REGEXP, REPLACEMENT, RESYNTAX) */
905 resyntax
= m4_resyntax_encode_safe (context
, me
, M4ARG (4),
911 /* regexp(VICTIM, REGEXP) */
914 if (m4_arg_empty (argv
, 2))
916 /* The empty regex matches everything. */
918 substitute (context
, obs
, me
, M4ARG (1), replace
, M4ARGLEN (3), NULL
);
920 m4_shipout_int (obs
, 0);
924 buf
= regexp_compile (context
, me
, pattern
, M4ARGLEN (2), resyntax
);
930 startpos
= regexp_search (buf
, victim
, len
, 0, len
, replace
== NULL
);
934 m4_error (context
, 0, 0, me
, _("problem matching regular expression %s"),
935 quotearg_style_mem (locale_quoting_style
, pattern
,
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
);
959 const m4_call_info
*me
= m4_arg_info (argv
);
960 const char *regexp
; /* regular expression string */
962 const char *replace
; /* replacement expression string */
965 m4_pattern_buffer
*buf
; /* compiled regular expression */
967 m4_dump_symbol_data data
;
972 regexp_len
= M4ARGLEN (1);
974 replace_len
= M4ARGLEN (2);
976 resyntax
= m4_get_regexp_syntax_opt (context
);
979 resyntax
= m4_resyntax_encode_safe (context
, me
, M4ARG (3),
985 buf
= regexp_compile (context
, me
, regexp
, regexp_len
, resyntax
);
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
,
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
);
1007 assert (!"Unable to import from m4 module");
1014 M4BUILTIN_HANDLER (m4modules
)
1016 /* The expansion of this builtin is a comma separated list of
1018 m4_module
*module
= m4_module_next (context
, NULL
);
1023 m4_shipout_string (context
, obs
, m4_get_module_name (module
), SIZE_MAX
,
1026 if ((module
= m4_module_next (context
, module
)))
1027 obstack_1grow (obs
, ',');
1033 /* Implementation of "m4symbols". It builds up a table of pointers to
1034 symbols, sorts it and ships out the symbol names. */
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
,
1055 obstack_1grow (obs
, ',');
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 */
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
);