From 1b1d17cfb54b13702fbf5e6480d195d786354511 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 5 Nov 2020 08:44:34 +0100 Subject: [PATCH] os: basic proof of concept stdout capture; autofree: small fixes --- vlib/os/os_nix.c.v | 48 ++++++++++++++++++++++++++++++++++++++++++++++ vlib/os/os_test.v | 15 +++++++++++++++ vlib/v/gen/cgen.v | 18 ++++++++++------- vlib/v/gen/fn.v | 15 ++++++++++++--- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/vlib/os/os_nix.c.v b/vlib/os/os_nix.c.v index a46e53394d..97cbdd758d 100644 --- a/vlib/os/os_nix.c.v +++ b/vlib/os/os_nix.c.v @@ -159,6 +159,54 @@ pub fn exec(cmd string) ?Result { } } +pub struct Command { +mut: + f voidptr +pub mut: + eof bool +pub: + path string + redirect_stdout bool +} + +//pub fn command(cmd Command) Command { +//} + +pub fn (mut c Command) start()? { + pcmd := '$c.path 2>&1' + c.f = vpopen(pcmd) + if isnil(c.f) { + return error('exec("$c.path") failed') + } +} + +pub fn (mut c Command) read_line() string { + buf := [4096]byte{} + mut res := strings.new_builder(1024) + unsafe { + for C.fgets(charptr(buf), 4096, c.f) != 0 { + bufbp := byteptr(buf) + len := vstrlen(bufbp) + for i in 0..len { + if int(bufbp[i]) == `\n` { + res.write_bytes(bufbp, i) + return res.str() + } + } + res.write_bytes(bufbp, len) + } + } + c.eof = true + return res.str() +} + +pub fn (c &Command) close()? { + exit_code := vpclose(c.f) + if exit_code == 127 { + return error_with_code('error', 127) + } +} + pub fn symlink(origin string, target string) ?bool { res := C.symlink(charptr(origin.str), charptr(target.str)) if res == 0 { diff --git a/vlib/os/os_test.v b/vlib/os/os_test.v index 452b9570be..6a81e5bc37 100644 --- a/vlib/os/os_test.v +++ b/vlib/os/os_test.v @@ -503,3 +503,18 @@ fn test_write_file_array_structs() { assert rarr.len == maxn // eprintln( rarr.str().replace('\n', ' ').replace('},', '},\n')) } + +fn test_stdout_capture() { + /* +mut cmd := os.Command{ + path:'cat' + redirect_stdout: true +} +cmd.start() +for !cmd.eof { + line := cmd.read_line() + println('line="$line"') +} +cmd.close() +*/ +} diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 28b60e77a0..7f05394c64 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -118,7 +118,8 @@ mut: called_fn_name string cur_mod string is_js_call bool // for handling a special type arg #1 `json.decode(User, ...)` - nr_vars_to_free int + // nr_vars_to_free int + doing_autofree_tmp bool inside_lambda bool } @@ -1043,8 +1044,11 @@ fn (mut g Gen) stmt(node ast.Stmt) { // If we have temporary string exprs to free after this statement, do it. e.g.: // `foo('a' + 'b')` => `tmp := 'a' + 'b'; foo(tmp); string_free(&tmp);` if g.pref.autofree { - p := node.position() - g.autofree_call_postgen(p.pos) + // if node is ast.ExprStmt {&& node.expr is ast.CallExpr { + if node !is ast.FnDecl { + p := node.position() + g.autofree_call_postgen(p.pos) + } } } @@ -1975,13 +1979,13 @@ fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) { // tmp expr vars do not need to be freed again here return } - // if v.is_autofree_tmp { - // return - // } + if v.is_autofree_tmp && !g.doing_autofree_tmp { + return + } if v.typ.is_ptr() { g.writeln('\t${free_fn_name}(${c_name(v.name)}); // autofreed ptr var') } else { - g.writeln('\t${free_fn_name}(&${c_name(v.name)}); // autofreed var') + g.writeln('\t${free_fn_name}(&${c_name(v.name)}); // autofreed var $g.doing_autofree_tmp') } } diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index 853e96f54c..56f9914ee0 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -709,7 +709,7 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) { g.strs_to_free0 << s // Now free the tmp arg vars right after the function call // g.strs_to_free << t - g.nr_vars_to_free++ + // g.nr_vars_to_free++ // g.strs_to_free << 'string_free(&$t);' } } @@ -720,10 +720,12 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) { return } */ - // g.writeln('\n/* strs_to_free3: $g.nr_vars_to_free */') + /* + g.writeln('\n/* strs_to_free3: $g.nr_vars_to_free */') if g.nr_vars_to_free <= 0 { return } + */ /* for s in g.strs_to_free { g.writeln('string_free(&$s);') @@ -734,6 +736,11 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) { g.strs_to_free = [] } */ + if g.inside_vweb_tmpl { + return + } + g.doing_autofree_tmp = true + g.write('/* postgen */') scope := g.file.scope.innermost(node_pos) for _, obj in scope.objects { match mut obj { @@ -757,11 +764,13 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) { } obj.is_used = true g.autofree_variable(v) - g.nr_vars_to_free-- + // g.nr_vars_to_free-- } else {} } } + g.write('/* postgen end */') + g.doing_autofree_tmp = false } fn (mut g Gen) call_args(node ast.CallExpr) {