Source-Changes-HG archive

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

[src/trunk]: src/bin/sh Fix some parser weirdness...



details:   https://anonhg.NetBSD.org/src/rev/4ad58f6fbaec
branches:  trunk
changeset: 823848:4ad58f6fbaec
user:      kre <kre%NetBSD.org@localhost>
date:      Thu May 11 15:07:37 2017 +0000

description:
Fix some parser weirdness...
${#VAR:-foo} (or any other modifier on ${#VAR} is a syntax error.
On the other hand ${##} is not, nor is ${##13} though they mean
quite different things (the latter is an idiom everyone should learn,
... $# except we refuse to admit the possibility that it is 13...
Even I cannot explain what ${#-foo} used to do, but it wasn't sane!
(It should be just $# as $# is never unset, but ...)
Shell syntax is truly a wondrous thing!

diffstat:

 bin/sh/parser.c |  34 ++++++++++++++++++++++++++++++----
 1 files changed, 30 insertions(+), 4 deletions(-)

diffs (64 lines):

diff -r a71c3514002a -r 4ad58f6fbaec bin/sh/parser.c
--- a/bin/sh/parser.c   Thu May 11 14:57:14 2017 +0000
+++ b/bin/sh/parser.c   Thu May 11 15:07:37 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: parser.c,v 1.126 2017/05/10 11:06:47 kre Exp $ */
+/*     $NetBSD: parser.c,v 1.127 2017/05/11 15:07:37 kre Exp $ */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)parser.c   8.7 (Berkeley) 5/16/95";
 #else
-__RCSID("$NetBSD: parser.c,v 1.126 2017/05/10 11:06:47 kre Exp $");
+__RCSID("$NetBSD: parser.c,v 1.127 2017/05/11 15:07:37 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -1748,10 +1748,34 @@
                if (c == OPENBRACE) {
                        c = pgetc_linecont();
                        if (c == '#') {
-                               if ((c = pgetc()) == CLOSEBRACE)
+                               if ((c = pgetc_linecont()) == CLOSEBRACE)
                                        c = '#';
-                               else
+                               else if (is_name(c) || isdigit(c))
                                        subtype = VSLENGTH;
+                               else if (is_special(c)) {
+                                       /*
+                                        * ${##} is the length of ${#}
+                                        * ${##1} is ${#} with leading 1 gone
+                                        *
+                                        * this stuff is UGLY!
+                                        */
+                                       if (pgetc_linecont() == CLOSEBRACE) {
+                                               pungetc();
+                                               subtype = VSLENGTH;
+                                       } else {
+                                               static char cbuf[2];
+                                               pungetc();
+                                               cbuf[0] = c;
+                                               cbuf[1] = '\0';
+                                               pushstring(cbuf, 1, NULL);
+                                               c = '#';
+                                               subtype = 0;
+                                       }
+                               } else {
+                                       pungetc();
+                                       c = '#';
+                                       subtype = 0;
+                               }
                        }
                        else
                                subtype = 0;
@@ -1818,6 +1842,8 @@
                                }
                        }
                } else {
+                       if (subtype == VSLENGTH && c != /*{*/ '}')
+                               synerror("no modifiers allowed with ${#var}");
                        pungetc();
                }
                if (ISDBLQUOTE() || arinest)



Home | Main Index | Thread Index | Old Index