-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 After my recent enhancement to substr, I noticed that index could also be made more useful if it took an optional starting index. For example:
index(`a(`b', `b')', `b', `4') is much different than index(eval(4 + substr(`a(`b', `b')', 4))) because of the interference caused by splitting nested quotes in substr. Technically, regexp could also be made more useful with a starting index, but I don't see how to add that in without breaking backwards compatibility (since regexp already has an optional argument that changes whether the result is the index where the match was found, vs. a substitution pattern using the matched pattern). I'm committing this to branch-1.6 and master: - -- Don't work too hard, make some time for fun as well! Eric Blake [email protected] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkmRfrcACgkQ84KuGfSFAYCz4gCfcQEmCKKjykGxsc4IW6VrD3Oi WroAoNWSoTz4AVoXk8WfO+/k504HRwvX =9Z4d -----END PGP SIGNATURE-----
>From b9c165b394c06d2da657caae33efd5843689ff3b Mon Sep 17 00:00:00 2001 From: Eric Blake <[email protected]> Date: Mon, 9 Feb 2009 06:16:28 -0700 Subject: [PATCH] Enhance index to support starting offset. * src/builtin.c (m4_index): Add optional third argument. * NEWS: Document this. * doc/m4.texinfo (Index macro): Likewise. (Macro Arguments): Adjust tests. Signed-off-by: Eric Blake <[email protected]> --- ChangeLog | 8 ++++++++ NEWS | 4 ++++ doc/m4.texinfo | 29 ++++++++++++++++++++++++----- src/builtin.c | 30 ++++++++++++++++++++++++------ 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5763258..b96dccc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-02-09 Eric Blake <[email protected]> + + Enhance index to support starting offset. + * src/builtin.c (m4_index): Add optional third argument. + * NEWS: Document this. + * doc/m4.texinfo (Index macro): Likewise. + (Macro Arguments): Adjust tests. + 2009-01-24 Eric Blake <[email protected]> Add URLs to --help output. diff --git a/NEWS b/NEWS index cbea814..bfcb684 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,10 @@ Software Foundation, Inc. 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. +** The `index' builtin now takes an optional third argument as the index + to begin searching from, with a negative argument relative to the end of + the string. + ** The `-d'/`--debug' command-line option now understands `-' and `+' modifiers, the way the builtin `debugmode' has always done; this allows `-d-V' to disable prior debug settings from the command line, similar to diff --git a/doc/m4.texinfo b/doc/m4.texinfo index 37600c4..8341cc9 100644 --- a/doc/m4.texinfo +++ b/doc/m4.texinfo @@ -1648,8 +1648,8 @@ Macro Arguments @result{}0 index(`abc',) @result{}0 -index(`abc', `b', `ignored') -...@error{}m4:stdin:3: Warning: index: extra arguments ignored: 3 > 2 +index(`abc', `b', `0', `ignored') +...@error{}m4:stdin:3: Warning: index: extra arguments ignored: 4 > 3 @result{}1 @end example @@ -1660,7 +1660,7 @@ Macro Arguments @result{}0 index(`abc',) @result{}0 -index(`abc', `b', `ignored') +index(`abc', `b', `', `ignored') @result{}1 @end example @@ -6113,11 +6113,13 @@ Index macro @cindex substrings, locating Searching for substrings is done with @code{index}: -...@deffn Builtin index (@var{string}, @var{substring}) +...@deffn Builtin index (@var{string}, @var{substring}, @ovar{offset}) Expands to the index of the first occurrence of @var{substring} in @var{string}. The first character in @var{string} has index 0. If @var{substring} does not occur in @var{string}, @code{index} expands to -...@samp{-1}. +...@samp{-1}. If @var{offset} is provided, it determines the index at +which the search starts; a negative @var{offset} specifies the offset +relative to the end of @var{string}. The macro @code{index} is recognized only with parameters. @end deffn @@ -6142,6 +6144,23 @@ Index macro @result{}1 @end example +...@cindex @acronym{GNU} extensions +As an extension, an @var{offset} can be provided to limit the search to +the tail of the @var{string}. A negative offset is interpreted relative +to the end of @var{string}, and it is not an error if @var{offset} +exceeds the bounds of @var{string}. + +...@example +index(`aba', `a', `1') +...@result{}2 +index(`ababa', `ba', `-3') +...@result{}3 +index(`abc', `a', `4') +...@result{}-1 +index(`abc', `bc', `-4') +...@result{}1 +...@end example + @node Regexp @section Searching for regular expressions diff --git a/src/builtin.c b/src/builtin.c index 6594cb9..a398fdb 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -1828,20 +1828,23 @@ m4_len (struct obstack *obs, int argc, macro_arguments *argv) shipout_int (obs, ARG_LEN (1)); } -/*-------------------------------------------------------------------------. -| The macro expands to the first index of the second argument in the first | -| argument. | -`-------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------. +| The macro expands to the first index of the second argument in the | +| first argument. As an extension, start the search at the index | +| indicated by the third argument. | +`-------------------------------------------------------------------*/ static void m4_index (struct obstack *obs, int argc, macro_arguments *argv) { const char *haystack; + size_t haystack_len; const char *needle; const char *result = NULL; + int offset = 0; int retval = -1; - if (bad_argc (arg_info (argv), argc, 2, 2)) + if (bad_argc (arg_info (argv), argc, 2, 3)) { /* builtin(`index') is blank, but index(`abc') is 0. */ if (argc == 2) @@ -1850,11 +1853,26 @@ m4_index (struct obstack *obs, int argc, macro_arguments *argv) } haystack = ARG (1); + haystack_len = ARG_LEN (1); needle = ARG (2); + if (!arg_empty (argv, 3) && !numeric_arg (arg_info (argv), ARG (3), &offset)) + return; + if (offset < 0) + { + offset += haystack_len; + if (offset < 0) + offset = 0; + } + else if (haystack_len < offset) + { + shipout_int (obs, -1); + return; + } /* Rely on the optimizations guaranteed by gnulib's memmem module. */ - result = (char *) memmem (haystack, ARG_LEN (1), needle, ARG_LEN (2)); + result = (char *) memmem (haystack + offset, haystack_len - offset, needle, + ARG_LEN (2)); if (result) retval = result - haystack; -- 1.6.1.2
_______________________________________________ M4-patches mailing list [email protected] http://lists.gnu.org/mailman/listinfo/m4-patches
