예제 #1
0
 private Token tokenpaste(Token arg1, Token arg2, PreprocessorMacro macro) {
   if (arg1 == null) {
     return arg2;
   }
   if (arg2 == null) {
     return arg1;
   }
   final char[] image1 = arg1.getCharImage();
   final char[] image2 = arg2.getCharImage();
   final int l1 = image1.length;
   final int l2 = image2.length;
   final char[] image = new char[l1 + l2];
   System.arraycopy(image1, 0, image, 0, l1);
   System.arraycopy(image2, 0, image, l1, l2);
   Lexer lex = new Lexer(image, fLexOptions, ILexerLog.NULL, null);
   try {
     Token t1 = lex.nextToken();
     Token t2 = lex.nextToken();
     if (t1.getType() != IToken.tEND_OF_INPUT && t2.getType() == IToken.tEND_OF_INPUT) {
       t1.setOffset(arg1.getOffset(), arg2.getEndOffset());
       return t1;
     }
   } catch (OffsetLimitReachedException e) {
   }
   handleProblem(IProblem.PREPROCESSOR_MACRO_PASTING_ERROR, macro.getNameCharArray());
   return null;
 }
예제 #2
0
  private BitSet getParamUsage(PreprocessorMacro macro) {
    final BitSet result = new BitSet();
    final TokenList replacement = macro.getTokens(fDefinitionParser, fLexOptions, this);

    Token l = null;
    Token n;
    for (Token t = replacement.first(); t != null; l = t, t = n) {
      n = (Token) t.getNext();
      switch (t.getType()) {
        case ObjCPreprocessor.tMACRO_PARAMETER:
          int idx = 2 * ((TokenParameterReference) t).getIndex();
          if (!isKind(n, IToken.tPOUNDPOUND)) {
            idx++;
          }
          result.set(idx);
          break;

        case IToken.tPOUND:
          if (isKind(n, ObjCPreprocessor.tMACRO_PARAMETER)) {
            idx = ((TokenParameterReference) n).getIndex();
            result.set(2 * idx);
            t = n;
            n = (Token) n.getNext();
          }
          break;

        case IToken.tPOUNDPOUND:
          if (isKind(n, ObjCPreprocessor.tMACRO_PARAMETER)) {
            idx = ((TokenParameterReference) n).getIndex();
            // gcc-extension
            if (isKind(l, IToken.tCOMMA)
                && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS
                && idx == macro.getParameterPlaceholderList().length - 1
                && !isKind(n.getNext(), IToken.tPOUNDPOUND)) {
              result.set(2 * idx + 1);
            } else {
              result.set(2 * idx);
            }
            t = n;
            n = (Token) n.getNext();
          }
          break;
      }
    }
    return result;
  }
예제 #3
0
  private void objStyleTokenPaste(PreprocessorMacro macro, TokenList result) {
    TokenList replacement = clone(macro.getTokens(fDefinitionParser, fLexOptions, this));

    Token l = null;
    Token n;
    Token pasteArg1 = null;
    for (Token t = replacement.first(); t != null; l = t, t = n) {
      n = (Token) t.getNext();

      switch (t.getType()) {
        case IToken.tPOUNDPOUND:
          if (pasteArg1 != null) {
            Token pasteArg2 = null;
            if (n != null) {
              pasteArg2 = n;
              n = (Token) n.getNext();
            }

            t = tokenpaste(pasteArg1, pasteArg2, macro);
            if (t != null) {
              if (isKind(n, IToken.tPOUNDPOUND)) {
                pasteArg1 = t;
              } else {
                result.append(t);
                addSpacemarker(pasteArg2, n, result); // end
                // token
                // paste
              }
            }
          }
          break;

        default:
          if (isKind(n, IToken.tPOUNDPOUND)) {
            addSpacemarker(l, t, result); // start token paste
            pasteArg1 = t;
          } else {
            result.append(t);
          }
          break;
      }
    }
  }
