diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index 5552bbc4..b4db142f 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d-shader/hlsl.l @@ -29,6 +29,8 @@ static void update_location(struct hlsl_ctx *ctx, YYLTYPE *loc); +static void apply_escape_sequences(char *str); + #define YY_USER_ACTION update_location(yyget_extra(yyscanner), yyget_lloc(yyscanner)); %} @@ -53,7 +55,7 @@ RESERVED4 typename|union|using|virtual WS [ \t] NEWLINE (\n)|(\r\n) -STRING \"[^\"]*\" +STRING \"([^\"\\]|\\.)*\" IDENTIFIER [A-Za-z_][A-Za-z0-9_]* ANY (.) @@ -213,6 +215,7 @@ while {return KW_WHILE; } char *string = hlsl_strdup(ctx, yytext + 1); string[strlen(string) - 1] = 0; + apply_escape_sequences(string); yylval->name = string; return STRING; } @@ -301,6 +304,7 @@ while {return KW_WHILE; } BEGIN(pp_ignore); string[strlen(string) - 1] = 0; + apply_escape_sequences(string); yylval->name = string; return STRING; } @@ -350,3 +354,115 @@ int hlsl_lexer_compile(struct hlsl_ctx *ctx, const struct vkd3d_shader_code *hls yylex_destroy(ctx->scanner); return ret; } + +static void apply_escape_sequences(char *str) +{ + unsigned int i = 0, k = 0, r; + + while (str[i]) + { + unsigned char v = 0; + + if (str[i] != '\\') + { + str[k++] = str[i]; + ++i; + continue; + } + + ++i; + VKD3D_ASSERT(str[i]); + + if ('0' <= str[i] && str[i] <= '7') + { + /* octal, up to 3 digits. */ + for (r = 0; r < 3; ++r) + { + char c = str[i]; + + if ('0' <= c && c <= '7') + { + v = v << 3; + v += c - '0'; + ++i; + } + else + break; + } + str[k++] = v; + continue; + } + + if (str[i] == 'x') + { + bool number = false; + + /* hexadecimal */ + ++i; + while (1) + { + char c = str[i]; + + if ('0' <= c && c <= '9') + { + v = v << 4; + v += c - '0'; + number = true; + ++i; + } + else if ('a' <= c && c <= 'f') + { + v = v << 4; + v += c - 'a' + 10; + number = true; + ++i; + } + else if ('A' <= c && c <= 'F') + { + v = v << 4; + v += c - 'A' + 10; + number = true; + ++i; + } + else + break; + } + if (number) + str[k++] = v; + else + str[k++] = 'x'; + continue; + } + + switch (str[i]) + { + case 'a': + str[k++] = '\a'; + break; + case 'b': + str[k++] = '\b'; + break; + case 'f': + str[k++] = '\f'; + break; + case 'n': + str[k++] = '\n'; + break; + case 'r': + str[k++] = '\r'; + break; + case 't': + str[k++] = '\t'; + break; + case 'v': + str[k++] = '\v'; + break; + + default: + str[k++] = str[i]; + break; + } + ++i; + } + str[k++] = '\0'; +}