Here is a simple program, that parses and prints 2 options: -n (w/o associated value) and -t (with numeric value) and an argument after options.
C
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int flags, opt;
int nsecs, tfnd;
nsecs = 0;
tfnd = 0;
flags = 0;
while ((opt = getopt(argc, argv, "nt:")) != -1) {
switch (opt) {
case 'n':
flags = 1;
break;
case 't':
// converting string to integer
nsecs = atoi(optarg);
tfnd = 1;
break;
default: /* '?' */
exit(EXIT_FAILURE);
}
}
printf("flags=%d; tfnd=%d; nsecs=%d; optind=%d\n", flags, tfnd, nsecs,
optind);
if (optind >= argc) {
fprintf(stderr, "Expected argument after options\n");
exit(EXIT_FAILURE);
}
printf("name argument = %s\n", argv[optind]);
exit(EXIT_SUCCESS);
}
and the same program in no_std rust
Rust
#![no_std]
#![no_main]
//use libc; // 0.2.186
#[cfg(not(test))]
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
unsafe { libc::abort() }
}
unsafe extern "C" {
static mut optarg: *mut libc::c_char;
static mut optind: i32;
}
#[unsafe(no_mangle)]
extern "C" fn main(argc: i32, argv: *const *mut libc::c_char) {
let (mut nsecs, mut tfnd, mut flags) = (0, 0, 0);
loop {
let opt = unsafe { libc::getopt(argc, argv, c"nt:".as_ptr()) };
if opt == -1 {
break;
}
match opt as u8 {
b'n' => {
flags = 1;
}
b't' => {
nsecs = unsafe { libc::atoi(optarg) };
tfnd = 1;
}
_ => unsafe { libc::exit(libc::EXIT_FAILURE) },
}
}
unsafe {
libc::printf(
c"flags=%d; tfnd=%d; nsecs=%d; optind=%d\n".as_ptr(),
flags,
tfnd,
nsecs,
optind,
);
}
unsafe {
if optind >= argc {
libc::printf(c"Expected argument after options\n".as_ptr());
libc::exit(libc::EXIT_FAILURE)
}
libc::printf(c"name argument = %s\n".as_ptr(), *argv.add(optind as usize));
}
unsafe { libc::exit(libc::EXIT_SUCCESS) }
}
Important notice: it is not some dismiss of rust, it is just a factual state. MacOS for example pushes you to use libc, since their syscalls ABI is not stable. So there is no way to avoid it