예제 #4
0
  private void replaceArgs(
      PreprocessorMacro macro, TokenList[] args, TokenList[] expandedArgs, TokenList result) {
    TokenList replacement = clone(macro.getTokens(fDefinitionParser, fLexOptions, this));

    Token l = null;
    Token n;
    Token pasteArg1 = null;
    for (Token t = replacement.first(); t != null; l = t, t = n) {
      n = (Token) t.getNext();

      switch (t.getType()) {
        case ObjCPreprocessor.tMACRO_PARAMETER:
          int idx = ((TokenParameterReference) t).getIndex();
          if (idx < args.length) { // be defensive
            addSpacemarker(l, t, result); // start argument
            // replacement
            if (isKind(n, IToken.tPOUNDPOUND)) {
              TokenList arg = clone(args[idx]);
              pasteArg1 = arg.last();
              if (pasteArg1 != null) {
                result.appendAllButLast(arg);
                addSpacemarker(result.last(), pasteArg1, result); // start
                // token
                // paste
              }
            } else {
              TokenList arg = clone(expandedArgs[idx]);
              result.appendAll(arg);
              addSpacemarker(t, n, result); // end argument
              // replacement
            }
          }
          break;

        case IToken.tPOUND:
          addSpacemarker(l, t, result); // start stringify
          StringBuilder buf = new StringBuilder();
          buf.append('"');
          if (isKind(n, ObjCPreprocessor.tMACRO_PARAMETER)) {
            idx = ((TokenParameterReference) n).getIndex();
            if (idx < args.length) { // be defensive
              stringify(args[idx], buf);
            }
            t = n;
            n = (Token) n.getNext();
          }
          buf.append('"');
          final int length = buf.length();
          final char[] image = new char[length];
          buf.getChars(0, length, image, 0);

          Token generated = new TokenWithImage(IToken.tSTRING, null, 0, 0, image);
          if (isKind(n, IToken.tPOUNDPOUND)) { // start token paste,
            // same as start
            // stringify
            pasteArg1 = generated;
          } else {
            result.append(generated);
            addSpacemarker(t, n, result); // end stringify
          }
          break;

        case IToken.tPOUNDPOUND:
          Token pasteArg2 = null;
          TokenList rest = null;
          if (n != null) {
            if (n.getType() == ObjCPreprocessor.tMACRO_PARAMETER) {
              TokenList arg;
              idx = ((TokenParameterReference) n).getIndex();
              if (idx < args.length) { // be defensive
                arg = clone(args[idx]);
                pasteArg2 = arg.first();
                if (pasteArg2 != null && arg.first() != arg.last()) {
                  rest = arg;
                  rest.removeFirst();
                }
              }
            } else {
              idx = -1;
              pasteArg2 = n;
            }

            t = n;
            n = (Token) n.getNext();
            final boolean pasteNext = isKind(n, IToken.tPOUNDPOUND);

            generated = tokenpaste(pasteArg1, pasteArg2, macro);
            pasteArg1 = null;

            if (generated != null) {
              if (pasteNext && rest == null) {
                pasteArg1 = generated; // no need to mark
                // spaces, done ahead
              } else {
                result.append(generated);
                addSpacemarker(pasteArg2, rest == null ? n : rest.first(), result); // end
                // token
                // paste
              }
            }
            if (rest != null) {
              if (pasteNext) {
                pasteArg1 = rest.last();
                if (pasteArg1 != null) {
                  result.appendAllButLast(rest);
                  addSpacemarker(result.last(), pasteArg1, result); // start
                  // token
                  // paste
                }
              } else {
                result.appendAll(rest);
                if (idx >= 0) {
                  addSpacemarker(t, n, result); // end
                  // argument
                  // replacement
                }
              }
            }
          }
          break;

        case IToken.tCOMMA:
          if (isKind(n, IToken.tPOUNDPOUND)) {
            final Token nn = (Token) n.getNext();
            if (isKind(nn, ObjCPreprocessor.tMACRO_PARAMETER)) {
              idx = ((TokenParameterReference) nn).getIndex();

              // check for gcc-extension preventing the paste
              // operation
              if (idx == args.length - 1
                  && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS
                  && !isKind(nn.getNext(), IToken.tPOUNDPOUND)) {
                final Token nnn = (Token) nn.getNext();
                TokenList arg = clone(expandedArgs[idx]);
                if (arg.isEmpty()) {
                  addSpacemarker(l, t, result);
                  addSpacemarker(nn, nnn, result);
                } else {
                  result.append(t);
                  addSpacemarker(t, n, result);
                  result.appendAll(arg);
                  addSpacemarker(nn, nnn, result);
                }
                t = nn;
                n = nnn;
                break;
              }
            }

            addSpacemarker(l, t, result);
            pasteArg1 = t;
          } else {
            result.append(t);
          }
          break;

        default:
          if (isKind(n, IToken.tPOUNDPOUND)) {
            addSpacemarker(l, t, result); // start token paste
            pasteArg1 = t;
          } else {
            result.append(t);
          }
          break;
      }
    }
  }
예제 #5
0
 @Override
 public String toString() {
   return "{" + (fIsStart ? '+' : '-') + fMacro.getName() + '}'; // $NON-NLS-1$
 }
