Skip to content

Commit 79e78c4

Browse files
committed
auto merge of #8906 : novalis/rust/master, r=alexcrichton
This is a patch to fix #6031. I didn't see any tests for the C++ library code, so I didn't write a test for my changes. Did I miss something, or are there really no tests?
2 parents aa1d4ef + c684df1 commit 79e78c4

File tree

2 files changed

+150
-49
lines changed

2 files changed

+150
-49
lines changed

doc/rust.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -3385,9 +3385,11 @@ The path to a module consists of the crate name, any parent modules,
33853385
then the module itself, all separated by double colons (`::`). The
33863386
optional log level can be appended to the module path with an equals
33873387
sign (`=`) followed by the log level, from 1 to 4, inclusive. Level 1
3388-
is the error level, 2 is warning, 3 info, and 4 debug. Any logs
3389-
less than or equal to the specified level will be output. If not
3390-
specified then log level 4 is assumed.
3388+
is the error level, 2 is warning, 3 info, and 4 debug. You can also
3389+
use the symbolic constants `error`, `warn`, `info`, and `debug`. Any
3390+
logs less than or equal to the specified level will be output. If not
3391+
specified then log level 4 is assumed. However, debug messages are
3392+
only available if `--cfg=debug` is passed to `rustc`.
33913393

33923394
As an example, to see all the logs generated by the compiler, you would set
33933395
`RUST_LOG` to `rustc`, which is the crate name (as specified in its `link`

src/libstd/rt/logging.rs

+145-46
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use cast::transmute;
1111
use either::*;
1212
use libc::{c_void, uintptr_t, c_char, exit, STDERR_FILENO};
13-
use option::{Some, None};
13+
use option::{Some, None, Option};
1414
use rt::util::dumb_println;
1515
use str::StrSlice;
1616
use str::raw::from_c_str;
@@ -20,7 +20,7 @@ use vec::ImmutableVector;
2020

2121

2222
struct LogDirective {
23-
name: ~str,
23+
name: Option<~str>,
2424
level: u32
2525
}
2626

@@ -30,7 +30,6 @@ struct ModEntry{
3030
log_level: *mut u32
3131
}
3232

33-
static MAX_LOG_DIRECTIVES: u32 = 255;
3433
static MAX_LOG_LEVEL: u32 = 255;
3534
static DEFAULT_LOG_LEVEL: u32 = 1;
3635

@@ -68,42 +67,82 @@ fn iter_crate_map(map: *u8, f: &fn(*mut ModEntry)) {
6867
data: *c_void);
6968
}
7069
}
70+
static log_level_names : &'static[&'static str] = &'static["error", "warn", "info", "debug"];
71+
72+
/// Parse an individual log level that is either a number or a symbolic log level
73+
fn parse_log_level(level: &str) -> Option<u32> {
74+
let num = u32::from_str(level);
75+
let mut log_level;
76+
match num {
77+
Some(num) => {
78+
if num < MAX_LOG_LEVEL {
79+
log_level = Some(num);
80+
} else {
81+
log_level = Some(MAX_LOG_LEVEL);
82+
}
83+
}
84+
_ => {
85+
let position = log_level_names.iter().position(|&name| name == level);
86+
match position {
87+
Some(position) => {
88+
log_level = Some(u32::min(MAX_LOG_LEVEL, (position + 1) as u32))
89+
},
90+
_ => {
91+
log_level = None;
92+
}
93+
}
94+
}
95+
}
96+
log_level
97+
}
98+
7199

