X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=lexer.c;h=30ac500ca0b95be47e26d6df7d28fbfd885bee53;hb=359ba5f728af7498fb7c6952edd75ef62534bd8f;hp=e506aec31ef8c105f7c3ef5de7a74eefd560d809;hpb=6bc29a1601b6326dad807ac4f1d6db9e37adb3b6;p=xonotic%2Fgmqcc.git diff --git a/lexer.c b/lexer.c index e506aec..30ac500 100644 --- a/lexer.c +++ b/lexer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 + * Copyright (C) 2012, 2013 * Wolfgang Bumiller * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -736,12 +736,18 @@ static bool lex_finish_frames(lex_file *lex) vec_shrinkto(lex->tok.value, 0); vec_push(lex->frames, m); } while (true); + + return false; } static int GMQCC_WARN lex_finish_string(lex_file *lex, int quote) { + uchar_t chr; int ch = 0; int nextch; + bool hex; + char u8buf[8]; /* way more than enough */ + int u8len, uc; while (ch != EOF) { @@ -822,14 +828,53 @@ static int GMQCC_WARN lex_finish_string(lex_file *lex, int quote) case '[': ch = 16; break; case ']': ch = 17; break; case '{': - ch = 0; + chr = 0; + nextch = lex_getch(lex); + hex = (nextch == 'x'); + if (!hex) + lex_ungetch(lex, nextch); for (nextch = lex_getch(lex); nextch != '}'; nextch = lex_getch(lex)) { - ch = ch * 10 + nextch - '0'; - if (nextch < '0' || nextch > '9' || ch > 255) { - lexerror(lex, "bad character code"); + if (!hex) { + if (nextch >= '0' && nextch <= '9') + chr = chr * 10 + nextch - '0'; + else { + lexerror(lex, "bad character code"); + return (lex->tok.ttype = TOKEN_ERROR); + } + } else { + if (nextch >= '0' && nextch <= '9') + chr = chr * 0x10 + nextch - '0'; + else if (nextch >= 'a' && nextch <= 'f') + chr = chr * 0x10 + nextch - 'a' + 10; + else if (nextch >= 'A' && nextch <= 'F') + chr = chr * 0x10 + nextch - 'A' + 10; + else { + lexerror(lex, "bad character code"); + return (lex->tok.ttype = TOKEN_ERROR); + } + } + if (chr > 0x10FFFF || (!OPTS_FLAG(UTF8) && chr > 255)) + { + lexerror(lex, "character code out of range"); return (lex->tok.ttype = TOKEN_ERROR); } } + if (OPTS_FLAG(UTF8) && chr >= 128) { + u8len = u8_fromchar(chr, u8buf, sizeof(u8buf)); + if (!u8len) + ch = 0; + else { + --u8len; + for (uc = 0; uc < u8len; ++uc) + lex_tokench(lex, u8buf[uc]); + /* the last character will be inserted with the tokench() call + * below the switch + */ + ch = u8buf[uc]; + } + } + else + ch = chr; break; case '\n': ch = '\n'; break; @@ -1386,10 +1431,20 @@ int lex_do(lex_file *lex) else { if (!lex->flags.preprocessing && strlen(lex->tok.value) > 1) { - if (lexwarn(lex, WARN_MULTIBYTE_CHARACTER, "multibyte character: `%s`", lex->tok.value)) - return (lex->tok.ttype = TOKEN_ERROR); + uchar_t u8char; + /* check for a valid utf8 character */ + if (!OPTS_FLAG(UTF8) || !u8_analyze(lex->tok.value, NULL, NULL, &u8char, 8)) { + if (lexwarn(lex, WARN_MULTIBYTE_CHARACTER, + ( OPTS_FLAG(UTF8) ? "invalid multibyte character sequence `%s`" + : "multibyte character: `%s`" ), + lex->tok.value)) + return (lex->tok.ttype = TOKEN_ERROR); + } + else + lex->tok.constval.i = u8char; } - lex->tok.constval.i = lex->tok.value[0]; + else + lex->tok.constval.i = lex->tok.value[0]; } return lex->tok.ttype;