예제 #6
0
  /**
   * Expects that the identifier of the macro expansion has been consumed. Expands the macro
   * consuming tokens from the input (to read the parameters) and stores the resulting tokens
   * together with boundary markers in the result token list. Returns the last token of the
   * expansion.
   *
   * @throws AbortMacroExpansionException
   */
  private Token expandOne(
      Token lastConsumed,
      PreprocessorMacro macro,
      IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden,
      TokenSource input,
      TokenList result,
      MacroExpansionTracker tracker)
      throws OffsetLimitReachedException {
    if (macro.isFunctionStyle()) {
      final int paramCount = macro.getParameterPlaceholderList().length;
      final TokenSource[] argInputs = new TokenSource[paramCount];
      final BitSet paramUsage = getParamUsage(macro);
      if (tracker != null) {
        tracker.startFunctionStyleMacro((Token) lastConsumed.clone());
      }
      try {
        lastConsumed =
            parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs, tracker);
      } catch (AbortMacroExpansionException e) {
        // ignore this macro expansion
        for (int i = 0; i < argInputs.length; i++) {
          TokenSource argInput = argInputs[i];
          executeScopeMarkers(argInput, forbidden);
          if (tracker != null) {
            tracker.setExpandedMacroArgument(null);
          }
        }
        if (tracker != null) {
          if (tracker.isRequestedStep()) {
            tracker.storeFunctionStyleMacroReplacement(macro, new TokenList(), result);
          } else if (tracker.isDone()) {
            tracker.appendFunctionStyleMacro(result);
          }
          tracker.endFunctionStyleMacro();
        }
        return null;
      }

      TokenList[] clonedArgs = new TokenList[paramCount];
      TokenList[] expandedArgs = new TokenList[paramCount];
      for (int i = 0; i < paramCount; i++) {
        final TokenSource argInput = argInputs[i];
        final boolean needCopy = paramUsage.get(2 * i);
        final boolean needExpansion = paramUsage.get(2 * i + 1);
        clonedArgs[i] = needCopy ? argInput.cloneTokens() : EMPTY_TOKEN_LIST;
        expandedArgs[i] =
            needExpansion ? expandAll(argInput, forbidden, false, tracker) : EMPTY_TOKEN_LIST;
        if (!needExpansion) {
          executeScopeMarkers(argInput, forbidden);
        }

        if (tracker != null) {
          tracker.setExpandedMacroArgument(needExpansion ? expandedArgs[i] : null);
          // make sure that the trailing arguments do not get
          // expanded.
          if (tracker.isDone()) {
            paramUsage.clear();
          }
        }
      }
      if (tracker == null) {
        replaceArgs(macro, clonedArgs, expandedArgs, result);
      } else {
        if (tracker.isRequestedStep()) {
          TokenList replacement = new TokenList();
          replaceArgs(macro, clonedArgs, expandedArgs, replacement);
          tracker.storeFunctionStyleMacroReplacement(macro, replacement, result);
        } else if (tracker.isDone()) {
          tracker.appendFunctionStyleMacro(result);
        } else {
          replaceArgs(macro, clonedArgs, expandedArgs, result);
        }
        tracker.endFunctionStyleMacro();
      }
    } else {
      if (tracker == null) {
        objStyleTokenPaste(macro, result);
      } else {
        if (tracker.isRequestedStep()) {
          TokenList replacement = new TokenList();
          objStyleTokenPaste(macro, replacement);
          tracker.storeObjectStyleMacroReplacement(macro, lastConsumed, replacement, result);
        } else {
          objStyleTokenPaste(macro, result);
        }
        tracker.endObjectStyleMacro();
      }
    }
    return lastConsumed;
  }
예제 #7
0
  private TokenList expandAll(
      TokenSource input,
      IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden,
      boolean protectDefinedConstructs,
      MacroExpansionTracker tracker)
      throws OffsetLimitReachedException {
    final TokenList result = new TokenList();
    boolean protect = false;
    Token l = null;
    Token t = input.removeFirst();
    while (t != null) {
      switch (t.getType()) {
        case ObjCPreprocessor.tSCOPE_MARKER:
          ((ExpansionBoundary) t).execute(forbidden);
          break;
        case IToken.tIDENTIFIER:
          final char[] image = t.getCharImage();
          PreprocessorMacro macro = fDictionary.get(image);
          if (protect || (tracker != null && tracker.isDone())) {
            result.append(t);
          } else if (protectDefinedConstructs && Arrays.equals(image, Keywords.cDEFINED)) {
            t.setType(ObjCPreprocessor.tDEFINED);
            result.append(t);
            protect = true;
          }
          // tricky: don't mark function-style macros if you don't
          // find the left parenthesis
          else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) {
            result.append(t);
          } else if (forbidden.containsKey(macro)) {
            t.setType(ObjCPreprocessor.tEXPANDED_IDENTIFIER); // prevent
            // any
            // further
            // expansion
            result.append(t);
          } else {
            if (fLocationMap != null) {
              ImageLocationInfo info = null;
              if (fLexOptions.fCreateImageLocations) {
                info = createImageLocationInfo(t);
              }
              fImplicitMacroExpansions.add(
                  fLocationMap.encounterImplicitMacroExpansion(macro, info));
            }
            TokenList replacement = new TokenList();

            addSpacemarker(l, t, replacement); // start expansion
            replacement.append(new ExpansionBoundary(macro, true));
            Token last = expandOne(t, macro, forbidden, input, replacement, tracker);
            replacement.append(new ExpansionBoundary(macro, false));
            addSpacemarker(last, input.first(), replacement); // end
            // expansion

            input.prepend(replacement);
          }
          break;
        case IToken.tLPAREN:
        case ObjCPreprocessor.tNOSPACE:
        case ObjCPreprocessor.tSPACE:
          result.append(t);
          break;
        default:
          protect = false;
          result.append(t);
          break;
      }
      l = t;
      t = input.removeFirst();
    }
    return result;
  }