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:
parent
d2832063c3
commit
1628305811
1 changed files with 53 additions and 45 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue