diff options
author | Eric Blake <ebb9@byu.net> | 2009-01-07 07:21:35 -0700 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2009-01-07 14:12:13 -0700 |
commit | 6502f317d49a62e0fffca97793bf923cf7897918 (patch) | |
tree | c616c6317c460cfd4d94185bfb92f1276e97359a | |
parent | ae9dfa87a514d290fe349710a9f643d52856f4ba (diff) | |
download | m4-6502f317d49a62e0fffca97793bf923cf7897918.tar.gz |
Enhance substr to support replacement text.
* doc/m4.texinfo (Substr): Document new semantics.
* modules/m4.c (substr): Support optional fourth argument.
* NEWS: Document this.
Signed-off-by: Eric Blake <ebb9@byu.net>
(cherry picked from commit 59d3cfafa8d73e43a974bc066722cd6220cb479f)
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | doc/m4.texinfo | 34 | ||||
-rw-r--r-- | modules/m4.c | 26 |
4 files changed, 62 insertions, 6 deletions
@@ -1,5 +1,10 @@ 2009-01-07 Eric Blake <ebb9@byu.net> + Enhance substr to support replacement text. + * doc/m4.texinfo (Substr): Document new semantics. + * modules/m4.c (substr): Support optional fourth argument. + * NEWS: Document this. + Enhance substr to support negative values. * doc/m4.texinfo (Substr): Document new semantics, and how to simulate old. @@ -243,7 +243,8 @@ promoted to 2.0. macro. It has also been optimized for faster performance. ** The `substr' builtin now treats negative arguments as indices relative - to the end of the string. The manual gives an + to the end of the string, and accepts an optional fourth argument of + text to supply in place of the selected substring. The manual gives an example of how to recover M4 1.4.x behavior, as well as an example of simulating the new negative argument semantics with older M4. diff --git a/doc/m4.texinfo b/doc/m4.texinfo index 6b515cfd..fbe42f2c 100644 --- a/doc/m4.texinfo +++ b/doc/m4.texinfo @@ -7011,7 +7011,8 @@ regexp(`GNUs not Unix', `\w\(\w+\)$', `POSIX_EXTENDED', `') @cindex substrings, extracting Substrings are extracted with @code{substr}: -@deffn {Builtin (m4)} substr (@var{string}, @var{from}, @ovar{length}) +@deffn {Builtin (m4)} substr (@var{string}, @var{from}, @ovar{length}, @ + @ovar{replace}) Performs a substring operation on @var{string}. If @var{from} is positive, it represents the 0-based index where the substring begins. If @var{length} is omitted, the substring ends at the end of @@ -7030,9 +7031,13 @@ of @var{string} that overlap the selected indices. If the end point lies before the beginning point, the substring chosen is the empty string located at the starting index. -The expansion is the selected substring, which may be empty. The +If @var{replace} is omitted, then the expansion is only the selected +substring, which may be empty. As a @acronym{GNU} extension,if +@var{replace} is provided, then the expansion is the original +@var{string} with the selected substring replaced by @var{replace}. The expansion is empty and a warning issued if @var{from} or @var{length} -cannot be parsed. +cannot be parsed, or if @var{replace} is provided but the selected +indices do not overlap with @var{string}. The macro @code{substr} is recognized only with parameters. @end deffn @@ -7091,6 +7096,29 @@ substr(`abcdefghij', `-09', `08') @result{}bcdefghi @end example +Another useful @acronym{GNU} extension, also added in M4 1.6, is the +ability to replace a substring within the original @var{string}. An +empty length substring at the beginning or end of @var{string} is valid, +but selecting a substring that does not overlap @var{string} causes a +warning. + +@example +substr(`abcde', `1', `3', `t') +@result{}ate +substr(`abcde', `5', `', `f') +@result{}abcdef +substr(`abcde', `-3', `-4', `f') +@result{}abfcde +substr(`abcde', `-6', `1', `f') +@result{}fabcde +substr(`abcde', `-7', `1', `f') +@error{}m4:stdin:5: Warning: substr: substring out of range +@result{} +substr(`abcde', `6', `', `f') +@error{}m4:stdin:6: Warning: substr: substring out of range +@result{} +@end example + If backwards compabitility to M4 1.4.x behavior is necessary, the following macro is sufficient to do the job (mimicking warnings about empty @var{from} or @var{length} or an ignored fourth argument is left diff --git a/modules/m4.c b/modules/m4.c index b09510c8..b7d23d04 100644 --- a/modules/m4.c +++ b/modules/m4.c @@ -86,7 +86,7 @@ extern void m4_make_temp (m4 *, m4_obstack *, const m4_call_info *, BUILTIN (pushdef, true, true, false, 1, 2 ) \ BUILTIN (shift, true, true, false, 1, -1 ) \ BUILTIN (sinclude, false, true, false, 1, 1 ) \ - BUILTIN (substr, false, true, true, 2, 3 ) \ + BUILTIN (substr, false, true, true, 2, 4 ) \ BUILTIN (syscmd, false, true, true, 1, 1 ) \ BUILTIN (sysval, false, false, false, 0, 0 ) \ BUILTIN (traceoff, true, false, false, 0, -1 ) \ @@ -929,7 +929,9 @@ M4BUILTIN_HANDLER (index) a length given by the third argument. If the third argument is missing or empty, the substring extends to the end of the first argument. As an extension, negative arguments are treated as - indices relative to the string length. */ + indices relative to the string length. Also, if a fourth argument + is supplied, the original string is output with the selected + substring replaced by the argument. */ M4BUILTIN_HANDLER (substr) { const m4_call_info *me = m4_arg_info (argv); @@ -963,6 +965,26 @@ M4BUILTIN_HANDLER (substr) end += start; } + if (5 <= argc) + { + /* Replacement text provided. */ + if (end < start) + end = start; + if (end < 0 || length < start) + { + m4_warn (context, 0, me, _("substring out of range")); + return; + } + if (start < 0) + start = 0; + if (length < end) + end = length; + obstack_grow (obs, str, start); + m4_push_arg (context, obs, argv, 4); + obstack_grow (obs, str + end, length - end); + return; + } + if (start < 0) start = 0; if (length < end) |