Skip to content
Snippets Groups Projects
Unverified Commit ae097074 authored by Jeremy Soller's avatar Jeremy Soller Committed by GitHub
Browse files

Merge branch 'master' into master

parents 19705ccc 77b7a98d
No related branches found
No related tags found
No related merge requests found
......@@ -534,6 +534,8 @@ version = "0.1.0"
dependencies = [
"cbindgen 0.5.2",
"platform 0.1.0",
"stdio 0.1.0",
"string 0.1.0",
]
[[package]]
......
......@@ -9,3 +9,5 @@ cbindgen = { path = "../../cbindgen" }
[dependencies]
platform = { path = "../platform" }
stdio = { path = "../stdio" }
string = { path = "../string" }
//! getopt implementation for Redox, following http://pubs.opengroup.org/onlinepubs/009695399/functions/getopt.html
use super::platform::types::*;
use super::platform;
use super::stdio;
use super::string;
use core::ptr;
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static mut optarg: *mut c_char = ptr::null_mut();
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static mut optind: c_int = 1;
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static mut opterr: c_int = 1;
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static mut optopt: c_int = -1;
static mut CURRENT_OPT: *mut c_char = ptr::null_mut();
#[no_mangle]
pub unsafe extern "C" fn getopt(
argc: c_int,
argv: *const *mut c_char,
optstring: *const c_char,
) -> c_int {
if CURRENT_OPT.is_null() || *CURRENT_OPT == 0 {
if optind >= argc {
-1
} else {
let current_arg = *argv.offset(optind as isize);
if current_arg.is_null() || *current_arg != b'-' as c_char
|| string::strcmp(current_arg, b"-\0".as_ptr() as _) == 0
{
-1
} else if string::strcmp(current_arg, b"--\0".as_ptr() as _) == 0 {
optind += 1;
-1
} else {
// remove the '-'
let current_arg = current_arg.offset(1);
parse_arg(argc, argv, current_arg, optstring)
}
}
} else {
parse_arg(argc, argv, CURRENT_OPT, optstring)
}
}
unsafe fn parse_arg(
argc: c_int,
argv: *const *mut c_char,
current_arg: *mut c_char,
optstring: *const c_char,
) -> c_int {
let update_current_opt = || {
CURRENT_OPT = current_arg.offset(1);
if *CURRENT_OPT == 0 {
optind += 1;
}
};
let print_error = |desc: &[u8]| {
// NOTE: we don't use fprintf to get around the usage of va_list
stdio::fputs(*argv as _, stdio::stderr);
stdio::fputs(desc.as_ptr() as _, stdio::stderr);
stdio::fputc(*current_arg as _, stdio::stderr);
stdio::fputc(b'\n' as _, stdio::stderr);
};
match find_option(*current_arg, optstring) {
Some(GetoptOption::Flag) => {
update_current_opt();
*current_arg as c_int
}
Some(GetoptOption::OptArg) => {
CURRENT_OPT = b"\0".as_ptr() as _;
if *current_arg.offset(1) == 0 {
optind += 2;
if optind > argc {
CURRENT_OPT = ptr::null_mut();
optopt = *current_arg as c_int;
let errch = if *optstring == b':' as c_char {
b':'
} else {
if opterr != 0 {
print_error(b": option requries an argument -- \0");
}
b'?'
};
errch as c_int
} else {
optarg = *argv.offset(optind as isize - 1);
*current_arg as c_int
}
} else {
optarg = current_arg.offset(1);
optind += 1;
*current_arg as c_int
}
}
None => {
// couldn't find the given option in optstring
if opterr != 0 {
print_error(b": illegal option -- \0");
}
update_current_opt();
optopt = *current_arg as _;
b'?' as c_int
}
}
}
enum GetoptOption {
Flag,
OptArg,
}
unsafe fn find_option(ch: c_char, optstring: *const c_char) -> Option<GetoptOption> {
let mut i = 0;
while *optstring.offset(i) != 0 {
if *optstring.offset(i) == ch {
let result = if *optstring.offset(i + 1) == b':' as c_char {
GetoptOption::OptArg
} else {
GetoptOption::Flag
};
return Some(result);
}
i += 1;
}
None
}
......@@ -3,10 +3,15 @@
#![no_std]
extern crate platform;
extern crate stdio;
extern crate string;
pub use platform::types::*;
pub use getopt::*;
use core::ptr;
mod getopt;
pub const R_OK: c_int = 1;
pub const W_OK: c_int = 2;
pub const X_OK: c_int = 4;
......@@ -204,11 +209,6 @@ pub extern "C" fn getlogin_r(name: *mut c_char, namesize: size_t) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn getopt(argc: c_int, argv: *const *mut c_char, opstring: *const c_char) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn getpagesize() -> c_int {
unimplemented!();
......
......@@ -37,6 +37,7 @@
/string/strchr
/string/strrchr
/string/strspn
/unistd/getopt
/unlink
/waitpid
/write
......
......@@ -37,6 +37,7 @@ EXPECT_BINS=\
string/strpbrk \
string/strtok \
string/strtok_r \
unistd/getopt \
unlink \
waitpid \
write
......
bflg: 0
aflg: 1
errflg: 0
ifile:
ofile: arg
result: 0
bflg: 0
aflg: 1
errflg: 0
ifile:
ofile: arg
result: 0
bflg: 0
aflg: 1
errflg: 0
ifile:
ofile: arg
result: 0
bflg: 0
aflg: 1
errflg: 0
ifile:
ofile: arg
result: 0
bflg: 0
aflg: 1
errflg: 0
ifile:
ofile: arg
result: 0
bflg: 0
aflg: 1
errflg: 0
ifile:
ofile: arg
result: 0
bflg: 0
aflg: 0
errflg: 0
ifile:
ofile:
result: 0
#include <unistd.h>
#include <stdio.h>
#define RUN(...) \
{ \
optind = 1; \
optarg = NULL; \
opterr = 1; \
optopt = -1; \
char *args_arr[] = { __VA_ARGS__ }; \
printf("result: %d\n", runner(sizeof(args_arr) / sizeof(args_arr[0]), args_arr)); \
}
int runner(int argc, char *argv[]) {
int c;
int bflg = 0, aflg = 0, errflg = 0;
char *ifile = "";
char *ofile = "";
while((c = getopt(argc, argv, ":abf:o:")) != -1) {
switch(c) {
case 'a':
if(bflg)
errflg++;
else
aflg++;
break;
case 'b':
if(aflg)
errflg++;
else
bflg++;
break;
case 'f':
ifile = optarg;
break;
case 'o':
ofile = optarg;
break;
case ':':
printf("Option -%c requires an operand\n", optopt);
errflg++;
break;
case '?':
printf("Unrecognized option: -%c\n", optopt);
errflg++;
}
}
printf("bflg: %d\n", bflg);
printf("aflg: %d\n", aflg);
printf("errflg: %d\n", errflg);
printf("ifile: %s\n", ifile);
printf("ofile: %s\n", ofile);
if(errflg) {
printf("Usage: info goes here\n");
return 2;
}
return 0;
}
int main(int argc, const char *argv[]) {
RUN("test", "-ao", "arg", "path", "path");
RUN("test", "-a", "-o", "arg", "path", "path");
RUN("test", "-o", "arg", "-a", "path", "path");
RUN("test", "-a", "-o", "arg", "--", "path", "path");
RUN("test", "-a", "-oarg", "path", "path");
RUN("test", "-aoarg", "path", "path");
RUN("test");
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment