@@ -55,38 +55,35 @@ unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(lp_cmd_line: *const u16, exe_na
5555 const QUOTE : u16 = '"' as u16 ;
5656 const TAB : u16 = '\t' as u16 ;
5757 const SPACE : u16 = ' ' as u16 ;
58- let mut in_quotes = false ;
59- let mut was_in_quotes = false ;
60- let mut backslash_count: usize = 0 ;
6158 let mut ret_val = Vec :: new ( ) ;
62- let mut cur = Vec :: new ( ) ;
6359 if lp_cmd_line. is_null ( ) || * lp_cmd_line == 0 {
6460 ret_val. push ( exe_name ( ) ) ;
6561 return ret_val;
6662 }
67- let mut i = 0 ;
63+ let mut cmd_line = {
64+ let mut end = 0 ;
65+ while * lp_cmd_line. offset ( end) != 0 {
66+ end += 1 ;
67+ }
68+ slice:: from_raw_parts ( lp_cmd_line, end as usize )
69+ } ;
6870 // The executable name at the beginning is special.
69- match * lp_cmd_line {
71+ cmd_line = match cmd_line [ 0 ] {
7072 // The executable name ends at the next quote mark,
7173 // no matter what.
7274 QUOTE => {
73- loop {
74- i += 1 ;
75- let c = * lp_cmd_line. offset ( i) ;
76- if c == 0 {
77- ret_val. push ( OsString :: from_wide (
78- slice:: from_raw_parts ( lp_cmd_line. offset ( 1 ) , i as usize - 1 )
79- ) ) ;
80- return ret_val;
81- }
82- if c == QUOTE {
83- break ;
75+ let args = {
76+ let mut cut = cmd_line[ 1 ..] . splitn ( 2 , |& c| c == QUOTE ) ;
77+ if let Some ( exe) = cut. next ( ) {
78+ ret_val. push ( OsString :: from_wide ( exe) ) ;
8479 }
80+ cut. next ( )
81+ } ;
82+ if let Some ( args) = args {
83+ args
84+ } else {
85+ return ret_val;
8586 }
86- ret_val. push ( OsString :: from_wide (
87- slice:: from_raw_parts ( lp_cmd_line. offset ( 1 ) , i as usize - 1 )
88- ) ) ;
89- i += 1 ;
9087 }
9188 // Implement quirk: when they say whitespace here,
9289 // they include the entire ASCII control plane:
@@ -95,32 +92,30 @@ unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(lp_cmd_line: *const u16, exe_na
9592 // end of lpCmdLine is ignored."
9693 0 ...SPACE => {
9794 ret_val. push ( OsString :: new ( ) ) ;
98- i += 1 ;
95+ & cmd_line [ 1 .. ]
9996 } ,
10097 // The executable name ends at the next whitespace,
10198 // no matter what.
10299 _ => {
103- loop {
104- i += 1 ;
105- let c = * lp_cmd_line. offset ( i) ;
106- if c == 0 {
107- ret_val. push ( OsString :: from_wide (
108- slice:: from_raw_parts ( lp_cmd_line, i as usize )
109- ) ) ;
110- return ret_val;
111- }
112- if c > 0 && c <= SPACE {
113- break ;
100+ let args = {
101+ let mut cut = cmd_line. splitn ( 2 , |& c| c > 0 && c <= SPACE ) ;
102+ if let Some ( exe) = cut. next ( ) {
103+ ret_val. push ( OsString :: from_wide ( exe) ) ;
114104 }
105+ cut. next ( )
106+ } ;
107+ if let Some ( args) = args {
108+ args
109+ } else {
110+ return ret_val;
115111 }
116- ret_val. push ( OsString :: from_wide (
117- slice:: from_raw_parts ( lp_cmd_line, i as usize )
118- ) ) ;
119- i += 1 ;
120112 }
121- }
122- loop {
123- let c = * lp_cmd_line. offset ( i) ;
113+ } ;
114+ let mut cur = Vec :: new ( ) ;
115+ let mut in_quotes = false ;
116+ let mut was_in_quotes = false ;
117+ let mut backslash_count: usize = 0 ;
118+ for & c in cmd_line {
124119 match c {
125120 // backslash
126121 BACKSLASH => {
@@ -153,22 +148,18 @@ unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(lp_cmd_line: *const u16, exe_na
153148 backslash_count = 0 ;
154149 was_in_quotes = false ;
155150 }
156- 0x00 => {
157- cur. extend ( iter:: repeat ( b'\\' as u16 ) . take ( backslash_count) ) ;
158- // include empty quoted strings at the end of the arguments list
159- if !cur. is_empty ( ) || was_in_quotes || in_quotes {
160- ret_val. push ( OsString :: from_wide ( & cur[ ..] ) ) ;
161- }
162- break ;
163- }
164151 _ => {
165152 cur. extend ( iter:: repeat ( b'\\' as u16 ) . take ( backslash_count) ) ;
166153 backslash_count = 0 ;
167154 was_in_quotes = false ;
168155 cur. push ( c) ;
169156 }
170157 }
171- i += 1 ;
158+ }
159+ cur. extend ( iter:: repeat ( b'\\' as u16 ) . take ( backslash_count) ) ;
160+ // include empty quoted strings at the end of the arguments list
161+ if !cur. is_empty ( ) || was_in_quotes || in_quotes {
162+ ret_val. push ( OsString :: from_wide ( & cur[ ..] ) ) ;
172163 }
173164 ret_val
174165}
@@ -267,5 +258,10 @@ mod tests {
267258 ) ;
268259 chk ( r#"EXE "a"""# , & [ "EXE" , "a\" " ] ) ;
269260 chk ( r#"EXE "a"" a"# , & [ "EXE" , "a\" " , "a" ] ) ;
261+ // quotes cannot be escaped in command names
262+ chk ( r#""EXE" check"# , & [ "EXE" , "check" ] ) ;
263+ chk ( r#""EXE check""# , & [ "EXE check" ] ) ;
264+ chk ( r#""EXE """for""" check"# , & [ "EXE " , r#"for""# , "check" ] ) ;
265+ chk ( r#""EXE \"for\" check"# , & [ r#"EXE \"# , r#"for""# , "check" ] ) ;
270266 }
271267}
0 commit comments