From 68ca2c496298573553f0cf98d2cf556c25b591ee Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Thu, 25 Apr 2013 17:08:02 +0000 Subject: [PATCH] Pushing the -fexpressions-for-builtins stuff and the modff for catching fractional-part builtin numbers. --- main.c | 1 + opts.def | 1 + parser.c | 70 ++++++++++++++++++++++++++++++++++---------------------- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/main.c b/main.c index 60780ef..498386c 100644 --- a/main.c +++ b/main.c @@ -173,6 +173,7 @@ static bool options_parse(int argc, char **argv) { opts_set(opts.flags, INITIALIZED_NONCONSTANTS, true); opts_set(opts.werror, WARN_INVALID_PARAMETER_COUNT, true); opts_set(opts.werror, WARN_MISSING_RETURN_VALUES, true); + opts_set(opts.flags, EXPRESSIONS_FOR_BUILTINS, true); OPTS_OPTION_U32(OPTION_STANDARD) = COMPILER_GMQCC; diff --git a/opts.def b/opts.def index f7b5cf1..a9301a5 100644 --- a/opts.def +++ b/opts.def @@ -50,6 +50,7 @@ GMQCC_DEFINE_FLAG(PERMISSIVE) GMQCC_DEFINE_FLAG(VARIADIC_ARGS) GMQCC_DEFINE_FLAG(LEGACY_VECTOR_MATHS) + GMQCC_DEFINE_FLAG(EXPRESSIONS_FOR_BUILTINS) #endif /* warning flags */ diff --git a/parser.c b/parser.c index d95a446..14cf583 100644 --- a/parser.c +++ b/parser.c @@ -5639,9 +5639,11 @@ skipvar: } if (parser->tok == '#') { - ast_function *func = NULL; - ast_value *number; - int builtin_num; + ast_function *func = NULL; + ast_value *number = NULL; + float fractional; + float integral; + int builtin_num; if (localblock) { parseerror(parser, "cannot declare builtins within functions"); @@ -5656,30 +5658,39 @@ skipvar: break; } - number = (ast_value*)parse_expression_leave(parser, true, false, false); - if (!number) { - parseerror(parser, "builtin number expected"); - break; - } - if (!ast_istype(number, ast_value) || !number->hasvalue || number->cvq != CV_CONST) - { + if (OPTS_FLAG(EXPRESSIONS_FOR_BUILTINS)) { + number = (ast_value*)parse_expression_leave(parser, true, false, false); + if (!number) { + parseerror(parser, "builtin number expected"); + break; + } + if (!ast_istype(number, ast_value) || !number->hasvalue || number->cvq != CV_CONST) + { + ast_unref(number); + parseerror(parser, "builtin number must be a compile time constant"); + break; + } + if (number->expression.vtype == TYPE_INTEGER) + builtin_num = number->constval.vint; + else if (number->expression.vtype == TYPE_FLOAT) + builtin_num = number->constval.vfloat; + else { + ast_unref(number); + parseerror(parser, "builtin number must be an integer constant"); + break; + } ast_unref(number); - parseerror(parser, "builtin number must be a compile time constant"); - break; - } - if (number->expression.vtype == TYPE_INTEGER) - builtin_num = number->constval.vint; - else if (number->expression.vtype == TYPE_FLOAT) - builtin_num = number->constval.vfloat; - else { - ast_unref(number); - parseerror(parser, "builtin number must be an integer constant"); - break; - } - ast_unref(number); - if (builtin_num < 0) { - parseerror(parser, "builtin number must be an integer greater than zero"); + fractional = modff(builtin_num, &integral); + if (builtin_num < 0 || fractional != 0) { + parseerror(parser, "builtin number must be an integer greater than zero"); + break; + } + + /* we only want the integral part anyways */ + builtin_num = integral; + } else if (parser->tok != TOKEN_INTCONST) { + parseerror(parser, "builtin number must be a compile time constant"); break; } @@ -5698,10 +5709,15 @@ skipvar: } vec_push(parser->functions, func); - func->builtin = -builtin_num-1; + func->builtin = -((OPTS_FLAG(EXPRESSIONS_FOR_BUILTINS)) + ? builtin_num + : parser_token(parser)->constval.i) - 1; } - if (parser->tok != ',' && parser->tok != ';') { + if (OPTS_FLAG(EXPRESSIONS_FOR_BUILTINS) + ? (parser->tok != ',' && parser->tok != ';') + : (!parser_next(parser))) + { parseerror(parser, "expected comma or semicolon"); if (func) ast_function_delete(func);