72100
/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1")
73101
/// and return a vector with log directives.
74-
/// Valid log levels are 0-255, with the most likely ones being 0-3 (defined in std::).
102+
/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in std::).
103+
/// Also supports string log levels of error, warn, info, and debug
104+
75105
fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
76106
let mut dirs = ~[];
77107
for s in spec.split_iter(',') {
78108
let parts: ~[&str] = s.split_iter('=').collect();
79-
let mut loglevel;
109+
let mut log_level;
110+
let mut name = Some(parts[0].to_owned());
80111
match parts.len() {
81-
1 => loglevel = MAX_LOG_LEVEL,
82-
2 => {
83-
let num = u32::from_str(parts[1]);
84-
match (num) {
112+
1 => {
113+
//if the single argument is a log-level string or number,
114+
//treat that as a global fallback
115+
let possible_log_level = parse_log_level(parts[0]);
116+
match possible_log_level {
85117
Some(num) => {
86-
if num < MAX_LOG_LEVEL {
87-
loglevel = num;
88-
} else {
89-
loglevel = MAX_LOG_LEVEL;
90-
}
118+
name = None;
119+
log_level = num;
120+
},
121+
_ => {
122+
log_level = MAX_LOG_LEVEL
91123
}
124+
}
125+
}
126+
2 => {
127+
let possible_log_level = parse_log_level(parts[1]);
128+
match possible_log_level {
129+
Some(num) => {
130+
log_level = num;
131+
},
92132
_ => {
93-
dumb_println(fmt!("warning: invalid logging spec \
94-
'%s', ignoring it", s));
95-
loop;
133+
dumb_println(fmt!("warning: invalid logging spec \
134+
'%s', ignoring it", parts[1]));
135+
loop;
96136
}
97137
}
98-
if loglevel > MAX_LOG_LEVEL { loglevel = MAX_LOG_LEVEL}
99138
},
100139
_ => {
101140
dumb_println(fmt!("warning: invalid logging spec '%s',\
102141
ignoring it", s));
103142
loop;
104143
}
105144
}
106-
let dir = LogDirective {name: parts[0].to_owned(), level: loglevel};
145+
let dir = LogDirective {name: name, level: log_level};
107146
dirs.push(dir);
108147
}
109148
return dirs;
@@ -113,18 +152,30 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
113152
/// of log directives
114153
fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 {
115154
let mut new_lvl: u32 = DEFAULT_LOG_LEVEL;
116-
let mut longest_match = 0;
155+
let mut longest_match = -1i;
117156
unsafe {
118157
for dir in dirs.iter() {
119-
let name = from_c_str((*entry).name);
120-
if name.starts_with(dir.name) && dir.name.len() > longest_match {
121-
longest_match = dir.name.len();
122-
new_lvl = dir.level;
123-
}
158+
match dir.name {
159+
None => {
160+
if longest_match == -1 {
161+
longest_match = 0;
162+
new_lvl = dir.level;
163+
}
164+
}
165+
Some(ref dir_name) => {
166+
let name = from_c_str((*entry).name);
167+
let len = dir_name.len() as int;
168+
if name.starts_with(*dir_name) &&
169+
len >= longest_match {
170+
longest_match = len;
171+
new_lvl = dir.level;
172+
}
173+
}
174+
};
124175
}
125176
*(*entry).log_level = new_lvl;
126177
}
127-
if longest_match > 0 { return 1; } else { return 0; }
178+
if longest_match >= 0 { return 1; } else { return 0; }
128179
}
129180

130181
#[fixed_stack_segment] #[inline(never)]
@@ -238,45 +289,66 @@ extern {
238289
// Tests for parse_logging_spec()
239290
#[test]
240291
fn parse_logging_spec_valid() {
241-
let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=1,crate1::mod2,crate2=4");
292+
let dirs = parse_logging_spec(~"crate1::mod1=1,crate1::mod2,crate2=4");
242293
assert_eq!(dirs.len(), 3);
243-
assert!(dirs[0].name == ~"crate1::mod1");
294+
assert!(dirs[0].name == Some(~"crate1::mod1"));
244295
assert_eq!(dirs[0].level, 1);
245296
246-
assert!(dirs[1].name == ~"crate1::mod2");
297+
assert!(dirs[1].name == Some(~"crate1::mod2"));
247298
assert_eq!(dirs[1].level, MAX_LOG_LEVEL);
248299
249-
assert!(dirs[2].name == ~"crate2");
300+
assert!(dirs[2].name == Some(~"crate2"));
250301
assert_eq!(dirs[2].level, 4);
251302
}
252303
253304
#[test]
254305
fn parse_logging_spec_invalid_crate() {
255306
// test parse_logging_spec with multiple = in specification
256-
let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=1=2,crate2=4");
307+
let dirs = parse_logging_spec(~"crate1::mod1=1=2,crate2=4");
257308
assert_eq!(dirs.len(), 1);
258-
assert!(dirs[0].name == ~"crate2");
309+
assert!(dirs[0].name == Some(~"crate2"));
259310
assert_eq!(dirs[0].level, 4);
260311
}
261312
262313
#[test]
263314
fn parse_logging_spec_invalid_log_level() {
264315
// test parse_logging_spec with 'noNumber' as log level
265-
let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=noNumber,crate2=4");
316+
let dirs = parse_logging_spec(~"crate1::mod1=noNumber,crate2=4");
266317
assert_eq!(dirs.len(), 1);
267-
assert!(dirs[0].name == ~"crate2");
318+
assert!(dirs[0].name == Some(~"crate2"));
268319
assert_eq!(dirs[0].level, 4);
269320
}
270321
322+
#[test]
323+
fn parse_logging_spec_string_log_level() {
324+
// test parse_logging_spec with 'warn' as log level
325+
let dirs = parse_logging_spec(~"crate1::mod1=wrong,crate2=warn");
326+
assert_eq!(dirs.len(), 1);
327+
assert!(dirs[0].name == Some(~"crate2"));
328+
assert_eq!(dirs[0].level, 2);
329+
}
330+
331+
#[test]
332+
fn parse_logging_spec_global() {
333+
// test parse_logging_spec with no crate
334+
let dirs = parse_logging_spec(~"warn,crate2=4");
335+
assert_eq!(dirs.len(), 2);
336+
assert!(dirs[0].name == None);
337+
assert_eq!(dirs[0].level, 2);
338+
assert!(dirs[1].name == Some(~"crate2"));
339+
assert_eq!(dirs[1].level, 4);
340+
}
341+
271342
// Tests for update_entry
272343
#[test]
273344
fn update_entry_match_full_path() {
274345
use c_str::ToCStr;
275-
let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 },
276-
LogDirective {name: ~"crate2", level: 3}];
346+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
347+
LogDirective {name: Some(~"crate2"), level: 3}];
348+
let level = &mut 0;
277349
unsafe {
278350
do "crate1::mod1".to_c_str().with_ref |ptr| {
279-
let entry= &ModEntry {name: ptr, log_level: &mut 0};
351+
let entry= &ModEntry {name: ptr, log_level: level};
280352
let m = update_entry(dirs, transmute(entry));
281353
assert!(*entry.log_level == 2);
282354
assert!(m == 1);
@@ -287,11 +359,12 @@ fn update_entry_match_full_path() {
287359
#[test]
288360
fn update_entry_no_match() {
289361
use c_str::ToCStr;
290-
let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 },
291-
LogDirective {name: ~"crate2", level: 3}];
362+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
363+
LogDirective {name: Some(~"crate2"), level: 3}];
364+
let level = &mut 0;
292365
unsafe {
293366
do "crate3::mod1".to_c_str().with_ref |ptr| {
294-
let entry= &ModEntry {name: ptr, log_level: &mut 0};
367+
let entry= &ModEntry {name: ptr, log_level: level};
295368
let m = update_entry(dirs, transmute(entry));
296369
assert!(*entry.log_level == DEFAULT_LOG_LEVEL);
297370
assert!(m == 0);
@@ -302,11 +375,12 @@ fn update_entry_no_match() {
302375
#[test]
303376
fn update_entry_match_beginning() {
304377
use c_str::ToCStr;
305-
let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 },
306-
LogDirective {name: ~"crate2", level: 3}];
378+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
379+
LogDirective {name: Some(~"crate2"), level: 3}];
380+
let level = &mut 0;
307381
unsafe {
308382
do "crate2::mod1".to_c_str().with_ref |ptr| {
309-
let entry= &ModEntry {name: ptr, log_level: &mut 0};
383+
let entry= &ModEntry {name: ptr, log_level: level};
310384
let m = update_entry(dirs, transmute(entry));
311385
assert!(*entry.log_level == 3);
312386
assert!(m == 1);
@@ -317,14 +391,39 @@ fn update_entry_match_beginning() {
317391
#[test]
318392
fn update_entry_match_beginning_longest_match() {
319393
use c_str::ToCStr;
320-
let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 },
321-
LogDirective {name: ~"crate2", level: 3}, LogDirective {name: ~"crate2::mod", level: 4}];
394+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
395+
LogDirective {name: Some(~"crate2"), level: 3},
396+
LogDirective {name: Some(~"crate2::mod"), level: 4}];
397+
let level = &mut 0;
322398
unsafe {
323399
do "crate2::mod1".to_c_str().with_ref |ptr| {
324-
let entry = &ModEntry {name: ptr, log_level: &mut 0};
400+
let entry = &ModEntry {name: ptr, log_level: level};
325401
let m = update_entry(dirs, transmute(entry));
326402
assert!(*entry.log_level == 4);
327403
assert!(m == 1);
328404
}
329405
}
330406
}
407+
408+
#[test]
409+
fn update_entry_match_default() {
410+
use c_str::ToCStr;
411+
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
412+
LogDirective {name: None, level: 3}
413+
];
414+
let level = &mut 0;
415+
unsafe {
416+
do "crate1::mod1".to_c_str().with_ref |ptr| {
417+
let entry= &ModEntry {name: ptr, log_level: level};
418+
let m = update_entry(dirs, transmute(entry));
419+
assert!(*entry.log_level == 2);
420+
assert!(m == 1);
421+
}
422+
do "crate2::mod2".to_c_str().with_ref |ptr| {
423+
let entry= &ModEntry {name: ptr, log_level: level};
424+
let m = update_entry(dirs, transmute(entry));
425+
assert!(*entry.log_level == 3);
426+
assert!(m == 1);
427+
}
428+
}
429+
}

0 commit comments

Comments
 (0)