#1090 cpp parser exception with inline asm
This commit is contained in:
@ -3,6 +3,8 @@
|
||||
*/
|
||||
package net.sourceforge.pmd.cpd;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Defines the Language module for C/C++
|
||||
*/
|
||||
@ -14,4 +16,13 @@ public class CPPLanguage extends AbstractLanguage {
|
||||
public CPPLanguage() {
|
||||
super("C++", "cpp", new CPPTokenizer(), ".h", ".hpp", ".hxx", ".c", ".cpp", ".cxx", ".cc", ".C");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see net.sourceforge.pmd.cpd.AbstractLanguage#setProperties(java.util.Properties)
|
||||
*/
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
super.setProperties(properties);
|
||||
((CPPTokenizer)getTokenizer()).setProperties(properties);
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,12 @@
|
||||
*/
|
||||
package net.sourceforge.pmd.cpd;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sourceforge.pmd.PMD;
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.lang.LanguageVersionHandler;
|
||||
import net.sourceforge.pmd.lang.TokenManager;
|
||||
@ -19,6 +23,30 @@ import org.apache.commons.io.IOUtils;
|
||||
*/
|
||||
public class CPPTokenizer implements Tokenizer {
|
||||
|
||||
private boolean skipBlocks = true;
|
||||
private String skipBlocksStart;
|
||||
private String skipBlocksEnd;
|
||||
|
||||
/**
|
||||
* Sets the possible options for the C++ tokenizer.
|
||||
* @param properties the properties
|
||||
* @see #OPTION_SKIP_BLOCKS
|
||||
* @see #OPTION_SKIP_BLOCKS_PATTERN
|
||||
*/
|
||||
public void setProperties(Properties properties) {
|
||||
skipBlocks = Boolean.parseBoolean(properties.getProperty(OPTION_SKIP_BLOCKS, Boolean.TRUE.toString()));
|
||||
if (skipBlocks) {
|
||||
String skipBlocksPattern = properties.getProperty(OPTION_SKIP_BLOCKS_PATTERN, DEFAULT_SKIP_BLOCKS_PATTERN);
|
||||
String[] split = skipBlocksPattern.split("\\|", 2);
|
||||
skipBlocksStart = split[0];
|
||||
if (split.length == 1) {
|
||||
skipBlocksEnd = split[0];
|
||||
} else {
|
||||
skipBlocksEnd = split[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tokenize(SourceCode sourceCode, Tokens tokenEntries) {
|
||||
StringBuilder buffer = sourceCode.getCodeBuffer();
|
||||
@ -26,7 +54,7 @@ public class CPPTokenizer implements Tokenizer {
|
||||
try {
|
||||
LanguageVersionHandler languageVersionHandler = LanguageRegistry.getLanguage(CppLanguageModule.NAME)
|
||||
.getDefaultVersion().getLanguageVersionHandler();
|
||||
reader = new StringReader(buffer.toString());
|
||||
reader = new StringReader(maybeSkipBlocks(buffer.toString()));
|
||||
TokenManager tokenManager = languageVersionHandler.getParser(
|
||||
languageVersionHandler.getDefaultParserOptions()).getTokenManager(sourceCode.getFileName(), reader);
|
||||
Token currentToken = (Token) tokenManager.getNextToken();
|
||||
@ -40,8 +68,35 @@ public class CPPTokenizer implements Tokenizer {
|
||||
err.printStackTrace();
|
||||
System.err.println("Skipping " + sourceCode.getFileName() + " due to parse error");
|
||||
tokenEntries.add(TokenEntry.getEOF());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Skipping " + sourceCode.getFileName() + " due to parse error");
|
||||
tokenEntries.add(TokenEntry.getEOF());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(reader);
|
||||
}
|
||||
}
|
||||
|
||||
private String maybeSkipBlocks(String test) throws IOException {
|
||||
if (!skipBlocks) {
|
||||
return test;
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(new StringReader(test));
|
||||
StringBuilder filtered = new StringBuilder(test.length());
|
||||
String line;
|
||||
boolean skip = false;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (skipBlocksStart.equalsIgnoreCase(line.trim())) {
|
||||
skip = true;
|
||||
} else if (skip && skipBlocksEnd.equalsIgnoreCase(line.trim())) {
|
||||
skip = false;
|
||||
}
|
||||
if (!skip) {
|
||||
filtered.append(line);
|
||||
}
|
||||
filtered.append(PMD.EOL); // always add a new line to keep the line-numbering
|
||||
}
|
||||
return filtered.toString();
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,12 @@ package net.sourceforge.pmd.cpd;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sourceforge.pmd.PMD;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CPPTokenizerTest {
|
||||
@ -51,8 +55,43 @@ public class CPPTokenizerTest {
|
||||
assertEquals(17, tokens.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTokenizerWithSkipBlocks() throws Exception {
|
||||
String test = IOUtils.toString(CPPTokenizerTest.class.getResourceAsStream("cpp/cpp_with_asm.cpp"));
|
||||
Tokens tokens = parse(test, true);
|
||||
assertEquals(19, tokens.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTokenizerWithSkipBlocksPattern() throws Exception {
|
||||
String test = IOUtils.toString(CPPTokenizerTest.class.getResourceAsStream("cpp/cpp_with_asm.cpp"));
|
||||
Tokens tokens = parse(test, true, "#if debug|#endif");
|
||||
assertEquals(31, tokens.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTokenizerWithoutSkipBlocks() throws Exception {
|
||||
String test = IOUtils.toString(CPPTokenizerTest.class.getResourceAsStream("cpp/cpp_with_asm.cpp"));
|
||||
Tokens tokens = parse(test, false);
|
||||
assertEquals(37, tokens.size());
|
||||
}
|
||||
|
||||
private Tokens parse(String snippet) {
|
||||
return parse(snippet, false);
|
||||
}
|
||||
private Tokens parse(String snippet, boolean skipBlocks) {
|
||||
return parse(snippet, skipBlocks, null);
|
||||
}
|
||||
private Tokens parse(String snippet, boolean skipBlocks, String skipPattern) {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(Tokenizer.OPTION_SKIP_BLOCKS, Boolean.toString(skipBlocks));
|
||||
if (skipPattern != null) {
|
||||
properties.setProperty(Tokenizer.OPTION_SKIP_BLOCKS_PATTERN, skipPattern);
|
||||
}
|
||||
|
||||
CPPTokenizer tokenizer = new CPPTokenizer();
|
||||
tokenizer.setProperties(properties);
|
||||
|
||||
SourceCode code = new SourceCode(new SourceCode.StringCodeLoader(snippet));
|
||||
Tokens tokens = new Tokens();
|
||||
tokenizer.tokenize(code, tokens);
|
||||
|
@ -0,0 +1,28 @@
|
||||
int main() {
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
int foobar() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void my_memset(void *dest,int fill_value,int count)
|
||||
{
|
||||
__asm __volatile__(
|
||||
"cld\n"
|
||||
"mov %ecx, %ebx\n"
|
||||
"shr 2,%ecx\n"
|
||||
"rep "
|
||||
"stosl\n"
|
||||
"mov %ebx,%ecx\n"
|
||||
" // line 157 mentioned above
|
||||
:
|
||||
: "c" (count), "a" (fill_value), "D" (dest)
|
||||
: "cc","%ebx" );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int otherMethod() {
|
||||
}
|
Reference in New Issue
Block a user