summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2009-02-09 11:22:57 -0700
committerEric Blake <ebb9@byu.net>2009-02-09 11:22:57 -0700
commit3aa86615d46144acfff9b7ff60cdec4f7cc2a43d (patch)
tree5183263197ff8a06f716851defd1930981fd4f86
parent3998b3ad447a3200ce8a040b860a8fd0e109850b (diff)
downloadm4-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--ChangeLog8
-rw-r--r--NEWS4
-rw-r--r--doc/m4.texinfo29
-rw-r--r--modules/m4.c27
4 files changed, 59 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 72d80e35..85e876b7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/NEWS b/NEWS
index dd7e674a..772216dc 100644
--- a/NEWS
+++ b/NEWS
@@ -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;