1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! The running program's arguments, and a way to end it with a status:
//! the runtime half of `std/process`'s `args()` and `exit()`.
//!
//! **One process-wide list, set at most once.** `nova run` runs a program
//! inside `nova.exe`, whose own argv is nova's, so the driver calls
//! [`set_args`] with `[FILE, ARGS...]` before `main`
//! (`CompiledProgram::run_with_args`). If nothing set it, the first read takes
//! the OS's argv through `std::env::args_os()`. A built executable takes that
//! path: its generated C `main` drops `argc` and `argv`, but std's argv does
//! not depend on them. glibc passes them to std's `.init_array` function,
//! macOS answers `_NSGetArgc`/`_NSGetArgv`, and Windows parses the UTF-16
//! `GetCommandLineW`, which keeps non-ASCII arguments a C `main`'s ANSI
//! `argv` would garble. `nova test`'s binary takes it too, and gets no
//! arguments. `docs/adr/0023-program-arguments.md` records the decision.
//!
//! An argument that is not valid Unicode is converted with
//! `to_string_lossy`: U+FFFD stands in for its bad bytes, and nothing panics.
//!
//! `pub`, so `crates/nova-runtime/tests/process_args_*.rs` can drive it, and
//! so `nova-codegen-cranelift` can call [`set_args`].
use OnceLock;
use crateNovaStr;
/// The program's arguments, once set or read.
static ARGS: = new;
/// Fixes the program's arguments to `args`. Returns `true` if this call set
/// them, and `false`, changing nothing, if they were already fixed by an
/// earlier call or an earlier read.
/// The program's arguments: the list [`set_args`] stored, or else the OS's.
/// Argument `i` of `list`, or the empty string for an index out of range.
/// `process_arg_count() -> Int`: how many arguments the program has,
/// counting the program itself at index 0.
pub extern "C"
/// `process_arg(i: Int) -> String`: argument `i`, or the empty string for an
/// index out of range. `std/process`'s `args()` never asks for one.
pub extern "C"
/// `process_exit(code: Int)`: ends the process with `code`. `std::process::exit`
/// runs std's cleanup, which flushes stdout, and does not join running tasks.
/// The OS truncates `code`: Unix keeps its low 8 bits.
pub extern "C" !