svn commit: r223024 - head/bin/sh

Jilles Tjoelker jilles at FreeBSD.org
Sun Jun 12 23:06:05 UTC 2011


Author: jilles
Date: Sun Jun 12 23:06:04 2011
New Revision: 223024
URL: http://svn.freebsd.org/changeset/base/223024

Log:
  sh: Save/restore changed variables in optimized command substitution.
  
  In optimized command substitution, save and restore any variables changed by
  expansions (${var=value} and $((var=assigned))), instead of trying to
  determine if an expansion may cause such changes.
  
  If $! is referenced in optimized command substitution, do not cause jobs to
  be remembered longer.
  
  This fixes $(jobs $!) again, simplifies the man page and shortens the code.

Modified:
  head/bin/sh/eval.c
  head/bin/sh/expand.c
  head/bin/sh/expand.h
  head/bin/sh/jobs.c
  head/bin/sh/sh.1
  head/bin/sh/var.c
  head/bin/sh/var.h

Modified: head/bin/sh/eval.c
==============================================================================
--- head/bin/sh/eval.c	Sun Jun 12 22:47:04 2011	(r223023)
+++ head/bin/sh/eval.c	Sun Jun 12 23:06:04 2011	(r223024)
@@ -571,14 +571,8 @@ evalpipe(union node *n)
 static int
 is_valid_fast_cmdsubst(union node *n)
 {
-	union node *argp;
 
-	if (n->type != NCMD)
-		return 0;
-	for (argp = n->ncmd.args ; argp ; argp = argp->narg.next)
-		if (expandhassideeffects(argp->narg.text))
-			return 0;
-	return 1;
+	return (n->type == NCMD);
 }
 
 /*
@@ -596,6 +590,7 @@ evalbackcmd(union node *n, struct backcm
 	struct stackmark smark;		/* unnecessary */
 	struct jmploc jmploc;
 	struct jmploc *savehandler;
+	struct localvar *savelocalvars;
 
 	setstackmark(&smark);
 	result->fd = -1;
