|
47 | 47 | import java.io.ByteArrayOutputStream;
|
48 | 48 | import java.io.IOException;
|
49 | 49 | import java.util.ArrayList;
|
50 |
| -import java.util.Arrays; |
51 | 50 | import java.util.List;
|
| 51 | +import java.util.StringTokenizer; |
52 | 52 |
|
53 | 53 | /**
|
54 | 54 | * @author Ray Hilton
|
@@ -552,12 +552,72 @@ else if (StringUtils.isEmpty(cfBundleVersion))
|
552 | 552 |
|
553 | 553 | return true;
|
554 | 554 | }
|
| 555 | + |
| 556 | + enum ParserState { |
| 557 | + NORMAL, |
| 558 | + IN_QUOTE, |
| 559 | + IN_DOUBLE_QUOTE, |
| 560 | + ESCAPE_CHAR |
| 561 | + }; |
555 | 562 |
|
556 | 563 | static List<String> splitXcodeBuildArguments(String xcodebuildArguments) {
|
557 |
| - String[] parts = xcodebuildArguments.split("(?<!\\\\)\\s+"); |
558 |
| - List<String> result = new ArrayList<String>(parts.length); |
559 |
| - for(String arg : parts) { |
560 |
| - result.add(arg.replaceAll("\\\\ ", " ")); |
| 564 | + if (xcodebuildArguments == null || xcodebuildArguments.length() == 0) { |
| 565 | + return new ArrayList<String>(0); |
| 566 | + } |
| 567 | + |
| 568 | + ParserState state = ParserState.NORMAL; |
| 569 | + final StringTokenizer tok = new StringTokenizer(xcodebuildArguments, "\"'\\ ", true); |
| 570 | + final List<String> result = new ArrayList<String>(); |
| 571 | + final StringBuilder current = new StringBuilder(); |
| 572 | + boolean lastTokenHasBeenQuoted = false; |
| 573 | + String nextTok; |
| 574 | + while (tok.hasMoreTokens()) { |
| 575 | + nextTok = tok.nextToken(); |
| 576 | + switch (state) { |
| 577 | + case IN_QUOTE: |
| 578 | + if ("\'".equals(nextTok)) { |
| 579 | + lastTokenHasBeenQuoted = true; |
| 580 | + state = ParserState.NORMAL; |
| 581 | + } else { |
| 582 | + current.append(nextTok); |
| 583 | + } |
| 584 | + break; |
| 585 | + case IN_DOUBLE_QUOTE: |
| 586 | + if ("\"".equals(nextTok)) { |
| 587 | + lastTokenHasBeenQuoted = true; |
| 588 | + state = ParserState.NORMAL; |
| 589 | + } else { |
| 590 | + current.append(nextTok); |
| 591 | + } |
| 592 | + break; |
| 593 | + case ESCAPE_CHAR: |
| 594 | + current.append(nextTok); |
| 595 | + state = ParserState.NORMAL; |
| 596 | + break; |
| 597 | + default: |
| 598 | + if ("\'".equals(nextTok)) { |
| 599 | + state = ParserState.IN_QUOTE; |
| 600 | + } else if ("\"".equals(nextTok)) { |
| 601 | + state = ParserState.IN_DOUBLE_QUOTE; |
| 602 | + } else if ("\\".equals(nextTok)) { |
| 603 | + state = ParserState.ESCAPE_CHAR; |
| 604 | + } else if (" ".equals(nextTok) && !(current.length() > 0 && current.charAt(current.length() - 1) == '\\')) { |
| 605 | + if (lastTokenHasBeenQuoted || current.length() != 0) { |
| 606 | + result.add(current.toString()); |
| 607 | + current.setLength(0); |
| 608 | + } |
| 609 | + } else { |
| 610 | + current.append(nextTok); |
| 611 | + } |
| 612 | + lastTokenHasBeenQuoted = false; |
| 613 | + break; |
| 614 | + } |
| 615 | + } |
| 616 | + if (lastTokenHasBeenQuoted || current.length() != 0) { |
| 617 | + result.add(current.toString()); |
| 618 | + } |
| 619 | + if (state == ParserState.IN_QUOTE || state == ParserState.IN_DOUBLE_QUOTE) { |
| 620 | + throw new IllegalArgumentException(String.format("Inconsistent quotes: %s", xcodebuildArguments)); |
561 | 621 | }
|
562 | 622 | return result;
|
563 | 623 | }
|
|
0 commit comments