Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Some bugreports and a fix



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@xxxxxxxxxx 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@xxxxxxxxxxxxx>  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.



Messages sorted by: Reverse Date, Date, Thread, Author