error message for missing fi is not helpful

2018-09-12 Thread Manuel Reiter

++ Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu'
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib
-Wdate-time -D_FORTIFY_SOURCE=2 -g -O2
-fdebug-prefix-map=/build/bash-7fckc0/bash-4.4=.
-fstack-protector-strong -Wformat -Werror=format-security -Wall -no-pie
-Wno-parentheses -Wno-format-security
uname output: Linux eeyore 4.9.0-4-amd64 #1 SMP Debian 4.9.65-3
(2017-12-03) x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.4
Patch Level: 12
Release Status: release

++ Description:

When an if statement is not terminated by a fi, bash's error message is
not helpful in locating the problem.

This was mentioned in
http://lists.gnu.org/archive/html/bug-bash/2008-06/msg00105.html but
never replied to.

I don't know whether bash allows an if statement to be terminated by EOF
(as it does for a here document which was the original subject of the
cited post) but even if it does, a warning message might be helpful.

This applies to case not being terminated by esac (and possibly other
commands) as well.

++ Repeat-By:

+ run the following script in bash:
--snip
#!/bin/bash
if true
then
  exit 0
# fi missing

exit 1
-- snip

+ expected output:

./test.bash: line 2: syntax error: if without corresponding fi

or at least

./test.bash: line 2: warning: if without corresponding fi

+ actual output:

./test.bash: line 8: syntax error: unexpected end of file



Re: error message for missing fi is not helpful

2018-09-14 Thread Manuel Reiter

On 13.09.2018 04:29, L A Walsh wrote:

This isn't *exactly* what you wanted, but this gives the line number
of the last unmatched statement (but doesn't tell you what the statement
was).  The diff was against bash-4.4.23 (4.4 base w/23 patches)


Thank you for taking the time to look into this! There seems to be a 
problem with your code though: if word_top is zero and EOF_Reached is 
true, you set msg to msg0 without initializing msg0 first.


Reviving the code you commented out (your first attempt?) I came to the 
attached result. I also added if/fi to the compound commands tracked by 
word_top. There are probably others that I have missed missed.



Anyway, if you store the word in a separate array where the line #
is stored, you _could_ list the matching word, but I suspect just the
line it started on would be enough for most users.


I totally agree with that.

Thanks and best regards,

  Manuel
diff --git a/parse.y.orig b/parse.y
index f415d2e..76974f0 100644
--- a/parse.y.orig
+++ b/parse.y
@@ -1000,11 +1000,11 @@ coproc:		COPROC shell_command
 	;
 
 if_command:	IF compound_list THEN compound_list FI
-			{ $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
+			{ $$ = make_if_command ($2, $4, (COMMAND *)NULL); if (word_top > 0) word_top--; }
 	|	IF compound_list THEN compound_list ELSE compound_list FI
-			{ $$ = make_if_command ($2, $4, $6); }
+			{ $$ = make_if_command ($2, $4, $6); if (word_top > 0) word_top--; }
 	|	IF compound_list THEN compound_list elif_clause FI
-			{ $$ = make_if_command ($2, $4, $5); }
+			{ $$ = make_if_command ($2, $4, $5); if (word_top > 0) word_top--; }
 	;
 
 
@@ -5142,6 +5142,7 @@ got_token:
 case CASE:
 case SELECT:
 case FOR:
+case IF:
   if (word_top < MAX_CASE_NEST)
 	word_top++;
   word_lineno[word_top] = line_number;
@@ -6020,9 +6021,13 @@ report_syntax_error (message)
 print_offending_line ();
 }
   else
-{
-  msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
-  parser_error (line_number, "%s", msg);
+{ 
+  if (EOF_Reached && word_top>=0) {
+parser_error(line_number, _("syntax error: unexpected end of file from line %d."), word_lineno[word_top] );
+  } else {
+msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
+parser_error (line_number, "%s", msg);
+  }
   /* When the shell is interactive, this file uses EOF_Reached
 	 only for error reporting.  Other mechanisms are used to
 	 decide whether or not to exit. */