summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2009-01-06 22:03:27 -0700
committerEric Blake <ebb9@byu.net>2009-01-07 14:11:08 -0700
commitae9dfa87a514d290fe349710a9f643d52856f4ba (patch)
tree56561d37876dd6b774b9ce07e608c3df436a9093 /modules
parente6819ca240b76700f07c31ba157f7795caada02e (diff)
downloadm4-ae9dfa87a514d290fe349710a9f643d52856f4ba.tar.gz
Enhance substr to support negative values.
* doc/m4.texinfo (Substr): Document new semantics, and how to simulate old. * modules/m4.c (substr): Support negative values. * NEWS: Document this. Signed-off-by: Eric Blake <ebb9@byu.net> (cherry picked from commit e9e4abba45f7e9f368cf497e14bc2ce64b867a02)
Diffstat (limited to 'modules')
-rw-r--r--modules/m4.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/modules/m4.c b/modules/m4.c
index f578261a..b09510c8 100644
--- a/modules/m4.c
+++ b/modules/m4.c
@@ -1,6 +1,6 @@
/* GNU m4 -- A simple macro processor
- Copyright (C) 2000, 2002, 2003, 2004, 2006, 2007, 2008 Free Software
- Foundation, Inc.
+ Copyright (C) 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2009 Free
+ Software Foundation, Inc.
This file is part of GNU M4.
@@ -924,17 +924,19 @@ M4BUILTIN_HANDLER (index)
m4_shipout_int (obs, retval);
}
-/* The macro "substr" extracts substrings from the first argument, starting
- from the index given by the second argument, extending for a length
- given by the third argument. If the third argument is missing, the
- substring extends to the end of the first argument. */
+/* The macro "substr" extracts substrings from the first argument,
+ starting from the index given by the second argument, extending for
+ 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. */
M4BUILTIN_HANDLER (substr)
{
const m4_call_info *me = m4_arg_info (argv);
const char *str = M4ARG (1);
int start = 0;
+ int end;
int length;
- int avail;
if (argc <= 2)
{
@@ -942,19 +944,33 @@ M4BUILTIN_HANDLER (substr)
return;
}
- length = avail = M4ARGLEN (1);
- if (!m4_numeric_arg (context, me, M4ARG (2), &start))
+ length = M4ARGLEN (1);
+ if (!m4_arg_empty (argv, 2)
+ && !m4_numeric_arg (context, me, M4ARG (2), &start))
return;
+ if (start < 0)
+ start += length;
- if (argc >= 4 && !m4_numeric_arg (context, me, M4ARG (3), &length))
- return;
+ if (m4_arg_empty (argv, 3))
+ end = length;
+ else
+ {
+ if (!m4_numeric_arg (context, me, M4ARG (3), &end))
+ return;
+ if (end < 0)
+ end += length;
+ else
+ end += start;
+ }
- if (start < 0 || length <= 0 || start >= avail)
+ if (start < 0)
+ start = 0;
+ if (length < end)
+ end = length;
+ if (end <= start)
return;
- if (start + length > avail)
- length = avail - start;
- obstack_grow (obs, str + start, length);
+ obstack_grow (obs, str + start, end - start);
}