summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/builtin.c35
-rw-r--r--Src/lex.c8
-rw-r--r--Src/params.c29
3 files changed, 54 insertions, 18 deletions
diff --git a/Src/builtin.c b/Src/builtin.c
index 0f02ae0a9..bc1a35f90 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1691,7 +1691,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 		pm->env = NULL;
 	    }
 	    if (value && !(pm = setsparam(pname, ztrdup(value))))
-		return 0;
+		return NULL;
 	} else if (value) {
 	    zwarnnam(cname, "can't assign new value for array %s", pname, 0);
 	    return NULL;
@@ -1782,7 +1782,27 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	    pm->ct = auxlen;
 	else
 	    pm->ct = 0;
-    } else {
+    } else if (strchr(pname, '[')) {
+	if (on & PM_READONLY) {
+	    zerrnam(cname,
+		    "%s: can't create readonly array elements", pname, 0);
+	    return NULL;
+	} else if (PM_TYPE(on) == PM_SCALAR) {
+	    /*
+	     * This will either complain about bad identifiers, or will set
+	     * a hash element or array slice.  This once worked by accident,
+	     * creating a stray parameter along the way via createparam(),
+	     * now called below in the isident() branch.
+	     */
+	    if (!(pm = setsparam(pname, ztrdup(value ? value : ""))))
+		return NULL;
+	    value = NULL;
+	} else {
+	    zerrnam(cname,
+		    "%s: array elements must be scalar", pname, 0);
+	    return NULL;
+	}
+    } else if (isident(pname)) {
 	/*
 	 * Create a new node for a parameter with the flags in `on' minus the
 	 * readonly flag
@@ -1790,6 +1810,9 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	pm = createparam(pname, on & ~PM_READONLY);
 	DPUTS(!pm, "BUG: parameter not created");
 	pm->ct = auxlen;
+    } else {
+	zerr("not an identifier: %s", pname, 0);
+	return NULL;
     }
 
     if (altpm && PM_TYPE(pm->flags) == PM_SCALAR) {
@@ -1808,8 +1831,14 @@ typeset_single(char *cname, char *pname, Param pm, int func,
     else if (on & PM_LOCAL)
 	pm->level = locallevel;
     if (value && !(pm->flags & (PM_ARRAY|PM_HASHED))) {
+	Param ipm = pm;
 	if (!(pm = setsparam(pname, ztrdup(value))))
-	    return 0;
+	    return NULL;
+	if (pm != ipm) {
+	    DPUTS(ipm->flags != pm->flags,
+		  "BUG: parameter recreated with wrong flags");
+	    unsetparam_pm(ipm, 0, 1);
+	}
     } else if (newspecial && !(pm->old->flags & PM_NORESTORE)) {
 	/*
 	 * We need to use the special setting function to re-initialise
diff --git a/Src/lex.c b/Src/lex.c
index 46d83cb21..428e77431 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -1303,9 +1303,9 @@ dquote_parse(char endchar, int sub)
 	    if (c != '\n') {
 		if (c == '$' || c == '\\' || (c == '}' && !intick && bct) ||
 		    c == endchar || c == '`' ||
-		    (math && (c == '[' || c == ']' ||
-			      c == '(' || c == ')' ||
-			      c == '{' || c == '}')))
+		    (endchar == ']' && (c == '[' || c == ']' ||
+					c == '(' || c == ')' ||
+					c == '{' || c == '}')))
 		    add(Bnull);
 		else {
 		    /* lexstop is implicitly handled here */
@@ -1390,7 +1390,7 @@ dquote_parse(char endchar, int sub)
 		err = (!brct-- && math);
 	    break;
 	case '"':
-	    if (intick || (!endchar && !bct))
+	    if (intick || endchar == ']' || (!endchar && !bct))
 		break;
 	    if (bct) {
 		add(Dnull);
diff --git a/Src/params.c b/Src/params.c
index aaeebce76..48b514008 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -765,10 +765,17 @@ isident(char *s)
     if (!*s)			/* empty string is definitely not valid */
 	return 0;
 
-    /* find the first character in `s' not in the iident type table */
-    for (ss = s; *ss; ss++)
-	if (!iident(*ss))
-	    break;
+    if (idigit(*s)) {
+	/* If the first character is `s' is a digit, then all must be */
+	for (ss = ++s; *ss; ss++)
+	    if (!idigit(*ss))
+		break;
+    } else {
+	/* Find the first character in `s' not in the iident type table */
+	for (ss = s; *ss; ss++)
+	    if (!iident(*ss))
+		break;
+    }
 
     /* If the next character is not [, then it is *
      * definitely not a valid identifier.         */
@@ -1171,7 +1178,7 @@ getindex(char **pptr, Value v)
     int start, end, inv = 0;
     char *s = *pptr, *tbrack;
 
-    *s++ = Inbrack;
+    *s++ = '[';
     s = parse_subscript(s);	/* Error handled after untokenizing */
     /* Now we untokenize everthing except INULL() markers so we can check *
      * for the '*' and '@' special subscripts.  The INULL()s are removed  *
@@ -1191,7 +1198,7 @@ getindex(char **pptr, Value v)
 	return 1;
     }
     s = *pptr + 1;
-    if ((s[0] == '*' || s[0] == '@') && s[1] == Outbrack) {
+    if ((s[0] == '*' || s[0] == '@') && s + 1 == tbrack) {
 	if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@')
 	    v->isarr |= SCANPM_ISVAR_AT;
 	v->start = 0;
@@ -1223,12 +1230,11 @@ getindex(char **pptr, Value v)
 	    }
 	    if (*s == ',') {
 		zerr("invalid subscript", NULL, 0);
-		while (*s && *s != Outbrack)
-		    s++;
-		*pptr = s;
+		*tbrack = ']';
+		*pptr = tbrack+1;
 		return 1;
 	    }
-	    if (*s == Outbrack)
+	    if (s == tbrack)
 		s++;
 	} else {
 	    int com;
@@ -1243,7 +1249,7 @@ getindex(char **pptr, Value v)
 		start--;
 	    else if (start == 0 && end == 0)
 		end++;
-	    if (*s == Outbrack) {
+	    if (s == tbrack) {
 		s++;
 		if (v->isarr && start == end-1 && !com &&
 		    (!(v->isarr & SCANPM_MATCHMANY) ||
@@ -1256,6 +1262,7 @@ getindex(char **pptr, Value v)
 		s = *pptr;
 	}
     }
+    *tbrack = ']';
     *pptr = s;
     return 0;
 }