@@ -608,12 +603,18 @@ evalbackcmd(union node *n, struct backcm
 	}
 	if (is_valid_fast_cmdsubst(n)) {
 		exitstatus = oexitstatus;
+		savelocalvars = localvars;
+		localvars = NULL;
+		forcelocal++;
 		savehandler = handler;
 		if (setjmp(jmploc.loc)) {
 			if (exception == EXERROR || exception == EXEXEC)
 				exitstatus = 2;
 			else if (exception != 0) {
 				handler = savehandler;
+				forcelocal--;
+				poplocalvars();
+				localvars = savelocalvars;
 				longjmp(handler->loc, 1);
 			}
 		} else {
@@ -621,6 +622,9 @@ evalbackcmd(union node *n, struct backcm
 			evalcommand(n, EV_BACKCMD, result);
 		}
 		handler = savehandler;
+		forcelocal--;
+		poplocalvars();
+		localvars = savelocalvars;
 	} else {
 		exitstatus = 0;
 		if (pipe(pip) < 0)

Modified: head/bin/sh/expand.c
==============================================================================
--- head/bin/sh/expand.c	Sun Jun 12 22:47:04 2011	(r223023)
+++ head/bin/sh/expand.c	Sun Jun 12 23:06:04 2011	(r223024)
@@ -1621,78 +1621,6 @@ cvtnum(int num, char *buf)
 }
 
 /*
- * Check statically if expanding a string may have side effects.
- */
-int
-expandhassideeffects(const char *p)
-{
-	int c;
-	int arinest;
-
-	arinest = 0;
-	while ((c = *p++) != '\0') {
-		switch (c) {
-		case CTLESC:
-			p++;
-			break;
-		case CTLVAR:
-			c = *p++;
-			/* Expanding $! sets the job to remembered. */
-			if (*p == '!')
-				return 1;
-			if ((c & VSTYPE) == VSASSIGN)
-				return 1;
-			/*
-			 * If we are in arithmetic, the parameter may contain
-			 * '=' which may cause side effects. Exceptions are
-			 * the length of a parameter and $$, $# and $? which
-			 * are always numeric.
-			 */
-			if ((c & VSTYPE) == VSLENGTH) {
-				while (*p != '=')
-					p++;
-				p++;
-				break;
-			}
-			if ((*p == '$' || *p == '#' || *p == '?') &&
-			    p[1] == '=') {
-				p += 2;
-				break;
-			}
-			if (arinest > 0)
-				return 1;
-			break;
-		case CTLBACKQ:
-		case CTLBACKQ | CTLQUOTE:
-			if (arinest > 0)
-				return 1;
-			break;
-		case CTLARI:
-			arinest++;
-			break;
-		case CTLENDARI:
-			arinest--;
-			break;
-		case '=':
-			if (*p == '=') {
-				/* Allow '==' operator. */
-				p++;
-				continue;
-			}
-			if (arinest > 0)
-				return 1;
-			break;
-		case '!': case '<': case '>':
-			/* Allow '!=', '<=', '>=' operators. */
-			if (*p == '=')
-				p++;
-			break;
-		}
-	}
-	return 0;
-}
-
-/*
  * Do most of the work for wordexp(3).
  */
 

Modified: head/bin/sh/expand.h
==============================================================================
--- head/bin/sh/expand.h	Sun Jun 12 22:47:04 2011	(r223023)
+++ head/bin/sh/expand.h	Sun Jun 12 23:06:04 2011	(r223024)
@@ -63,5 +63,4 @@ void expari(int);
 int patmatch(const char *, const char *, int);
 void rmescapes(char *);
 int casematch(union node *, const char *);
-int expandhassideeffects(const char *);
 int wordexpcmd(int, char **);

Modified: head/bin/sh/jobs.c
==============================================================================
--- head/bin/sh/jobs.c	Sun Jun 12 22:47:04 2011	(r223023)
+++ head/bin/sh/jobs.c	Sun Jun 12 23:06:04 2011	(r223024)
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
 #include "memalloc.h"
 #include "error.h"
 #include "mystring.h"
+#include "var.h"
 
 
 static struct job *jobtab;	/* array of jobs */
@@ -798,6 +799,7 @@ forkshell(struct job *jp, union node *n,
 		handler = &main_handler;
 		closescript();
 		INTON;
+		forcelocal = 0;
 		clear_traps();
 #if JOBS
 		jobctl = 0;		/* do job control only in root shell */
@@ -1121,7 +1123,7 @@ backgndpidset(void)
 pid_t
 backgndpidval(void)
 {
-	if (bgjob != NULL)
+	if (bgjob != NULL && !forcelocal)
 		bgjob->remembered = 1;
 	return backgndpid;
 }

Modified: head/bin/sh/sh.1
==============================================================================
--- head/bin/sh/sh.1	Sun Jun 12 22:47:04 2011	(r223023)
+++ head/bin/sh/sh.1	Sun Jun 12 23:06:04 2011	(r223024)
@@ -32,7 +32,7 @@
 .\"	from: @(#)sh.1	8.6 (Berkeley) 5/4/95
 .\" $FreeBSD$
 .\"
-.Dd June 10, 2011
+.Dd June 12, 2011
 .Dt SH 1
 .Os
 .Sh NAME
@@ -1536,10 +1536,7 @@ except that the built-in commands
 and
 .Ic trap
 return information about the main shell environment
-if they are the only command in a command substitution
-and the substitutions in the command cannot cause side effects
-(such as from assigning values to variables or referencing
-.Li $! ).
+if they are the only command in a command substitution.
 .Ss Arithmetic Expansion
 Arithmetic expansion provides a mechanism for evaluating an arithmetic
 expression and substituting its value.

Modified: head/bin/sh/var.c
==============================================================================
--- head/bin/sh/var.c	Sun Jun 12 22:47:04 2011	(r223023)
+++ head/bin/sh/var.c	Sun Jun 12 23:06:04 2011	(r223024)
@@ -94,6 +94,8 @@ struct var vps4;
 struct var vvers;
 static struct var voptind;
 
+int forcelocal;
+
 static const struct varinit varinit[] = {
 #ifndef NO_HISTORY
 	{ &vhistsize,	VUNSET,				"HISTSIZE=",
@@ -325,6 +327,8 @@ setvareq(char *s, int flags)
 
 	if (aflag)
 		flags |= VEXPORT;
+	if (forcelocal && !(flags & (VNOSET | VNOLOCAL)))
+		mklocal(s);
 	vp = find_var(s, &vpp, &nlen);
 	if (vp != NULL) {
 		if (vp->flags & VREADONLY)
@@ -740,9 +744,9 @@ mklocal(char *name)
 		vp = find_var(name, &vpp, NULL);
 		if (vp == NULL) {
 			if (strchr(name, '='))
-				setvareq(savestr(name), VSTRFIXED);
+				setvareq(savestr(name), VSTRFIXED | VNOLOCAL);
 			else
-				setvar(name, NULL, VSTRFIXED);
+				setvar(name, NULL, VSTRFIXED | VNOLOCAL);
 			vp = *vpp;	/* the new variable */
 			lvp->text = NULL;
 			lvp->flags = VUNSET;
@@ -751,7 +755,7 @@ mklocal(char *name)
 			lvp->flags = vp->flags;
 			vp->flags |= VSTRFIXED|VTEXTFIXED;
 			if (name[vp->name_len] == '=')
-				setvareq(savestr(name), 0);
+				setvareq(savestr(name), VNOLOCAL);
 		}
 	}
 	lvp->vp = vp;

Modified: head/bin/sh/var.h
==============================================================================
--- head/bin/sh/var.h	Sun Jun 12 22:47:04 2011	(r223023)
+++ head/bin/sh/var.h	Sun Jun 12 23:06:04 2011	(r223024)
@@ -46,6 +46,7 @@
 #define VUNSET		0x20	/* the variable is not set */
 #define VNOFUNC		0x40	/* don't call the callback function */
 #define VNOSET		0x80	/* do not set variable - just readonly test */
+#define VNOLOCAL	0x100	/* ignore forcelocal */
 
 
 struct var {
@@ -68,6 +69,7 @@ struct localvar {
 
 
 struct localvar *localvars;
+extern int forcelocal;
 
 extern struct var vifs;
 extern struct var vmail;


More information about the svn-src-all mailing list