Move platform-specific arg handling to sys::args
This commit is contained in:
parent
29e0235415
commit
4d76ac8492
11 changed files with 294 additions and 282 deletions
|
|
@ -21,6 +21,7 @@ use ffi::{OsStr, OsString};
|
|||
use fmt;
|
||||
use io;
|
||||
use path::{Path, PathBuf};
|
||||
use sys;
|
||||
use sys::os as os_imp;
|
||||
|
||||
/// Returns the current working directory as a `PathBuf`.
|
||||
|
|
@ -557,7 +558,7 @@ pub struct Args { inner: ArgsOs }
|
|||
///
|
||||
/// This structure is created through the `std::env::args_os` method.
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
pub struct ArgsOs { inner: os_imp::Args }
|
||||
pub struct ArgsOs { inner: sys::args::Args }
|
||||
|
||||
/// Returns the arguments which this program was started with (normally passed
|
||||
/// via the command line).
|
||||
|
|
@ -606,7 +607,7 @@ pub fn args() -> Args {
|
|||
/// ```
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
pub fn args_os() -> ArgsOs {
|
||||
ArgsOs { inner: os_imp::args() }
|
||||
ArgsOs { inner: sys::args::args() }
|
||||
}
|
||||
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
|
|||
thread_info::set(main_guard, thread);
|
||||
|
||||
// Store our args if necessary in a squirreled away location
|
||||
sys_common::args::init(argc, argv);
|
||||
sys::args::init(argc, argv);
|
||||
|
||||
// Let's run some code!
|
||||
let res = panic::catch_unwind(mem::transmute::<_, fn()>(main));
|
||||
|
|
|
|||
|
|
@ -1,100 +0,0 @@
|
|||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Global storage for command line arguments
|
||||
//!
|
||||
//! The current incarnation of the Rust runtime expects for
|
||||
//! the processes `argc` and `argv` arguments to be stored
|
||||
//! in a globally-accessible location for use by the `os` module.
|
||||
//!
|
||||
//! Only valid to call on Linux. Mac and Windows use syscalls to
|
||||
//! discover the command line arguments.
|
||||
//!
|
||||
//! FIXME #7756: Would be nice for this to not exist.
|
||||
|
||||
#![allow(dead_code)] // different code on OSX/linux/etc
|
||||
|
||||
/// One-time global initialization.
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }
|
||||
|
||||
/// One-time global cleanup.
|
||||
pub unsafe fn cleanup() { imp::cleanup() }
|
||||
|
||||
/// Make a clone of the global arguments.
|
||||
pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
|
||||
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "bitrig",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku"))]
|
||||
mod imp {
|
||||
use libc::c_char;
|
||||
use mem;
|
||||
use ffi::CStr;
|
||||
|
||||
use sys_common::mutex::Mutex;
|
||||
|
||||
static mut GLOBAL_ARGS_PTR: usize = 0;
|
||||
static LOCK: Mutex = Mutex::new();
|
||||
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
let args = (0..argc).map(|i| {
|
||||
CStr::from_ptr(*argv.offset(i) as *const c_char).to_bytes().to_vec()
|
||||
}).collect();
|
||||
|
||||
LOCK.lock();
|
||||
let ptr = get_global_ptr();
|
||||
assert!((*ptr).is_none());
|
||||
(*ptr) = Some(box args);
|
||||
LOCK.unlock();
|
||||
}
|
||||
|
||||
pub unsafe fn cleanup() {
|
||||
LOCK.lock();
|
||||
*get_global_ptr() = None;
|
||||
LOCK.unlock();
|
||||
}
|
||||
|
||||
pub fn clone() -> Option<Vec<Vec<u8>>> {
|
||||
unsafe {
|
||||
LOCK.lock();
|
||||
let ptr = get_global_ptr();
|
||||
let ret = (*ptr).as_ref().map(|s| (**s).clone());
|
||||
LOCK.unlock();
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
|
||||
unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "windows"))]
|
||||
mod imp {
|
||||
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
|
||||
}
|
||||
|
||||
pub fn cleanup() {
|
||||
}
|
||||
|
||||
pub fn clone() -> Option<Vec<Vec<u8>>> {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,6 @@ macro_rules! rtassert {
|
|||
})
|
||||
}
|
||||
|
||||
pub mod args;
|
||||
pub mod at_exit_imp;
|
||||
#[cfg(any(not(cargobuild), feature = "backtrace"))]
|
||||
pub mod backtrace;
|
||||
|
|
@ -92,7 +91,7 @@ pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
|
|||
pub fn cleanup() {
|
||||
static CLEANUP: Once = Once::new();
|
||||
CLEANUP.call_once(|| unsafe {
|
||||
args::cleanup();
|
||||
sys::args::cleanup();
|
||||
sys::stack_overflow::cleanup();
|
||||
at_exit_imp::cleanup();
|
||||
});
|
||||
|
|
|
|||
211
src/libstd/sys/unix/args.rs
Normal file
211
src/libstd/sys/unix/args.rs
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Global initialization and retreival of command line arguments.
|
||||
//!
|
||||
//! On some platforms these are stored during runtime startup,
|
||||
//! and on some they are retrieved from the system on demand.
|
||||
|
||||
#![allow(dead_code)] // runtime init functions not used during testing
|
||||
|
||||
use ffi::OsString;
|
||||
use marker::PhantomData;
|
||||
use vec;
|
||||
|
||||
/// One-time global initialization.
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }
|
||||
|
||||
/// One-time global cleanup.
|
||||
pub unsafe fn cleanup() { imp::cleanup() }
|
||||
|
||||
/// Returns the command line arguments
|
||||
pub fn args() -> Args {
|
||||
imp::args()
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> { self.iter.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize { self.iter.len() }
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "bitrig",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku"))]
|
||||
mod imp {
|
||||
use os::unix::prelude::*;
|
||||
use mem;
|
||||
use ffi::{CStr, OsString};
|
||||
use marker::PhantomData;
|
||||
use libc;
|
||||
use super::Args;
|
||||
|
||||
use sys_common::mutex::Mutex;
|
||||
|
||||
static mut GLOBAL_ARGS_PTR: usize = 0;
|
||||
static LOCK: Mutex = Mutex::new();
|
||||
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
let args = (0..argc).map(|i| {
|
||||
CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
|
||||
}).collect();
|
||||
|
||||
LOCK.lock();
|
||||
let ptr = get_global_ptr();
|
||||
assert!((*ptr).is_none());
|
||||
(*ptr) = Some(box args);
|
||||
LOCK.unlock();
|
||||
}
|
||||
|
||||
pub unsafe fn cleanup() {
|
||||
LOCK.lock();
|
||||
*get_global_ptr() = None;
|
||||
LOCK.unlock();
|
||||
}
|
||||
|
||||
pub fn args() -> Args {
|
||||
let bytes = clone().unwrap_or(Vec::new());
|
||||
let v: Vec<OsString> = bytes.into_iter().map(|v| {
|
||||
OsStringExt::from_vec(v)
|
||||
}).collect();
|
||||
Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
|
||||
}
|
||||
|
||||
fn clone() -> Option<Vec<Vec<u8>>> {
|
||||
unsafe {
|
||||
LOCK.lock();
|
||||
let ptr = get_global_ptr();
|
||||
let ret = (*ptr).as_ref().map(|s| (**s).clone());
|
||||
LOCK.unlock();
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
|
||||
unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos",
|
||||
target_os = "ios"))]
|
||||
mod imp {
|
||||
use ffi::CStr;
|
||||
use marker::PhantomData;
|
||||
use libc;
|
||||
use super::Args;
|
||||
|
||||
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
|
||||
}
|
||||
|
||||
pub fn cleanup() {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn args() -> Args {
|
||||
use os::unix::prelude::*;
|
||||
extern {
|
||||
// These functions are in crt_externs.h.
|
||||
fn _NSGetArgc() -> *mut libc::c_int;
|
||||
fn _NSGetArgv() -> *mut *mut *mut libc::c_char;
|
||||
}
|
||||
|
||||
let vec = unsafe {
|
||||
let (argc, argv) = (*_NSGetArgc() as isize,
|
||||
*_NSGetArgv() as *const *const libc::c_char);
|
||||
(0.. argc as isize).map(|i| {
|
||||
let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
|
||||
OsStringExt::from_vec(bytes)
|
||||
}).collect::<Vec<_>>()
|
||||
};
|
||||
Args {
|
||||
iter: vec.into_iter(),
|
||||
_dont_send_or_sync_me: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
|
||||
// and use underscores in their names - they're most probably
|
||||
// are considered private and therefore should be avoided
|
||||
// Here is another way to get arguments using Objective C
|
||||
// runtime
|
||||
//
|
||||
// In general it looks like:
|
||||
// res = Vec::new()
|
||||
// let args = [[NSProcessInfo processInfo] arguments]
|
||||
// for i in (0..[args count])
|
||||
// res.push([args objectAtIndex:i])
|
||||
// res
|
||||
#[cfg(target_os = "ios")]
|
||||
pub fn args() -> Args {
|
||||
use ffi::OsString;
|
||||
use mem;
|
||||
use str;
|
||||
|
||||
extern {
|
||||
fn sel_registerName(name: *const libc::c_uchar) -> Sel;
|
||||
fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
|
||||
fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
|
||||
}
|
||||
|
||||
#[link(name = "Foundation", kind = "framework")]
|
||||
#[link(name = "objc")]
|
||||
#[cfg(not(cargobuild))]
|
||||
extern {}
|
||||
|
||||
type Sel = *const libc::c_void;
|
||||
type NsId = *const libc::c_void;
|
||||
|
||||
let mut res = Vec::new();
|
||||
|
||||
unsafe {
|
||||
let process_info_sel = sel_registerName("processInfo\0".as_ptr());
|
||||
let arguments_sel = sel_registerName("arguments\0".as_ptr());
|
||||
let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
|
||||
let count_sel = sel_registerName("count\0".as_ptr());
|
||||
let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());
|
||||
|
||||
let klass = objc_getClass("NSProcessInfo\0".as_ptr());
|
||||
let info = objc_msgSend(klass, process_info_sel);
|
||||
let args = objc_msgSend(info, arguments_sel);
|
||||
|
||||
let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
|
||||
for i in 0..cnt {
|
||||
let tmp = objc_msgSend(args, object_at_sel, i);
|
||||
let utf_c_str: *const libc::c_char =
|
||||
mem::transmute(objc_msgSend(tmp, utf8_sel));
|
||||
let bytes = CStr::from_ptr(utf_c_str).to_bytes();
|
||||
res.push(OsString::from(str::from_utf8(bytes).unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData }
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ use libc;
|
|||
#[macro_use]
|
||||
pub mod weak;
|
||||
|
||||
pub mod args;
|
||||
pub mod android;
|
||||
#[cfg(any(not(cargobuild), feature = "backtrace"))]
|
||||
pub mod backtrace;
|
||||
|
|
|
|||
|
|
@ -347,126 +347,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> { self.iter.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize { self.iter.len() }
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
|
||||
}
|
||||
|
||||
/// Returns the command line arguments
|
||||
///
|
||||
/// Returns a list of the command line arguments.
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn args() -> Args {
|
||||
extern {
|
||||
// These functions are in crt_externs.h.
|
||||
fn _NSGetArgc() -> *mut c_int;
|
||||
fn _NSGetArgv() -> *mut *mut *mut c_char;
|
||||
}
|
||||
|
||||
let vec = unsafe {
|
||||
let (argc, argv) = (*_NSGetArgc() as isize,
|
||||
*_NSGetArgv() as *const *const c_char);
|
||||
(0.. argc as isize).map(|i| {
|
||||
let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
|
||||
OsStringExt::from_vec(bytes)
|
||||
}).collect::<Vec<_>>()
|
||||
};
|
||||
Args {
|
||||
iter: vec.into_iter(),
|
||||
_dont_send_or_sync_me: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
|
||||
// and use underscores in their names - they're most probably
|
||||
// are considered private and therefore should be avoided
|
||||
// Here is another way to get arguments using Objective C
|
||||
// runtime
|
||||
//
|
||||
// In general it looks like:
|
||||
// res = Vec::new()
|
||||
// let args = [[NSProcessInfo processInfo] arguments]
|
||||
// for i in (0..[args count])
|
||||
// res.push([args objectAtIndex:i])
|
||||
// res
|
||||
#[cfg(target_os = "ios")]
|
||||
pub fn args() -> Args {
|
||||
use mem;
|
||||
|
||||
extern {
|
||||
fn sel_registerName(name: *const libc::c_uchar) -> Sel;
|
||||
fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
|
||||
fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
|
||||
}
|
||||
|
||||
#[link(name = "Foundation", kind = "framework")]
|
||||
#[link(name = "objc")]
|
||||
#[cfg(not(cargobuild))]
|
||||
extern {}
|
||||
|
||||
type Sel = *const libc::c_void;
|
||||
type NsId = *const libc::c_void;
|
||||
|
||||
let mut res = Vec::new();
|
||||
|
||||
unsafe {
|
||||
let process_info_sel = sel_registerName("processInfo\0".as_ptr());
|
||||
let arguments_sel = sel_registerName("arguments\0".as_ptr());
|
||||
let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
|
||||
let count_sel = sel_registerName("count\0".as_ptr());
|
||||
let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());
|
||||
|
||||
let klass = objc_getClass("NSProcessInfo\0".as_ptr());
|
||||
let info = objc_msgSend(klass, process_info_sel);
|
||||
let args = objc_msgSend(info, arguments_sel);
|
||||
|
||||
let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
|
||||
for i in 0..cnt {
|
||||
let tmp = objc_msgSend(args, object_at_sel, i);
|
||||
let utf_c_str: *const libc::c_char =
|
||||
mem::transmute(objc_msgSend(tmp, utf8_sel));
|
||||
let bytes = CStr::from_ptr(utf_c_str).to_bytes();
|
||||
res.push(OsString::from(str::from_utf8(bytes).unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "bitrig",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
target_os = "nacl",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku"))]
|
||||
pub fn args() -> Args {
|
||||
use sys_common;
|
||||
let bytes = sys_common::args::clone().unwrap_or(Vec::new());
|
||||
let v: Vec<OsString> = bytes.into_iter().map(|v| {
|
||||
OsStringExt::from_vec(v)
|
||||
}).collect();
|
||||
Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||
|
|
|
|||
76
src/libstd/sys/windows/args.rs
Normal file
76
src/libstd/sys/windows/args.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)] // runtime init functions not used during testing
|
||||
|
||||
use os::windows::prelude::*;
|
||||
use sys::c;
|
||||
use slice;
|
||||
use ops::Range;
|
||||
use ffi::OsString;
|
||||
use libc::{c_int, c_void};
|
||||
|
||||
pub unsafe fn init(_argc: isize, _argv: *const *const u8) { }
|
||||
|
||||
pub unsafe fn cleanup() { }
|
||||
|
||||
pub fn args() -> Args {
|
||||
unsafe {
|
||||
let mut nArgs: c_int = 0;
|
||||
let lpCmdLine = c::GetCommandLineW();
|
||||
let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
|
||||
|
||||
// szArcList can be NULL if CommandLinToArgvW failed,
|
||||
// but in that case nArgs is 0 so we won't actually
|
||||
// try to read a null pointer
|
||||
Args { cur: szArgList, range: 0..(nArgs as isize) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
range: Range<isize>,
|
||||
cur: *mut *mut u16,
|
||||
}
|
||||
|
||||
unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString {
|
||||
let mut len = 0;
|
||||
while *ptr.offset(len) != 0 { len += 1; }
|
||||
|
||||
// Push it onto the list.
|
||||
let ptr = ptr as *const u16;
|
||||
let buf = slice::from_raw_parts(ptr, len as usize);
|
||||
OsStringExt::from_wide(buf)
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.range.next().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.range.next_back().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize { self.range.len() }
|
||||
}
|
||||
|
||||
impl Drop for Args {
|
||||
fn drop(&mut self) {
|
||||
// self.cur can be null if CommandLineToArgvW previously failed,
|
||||
// but LocalFree ignores NULL pointers
|
||||
unsafe { c::LocalFree(self.cur as *mut c_void); }
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ use time::Duration;
|
|||
|
||||
#[macro_use] pub mod compat;
|
||||
|
||||
pub mod args;
|
||||
pub mod backtrace;
|
||||
pub mod c;
|
||||
pub mod condvar;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ use error::Error as StdError;
|
|||
use ffi::{OsString, OsStr};
|
||||
use fmt;
|
||||
use io;
|
||||
use libc::{c_int, c_void};
|
||||
use ops::Range;
|
||||
use os::windows::ffi::EncodeWide;
|
||||
use path::{self, PathBuf};
|
||||
use ptr;
|
||||
|
|
@ -272,60 +270,6 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
|
|||
}).map(|_| ())
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
range: Range<isize>,
|
||||
cur: *mut *mut u16,
|
||||
}
|
||||
|
||||
unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString {
|
||||
let mut len = 0;
|
||||
while *ptr.offset(len) != 0 { len += 1; }
|
||||
|
||||
// Push it onto the list.
|
||||
let ptr = ptr as *const u16;
|
||||
let buf = slice::from_raw_parts(ptr, len as usize);
|
||||
OsStringExt::from_wide(buf)
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.range.next().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.range.next_back().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize { self.range.len() }
|
||||
}
|
||||
|
||||
impl Drop for Args {
|
||||
fn drop(&mut self) {
|
||||
// self.cur can be null if CommandLineToArgvW previously failed,
|
||||
// but LocalFree ignores NULL pointers
|
||||
unsafe { c::LocalFree(self.cur as *mut c_void); }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn args() -> Args {
|
||||
unsafe {
|
||||
let mut nArgs: c_int = 0;
|
||||
let lpCmdLine = c::GetCommandLineW();
|
||||
let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
|
||||
|
||||
// szArcList can be NULL if CommandLinToArgvW failed,
|
||||
// but in that case nArgs is 0 so we won't actually
|
||||
// try to read a null pointer
|
||||
Args { cur: szArgList, range: 0..(nArgs as isize) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
super::fill_utf16_buf(|buf, sz| unsafe {
|
||||
c::GetTempPathW(sz, buf)
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[
|
|||
"src/libstd/num/f64.rs",
|
||||
"src/libstd/thread/local.rs",
|
||||
"src/libstd/sys/common/mod.rs",
|
||||
"src/libstd/sys/common/args.rs",
|
||||
"src/libstd/sys/common/net.rs",
|
||||
"src/libstd/sys/common/util.rs",
|
||||
"src/libterm", // Not sure how to make this crate portable, but test needs it
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue