From 7d2eb4f60454c2bdcebf3ad0f08e1ffd66ee8f83 Mon Sep 17 00:00:00 2001 From: SleepyRoy <47302112+SleepyRoy@users.noreply.github.com> Date: Mon, 24 Feb 2020 06:43:04 +0800 Subject: [PATCH] scanner: make `0o` prefix the only way to define octals --- vlib/builtin/int_test.v | 18 ++++++++++++++++-- vlib/compiler/scanner.v | 13 +++++++++++++ vlib/os/os.v | 4 ++-- vlib/os/os_test.v | 8 ++++---- vlib/strconv/atoi_test.v | 2 +- vlib/v/gen/x64/elf.v | 2 +- vlib/v/scanner/scanner.v | 13 +++++++++++++ 7 files changed, 50 insertions(+), 10 deletions(-) diff --git a/vlib/builtin/int_test.v b/vlib/builtin/int_test.v index de22637478..455ac37885 100644 --- a/vlib/builtin/int_test.v +++ b/vlib/builtin/int_test.v @@ -117,6 +117,20 @@ fn test_hex() { fn test_oct() { x1 := 0o12 assert x1 == 10 - x2 := 012 - assert x2 == 10 + x2 := 00000o350 + assert x2 == 232 + x3 := 000o00073 + assert x3 == 59 + x4 := 00000000 + assert x4 == 0 + x5 := 00000195 + assert x5 == 195 + x6 := -0o744 + assert x6 == -484 + x7 := -000o000042 + assert x7 == -34 + x8 := -0000112 + assert x8 == -112 + x9 := -000 + assert x9 == 0 } diff --git a/vlib/compiler/scanner.v b/vlib/compiler/scanner.v index b7ac8761d6..1fd24060fb 100644 --- a/vlib/compiler/scanner.v +++ b/vlib/compiler/scanner.v @@ -346,6 +346,19 @@ fn (s mut Scanner) scan() ScanRes { } // `123`, `.123` else if c.is_digit() || (c == `.` && nextc.is_digit()) { + if !s.inside_string { + // In C ints with `0` prefix are octal (in V they're decimal), so discarding heading zeros is needed. + mut start_pos := s.pos + for start_pos < s.text.len && s.text[start_pos] == `0` { + start_pos++ + } + mut prefix_zero_num := start_pos - s.pos // how many prefix zeros should be jumped + // for 0b, 0o, 0x the heading zero shouldn't be jumped + if c == `0` && start_pos < s.text.len && !s.text[start_pos].is_digit() { + prefix_zero_num-- + } + s.pos += prefix_zero_num // jump these zeros + } num := s.ident_number() return scan_res(.number, num) } diff --git a/vlib/os/os.v b/vlib/os/os.v index 1d760085c9..f10a40acb0 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -290,13 +290,13 @@ pub fn open_file(path string, mode string, options ...int) ?File { } } - mut permission := 0666 + mut permission := 0o666 if options.len > 0 { permission = options[0] } $if windows { - if permission < 0600 { + if permission < 0o600 { permission = 0x0100 } else { diff --git a/vlib/os/os_test.v b/vlib/os/os_test.v index b3cec0fa9d..ca59406e02 100644 --- a/vlib/os/os_test.v +++ b/vlib/os/os_test.v @@ -33,11 +33,11 @@ fn test_unsetenv() { fn test_open_file() { filename := './test1.txt' hello := 'hello world!' - os.open_file(filename, "r+", 0666) or { + os.open_file(filename, "r+", 0o666) or { assert err == "No such file or directory" } - mut file := os.open_file(filename, "w+", 0666) or { panic(err) } + mut file := os.open_file(filename, "w+", 0o666) or { panic(err) } file.write(hello) file.close() @@ -278,11 +278,11 @@ fn test_is_executable_writable_readable() { f.close() $if !windows { - os.chmod(file_name, 0600) // mark as readable && writable, but NOT executable + os.chmod(file_name, 0o600) // mark as readable && writable, but NOT executable assert os.is_writable(file_name) assert os.is_readable(file_name) assert !os.is_executable(file_name) - os.chmod(file_name, 0700) // mark as executable too + os.chmod(file_name, 0o700) // mark as executable too assert os.is_executable(file_name) } $else { assert os.is_writable(file_name) diff --git a/vlib/strconv/atoi_test.v b/vlib/strconv/atoi_test.v index 6c34fd6462..dbdd0a48bf 100644 --- a/vlib/strconv/atoi_test.v +++ b/vlib/strconv/atoi_test.v @@ -11,7 +11,7 @@ fn test_atoi() { fn test_parse_int() { // Different bases assert strconv.parse_int('16', 16, 0) == 0x16 - assert strconv.parse_int('16', 8, 0) == 016 + assert strconv.parse_int('16', 8, 0) == 0o16 assert strconv.parse_int('11', 2, 0) == 3 // Different bit sizes assert strconv.parse_int('127', 10, 8) == 127 diff --git a/vlib/v/gen/x64/elf.v b/vlib/v/gen/x64/elf.v index df49205584..fdcdc83609 100644 --- a/vlib/v/gen/x64/elf.v +++ b/vlib/v/gen/x64/elf.v @@ -92,7 +92,7 @@ pub fn (g mut Gen) generate_elf_footer() { mut f := os.create(g.out_name) or { panic(err) } - os.chmod(g.out_name, 0775) // make it an executable + os.chmod(g.out_name, 0o775) // make it an executable f.write_bytes(g.buf.data, g.buf.len) f.close() println('x64 elf binary has been successfully generated') diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index fff6d8926c..03ca391350 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -340,6 +340,19 @@ pub fn (s mut Scanner) scan() token.Token { } // `123`, `.123` else if c.is_digit() || (c == `.` && nextc.is_digit()) { + if !s.inside_string { + // In C ints with `0` prefix are octal (in V they're decimal), so discarding heading zeros is needed. + mut start_pos := s.pos + for start_pos < s.text.len && s.text[start_pos] == `0` { + start_pos++ + } + mut prefix_zero_num := start_pos - s.pos // how many prefix zeros should be jumped + // for 0b, 0o, 0x the heading zero shouldn't be jumped + if c == `0` && start_pos < s.text.len && !s.text[start_pos].is_digit() { + prefix_zero_num-- + } + s.pos += prefix_zero_num // jump these zeros + } num := s.ident_number() return s.scan_res(.number, num) }