{
int ch = 0;
int nextch;
+ bool hex;
+ char u8buf[8]; /* way more than enough */
+ int u8len, uc;
while (ch != EOF)
{
case ']': ch = 17; break;
case '{':
ch = 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')
+ ch = ch * 10 + nextch - '0';
+ else {
+ lexerror(lex, "bad character code");
+ return (lex->tok.ttype = TOKEN_ERROR);
+ }
+ } else {
+ if (nextch >= '0' || nextch <= '9')
+ ch = ch * 16 + nextch - '0';
+ else if (nextch >= 'a' && nextch <= 'f')
+ ch = ch * 16 + nextch - 'a' + 10;
+ else if (nextch >= 'A' && nextch <= 'F')
+ ch = ch * 16 + nextch - 'A' + 10;
+ else {
+ lexerror(lex, "bad character code");
+ return (lex->tok.ttype = TOKEN_ERROR);
+ }
+ }
+ if ( (!OPTS_FLAG(UTF8) && ch > 255) ||
+ ( OPTS_FLAG(UTF8) && ch > 0x10FFFF) )
+ {
+ lexerror(lex, "character code out of range");
return (lex->tok.ttype = TOKEN_ERROR);
}
}
+ if (OPTS_FLAG(UTF8) && ch >= 128) {
+ u8len = u8_fromchar((Uchar)ch, 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];
+ }
+ }
break;
case '\n': ch = '\n'; break;
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 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, "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;
/** Analyze the next character and return various information if requested.
* @param _s An utf-8 string.
* @param _start Filled with the start byte-offset of the next valid character
- * @param _len Fileed with the length of the next valid character
+ * @param _len Filled with the length of the next valid character
* @param _ch Filled with the unicode value of the next character
* @param _maxlen Maximum number of bytes to read from _s
* @return Whether or not another valid character is in the string
*/
-static bool u8_analyze(const char *_s, size_t *_start, size_t *_len, Uchar *_ch, size_t _maxlen)
+bool u8_analyze(const char *_s, size_t *_start, size_t *_len, Uchar *_ch, size_t _maxlen)
{
const unsigned char *s = (const unsigned char*)_s;
size_t i, j;