190 lines
5.5 KiB
V
190 lines
5.5 KiB
V
@[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 v2_native_windows_pe_minimal ? {
|
|
eprintln('signal 11: segmentation fault')
|
|
exit(128 + signal_number)
|
|
} $else {
|
|
$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()
|
|
}
|
|
}
|