Pushing the -fexpressions-for-builtins stuff and the modff for catching fractional...
authorDale Weiler <killfieldengine@gmail.com>
Thu, 25 Apr 2013 17:08:02 +0000 (17:08 +0000)
committerDale Weiler <killfieldengine@gmail.com>
Thu, 25 Apr 2013 17:08:02 +0000 (17:08 +0000)
main.c
opts.def
parser.c

diff --git a/main.c b/main.c
index 60780efe1cb5db4eeb6455c24ad55e161f5194f0..498386cc0129e7b578fc59fcd6aee95280114e47 100644 (file)
--- 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, 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;
 
 
                     OPTS_OPTION_U32(OPTION_STANDARD) = COMPILER_GMQCC;
index f7b5cf115ea90ee143bb713bd99d9920f1fefcab..a9301a593998f5b7a99cdd857d279e39ec9ca5d4 100644 (file)
--- 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(PERMISSIVE)
     GMQCC_DEFINE_FLAG(VARIADIC_ARGS)
     GMQCC_DEFINE_FLAG(LEGACY_VECTOR_MATHS)
+    GMQCC_DEFINE_FLAG(EXPRESSIONS_FOR_BUILTINS)
 #endif
 
 /* warning flags */
 #endif
 
 /* warning flags */
index d95a44642beaa606c13b88d07effdf6a760e0bc8..14cf583647c0a79362691193440f75b0d8761572 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -5639,9 +5639,11 @@ skipvar:
         }
 
         if (parser->tok == '#') {
         }
 
         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");
 
             if (localblock) {
                 parseerror(parser, "cannot declare builtins within functions");
@@ -5656,30 +5658,39 @@ skipvar:
                 break;
             }
 
                 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)
-            {
-                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 {
+            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);
                 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;
             }
 
                 break;
             }
 
@@ -5698,10 +5709,15 @@ skipvar:
                 }
                 vec_push(parser->functions, func);
 
                 }
                 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);
                 parseerror(parser, "expected comma or semicolon");
                 if (func)
                     ast_function_delete(func);