X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=lexer.c;h=10e049f039af7aebea79d9c74acf057882475ea8;hb=2a568dda2ebe09066e0a71f22b22aa9488881aa4;hp=10bca9d9c72f6239d7c0baeefa697b9d0dd8ec7c;hpb=43e48b16faa9d8bc68a25656648842f90f9977c6;p=cparser diff --git a/lexer.c b/lexer.c index 10bca9d..10e049f 100644 --- a/lexer.c +++ b/lexer.c @@ -43,7 +43,7 @@ //#define DEBUG_CHARS #define MAX_PUTBACK 3 -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) /* No strtold on windows and no replacement yet */ #define strtold(s, e) strtod(s, e) #endif @@ -65,7 +65,7 @@ bool allow_dollar_in_symbol = true; */ static void parse_error(const char *msg) { - errorf(&lexer_token.source_position, "%s", msg); + errorf(&lexer_token.source_position, "%s", msg); } /** @@ -75,7 +75,7 @@ static void parse_error(const char *msg) */ static NORETURN internal_error(const char *msg) { - internal_errorf(&lexer_token.source_position, "%s", msg); + internal_errorf(&lexer_token.source_position, "%s", msg); } static inline void next_real_char(void) @@ -96,7 +96,7 @@ static inline void next_real_char(void) bufpos = buf + MAX_PUTBACK; bufend = buf + MAX_PUTBACK + s; } - c = *bufpos++; + c = (unsigned char)*bufpos++; } /** @@ -304,60 +304,78 @@ end_symbol: static void parse_integer_suffix(bool is_oct_hex) { - bool is_unsigned = false; - bool min_long = false; - bool min_longlong = false; - - if(c == 'U' || c == 'u') { - is_unsigned = true; + bool is_unsigned = false; + bool min_long = false; + bool min_longlong = false; + bool not_traditional = false; + int pos = 0; + char suffix[4]; + + if (c == 'U' || c == 'u') { + not_traditional = true; + suffix[pos++] = toupper(c); + is_unsigned = true; next_char(); - if(c == 'L' || c == 'l') { + if (c == 'L' || c == 'l') { + suffix[pos++] = toupper(c); min_long = true; next_char(); - if(c == 'L' || c == 'l') { + if (c == 'L' || c == 'l') { + suffix[pos++] = toupper(c); min_longlong = true; next_char(); } } - } else if(c == 'l' || c == 'L') { + } else if (c == 'l' || c == 'L') { + suffix[pos++] = toupper(c); min_long = true; next_char(); - if(c == 'l' || c == 'L') { - min_longlong = true; + if (c == 'l' || c == 'L') { + not_traditional = true; + suffix[pos++] = toupper(c); + min_longlong = true; next_char(); - if(c == 'u' || c == 'U') { - is_unsigned = true; + if (c == 'u' || c == 'U') { + suffix[pos++] = toupper(c); + is_unsigned = true; next_char(); } - } else if(c == 'u' || c == 'U') { - is_unsigned = true; + } else if (c == 'u' || c == 'U') { + not_traditional = true; + suffix[pos++] = toupper(c); + is_unsigned = true; next_char(); lexer_token.datatype = type_unsigned_long; } } - if(!is_unsigned) { + if (warning.traditional && not_traditional) { + suffix[pos] = '\0'; + warningf(&lexer_token.source_position, + "traditional C rejects the '%s' suffix", suffix); + } + if (!is_unsigned) { long long v = lexer_token.v.intvalue; - if(!min_long) { - if(v >= TARGET_INT_MIN && v <= TARGET_INT_MAX) { + if (!min_long) { + if (v >= TARGET_INT_MIN && v <= TARGET_INT_MAX) { lexer_token.datatype = type_int; return; - } else if(is_oct_hex && v >= 0 && v <= TARGET_UINT_MAX) { + } else if (is_oct_hex && v >= 0 && v <= TARGET_UINT_MAX) { lexer_token.datatype = type_unsigned_int; return; } } - if(!min_longlong) { - if(v >= TARGET_LONG_MIN && v <= TARGET_LONG_MAX) { + if (!min_longlong) { + if (v >= TARGET_LONG_MIN && v <= TARGET_LONG_MAX) { lexer_token.datatype = type_long; return; - } else if(is_oct_hex && v >= 0 && (unsigned long long)v <= (unsigned long long)TARGET_ULONG_MAX) { + } else if (is_oct_hex && v >= 0 && (unsigned long long)v <= (unsigned long long)TARGET_ULONG_MAX) { lexer_token.datatype = type_unsigned_long; return; } } unsigned long long uv = (unsigned long long) v; - if(is_oct_hex && uv > (unsigned long long) TARGET_LONGLONG_MAX) { + if (is_oct_hex && uv > (unsigned long long) TARGET_LONGLONG_MAX) { lexer_token.datatype = type_unsigned_long_long; return; } @@ -365,11 +383,11 @@ static void parse_integer_suffix(bool is_oct_hex) lexer_token.datatype = type_long_long; } else { unsigned long long v = (unsigned long long) lexer_token.v.intvalue; - if(!min_long && v <= TARGET_UINT_MAX) { + if (!min_long && v <= TARGET_UINT_MAX) { lexer_token.datatype = type_unsigned_int; return; } - if(!min_longlong && v <= TARGET_ULONG_MAX) { + if (!min_longlong && v <= TARGET_ULONG_MAX) { lexer_token.datatype = type_unsigned_long; return; } @@ -383,11 +401,19 @@ static void parse_floating_suffix(void) /* TODO: do something useful with the suffixes... */ case 'f': case 'F': + if (warning.traditional) { + warningf(&lexer_token.source_position, + "traditional C rejects the 'F' suffix"); + } next_char(); lexer_token.datatype = type_float; break; case 'l': case 'L': + if (warning.traditional) { + warningf(&lexer_token.source_position, + "traditional C rejects the 'F' suffix"); + } next_char(); lexer_token.datatype = type_long_double; break; @@ -818,11 +844,15 @@ static int parse_escape_sequence(void) case EOF: parse_error("reached end of file while parsing escape sequence"); return EOF; + /* \E is not documented, but handled, by GCC. It is acceptable according + * to §6.11.4, whereas \e is not. */ + case 'E': case 'e': if (c_mode & _GNUC) - return 27; /* hopefully 27 is ALWAYS the code for ESACAPE */ - /*fallthrough*/ + return 27; /* hopefully 27 is ALWAYS the code for ESCAPE */ + /* FALLTHROUGH */ default: + /* §6.4.4.4:8 footnote 64 */ parse_error("unknown escape sequence"); return EOF; } @@ -840,6 +870,10 @@ string_t concat_strings(const string_t *const s1, const string_t *const s2) memcpy(concat, s1->begin, len1); memcpy(concat + len1, s2->begin, len2 + 1); + if (warning.traditional) { + warningf(&lexer_token.source_position, + "traditional C rejects string constant concatenation"); + } #if 0 /* TODO hash */ const char *result = strset_insert(&stringset, concat); if(result != concat) { @@ -866,6 +900,10 @@ wide_string_t concat_string_wide_string(const string_t *const s1, const wide_str concat[i] = src[i]; } memcpy(concat + len1, s2->begin, (len2 + 1) * sizeof(*concat)); + if (warning.traditional) { + warningf(&lexer_token.source_position, + "traditional C rejects string constant concatenation"); + } return (wide_string_t){ concat, len1 + len2 + 1 }; } @@ -881,6 +919,10 @@ wide_string_t concat_wide_strings(const wide_string_t *const s1, const wide_stri wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat)); memcpy(concat, s1->begin, len1 * sizeof(*concat)); memcpy(concat + len1, s2->begin, (len2 + 1) * sizeof(*concat)); + if (warning.traditional) { + warningf(&lexer_token.source_position, + "traditional C rejects string constant concatenation"); + } return (wide_string_t){ concat, len1 + len2 + 1 }; } @@ -895,9 +937,14 @@ wide_string_t concat_wide_string_string(const wide_string_t *const s1, const str wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat)); memcpy(concat, s1->begin, len1 * sizeof(*concat)); - const char *const src = s2->begin; + const char *const src = s2->begin; + wchar_rep_t *const dst = concat + len1; for (size_t i = 0; i != len2 + 1; ++i) { - concat[i] = src[i]; + dst[i] = src[i]; + } + if (warning.traditional) { + warningf(&lexer_token.source_position, + "traditional C rejects string constant concatenation"); } return (wide_string_t){ concat, len1 + len2 + 1 }; @@ -1135,7 +1182,7 @@ end_of_char_constant:; lexer_token.type = T_CHARACTER_CONSTANT; lexer_token.v.string.begin = string; lexer_token.v.string.size = size; - lexer_token.datatype = type_int; + lexer_token.datatype = c_mode & _CXX && size == 1 ? type_char : type_int; } /** @@ -1150,7 +1197,10 @@ static void skip_multiline_comment(void) case '/': next_char(); if (c == '*') { - /* TODO: nested comment, warn here */ + /* nested comment, warn here */ + if (warning.comment) { + warningf(&lexer_token.source_position, "'/*' within comment"); + } } break; case '*': @@ -1192,6 +1242,15 @@ static void skip_line_comment(void) case '\r': return; + case '\\': + next_char(); + if (c == '\n' || c == '\r') { + if (warning.comment) + warningf(&lexer_token.source_position, "multi-line comment"); + return; + } + break; + default: next_char(); break;