From f429777918537edad9f24d219609f79d8a84eb78 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 11:49:45 +0900 Subject: [PATCH] [qfcc] Extend vector literal processing With this, all vector widths and types are supported: 2, 3, 4 and int, uint, long, ulong, float and double, along with support for suffixes to make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for literals with float-type components, and int (ivec2...) for those with integer-type components. --- tools/qfcc/source/qc-lex.l | 207 ++++++++++++++++++++++++++++++++++--- 1 file changed, 194 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index c74dcea4a..5a06a64db 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -80,7 +80,9 @@ int yyget_debug (void) __attribute__((pure)); FILE *yyget_in (void) __attribute__((pure)); FILE *yyget_out (void) __attribute__((pure)); -static int keyword_or_id (char *token); +static int keyword_or_id (const char *token); +static expr_t *parse_float_vector (const char *token, int width); +static expr_t *parse_int_vector (const char *token, int width); extern QC_YYSTYPE qc_yylval; @@ -95,7 +97,12 @@ ID [a-zA-Z_][a-zA-Z_0-9]* FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)? FLOATf {FLOAT}[fF] FLOATd {FLOAT}[dD] +FCOMP {m}?{FLOAT} +FD [fFdD] INT ({D}+|0[xX]{X}+|0[bB]{B}) +ICOMP {m}?{INT} +UL ([uU]?([lL][lL]?)?) +ULFD ({UL}|{FD}) RANGE \.\. ELLIPSIS \.\.\. FRAMEID {ID}(\.{ID})* @@ -122,7 +129,7 @@ STRING \"(\\.|[^"\\])*\" ^{s}*#{s}*pragma{s}+ { BEGIN (PRAGMA); } -{INT}+[uU]?([lL][lL]?)? { +{INT}+{UL}? { const char *c = yytext + yyleng - 1; int i; @@ -187,19 +194,33 @@ STRING \"(\\.|[^"\\])*\" } @ return '@'; -'{s}*{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}*' { - vec3_t v; - sscanf (yytext, "' %f %f %f '", - &v[0], &v[1], &v[2]); - qc_yylval.expr = new_vector_expr (v); +'{s}*{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 2); return VALUE; } -'{s}*{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}*' { - quat_t q; - sscanf (yytext, "' %f %f %f %f'", - &q[0], &q[1], &q[2], &q[3]); - qc_yylval.expr = new_quaternion_expr (q); +'{s}*{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 3); + return VALUE; + } + +'{s}*{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 4); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 2); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 3); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 4); return VALUE; } @@ -453,7 +474,7 @@ process_keyword (keyword_t *keyword, const char *token) } static int -keyword_or_id (char *token) +keyword_or_id (const char *token) { static hashtab_t *keyword_tab; static hashtab_t *qf_keyword_tab; @@ -525,6 +546,166 @@ keyword_or_id (char *token) return NAME; } +static expr_t * +parse_int_vector (const char *token, int width) +{ + char t1 = 0, t2 = 0; + type_t *type = 0; + + union { + pr_long_t l[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } long_data = {}; + pr_type_t *data = __builtin_choose_expr ( + sizeof (pr_long_t) == sizeof (long), long_data.t, (void) 0); + + switch (width) { + case 4: + sscanf (token, "' %li %li %li %li '%c%c", + &long_data.l[0], &long_data.l[1], + &long_data.l[2], &long_data.l[3], &t1, &t2); + break; + case 3: + sscanf (token, "' %li %li %li '%c%c", + &long_data.l[0], &long_data.l[1], + &long_data.l[2], &t1, &t2); + break; + case 2: + sscanf (token, "' %li %li '%c%c", + &long_data.l[0], &long_data.l[1], &t1, &t2); + break; + } + t1 = tolower (t1); + t2 = tolower (t2); + switch (t1) { + case 'u': + if (t2 == 'l') { + type = &type_ulong; + } else { + type = &type_uint; + volatile union { + pr_uint_t u[4]; + pr_type_t t[PR_SIZEOF (ivec4)]; + } uint_data = { + .u = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) uint_data.t; + } + break; + case 'l': + type = &type_long; + break; + case 'f': + type = &type_float; + volatile union { + pr_float_t f[4]; + pr_type_t t[PR_SIZEOF (vec4)]; + } float_data = { + .f = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) float_data.t; + break; + case 'd': + type = &type_double; + volatile union { + pr_double_t d[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } double_data = { + .d = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) double_data.t; + break; + case 0: + type = &type_int; + volatile union { + pr_int_t i[4]; + pr_type_t t[PR_SIZEOF (ivec4)]; + } int_data = { + .i = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) int_data.t; + break; + } + type = vector_type (type, width); + expr_t *expr = new_value_expr (new_type_value (type, data)); + expr->implicit = !t1; + return expr; +} + +static expr_t * +parse_float_vector (const char *token, int width) +{ + char t = 0; + type_t *type = 0; + + union { + pr_double_t d[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } double_data = {}; + pr_type_t *data = __builtin_choose_expr ( + sizeof (pr_double_t) == sizeof (double), double_data.t, (void) 0); + + switch (width) { + case 4: + sscanf (token, "' %lf %lf %lf %lf '%c", + &double_data.d[0], &double_data.d[1], + &double_data.d[2], &double_data.d[3], &t); + break; + case 3: + sscanf (token, "' %lf %lf %lf '%c", + &double_data.d[0], &double_data.d[1], + &double_data.d[1], &t); + type = (t == 'f' || t == 'F') ? &type_vec3 : &type_dvec3; + break; + case 2: + sscanf (token, "' %lf %lf '%c", + &double_data.d[0], &double_data.d[1], &t); + type = (t == 'f' || t == 'F') ? &type_vec2 : &type_dvec2; + break; + } + if (t == 'f' || t == 'F') { + volatile union { + pr_float_t f[4]; + pr_type_t t[PR_SIZEOF (vec4)]; + } float_data = { + .f = { + double_data.d[0], + double_data.d[1], + double_data.d[2], + double_data.d[3], + } + }; + data = (pr_type_t *) float_data.t; + type = &type_float; + } else { + type = &type_double; + } + type = vector_type (type, width); + expr_t *expr = new_value_expr (new_type_value (type, data)); + expr->implicit = !t; + return expr; +} + #ifdef YY_FLEX_REALLOC_HACK static __attribute__ ((used)) void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc; #else