(index<- )        ./libstd/rt/args.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  //! Global storage for command line arguments
  12  //!
  13  //! The current incarnation of the Rust runtime expects for
  14  //! the processes `argc` and `argv` arguments to be stored
  15  //! in a globally-accessible location for use by the `os` module.
  16  //!
  17  //! Only valid to call on linux. Mac and Windows use syscalls to
  18  //! discover the command line arguments.
  19  //!
  20  //! FIXME #7756: Would be nice for this to not exist.
  21  //! FIXME #7756: This has a lot of C glue for lack of globals.
  22  
  23  use option::Option;
  24  use vec::Vec;
  25  #[cfg(test)] use option::{Some, None};
  26  #[cfg(test)] use realstd;
  27  #[cfg(test)] use realargs = realstd::rt::args;
  28  
  29  /// One-time global initialization.
  30  #[cfg(not(test))]
  31  pub unsafe fn init(argc: int, argv: **u8) { imp::init(argc, argv) }
  32  #[cfg(test)]
  33  pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) }
  34  
  35  /// One-time global cleanup.
  36  #[cfg(not(test))] pub unsafe fn cleanup() { imp::cleanup() }
  37  #[cfg(test)]      pub unsafe fn cleanup() { realargs::cleanup() }
  38  
  39  /// Take the global arguments from global storage.
  40  #[cfg(not(test))] pub fn take() -> Option<Vec<~[u8]>> { imp::take() }
  41  #[cfg(test)]      pub fn take() -> Option<Vec<~[u8]>> {
  42      match realargs::take() {
  43          realstd::option::Some(v) => Some(unsafe{ ::cast::transmute(v) }),
  44          realstd::option::None => None,
  45      }
  46  }
  47  
  48  /// Give the global arguments to global storage.
  49  ///
  50  /// It is an error if the arguments already exist.
  51  #[cfg(not(test))] pub fn put(argsVec<~[u8]>) { imp::put(args) }
  52  #[cfg(test)]      pub fn put(args: Vec<~[u8]>) { realargs::put(unsafe { ::cast::transmute(args) }) }
  53  
  54  /// Make a clone of the global arguments.
  55  #[cfg(not(test))] pub fn clone() -> Option<Vec<~[u8]>> { imp::clone() }
  56  #[cfg(test)]      pub fn clone() -> Option<Vec<~[u8]>> {
  57      match realargs::clone() {
  58          realstd::option::Some(v) => Some(unsafe { ::cast::transmute(v) }),
  59          realstd::option::None => None,
  60      }
  61  }
  62  
  63  #[cfg(target_os = "linux")]
  64  #[cfg(target_os = "android")]
  65  #[cfg(target_os = "freebsd")]
  66  mod imp {
  67      use cast;
  68      use clone::Clone;
  69      use option::{Option, Some, None};
  70      use iter::Iterator;
  71      use owned::Box;
  72      use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
  73      use mem;
  74      use vec::Vec;
  75      #[cfg(not(test))] use ptr::RawPtr;
  76  
  77      static mut global_args_ptr: uint = 0;
  78      static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
  79  
  80      #[cfg(not(test))]
  81      pub unsafe fn init(argc: int, argv: **u8) {
  82          let args = load_argc_and_argv(argc, argv);
  83          put(args);
  84      }
  85  
  86      #[cfg(not(test))]
  87      pub unsafe fn cleanup() {
  88          rtassert!(take().is_some());
  89          lock.destroy();
  90      }
  91  
  92      pub fn take() -> Option<Vec<~[u8]>> {
  93          with_lock(|| unsafe {
  94              let ptr = get_global_ptr();
  95              let val = mem::replace(&mut *ptr, None);
  96              val.as_ref().map(|s&Box<Vec<~[u8]>>(**s).clone())
  97          })
  98      }
  99  
 100      pub fn put(argsVec<~[u8]>) {
 101          with_lock(|| unsafe {
 102              let ptr = get_global_ptr();
 103              rtassert!((*ptr).is_none());
 104              (*ptr) = Some(box args.clone());
 105          })
 106      }
 107  
 108      pub fn clone() -> Option<Vec<~[u8]>> {
 109          with_lock(|| unsafe {
 110              let ptr = get_global_ptr();
 111              (*ptr).as_ref().map(|s&Box<Vec<~[u8]>>(**s).clone())
 112          })
 113      }
 114  
 115      fn with_lock<T>(f: || -> T) -> T {
 116          unsafe {
 117              let _guard = lock.lock();
 118              f()
 119          }
 120      }
 121  
 122      fn get_global_ptr() -> *mut Option<Box<Vec<~[u8]>>> {
 123          unsafe { cast::transmute(&global_args_ptr) }
 124      }
 125  
 126      // Copied from `os`.
 127      #[cfg(not(test))]
 128      unsafe fn load_argc_and_argv(argc: int, argv: **u8) -> Vec<~[u8]> {
 129          use c_str::CString;
 130          use ptr::RawPtr;
 131          use libc;
 132          use slice::CloneableVector;
 133          use vec::Vec;
 134  
 135          Vec::from_fn(argc as uint, |i| {
 136              let cs = CString::new(*(argv as **libc::c_char).offset(i as int), false);
 137              cs.as_bytes_no_nul().to_owned()
 138          })
 139      }
 140  
 141      #[cfg(test)]
 142      mod tests {
 143          use prelude::*;
 144          use super::*;
 145          use unstable::finally::Finally;
 146  
 147          #[test]
 148          fn smoke_test() {
 149              // Preserve the actual global state.
 150              let saved_value = take();
 151  
 152              let expected = vec![bytes!("happy").to_owned(), bytes!("today?").to_owned()];
 153  
 154              put(expected.clone());
 155              assert!(clone() == Some(expected.clone()));
 156              assert!(take() == Some(expected.clone()));
 157              assert!(take() == None);
 158  
 159              (|| {
 160              }).finally(|| {
 161                  // Restore the actual global state.
 162                  match saved_value {
 163                      Some(ref args) => put(args.clone()),
 164                      None => ()
 165                  }
 166              })
 167          }
 168      }
 169  }
 170  
 171  #[cfg(target_os = "macos", not(test))]
 172  #[cfg(target_os = "win32", not(test))]
 173  mod imp {
 174      use option::Option;
 175      use vec::Vec;
 176  
 177      pub unsafe fn init(_argc: int, _argv: **u8) {
 178      }
 179  
 180      pub fn cleanup() {
 181      }
 182  
 183      pub fn take() -> Option<Vec<~[u8]>> {
 184          fail!()
 185      }
 186  
 187      pub fn put(_args: Vec<~[u8]>) {
 188          fail!()
 189      }
 190  
 191      pub fn clone() -> Option<Vec<~[u8]>> {
 192          fail!()
 193      }
 194  }


