|
32 | 32 | import java.nio.charset.Charset;
|
33 | 33 | import java.util.ArrayList;
|
34 | 34 | import java.util.Collections;
|
35 |
| -import java.util.LinkedList; |
36 | 35 | import java.util.List;
|
37 | 36 | import java.util.Optional;
|
38 | 37 | import javax.annotation.CheckForNull;
|
@@ -196,7 +195,10 @@ public PreprocessorAction process(List<Token> tokens) {
|
196 | 195 | } else if (state().skipTokens() && !GenericTokenType.EOF.equals(type)) {
|
197 | 196 | return oneConsumedToken(token);
|
198 | 197 | } else if (GenericTokenType.IDENTIFIER.equals(type) || (type instanceof CxxKeyword)) {
|
199 |
| - return handleMacroReplacement(tokens); |
| 198 | + PPMacro macro = getMacro(token.getValue()); |
| 199 | + if (macro != null) { |
| 200 | + return macroReplacement(macro, tokens); |
| 201 | + } |
200 | 202 | }
|
201 | 203 |
|
202 | 204 | return PreprocessorAction.NO_OPERATION;
|
@@ -557,70 +559,71 @@ private PreprocessorAction handleModuleLine(AstNode ast, Token token) {
|
557 | 559 | * Every identifier and every keyword can be a macro instance. Pipe the resulting string through a lexer to create
|
558 | 560 | * proper tokens and to expand recursively all macros which may be in there.
|
559 | 561 | */
|
560 |
| - private PreprocessorAction handleMacroReplacement(List<Token> tokens) { |
| 562 | + private PreprocessorAction macroReplacement(PPMacro macro, List<Token> tokens) { |
561 | 563 | var action = PreprocessorAction.NO_OPERATION;
|
562 | 564 | var firstToken = tokens.get(0);
|
563 |
| - var macro = getMacro(firstToken.getValue()); |
564 |
| - if (macro != null) { |
565 |
| - var totalTokensConsumed = 0; |
566 |
| - List<Token> result; |
567 |
| - |
568 |
| - if (macro.parameterList == null) { |
569 |
| - totalTokensConsumed = 1; |
570 |
| - result = new LinkedList<>(replace.replaceObjectLikeMacro( |
571 |
| - macro, TokenUtils.merge(PPConcatenation.concatenate(macro.replacementList))) |
572 |
| - ); |
573 |
| - } else { |
574 |
| - result = new LinkedList<>(); |
575 |
| - int argsTokensConsumed = replace.replaceFunctionLikeMacro( |
576 |
| - macro, tokens.subList(1, tokens.size()), result); |
577 |
| - if (argsTokensConsumed > 0) { |
578 |
| - totalTokensConsumed = 1 + argsTokensConsumed; |
579 |
| - } |
| 565 | + var consumedTokens = 0; |
| 566 | + List<Token> result; |
| 567 | + |
| 568 | + if (macro.isFunctionLikeMacro()) { |
| 569 | + result = new ArrayList<>(); |
| 570 | + int consumedArgTokens = replace.replaceFunctionLikeMacro( |
| 571 | + macro, tokens.subList(1, tokens.size()), result); |
| 572 | + if (consumedArgTokens > 0) { |
| 573 | + consumedTokens = 1 + consumedArgTokens; |
580 | 574 | }
|
| 575 | + } else { |
| 576 | + consumedTokens = 1; |
| 577 | + result = replace.replaceObjectLikeMacro( |
| 578 | + macro, TokenUtils.merge(PPConcatenation.concatenate(macro.replacementList)) |
| 579 | + ); |
| 580 | + } |
581 | 581 |
|
582 |
| - if (totalTokensConsumed > 0) { |
583 |
| - // Rescanning to expand function like macros, in case it requires consuming more tokens |
584 |
| - unitMacros.pushDisable(macro.identifier); |
585 |
| - List<Token> rescanningResult = new LinkedList<>(); |
586 |
| - totalTokensConsumed = rescanning(result, tokens, totalTokensConsumed, rescanningResult); |
587 |
| - unitMacros.popDisable(); |
588 |
| - |
589 |
| - result = TokenList.adjustPosition(rescanningResult, firstToken); |
590 |
| - action = new PreprocessorAction( |
591 |
| - totalTokensConsumed, |
592 |
| - Collections.singletonList(Trivia.createSkippedText(tokens.subList(0, totalTokensConsumed))), |
593 |
| - result); |
594 |
| - } |
| 582 | + if (consumedTokens > 0) { |
| 583 | + // Rescanning to expand function like macros, in case it requires consuming more tokens |
| 584 | + unitMacros.pushDisable(macro.identifier); |
| 585 | + List<Token> rescanningResult = new ArrayList<>(); |
| 586 | + consumedTokens = macroRescanning(result, tokens, consumedTokens, rescanningResult); |
| 587 | + unitMacros.popDisable(); |
| 588 | + |
| 589 | + result = TokenList.adjustPosition(rescanningResult, firstToken); |
| 590 | + action = new PreprocessorAction( |
| 591 | + consumedTokens, |
| 592 | + Collections.singletonList(Trivia.createSkippedText(tokens.subList(0, consumedTokens))), |
| 593 | + result); |
595 | 594 | }
|
596 | 595 |
|
597 | 596 | return action;
|
598 | 597 | }
|
599 | 598 |
|
600 |
| - private int rescanning(List<Token> input, List<Token> tokens, int tokensConsumed, List<Token> output) { |
601 |
| - while (!input.isEmpty()) { |
602 |
| - var firstToken = input.get(0); |
| 599 | + private int macroRescanning(List<Token> input, List<Token> tokens, int consumedTokens, List<Token> output) { |
| 600 | + List<Token> view = input; |
| 601 | + while (!view.isEmpty()) { |
| 602 | + var firstToken = view.get(0); |
603 | 603 | var action = PreprocessorAction.NO_OPERATION;
|
604 |
| - if (firstToken.getType().equals(GenericTokenType.IDENTIFIER)) { |
605 |
| - List<Token> rest = new ArrayList<>(input); |
606 |
| - rest.addAll(tokens.subList(tokensConsumed, tokens.size())); |
607 |
| - action = handleMacroReplacement(rest); |
| 604 | + if (GenericTokenType.IDENTIFIER.equals(firstToken.getType())) { |
| 605 | + PPMacro macro = getMacro(firstToken.getValue()); |
| 606 | + if (macro != null) { |
| 607 | + List<Token> rest = new ArrayList<>(view); |
| 608 | + rest.addAll(tokens.subList(consumedTokens, tokens.size())); |
| 609 | + action = macroReplacement(macro, rest); |
| 610 | + } |
608 | 611 | }
|
609 |
| - if (action.equals(PreprocessorAction.NO_OPERATION)) { |
610 |
| - input.remove(0); |
| 612 | + if (PreprocessorAction.NO_OPERATION.equals(action)) { |
| 613 | + view = view.subList(1, view.size()); // next tokens |
611 | 614 | output.add(firstToken);
|
612 | 615 | } else {
|
613 | 616 | output.addAll(action.getTokensToInject());
|
614 |
| - int tokensConsumedRescanning = action.getNumberOfConsumedTokens(); |
615 |
| - if (tokensConsumedRescanning >= input.size()) { |
616 |
| - tokensConsumed += tokensConsumedRescanning - input.size(); |
617 |
| - input.clear(); |
| 617 | + int consumedRescanningTokens = action.getNumberOfConsumedTokens(); |
| 618 | + if (consumedRescanningTokens >= view.size()) { |
| 619 | + consumedTokens += consumedRescanningTokens - view.size(); |
| 620 | + view = view.subList(view.size(), view.size()); // was last token |
618 | 621 | } else {
|
619 |
| - input.subList(0, tokensConsumedRescanning).clear(); |
| 622 | + view = view.subList(consumedRescanningTokens, view.size()); // next tokens |
620 | 623 | }
|
621 | 624 | }
|
622 | 625 | }
|
623 |
| - return tokensConsumed; |
| 626 | + return consumedTokens; |
624 | 627 | }
|
625 | 628 |
|
626 | 629 | private static PreprocessorAction oneConsumedToken(Token token) {
|
|
0 commit comments