The 'mbfile' module currently allows 1 character of pushback.
This is not always sufficient: In general, the number of pushback characters
required depends on the lexer / parser built on top of it.


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

        mbfile: Allow 2 pushback characters.
        * lib/mbfile.h: Include <stdlib.h>.
        (MBFILE_MAX_PUSHBACK): New macro.
        (struct mbfile_multi): Replace field 'have_pushback' with
        'pushback_count'. Make field 'pushback' an array.
        (mbfile_multi_getc, mbfile_multi_ungetc): Handle multiple pushback
        characters.
        (mbf_init): Update.

diff --git a/lib/mbfile.h b/lib/mbfile.h
index fe83eb648b..b110aff229 100644
--- a/lib/mbfile.h
+++ b/lib/mbfile.h
@@ -54,6 +54,7 @@
 
 #include <assert.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
 
@@ -69,14 +70,17 @@ extern "C" {
 #endif
 
 
+/* Guarantee two characters of pushback.  */
+#define MBFILE_MAX_PUSHBACK 2
+
 struct mbfile_multi {
   FILE *fp;
   bool eof_seen;
-  bool have_pushback;
+  unsigned int pushback_count; /* <= MBFILE_MAX_PUSHBACK */
   mbstate_t state;
   unsigned int bufcount;
   char buf[MBCHAR_BUF_SIZE];
-  struct mbchar pushback;
+  struct mbchar pushback[MBFILE_MAX_PUSHBACK];
 };
 
 MBFILE_INLINE void
@@ -91,10 +95,10 @@ mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi 
*mbf)
     goto eof;
 
   /* Return character pushed back, if there is one.  */
-  if (mbf->have_pushback)
+  if (mbf->pushback_count > 0)
     {
-      mb_copy (mbc, &mbf->pushback);
-      mbf->have_pushback = false;
+      mb_copy (mbc, &mbf->pushback[mbf->pushback_count - 1]);
+      mbf->pushback_count--;
       return;
     }
 
@@ -246,8 +250,10 @@ eof:
 MBFILE_INLINE void
 mbfile_multi_ungetc (const struct mbchar *mbc, struct mbfile_multi *mbf)
 {
-  mb_copy (&mbf->pushback, mbc);
-  mbf->have_pushback = true;
+  if (mbf->pushback_count == MBFILE_MAX_PUSHBACK)
+    abort ();
+  mb_copy (&mbf->pushback[mbf->pushback_count], mbc);
+  mbf->pushback_count++;
 }
 
 typedef struct mbfile_multi mb_file_t;
@@ -257,7 +263,7 @@ typedef mbchar_t mbf_char_t;
 #define mbf_init(mbf, stream)                                           \
   ((mbf).fp = (stream),                                                 \
    (mbf).eof_seen = false,                                              \
-   (mbf).have_pushback = false,                                         \
+   (mbf).pushback_count = 0,                                            \
    mbszero (&(mbf).state),                                              \
    (mbf).bufcount = 0)
 




Reply via email to