diff options
author | Eric Blake <ebb9@byu.net> | 2009-02-09 11:22:57 -0700 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2009-02-09 11:22:57 -0700 |
commit | 3aa86615d46144acfff9b7ff60cdec4f7cc2a43d (patch) | |
tree | 5183263197ff8a06f716851defd1930981fd4f86 | |
parent | 3998b3ad447a3200ce8a040b860a8fd0e109850b (diff) | |
download | m4-3aa86615d46144acfff9b7ff60cdec4f7cc2a43d.tar.gz |
Enhance index to support starting offset.
* modules/m4.c (index): Add optional third argument.
* NEWS: Document this.
* doc/m4.texinfo (Index macro): Likewise.
(Macro Arguments): Adjust tests.
Signed-off-by: Eric Blake <ebb9@byu.net>
(cherry picked from commit b9c165b394c06d2da657caae33efd5843689ff3b)
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/m4.texinfo | 29 | ||||
-rw-r--r-- | modules/m4.c | 27 |
4 files changed, 59 insertions, 9 deletions
@@ -1,3 +1,11 @@ +2009-02-09 Eric Blake <ebb9@byu.net> + + Enhance index to support starting offset. + * modules/m4.c (index): Add optional third argument. + * NEWS: Document this. + * doc/m4.texinfo (Index macro): Likewise. + (Macro Arguments): Adjust tests. + 2009-01-24 Eric Blake <ebb9@byu.net> Add URLs to --help output. @@ -248,6 +248,10 @@ promoted to 2.0. 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 fbe42f2c..093f3952 100644 --- a/doc/m4.texinfo +++ b/doc/m4.texinfo @@ -1692,8 +1692,8 @@ index(`abc') @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 @@ -1704,7 +1704,7 @@ index(`abc') @result{}0 index(`abc',) @result{}0 -index(`abc', `b', `ignored') +index(`abc', `b', `', `ignored') @result{}1 @end example @@ -6869,11 +6869,13 @@ len(`abcdef') @cindex substrings, locating Searching for substrings is done with @code{index}: -@deffn {Builtin (m4)} index (@var{string}, @var{substring}) +@deffn {Builtin (m4)} 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 @@ -6898,6 +6900,23 @@ index(`abc', `b') @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', `ab', `4') +@result{}-1 +index(`abc', `bc', `-4') +@result{}1 +@end example + @node Regexp @section Searching for regular expressions diff --git a/modules/m4.c b/modules/m4.c index b7d23d04..177590dc 100644 --- a/modules/m4.c +++ b/modules/m4.c @@ -76,7 +76,7 @@ extern void m4_make_temp (m4 *, m4_obstack *, const m4_call_info *, BUILTIN (ifelse, true, true, false, 1, -1 ) \ BUILTIN (include, false, true, false, 1, 1 ) \ BUILTIN (incr, false, true, true, 1, 1 ) \ - BUILTIN (index, false, true, true, 2, 2 ) \ + BUILTIN (index, false, true, true, 2, 3 ) \ BUILTIN (len, false, true, true, 1, 1 ) \ BUILTIN (m4exit, false, false, false, 0, 1 ) \ BUILTIN (m4wrap, true, true, false, 1, -1 ) \ @@ -906,18 +906,37 @@ M4BUILTIN_HANDLER (len) m4_shipout_int (obs, M4ARGLEN (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. */ M4BUILTIN_HANDLER (index) { const char *haystack = M4ARG (1); + size_t haystack_len = M4ARGLEN (1); const char *needle = M4ARG (2); const char *result = NULL; + int offset = 0; int retval = -1; + if (!m4_arg_empty (argv, 3) && !m4_numeric_arg (context, m4_arg_info (argv), + M4ARG (3), &offset)) + return; + if (offset < 0) + { + offset += haystack_len; + if (offset < 0) + offset = 0; + } + else if (haystack_len < offset) + { + m4_shipout_int (obs, -1); + return; + } + /* Rely on the optimizations guaranteed by gnulib's memmem module. */ - result = (char *) memmem (haystack, M4ARGLEN (1), needle, M4ARGLEN (2)); + result = (char *) memmem (haystack + offset, haystack_len - offset, needle, + M4ARGLEN (2)); if (result) retval = result - haystack; |