libstd/rt/args.rs:92:4-92:4 -fn- definition:
    pub fn take() -> Option<Vec<~[u8]>> {
        with_lock(|| unsafe {
            let ptr = get_global_ptr();
references:- 2
87:     pub unsafe fn cleanup() {
88:         rtassert!(take().is_some());
89:         lock.destroy();


libstd/rt/args.rs:100:4-100:4 -fn- definition:
    pub fn put(args: Vec<~[u8]>) {
        with_lock(|| unsafe {
            let ptr = get_global_ptr();
references:- 2
82:         let args = load_argc_and_argv(argc, argv);
83:         put(args);
84:     }


libstd/rt/args.rs:122:4-122:4 -fn- definition:
    fn get_global_ptr() -> *mut Option<Box<Vec<~[u8]>>> {
        unsafe { cast::transmute(&global_args_ptr) }
    }
references:- 3
109:         with_lock(|| unsafe {
110:             let ptr = get_global_ptr();
111:             (*ptr).as_ref().map(|s: &Box<Vec<~[u8]>>| (**s).clone())


libstd/rt/args.rs:115:4-115:4 -fn- definition:
    fn with_lock<T>(f: || -> T) -> T {
        unsafe {
            let _guard = lock.lock();
references:- 3
100:     pub fn put(args: Vec<~[u8]>) {
101:         with_lock(|| unsafe {
102:             let ptr = get_global_ptr();
--
108:     pub fn clone() -> Option<Vec<~[u8]>> {
109:         with_lock(|| unsafe {
110:             let ptr = get_global_ptr();