zsh-workers
 help / color / mirror / code / Atom feed
* Some bugreports and a fix
@ 1995-05-29 18:50 Zoltan Hidvegi
  1995-05-31 17:45 ` P.Stephenson
  0 siblings, 1 reply; 2+ messages in thread
From: Zoltan Hidvegi @ 1995-05-29 18:50 UTC (permalink / raw)
  To: zsh-workers

Zsh exits from a script if it finds a syntax error while executing an eval
command. Eg. in

eval let '8#8'
echo Right

Right is not printed. This is because eval uses the lexer which changes the
tok global variable. But the main loop examines tok to decide if it has to
exit if errflag is nonzero. To fix this the patch below saves tok before
calling execlist. With my zsh version this bug occured more often as the
lexer is used more often. I discovered this when zsh exited from my
shutdown script leaving the filesystems mounted (I had to do a hard reset).

There is a similar problem which is not fixed by this patch:

% let '8#8' ; echo right

again does not print `right'. That's because execcmd() does not executes
a command if errflag is true.  This particular problem can be fixed by
uncommenting the errflag = 0; assignment in exec.c in execlist but it
probably has unwanted side effects. I really do not know this part of
the code so someone more expert should look at it.

An other bug is that TRAPZERR is not executed in the above cases.

But TRAPZERR is exectued in other cases when it shouldn't: both
% false || foo=bug
and
% if false; then true; else foo=bug; fi
calls TRAPZERR. I think the problem is that a single assignment does not
reset lastval.

Also a bug (or sh incompatibility) is that
% false && true
exits the shell if ERR_EXIT is set. It's a problem since foo && bar is
a common idiom in shell scripts. The general idea is that ERR_EXIT and
TRAPZERR should be ignored for a command whose return value is used to
decide wether to execute something or not.

Zoltan

*** 1.6	1995/05/05 22:01:58
--- Src/init.c	1995/05/28 21:06:06
***************
*** 110,118 ****
--- 110,121 ----
  	    continue;
  	}
  	if (hend()) {
+ 	    int toksav = tok;
+ 
  	    if (stopmsg)	/* unset 'you have stopped jobs' flag */
  		stopmsg--;
  	    execlist(list, 0);
+ 	    tok = toksav;
  	    if (toplevel)
  		noexitct = 0;
  	}


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Some bugreports and a fix
  1995-05-29 18:50 Some bugreports and a fix Zoltan Hidvegi
@ 1995-05-31 17:45 ` P.Stephenson
  0 siblings, 0 replies; 2+ messages in thread
From: P.Stephenson @ 1995-05-31 17:45 UTC (permalink / raw)
  To: Zsh hackers list

I just realised that the three patches I sent fixing the problems
below went to Zoltan and not the list because of the new reply
behaviour (again).

I'm not wasting time reconstructing the original messages, but this
should fix all the problems as well as a couple of others:  multiple
TRAPZERR's in a list didn't work properly and 'return && foo' executed
foo when it shouldn't.  I made some comments about non-fatal errors
and resetting errflag (at the moment there are possible problems with
signal handling), too.

I think I've found all the bits.

hzoli@cs.elte.hu wrote:
> There is a similar problem which is not fixed by this patch:
> 
> % let '8#8' ; echo right
> 
> again does not print `right'. That's because execcmd() does not executes
> a command if errflag is true.  This particular problem can be fixed by
> uncommenting the errflag = 0; assignment in exec.c in execlist but it
> probably has unwanted side effects. I really do not know this part of
> the code so someone more expert should look at it.
> 
> An other bug is that TRAPZERR is not executed in the above cases.
> 
> But TRAPZERR is exectued in other cases when it shouldn't: both
> % false || foo=bug
> and
> % if false; then true; else foo=bug; fi
> calls TRAPZERR. I think the problem is that a single assignment does not
> reset lastval.
> 
> Also a bug (or sh incompatibility) is that
> % false && true
> exits the shell if ERR_EXIT is set. It's a problem since foo && bar is
> a common idiom in shell scripts. The general idea is that ERR_EXIT and
> TRAPZERR should be ignored for a command whose return value is used to
> decide wether to execute something or not.

*** Src/builtin.c.mer	Tue May 30 12:34:09 1995
--- Src/builtin.c	Tue May 30 14:00:12 1995
***************
*** 5692,5697 ****
--- 5692,5699 ----
  
      while (*argv)
  	val = matheval(*argv++);
+     /* Errors in math evaluation in let are non-fatal. */
+     errflag = 0;
      return !val;
  }
  
