1010use cast:: transmute;
1111use either:: * ;
1212use libc:: { c_void, uintptr_t, c_char, exit, STDERR_FILENO } ;
13- use option:: { Some , None } ;
13+ use option:: { Some , None , Option } ;
1414use rt:: util:: dumb_println;
1515use str:: StrSlice ;
1616use str:: raw:: from_c_str;
1717use u32;
18+ use u32:: { min} ;
1819use unstable:: raw:: Closure ;
1920use vec:: ImmutableVector ;
2021
@@ -30,7 +31,6 @@ struct ModEntry{
3031 log_level : * mut u32
3132}
3233
33- static MAX_LOG_DIRECTIVES : u32 = 255 ;
3434static MAX_LOG_LEVEL : u32 = 255 ;
3535static DEFAULT_LOG_LEVEL : u32 = 1 ;
3636
@@ -68,42 +68,68 @@ fn iter_crate_map(map: *u8, f: &fn(*mut ModEntry)) {
6868 data : * c_void ) ;
6969 }
7070}
71+ static log_level_names : & ' static [ & ' static str ] = & ' static[ "error" , "warn" , "info" , "debug" ] ;
72+
73+ /// Parse an individual log level that is either a number or a symbolic log level
74+ fn parse_log_level ( level : & str ) -> Option < u32 > {
75+ let num = u32:: from_str ( level) ;
76+ let mut log_level;
77+ match ( num) {
78+ Some ( num) => {
79+ if num < MAX_LOG_LEVEL {
80+ log_level = Some ( num) ;
81+ } else {
82+ log_level = Some ( MAX_LOG_LEVEL ) ;
83+ }
84+ }
85+ _ => {
86+ let position = log_level_names. iter ( ) . position ( |& name| name == level) ;
87+ match ( position) {
88+ Some ( position) => {
89+ log_level = Some ( min ( MAX_LOG_LEVEL , ( position + 1 ) as u32 ) )
90+ } ,
91+ _ => {
92+ log_level = None ;
93+ }
94+ }
95+ }
96+ }
97+ log_level
98+ }
99+
71100
72101/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1")
73102/// 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::).
103+ /// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in std::).
104+ /// Also supports string log levels of error, warn, info, and debug
105+
75106fn parse_logging_spec ( spec : ~str ) -> ~[ LogDirective ] {
76107 let mut dirs = ~[ ] ;
77108 for s in spec. split_iter ( ',' ) {
78109 let parts: ~[ & str ] = s. split_iter ( '=' ) . collect ( ) ;
79- let mut loglevel ;
110+ let mut log_level ;
80111 match parts. len ( ) {
81- 1 => loglevel = MAX_LOG_LEVEL ,
112+ 1 => log_level = MAX_LOG_LEVEL ,
82113 2 => {
83- let num = u32 :: from_str ( parts[ 1 ] ) ;
84- match ( num ) {
114+ let possible_log_level = parse_log_level ( parts[ 1 ] ) ;
115+ match possible_log_level {
85116 Some ( num) => {
86- if num < MAX_LOG_LEVEL {
87- loglevel = num;
88- } else {
89- loglevel = MAX_LOG_LEVEL ;
90- }
91- }
117+ log_level = num;
118+ } ,
92119 _ => {
93- dumb_println ( fmt ! ( "warning: invalid logging spec \
94- '%s', ignoring it", s ) ) ;
95- loop ;
120+ dumb_println ( fmt ! ( "warning: invalid logging spec \
121+ '%s', ignoring it", parts [ 1 ] ) ) ;
122+ loop ;
96123 }
97124 }
98- if loglevel > MAX_LOG_LEVEL { loglevel = MAX_LOG_LEVEL }
99125 } ,
100126 _ => {
101127 dumb_println ( fmt ! ( "warning: invalid logging spec '%s',\
102128 ignoring it", s) ) ;
103129 loop ;
104130 }
105131 }
106- let dir = LogDirective { name : parts[ 0 ] . to_owned ( ) , level : loglevel } ;
132+ let dir = LogDirective { name : parts[ 0 ] . to_owned ( ) , level : log_level } ;
107133 dirs. push ( dir) ;
108134 }
109135 return dirs;
@@ -268,6 +294,15 @@ fn parse_logging_spec_invalid_log_level() {
268294 assert_eq!(dirs[0].level, 4);
269295}
270296
297+ #[test]
298+ fn parse_logging_spec_string_log_level() {
299+ // test parse_logging_spec with 'warn' as log level
300+ let dirs: ~[LogDirective] = parse_logging_spec(~" crate1:: mod1=wrong, crate2=warn");
301+ assert_eq!(dirs.len(), 1);
302+ assert!(dirs[0].name == ~" crate2");
303+ assert_eq!(dirs[0].level, 2);
304+ }
305+
271306// Tests for update_entry
272307#[test]
273308fn update_entry_match_full_path() {
0 commit comments