@@ -55,38 +55,35 @@ unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(lp_cmd_line: *const u16, exe_na
55
55
const QUOTE : u16 = '"' as u16 ;
56
56
const TAB : u16 = '\t' as u16 ;
57
57
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 ;
61
58
let mut ret_val = Vec :: new ( ) ;
62
- let mut cur = Vec :: new ( ) ;
63
59
if lp_cmd_line. is_null ( ) || * lp_cmd_line == 0 {
64
60
ret_val. push ( exe_name ( ) ) ;
65
61
return ret_val;
66
62
}
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
+ } ;
68
70
// The executable name at the beginning is special.
69
- match * lp_cmd_line {
71
+ cmd_line = match cmd_line [ 0 ] {
70
72
// The executable name ends at the next quote mark,
71
73
// no matter what.
72
74
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) ) ;
84
79
}
80
+ cut. next ( )
81
+ } ;
82
+ if let Some ( args) = args {
83
+ args
84
+ } else {
85
+ return ret_val;
85
86
}
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 ;
90
87
}
91
88
// Implement quirk: when they say whitespace here,
92
89
// 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
95
92
// end of lpCmdLine is ignored."
96
93
0 ...SPACE => {
97
94
ret_val. push ( OsString :: new ( ) ) ;
98
- i += 1 ;
95
+ & cmd_line [ 1 .. ]
99
96
} ,
100
97
// The executable name ends at the next whitespace,
101
98
// no matter what.
102
99
_ => {
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) ) ;
114
104
}
105
+ cut. next ( )
106
+ } ;
107
+ if let Some ( args) = args {
108
+ args
109
+ } else {
110
+ return ret_val;
115
111
}
116
- ret_val. push ( OsString :: from_wide (
117
- slice:: from_raw_parts ( lp_cmd_line, i as usize )
118
- ) ) ;
119
- i += 1 ;
120
112
}
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 {
124
119
match c {
125
120
// backslash
126
121
BACKSLASH => {
@@ -153,22 +148,18 @@ unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(lp_cmd_line: *const u16, exe_na
153
148
backslash_count = 0 ;
154
149
was_in_quotes = false ;
155
150
}
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
- }
164
151
_ => {
165
152
cur. extend ( iter:: repeat ( b'\\' as u16 ) . take ( backslash_count) ) ;
166
153
backslash_count = 0 ;
167
154
was_in_quotes = false ;
168
155
cur. push ( c) ;
169
156
}
170
157
}
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[ ..] ) ) ;
172
163
}
173
164
ret_val
174
165
}
@@ -267,5 +258,10 @@ mod tests {
267
258
) ;
268
259
chk ( r#"EXE "a"""# , & [ "EXE" , "a\" " ] ) ;
269
260
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" ] ) ;
270
266
}
271
267
}
0 commit comments