Exemplo n.º 1
0
  /** Expects that the identifier has been consumed. */
  private Token parseArguments(
      TokenSource input,
      FunctionStyleMacro macro,
      IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden,
      TokenSource[] result,
      MacroExpansionTracker tracker)
      throws OffsetLimitReachedException, AbortMacroExpansionException {
    final int argCount = macro.getParameterPlaceholderList().length;
    final boolean hasVarargs = macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS;
    final int requiredArgs = hasVarargs ? argCount - 1 : argCount;
    int idx = 0;
    int nesting = -1;
    for (int i = 0; i < result.length; i++) {
      result[i] = new TokenSource(null);
    }

    boolean missingRParenthesis = false;
    boolean tooManyArgs = false;

    boolean isFirstOfArg = true;
    Token lastToken = null;
    TokenList spaceMarkers = new TokenList();
    loop:
    while (true) {
      Token t = input.fetchFirst();
      if (t == null) {
        missingRParenthesis = true;
        break loop;
      }
      if (tracker != null) {
        switch (t.getType()) {
          case IToken.tEND_OF_INPUT:
          case IToken.tCOMPLETION:
          case ObjCPreprocessor.tSCOPE_MARKER:
          case Lexer.tNEWLINE:
            break;
          default:
            tracker.addFunctionStyleMacroExpansionToken((Token) t.clone());
            break;
        }
      }
      lastToken = t;
      switch (t.getType()) {
        case IToken.tEND_OF_INPUT:
          assert nesting >= 0;
          if (fCompletionMode) {
            if (idx < result.length) {
              throw new CompletionInMacroExpansionException(ORIGIN, t, result[idx]);
            }
            throw new OffsetLimitReachedException(ORIGIN, null);
          }
          missingRParenthesis = true;
          break loop;
        case IToken.tCOMPLETION:
          if (idx < result.length) {
            result[idx].append(t);
            throw new CompletionInMacroExpansionException(ORIGIN, t, result[idx]);
          }
          throw new OffsetLimitReachedException(ORIGIN, t);

        case Lexer.tNEWLINE:
          continue loop;

        case IToken.tLPAREN:
          // the first one sets nesting to zero.
          if (++nesting == 0) {
            continue;
          }
          break;

        case IToken.tRPAREN:
          assert nesting >= 0;
          if (--nesting < 0) {
            break loop;
          }
          break;

        case IToken.tCOMMA:
          assert nesting >= 0;
          if (nesting == 0) {
            if (idx < argCount - 1) { // next argument
              isFirstOfArg = true;
              spaceMarkers.clear();
              idx++;
              continue loop;
            } else if (!hasVarargs) {
              tooManyArgs = true;
              break loop;
            }
          }
          break;

        case ObjCPreprocessor.tSCOPE_MARKER:
          if (argCount == 0) {
            ((ExpansionBoundary) t).execute(forbidden);
          } else {
            result[idx].append(t);
          }
          continue loop;

        case ObjCPreprocessor.tSPACE:
        case ObjCPreprocessor.tNOSPACE:
          if (!isFirstOfArg) {
            spaceMarkers.append(t);
          }
          continue loop;

        default:
          assert nesting >= 0;
      }
      if (argCount == 0) {
        tooManyArgs = true;
        break loop;
      }
      result[idx].appendAll(spaceMarkers);
      result[idx].append(t);
      isFirstOfArg = false;
    }

    if (missingRParenthesis) {
      handleProblem(IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, macro.getNameCharArray());
      throw new AbortMacroExpansionException();
    }

    if (tooManyArgs) {
      handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray());
    } else if (idx + 1 < requiredArgs) {
      handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray());
    }
    return lastToken;
  }