/* Number of characters that can be pushed back.
- We need 1 for lex_getc, plus 1 for lex_ungetc. */
-#define NPUSHBACK 2
+ We need 1 for mbfile_getc_normalized, plus 1 for lex_getc,
+ plus 1 for lex_ungetc. */
+#define MBFILE_MAX_PUSHBACK 3
/* Data type of a multibyte character input stream. */
struct mbfile
{
FILE *fp;
bool eof_seen;
- int have_pushback;
+ unsigned int pushback_count; /* <= MBFILE_MAX_PUSHBACK */
unsigned int bufcount;
char buf[MBCHAR_BUF_SIZE];
- struct mbchar pushback[NPUSHBACK];
+ struct mbchar pushback[MBFILE_MAX_PUSHBACK];
};
/* We want to pass multibyte streams by reference automatically,
{
mbf->fp = stream;
mbf->eof_seen = false;
- mbf->have_pushback = 0;
+ mbf->pushback_count = 0;
mbf->bufcount = 0;
}
{
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->have_pushback > 0)
+ if (mbf->pushback_count > 0)
{
- mbf->have_pushback--;
- mb_copy (mbc, &mbf->pushback[mbf->have_pushback]);
+ mbf->pushback_count--;
+ mb_copy (mbc, &mbf->pushback[mbf->pushback_count]);
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;
+
/* Before using iconv, we need at least one byte. */
if (mbf->bufcount == 0)
{
static void
mbfile_ungetc (const mbchar_t mbc, mbfile_t mbf)
{
- if (mbf->have_pushback >= NPUSHBACK)
+ if (mbf->pushback_count >= MBFILE_MAX_PUSHBACK)
abort ();
- mb_copy (&mbf->pushback[mbf->have_pushback], mbc);
- mbf->have_pushback++;
+ mb_copy (&mbf->pushback[mbf->pushback_count], mbc);
+ mbf->pushback_count++;
}
}
+/* Read a single character, collapsing the Windows CRLF line terminator
+ to a single LF.
+ Supports 1 character of pushback (via mbfile_ungetc). */
+static void
+mbfile_getc_normalized (struct po_parser_state *ps, mbchar_t mbc, mbfile_t mbf)
+{
+ mbfile_getc (ps, mbc, ps->mbf);
+ if (!mb_iseof (mbc) && mb_iseq (mbc, '\r'))
+ {
+ mbchar_t mbc2;
+
+ mbfile_getc (ps, mbc2, ps->mbf);
+ if (!mb_iseof (mbc2))
+ {
+ if (mb_iseq (mbc2, '\n'))
+ /* Eliminate the CR. */
+ mb_copy (mbc, mbc2);
+ else
+ {
+ mbfile_ungetc (mbc2, ps->mbf);
+ /* If we get here, the caller can still do
+ mbfile_ungetc (mbc, ps->mbf);
+ since mbfile_getc supports 2 characters of pushback. */
+ }
+ }
+ }
+}
+
+
/* Read a single character, dealing with backslash-newline.
Also keep track of the current line number and column number. */
static void
{
for (;;)
{
- mbfile_getc (ps, mbc, ps->mbf);
+ mbfile_getc_normalized (ps, mbc, ps->mbf);
if (mb_iseof (mbc))
{
{
mbchar_t mbc2;
- mbfile_getc (ps, mbc2, ps->mbf);
+ mbfile_getc_normalized (ps, mbc2, ps->mbf);
if (mb_iseof (mbc2))
{