From 48c05b5a45a5a5af0b017ef48cffe63d3b61d7fb Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 15 Sep 2019 15:57:17 +0300 Subject: [PATCH] cgen: use *char in all functions with *char args to avoid warnings --- CONTRIBUTING.md | 4 ++-- compiler/fn.v | 9 ++++++--- compiler/parser.v | 13 ++++++++++--- vlib/os/os.v | 36 +++++++++++++++++------------------- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b2066b4708..818e74de86 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ I tried making the code of the compiler and vlib as simple and readable as possi The compiler itself is located in `compiler/` -It has only 8 files (soon to be 7): +The main files are: 1. `main.v` The entry point. - V figures out the build mode. @@ -19,7 +19,7 @@ It has only 8 files (soon to be 7): In V, objects can be used before declaration, so there are 2 passes. During the first pass, it only looks at declarations and skips function bodies. It memorizes all function signatures, types, consts, etc. During the second pass it looks at function bodies and generates C (e.g. `cgen('if ($expr) {'`) or machine code (e.g. `gen.mov(EDI, 1)`). The formatter is embedded in the parser. Correctly formatted tokens are emitted as they are parsed. This allowed to simplify the compiler and avoid duplication, but slowed it down a bit. In the future this will be fixed with build flags and separate binaries for C generation, machine code generation, and formatting. This way there will be no unnecessary branching and function calls. - + 3. `scanner.v` The scanner's job is to parse a list of characters and convert them to tokens. It also takes care of string interpolation, which is a mess at the moment. 4. `token.v` This is simply a list of all tokens, their string values, and a couple of helper functions. diff --git a/compiler/fn.v b/compiler/fn.v index e84f87d0c9..d789530282 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -746,14 +746,17 @@ fn (p mut Parser) fn_args(f mut Fn) { // foo *(1, 2, 3, mut bar)* fn (p mut Parser) fn_call_args(f mut Fn) &Fn { - // p.gen('(') // println('fn_call_args() name=$f.name args.len=$f.args.len') // C func. # of args is not known - // if f.name.starts_with('c_') { p.check(.lpar) if f.is_c { for p.tok != .rpar { - p.bool_expression() + ph := p.cgen.add_placeholder() + typ := p.bool_expression() + // Cast V byteptr to C char* (byte is unsigned in V, that led to C warnings) + if typ == 'byte*' { + p.cgen.set_placeholder(ph, '(char*)') + } if p.tok == .comma { p.gen(', ') p.check(.comma) diff --git a/compiler/parser.v b/compiler/parser.v index 2ce8807c8d..389140a751 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -3171,6 +3171,7 @@ fn (p mut Parser) switch_statement() { } p.cgen.start_tmp() typ := p.bool_expression() + is_str := typ == 'string' expr := p.cgen.end_tmp() p.check(.lcbr) mut i := 0 @@ -3198,13 +3199,16 @@ fn (p mut Parser) switch_statement() { mut got_comma := false for { if got_comma { - p.gen(') || ') + if is_str { + p.gen(')') + } + p.gen(' || ') } if typ == 'string' { p.gen('string_eq($expr, ') } else { - p.gen('($expr == ') + p.gen('$expr == ') } if p.tok == .key_case || p.tok == .key_default { p.check(p.tok) @@ -3222,7 +3226,10 @@ fn (p mut Parser) switch_statement() { else { p.check(.arrow) } - p.gen(')) {') + if is_str { + p.gen(')') + } + p.gen(') {') p.genln('/* case */') p.statements() all_cases_return = all_cases_return && p.returns diff --git a/vlib/os/os.v b/vlib/os/os.v index 74d1e0b5dd..c16a8c46b8 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -77,12 +77,7 @@ fn parse_windows_cmd_line(cmd byteptr) []string { // read_file reads the file in `path` and returns the contents. pub fn read_file(path string) ?string { mode := 'rb' - mut fp := &C.FILE{!} - $if windows { - fp = C._wfopen(path.to_wide(), mode.to_wide()) - } $else { - fp = C.fopen(path.str, mode.str) - } + mut fp := vfopen(path, mode) if isnil(fp) { return error('failed to open file "$path"') } @@ -103,7 +98,7 @@ pub fn file_size(path string) int { $if windows { C._wstat(path.to_wide(), &s) } $else { - C.stat(path.str, &s) + C.stat(*char(path.str), &s) } return s.st_size } @@ -112,10 +107,18 @@ pub fn mv(old, new string) { $if windows { C._wrename(old.to_wide(), new.to_wide()) } $else { - C.rename(old.str, new.str) + C.rename(*char(old.str), *char(new.str)) } } +fn vfopen(path, mode string) *C.FILE { + $if windows { + return C._wfopen(path.to_wide(), mode.to_wide()) + } $else { + return C.fopen(*char(path.str), *char(mode.str)) + } +} + // read_lines reads the file in `path` into an array of lines. // TODO return `?[]string` TODO implement `?[]` support pub fn read_lines(path string) []string { @@ -124,12 +127,7 @@ pub fn read_lines(path string) []string { mut buf := malloc(buf_len) mode := 'rb' - mut fp := &C.FILE{!} - $if windows { - fp = C._wfopen(path.to_wide(), mode.to_wide()) - } $else { - fp = C.fopen(path.str, mode.str) - } + mut fp := vfopen(path, mode) if isnil(fp) { // TODO // return error('failed to open file "$path"') @@ -183,7 +181,7 @@ pub fn open(path string) ?File { } $else { cpath := path.str file = File { - cfile: C.fopen(cpath, 'rb') + cfile: C.fopen(*char(cpath), 'rb') } } if isnil(file.cfile) { @@ -204,7 +202,7 @@ pub fn create(path string) ?File { } $else { cpath := path.str file = File { - cfile: C.fopen(cpath, 'wb') + cfile: C.fopen(*char(cpath), 'wb') } } if isnil(file.cfile) { @@ -224,7 +222,7 @@ pub fn open_append(path string) ?File { } $else { cpath := path.str file = File { - cfile: C.fopen(cpath, 'ab') + cfile: C.fopen(*char(cpath), 'ab') } } if isnil(file.cfile) { @@ -306,7 +304,7 @@ pub fn exec(cmd string) ?Result { } buf := [1000]byte mut res := '' - for C.fgets(buf, 1000, f) != 0 { + for C.fgets(*char(buf), 1000, f) != 0 { res += tos(buf, vstrlen(buf)) } res = res.trim_space() @@ -342,7 +340,7 @@ pub fn getenv(key string) string { } return string_from_wide(s) } $else { - s := C.getenv(key.str) + s := *byte(C.getenv(key.str)) if isnil(s) { return '' }