about summary refs log tree commit diff
path: root/src/libstd/sys/unix
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2016-09-29 22:00:44 +0000
committerBrian Anderson <banderson@mozilla.com>2016-10-02 14:52:30 -0700
commit4d76ac84922bec9ea790c1394f6959ad399d7aa1 (patch)
tree17f2debbe4a921dcfc47cfd13e7f1dc56886d77b /src/libstd/sys/unix
parent29e0235415a42299e4a7467c5edb09a159ec680e (diff)
Move platform-specific arg handling to sys::args
Diffstat (limited to 'src/libstd/sys/unix')
-rw-r--r--src/libstd/sys/unix/args.rs211
-rw-r--r--src/libstd/sys/unix/mod.rs1
-rw-r--r--src/libstd/sys/unix/os.rs120
3 files changed, 212 insertions, 120 deletions
diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs
new file mode 100644
index 00000000000..c64db333e51
--- /dev/null
+++ b/src/libstd/sys/unix/args.rs
@@ -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 }
+    }
+}
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index c4763e1739e..dc410cba89e 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -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;
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 850c3d52715..c6118a333b1 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -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 ()>,