///| Tokenize compiler/linker fragments without executing shell expansion.
///|
/// Supports quoted spaces, empty arguments and escaped characters.
pub fn split_flags(
value : String,
source? : String = "flags",
) -> Result[Array[String], Diagnostic] {
let chars = value.to_array()
let result : Array[String] = []
let token = StringBuilder()
let mut quote : Char? = None
let mut started = false
let mut i = 0
while i < chars.length() {
let c = chars[i]
if c == '\\' && quote != Some('\'') {
if i + 1 == chars.length() {
return Err(
diag("PC007", "Trailing escape in flags", {
source,
line: 1,
column: i + 1,
}),
)
}
let next = chars[i + 1]
if quote == Some('"') &&
next != '"' &&
next != '\\' &&
next != '$' &&
next != '`' &&
next != '\n' {
token.write_char('\\')
}
if next != '\n' {
token.write_char(next)
}
started = true
i = i + 2
continue
}
match quote {
Some(q) => if c == q { quote = None } else { token.write_char(c) }
None =>
if c == '\'' || c == '"' {
quote = Some(c)
started = true
} else if whitespace(c) {
if started {
result.push(token.to_string())
token.reset()
started = false
}
} else {
token.write_char(c)
started = true
}
}
i = i + 1
}
if quote != None {
return Err(
diag("PC006", "Unclosed quote in flags", {
source,
line: 1,
column: chars.length() + 1,
}),
)
}
if started {
result.push(token.to_string())
}
Ok(result)
}