Module Name:    src
Committed By:   christos
Date:           Tue Nov 16 18:17:32 UTC 2010

Modified Files:
        src/bin/sh: parser.c

Log Message:
PR/43469: Antii Kantee: test/util/sh/t_expand:strip fails.
Bring back fixes from revision 1.75:

- Fix a couple of bugs to make the following two echo statements print the
  same output as they should:

    line='#define bindir "/usr/bin" /* comment */'
    echo "${line%%/\**}"
    echo ${line%%/\**}

1. ISDBLQUOTE() was not working properly for non VSNORMAL expansions because
   varnest was incremented before the variable was completely parsed. Add
   an insub adjustment to keep track of that.
2. When we have a quoted backslash, we either need to escape twice, because
   one level of escaping will be stripped later (in the variable substitution
   case) or simply enter the backslash.


To generate a diff of this commit:
cvs rdiff -u -r1.76 -r1.77 src/bin/sh/parser.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/parser.c
diff -u src/bin/sh/parser.c:1.76 src/bin/sh/parser.c:1.77
--- src/bin/sh/parser.c:1.76	Sun Nov 14 14:49:16 2010
+++ src/bin/sh/parser.c	Tue Nov 16 13:17:32 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: parser.c,v 1.76 2010/11/14 19:49:16 christos Exp $	*/
+/*	$NetBSD: parser.c,v 1.77 2010/11/16 18:17:32 christos 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.76 2010/11/14 19:49:16 christos Exp $");
+__RCSID("$NetBSD: parser.c,v 1.77 2010/11/16 18:17:32 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -896,20 +896,27 @@
  * This code assumes that an int is 32 bits. We don't use uint32_t,
  * because the rest of the code does not.
  */
-#define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \
-    (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32))))
+#define VN (varnest - insub)
+#define ISDBLQUOTE() ((VN < 32) ? (dblquote & (1 << VN)) : \
+    (dblquotep[(VN / 32) - 1] & (1 << (VN % 32))))
 
 #define SETDBLQUOTE() \
-    if (varnest < 32) \
-	dblquote |= (1 << varnest); \
-    else \
-	dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32))
+    do { \
+	    TRACE(("setdblquote varnest=%d insub=%d\n", varnest, insub)); \
+	    if (VN < 32) \
+		    dblquote |= (1 << VN); \
+	    else \
+		    dblquotep[(VN / 32) - 1] |= (1 << (VN % 32));\
+    } while (/*CONSTCOND*/0)
 
 #define CLRDBLQUOTE() \
-    if (varnest < 32) \
-	dblquote &= ~(1 << varnest); \
-    else \
-	dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32))
+    do { \
+	    TRACE(("clrdblquote varnest=%d insub=%d\n", varnest, insub)); \
+	    if (VN < 32) \
+		    dblquote &= ~(1 << VN); \
+	    else \
+		    dblquotep[(VN / 32) - 1] &= ~(1 << (VN % 32)); \
+    } while (/*CONSTCOND*/0)
 
 STATIC int
 readtoken1(int firstc, char const *syn, char *eofmark, int striptabs)
@@ -928,6 +935,7 @@
 	volatile int arinest;	/* levels of arithmetic expansion */
 	volatile int parenlevel;	/* levels of parens in arithmetic */
 	volatile int oldstyle;
+	volatile int insub;
 	char const * volatile prevsyntax;	/* syntax before arithmetic */
 #ifdef __GNUC__
 	prevsyntax = NULL;	/* XXX gcc4 */
@@ -936,9 +944,9 @@
 	startlinno = plinno;
 	dblquote = 0;
 	varnest = 0;
-	if (syntax == DQSYNTAX) {
+	insub = 0;
+	if (syntax == DQSYNTAX)
 		SETDBLQUOTE();
-	}
 	quotef = 0;
 	bqlist = NULL;
 	arinest = 0;
@@ -994,10 +1002,17 @@
 					break;
 				}
 				quotef = 1;
+				TRACE(("varnest=%d doubleq=%d c=%c\n",
+				    varnest, ISDBLQUOTE(), c));
 				if (ISDBLQUOTE() && c != '\\' &&
 				    c != '`' && c != '$' &&
-				    (c != '"' || eofmark != NULL))
-					USTPUTC('\\', out);
+				    (c != '"' || eofmark != NULL)) {
+					if (insub) {
+						USTPUTC(CTLESC, out);
+						USTPUTC(CTLESC, out);
+					} else
+						USTPUTC('\\', out);
+				}
 				if (SQSYNTAX[c] == CCTL)
 					USTPUTC(CTLESC, out);
 				else if (eofmark == NULL) {
@@ -1053,6 +1068,8 @@
 				}
 				if (eofmark != NULL)
 					break;
+				TRACE(("CDQUOTE %d varnest=%d insub=%d\n",
+				    ISDBLQUOTE(), varnest, insub));
 				if (ISDBLQUOTE()) {
 					if (varnest != 0)
 						USTPUTC(CTLQUOTEEND, out);
@@ -1068,6 +1085,7 @@
 				PARSESUB();		/* parse substitution */
 				break;
 			case CENDVAR:	/* CLOSEBRACE */
+				insub = 0;
 				if (varnest > 0 && !ISDBLQUOTE()) {
 					varnest--;
 					USTPUTC(CTLENDVAR, out);
@@ -1340,7 +1358,9 @@
 			flags |= VSQUOTE;
 		*(stackblock() + typeloc) = subtype | flags;
 		if (subtype != VSNORMAL) {
+			TRACE(("varnest=%d subtype=%d\n", varnest, subtype));
 			varnest++;
+			insub = 1;
 			if (varnest >= maxnest) {
 				dblquotep = ckrealloc(dblquotep, maxnest / 8);
 				dblquotep[(maxnest / 32) - 1] = 0;

Reply via email to