Make identifier decoding work under all locales

Replace isxxx() functions from ctype.h with locale-independent macros.

Fixes GH-35.
This commit is contained in:
Petri Lehtinen 2011-10-03 21:35:51 +03:00
parent fd56deb7dd
commit f0d5c04734

View File

@ -6,7 +6,6 @@
*/
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
@ -32,6 +31,14 @@
#define TOKEN_FALSE 260
#define TOKEN_NULL 261
/* Locale independent versions of isxxx() functions */
#define l_isupper(c) ('A' <= c && c <= 'Z')
#define l_islower(c) ('a' <= c && c <= 'z')
#define l_isalpha(c) (l_isupper(c) || l_islower(c))
#define l_isdigit(c) ('0' <= c && c <= '9')
#define l_isxdigit(c) \
(l_isdigit(c) || 'A' <= c || c <= 'F' || 'a' <= c || c <= 'f')
/* Read one byte from stream, convert to unsigned char, then int, and
return. return EOF on end of file. This corresponds to the
behaviour of fgetc(). */
@ -268,11 +275,11 @@ static int32_t decode_unicode_escape(const char *str)
for(i = 1; i <= 4; i++) {
char c = str[i];
value <<= 4;
if(isdigit(c))
if(l_isdigit(c))
value += c - '0';
else if(islower(c))
else if(l_islower(c))
value += c - 'a' + 10;
else if(isupper(c))
else if(l_isupper(c))
value += c - 'A' + 10;
else
assert(0);
@ -317,7 +324,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
if(c == 'u') {
c = lex_get_save(lex, error);
for(i = 0; i < 4; i++) {
if(!isxdigit(c)) {
if(!l_isxdigit(c)) {
error_set(error, lex, "invalid escape");
goto out;
}
@ -455,14 +462,14 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
if(c == '0') {
c = lex_get_save(lex, error);
if(isdigit(c)) {
if(l_isdigit(c)) {
lex_unget_unsave(lex, c);
goto out;
}
}
else if(isdigit(c)) {
else if(l_isdigit(c)) {
c = lex_get_save(lex, error);
while(isdigit(c))
while(l_isdigit(c))
c = lex_get_save(lex, error);
}
else {
@ -496,14 +503,14 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
if(c == '.') {
c = lex_get(lex, error);
if(!isdigit(c)) {
if(!l_isdigit(c)) {
lex_unget(lex, c);
goto out;
}
lex_save(lex, c);
c = lex_get_save(lex, error);
while(isdigit(c))
while(l_isdigit(c))
c = lex_get_save(lex, error);
}
@ -512,13 +519,13 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
if(c == '+' || c == '-')
c = lex_get_save(lex, error);
if(!isdigit(c)) {
if(!l_isdigit(c)) {
lex_unget_unsave(lex, c);
goto out;
}
c = lex_get_save(lex, error);
while(isdigit(c))
while(l_isdigit(c))
c = lex_get_save(lex, error);
}
@ -570,17 +577,17 @@ static int lex_scan(lex_t *lex, json_error_t *error)
else if(c == '"')
lex_scan_string(lex, error);
else if(isdigit(c) || c == '-') {
else if(l_isdigit(c) || c == '-') {
if(lex_scan_number(lex, c, error))
goto out;
}
else if(isupper(c) || islower(c)) {
else if(l_isalpha(c)) {
/* eat up the whole identifier for clearer error messages */
const char *saved_text;
c = lex_get_save(lex, error);
while(isupper(c) || islower(c))
while(l_isalpha(c))
c = lex_get_save(lex, error);
lex_unget_unsave(lex, c);