@[has_globals] module builtin // 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` or call `arguments()` instead. @[markused] __global g_main_argc = int(0) @[markused] __global g_main_argv = unsafe { nil } @[markused] __global g_live_reload_info voidptr pub type FnExitCb = fn () fn C.atexit(f FnExitCb) i32 fn C.strerror(i32) &char // These functions (_vinit, and _vcleanup), are generated by V. // `module no_main` programs that use custom manual entrypoints should ensure to call them when appropriate. // Exported V entrypoints are initialized automatically by the generated wrappers. fn C._vinit(argc i32, argv &&char) fn C._vcleanup() // exit terminates execution immediately and returns exit `code` to the shell. @[noreturn] pub fn exit(code int) { C.exit(code) for {} } // at_exit registers a fn callback, that will be called at normal process termination. // It returns an error, if the registration was not successful. // The registered callback functions, will be called either via exit/1, // or via return from the main program, in the reverse order of their registration. // The same fn may be registered multiple times. // Each callback fn will called once for each registration. pub fn at_exit(cb FnExitCb) ! { $if freestanding { return error('at_exit not implemented with -freestanding') } $else { res := C.atexit(cb) if res != 0 { return error_with_code('at_exit failed', res) } } } fn v_segmentation_fault_handler(signal_number i32) { $if freestanding { eprintln('signal 11: segmentation fault') } $else { C.fprintf(C.stderr, c'signal %d: segmentation fault\n', signal_number) } $if use_libbacktrace ? { $if openbsd { print_backtrace() } $else { eprint_libbacktrace(1) } } $else { print_backtrace() } exit(128 + signal_number) } @[inline] fn v_fixed_index(i int, len int) int { $if !no_bounds_checking { if i < 0 || i >= len { panic('fixed array index out of range (index: ' + i64(i).str() + ', len: ' + i64(len).str() + ')') } } return i } @[inline; markused] fn v_fixed_index_i64(i i64, len int) int { $if !no_bounds_checking { if i < 0 || i >= i64(len) { panic('fixed array index out of range (index: ' + i.str() + ', len: ' + i64(len).str() + ')') } } return int(i) } @[inline; markused] fn v_fixed_index_u64(i u64, len int) int { $if !no_bounds_checking { if i >= u64(len) { panic('fixed array index out of range (index: ' + i.str() + ', len: ' + i64(len).str() + ')') } } return int(i) } @[inline; markused] fn v_fixed_index_ni(i int, len int) int { return v_fixed_index(v_ni_index(i, len), len) } @[inline; markused] fn v_slice_index_i64(i i64) int { if i < i64(min_int) || i > i64(max_int) { panic('slice index out of range for int: ' + i.str()) } return int(i) } @[inline; markused] fn v_slice_index_u64(i u64) int { if i > u64(max_int) { panic('slice index out of range for int: ' + i.str()) } return int(i) } // 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 } // vcurrent_hash returns @VCURRENTHASH, which depends on the git version of // the V repository, from which the V executable had been compiled. pub fn vcurrent_hash() string { return @VCURRENTHASH } // v_getpid returns a process identifier. It is a number that is guaranteed to // remain the same while the current process is running. It may or may not be // equal to the value of v_gettid(). Note: it is *NOT equal on Windows*. pub fn v_getpid() u64 { $if no_getpid ? { // support non posix/windows systems that lack process management return 0 } $else $if windows { return u64(C.GetCurrentProcessId()) } $else { return u64(C.getpid()) } } // v_gettid retuns a thread identifier. It is a number that is guaranteed to not // change, while the current thread is running. Different threads, running at // the same time in the same process, have different thread ids. There is no // such guarantee for threads running in different processes. // Important: this will be the same number returned by v_getpid(), but only on // non windows systems, when the current thread is the main one. It is best to // *avoid relying on this equivalence*, and use v_gettid and v_getpid only for // tracing and debugging multithreaded issues, but *NOT for logic decisions*. pub fn v_gettid() u64 { $if no_gettid ? { // support non posix/windows systems that lack process management return 0 } $else $if windows { return u64(C.GetCurrentThreadId()) } $else $if linux && !musl ? { return u64(C.gettid()) } $else $if threads { return u64(C.pthread_self()) } $else { return v_getpid() } }