Subject: bug#4616: 23.1.50; empty script files

From: Markus Rost <[email-masked]>
Date: Mon, 5 Oct 2009 05:11:36 +0200 (CEST)

What about the following tentative patch?

It moves the handling of '#!' from read1 up to readevalloop, which
then would skip the first line if it starts with '#!'.

To achieve this, the patch allows the readchar/unreadchar mechanism to
look 2 characters ahead, instead of just 1.

Omitting ' && first_sexp' in the patch would skip '#!' + rest of line
anywhere as before.

Be aware that I just made some guesses after glancing briefly over
lread.c (and I am not a C-programmer).

*** /home/rost/build/cvs/emacs/src/lread.c.~1.414~	2009-10-05 01:38:28.000000000 +0200
--- /home/rost/build/cvs/emacs/src/lread.c	2009-10-05 04:31:51.000000000 +0200
***************
*** 271,276 ****
--- 271,277 ----
     a file stream can't handle multibyte-char unreading.  The value -1
     means that there's no unread character. */
  static int unread_char;
+ static int unread_char1;
  
  static int
  readchar (readcharfun, multibyte)
***************
*** 410,415 ****
--- 411,422 ----
    return XINT (tem);
  
   read_multibyte:
+   if (unread_char1 >= 0)
+     {
+       c = unread_char1;
+       unread_char1 = -1;
+       return c;
+     }
    if (unread_char >= 0)
      {
        c = unread_char;
***************
*** 489,499 ****
      }
    else if (CONSP (readcharfun))
      {
!       unread_char = c;
      }
    else if (EQ (readcharfun, Qlambda))
      {
!       unread_char = c;
      }
    else if (EQ (readcharfun, Qget_file_char)
  	   || EQ (readcharfun, Qget_emacs_mule_file_char))
--- 496,512 ----
      }
    else if (CONSP (readcharfun))
      {
!       if (unread_char >= 0)
! 	unread_char1 = c;
!       else
! 	unread_char = c;
      }
    else if (EQ (readcharfun, Qlambda))
      {
!       if (unread_char >= 0)
! 	unread_char1 = c;
!       else
! 	unread_char = c;
      }
    else if (EQ (readcharfun, Qget_file_char)
  	   || EQ (readcharfun, Qget_emacs_mule_file_char))
***************
*** 505,511 ****
  	  UNBLOCK_INPUT;
  	}
        else
! 	unread_char = c;
      }
    else
      call1 (readcharfun, make_number (c));
--- 518,527 ----
  	  UNBLOCK_INPUT;
  	}
        else
! 	if (unread_char >= 0)
! 	  unread_char1 = c;
! 	else
! 	  unread_char = c;
      }
    else
      call1 (readcharfun, make_number (c));
***************
*** 1658,1663 ****
--- 1674,1680 ----
       Lisp_Object start, end;
  {
    register int c;
+   register int c1;
    register Lisp_Object val;
    int count = SPECPDL_INDEX ();
    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
***************
*** 1747,1752 ****
--- 1764,1782 ----
  	  unbind_to (count1, Qnil);
  	  break;
  	}
+       if (c == '#' && first_sexp)
+ 	{
+ 	  c1 = READCHAR;
+ 	  if (c1 == '!')
+ 	    {
+ 	      /* #! appears at the beginning of an executable file.
+ 		 Skip the first line.  */
+ 	      while ((c1 = READCHAR) != '\n' && c1 != -1);
+ 	      goto read_next;
+ 	    }
+ 	  else
+ 	    UNREAD (c1);
+ 	}
  
        /* Ignore whitespace here, so we can detect eof.  */
        if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r'
***************
*** 2607,2620 ****
  	  load_each_byte = 0;
  	  goto retry;
  	}
-       if (c == '!')
- 	{
- 	  /* #! appears at the beginning of an executable file.
- 	     Skip the first line.  */
- 	  while (c != '\n' && c >= 0)
- 	    c = READCHAR;
- 	  goto retry;
- 	}
        if (c == '$')
  	return Vload_file_name;
        if (c == '\'')
--- 2637,2642 ----