diff --git a/src/big_int.cpp b/src/big_int.cpp index 20f940e8e..8203f0522 100644 --- a/src/big_int.cpp +++ b/src/big_int.cpp @@ -40,7 +40,7 @@ typedef mp_int BigInt; void big_int_from_u64(BigInt *dst, u64 x); void big_int_from_i64(BigInt *dst, i64 x); void big_int_init (BigInt *dst, BigInt const *src); -void big_int_from_string(BigInt *dst, String const &s); +void big_int_from_string(BigInt *dst, String const &s, bool &success); void big_int_dealloc(BigInt *dst) { mp_clear(dst); @@ -84,7 +84,7 @@ void big_int_quo_eq(BigInt *dst, BigInt const *x); void big_int_rem_eq(BigInt *dst, BigInt const *x); bool big_int_is_neg(BigInt const *x); - +void big_int_neg(BigInt *dst, BigInt const *x); void big_int_add_eq(BigInt *dst, BigInt const *x) { BigInt res = {}; @@ -169,7 +169,11 @@ BigInt big_int_make_i64(i64 x) { } -void big_int_from_string(BigInt *dst, String const &s) { +void big_int_from_string(BigInt *dst, String const &s, bool *success) { + *success = true; + + bool is_negative = false; + u64 base = 10; bool has_prefix = false; if (s.len > 2 && s[0] == '0') { @@ -197,11 +201,26 @@ void big_int_from_string(BigInt *dst, String const &s) { isize i = 0; for (; i < len; i++) { Rune r = cast(Rune)text[i]; + + if (r == '-') { + if (is_negative) { + // NOTE(Jeroen): Can't have a doubly negative number. + *success = false; + return; + } + is_negative = true; + continue; + } + if (r == '_') { continue; } u64 v = u64_digit_value(r); if (v >= base) { + // NOTE(Jeroen): Can still be a valid integer if the next character is an `e` or `E`. + if (r != 'e' && r != 'E') { + *success = false; + } break; } BigInt val = big_int_make_u64(v); @@ -225,6 +244,7 @@ void big_int_from_string(BigInt *dst, String const &s) { if (gb_char_is_digit(r)) { v = u64_digit_value(r); } else { + *success = false; break; } exp *= 10; @@ -234,6 +254,10 @@ void big_int_from_string(BigInt *dst, String const &s) { big_int_mul_eq(dst, &b); } } + + if (is_negative) { + big_int_neg(dst, dst); + } } diff --git a/src/exact_value.cpp b/src/exact_value.cpp index cedef48c4..175cb61f6 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -177,7 +177,11 @@ ExactValue exact_value_typeid(Type *type) { ExactValue exact_value_integer_from_string(String const &string) { ExactValue result = {ExactValue_Integer}; - big_int_from_string(&result.value_integer, string); + bool success; + big_int_from_string(&result.value_integer, string, &success); + if (!success) { + result = {ExactValue_Invalid}; + } return result; } diff --git a/src/main.cpp b/src/main.cpp index 86c1544a4..8bd6fc618 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -961,19 +961,10 @@ bool parse_build_flags(Array args) { bad_flags = true; break; } - // NOTE(Jeroen): We can't rely on `value.value_integer` here, because words will be returned as `0`. - // Meaning that -opt:speed will coerce to opt:0. That's not what the user intended. - // Instead we'll just compare 0..3 directly. - if (param == "0") { - build_context.optimization_level = 0; - } else if (param == "1") { - build_context.optimization_level = 1; - } else if (param == "2") { - build_context.optimization_level = 2; - } else if (param == "3") { - build_context.optimization_level = 3; - } else { - gb_printf_err("Invalid optimization level for -o:, got %.*s\n", LIT(param)); + + build_context.optimization_level = cast(i32)big_int_to_i64(&value.value_integer); + if (build_context.optimization_level < 0 || build_context.optimization_level > 3) { + gb_printf_err("Invalid optimization level for -o:, got %d\n", build_context.optimization_level); gb_printf_err("Valid optimization levels:\n"); gb_printf_err("\t0\n"); gb_printf_err("\t1\n");