summaryrefslogtreecommitdiff
path: root/Src/subst.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2010-11-18 10:07:55 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2010-11-18 10:07:55 +0000
commit23bdfc7fd2a012d5205ed22d18eb39e41c8fbc95 (patch)
tree80d7f0e6c868a1283f3275cf88e08b8c86d509c1 /Src/subst.c
parent851b8e151004ec729dad9c8c7867bbf67649df8e (diff)
downloadzsh-23bdfc7fd2a012d5205ed22d18eb39e41c8fbc95.tar.gz
zsh-23bdfc7fd2a012d5205ed22d18eb39e41c8fbc95.zip
28418: add ${NAME:OFFSET:LENGTH} substitution
Diffstat (limited to 'Src/subst.c')
-rw-r--r--Src/subst.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/Src/subst.c b/Src/subst.c
index 5f65945a5..c0fb38a48 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1371,6 +1371,43 @@ untok_and_escape(char *s, int escapes, int tok_arg)
return dst;
}
+/*
+ * See if an argument str looks like a subscript or length following
+ * a colon and parse it. It must be followed by a ':' or nothing.
+ * If this succeeds, expand and return the evaulated expression if
+ * found, else return NULL.
+ *
+ * We assume this is what is meant if the first character is not
+ * an alphabetic character or '&', which signify modifiers.
+ *
+ * Set *endp to point to the next character following.
+ */
+static char *
+check_colon_subscript(char *str, char **endp)
+{
+ int sav;
+
+ /* Could this be a modifier (or empty)? */
+ if (!*str || ialpha(*str) || *str == '&')
+ return NULL;
+
+ *endp = parse_subscript(str, 0, ':');
+ if (!*endp) {
+ /* No trailing colon? */
+ *endp = parse_subscript(str, 0, '\0');
+ if (!*endp)
+ return NULL;
+ }
+ sav = **endp;
+ **endp = '\0';
+ if (parsestr(str = dupstring(str)))
+ return NULL;
+ singsub(&str);
+
+ **endp = sav;
+ return str;
+}
+
/* parameter substitution */
#define isstring(c) ((c) == '$' || (char)(c) == String || (char)(c) == Qstring)
@@ -2683,6 +2720,97 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
}
val = dupstring("");
}
+ if (colf && inbrace) {
+ /*
+ * Look for ${PARAM:OFFSET} or ${PARAM:OFFSET:LENGTH}.
+ * This must appear before modifiers. For compatibility
+ * with bash we perform both standard string substitutions
+ * and math eval.
+ */
+ char *check_offset2;
+ char *check_offset = check_colon_subscript(s, &check_offset2);
+ if (check_offset) {
+ zlong offset = mathevali(check_offset);
+ zlong length = (zlong)-1;
+ if (errflag)
+ return NULL;
+ if ((*check_offset2 && *check_offset2 != ':')) {
+ zerr("invalid subscript: %s", check_offset);
+ return NULL;
+ }
+ if (*check_offset2) {
+ check_offset = check_colon_subscript(check_offset2 + 1,
+ &check_offset2);
+ if (*check_offset2 && *check_offset2 != ':') {
+ zerr("invalid length: %s", check_offset);
+ return NULL;
+ }
+ length = mathevali(check_offset);
+ if (errflag)
+ return NULL;
+ if (length < (zlong)0) {
+ zerr("invalid length: %s", check_offset);
+ return NULL;
+ }
+ }
+ if (!isset(KSHARRAYS) && offset > 0)
+ offset--;
+ if (isarr) {
+ int alen = arrlen(aval), count;
+ char **srcptr, **dstptr, **newarr;
+
+ if (offset < 0) {
+ offset += alen;
+ if (offset < 0)
+ offset = 0;
+ }
+ if (length < 0)
+ length = alen;
+ if (offset > alen)
+ offset = alen;
+ if (offset + length > alen)
+ length = alen - offset;
+ count = length;
+ srcptr = aval + offset;
+ newarr = dstptr = (char **)
+ zhalloc((length+1)*sizeof(char *));
+ while (count--)
+ *dstptr++ = dupstring(*srcptr++);
+ *dstptr = (char *)NULL;
+ aval = newarr;
+ } else {
+ char *sptr, *eptr;
+ if (offset < 0) {
+ MB_METACHARINIT();
+ for (sptr = val; *sptr; ) {
+ sptr += MB_METACHARLEN(sptr);
+ offset++;
+ }
+ if (offset < 0)
+ offset = 0;
+ }
+ MB_METACHARINIT();
+ for (sptr = val; *sptr && offset; ) {
+ sptr += MB_METACHARLEN(sptr);
+ offset--;
+ }
+ if (length >= 0) {
+ for (eptr = sptr; *eptr && length; ) {
+ eptr += MB_METACHARLEN(eptr);
+ length--;
+ }
+ val = dupstrpfx(sptr, eptr - sptr);
+ } else {
+ val = dupstring(sptr);
+ }
+ }
+ if (!*check_offset2) {
+ colf = 0;
+ } else {
+ s = check_offset2 + 1;
+ }
+ }
+ }
if (colf) {
/*
* History style colon modifiers. May need to apply