m4-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

enhance index builtin


From: Eric Blake
Subject: enhance index builtin
Date: Tue, 10 Feb 2009 06:18:47 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.19) Gecko/20081209 Thunderbird/2.0.0.19 Mnenhy/0.7.6.666

-----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             address@hidden
-----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 <address@hidden>
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 <address@hidden>
---
 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  <address@hidden>
+
+       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  <address@hidden>

        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')
address@hidden:stdin:3: Warning: index: extra arguments ignored: 3 > 2
+index(`abc', `b', `0', `ignored')
address@hidden: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}:

address@hidden Builtin index (@var{string}, @var{substring})
address@hidden 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
address@hidden
address@hidden  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

address@hidden @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}.
+
address@hidden
+index(`aba', `a', `1')
address@hidden
+index(`ababa', `ba', `-3')
address@hidden
+index(`abc', `a', `4')
address@hidden
+index(`abc', `bc', `-4')
address@hidden
address@hidden 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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]