Avoid ungetc when loading charset maps from files

* src/charset.c (read_hex): New args LOOKAHEAD and TERMINATOR,
replacing the old EOF.  All callers changed.  This avoids the
need to call ungetc.
This commit is contained in:
Paul Eggert 2017-07-07 18:12:16 -07:00
parent d2832063c3
commit 1628305811

View file

@ -407,44 +407,49 @@ load_charset_map (struct charset *charset, struct charset_map_entries *entries,
/* Read a hexadecimal number (preceded by "0x") from the file FP while
paying attention to comment character '#'. */
paying attention to comment character '#'. LOOKAHEAD is the
lookahead byte if it is nonnegative. Store into *TERMINATOR the
input byte after the number, or EOF if an end-of-file or input
error occurred. Set *OVERFLOW if the number overflows. */
static unsigned
read_hex (FILE *fp, bool *eof, bool *overflow)
read_hex (FILE *fp, int lookahead, int *terminator, bool *overflow)
{
int c;
unsigned n;
int c = lookahead < 0 ? getc_unlocked (fp) : lookahead;
while ((c = getc_unlocked (fp)) != EOF)
{
if (c == '#')
{
while ((c = getc_unlocked (fp)) != EOF && c != '\n');
}
else if (c == '0')
{
if ((c = getc_unlocked (fp)) == EOF || c == 'x')
break;
}
}
if (c == EOF)
{
*eof = 1;
return 0;
}
n = 0;
while (true)
{
c = getc_unlocked (fp);
int digit = char_hexdigit (c);
if (digit < 0)
if (c == '#')
do
c = getc_unlocked (fp);
while (0 <= c && c != '\n');
else if (c == '0')
{
c = getc_unlocked (fp);
if (c < 0 || c == 'x')
break;
}
if (c < 0)
break;
if (INT_LEFT_SHIFT_OVERFLOW (n, 4))
*overflow = 1;
n = (n << 4) + digit;
c = getc_unlocked (fp);
}
if (c != EOF)
ungetc (c, fp);
unsigned n = 0;
bool v = false;
if (0 <= c)
while (true)
{
c = getc_unlocked (fp);
int digit = char_hexdigit (c);
if (digit < 0)
break;
v |= INT_LEFT_SHIFT_OVERFLOW (n, 4);
n = (n << 4) + digit;
}
*terminator = c;
*overflow |= v;
return n;
}
@ -499,23 +504,26 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
memset (entries, 0, sizeof (struct charset_map_entries));
n_entries = 0;
while (1)
int ch = -1;
while (true)
{
unsigned from, to, c;
int idx;
bool eof = 0, overflow = 0;
from = read_hex (fp, &eof, &overflow);
if (eof)
bool overflow = false;
unsigned from = read_hex (fp, ch, &ch, &overflow), to;
if (ch < 0)
break;
if (getc_unlocked (fp) == '-')
to = read_hex (fp, &eof, &overflow);
if (ch == '-')
{
to = read_hex (fp, -1, &ch, &overflow);
if (ch < 0)
break;
}
else
to = from;
if (eof)
break;
c = read_hex (fp, &eof, &overflow);
if (eof)
{
to = from;
ch = -1;
}
unsigned c = read_hex (fp, ch, &ch, &overflow);
if (ch < 0)
break;
if (overflow)
@ -530,7 +538,7 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
memset (entries, 0, sizeof (struct charset_map_entries));
n_entries = 0;
}
idx = n_entries;
int idx = n_entries;
entries->entry[idx].from = from;
entries->entry[idx].to = to;
entries->entry[idx].c = c;