Skip to content

Commit

Permalink
builtin: add pub fn arguments() []string {; make os.args use it, …
Browse files Browse the repository at this point in the history
…remove edge case in cgen (#21852)
  • Loading branch information
spytheman authored Jul 12, 2024
1 parent 48ab08c commit c2f7afd
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 32 deletions.
20 changes: 19 additions & 1 deletion vlib/builtin/builtin.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -711,14 +711,32 @@ fn v_fixed_index(i int, len int) int {

// NOTE: g_main_argc and g_main_argv are filled in right after C's main start.
// They are used internally by V's builtin; for user code, it is much
// more convenient to just use `os.args` instead.
// more convenient to just use `os.args` or call `arguments()` instead.

@[markused]
__global g_main_argc = int(0)

@[markused]
__global g_main_argv = unsafe { nil }

// arguments returns the command line arguments, used for starting the current program as a V array of strings.
// The first string in the array (index 0), is the name of the program, used for invoking the program.
// The second string in the array (index 1), if it exists, is the first argument to the program, etc.
// For example, if you started your program as `myprogram -option`, then arguments() will return ['myprogram', '-option'].
// Note: if you `v run file.v abc def`, then arguments() will return ['file', 'abc', 'def'], or ['file.exe', 'abc', 'def'] (on Windows).
pub fn arguments() []string {
argv := &&u8(g_main_argv)
mut res := []string{cap: g_main_argc}
for i in 0 .. g_main_argc {
$if windows {
res << unsafe { string_from_wide(&u16(argv[i])) }
} $else {
res << unsafe { tos_clone(argv[i]) }
}
}
return res
}

@[if vplayground ?]
fn vplayground_mlimit(n isize) {
if n > 10000 {
Expand Down
2 changes: 1 addition & 1 deletion vlib/os/os.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ $if freebsd || openbsd {
#include <sys/sysctl.h>
}

pub const args = []string{}
pub const args = arguments()

fn C.readdir(voidptr) &C.dirent

Expand Down
2 changes: 2 additions & 0 deletions vlib/os/os_nix.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ pub fn loginname() !string {
return error(posix_get_error_msg(C.errno))
}

@[deprecated: 'os.args now uses arguments()']
@[deprecated_after: '2024-07-30']
fn init_os_args(argc int, argv &&u8) []string {
mut args_ := []string{len: argc}
for i in 0 .. argc {
Expand Down
2 changes: 2 additions & 0 deletions vlib/os/os_windows.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ pub struct C._utimbuf {

fn C._utime(&char, voidptr) int

@[deprecated: 'os.args now uses arguments()']
@[deprecated_after: '2024-07-30']
fn init_os_args_wide(argc int, argv &&u8) []string {
mut args_ := []string{len: argc}
for i in 0 .. argc {
Expand Down
43 changes: 20 additions & 23 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -6116,29 +6116,22 @@ fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ
mut styp := g.typ(typ)
cname := g.c_const_name(name)
mut init := strings.new_builder(100)
if cname == '_const_os__args' {
if g.pref.os == .windows {
init.writeln('\t_const_os__args = os__init_os_args_wide(___argc, (byteptr*)___argv);')
} else {
init.writeln('\t_const_os__args = os__init_os_args(___argc, (byte**)___argv);')
}

if surround_cbr {
init.writeln('{')
}
if unwrap_option {
init.writeln(g.expr_string_surround('\t${cname} = *(${styp}*)', expr, '.data;'))
} else if expr is ast.ArrayInit && (expr as ast.ArrayInit).has_index {
init.writeln(g.expr_string_surround('\tmemcpy(&${cname}, &', expr, ', sizeof(${styp}));'))
} else if expr is ast.CallExpr
&& g.table.final_sym(g.unwrap_generic((expr as ast.CallExpr).return_type)).kind == .array_fixed {
init.writeln(g.expr_string_surround('\tmemcpy(&${cname}, ', expr, ', sizeof(${styp}));'))
} else {
if surround_cbr {
init.writeln('{')
}
if unwrap_option {
init.writeln(g.expr_string_surround('\t${cname} = *(${styp}*)', expr, '.data;'))
} else if expr is ast.ArrayInit && (expr as ast.ArrayInit).has_index {
init.writeln(g.expr_string_surround('\tmemcpy(&${cname}, &', expr, ', sizeof(${styp}));'))
} else if expr is ast.CallExpr
&& g.table.final_sym(g.unwrap_generic((expr as ast.CallExpr).return_type)).kind == .array_fixed {
init.writeln(g.expr_string_surround('\tmemcpy(&${cname}, ', expr, ', sizeof(${styp}));'))
} else {
init.writeln(g.expr_string_surround('\t${cname} = ', expr, ';'))
}
if surround_cbr {
init.writeln('}')
}
init.writeln(g.expr_string_surround('\t${cname} = ', expr, ';'))
}
if surround_cbr {
init.writeln('}')
}
mut def := '${styp} ${cname}'
expr_sym := g.table.sym(typ)
Expand Down Expand Up @@ -6288,7 +6281,11 @@ fn (mut g Gen) global_decl(node ast.GlobalDecl) {
} else {
// More complex expressions need to be moved to `_vinit()`
// e.g. `__global ( mygblobal = 'hello ' + world' )`
init = '\t${field.name} = ${g.expr_string(field.expr)}; // 3global'
if field.name in ['g_main_argc', 'g_main_argv'] {
init = '\t// skipping ${field.name}, it was initialised in main'
} else {
init = '\t${field.name} = ${g.expr_string(field.expr)}; // 3global'
}
}
} else if !g.pref.translated { // don't zero globals from C code
default_initializer := g.type_default(field.typ)
Expand Down
2 changes: 0 additions & 2 deletions vlib/v/markused/markused.v
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
'main.vtest_new_metainfo',
'main.vtest_new_filemetainfo',
'os.getwd',
'os.init_os_args',
'os.init_os_args_wide',
'v.embed_file.find_index_entry_by_path',
]
}
Expand Down
8 changes: 4 additions & 4 deletions vlib/v/slow_tests/profile/profile_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ fn test_v_profile_works() {
println(@FN)
sfile := 'vlib/v/slow_tests/profile/profile_test_1.v'
validate_output(@FN, '', sfile, {
'os__init_os_args': 1
'main__main': 1
'println': 1
'strconv__atoi': 1
'arguments': 1
'main__main': 1
'println': 1
'strconv__atoi': 1
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
*> trace * C.main*
*> trace * _vinit*
*> trace * os os.init_os_args*
*> trace * builtin arguments/0*
*> trace * main main.main/0*
*> trace * main main.f1/0*
*> trace * main main.f2/0*
Expand Down

0 comments on commit c2f7afd

Please sign in to comment.