vkd3d-shader/hlsl: Parse string escape sequences.

This commit is contained in:
Francisco Casas 2024-07-17 11:22:44 -04:00 committed by Henri Verbeet
parent 090df488ba
commit 652db433e1
Notes: Henri Verbeet 2024-08-07 16:01:12 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/962

View File

@ -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';
}