Adding a unit test for such pushback characters show that the EOF recognition
must be done with lower priority than the pushback character test.


2024-12-30  Bruno Haible  <br...@clisp.org>

        mbfile: Support pushback characters also right before EOF.
        * lib/mbfile.h (mbfile_multi_getc): Read pushed-back character before
        testing for sticky EOF.
        * tests/test-mbfile.c (main): Test pushback at EOF.

diff --git a/lib/mbfile.h b/lib/mbfile.h
index b110aff229..b36ed1c350 100644
--- a/lib/mbfile.h
+++ b/lib/mbfile.h
@@ -89,11 +89,6 @@ mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi 
*mbf)
   unsigned int new_bufcount;
   size_t bytes;
 
-  /* If EOF has already been seen, don't use getc.  This matters if
-     mbf->fp is connected to an interactive tty.  */
-  if (mbf->eof_seen)
-    goto eof;
-
   /* Return character pushed back, if there is one.  */
   if (mbf->pushback_count > 0)
     {
@@ -102,6 +97,11 @@ mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi 
*mbf)
       return;
     }
 
+  /* If EOF has already been seen, don't use getc.  This matters if
+     mbf->fp is connected to an interactive tty.  */
+  if (mbf->eof_seen)
+    goto eof;
+
   new_bufcount = mbf->bufcount;
 
   /* If mbf->state is not in an initial state, some more 32-bit wide character
diff --git a/tests/test-mbfile.c b/tests/test-mbfile.c
index 3565404294..c59803d308 100644
--- a/tests/test-mbfile.c
+++ b/tests/test-mbfile.c
@@ -45,6 +45,7 @@ main ()
   /* The input consists of 4 UTF-8 characters:
      '$', U+00A5, U+20AC, U+0001F403.  */
   mbf_char_t next;
+  mbf_char_t prev;
 
   mbf_getc (next, mbstdin);
   ASSERT (!mb_iseof (next));
@@ -65,9 +66,24 @@ main ()
   ASSERT (!mb_iseof (next));
   ASSERT (mb_len (next) == 4);
   ASSERT (mb_iseq (next, 0x1F403));
+  mb_copy (&prev, &next);
 
   mbf_getc (next, mbstdin);
   ASSERT (mb_iseof (next));
 
+  /* Even at EOF, we need to be able to push back 2 characters.  */
+  mbf_ungetc (next, mbstdin);
+  mbf_ungetc (prev, mbstdin);
+
+  mbf_char_t renext;
+
+  mbf_getc (renext, mbstdin);
+  ASSERT (!mb_iseof (renext));
+  ASSERT (mb_len (renext) == 4);
+  ASSERT (mb_iseq (renext, 0x1F403));
+
+  mbf_getc (renext, mbstdin);
+  ASSERT (mb_iseof (renext));
+
   return test_exit_status;
 }




Reply via email to