Skip to content

Commit 08df652

Browse files
committed
Support CLI arguments.
1 parent f1e335f commit 08df652

File tree

3 files changed

+44
-17
lines changed

3 files changed

+44
-17
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ authors = ["Jonathan 'theJPster' Pallant <[email protected]>"]
88

99
[dependencies]
1010
neotron-ffi = "0.1"
11-
neotron-api = "0.1"
11+
neotron-api = "0.2"
1212

1313
[target.'cfg(unix)'.dependencies]
1414
crossterm = "0.26"

samples/chello/chello.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,11 @@
99

1010
const NeotronApi *g_api;
1111

12-
static int main(void);
13-
1412
/*
1513
* Called by Neotron OS when the binary is 'run'.
1614
*/
17-
int app_entry(const NeotronApi *f) {
15+
int app_entry(const NeotronApi *f, size_t argc, const FfiString* argv) {
1816
g_api = f;
19-
return main();
20-
}
21-
22-
/*
23-
* Our main function.
24-
*
25-
* Just prints a message and exits.
26-
*/
27-
static int main(void) {
2817
// allocate a buffer
2918
void *buffer = calloc(1024, 1);
3019
// write a string into it
@@ -33,6 +22,10 @@ static int main(void) {
3322
printf(buffer);
3423
// free the buffer
3524
free(buffer);
25+
for(size_t i = 0; i < argc; i++) {
26+
const FfiString* ffi_arg = &argv[i];
27+
printf("Arg %u: %.*s\n", (unsigned int) i, ffi_arg->_0.data_len, ffi_arg->_0.data);
28+
}
3629
return 0;
3730
}
3831

src/lib.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// Imports
99
// ============================================================================
1010

11-
use core::sync::atomic::{AtomicPtr, Ordering};
11+
use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
1212

1313
pub use neotron_ffi::{FfiBuffer, FfiByteSlice, FfiString};
1414

@@ -46,14 +46,20 @@ extern "C" {
4646
/// Once you've hit the application `main()`, this will be non-null.
4747
static API: AtomicPtr<Api> = AtomicPtr::new(core::ptr::null_mut());
4848

49+
/// Number of arguments passed
50+
static ARG_COUNT: AtomicUsize = AtomicUsize::new(0);
51+
52+
/// Start of the argument list
53+
static ARG_PTR: AtomicPtr<FfiString> = AtomicPtr::new(core::ptr::null_mut());
54+
4955
// ============================================================================
5056
// Types
5157
// ============================================================================
5258

5359
/// The type of the application entry-point.
5460
///
5561
/// The OS calls a function of this type.
56-
pub type AppStartFn = extern "C" fn(*mut crate::Api) -> i32;
62+
pub use neotron_api::AppStartFn;
5763

5864
/// The result type for any SDK function.
5965
///
@@ -259,11 +265,39 @@ impl Drop for ReadDir {
259265
/// Will jump to the application entry point, and `extern "C"` function
260266
/// called `main`.
261267
#[no_mangle]
262-
extern "C" fn app_entry(api: *mut Api) -> i32 {
263-
API.store(api, Ordering::Relaxed);
268+
extern "C" fn app_entry(api: *const Api, argc: usize, argv: *const FfiString) -> i32 {
269+
let _check: AppStartFn = app_entry;
270+
API.store(api as *mut Api, Ordering::Relaxed);
271+
ARG_COUNT.store(argc, Ordering::Relaxed);
272+
ARG_PTR.store(argv as *mut FfiString, Ordering::Relaxed);
264273
unsafe { neotron_main() }
265274
}
266275

276+
/// Get a command line argument.
277+
///
278+
/// Given an zero-based index, returns `Some(str)` if that argument was
279+
/// provided, otherwise None.
280+
///
281+
/// Does not return the name of the program in the first argument.
282+
#[cfg(target_os = "none")]
283+
pub fn arg(n: usize) -> Option<&'static str> {
284+
let arg_count = ARG_COUNT.load(Ordering::Relaxed);
285+
let arg_ptr = ARG_PTR.load(Ordering::Relaxed);
286+
let arg_slice = unsafe { core::slice::from_raw_parts(arg_ptr, arg_count) };
287+
arg_slice.get(n).map(|ffi| ffi.as_str())
288+
}
289+
290+
/// Get a command line argument.
291+
///
292+
/// Given an zero-based index, returns `Some(str)` if that argument was
293+
/// provided, otherwise None.
294+
///
295+
/// Does not return the name of the program in the first argument.
296+
#[cfg(not(target_os = "none"))]
297+
pub fn arg(n: usize) -> Option<String> {
298+
std::env::args().skip(1).nth(n)
299+
}
300+
267301
/// Get information about a file on disk.
268302
pub fn stat(_path: path::Path) -> Result<api::file::Stat> {
269303
todo!()

0 commit comments

Comments
 (0)