Skip to content

Commit

Permalink
auto merge of #8296 : erickt/rust/remove-str-trailing-nulls, r=erickt
Browse files Browse the repository at this point in the history
This PR fixes #7235 and #3371, which removes trailing nulls from `str` types. Instead, it replaces the creation of c strings with a new type, `std::c_str::CString`, which wraps a malloced byte array, and respects:

*  No interior nulls
* Ends with a trailing null
  • Loading branch information
bors committed Aug 10, 2013
2 parents e81e81f + ee59aac commit 60f5011
Show file tree
Hide file tree
Showing 47 changed files with 1,236 additions and 619 deletions.
12 changes: 6 additions & 6 deletions src/libextra/rl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// FIXME #3921. This is unsafe because linenoise uses global mutable
// state without mutexes.


use std::c_str::ToCStr;
use std::libc::{c_char, c_int};
use std::local_data;
use std::str;
Expand All @@ -32,7 +32,7 @@ pub mod rustrt {

/// Add a line to history
pub unsafe fn add_history(line: &str) -> bool {
do line.as_c_str |buf| {
do line.to_c_str().with_ref |buf| {
rustrt::linenoiseHistoryAdd(buf) == 1 as c_int
}
}
Expand All @@ -44,21 +44,21 @@ pub unsafe fn set_history_max_len(len: int) -> bool {

/// Save line history to a file
pub unsafe fn save_history(file: &str) -> bool {
do file.as_c_str |buf| {
do file.to_c_str().with_ref |buf| {
rustrt::linenoiseHistorySave(buf) == 1 as c_int
}
}

/// Load line history from a file
pub unsafe fn load_history(file: &str) -> bool {
do file.as_c_str |buf| {
do file.to_c_str().with_ref |buf| {
rustrt::linenoiseHistoryLoad(buf) == 1 as c_int
}
}

/// Print out a prompt and then wait for input and return it
pub unsafe fn read(prompt: &str) -> Option<~str> {
do prompt.as_c_str |buf| {
do prompt.to_c_str().with_ref |buf| {
let line = rustrt::linenoise(buf);

if line.is_null() { None }
Expand All @@ -80,7 +80,7 @@ pub unsafe fn complete(cb: CompletionCb) {

unsafe {
do cb(str::raw::from_c_str(line)) |suggestion| {
do suggestion.as_c_str |buf| {
do suggestion.to_c_str().with_ref |buf| {
rustrt::linenoiseAddCompletion(completions, buf);
}
}
Expand Down
100 changes: 98 additions & 2 deletions src/libextra/terminfo/parm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ impl FormatOp {
}
}

#[cfg(stage0)]
fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
let mut s = match val {
Number(d) => {
Expand Down Expand Up @@ -545,8 +546,103 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
String(s) => {
match op {
FormatString => {
let mut s = s.to_bytes_with_null();
s.pop(); // remove the null
let mut s = s.as_bytes().to_owned();
if flags.precision > 0 && flags.precision < s.len() {
s.truncate(flags.precision);
}
s
}
_ => {
return Err(fmt!("non-string on stack with %%%c", op.to_char()))
}
}
}
};
if flags.width > s.len() {
let n = flags.width - s.len();
if flags.left {
s.grow(n, &(' ' as u8));
} else {
let mut s_ = vec::with_capacity(flags.width);
s_.grow(n, &(' ' as u8));
s_.push_all_move(s);
s = s_;
}
}
Ok(s)
}

#[cfg(not(stage0))]
fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
let mut s = match val {
Number(d) => {
match op {
FormatString => {
return Err(~"non-number on stack with %s")
}
_ => {
let radix = match op {
FormatDigit => 10,
FormatOctal => 8,
FormatHex|FormatHEX => 16,
FormatString => util::unreachable()
};
let mut s = ~[];
match op {
FormatDigit => {
let sign = if flags.sign { SignAll } else { SignNeg };
do int_to_str_bytes_common(d, radix, sign) |c| {
s.push(c);
}
}
_ => {
do int_to_str_bytes_common(d as uint, radix, SignNone) |c| {
s.push(c);
}
}
};
if flags.precision > s.len() {
let mut s_ = vec::with_capacity(flags.precision);
let n = flags.precision - s.len();
s_.grow(n, &('0' as u8));
s_.push_all_move(s);
s = s_;
}
assert!(!s.is_empty(), "string conversion produced empty result");
match op {
FormatDigit => {
if flags.space && !(s[0] == '-' as u8 || s[0] == '+' as u8) {
s.unshift(' ' as u8);
}
}
FormatOctal => {
if flags.alternate && s[0] != '0' as u8 {
s.unshift('0' as u8);
}
}
FormatHex => {
if flags.alternate {
let s_ = util::replace(&mut s, ~['0' as u8, 'x' as u8]);
s.push_all_move(s_);
}
}
FormatHEX => {
s = s.into_ascii().to_upper().into_bytes();
if flags.alternate {
let s_ = util::replace(&mut s, ~['0' as u8, 'X' as u8]);
s.push_all_move(s_);
}
}
FormatString => util::unreachable()
}
s
}
}
}
String(s) => {
match op {
FormatString => {
let mut s = s.as_bytes().to_owned();
if flags.precision > 0 && flags.precision < s.len() {
s.truncate(flags.precision);
}
Expand Down
18 changes: 11 additions & 7 deletions src/libextra/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,14 @@ fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> {
fn match_digits(ss: &str, pos: uint, digits: uint, ws: bool)
-> Option<(i32, uint)> {
let mut pos = pos;
let len = ss.len();
let mut value = 0_i32;

let mut i = 0u;
while i < digits {
if pos >= len {
return None;
}
let range = ss.char_range_at(pos);
pos = range.next;

Expand Down Expand Up @@ -853,7 +857,7 @@ fn do_strftime(format: &str, tm: &Tm) -> ~str {

#[cfg(test)]
mod tests {
use time::*;
use super::*;

use std::float;
use std::os;
Expand Down Expand Up @@ -901,7 +905,7 @@ mod tests {
os::setenv("TZ", "America/Los_Angeles");
tzset();

let time = ::time::Timespec::new(1234567890, 54321);
let time = Timespec::new(1234567890, 54321);
let utc = at_utc(time);

assert!(utc.tm_sec == 30_i32);
Expand All @@ -922,7 +926,7 @@ mod tests {
os::setenv("TZ", "America/Los_Angeles");
tzset();

let time = ::time::Timespec::new(1234567890, 54321);
let time = Timespec::new(1234567890, 54321);
let local = at(time);

error!("time_at: %?", local);
Expand Down Expand Up @@ -950,7 +954,7 @@ mod tests {
os::setenv("TZ", "America/Los_Angeles");
tzset();

let time = ::time::Timespec::new(1234567890, 54321);
let time = Timespec::new(1234567890, 54321);
let utc = at_utc(time);

assert_eq!(utc.to_timespec(), time);
Expand All @@ -961,7 +965,7 @@ mod tests {
os::setenv("TZ", "America/Los_Angeles");
tzset();

let time = ::time::Timespec::new(1234567890, 54321);
let time = Timespec::new(1234567890, 54321);
let utc = at_utc(time);
let local = at(time);

Expand Down Expand Up @@ -1142,7 +1146,7 @@ mod tests {
os::setenv("TZ", "America/Los_Angeles");
tzset();

let time = ::time::Timespec::new(1234567890, 54321);
let time = Timespec::new(1234567890, 54321);
let utc = at_utc(time);
let local = at(time);

Expand All @@ -1156,7 +1160,7 @@ mod tests {
os::setenv("TZ", "America/Los_Angeles");
tzset();

let time = ::time::Timespec::new(1234567890, 54321);
let time = Timespec::new(1234567890, 54321);
let utc = at_utc(time);
let local = at(time);

Expand Down
23 changes: 13 additions & 10 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use middle::trans::common::gensym_name;
use middle::ty;
use util::ppaux;

use std::c_str::ToCStr;
use std::char;
use std::hash::Streaming;
use std::hash;
Expand Down Expand Up @@ -76,9 +77,9 @@ pub fn WriteOutputFile(sess: Session,
OptLevel: c_int,
EnableSegmentedStacks: bool) {
unsafe {
do Triple.as_c_str |Triple| {
do Feature.as_c_str |Feature| {
do Output.as_c_str |Output| {
do Triple.to_c_str().with_ref |Triple| {
do Feature.to_c_str().with_ref |Feature| {
do Output.to_c_str().with_ref |Output| {
let result = llvm::LLVMRustWriteOutputFile(
PM,
M,
Expand All @@ -105,6 +106,7 @@ pub mod jit {
use lib::llvm::{ModuleRef, ContextRef, ExecutionEngineRef};
use metadata::cstore;

use std::c_str::ToCStr;
use std::cast;
use std::local_data;
use std::unstable::intrinsics;
Expand Down Expand Up @@ -146,7 +148,7 @@ pub mod jit {

debug!("linking: %s", path);

do path.as_c_str |buf_t| {
do path.to_c_str().with_ref |buf_t| {
if !llvm::LLVMRustLoadCrate(manager, buf_t) {
llvm_err(sess, ~"Could not link");
}
Expand All @@ -165,7 +167,7 @@ pub mod jit {
// Next, we need to get a handle on the _rust_main function by
// looking up it's corresponding ValueRef and then requesting that
// the execution engine compiles the function.
let fun = do "_rust_main".as_c_str |entry| {
let fun = do "_rust_main".to_c_str().with_ref |entry| {
llvm::LLVMGetNamedFunction(m, entry)
};
if fun.is_null() {
Expand Down Expand Up @@ -230,6 +232,7 @@ pub mod write {

use back::passes;

use std::c_str::ToCStr;
use std::libc::{c_int, c_uint};
use std::path::Path;
use std::run;
Expand Down Expand Up @@ -263,14 +266,14 @@ pub mod write {
output_type_bitcode => {
if opts.optimize != session::No {
let filename = output.with_filetype("no-opt.bc");
do filename.to_str().as_c_str |buf| {
do filename.to_c_str().with_ref |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
}
}
}
_ => {
let filename = output.with_filetype("bc");
do filename.to_str().as_c_str |buf| {
do filename.to_c_str().with_ref |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
}
}
Expand Down Expand Up @@ -333,7 +336,7 @@ pub mod write {
// Always output the bitcode file with --save-temps

let filename = output.with_filetype("opt.bc");
do filename.to_str().as_c_str |buf| {
do filename.to_c_str().with_ref |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf)
};
// Save the assembly file if -S is used
Expand Down Expand Up @@ -391,13 +394,13 @@ pub mod write {

if output_type == output_type_llvm_assembly {
// Given options "-S --emit-llvm": output LLVM assembly
do output.to_str().as_c_str |buf_o| {
do output.to_c_str().with_ref |buf_o| {
llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o);
}
} else {
// If only a bitcode file is asked for by using the
// '--emit-llvm' flag, then output it here
do output.to_str().as_c_str |buf| {
do output.to_c_str().with_ref |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/back/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::c_str::ToCStr;
use std::io;

use driver::session::{OptLevel, No, Less, Aggressive};
Expand Down Expand Up @@ -172,7 +173,7 @@ pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~s
}

pub fn create_pass(name:&str) -> Option<PassRef> {
do name.as_c_str |s| {
do name.to_c_str().with_ref |s| {
unsafe {
let p = llvm::LLVMCreatePass(s);
if p.is_null() {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.


use std::c_str::ToCStr;
use std::hashmap::HashMap;
use std::libc::{c_uint, c_ushort};
use std::option;
Expand Down Expand Up @@ -2259,7 +2259,7 @@ pub struct TargetData {
}

pub fn mk_target_data(string_rep: &str) -> TargetData {
let lltd = do string_rep.as_c_str |buf| {
let lltd = do string_rep.to_c_str().with_ref |buf| {
unsafe { llvm::LLVMCreateTargetData(buf) }
};

Expand Down
3 changes: 2 additions & 1 deletion src/librustc/metadata/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use syntax::print::pprust;
use syntax::{ast, attr};
use syntax::attr::AttrMetaMethods;

use std::c_str::ToCStr;
use std::cast;
use std::io;
use std::num;
Expand Down Expand Up @@ -198,7 +199,7 @@ pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
fn get_metadata_section(os: os,
filename: &Path) -> Option<@~[u8]> {
unsafe {
let mb = do filename.to_str().as_c_str |buf| {
let mb = do filename.to_c_str().with_ref |buf| {
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
};
if mb as int == 0 { return option::None::<@~[u8]>; }
Expand Down
Loading

0 comments on commit 60f5011

Please sign in to comment.