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; }
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; } } }