*** Src/exec.c.vst	Thu May 25 10:35:42 1995
--- Src/exec.c	Wed May 31 16:10:59 1995
***************
*** 476,502 ****
  
      if (sourcelevel && unset(SHINSTDIN))
  	pline_level = list_pipe = 0;
-     donetrap = 0;
  
      while (list && list != &dummy_list && !breaks && !retflag) {
  	simplifyright(list);
  
  	slist = list->left;
  	while (slist) {
  	    if (slist->type == END) {
  		execpline(slist, list->type, !list->right && exiting);
  		break;
  	    }
  	    ret = execpline(slist, Z_SYNC, 0);
  	    ornext = (slist->type == ORNEXT);
  
  	    if (ornext ^ ret) {
  		alt = ornext ? ANDNEXT : ORNEXT;
  		while ((slist = slist->right))
  		    if (slist->type == alt)
  			break;
! 		if (!slist)
  		    break;
  	    }
  
  	    slist = slist->right;
--- 476,531 ----
  
      if (sourcelevel && unset(SHINSTDIN))
  	pline_level = list_pipe = 0;
  
+     /*
+      * Loop over all sets of comands separated by newline,
+      * semi-colon or ampersand (`sublists').
+      */
      while (list && list != &dummy_list && !breaks && !retflag) {
+ 	/*
+ 	 * Reset donetrap:  this ensures that a trap is only called
+ 	 * once for each sublist that fails.
+ 	 */
+ 	donetrap = 0;
  	simplifyright(list);
  
  	slist = list->left;
  	while (slist) {
+ 	    /*
+ 	     * Loop through code followed by &&, ||, or end of sublist.
+ 	     */
  	    if (slist->type == END) {
+ 		/* End of sublist; just execute, ignoring status. */
  		execpline(slist, list->type, !list->right && exiting);
  		break;
  	    }
  	    ret = execpline(slist, Z_SYNC, 0);
+ 	    /*
+ 	     * Next pipeline is either or'd or and'd with this one;
+ 	     * find which.
+ 	     */
  	    ornext = (slist->type == ORNEXT);
  
  	    if (ornext ^ ret) {
+ 		/*
+ 		 * If either (1) it's an or, and the return code
+ 		 * was zero, or (2) it's an and, and the return
+ 		 * code was non-zero, skip pipelines until we find
+ 		 * a sublist followed by the opposite type.
+ 		 */
  		alt = ornext ? ANDNEXT : ORNEXT;
  		while ((slist = slist->right))
  		    if (slist->type == alt)
  			break;
! 		if (!slist) {
! 		    /*
! 		     * We've skipped to the end of the list, not executing
! 		     * the final pipeline, so don't perform error handling
! 		     * for this sublist.
! 		     */
! 		    donetrap = 1;
  		    break;
+ 		}
  	    }
  
  	    slist = slist->right;
***************
*** 505,510 ****
--- 534,543 ----
  	if (sigtrapped[SIGDEBUG])
  	    dotrap(SIGDEBUG);
  	if (sourcelevel < 32768 && !donetrap) {
+ 	    /*
+ 	     * Only perform traps/errorexit if not in initialisation
+ 	     * scripts, and if we haven't performed them for this sublist.
+ 	     */
  	    if (sigtrapped[SIGZERR] && lastval) {
  		dotrap(SIGZERR);
  		donetrap = 1;
***************
*** 710,716 ****
      int pipes[2];
      int oldlineno = lineno;
  
!     if (breaks)
  	return;
      if (!pline)
  	return;
--- 743,749 ----
      int pipes[2];
      int oldlineno = lineno;
  
!     if (breaks || retflag)
  	return;
      if (!pline)
  	return;
***************
*** 1041,1048 ****
  		addnode(args, dupstring(nullcmd));
  	else {
  	    addvars(cmd->vars, 0);
! 	    if (errflag)
! 		lastval = 1;
  	    if (isset(XTRACE)) {
  		fputc('\n', stderr);
  		fflush(stderr);
--- 1074,1080 ----
  		addnode(args, dupstring(nullcmd));
  	else {
  	    addvars(cmd->vars, 0);
! 	    lastval = errflag;
  	    if (isset(XTRACE)) {
  		fputc('\n', stderr);
  		fflush(stderr);

-- 
Peter Stephenson <P.Stephenson@swansea.ac.uk>  Tel: +44 1792 205678 extn. 4461
WWW:  http://python.swan.ac.uk/~pypeters/      Fax: +44 1792 295324
Department of Physics, University of Wales, Swansea,
Singleton Park, Swansea, SA2 8PP, U.K.


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~1995-05-31 18:22 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1995-05-29 18:50 Some bugreports and a fix Zoltan Hidvegi
1995-05-31 17:45 ` P.Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).