X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=parser.c;h=7034e64c7314ede34e1d65878c7b71c746efa40e;hb=aed2b1031c6466a2dbcf909faeac1ac1cff0f6e6;hp=c81fd2c4db714d9e410b726accbe3ca19321cf48;hpb=9fee84f250dcad087d117be541588a2c122137b4;p=xonotic%2Fgmqcc.git diff --git a/parser.c b/parser.c index c81fd2c..7034e64 100644 --- a/parser.c +++ b/parser.c @@ -5639,7 +5639,11 @@ skipvar: } if (parser->tok == '#') { - ast_function *func = NULL; + ast_function *func = NULL; + ast_value *number = NULL; + float fractional = 0; + float integral = 0; + int builtin_num = 0; if (localblock) { parseerror(parser, "cannot declare builtins within functions"); @@ -5653,12 +5657,40 @@ skipvar: parseerror(parser, "expected builtin number"); break; } - if (parser->tok != TOKEN_INTCONST) { - parseerror(parser, "builtin number must be an integer constant"); - break; - } - if (parser_token(parser)->constval.i < 0) { - parseerror(parser, "builtin number must be an integer greater than zero"); + + 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); + + 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; } @@ -5677,10 +5709,15 @@ skipvar: } vec_push(parser->functions, func); - func->builtin = -parser_token(parser)->constval.i-1; + func->builtin = -((OPTS_FLAG(EXPRESSIONS_FOR_BUILTINS)) + ? builtin_num + : parser_token(parser)->constval.i) - 1; } - if (!parser_next(parser)) { + 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);