[gnu.bash.bug] Bash functions incompatibility with sh?

brian@radio.astro.utoronto.ca (Brian Glendenning) (06/27/89)

The following may not be a bug, it may be due to my not understanding
shell functions properly. It does, however,  seem to be at least an
incompatibility with sh (the one on SunOS 4.0.1 anyway), and I would
also appreciate knowing the correct way to do this type of thing if
I'm mishandling the syntax.

Under sh if I type:

c() { for i in a b c d; do echo $i; done ; }

then "c" does what I expect (i.e. echoes a b c d each on a new line).
However under bash exactly the same line gives me:

syntax error near `do'

So, I'd like to report this incompatibility, and ask for the correct
syntax for getting "for" "while" "if" and friends into bash shell
functions. Thanks.

--
	  Brian Glendenning - Radio astronomy, University of Toronto
brian@radio.astro.utoronto.ca uunet!utai!radio!brian  glendenn@utorphys.bitnet
-- 
	  Brian Glendenning - Radio astronomy, University of Toronto
brian@radio.astro.utoronto.ca uunet!utai!radio!brian  glendenn@utorphys.bitnet

bfox@AUREL.CALTECH.EDU (Brian Fox) (06/27/89)

   Date: 26 Jun 89 20:10:03 GMT
   From: brian@radio.astro  (Brian Glendenning)
   Organization: Radio Astronomy, Univeristy of Toronto
   Sender: bug-bash-request@prep.ai.mit.edu

   The following may not be a bug...

It was a bug. I've enclosed the fix.

   Under sh if I type:

   c() { for i in a b c d; do echo $i; done ; }

   then "c" does what I expect (i.e. echoes a b c d each on a new line).
   However under bash exactly the same line gives me:

   syntax error near `do'

Two problems:

	1) Because Bash does curly brace expansion, the curly brace
	   character cannot be a reserved word, and has to be found
	   specially.  I fixed that.

	2) After fixing that, I noticed that FOR wasn't being
	   recognized, since it wasn't (according to the buggy code)
	   in a place where reserved words can appear.  So I fixed
	   that.
	
----------------------------------------
File: /usr/gnu/src/bash/parse.y-diffs
----------------------------------------
*** bash-1.01/parse.y	Fri Jun 23 00:10:32 1989
--- parse.y	Mon Jun 26 16:42:24 1989
***************
*** 970,977 ****
    
  /* When non-zero, we have read the required tokens
     which allow ESAC to be the next one read. */
! int allow_esac_as_next = 0;
  
  /* If non-zero, it is the token that we want read_token to return regardless
     of what text is (or isn't) present to be read.  read_token resets this. */
  int token_to_read = 0;
--- 970,980 ----
    
  /* When non-zero, we have read the required tokens
     which allow ESAC to be the next one read. */
! static int allow_esac_as_next = 0;
  
+ /* When non-zero, accept single '{' as a token itself. */
+ static int allow_open_brace = 0;
+ 
  /* If non-zero, it is the token that we want read_token to return regardless
     of what text is (or isn't) present to be read.  read_token resets this. */
  int token_to_read = 0;
***************
*** 1076,1081 ****
--- 1079,1092 ----
  	    return (AND_GREATER);
  	}
        shell_ungetc (peek_char);
+ 
+       /* If we look like we are reading the start of a function
+ 	 definition, then let the reader know about it so that
+ 	 we will do the right thing with `{'. */
+       if (character == ')' && last_read_token == '(' &&
+ 	  token_before_that == WORD)
+ 	allow_open_brace = 1;
+ 
        return (character);
      }
  
***************
*** 1268,1274 ****
  got_token:
  
      token[token_index] = '\0';
! 
      if ((delimiter || dollar_paren_level) && character == EOF)
        {
  	if (dollar_paren_level && !delimiter)
--- 1279,1285 ----
  got_token:
  
      token[token_index] = '\0';
! 	
      if ((delimiter || dollar_paren_level) && character == EOF)
        {
  	if (dollar_paren_level && !delimiter)
***************
*** 1293,1298 ****
--- 1304,1310 ----
  	    return (NUMBER);
  	  }
        }
+ 
      /* Handle special case.  IN is recognized if the last token
         was WORD and the token before that was FOR or CASE. */
      if ((strcmp (token, "in") == 0) &&
***************
*** 1324,1335 ****
        }
  
      /* Ditto for `{' in the FUNCTION case. */
!     if ((strcmp (token, "{") == 0) &&
! 	(last_read_token == WORD) &&
! 	(token_before_that == FUNCTION))
!       return ('{');
  
!     if (!dollar_present && !quoted && reserved_word_acceptable (last_read_token))
        {
  	/* Check to see if it is a reserved word. */
  	int i;
--- 1336,1350 ----
        }
  
      /* Ditto for `{' in the FUNCTION case. */
!     if (allow_open_brace)
!       {
! 	allow_open_brace = 0;
! 	if (strcmp (token, "{") == 0)
! 	  return ('{');
!       }
  
!     if (!dollar_present && !quoted &&
! 	reserved_word_acceptable (last_read_token))
        {
  	/* Check to see if it is a reserved word. */
  	int i;
***************
*** 1356,1362 ****
  reserved_word_acceptable (token)
       int token;
  {
!   if (member (last_read_token, "\n;()|&") ||
        last_read_token == AND_AND ||
        last_read_token == OR_OR ||
        last_read_token == SEMI_SEMI ||
--- 1371,1377 ----
  reserved_word_acceptable (token)
       int token;
  {
!   if (member (last_read_token, "\n;()|&{") ||
        last_read_token == AND_AND ||
        last_read_token == OR_OR ||
        last_read_token == SEMI_SEMI ||
***************
*** 1510,1516 ****
  	    case 'h':
  	      {
  		extern char *current_host_name;
! 		char *t_string;
  
  		temp = savestring (current_host_name);
  		if (t_string = index (temp, '.'))
--- 1525,1531 ----
  	    case 'h':
  	      {
  		extern char *current_host_name;
! 		char *t_string, *index ();
  
  		temp = savestring (current_host_name);
  		if (t_string = index (temp, '.'))
----------------------------------------