From f0d5c047342c7bc68c5a75751cb2e3434c9273ca Mon Sep 17 00:00:00 2001 From: Petri Lehtinen Date: Mon, 3 Oct 2011 21:35:51 +0300 Subject: [PATCH] Make identifier decoding work under all locales Replace isxxx() functions from ctype.h with locale-independent macros. Fixes GH-35. --- src/load.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/load.c b/src/load.c index 36fc9e9..8942dd9 100644 --- a/src/load.c +++ b/src/load.c @@ -6,7 +6,6 @@ */ #define _GNU_SOURCE -#include #include #include #include @@ -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);