summaryrefslogtreecommitdiffstats
path: root/sonar-duplications
diff options
context:
space:
mode:
Diffstat (limited to 'sonar-duplications')
-rw-r--r--sonar-duplications/pom.xml36
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java23
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java136
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyLanguage.java10
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java52
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDListener.java19
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDNullListener.java14
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileFinder.java10
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java47
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Language.java15
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/ReportException.java14
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java136
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/TokenEntry.java84
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokenizer.java10
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokens.java44
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserConstants.java397
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java1687
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/ParseException.java198
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java476
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/Token.java124
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java140
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/FileFinder.java42
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/StringUtil.java310
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractCompoundFilter.java56
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractDelegateFilter.java37
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AndFilter.java34
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/DirectoryFilter.java17
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/FileExtensionFilter.java42
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filter.java11
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filters.java200
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/NotFilter.java25
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/OrFilter.java34
-rw-r--r--sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/RegexStringFilter.java40
-rw-r--r--sonar-duplications/src/main/java/org/sonar/duplications/cpd/CPD.java114
-rw-r--r--sonar-duplications/src/main/java/org/sonar/duplications/cpd/CodeLoaderWithoutCache.java31
-rw-r--r--sonar-duplications/src/main/java/org/sonar/duplications/cpd/FileCodeLoaderWithoutCache.java44
-rw-r--r--sonar-duplications/src/main/java/org/sonar/duplications/cpd/Match.java171
-rw-r--r--sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchAlgorithm.java131
-rw-r--r--sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchCollector.java167
-rw-r--r--sonar-duplications/src/test/java/org/sonar/duplications/cpd/CPDTest.java90
-rw-r--r--sonar-duplications/test-resources/README.txt2
-rw-r--r--sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java41
-rw-r--r--sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java41
-rw-r--r--sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java63
44 files changed, 5415 insertions, 0 deletions
diff --git a/sonar-duplications/pom.xml b/sonar-duplications/pom.xml
new file mode 100644
index 00000000000..9b0554bc921
--- /dev/null
+++ b/sonar-duplications/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar</artifactId>
+ <version>2.3-SNAPSHOT</version>
+ </parent>
+ <artifactId>sonar-duplications</artifactId>
+ <name>Sonar :: Duplications</name>
+ <description>Detect duplicated code</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>pmd</groupId>
+ <artifactId>pmd</artifactId>
+ <version>4.2.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java
new file mode 100644
index 00000000000..b10585d5f97
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java
@@ -0,0 +1,23 @@
+package net.sourceforge.pmd.cpd;
+
+import net.sourceforge.pmd.util.filter.Filters;
+
+import java.io.FilenameFilter;
+
+public abstract class AbstractLanguage implements Language {
+ private final Tokenizer tokenizer;
+ private final FilenameFilter fileFilter;
+
+ public AbstractLanguage(Tokenizer tokenizer, String... extensions) {
+ this.tokenizer = tokenizer;
+ fileFilter = net.sourceforge.pmd.util.filter.Filters.toFilenameFilter(Filters.getFileExtensionOrDirectoryFilter(extensions));
+ }
+
+ public FilenameFilter getFileFilter() {
+ return fileFilter;
+ }
+
+ public Tokenizer getTokenizer() {
+ return tokenizer;
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java
new file mode 100644
index 00000000000..be76b12b139
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java
@@ -0,0 +1,136 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ * @author Zev Blut zb@ubit.com
+ * @author Romain PELISSE belaran@gmail.com
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.util.List;
+
+public abstract class AbstractTokenizer implements Tokenizer
+{
+
+ protected List<String> stringToken; // List<String>, should be setted by children classes
+ protected List<String> ignorableCharacter; // List<String>, should be setted by children classes
+ // FIXME:Maybe an array of 'char' would be better for perfomance ?
+ protected List<String> ignorableStmt; // List<String>, should be setted by children classes
+ protected char ONE_LINE_COMMENT_CHAR = '#'; // Most script language ( shell, ruby, python,...) use this symbol for comment line
+
+ private List<String> code;
+ private int lineNumber = 0;
+ private String currentLine;
+
+ protected boolean spanMultipleLinesString = true; // Most language does, so default is true
+
+ private boolean downcaseString = true;
+
+ public void tokenize(SourceCode tokens, Tokens tokenEntries) {
+ this.code = tokens.getCode();
+
+ for ( this.lineNumber = 0; lineNumber < this.code.size(); lineNumber++ ) {
+ this.currentLine = this.code.get(this.lineNumber);
+ int loc = 0;
+ while ( loc < currentLine.length() ) {
+ StringBuffer token = new StringBuffer();
+ loc = getTokenFromLine(token,loc);
+ if (token.length() > 0 && !isIgnorableString(token.toString())) {
+ if (downcaseString) {
+ token = new StringBuffer(token.toString().toLowerCase());
+ }
+ }
+ }
+ }
+ tokenEntries.add(TokenEntry.getEOF());
+ }
+
+ private int getTokenFromLine(StringBuffer token, int loc) {
+ for (int j = loc; j < this.currentLine.length(); j++) {
+ char tok = this.currentLine.charAt(j);
+ if (!Character.isWhitespace(tok) && !ignoreCharacter(tok)) {
+ if (isComment(tok)) {
+ if (token.length() > 0) {
+ return j;
+ } else {
+ return getCommentToken(token, loc);
+ }
+ } else if (isString(tok)) {
+ if (token.length() > 0) {
+ return j; // we need to now parse the string as a seperate token.
+ } else {
+ // we are at the start of a string
+ return parseString(token, j, tok);
+ }
+ } else {
+ token.append(tok);
+ }
+ } else {
+ if (token.length() > 0) {
+ return j;
+ }
+ }
+ loc = j;
+ }
+ return loc + 1;
+ }
+
+ private int parseString(StringBuffer token, int loc, char stringDelimiter) {
+ boolean escaped = false;
+ boolean done = false;
+ char tok = ' '; // this will be replaced.
+ while ((loc < currentLine.length()) && ! done) {
+ tok = currentLine.charAt(loc);
+ if (escaped && tok == stringDelimiter) // Found an escaped string
+ escaped = false;
+ else if (tok == stringDelimiter && (token.length() > 0)) // We are done, we found the end of the string...
+ done = true;
+ else if (tok == '\\') // Found an escaped char
+ escaped = true;
+ else // Adding char...
+ escaped = false;
+ //Adding char to String:" + token.toString());
+ token.append(tok);
+ loc++;
+ }
+ // Handling multiple lines string
+ if ( ! done && // ... we didn't find the end of the string
+ loc >= currentLine.length() && // ... we have reach the end of the line ( the String is incomplete, for the moment at least)
+ this.spanMultipleLinesString && // ... the language allow multiple line span Strings
+ ++this.lineNumber < this.code.size() // ... there is still more lines to parse
+ ) {
+ // parsing new line
+ this.currentLine = this.code.get(this.lineNumber);
+ // Warning : recursive call !
+ loc = this.parseString(token, loc, stringDelimiter);
+ }
+ return loc + 1;
+ }
+
+ private boolean ignoreCharacter(char tok)
+ {
+ return this.ignorableCharacter.contains("" + tok);
+ }
+
+ private boolean isString(char tok)
+ {
+ return this.stringToken.contains("" + tok);
+ }
+
+ private boolean isComment(char tok)
+ {
+ return tok == ONE_LINE_COMMENT_CHAR;
+ }
+
+ private int getCommentToken(StringBuffer token, int loc)
+ {
+ while (loc < this.currentLine.length())
+ {
+ token.append(this.currentLine.charAt(loc++));
+ }
+ return loc;
+ }
+
+ private boolean isIgnorableString(String token)
+ {
+ return this.ignorableStmt.contains(token);
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyLanguage.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyLanguage.java
new file mode 100644
index 00000000000..2bf3f913f3d
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyLanguage.java
@@ -0,0 +1,10 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+public class AnyLanguage extends AbstractLanguage {
+ public AnyLanguage(String extension) {
+ super(new AnyTokenizer(), extension);
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java
new file mode 100644
index 00000000000..cd2bd17ade8
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java
@@ -0,0 +1,52 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.io.BufferedReader;
+import java.io.CharArrayReader;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * This class does a best-guess try-anything tokenization.
+ *
+ * @author jheintz
+ */
+public class AnyTokenizer implements Tokenizer {
+ public static final String TOKENS = " \t!#$%^&*(){}-=+<>/\\`~;:";
+
+ public void tokenize(SourceCode sourceCode, Tokens tokenEntries) {
+ StringBuffer sb = sourceCode.getCodeBuffer();
+ BufferedReader reader = new BufferedReader(new CharArrayReader(sb.toString().toCharArray()));
+ try {
+ int lineNumber = 1;
+ String line = reader.readLine();
+ while (line != null) {
+ StringTokenizer tokenizer = new StringTokenizer(line, TOKENS, true);
+ try {
+ String token = tokenizer.nextToken();
+ while (token != null) {
+ if (!token.equals(" ") && !token.equals("\t")) {
+ tokenEntries.add(new TokenEntry(token, sourceCode.getFileName(), lineNumber));
+ }
+ token = tokenizer.nextToken();
+ }
+ } catch (NoSuchElementException ex) {
+ // done with tokens
+ }
+ // advance iteration variables
+ line = reader.readLine();
+ lineNumber++;
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ } finally {
+ try {
+ reader.close();
+ } catch (Exception ex) {
+ }
+ tokenEntries.add(TokenEntry.getEOF());
+ }
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDListener.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDListener.java
new file mode 100644
index 00000000000..a675007718b
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDListener.java
@@ -0,0 +1,19 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.io.File;
+
+public interface CPDListener {
+
+ public static final int INIT = 0;
+ public static final int HASH = 1;
+ public static final int MATCH = 2;
+ public static final int GROUPING = 3;
+ public static final int DONE = 4;
+
+ void addedFile(int fileCount, File file);
+
+ void phaseUpdate(int phase);
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDNullListener.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDNullListener.java
new file mode 100644
index 00000000000..8a8a1e6ddc0
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDNullListener.java
@@ -0,0 +1,14 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.io.File;
+
+public class CPDNullListener implements CPDListener {
+ public void addedFile(int fileCount, File file) {
+ }
+
+ public void phaseUpdate(int phase) {
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileFinder.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileFinder.java
new file mode 100644
index 00000000000..587c9d8aca1
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileFinder.java
@@ -0,0 +1,10 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+/**
+ * @deprecated Use net.sourceforge.pmd.util.FileFinder instead.
+ */
+public class FileFinder extends net.sourceforge.pmd.util.FileFinder {
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java
new file mode 100644
index 00000000000..a4fff9ea0aa
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java
@@ -0,0 +1,47 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.io.*;
+
+/**
+ * @author Philippe T'Seyen
+ */
+public class FileReporter {
+ private File reportFile;
+ private String encoding;
+
+ public FileReporter(String encoding) {
+ this(null, encoding);
+ }
+
+ public FileReporter(File reportFile) {
+ this(reportFile, System.getProperty("file.encoding"));
+ }
+
+ public FileReporter(File reportFile, String encoding) {
+ this.reportFile = reportFile;
+ this.encoding = encoding;
+ }
+
+ public void report(String content) throws ReportException {
+ try {
+ Writer writer = null;
+ try {
+ OutputStream outputStream;
+ if (reportFile == null) {
+ outputStream = System.out;
+ } else {
+ outputStream = new FileOutputStream(reportFile);
+ }
+ writer = new BufferedWriter(new OutputStreamWriter(outputStream, encoding));
+ writer.write(content);
+ } finally {
+ if (writer != null) writer.close();
+ }
+ } catch (IOException ioe) {
+ throw new ReportException(ioe);
+ }
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Language.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Language.java
new file mode 100644
index 00000000000..dc861835a49
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Language.java
@@ -0,0 +1,15 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.io.FilenameFilter;
+
+public interface Language {
+
+ String fileSeparator = System.getProperty("file.separator");
+
+ public Tokenizer getTokenizer();
+
+ public FilenameFilter getFileFilter();
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/ReportException.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/ReportException.java
new file mode 100644
index 00000000000..680da398bf6
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/ReportException.java
@@ -0,0 +1,14 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+/**
+ * @author Philippe T'Seyen
+ */
+public class ReportException extends Exception {
+
+ public ReportException(Throwable cause) {
+ super();
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java
new file mode 100644
index 00000000000..1c79e203561
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java
@@ -0,0 +1,136 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.io.*;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SourceCode {
+
+ public static final String EOL = System.getProperty("line.separator", "\n");
+
+ public static abstract class CodeLoader {
+ private SoftReference<List<String>> code;
+
+ public List<String> getCode() {
+ List<String> c = null;
+ if (code != null) {
+ c = code.get();
+ }
+ if (c != null) {
+ return c;
+ }
+ this.code = new SoftReference<List<String>>(load());
+ return code.get();
+ }
+
+ public abstract String getFileName();
+
+ protected abstract Reader getReader() throws Exception;
+
+ protected List<String> load() {
+ LineNumberReader lnr = null;
+ try {
+ lnr = new LineNumberReader(getReader());
+ List<String> lines = new ArrayList<String>();
+ String currentLine;
+ while ((currentLine = lnr.readLine()) != null) {
+ lines.add(currentLine);
+ }
+ return lines;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage());
+ } finally {
+ try {
+ if (lnr != null)
+ lnr.close();
+ } catch (Exception e) {
+ throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage());
+ }
+ }
+ }
+ }
+
+ public static class FileCodeLoader extends CodeLoader {
+ private File file;
+ private String encoding;
+
+ public FileCodeLoader(File file, String encoding) {
+ this.file = file;
+ this.encoding = encoding;
+ }
+
+ public Reader getReader() throws Exception {
+ return new InputStreamReader(new FileInputStream(file), encoding);
+ }
+
+ public String getFileName() {
+ return this.file.getAbsolutePath();
+ }
+ }
+
+ public static class StringCodeLoader extends CodeLoader {
+ public static final String DEFAULT_NAME = "CODE_LOADED_FROM_STRING";
+
+ private String source_code;
+
+ private String name;
+
+ public StringCodeLoader(String code) {
+ this(code, DEFAULT_NAME);
+ }
+
+ public StringCodeLoader(String code, String name) {
+ this.source_code = code;
+ this.name = name;
+ }
+
+ public Reader getReader() {
+ return new StringReader(source_code);
+ }
+
+ public String getFileName() {
+ return name;
+ }
+ }
+
+ private CodeLoader cl;
+
+ public SourceCode(CodeLoader cl) {
+ this.cl = cl;
+ }
+
+ public List<String> getCode() {
+ return cl.getCode();
+ }
+
+ public StringBuffer getCodeBuffer() {
+ StringBuffer sb = new StringBuffer();
+ List<String> lines = cl.getCode();
+ for ( String line : lines ) {
+ sb.append(line);
+ sb.append(EOL);
+ }
+ return sb;
+ }
+
+ public String getSlice(int startLine, int endLine) {
+ StringBuffer sb = new StringBuffer();
+ List lines = cl.getCode();
+ for (int i = (startLine == 0 ? startLine :startLine - 1); i < endLine && i < lines.size(); i++) {
+ if (sb.length() != 0) {
+ sb.append(EOL);
+ }
+ sb.append((String) lines.get(i));
+ }
+ return sb.toString();
+ }
+
+ public String getFileName() {
+ return cl.getFileName();
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/TokenEntry.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/TokenEntry.java
new file mode 100644
index 00000000000..07092e78423
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/TokenEntry.java
@@ -0,0 +1,84 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class TokenEntry implements Comparable<TokenEntry> {
+
+ public static final TokenEntry EOF = new TokenEntry();
+
+ private String tokenSrcID;
+ private int beginLine;
+ private int index;
+ private int identifier;
+ private int hashCode;
+
+ private final static Map<String, Integer> Tokens = new HashMap<String, Integer>();
+ private static int TokenCount = 0;
+
+ private TokenEntry() {
+ this.identifier = 0;
+ this.tokenSrcID = "EOFMarker";
+ }
+
+ public TokenEntry(String image, String tokenSrcID, int beginLine) {
+ Integer i = Tokens.get(image);
+ if (i == null) {
+ i = Tokens.size() + 1;
+ Tokens.put(image, i);
+ }
+ this.identifier = i.intValue();
+ this.tokenSrcID = tokenSrcID;
+ this.beginLine = beginLine;
+ this.index = TokenCount++;
+ }
+
+ public static TokenEntry getEOF() {
+ TokenCount++;
+ return EOF;
+ }
+
+ public static void clearImages() {
+ Tokens.clear();
+ TokenCount = 0;
+ }
+
+ public String getTokenSrcID() {
+ return tokenSrcID;
+ }
+
+ public int getBeginLine() {
+ return beginLine;
+ }
+
+ public int getIdentifier() {
+ return this.identifier;
+ }
+
+ public int getIndex() {
+ return this.index;
+ }
+
+ public int hashCode() {
+ return hashCode;
+ }
+
+ public void setHashCode(int hashCode) {
+ this.hashCode = hashCode;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof TokenEntry)) {
+ return false;
+ }
+ TokenEntry other = (TokenEntry) o;
+ return other.hashCode == hashCode;
+ }
+
+ public int compareTo(TokenEntry other) {
+ return getIndex() - other.getIndex();
+ }
+} \ No newline at end of file
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokenizer.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokenizer.java
new file mode 100644
index 00000000000..f95c312d496
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokenizer.java
@@ -0,0 +1,10 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import java.io.IOException;
+
+public interface Tokenizer {
+ void tokenize(SourceCode tokens, Tokens tokenEntries) throws IOException;
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokens.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokens.java
new file mode 100644
index 00000000000..c90cf526551
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokens.java
@@ -0,0 +1,44 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd;
+
+import org.sonar.duplications.cpd.Match;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class Tokens {
+
+ private List<TokenEntry> tokens = new ArrayList<TokenEntry>();
+
+ public void add(TokenEntry tokenEntry) {
+ this.tokens.add(tokenEntry);
+ }
+
+ public Iterator<TokenEntry> iterator() {
+ return tokens.iterator();
+ }
+
+ private TokenEntry get(int index) {
+ return tokens.get(index);
+ }
+
+ public int size() {
+ return tokens.size();
+ }
+
+ public int getLineCount(TokenEntry mark, Match match) {
+ TokenEntry endTok = get(mark.getIndex() + match.getTokenCount() - 1);
+ if (endTok == TokenEntry.EOF) {
+ endTok = get(mark.getIndex() + match.getTokenCount() - 2);
+ }
+ return endTok.getBeginLine() - mark.getBeginLine() + 1;
+ }
+
+ public List<TokenEntry> getTokens() {
+ return tokens;
+ }
+
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserConstants.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserConstants.java
new file mode 100644
index 00000000000..79b06785b69
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserConstants.java
@@ -0,0 +1,397 @@
+/* Generated By:JavaCC: Do not edit this line. CPPParserConstants.java */
+package net.sourceforge.pmd.cpd.cppast;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface CPPParserConstants {
+
+ /** End of File. */
+ int EOF = 0;
+ /** RegularExpression Id. */
+ int LCURLYBRACE = 19;
+ /** RegularExpression Id. */
+ int RCURLYBRACE = 20;
+ /** RegularExpression Id. */
+ int LSQUAREBRACKET = 21;
+ /** RegularExpression Id. */
+ int RSQUAREBRACKET = 22;
+ /** RegularExpression Id. */
+ int LPARENTHESIS = 23;
+ /** RegularExpression Id. */
+ int RPARENTHESIS = 24;
+ /** RegularExpression Id. */
+ int SCOPE = 25;
+ /** RegularExpression Id. */
+ int COLON = 26;
+ /** RegularExpression Id. */
+ int SEMICOLON = 27;
+ /** RegularExpression Id. */
+ int COMMA = 28;
+ /** RegularExpression Id. */
+ int QUESTIONMARK = 29;
+ /** RegularExpression Id. */
+ int ELLIPSIS = 30;
+ /** RegularExpression Id. */
+ int ASSIGNEQUAL = 31;
+ /** RegularExpression Id. */
+ int TIMESEQUAL = 32;
+ /** RegularExpression Id. */
+ int DIVIDEEQUAL = 33;
+ /** RegularExpression Id. */
+ int MODEQUAL = 34;
+ /** RegularExpression Id. */
+ int PLUSEQUAL = 35;
+ /** RegularExpression Id. */
+ int MINUSEQUAL = 36;
+ /** RegularExpression Id. */
+ int SHIFTLEFTEQUAL = 37;
+ /** RegularExpression Id. */
+ int SHIFTRIGHTEQUAL = 38;
+ /** RegularExpression Id. */
+ int BITWISEANDEQUAL = 39;
+ /** RegularExpression Id. */
+ int BITWISEXOREQUAL = 40;
+ /** RegularExpression Id. */
+ int BITWISEOREQUAL = 41;
+ /** RegularExpression Id. */
+ int OR = 42;
+ /** RegularExpression Id. */
+ int AND = 43;
+ /** RegularExpression Id. */
+ int BITWISEOR = 44;
+ /** RegularExpression Id. */
+ int BITWISEXOR = 45;
+ /** RegularExpression Id. */
+ int AMPERSAND = 46;
+ /** RegularExpression Id. */
+ int EQUAL = 47;
+ /** RegularExpression Id. */
+ int NOTEQUAL = 48;
+ /** RegularExpression Id. */
+ int LESSTHAN = 49;
+ /** RegularExpression Id. */
+ int GREATERTHAN = 50;
+ /** RegularExpression Id. */
+ int LESSTHANOREQUALTO = 51;
+ /** RegularExpression Id. */
+ int GREATERTHANOREQUALTO = 52;
+ /** RegularExpression Id. */
+ int SHIFTLEFT = 53;
+ /** RegularExpression Id. */
+ int SHIFTRIGHT = 54;
+ /** RegularExpression Id. */
+ int PLUS = 55;
+ /** RegularExpression Id. */
+ int MINUS = 56;
+ /** RegularExpression Id. */
+ int STAR = 57;
+ /** RegularExpression Id. */
+ int DIVIDE = 58;
+ /** RegularExpression Id. */
+ int MOD = 59;
+ /** RegularExpression Id. */
+ int PLUSPLUS = 60;
+ /** RegularExpression Id. */
+ int MINUSMINUS = 61;
+ /** RegularExpression Id. */
+ int TILDE = 62;
+ /** RegularExpression Id. */
+ int NOT = 63;
+ /** RegularExpression Id. */
+ int DOT = 64;
+ /** RegularExpression Id. */
+ int POINTERTO = 65;
+ /** RegularExpression Id. */
+ int DOTSTAR = 66;
+ /** RegularExpression Id. */
+ int ARROWSTAR = 67;
+ /** RegularExpression Id. */
+ int AUTO = 68;
+ /** RegularExpression Id. */
+ int BREAK = 69;
+ /** RegularExpression Id. */
+ int CASE = 70;
+ /** RegularExpression Id. */
+ int CATCH = 71;
+ /** RegularExpression Id. */
+ int CHAR = 72;
+ /** RegularExpression Id. */
+ int CONST = 73;
+ /** RegularExpression Id. */
+ int CONTINUE = 74;
+ /** RegularExpression Id. */
+ int _DEFAULT = 75;
+ /** RegularExpression Id. */
+ int DELETE = 76;
+ /** RegularExpression Id. */
+ int DO = 77;
+ /** RegularExpression Id. */
+ int DOUBLE = 78;
+ /** RegularExpression Id. */
+ int ELSE = 79;
+ /** RegularExpression Id. */
+ int ENUM = 80;
+ /** RegularExpression Id. */
+ int EXTERN = 81;
+ /** RegularExpression Id. */
+ int FLOAT = 82;
+ /** RegularExpression Id. */
+ int FOR = 83;
+ /** RegularExpression Id. */
+ int FRIEND = 84;
+ /** RegularExpression Id. */
+ int GOTO = 85;
+ /** RegularExpression Id. */
+ int IF = 86;
+ /** RegularExpression Id. */
+ int INLINE = 87;
+ /** RegularExpression Id. */
+ int INT = 88;
+ /** RegularExpression Id. */
+ int LONG = 89;
+ /** RegularExpression Id. */
+ int NEW = 90;
+ /** RegularExpression Id. */
+ int PRIVATE = 91;
+ /** RegularExpression Id. */
+ int PROTECTED = 92;
+ /** RegularExpression Id. */
+ int PUBLIC = 93;
+ /** RegularExpression Id. */
+ int REDECLARED = 94;
+ /** RegularExpression Id. */
+ int REGISTER = 95;
+ /** RegularExpression Id. */
+ int RETURN = 96;
+ /** RegularExpression Id. */
+ int SHORT = 97;
+ /** RegularExpression Id. */
+ int SIGNED = 98;
+ /** RegularExpression Id. */
+ int SIZEOF = 99;
+ /** RegularExpression Id. */
+ int STATIC = 100;
+ /** RegularExpression Id. */
+ int STRUCT = 101;
+ /** RegularExpression Id. */
+ int CLASS = 102;
+ /** RegularExpression Id. */
+ int SWITCH = 103;
+ /** RegularExpression Id. */
+ int TEMPLATE = 104;
+ /** RegularExpression Id. */
+ int THIS = 105;
+ /** RegularExpression Id. */
+ int TRY = 106;
+ /** RegularExpression Id. */
+ int TYPEDEF = 107;
+ /** RegularExpression Id. */
+ int UNION = 108;
+ /** RegularExpression Id. */
+ int UNSIGNED = 109;
+ /** RegularExpression Id. */
+ int VIRTUAL = 110;
+ /** RegularExpression Id. */
+ int VOID = 111;
+ /** RegularExpression Id. */
+ int VOLATILE = 112;
+ /** RegularExpression Id. */
+ int WHILE = 113;
+ /** RegularExpression Id. */
+ int OPERATOR = 114;
+ /** RegularExpression Id. */
+ int TRUETOK = 115;
+ /** RegularExpression Id. */
+ int FALSETOK = 116;
+ /** RegularExpression Id. */
+ int THROW = 117;
+ /** RegularExpression Id. */
+ int OCTALINT = 118;
+ /** RegularExpression Id. */
+ int OCTALLONG = 119;
+ /** RegularExpression Id. */
+ int UNSIGNED_OCTALINT = 120;
+ /** RegularExpression Id. */
+ int UNSIGNED_OCTALLONG = 121;
+ /** RegularExpression Id. */
+ int DECIMALINT = 122;
+ /** RegularExpression Id. */
+ int DECIMALLONG = 123;
+ /** RegularExpression Id. */
+ int UNSIGNED_DECIMALINT = 124;
+ /** RegularExpression Id. */
+ int UNSIGNED_DECIMALLONG = 125;
+ /** RegularExpression Id. */
+ int HEXADECIMALINT = 126;
+ /** RegularExpression Id. */
+ int HEXADECIMALLONG = 127;
+ /** RegularExpression Id. */
+ int UNSIGNED_HEXADECIMALINT = 128;
+ /** RegularExpression Id. */
+ int UNSIGNED_HEXADECIMALLONG = 129;
+ /** RegularExpression Id. */
+ int FLOATONE = 130;
+ /** RegularExpression Id. */
+ int FLOATTWO = 131;
+ /** RegularExpression Id. */
+ int CHARACTER = 132;
+ /** RegularExpression Id. */
+ int STRING = 133;
+ /** RegularExpression Id. */
+ int ID = 135;
+
+ /** Lexical state. */
+ int DEFAULT = 0;
+ /** Lexical state. */
+ int IN_LINE_COMMENT = 1;
+ /** Lexical state. */
+ int IN_COMMENT = 2;
+ /** Lexical state. */
+ int IN_PREPROCESSOR_OUTPUT_COMMENT = 3;
+ /** Lexical state. */
+ int PREPROCESSOR_OUTPUT = 4;
+
+ /** Literal token values. */
+ String[] tokenImage = {
+ "<EOF>",
+ "\" \"",
+ "\"\\f\"",
+ "\"\\t\"",
+ "\"\\r\\n\"",
+ "\"\\n\"",
+ "\"//\"",
+ "\"/*\"",
+ "\"#\"",
+ "\"\\n\"",
+ "<token of kind 10>",
+ "\"*/\"",
+ "<token of kind 12>",
+ "\"*/\"",
+ "\"\\n\"",
+ "\"/*\"",
+ "\"\\\\\\n\"",
+ "\"\\\\\\r\\n\"",
+ "<token of kind 18>",
+ "\"{\"",
+ "\"}\"",
+ "\"[\"",
+ "\"]\"",
+ "\"(\"",
+ "\")\"",
+ "\"::\"",
+ "\":\"",
+ "\";\"",
+ "\",\"",
+ "\"?\"",
+ "\"...\"",
+ "\"=\"",
+ "\"*=\"",
+ "\"/=\"",
+ "\"%=\"",
+ "\"+=\"",
+ "\"-=\"",
+ "\"<<=\"",
+ "\">>=\"",
+ "\"&=\"",
+ "\"^=\"",
+ "\"|=\"",
+ "\"||\"",
+ "\"&&\"",
+ "\"|\"",
+ "\"^\"",
+ "\"&\"",
+ "\"==\"",
+ "\"!=\"",
+ "\"<\"",
+ "\">\"",
+ "\"<=\"",
+ "\">=\"",
+ "\"<<\"",
+ "\">>\"",
+ "\"+\"",
+ "\"-\"",
+ "\"*\"",
+ "\"/\"",
+ "\"%\"",
+ "\"++\"",
+ "\"--\"",
+ "\"~\"",
+ "\"!\"",
+ "\".\"",
+ "\"->\"",
+ "\".*\"",
+ "\"->*\"",
+ "\"auto\"",
+ "\"break\"",
+ "\"case\"",
+ "\"catch\"",
+ "\"char\"",
+ "\"const\"",
+ "\"continue\"",
+ "\"default\"",
+ "\"delete\"",
+ "\"do\"",
+ "\"double\"",
+ "\"else\"",
+ "\"enum\"",
+ "\"extern\"",
+ "\"float\"",
+ "\"for\"",
+ "\"friend\"",
+ "\"goto\"",
+ "\"if\"",
+ "\"inline\"",
+ "\"int\"",
+ "\"long\"",
+ "\"new\"",
+ "\"private\"",
+ "\"protected\"",
+ "\"public\"",
+ "\"redeclared\"",
+ "\"register\"",
+ "\"return\"",
+ "\"short\"",
+ "\"signed\"",
+ "\"sizeof\"",
+ "\"static\"",
+ "\"struct\"",
+ "\"class\"",
+ "\"switch\"",
+ "\"template\"",
+ "\"this\"",
+ "\"try\"",
+ "\"typedef\"",
+ "\"union\"",
+ "\"unsigned\"",
+ "\"virtual\"",
+ "\"void\"",
+ "\"volatile\"",
+ "\"while\"",
+ "\"operator\"",
+ "\"true\"",
+ "\"false\"",
+ "\"throw\"",
+ "<OCTALINT>",
+ "<OCTALLONG>",
+ "<UNSIGNED_OCTALINT>",
+ "<UNSIGNED_OCTALLONG>",
+ "<DECIMALINT>",
+ "<DECIMALLONG>",
+ "<UNSIGNED_DECIMALINT>",
+ "<UNSIGNED_DECIMALLONG>",
+ "<HEXADECIMALINT>",
+ "<HEXADECIMALLONG>",
+ "<UNSIGNED_HEXADECIMALINT>",
+ "<UNSIGNED_HEXADECIMALLONG>",
+ "<FLOATONE>",
+ "<FLOATTWO>",
+ "<CHARACTER>",
+ "<STRING>",
+ "\"finally\"",
+ "<ID>",
+ };
+
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java
new file mode 100644
index 00000000000..673307e1450
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java
@@ -0,0 +1,1687 @@
+/* Generated By:JavaCC: Do not edit this line. CPPParserTokenManager.java */
+package net.sourceforge.pmd.cpd.cppast;
+
+/** Token Manager. */
+public class CPPParserTokenManager implements CPPParserConstants
+{
+ private static String filename;
+ public static void setFileName(String name) {
+ filename = name;
+ }
+ public static String getFileName() {
+ return filename;
+ }
+
+ /** Debug output. */
+ public static java.io.PrintStream debugStream = System.out;
+ /** Set debug output. */
+ public static void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private static final int jjStopStringLiteralDfa_0(int pos, long active0, long active1, long active2)
+{
+ switch (pos)
+ {
+ case 0:
+ if ((active1 & 0x3ffffffffffff0L) != 0L || (active2 & 0x40L) != 0L)
+ {
+ jjmatchedKind = 135;
+ return 29;
+ }
+ if ((active0 & 0x40000000L) != 0L || (active1 & 0x5L) != 0L)
+ return 1;
+ return -1;
+ case 1:
+ if ((active1 & 0x3fffffffbf9ff0L) != 0L || (active2 & 0x40L) != 0L)
+ {
+ if (jjmatchedPos != 1)
+ {
+ jjmatchedKind = 135;
+ jjmatchedPos = 1;
+ }
+ return 29;
+ }
+ if ((active1 & 0x406000L) != 0L)
+ return 29;
+ return -1;
+ case 2:
+ if ((active1 & 0x3ffbfffab7dff0L) != 0L || (active2 & 0x40L) != 0L)
+ {
+ jjmatchedKind = 135;
+ jjmatchedPos = 2;
+ return 29;
+ }
+ if ((active1 & 0x40005080000L) != 0L)
+ return 29;
+ return -1;
+ case 3:
+ if ((active1 & 0x3779fff8965ea0L) != 0L || (active2 & 0x40L) != 0L)
+ {
+ jjmatchedKind = 135;
+ jjmatchedPos = 3;
+ return 29;
+ }
+ if ((active1 & 0x8820002218150L) != 0L)
+ return 29;
+ return -1;
+ case 4:
+ if ((active1 & 0x569bdf8925c00L) != 0L || (active2 & 0x40L) != 0L)
+ {
+ jjmatchedKind = 135;
+ jjmatchedPos = 4;
+ return 29;
+ }
+ if ((active1 & 0x321042000402a0L) != 0L)
+ return 29;
+ return -1;
+ case 5:
+ if ((active1 & 0x56900d8000c00L) != 0L || (active2 & 0x40L) != 0L)
+ {
+ jjmatchedKind = 135;
+ jjmatchedPos = 5;
+ return 29;
+ }
+ if ((active1 & 0xbd20925000L) != 0L)
+ return 29;
+ return -1;
+ case 6:
+ if ((active1 & 0x52100d0000400L) != 0L)
+ {
+ jjmatchedKind = 135;
+ jjmatchedPos = 6;
+ return 29;
+ }
+ if ((active1 & 0x480008000800L) != 0L || (active2 & 0x40L) != 0L)
+ return 29;
+ return -1;
+ case 7:
+ if ((active1 & 0x50000000L) != 0L)
+ {
+ jjmatchedKind = 135;
+ jjmatchedPos = 7;
+ return 29;
+ }
+ if ((active1 & 0x5210080000400L) != 0L)
+ return 29;
+ return -1;
+ case 8:
+ if ((active1 & 0x40000000L) != 0L)
+ {
+ jjmatchedKind = 135;
+ jjmatchedPos = 8;
+ return 29;
+ }
+ if ((active1 & 0x10000000L) != 0L)
+ return 29;
+ return -1;
+ default :
+ return -1;
+ }
+}
+private static final int jjStartNfa_0(int pos, long active0, long active1, long active2)
+{
+ return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1, active2), pos + 1);
+}
+static private int jjStopAtPos(int pos, int kind)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ return pos + 1;
+}
+static private int jjMoveStringLiteralDfa0_0()
+{
+ switch(curChar)
+ {
+ case 13:
+ return jjMoveStringLiteralDfa1_0(0x10L, 0x0L, 0x0L);
+ case 33:
+ jjmatchedKind = 63;
+ return jjMoveStringLiteralDfa1_0(0x1000000000000L, 0x0L, 0x0L);
+ case 35:
+ return jjStopAtPos(0, 8);
+ case 37:
+ jjmatchedKind = 59;
+ return jjMoveStringLiteralDfa1_0(0x400000000L, 0x0L, 0x0L);
+ case 38:
+ jjmatchedKind = 46;
+ return jjMoveStringLiteralDfa1_0(0x88000000000L, 0x0L, 0x0L);
+ case 40:
+ return jjStopAtPos(0, 23);
+ case 41:
+ return jjStopAtPos(0, 24);
+ case 42:
+ jjmatchedKind = 57;
+ return jjMoveStringLiteralDfa1_0(0x100000000L, 0x0L, 0x0L);
+ case 43:
+ jjmatchedKind = 55;
+ return jjMoveStringLiteralDfa1_0(0x1000000800000000L, 0x0L, 0x0L);
+ case 44:
+ return jjStopAtPos(0, 28);
+ case 45:
+ jjmatchedKind = 56;
+ return jjMoveStringLiteralDfa1_0(0x2000001000000000L, 0xaL, 0x0L);
+ case 46:
+ jjmatchedKind = 64;
+ return jjMoveStringLiteralDfa1_0(0x40000000L, 0x4L, 0x0L);
+ case 47:
+ jjmatchedKind = 58;
+ return jjMoveStringLiteralDfa1_0(0x2000000c0L, 0x0L, 0x0L);
+ case 58:
+ jjmatchedKind = 26;
+ return jjMoveStringLiteralDfa1_0(0x2000000L, 0x0L, 0x0L);
+ case 59:
+ return jjStopAtPos(0, 27);
+ case 60:
+ jjmatchedKind = 49;
+ return jjMoveStringLiteralDfa1_0(0x28002000000000L, 0x0L, 0x0L);
+ case 61:
+ jjmatchedKind = 31;
+ return jjMoveStringLiteralDfa1_0(0x800000000000L, 0x0L, 0x0L);
+ case 62:
+ jjmatchedKind = 50;
+ return jjMoveStringLiteralDfa1_0(0x50004000000000L, 0x0L, 0x0L);
+ case 63:
+ return jjStopAtPos(0, 29);
+ case 91:
+ return jjStopAtPos(0, 21);
+ case 93:
+ return jjStopAtPos(0, 22);
+ case 94:
+ jjmatchedKind = 45;
+ return jjMoveStringLiteralDfa1_0(0x10000000000L, 0x0L, 0x0L);
+ case 97:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x10L, 0x0L);
+ case 98:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x20L, 0x0L);
+ case 99:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x40000007c0L, 0x0L);
+ case 100:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x7800L, 0x0L);
+ case 101:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x38000L, 0x0L);
+ case 102:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x100000001c0000L, 0x40L);
+ case 103:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x200000L, 0x0L);
+ case 105:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x1c00000L, 0x0L);
+ case 108:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x2000000L, 0x0L);
+ case 110:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000L, 0x0L);
+ case 111:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000000000L, 0x0L);
+ case 112:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x38000000L, 0x0L);
+ case 114:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x1c0000000L, 0x0L);
+ case 115:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0xbe00000000L, 0x0L);
+ case 116:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x280f0000000000L, 0x0L);
+ case 117:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x300000000000L, 0x0L);
+ case 118:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x1c00000000000L, 0x0L);
+ case 119:
+ return jjMoveStringLiteralDfa1_0(0x0L, 0x2000000000000L, 0x0L);
+ case 123:
+ return jjStopAtPos(0, 19);
+ case 124:
+ jjmatchedKind = 44;
+ return jjMoveStringLiteralDfa1_0(0x60000000000L, 0x0L, 0x0L);
+ case 125:
+ return jjStopAtPos(0, 20);
+ case 126:
+ return jjStopAtPos(0, 62);
+ default :
+ return jjMoveNfa_0(28, 0);
+ }
+}
+static private int jjMoveStringLiteralDfa1_0(long active0, long active1, long active2)
+{
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(0, active0, active1, active2);
+ return 1;
+ }
+ switch(curChar)
+ {
+ case 10:
+ if ((active0 & 0x10L) != 0L)
+ return jjStopAtPos(1, 4);
+ break;
+ case 38:
+ if ((active0 & 0x80000000000L) != 0L)
+ return jjStopAtPos(1, 43);
+ break;
+ case 42:
+ if ((active0 & 0x80L) != 0L)
+ return jjStopAtPos(1, 7);
+ else if ((active1 & 0x4L) != 0L)
+ return jjStopAtPos(1, 66);
+ break;
+ case 43:
+ if ((active0 & 0x1000000000000000L) != 0L)
+ return jjStopAtPos(1, 60);
+ break;
+ case 45:
+ if ((active0 & 0x2000000000000000L) != 0L)
+ return jjStopAtPos(1, 61);
+ break;
+ case 46:
+ return jjMoveStringLiteralDfa2_0(active0, 0x40000000L, active1, 0L, active2, 0L);
+ case 47:
+ if ((active0 & 0x40L) != 0L)
+ return jjStopAtPos(1, 6);
+ break;
+ case 58:
+ if ((active0 & 0x2000000L) != 0L)
+ return jjStopAtPos(1, 25);
+ break;
+ case 60:
+ if ((active0 & 0x20000000000000L) != 0L)
+ {
+ jjmatchedKind = 53;
+ jjmatchedPos = 1;
+ }
+ return jjMoveStringLiteralDfa2_0(active0, 0x2000000000L, active1, 0L, active2, 0L);
+ case 61:
+ if ((active0 & 0x100000000L) != 0L)
+ return jjStopAtPos(1, 32);
+ else if ((active0 & 0x200000000L) != 0L)
+ return jjStopAtPos(1, 33);
+ else if ((active0 & 0x400000000L) != 0L)
+ return jjStopAtPos(1, 34);
+ else if ((active0 & 0x800000000L) != 0L)
+ return jjStopAtPos(1, 35);
+ else if ((active0 & 0x1000000000L) != 0L)
+ return jjStopAtPos(1, 36);
+ else if ((active0 & 0x8000000000L) != 0L)
+ return jjStopAtPos(1, 39);
+ else if ((active0 & 0x10000000000L) != 0L)
+ return jjStopAtPos(1, 40);
+ else if ((active0 & 0x20000000000L) != 0L)
+ return jjStopAtPos(1, 41);
+ else if ((active0 & 0x800000000000L) != 0L)
+ return jjStopAtPos(1, 47);
+ else if ((active0 & 0x1000000000000L) != 0L)
+ return jjStopAtPos(1, 48);
+ else if ((active0 & 0x8000000000000L) != 0L)
+ return jjStopAtPos(1, 51);
+ else if ((active0 & 0x10000000000000L) != 0L)
+ return jjStopAtPos(1, 52);
+ break;
+ case 62:
+ if ((active0 & 0x40000000000000L) != 0L)
+ {
+ jjmatchedKind = 54;
+ jjmatchedPos = 1;
+ }
+ else if ((active1 & 0x2L) != 0L)
+ {
+ jjmatchedKind = 65;
+ jjmatchedPos = 1;
+ }
+ return jjMoveStringLiteralDfa2_0(active0, 0x4000000000L, active1, 0x8L, active2, 0L);
+ case 97:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x100000000000c0L, active2, 0L);
+ case 101:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x101c4001800L, active2, 0L);
+ case 102:
+ if ((active1 & 0x400000L) != 0L)
+ return jjStartNfaWithStates_0(1, 86, 29);
+ break;
+ case 104:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x22020200000100L, active2, 0L);
+ case 105:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x400c00000000L, active2, 0x40L);
+ case 108:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x4000048000L, active2, 0L);
+ case 110:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x300001810000L, active2, 0L);
+ case 111:
+ if ((active1 & 0x2000L) != 0L)
+ {
+ jjmatchedKind = 77;
+ jjmatchedPos = 1;
+ }
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x1800002284600L, active2, 0L);
+ case 112:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x4000000000000L, active2, 0L);
+ case 114:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x8040018100020L, active2, 0L);
+ case 116:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x3000000000L, active2, 0L);
+ case 117:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x20000010L, active2, 0L);
+ case 119:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x8000000000L, active2, 0L);
+ case 120:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x20000L, active2, 0L);
+ case 121:
+ return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x80000000000L, active2, 0L);
+ case 124:
+ if ((active0 & 0x40000000000L) != 0L)
+ return jjStopAtPos(1, 42);
+ break;
+ default :
+ break;
+ }
+ return jjStartNfa_0(0, active0, active1, active2);
+}
+static private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1, long old2, long active2)
+{
+ if (((active0 &= old0) | (active1 &= old1) | (active2 &= old2)) == 0L)
+ return jjStartNfa_0(0, old0, old1, old2);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(1, active0, active1, active2);
+ return 2;
+ }
+ switch(curChar)
+ {
+ case 42:
+ if ((active1 & 0x8L) != 0L)
+ return jjStopAtPos(2, 67);
+ break;
+ case 46:
+ if ((active0 & 0x40000000L) != 0L)
+ return jjStopAtPos(2, 30);
+ break;
+ case 61:
+ if ((active0 & 0x2000000000L) != 0L)
+ return jjStopAtPos(2, 37);
+ else if ((active0 & 0x4000000000L) != 0L)
+ return jjStopAtPos(2, 38);
+ break;
+ case 97:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x5000000100L, active2, 0L);
+ case 98:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x20000000L, active2, 0L);
+ case 100:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x40000000L, active2, 0L);
+ case 101:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x4000000000020L, active2, 0L);
+ case 102:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x800L, active2, 0L);
+ case 103:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x480000000L, active2, 0L);
+ case 105:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x2928008100000L, active2, 0L);
+ case 108:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x11000000801000L, active2, 0L);
+ case 109:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x10000000000L, active2, 0L);
+ case 110:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x2000600L, active2, 0x40L);
+ case 111:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x210040000L, active2, 0L);
+ case 112:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x80000000000L, active2, 0L);
+ case 114:
+ if ((active1 & 0x80000L) != 0L)
+ return jjStartNfaWithStates_0(2, 83, 29);
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x20402000000000L, active2, 0L);
+ case 115:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x200000008040L, active2, 0L);
+ case 116:
+ if ((active1 & 0x1000000L) != 0L)
+ return jjStartNfaWithStates_0(2, 88, 29);
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x100220090L, active2, 0L);
+ case 117:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x8000000014000L, active2, 0L);
+ case 119:
+ if ((active1 & 0x4000000L) != 0L)
+ return jjStartNfaWithStates_0(2, 90, 29);
+ break;
+ case 121:
+ if ((active1 & 0x40000000000L) != 0L)
+ return jjStartNfaWithStates_0(2, 106, 29);
+ break;
+ case 122:
+ return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x800000000L, active2, 0L);
+ default :
+ break;
+ }
+ return jjStartNfa_0(1, active0, active1, active2);
+}
+static private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1, long old2, long active2)
+{
+ if (((active0 &= old0) | (active1 &= old1) | (active2 &= old2)) == 0L)
+ return jjStartNfa_0(1, old0, old1, old2);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(2, 0L, active1, active2);
+ return 3;
+ }
+ switch(curChar)
+ {
+ case 97:
+ return jjMoveStringLiteralDfa4_0(active1, 0x1000000040820L, active2, 0x40L);
+ case 98:
+ return jjMoveStringLiteralDfa4_0(active1, 0x4000L, active2, 0L);
+ case 99:
+ return jjMoveStringLiteralDfa4_0(active1, 0x80L, active2, 0L);
+ case 100:
+ if ((active1 & 0x800000000000L) != 0L)
+ return jjStartNfaWithStates_0(3, 111, 29);
+ break;
+ case 101:
+ if ((active1 & 0x40L) != 0L)
+ return jjStartNfaWithStates_0(3, 70, 29);
+ else if ((active1 & 0x8000L) != 0L)
+ return jjStartNfaWithStates_0(3, 79, 29);
+ else if ((active1 & 0x8000000000000L) != 0L)
+ return jjStartNfaWithStates_0(3, 115, 29);
+ return jjMoveStringLiteralDfa4_0(active1, 0x80840121000L, active2, 0L);
+ case 103:
+ if ((active1 & 0x2000000L) != 0L)
+ return jjStartNfaWithStates_0(3, 89, 29);
+ break;
+ case 105:
+ return jjMoveStringLiteralDfa4_0(active1, 0x200080800000L, active2, 0L);
+ case 108:
+ return jjMoveStringLiteralDfa4_0(active1, 0x2000020000000L, active2, 0L);
+ case 109:
+ if ((active1 & 0x10000L) != 0L)
+ return jjStartNfaWithStates_0(3, 80, 29);
+ break;
+ case 110:
+ return jjMoveStringLiteralDfa4_0(active1, 0x400000000L, active2, 0L);
+ case 111:
+ if ((active1 & 0x10L) != 0L)
+ return jjStartNfaWithStates_0(3, 68, 29);
+ else if ((active1 & 0x200000L) != 0L)
+ return jjStartNfaWithStates_0(3, 85, 29);
+ return jjMoveStringLiteralDfa4_0(active1, 0x20100000000000L, active2, 0L);
+ case 112:
+ return jjMoveStringLiteralDfa4_0(active1, 0x10000000000L, active2, 0L);
+ case 114:
+ if ((active1 & 0x100L) != 0L)
+ return jjStartNfaWithStates_0(3, 72, 29);
+ return jjMoveStringLiteralDfa4_0(active1, 0x4000200000000L, active2, 0L);
+ case 115:
+ if ((active1 & 0x20000000000L) != 0L)
+ return jjStartNfaWithStates_0(3, 105, 29);
+ return jjMoveStringLiteralDfa4_0(active1, 0x10004000000200L, active2, 0L);
+ case 116:
+ return jjMoveStringLiteralDfa4_0(active1, 0x409010000400L, active2, 0L);
+ case 117:
+ return jjMoveStringLiteralDfa4_0(active1, 0x2100000000L, active2, 0L);
+ case 118:
+ return jjMoveStringLiteralDfa4_0(active1, 0x8000000L, active2, 0L);
+ default :
+ break;
+ }
+ return jjStartNfa_0(2, 0L, active1, active2);
+}
+static private int jjMoveStringLiteralDfa4_0(long old1, long active1, long old2, long active2)
+{
+ if (((active1 &= old1) | (active2 &= old2)) == 0L)
+ return jjStartNfa_0(2, 0L, old1, old2);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(3, 0L, active1, active2);
+ return 4;
+ }
+ switch(curChar)
+ {
+ case 97:
+ return jjMoveStringLiteralDfa5_0(active1, 0x4000008000000L, active2, 0L);
+ case 99:
+ return jjMoveStringLiteralDfa5_0(active1, 0xa040000000L, active2, 0L);
+ case 100:
+ return jjMoveStringLiteralDfa5_0(active1, 0x80000000000L, active2, 0L);
+ case 101:
+ if ((active1 & 0x2000000000000L) != 0L)
+ return jjStartNfaWithStates_0(4, 113, 29);
+ else if ((active1 & 0x10000000000000L) != 0L)
+ return jjStartNfaWithStates_0(4, 116, 29);
+ return jjMoveStringLiteralDfa5_0(active1, 0x410000000L, active2, 0L);
+ case 103:
+ return jjMoveStringLiteralDfa5_0(active1, 0x200000000000L, active2, 0L);
+ case 104:
+ if ((active1 & 0x80L) != 0L)
+ return jjStartNfaWithStates_0(4, 71, 29);
+ break;
+ case 105:
+ return jjMoveStringLiteralDfa5_0(active1, 0x1020000400L, active2, 0L);
+ case 107:
+ if ((active1 & 0x20L) != 0L)
+ return jjStartNfaWithStates_0(4, 69, 29);
+ break;
+ case 108:
+ return jjMoveStringLiteralDfa5_0(active1, 0x10000004000L, active2, 0x40L);
+ case 110:
+ if ((active1 & 0x100000000000L) != 0L)
+ return jjStartNfaWithStates_0(4, 108, 29);
+ return jjMoveStringLiteralDfa5_0(active1, 0x900000L, active2, 0L);
+ case 111:
+ return jjMoveStringLiteralDfa5_0(active1, 0x800000000L, active2, 0L);
+ case 114:
+ return jjMoveStringLiteralDfa5_0(active1, 0x100020000L, active2, 0L);
+ case 115:
+ if ((active1 & 0x4000000000L) != 0L)
+ return jjStartNfaWithStates_0(4, 102, 29);
+ return jjMoveStringLiteralDfa5_0(active1, 0x80000000L, active2, 0L);
+ case 116:
+ if ((active1 & 0x200L) != 0L)
+ return jjStartNfaWithStates_0(4, 73, 29);
+ else if ((active1 & 0x40000L) != 0L)
+ return jjStartNfaWithStates_0(4, 82, 29);
+ else if ((active1 & 0x200000000L) != 0L)
+ return jjStartNfaWithStates_0(4, 97, 29);
+ return jjMoveStringLiteralDfa5_0(active1, 0x1000000001000L, active2, 0L);
+ case 117:
+ return jjMoveStringLiteralDfa5_0(active1, 0x400000000800L, active2, 0L);
+ case 119:
+ if ((active1 & 0x20000000000000L) != 0L)
+ return jjStartNfaWithStates_0(4, 117, 29);
+ break;
+ default :
+ break;
+ }
+ return jjStartNfa_0(3, 0L, active1, active2);
+}
+static private int jjMoveStringLiteralDfa5_0(long old1, long active1, long old2, long active2)
+{
+ if (((active1 &= old1) | (active2 &= old2)) == 0L)
+ return jjStartNfa_0(3, 0L, old1, old2);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(4, 0L, active1, active2);
+ return 5;
+ }
+ switch(curChar)
+ {
+ case 97:
+ return jjMoveStringLiteralDfa6_0(active1, 0x410000000000L, active2, 0L);
+ case 99:
+ if ((active1 & 0x20000000L) != 0L)
+ return jjStartNfaWithStates_0(5, 93, 29);
+ else if ((active1 & 0x1000000000L) != 0L)
+ return jjStartNfaWithStates_0(5, 100, 29);
+ return jjMoveStringLiteralDfa6_0(active1, 0x10000000L, active2, 0L);
+ case 100:
+ if ((active1 & 0x100000L) != 0L)
+ return jjStartNfaWithStates_0(5, 84, 29);
+ else if ((active1 & 0x400000000L) != 0L)
+ return jjStartNfaWithStates_0(5, 98, 29);
+ break;
+ case 101:
+ if ((active1 & 0x1000L) != 0L)
+ return jjStartNfaWithStates_0(5, 76, 29);
+ else if ((active1 & 0x4000L) != 0L)
+ return jjStartNfaWithStates_0(5, 78, 29);
+ else if ((active1 & 0x800000L) != 0L)
+ return jjStartNfaWithStates_0(5, 87, 29);
+ return jjMoveStringLiteralDfa6_0(active1, 0x80000000000L, active2, 0L);
+ case 102:
+ if ((active1 & 0x800000000L) != 0L)
+ return jjStartNfaWithStates_0(5, 99, 29);
+ break;
+ case 104:
+ if ((active1 & 0x8000000000L) != 0L)
+ return jjStartNfaWithStates_0(5, 103, 29);
+ break;
+ case 105:
+ return jjMoveStringLiteralDfa6_0(active1, 0x1000000000000L, active2, 0L);
+ case 108:
+ return jjMoveStringLiteralDfa6_0(active1, 0x40000800L, active2, 0x40L);
+ case 110:
+ if ((active1 & 0x20000L) != 0L)
+ return jjStartNfaWithStates_0(5, 81, 29);
+ else if ((active1 & 0x100000000L) != 0L)
+ return jjStartNfaWithStates_0(5, 96, 29);
+ return jjMoveStringLiteralDfa6_0(active1, 0x200000000400L, active2, 0L);
+ case 116:
+ if ((active1 & 0x2000000000L) != 0L)
+ return jjStartNfaWithStates_0(5, 101, 29);
+ return jjMoveStringLiteralDfa6_0(active1, 0x4000088000000L, active2, 0L);
+ default :
+ break;
+ }
+ return jjStartNfa_0(4, 0L, active1, active2);
+}
+static private int jjMoveStringLiteralDfa6_0(long old1, long active1, long old2, long active2)
+{
+ if (((active1 &= old1) | (active2 &= old2)) == 0L)
+ return jjStartNfa_0(4, 0L, old1, old2);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(5, 0L, active1, active2);
+ return 6;
+ }
+ switch(curChar)
+ {
+ case 97:
+ return jjMoveStringLiteralDfa7_0(active1, 0x40000000L, active2, 0L);
+ case 101:
+ if ((active1 & 0x8000000L) != 0L)
+ return jjStartNfaWithStates_0(6, 91, 29);
+ return jjMoveStringLiteralDfa7_0(active1, 0x200080000000L, active2, 0L);
+ case 102:
+ if ((active1 & 0x80000000000L) != 0L)
+ return jjStartNfaWithStates_0(6, 107, 29);
+ break;
+ case 108:
+ if ((active1 & 0x400000000000L) != 0L)
+ return jjStartNfaWithStates_0(6, 110, 29);
+ return jjMoveStringLiteralDfa7_0(active1, 0x1000000000000L, active2, 0L);
+ case 111:
+ return jjMoveStringLiteralDfa7_0(active1, 0x4000000000000L, active2, 0L);
+ case 116:
+ if ((active1 & 0x800L) != 0L)
+ return jjStartNfaWithStates_0(6, 75, 29);
+ return jjMoveStringLiteralDfa7_0(active1, 0x10010000000L, active2, 0L);
+ case 117:
+ return jjMoveStringLiteralDfa7_0(active1, 0x400L, active2, 0L);
+ case 121:
+ if ((active2 & 0x40L) != 0L)
+ return jjStartNfaWithStates_0(6, 134, 29);
+ break;
+ default :
+ break;
+ }
+ return jjStartNfa_0(5, 0L, active1, active2);
+}
+static private int jjMoveStringLiteralDfa7_0(long old1, long active1, long old2, long active2)
+{
+ if (((active1 &= old1) | (active2 &= old2)) == 0L)
+ return jjStartNfa_0(5, 0L, old1, old2);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(6, 0L, active1, 0L);
+ return 7;
+ }
+ switch(curChar)
+ {
+ case 100:
+ if ((active1 & 0x200000000000L) != 0L)
+ return jjStartNfaWithStates_0(7, 109, 29);
+ break;
+ case 101:
+ if ((active1 & 0x400L) != 0L)
+ return jjStartNfaWithStates_0(7, 74, 29);
+ else if ((active1 & 0x10000000000L) != 0L)
+ return jjStartNfaWithStates_0(7, 104, 29);
+ else if ((active1 & 0x1000000000000L) != 0L)
+ return jjStartNfaWithStates_0(7, 112, 29);
+ return jjMoveStringLiteralDfa8_0(active1, 0x10000000L);
+ case 114:
+ if ((active1 & 0x80000000L) != 0L)
+ return jjStartNfaWithStates_0(7, 95, 29);
+ else if ((active1 & 0x4000000000000L) != 0L)
+ return jjStartNfaWithStates_0(7, 114, 29);
+ return jjMoveStringLiteralDfa8_0(active1, 0x40000000L);
+ default :
+ break;
+ }
+ return jjStartNfa_0(6, 0L, active1, 0L);
+}
+static private int jjMoveStringLiteralDfa8_0(long old1, long active1)
+{
+ if (((active1 &= old1)) == 0L)
+ return jjStartNfa_0(6, 0L, old1, 0L);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(7, 0L, active1, 0L);
+ return 8;
+ }
+ switch(curChar)
+ {
+ case 100:
+ if ((active1 & 0x10000000L) != 0L)
+ return jjStartNfaWithStates_0(8, 92, 29);
+ break;
+ case 101:
+ return jjMoveStringLiteralDfa9_0(active1, 0x40000000L);
+ default :
+ break;
+ }
+ return jjStartNfa_0(7, 0L, active1, 0L);
+}
+static private int jjMoveStringLiteralDfa9_0(long old1, long active1)
+{
+ if (((active1 &= old1)) == 0L)
+ return jjStartNfa_0(7, 0L, old1, 0L);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_0(8, 0L, active1, 0L);
+ return 9;
+ }
+ switch(curChar)
+ {
+ case 100:
+ if ((active1 & 0x40000000L) != 0L)
+ return jjStartNfaWithStates_0(9, 94, 29);
+ break;
+ default :
+ break;
+ }
+ return jjStartNfa_0(8, 0L, active1, 0L);
+}
+static private int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return pos + 1; }
+ return jjMoveNfa_0(state, pos + 1);
+}
+static final long[] jjbitVec0 = {
+ 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static private int jjMoveNfa_0(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 78;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 28:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddStates(0, 5);
+ else if (curChar == 36)
+ {
+ if (kind > 135)
+ kind = 135;
+ jjCheckNAdd(29);
+ }
+ else if (curChar == 34)
+ jjCheckNAddStates(6, 8);
+ else if (curChar == 39)
+ jjCheckNAddTwoStates(7, 9);
+ else if (curChar == 46)
+ jjCheckNAdd(1);
+ if ((0x3fe000000000000L & l) != 0L)
+ {
+ if (kind > 122)
+ kind = 122;
+ jjCheckNAddStates(9, 16);
+ }
+ else if (curChar == 48)
+ jjAddStates(17, 20);
+ if (curChar == 48)
+ {
+ if (kind > 118)
+ kind = 118;
+ jjCheckNAddStates(21, 28);
+ }
+ break;
+ case 0:
+ if (curChar == 46)
+ jjCheckNAdd(1);
+ break;
+ case 1:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 130)
+ kind = 130;
+ jjCheckNAddStates(29, 31);
+ break;
+ case 3:
+ if ((0x280000000000L & l) != 0L)
+ jjCheckNAdd(4);
+ break;
+ case 4:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 130)
+ kind = 130;
+ jjCheckNAddTwoStates(4, 5);
+ break;
+ case 6:
+ if (curChar == 39)
+ jjCheckNAddTwoStates(7, 9);
+ break;
+ case 7:
+ if ((0xffffff7fffffdbffL & l) != 0L)
+ jjCheckNAddTwoStates(7, 8);
+ break;
+ case 8:
+ if (curChar == 39 && kind > 132)
+ kind = 132;
+ break;
+ case 10:
+ if ((0x8000008400000000L & l) != 0L)
+ jjCheckNAdd(8);
+ break;
+ case 11:
+ if (curChar == 48)
+ jjCheckNAddTwoStates(12, 8);
+ break;
+ case 12:
+ if ((0xff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(12, 8);
+ break;
+ case 13:
+ if ((0x3fe000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(14, 8);
+ break;
+ case 14:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(14, 8);
+ break;
+ case 16:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(16, 8);
+ break;
+ case 17:
+ if (curChar == 34)
+ jjCheckNAddStates(6, 8);
+ break;
+ case 18:
+ if ((0xfffffffbffffdbffL & l) != 0L)
+ jjCheckNAddStates(6, 8);
+ break;
+ case 20:
+ if ((0x8000008400000400L & l) != 0L)
+ jjCheckNAddStates(6, 8);
+ break;
+ case 21:
+ if (curChar == 34 && kind > 133)
+ kind = 133;
+ break;
+ case 22:
+ if (curChar == 48)
+ jjCheckNAddStates(32, 35);
+ break;
+ case 23:
+ if ((0xff000000000000L & l) != 0L)
+ jjCheckNAddStates(32, 35);
+ break;
+ case 24:
+ if ((0x3fe000000000000L & l) != 0L)
+ jjCheckNAddStates(36, 39);
+ break;
+ case 25:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddStates(36, 39);
+ break;
+ case 27:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddStates(40, 43);
+ break;
+ case 29:
+ if ((0x3ff001000000000L & l) == 0L)
+ break;
+ if (kind > 135)
+ kind = 135;
+ jjCheckNAdd(29);
+ break;
+ case 30:
+ if (curChar != 48)
+ break;
+ if (kind > 118)
+ kind = 118;
+ jjCheckNAddStates(21, 28);
+ break;
+ case 31:
+ if ((0xff000000000000L & l) == 0L)
+ break;
+ if (kind > 118)
+ kind = 118;
+ jjCheckNAdd(31);
+ break;
+ case 32:
+ if ((0xff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(32, 33);
+ break;
+ case 34:
+ if ((0xff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(34, 35);
+ break;
+ case 36:
+ if ((0xff000000000000L & l) != 0L)
+ jjCheckNAddStates(44, 46);
+ break;
+ case 41:
+ if ((0x3fe000000000000L & l) == 0L)
+ break;
+ if (kind > 122)
+ kind = 122;
+ jjCheckNAddStates(9, 16);
+ break;
+ case 42:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 122)
+ kind = 122;
+ jjCheckNAdd(42);
+ break;
+ case 43:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(43, 44);
+ break;
+ case 45:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(45, 46);
+ break;
+ case 47:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddStates(47, 49);
+ break;
+ case 52:
+ if (curChar == 48)
+ jjAddStates(17, 20);
+ break;
+ case 54:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 126)
+ kind = 126;
+ jjstateSet[jjnewStateCnt++] = 54;
+ break;
+ case 56:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 127)
+ kind = 127;
+ jjAddStates(50, 51);
+ break;
+ case 59:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjAddStates(52, 53);
+ break;
+ case 62:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjAddStates(54, 56);
+ break;
+ case 67:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddStates(0, 5);
+ break;
+ case 68:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(68, 69);
+ break;
+ case 69:
+ if (curChar != 46)
+ break;
+ if (kind > 130)
+ kind = 130;
+ jjCheckNAddStates(57, 59);
+ break;
+ case 70:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 130)
+ kind = 130;
+ jjCheckNAddStates(57, 59);
+ break;
+ case 71:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(71, 0);
+ break;
+ case 72:
+ if ((0x3ff000000000000L & l) != 0L)
+ jjCheckNAddTwoStates(72, 73);
+ break;
+ case 74:
+ if ((0x280000000000L & l) != 0L)
+ jjCheckNAdd(75);
+ break;
+ case 75:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 131)
+ kind = 131;
+ jjCheckNAddTwoStates(75, 76);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 28:
+ if ((0x7fffffe87fffffeL & l) != 0L)
+ {
+ if (kind > 135)
+ kind = 135;
+ jjCheckNAdd(29);
+ }
+ if (curChar == 76)
+ jjAddStates(60, 61);
+ break;
+ case 2:
+ if ((0x2000000020L & l) != 0L)
+ jjAddStates(62, 63);
+ break;
+ case 5:
+ if ((0x104000001040L & l) != 0L && kind > 130)
+ kind = 130;
+ break;
+ case 7:
+ if ((0xffffffffefffffffL & l) != 0L)
+ jjCheckNAddTwoStates(7, 8);
+ break;
+ case 9:
+ if (curChar == 92)
+ jjAddStates(64, 67);
+ break;
+ case 10:
+ if ((0x54404610000000L & l) != 0L)
+ jjCheckNAdd(8);
+ break;
+ case 15:
+ if ((0x100000001000000L & l) != 0L)
+ jjCheckNAdd(16);
+ break;
+ case 16:
+ if ((0x7e0000007eL & l) != 0L)
+ jjCheckNAddTwoStates(16, 8);
+ break;
+ case 18:
+ if ((0xffffffffefffffffL & l) != 0L)
+ jjCheckNAddStates(6, 8);
+ break;
+ case 19:
+ if (curChar == 92)
+ jjAddStates(68, 71);
+ break;
+ case 20:
+ if ((0x54404610000000L & l) != 0L)
+ jjCheckNAddStates(6, 8);
+ break;
+ case 26:
+ if ((0x100000001000000L & l) != 0L)
+ jjCheckNAdd(27);
+ break;
+ case 27:
+ if ((0x7e0000007eL & l) != 0L)
+ jjCheckNAddStates(40, 43);
+ break;
+ case 29:
+ if ((0x7fffffe87fffffeL & l) == 0L)
+ break;
+ if (kind > 135)
+ kind = 135;
+ jjCheckNAdd(29);
+ break;
+ case 33:
+ if ((0x100000001000L & l) != 0L && kind > 119)
+ kind = 119;
+ break;
+ case 35:
+ if ((0x20000000200000L & l) != 0L && kind > 120)
+ kind = 120;
+ break;
+ case 37:
+ if ((0x100000001000L & l) != 0L && kind > 121)
+ kind = 121;
+ break;
+ case 38:
+ if ((0x20000000200000L & l) != 0L)
+ jjstateSet[jjnewStateCnt++] = 37;
+ break;
+ case 39:
+ if ((0x20000000200000L & l) != 0L && kind > 121)
+ kind = 121;
+ break;
+ case 40:
+ if ((0x100000001000L & l) != 0L)
+ jjstateSet[jjnewStateCnt++] = 39;
+ break;
+ case 44:
+ if ((0x20100000201000L & l) != 0L && kind > 123)
+ kind = 123;
+ break;
+ case 46:
+ if ((0x20000000200000L & l) != 0L && kind > 124)
+ kind = 124;
+ break;
+ case 48:
+ if ((0x100000001000L & l) != 0L && kind > 125)
+ kind = 125;
+ break;
+ case 49:
+ if ((0x20000000200000L & l) != 0L)
+ jjstateSet[jjnewStateCnt++] = 48;
+ break;
+ case 50:
+ if ((0x20000000200000L & l) != 0L && kind > 125)
+ kind = 125;
+ break;
+ case 51:
+ if ((0x100000001000L & l) != 0L)
+ jjstateSet[jjnewStateCnt++] = 50;
+ break;
+ case 53:
+ if ((0x100000001000000L & l) != 0L)
+ jjCheckNAdd(54);
+ break;
+ case 54:
+ if ((0x7e0000007eL & l) == 0L)
+ break;
+ if (kind > 126)
+ kind = 126;
+ jjCheckNAdd(54);
+ break;
+ case 55:
+ if ((0x100000001000000L & l) != 0L)
+ jjCheckNAdd(56);
+ break;
+ case 56:
+ if ((0x7e0000007eL & l) == 0L)
+ break;
+ if (kind > 127)
+ kind = 127;
+ jjCheckNAddTwoStates(56, 57);
+ break;
+ case 57:
+ if ((0x20100000201000L & l) != 0L && kind > 127)
+ kind = 127;
+ break;
+ case 58:
+ if ((0x100000001000000L & l) != 0L)
+ jjCheckNAdd(59);
+ break;
+ case 59:
+ if ((0x7e0000007eL & l) != 0L)
+ jjCheckNAddTwoStates(59, 60);
+ break;
+ case 60:
+ if ((0x20000000200000L & l) != 0L && kind > 128)
+ kind = 128;
+ break;
+ case 61:
+ if ((0x100000001000000L & l) != 0L)
+ jjCheckNAdd(62);
+ break;
+ case 62:
+ if ((0x7e0000007eL & l) != 0L)
+ jjCheckNAddStates(54, 56);
+ break;
+ case 63:
+ if ((0x100000001000L & l) != 0L && kind > 129)
+ kind = 129;
+ break;
+ case 64:
+ if ((0x20000000200000L & l) != 0L)
+ jjstateSet[jjnewStateCnt++] = 63;
+ break;
+ case 65:
+ if ((0x20000000200000L & l) != 0L && kind > 129)
+ kind = 129;
+ break;
+ case 66:
+ if ((0x100000001000L & l) != 0L)
+ jjstateSet[jjnewStateCnt++] = 65;
+ break;
+ case 73:
+ if ((0x2000000020L & l) != 0L)
+ jjAddStates(72, 73);
+ break;
+ case 76:
+ if ((0x104000001040L & l) != 0L && kind > 131)
+ kind = 131;
+ break;
+ case 77:
+ if (curChar == 76)
+ jjAddStates(60, 61);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 7:
+ if ((jjbitVec0[i2] & l2) != 0L)
+ jjAddStates(74, 75);
+ break;
+ case 18:
+ if ((jjbitVec0[i2] & l2) != 0L)
+ jjAddStates(6, 8);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 78 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+static private int jjMoveStringLiteralDfa0_1()
+{
+ switch(curChar)
+ {
+ case 10:
+ return jjStopAtPos(0, 9);
+ default :
+ return 1;
+ }
+}
+static private int jjMoveStringLiteralDfa0_4()
+{
+ switch(curChar)
+ {
+ case 10:
+ return jjStopAtPos(0, 14);
+ case 47:
+ return jjMoveStringLiteralDfa1_4(0x8000L);
+ case 92:
+ return jjMoveStringLiteralDfa1_4(0x30000L);
+ default :
+ return 1;
+ }
+}
+static private int jjMoveStringLiteralDfa1_4(long active0)
+{
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ return 1;
+ }
+ switch(curChar)
+ {
+ case 10:
+ if ((active0 & 0x10000L) != 0L)
+ return jjStopAtPos(1, 16);
+ break;
+ case 13:
+ return jjMoveStringLiteralDfa2_4(active0, 0x20000L);
+ case 42:
+ if ((active0 & 0x8000L) != 0L)
+ return jjStopAtPos(1, 15);
+ break;
+ default :
+ return 2;
+ }
+ return 2;
+}
+static private int jjMoveStringLiteralDfa2_4(long old0, long active0)
+{
+ if (((active0 &= old0)) == 0L)
+ return 2;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ return 2;
+ }
+ switch(curChar)
+ {
+ case 10:
+ if ((active0 & 0x20000L) != 0L)
+ return jjStopAtPos(2, 17);
+ break;
+ default :
+ return 3;
+ }
+ return 3;
+}
+static private int jjMoveStringLiteralDfa0_3()
+{
+ switch(curChar)
+ {
+ case 42:
+ return jjMoveStringLiteralDfa1_3(0x2000L);
+ default :
+ return 1;
+ }
+}
+static private int jjMoveStringLiteralDfa1_3(long active0)
+{
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ return 1;
+ }
+ switch(curChar)
+ {
+ case 47:
+ if ((active0 & 0x2000L) != 0L)
+ return jjStopAtPos(1, 13);
+ break;
+ default :
+ return 2;
+ }
+ return 2;
+}
+static private int jjMoveStringLiteralDfa0_2()
+{
+ switch(curChar)
+ {
+ case 42:
+ return jjMoveStringLiteralDfa1_2(0x800L);
+ default :
+ return 1;
+ }
+}
+static private int jjMoveStringLiteralDfa1_2(long active0)
+{
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ return 1;
+ }
+ switch(curChar)
+ {
+ case 47:
+ if ((active0 & 0x800L) != 0L)
+ return jjStopAtPos(1, 11);
+ break;
+ default :
+ return 2;
+ }
+ return 2;
+}
+static final int[] jjnextStates = {
+ 68, 69, 71, 0, 72, 73, 18, 19, 21, 42, 43, 44, 45, 46, 47, 49,
+ 51, 53, 55, 58, 61, 31, 32, 33, 34, 35, 36, 38, 40, 1, 2, 5,
+ 18, 19, 23, 21, 18, 19, 25, 21, 18, 19, 27, 21, 36, 38, 40, 47,
+ 49, 51, 56, 57, 59, 60, 62, 64, 66, 70, 2, 5, 6, 17, 3, 4,
+ 10, 11, 13, 15, 20, 22, 24, 26, 74, 75, 7, 8,
+};
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, null, null, null, null, null,
+null, null, null, null, null, null, "\173", "\175", "\133", "\135", "\50", "\51",
+"\72\72", "\72", "\73", "\54", "\77", "\56\56\56", "\75", "\52\75", "\57\75", "\45\75",
+"\53\75", "\55\75", "\74\74\75", "\76\76\75", "\46\75", "\136\75", "\174\75",
+"\174\174", "\46\46", "\174", "\136", "\46", "\75\75", "\41\75", "\74", "\76", "\74\75",
+"\76\75", "\74\74", "\76\76", "\53", "\55", "\52", "\57", "\45", "\53\53", "\55\55",
+"\176", "\41", "\56", "\55\76", "\56\52", "\55\76\52", "\141\165\164\157",
+"\142\162\145\141\153", "\143\141\163\145", "\143\141\164\143\150", "\143\150\141\162",
+"\143\157\156\163\164", "\143\157\156\164\151\156\165\145", "\144\145\146\141\165\154\164",
+"\144\145\154\145\164\145", "\144\157", "\144\157\165\142\154\145", "\145\154\163\145",
+"\145\156\165\155", "\145\170\164\145\162\156", "\146\154\157\141\164", "\146\157\162",
+"\146\162\151\145\156\144", "\147\157\164\157", "\151\146", "\151\156\154\151\156\145", "\151\156\164",
+"\154\157\156\147", "\156\145\167", "\160\162\151\166\141\164\145",
+"\160\162\157\164\145\143\164\145\144", "\160\165\142\154\151\143", "\162\145\144\145\143\154\141\162\145\144",
+"\162\145\147\151\163\164\145\162", "\162\145\164\165\162\156", "\163\150\157\162\164",
+"\163\151\147\156\145\144", "\163\151\172\145\157\146", "\163\164\141\164\151\143",
+"\163\164\162\165\143\164", "\143\154\141\163\163", "\163\167\151\164\143\150",
+"\164\145\155\160\154\141\164\145", "\164\150\151\163", "\164\162\171", "\164\171\160\145\144\145\146",
+"\165\156\151\157\156", "\165\156\163\151\147\156\145\144", "\166\151\162\164\165\141\154",
+"\166\157\151\144", "\166\157\154\141\164\151\154\145", "\167\150\151\154\145",
+"\157\160\145\162\141\164\157\162", "\164\162\165\145", "\146\141\154\163\145", "\164\150\162\157\167", null, null,
+null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+"\146\151\156\141\154\154\171", null, };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+ "DEFAULT",
+ "IN_LINE_COMMENT",
+ "IN_COMMENT",
+ "IN_PREPROCESSOR_OUTPUT_COMMENT",
+ "PREPROCESSOR_OUTPUT",
+};
+
+/** Lex State array. */
+public static final int[] jjnewLexState = {
+ -1, -1, -1, -1, -1, -1, 1, 2, 4, 0, -1, 0, -1, 4, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+static final long[] jjtoToken = {
+ 0xfffffffffff80001L, 0xffffffffffffffffL, 0xffL,
+};
+static final long[] jjtoSkip = {
+ 0xebfeL, 0x0L, 0x0L,
+};
+static final long[] jjtoMore = {
+ 0x71400L, 0x0L, 0x0L,
+};
+static protected SimpleCharStream input_stream;
+static private final int[] jjrounds = new int[78];
+static private final int[] jjstateSet = new int[156];
+static protected char curChar;
+/** Constructor. */
+public CPPParserTokenManager(SimpleCharStream stream){
+ if (input_stream != null)
+ throw new TokenMgrError("ERROR: Second call to constructor of static lexer. You must use ReInit() to initialize the static variables.", TokenMgrError.STATIC_LEXER_ERROR);
+ input_stream = stream;
+}
+
+/** Constructor. */
+public CPPParserTokenManager(SimpleCharStream stream, int lexState){
+ this(stream);
+ SwitchTo(lexState);
+}
+
+/** Reinitialise parser. */
+static public void ReInit(SimpleCharStream stream)
+{
+ jjmatchedPos = jjnewStateCnt = 0;
+ curLexState = defaultLexState;
+ input_stream = stream;
+ ReInitRounds();
+}
+static private void ReInitRounds()
+{
+ int i;
+ jjround = 0x80000001;
+ for (i = 78; i-- > 0;)
+ jjrounds[i] = 0x80000000;
+}
+
+/** Reinitialise parser. */
+static public void ReInit(SimpleCharStream stream, int lexState)
+{
+ ReInit(stream);
+ SwitchTo(lexState);
+}
+
+/** Switch to specified lex state. */
+static public void SwitchTo(int lexState)
+{
+ if (lexState >= 5 || lexState < 0)
+ throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+ else
+ curLexState = lexState;
+}
+
+static protected Token jjFillToken()
+{
+ final Token t;
+ final String curTokenImage;
+ final int beginLine;
+ final int endLine;
+ final int beginColumn;
+ final int endColumn;
+ String im = jjstrLiteralImages[jjmatchedKind];
+ curTokenImage = (im == null) ? input_stream.GetImage() : im;
+ beginLine = input_stream.getBeginLine();
+ beginColumn = input_stream.getBeginColumn();
+ endLine = input_stream.getEndLine();
+ endColumn = input_stream.getEndColumn();
+ t = Token.newToken(jjmatchedKind, curTokenImage);
+
+ t.beginLine = beginLine;
+ t.endLine = endLine;
+ t.beginColumn = beginColumn;
+ t.endColumn = endColumn;
+
+ return t;
+}
+
+static int curLexState = 0;
+static int defaultLexState = 0;
+static int jjnewStateCnt;
+static int jjround;
+static int jjmatchedPos;
+static int jjmatchedKind;
+
+/** Get the next Token. */
+public static Token getNextToken()
+{
+ Token matchedToken;
+ int curPos = 0;
+
+ EOFLoop :
+ for (;;)
+ {
+ try
+ {
+ curChar = input_stream.BeginToken();
+ }
+ catch(java.io.IOException e)
+ {
+ jjmatchedKind = 0;
+ matchedToken = jjFillToken();
+ return matchedToken;
+ }
+
+ for (;;)
+ {
+ switch(curLexState)
+ {
+ case 0:
+ try { input_stream.backup(0);
+ while (curChar <= 32 && (0x100001600L & (1L << curChar)) != 0L)
+ curChar = input_stream.BeginToken();
+ }
+ catch (java.io.IOException e1) { continue EOFLoop; }
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_0();
+ break;
+ case 1:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_1();
+ if (jjmatchedPos == 0 && jjmatchedKind > 10)
+ {
+ jjmatchedKind = 10;
+ }
+ break;
+ case 2:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_2();
+ if (jjmatchedPos == 0 && jjmatchedKind > 12)
+ {
+ jjmatchedKind = 12;
+ }
+ break;
+ case 3:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_3();
+ if (jjmatchedPos == 0 && jjmatchedKind > 12)
+ {
+ jjmatchedKind = 12;
+ }
+ break;
+ case 4:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_4();
+ if (jjmatchedPos == 0 && jjmatchedKind > 18)
+ {
+ jjmatchedKind = 18;
+ }
+ break;
+ }
+ if (jjmatchedKind != 0x7fffffff)
+ {
+ if (jjmatchedPos + 1 < curPos)
+ input_stream.backup(curPos - jjmatchedPos - 1);
+ if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+ {
+ matchedToken = jjFillToken();
+ if (jjnewLexState[jjmatchedKind] != -1)
+ curLexState = jjnewLexState[jjmatchedKind];
+ return matchedToken;
+ }
+ else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+ {
+ if (jjnewLexState[jjmatchedKind] != -1)
+ curLexState = jjnewLexState[jjmatchedKind];
+ continue EOFLoop;
+ }
+ if (jjnewLexState[jjmatchedKind] != -1)
+ curLexState = jjnewLexState[jjmatchedKind];
+ curPos = 0;
+ jjmatchedKind = 0x7fffffff;
+ try {
+ curChar = input_stream.readChar();
+ continue;
+ }
+ catch (java.io.IOException e1) { }
+ }
+ int error_line = input_stream.getEndLine();
+ int error_column = input_stream.getEndColumn();
+ String error_after = null;
+ boolean EOFSeen = false;
+ try { input_stream.readChar(); input_stream.backup(1); }
+ catch (java.io.IOException e1) {
+ EOFSeen = true;
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ if (curChar == '\n' || curChar == '\r') {
+ error_line++;
+ error_column = 0;
+ }
+ else
+ error_column++;
+ }
+ if (!EOFSeen) {
+ input_stream.backup(1);
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ }
+ throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+ }
+ }
+}
+
+static private void jjCheckNAdd(int state)
+{
+ if (jjrounds[state] != jjround)
+ {
+ jjstateSet[jjnewStateCnt++] = state;
+ jjrounds[state] = jjround;
+ }
+}
+static private void jjAddStates(int start, int end)
+{
+ do {
+ jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+ } while (start++ != end);
+}
+static private void jjCheckNAddTwoStates(int state1, int state2)
+{
+ jjCheckNAdd(state1);
+ jjCheckNAdd(state2);
+}
+
+static private void jjCheckNAddStates(int start, int end)
+{
+ do {
+ jjCheckNAdd(jjnextStates[start]);
+ } while (start++ != end);
+}
+
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/ParseException.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/ParseException.java
new file mode 100644
index 00000000000..cc7d6e24f28
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/ParseException.java
@@ -0,0 +1,198 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 4.1 */
+/* JavaCCOptions:KEEP_LINE_COL=null */
+package net.sourceforge.pmd.cpd.cppast;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends RuntimeException {
+
+ /**
+ * This constructor is used by the method "generateParseException"
+ * in the generated parser. Calling this constructor generates
+ * a new object of this type with the fields "currentToken",
+ * "expectedTokenSequences", and "tokenImage" set. The boolean
+ * flag "specialConstructor" is also set to true to indicate that
+ * this constructor was used to create this object.
+ * This constructor calls its super class with the empty string
+ * to force the "toString" method of parent class "Throwable" to
+ * print the error message in the form:
+ * ParseException: <result of getMessage>
+ */
+ public ParseException(Token currentTokenVal,
+ int[][] expectedTokenSequencesVal,
+ String[] tokenImageVal
+ )
+ {
+ super("");
+ specialConstructor = true;
+ currentToken = currentTokenVal;
+ expectedTokenSequences = expectedTokenSequencesVal;
+ tokenImage = tokenImageVal;
+ }
+
+ /**
+ * The following constructors are for use by you for whatever
+ * purpose you can think of. Constructing the exception in this
+ * manner makes the exception behave in the normal way - i.e., as
+ * documented in the class "Throwable". The fields "errorToken",
+ * "expectedTokenSequences", and "tokenImage" do not contain
+ * relevant information. The JavaCC generated code does not use
+ * these constructors.
+ */
+
+ public ParseException() {
+ super();
+ specialConstructor = false;
+ }
+
+ /** Constructor with message. */
+ public ParseException(String message) {
+ super(message);
+ specialConstructor = false;
+ }
+
+ /**
+ * This variable determines which constructor was used to create
+ * this object and thereby affects the semantics of the
+ * "getMessage" method (see below).
+ */
+ protected boolean specialConstructor;
+
+ /**
+ * This is the last token that has been consumed successfully. If
+ * this object has been created due to a parse error, the token
+ * followng this token will (therefore) be the first error token.
+ */
+ public Token currentToken;
+
+ /**
+ * Each entry in this array is an array of integers. Each array
+ * of integers represents a sequence of tokens (by their ordinal
+ * values) that is expected at this point of the parse.
+ */
+ public int[][] expectedTokenSequences;
+
+ /**
+ * This is a reference to the "tokenImage" array of the generated
+ * parser within which the parse error occurred. This array is
+ * defined in the generated ...Constants interface.
+ */
+ public String[] tokenImage;
+
+ /**
+ * This method has the standard behavior when this object has been
+ * created using the standard constructors. Otherwise, it uses
+ * "currentToken" and "expectedTokenSequences" to generate a parse
+ * error message and returns it. If this object has been created
+ * due to a parse error, and you do not catch it (it gets thrown
+ * from the parser), then this method is called during the printing
+ * of the final stack trace, and hence the correct error message
+ * gets displayed.
+ */
+ public String getMessage() {
+ if (!specialConstructor) {
+ return super.getMessage();
+ }
+ StringBuffer expected = new StringBuffer();
+ int maxSize = 0;
+ for (int i = 0; i < expectedTokenSequences.length; i++) {
+ if (maxSize < expectedTokenSequences[i].length) {
+ maxSize = expectedTokenSequences[i].length;
+ }
+ for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+ expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+ }
+ if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+ expected.append("...");
+ }
+ expected.append(eol).append(" ");
+ }
+ String retval = "Encountered \"";
+ Token tok = currentToken.next;
+ for (int i = 0; i < maxSize; i++) {
+ if (i != 0) retval += " ";
+ if (tok.kind == 0) {
+ retval += tokenImage[0];
+ break;
+ }
+ retval += " " + tokenImage[tok.kind];
+ retval += " \"";
+ retval += add_escapes(tok.image);
+ retval += " \"";
+ tok = tok.next;
+ }
+ retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+ retval += "." + eol;
+ if (expectedTokenSequences.length == 1) {
+ retval += "Was expecting:" + eol + " ";
+ } else {
+ retval += "Was expecting one of:" + eol + " ";
+ }
+ retval += expected.toString();
+ return retval;
+ }
+
+ /**
+ * The end of line string for this machine.
+ */
+ protected String eol = System.getProperty("line.separator", "\n");
+
+ /**
+ * Used to convert raw characters to their escaped version
+ * when these raw version cannot be used as part of an ASCII
+ * string literal.
+ */
+ protected String add_escapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+}
+/* JavaCC - OriginalChecksum=8b42f597f21215eb130252440c369111 (do not edit this line) */
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java
new file mode 100644
index 00000000000..92464e2280d
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java
@@ -0,0 +1,476 @@
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.1 */
+/* JavaCCOptions:STATIC=true */
+package net.sourceforge.pmd.cpd.cppast;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream
+{
+/** Whether parser is static. */
+ public static final boolean staticFlag = true;
+ static int bufsize;
+ static int available;
+ static int tokenBegin;
+/** Position in buffer. */
+ static public int bufpos = -1;
+ static protected int bufline[];
+ static protected int bufcolumn[];
+
+ static protected int column = 0;
+ static protected int line = 1;
+
+ static protected boolean prevCharIsCR = false;
+ static protected boolean prevCharIsLF = false;
+
+ static protected java.io.Reader inputStream;
+
+ static protected char[] buffer;
+ static protected int maxNextCharInd = 0;
+ static protected int inBuf = 0;
+ static protected int tabSize = 8;
+
+ static protected void setTabSize(int i) { tabSize = i; }
+ static protected int getTabSize(int i) { return tabSize; }
+
+
+ static protected void ExpandBuff(boolean wrapAround)
+ {
+ char[] newbuffer = new char[bufsize + 2048];
+ int newbufline[] = new int[bufsize + 2048];
+ int newbufcolumn[] = new int[bufsize + 2048];
+
+ try
+ {
+ if (wrapAround)
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ System.arraycopy(buffer, 0, newbuffer,
+ bufsize - tokenBegin, bufpos);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+ bufcolumn = newbufcolumn;
+
+ maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+ }
+ else
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ bufcolumn = newbufcolumn;
+
+ maxNextCharInd = (bufpos -= tokenBegin);
+ }
+ }
+ catch (Throwable t)
+ {
+ throw new Error(t.getMessage());
+ }
+
+
+ bufsize += 2048;
+ available = bufsize;
+ tokenBegin = 0;
+ }
+
+ static protected void FillBuff() throws java.io.IOException
+ {
+ if (maxNextCharInd == available)
+ {
+ if (available == bufsize)
+ {
+ if (tokenBegin > 2048)
+ {
+ bufpos = maxNextCharInd = 0;
+ available = tokenBegin;
+ }
+ else if (tokenBegin < 0)
+ bufpos = maxNextCharInd = 0;
+ else
+ ExpandBuff(false);
+ }
+ else if (available > tokenBegin)
+ available = bufsize;
+ else if ((tokenBegin - available) < 2048)
+ ExpandBuff(true);
+ else
+ available = tokenBegin;
+ }
+
+ int i;
+ try {
+ if ((i = inputStream.read(buffer, maxNextCharInd,
+ available - maxNextCharInd)) == -1)
+ {
+ inputStream.close();
+ throw new java.io.IOException();
+ }
+ else
+ maxNextCharInd += i;
+ return;
+ }
+ catch(java.io.IOException e) {
+ --bufpos;
+ backup(0);
+ if (tokenBegin == -1)
+ tokenBegin = bufpos;
+ throw e;
+ }
+ }
+
+/** Start. */
+ static public char BeginToken() throws java.io.IOException
+ {
+ tokenBegin = -1;
+ char c = readChar();
+ tokenBegin = bufpos;
+
+ return c;
+ }
+
+ static protected void UpdateLineColumn(char c)
+ {
+ column++;
+
+ if (prevCharIsLF)
+ {
+ prevCharIsLF = false;
+ line += (column = 1);
+ }
+ else if (prevCharIsCR)
+ {
+ prevCharIsCR = false;
+ if (c == '\n')
+ {
+ prevCharIsLF = true;
+ }
+ else
+ line += (column = 1);
+ }
+
+ switch (c)
+ {
+ case '\r' :
+ prevCharIsCR = true;
+ break;
+ case '\n' :
+ prevCharIsLF = true;
+ break;
+ case '\t' :
+ column--;
+ column += (tabSize - (column % tabSize));
+ break;
+ default :
+ break;
+ }
+
+ bufline[bufpos] = line;
+ bufcolumn[bufpos] = column;
+ }
+
+/** Read a character. */
+ static public char readChar() throws java.io.IOException
+ {
+ if (inBuf > 0)
+ {
+ --inBuf;
+
+ if (++bufpos == bufsize)
+ bufpos = 0;
+
+ return buffer[bufpos];
+ }
+
+ if (++bufpos >= maxNextCharInd)
+ FillBuff();
+
+ char c = buffer[bufpos];
+
+ UpdateLineColumn(c);
+ return c;
+ }
+
+ /**
+ * @deprecated
+ * @see #getEndColumn
+ */
+
+ static public int getColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ /**
+ * @deprecated
+ * @see #getEndLine
+ */
+
+ static public int getLine() {
+ return bufline[bufpos];
+ }
+
+ /** Get token end column number. */
+ static public int getEndColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ /** Get token end line number. */
+ static public int getEndLine() {
+ return bufline[bufpos];
+ }
+
+ /** Get token beginning column number. */
+ static public int getBeginColumn() {
+ return bufcolumn[tokenBegin];
+ }
+
+ /** Get token beginning line number. */
+ static public int getBeginLine() {
+ return bufline[tokenBegin];
+ }
+
+/** Backup a number of characters. */
+ static public void backup(int amount) {
+
+ inBuf += amount;
+ if ((bufpos -= amount) < 0)
+ bufpos += bufsize;
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.Reader dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ if (inputStream != null)
+ throw new Error("\n ERROR: Second call to the constructor of a static SimpleCharStream.\n" +
+ " You must either use ReInit() or set the JavaCC option STATIC to false\n" +
+ " during the generation of this class.");
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.Reader dstream, int startline,
+ int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.Reader dstream)
+ {
+ this(dstream, 1, 1, 4096);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.Reader dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ if (buffer == null || buffersize != buffer.length)
+ {
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ }
+ prevCharIsLF = prevCharIsCR = false;
+ tokenBegin = inBuf = maxNextCharInd = 0;
+ bufpos = -1;
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.Reader dstream, int startline,
+ int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.Reader dstream)
+ {
+ ReInit(dstream, 1, 1, 4096);
+ }
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+ {
+ this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn) throws java.io.UnsupportedEncodingException
+ {
+ this(dstream, encoding, startline, startcolumn, 4096);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+ {
+ this(dstream, encoding, 1, 1, 4096);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream)
+ {
+ this(dstream, 1, 1, 4096);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(dstream, encoding, 1, 1, 4096);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream)
+ {
+ ReInit(dstream, 1, 1, 4096);
+ }
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(dstream, encoding, startline, startcolumn, 4096);
+ }
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+ /** Get token literal value. */
+ static public String GetImage()
+ {
+ if (bufpos >= tokenBegin)
+ return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+ else
+ return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+ new String(buffer, 0, bufpos + 1);
+ }
+
+ /** Get the suffix. */
+ static public char[] GetSuffix(int len)
+ {
+ char[] ret = new char[len];
+
+ if ((bufpos + 1) >= len)
+ System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+ else
+ {
+ System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+ len - bufpos - 1);
+ System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+ }
+
+ return ret;
+ }
+
+ /** Reset buffer when finished. */
+ static public void Done()
+ {
+ buffer = null;
+ bufline = null;
+ bufcolumn = null;
+ }
+
+ /**
+ * Method to adjust line and column numbers for the start of a token.
+ */
+ static public void adjustBeginLineColumn(int newLine, int newCol)
+ {
+ int start = tokenBegin;
+ int len;
+
+ if (bufpos >= tokenBegin)
+ {
+ len = bufpos - tokenBegin + inBuf + 1;
+ }
+ else
+ {
+ len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+ }
+
+ int i = 0, j = 0, k = 0;
+ int nextColDiff = 0, columnDiff = 0;
+
+ while (i < len &&
+ bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+ {
+ bufline[j] = newLine;
+ nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+ bufcolumn[j] = newCol + columnDiff;
+ columnDiff = nextColDiff;
+ i++;
+ }
+
+ if (i < len)
+ {
+ bufline[j] = newLine++;
+ bufcolumn[j] = newCol + columnDiff;
+
+ while (i++ < len)
+ {
+ if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+ bufline[j] = newLine++;
+ else
+ bufline[j] = newLine;
+ }
+ }
+
+ line = bufline[j];
+ column = bufcolumn[j];
+ }
+
+}
+/* JavaCC - OriginalChecksum=9bbb8cb4295bb8f7d58e31ce57dc2e0f (do not edit this line) */
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/Token.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/Token.java
new file mode 100644
index 00000000000..59cf8faec5e
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/Token.java
@@ -0,0 +1,124 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 4.1 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null */
+package net.sourceforge.pmd.cpd.cppast;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token {
+
+ /**
+ * An integer that describes the kind of this token. This numbering
+ * system is determined by JavaCCParser, and a table of these numbers is
+ * stored in the file ...Constants.java.
+ */
+ public int kind;
+
+ /** The line number of the first character of this Token. */
+ public int beginLine;
+ /** The column number of the first character of this Token. */
+ public int beginColumn;
+ /** The line number of the last character of this Token. */
+ public int endLine;
+ /** The column number of the last character of this Token. */
+ public int endColumn;
+
+ /**
+ * The string image of the token.
+ */
+ public String image;
+
+ /**
+ * A reference to the next regular (non-special) token from the input
+ * stream. If this is the last token from the input stream, or if the
+ * token manager has not read tokens beyond this one, this field is
+ * set to null. This is true only if this token is also a regular
+ * token. Otherwise, see below for a description of the contents of
+ * this field.
+ */
+ public Token next;
+
+ /**
+ * This field is used to access special tokens that occur prior to this
+ * token, but after the immediately preceding regular (non-special) token.
+ * If there are no such special tokens, this field is set to null.
+ * When there are more than one such special token, this field refers
+ * to the last of these special tokens, which in turn refers to the next
+ * previous special token through its specialToken field, and so on
+ * until the first special token (whose specialToken field is null).
+ * The next fields of special tokens refer to other special tokens that
+ * immediately follow it (without an intervening regular token). If there
+ * is no such token, this field is null.
+ */
+ public Token specialToken;
+
+ /**
+ * An optional attribute value of the Token.
+ * Tokens which are not used as syntactic sugar will often contain
+ * meaningful values that will be used later on by the compiler or
+ * interpreter. This attribute value is often different from the image.
+ * Any subclass of Token that actually wants to return a non-null value can
+ * override this method as appropriate.
+ */
+ public Object getValue() {
+ return null;
+ }
+
+ /**
+ * No-argument constructor
+ */
+ public Token() {}
+
+ /**
+ * Constructs a new token for the specified Image.
+ */
+ public Token(int kind)
+ {
+ this(kind, null);
+ }
+
+ /**
+ * Constructs a new token for the specified Image and Kind.
+ */
+ public Token(int kind, String image)
+ {
+ this.kind = kind;
+ this.image = image;
+ }
+
+ /**
+ * Returns the image.
+ */
+ public String toString()
+ {
+ return image;
+ }
+
+ /**
+ * Returns a new Token object, by default. However, if you want, you
+ * can create and return subclass objects based on the value of ofKind.
+ * Simply add the cases to the switch for all those special cases.
+ * For example, if you have a subclass of Token called IDToken that
+ * you want to create if ofKind is ID, simply add something like :
+ *
+ * case MyParserConstants.ID : return new IDToken(ofKind, image);
+ *
+ * to the following switch statement. Then you can cast matchedToken
+ * variable to the appropriate type and use sit in your lexical actions.
+ */
+ public static Token newToken(int ofKind, String image)
+ {
+ switch(ofKind)
+ {
+ default : return new Token(ofKind, image);
+ }
+ }
+
+ public static Token newToken(int ofKind)
+ {
+ return newToken(ofKind, null);
+ }
+
+}
+/* JavaCC - OriginalChecksum=1917659c640ac2c65feaa32a37580421 (do not edit this line) */
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java
new file mode 100644
index 00000000000..8a705c407ec
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java
@@ -0,0 +1,140 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 4.1 */
+/* JavaCCOptions: */
+package net.sourceforge.pmd.cpd.cppast;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+ /*
+ * Ordinals for various reasons why an Error of this type can be thrown.
+ */
+
+ /**
+ * Lexical error occurred.
+ */
+ static final int LEXICAL_ERROR = 0;
+
+ /**
+ * An attempt was made to create a second instance of a static token manager.
+ */
+ static final int STATIC_LEXER_ERROR = 1;
+
+ /**
+ * Tried to change to an invalid lexical state.
+ */
+ static final int INVALID_LEXICAL_STATE = 2;
+
+ /**
+ * Detected (and bailed out of) an infinite loop in the token manager.
+ */
+ static final int LOOP_DETECTED = 3;
+
+ /**
+ * Indicates the reason why the exception is thrown. It will have
+ * one of the above 4 values.
+ */
+ int errorCode;
+
+ /**
+ * Replaces unprintable characters by their escaped (or unicode escaped)
+ * equivalents in the given string
+ */
+ protected static final String addEscapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+ /**
+ * Returns a detailed message for the Error when it is thrown by the
+ * token manager to indicate a lexical error.
+ * Parameters :
+ * EOFSeen : indicates if EOF caused the lexical error
+ * curLexState : lexical state in which this error occurred
+ * errorLine : line number when the error occurred
+ * errorColumn : column number when the error occurred
+ * errorAfter : prefix that was seen before this error occurred
+ * curchar : the offending character
+ * Note: You can customize the lexical error message by modifying this method.
+ */
+ protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+ return("Lexical error in file " + CPPParserTokenManager.getFileName() + " at line " +
+ errorLine + ", column " +
+ errorColumn + ". Encountered: " +
+ (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+ "after : \"" + addEscapes(errorAfter) + "\"");
+ }
+
+ /**
+ * You can also modify the body of this method to customize your error messages.
+ * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+ * of end-users concern, so you can return something like :
+ *
+ * "Internal Error : Please file a bug report .... "
+ *
+ * from this method for such cases in the release version of your parser.
+ */
+ public String getMessage() {
+ return super.getMessage();
+ }
+
+ /*
+ * Constructors of various flavors follow.
+ */
+
+ /** No arg constructor. */
+ public TokenMgrError() {
+ }
+
+ /** Constructor with message and reason. */
+ public TokenMgrError(String message, int reason) {
+ super(message);
+ errorCode = reason;
+ }
+
+ /** Full Constructor. */
+ public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+ this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+ }
+}
+/* JavaCC - OriginalChecksum=7925b33c412b4bfa3a7147ae3e790276 (do not edit this line) */
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/FileFinder.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/FileFinder.java
new file mode 100644
index 00000000000..d07b32112a9
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/FileFinder.java
@@ -0,0 +1,42 @@
+package net.sourceforge.pmd.util;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A utility class for finding files within a directory.
+ */
+public class FileFinder {
+
+ private FilenameFilter filter;
+ private static final String FILE_SEP = System.getProperty("file.separator");
+
+ public List<File> findFilesFrom(String dir, FilenameFilter filter, boolean recurse) {
+ this.filter = filter;
+ List<File> files = new ArrayList<File>();
+ scanDirectory(new File(dir), files, recurse);
+ return files;
+ }
+
+ /**
+ * Implements a tail recursive file scanner
+ */
+ private void scanDirectory(File dir, List<File> list, boolean recurse) {
+ String[] candidates = dir.list(filter);
+ if (candidates == null) {
+ return;
+ }
+ for (int i = 0; i < candidates.length; i++) {
+ File tmp = new File(dir + FILE_SEP + candidates[i]);
+ if (tmp.isDirectory()) {
+ if (recurse) {
+ scanDirectory(tmp, list, true);
+ }
+ } else {
+ list.add(new File(dir + FILE_SEP + candidates[i]));
+ }
+ }
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/StringUtil.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/StringUtil.java
new file mode 100644
index 00000000000..bfb2f65855a
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/StringUtil.java
@@ -0,0 +1,310 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class StringUtil {
+
+ public static final String[] EMPTY_STRINGS = new String[0];
+ private static final boolean supportsUTF8 = System.getProperty("net.sourceforge.pmd.supportUTF8", "no").equals("yes");
+ private static final String[] ENTITIES;
+
+ static {
+ ENTITIES = new String[256 - 126];
+ for (int i = 126; i <= 255; i++) {
+ ENTITIES[i - 126] = "&#" + i + ';';
+ }
+ }
+
+ public static String replaceString(String original, char oldChar, String newString) {
+
+ String fixedNew = newString == null ? "" : newString;
+
+ StringBuffer desc = new StringBuffer();
+ int index = original.indexOf(oldChar);
+ int last = 0;
+ while (index != -1) {
+ desc.append(original.substring(last, index));
+ desc.append(fixedNew);
+ last = index + 1;
+ index = original.indexOf(oldChar, last);
+ }
+ desc.append(original.substring(last));
+ return desc.toString();
+ }
+
+ public static String replaceString(String original, String oldString, String newString) {
+
+ String fixedNew = newString == null ? "" : newString;
+
+ StringBuffer desc = new StringBuffer();
+ int index = original.indexOf(oldString);
+ int last = 0;
+ while (index != -1) {
+ desc.append(original.substring(last, index));
+ desc.append(fixedNew);
+ last = index + oldString.length();
+ index = original.indexOf(oldString, last);
+ }
+ desc.append(original.substring(last));
+ return desc.toString();
+ }
+
+ /**
+ * Appends to a StringBuffer the String src where non-ASCII and
+ * XML special chars are escaped.
+ *
+ * @param buf The destination XML stream
+ * @param src The String to append to the stream
+ */
+ public static void appendXmlEscaped(StringBuffer buf, String src) {
+ appendXmlEscaped(buf, src, supportsUTF8);
+ }
+
+ public static String htmlEncode(String string) {
+ String encoded = StringUtil.replaceString(string, '&', "&amp;");
+ encoded = StringUtil.replaceString(encoded, '<', "&lt;");
+ return StringUtil.replaceString(encoded, '>', "&gt;");
+ }
+
+ // TODO - unify the method above with the one below
+
+ private static void appendXmlEscaped(StringBuffer buf, String src, boolean supportUTF8) {
+ char c;
+ for (int i = 0; i < src.length(); i++) {
+ c = src.charAt(i);
+ if (c > '~') {// 126
+ if (!supportUTF8) {
+ if (c <= 255) {
+ buf.append(ENTITIES[c - 126]);
+ } else {
+ buf.append("&u").append(Integer.toHexString(c)).append(';');
+ }
+ } else {
+ buf.append(c);
+ }
+ } else if (c == '&')
+ buf.append("&amp;");
+ else if (c == '"')
+ buf.append("&quot;");
+ else if (c == '<')
+ buf.append("&lt;");
+ else if (c == '>')
+ buf.append("&gt;");
+ else
+ buf.append(c);
+ }
+ }
+
+ /**
+ * Parses the input source using the delimiter specified. This method is much
+ * faster than using the StringTokenizer or String.split(char) approach and
+ * serves as a replacement for String.split() for JDK1.3 that doesn't have it.
+ *
+ * FIXME - we're on JDK 1.4 now, can we replace this with String.split?
+ *
+ * @param source String
+ * @param delimiter char
+ * @return String[]
+ */
+ public static String[] substringsOf(String source, char delimiter) {
+
+ if (source == null || source.length() == 0) {
+ return EMPTY_STRINGS;
+ }
+
+ int delimiterCount = 0;
+ int length = source.length();
+ char[] chars = source.toCharArray();
+
+ for (int i=0; i<length; i++) {
+ if (chars[i] == delimiter) delimiterCount++;
+ }
+
+ if (delimiterCount == 0) return new String[] { source };
+
+ String results[] = new String[delimiterCount+1];
+
+ int i = 0;
+ int offset = 0;
+
+ while (offset <= length) {
+ int pos = source.indexOf(delimiter, offset);
+ if (pos < 0) pos = length;
+ results[i++] = pos == offset ? "" : source.substring(offset, pos);
+ offset = pos + 1;
+ }
+
+ return results;
+ }
+
+ /**
+ * Much more efficient than StringTokenizer.
+ *
+ * @param str String
+ * @param separator char
+ * @return String[]
+ */
+ public static String[] substringsOf(String str, String separator) {
+
+ if (str == null || str.length() == 0) {
+ return EMPTY_STRINGS;
+ }
+
+ int index = str.indexOf(separator);
+ if (index == -1) {
+ return new String[]{str};
+ }
+
+ List<String> list = new ArrayList<String>();
+ int currPos = 0;
+ int len = separator.length();
+ while (index != -1) {
+ list.add(str.substring(currPos, index));
+ currPos = index + len;
+ index = str.indexOf(separator, currPos);
+ }
+ list.add(str.substring(currPos));
+ return list.toArray(new String[list.size()]);
+ }
+
+
+ /**
+ * Copies the elements returned by the iterator onto the string buffer
+ * each delimited by the separator.
+ *
+ * @param sb StringBuffer
+ * @param iter Iterator
+ * @param separator String
+ */
+ public static void asStringOn(StringBuffer sb, Iterator iter, String separator) {
+
+ if (!iter.hasNext()) return;
+
+ sb.append(iter.next());
+
+ while (iter.hasNext()) {
+ sb.append(separator);
+ sb.append(iter.next());
+ }
+ }
+ /**
+ * Return the length of the shortest string in the array.
+ * If any one of them is null then it returns 0.
+ *
+ * @param strings String[]
+ * @return int
+ */
+ public static int lengthOfShortestIn(String[] strings) {
+
+ int minLength = Integer.MAX_VALUE;
+
+ for (int i=0; i<strings.length; i++) {
+ if (strings[i] == null) return 0;
+ minLength = Math.min(minLength, strings[i].length());
+ }
+
+ return minLength;
+ }
+
+ /**
+ * Determine the maximum number of common leading whitespace characters
+ * the strings share in the same sequence. Useful for determining how
+ * many leading characters can be removed to shift all the text in the
+ * strings to the left without misaligning them.
+ *
+ * @param strings String[]
+ * @return int
+ */
+ public static int maxCommonLeadingWhitespaceForAll(String[] strings) {
+
+ int shortest = lengthOfShortestIn(strings);
+ if (shortest == 0) return 0;
+
+ char[] matches = new char[shortest];
+
+ String str;
+ for (int m=0; m<matches.length; m++) {
+ matches[m] = strings[0].charAt(m);
+ if (!Character.isWhitespace(matches[m])) return m;
+ for (int i=0; i<strings.length; i++) {
+ str = strings[i];
+ if (str.charAt(m) != matches[m]) return m;
+ }
+ }
+
+ return shortest;
+ }
+
+ /**
+ * Trims off the leading characters off the strings up to the trimDepth
+ * specified. Returns the same strings if trimDepth = 0
+ *
+ * @param strings
+ * @param trimDepth
+ * @return String[]
+ */
+ public static String[] trimStartOn(String[] strings, int trimDepth) {
+
+ if (trimDepth == 0) return strings;
+
+ String[] results = new String[strings.length];
+ for (int i=0; i<strings.length; i++) {
+ results[i] = strings[i].substring(trimDepth);
+ }
+ return results;
+ }
+
+ /**
+ * Left pads a string.
+ * @param s The String to pad
+ * @param length The desired minimum length of the resulting padded String
+ * @return The resulting left padded String
+ */
+ public static String lpad(String s, int length) {
+ String res = s;
+ if (length - s.length() > 0) {
+ char [] arr = new char[length - s.length()];
+ java.util.Arrays.fill(arr, ' ');
+ res = new StringBuffer(length).append(arr).append(s).toString();
+ }
+ return res;
+ }
+
+ /**
+ * Are the two String values the same.
+ * The Strings can be optionally trimmed before checking.
+ * The Strings can be optionally compared ignoring case.
+ * The Strings can be have embedded whitespace standardized before comparing.
+ * Two null values are treated as equal.
+ *
+ * @param s1 The first String.
+ * @param s2 The second String.
+ * @param trim Indicates if the Strings should be trimmed before comparison.
+ * @param ignoreCase Indicates if the case of the Strings should ignored during comparison.
+ * @param standardizeWhitespace Indicates if the embedded whitespace should be standardized before comparison.
+ * @return <code>true</code> if the Strings are the same, <code>false</code> otherwise.
+ */
+ public static boolean isSame(String s1, String s2, boolean trim, boolean ignoreCase, boolean standardizeWhitespace) {
+ if (s1 == s2) {
+ return true;
+ } else if (s1 == null || s2 == null) {
+ return false;
+ } else {
+ if (trim) {
+ s1 = s1.trim();
+ s2 = s2.trim();
+ }
+ if (standardizeWhitespace) {
+ // Replace all whitespace with a standard single space character.
+ s1 = s1.replaceAll("\\s+", " ");
+ s2 = s2.replaceAll("\\s+", " ");
+ }
+ return ignoreCase ? s1.equalsIgnoreCase(s2) : s1.equals(s2);
+ }
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractCompoundFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractCompoundFilter.java
new file mode 100644
index 00000000000..01d6e66573b
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractCompoundFilter.java
@@ -0,0 +1,56 @@
+package net.sourceforge.pmd.util.filter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A base class for Filters which implements behavior using a List of other
+ * Filters.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public abstract class AbstractCompoundFilter<T> implements Filter<T> {
+
+ protected List<Filter<T>> filters;
+
+ public AbstractCompoundFilter() {
+ filters = new ArrayList<Filter<T>>(2);
+ }
+
+ public AbstractCompoundFilter(Filter<T>... filters) {
+ this.filters = new ArrayList<Filter<T>>(filters.length);
+ for (Filter<T> filter : filters) {
+ this.filters.add(filter);
+ }
+ }
+
+ public List<Filter<T>> getFilters() {
+ return filters;
+ }
+
+ public void setFilters(List<Filter<T>> filters) {
+ this.filters = filters;
+ }
+
+ public void addFilter(Filter<T> filter) {
+ filters.add(filter);
+ }
+
+ protected abstract String getOperator();
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("(");
+ for (int i = 0; i < filters.size(); i++) {
+ if (i > 0) {
+ builder.append(" ");
+ builder.append(getOperator());
+ builder.append(" ");
+ }
+ builder.append(filters.get(i));
+ }
+ builder.append(")");
+ return builder.toString();
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractDelegateFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractDelegateFilter.java
new file mode 100644
index 00000000000..f55c9c68d6f
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractDelegateFilter.java
@@ -0,0 +1,37 @@
+package net.sourceforge.pmd.util.filter;
+
+/**
+ * A base class for Filters which implements behavior using delegation
+ * to an underlying filter.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public abstract class AbstractDelegateFilter<T> implements Filter<T> {
+ protected Filter<T> filter;
+
+ public AbstractDelegateFilter() {
+ }
+
+ public AbstractDelegateFilter(Filter<T> filter) {
+ this.filter = filter;
+ }
+
+ public Filter<T> getFilter() {
+ return filter;
+ }
+
+ public void setFilter(Filter<T> filter) {
+ this.filter = filter;
+ }
+
+ // Subclass should override to do something other the simply delegate.
+ public boolean filter(T obj) {
+ return filter.filter(obj);
+ }
+
+ // Subclass should override to do something other the simply delegate.
+ public String toString() {
+ return filter.toString();
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AndFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AndFilter.java
new file mode 100644
index 00000000000..d2e29b9e8a8
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AndFilter.java
@@ -0,0 +1,34 @@
+package net.sourceforge.pmd.util.filter;
+
+/**
+ * A logical AND of a list of Filters. This implementation is short circuiting.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public class AndFilter<T> extends AbstractCompoundFilter<T> {
+
+ public AndFilter() {
+ super();
+ }
+
+ public AndFilter(Filter<T>... filters) {
+ super(filters);
+ }
+
+ public boolean filter(T obj) {
+ boolean match = true;
+ for (Filter<T> filter : filters) {
+ if (!filter.filter(obj)) {
+ match = false;
+ break;
+ }
+ }
+ return match;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "and";
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/DirectoryFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/DirectoryFilter.java
new file mode 100644
index 00000000000..acd3f8c3c37
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/DirectoryFilter.java
@@ -0,0 +1,17 @@
+package net.sourceforge.pmd.util.filter;
+
+import java.io.File;
+
+/**
+ * Directory filter.
+ */
+public class DirectoryFilter implements Filter<File> {
+ public static final DirectoryFilter INSTANCE = new DirectoryFilter();
+
+ private DirectoryFilter() {
+ }
+
+ public boolean filter(File file) {
+ return file.isDirectory();
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/FileExtensionFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/FileExtensionFilter.java
new file mode 100644
index 00000000000..5d7aa4ce0ed
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/FileExtensionFilter.java
@@ -0,0 +1,42 @@
+package net.sourceforge.pmd.util.filter;
+
+import java.io.File;
+
+public class FileExtensionFilter implements Filter<File> {
+ protected final String[] extensions;
+ protected final boolean ignoreCase;
+
+ /**
+ * Matches any files with the given extensions, ignoring case
+ */
+ public FileExtensionFilter(String... extensions) {
+ this(true, extensions);
+ }
+
+ /**
+ * Matches any files with the given extensions, optionally ignoring case.
+ */
+ public FileExtensionFilter(boolean ignoreCase, String... extensions) {
+ this.extensions = extensions;
+ this.ignoreCase = ignoreCase;
+ if (ignoreCase) {
+ for (int i = 0; i < this.extensions.length; i++) {
+ this.extensions[i] = this.extensions[i].toUpperCase();
+ }
+ }
+ }
+
+ public boolean filter(File file) {
+ boolean accept = extensions == null;
+ if (!accept) {
+ for (String extension : extensions) {
+ String name = file.getName();
+ if (ignoreCase ? name.toUpperCase().endsWith(extension) : name.endsWith(extension)) {
+ accept = true;
+ break;
+ }
+ }
+ }
+ return accept;
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filter.java
new file mode 100644
index 00000000000..9cb249d6dc7
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filter.java
@@ -0,0 +1,11 @@
+package net.sourceforge.pmd.util.filter;
+
+/**
+ * A Filter interface, used for filtering arbitrary objects.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public interface Filter<T> {
+ boolean filter(T obj);
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filters.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filters.java
new file mode 100644
index 00000000000..948bb5a1dc4
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filters.java
@@ -0,0 +1,200 @@
+package net.sourceforge.pmd.util.filter;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Utility class for working with Filters. Contains builder style methods,
+ * apply methods, as well as mechanisms for adapting Filters and FilenameFilters.
+ */
+public class Filters {
+
+ /**
+ * Filter a given Collection.
+ * @param <T> Type of the Collection.
+ * @param filter A Filter upon the Type of objects in the Collection.
+ * @param collection The Collection to filter.
+ * @return A List containing only those objects for which the Filter returned <code>true</code>.
+ */
+ public static <T> List<T> filter(Filter<T> filter, Collection<T> collection) {
+ List<T> list = new ArrayList<T>();
+ for (T obj : collection) {
+ if (filter.filter(obj)) {
+ list.add(obj);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Get a File Filter for files with the given extensions, ignoring case.
+ * @param extensions The extensions to filter.
+ * @return A File Filter.
+ */
+ public static Filter<File> getFileExtensionFilter(String... extensions) {
+ return new FileExtensionFilter(extensions);
+ }
+
+ /**
+ * Get a File Filter for directories.
+ * @return A File Filter.
+ */
+ public static Filter<File> getDirectoryFilter() {
+ return DirectoryFilter.INSTANCE;
+ }
+
+ /**
+ * Get a File Filter for directories or for files with the given extensions, ignoring case.
+ * @param extensions The extensions to filter.
+ * @return A File Filter.
+ */
+ public static Filter<File> getFileExtensionOrDirectoryFilter(String... extensions) {
+ return new OrFilter<File>(getFileExtensionFilter(extensions), getDirectoryFilter());
+ }
+
+ /**
+ * Given a String Filter, expose as a File Filter. The File paths are
+ * normalized to a standard pattern using <code>/</code> as a path separator
+ * which can be used cross platform easily in a regular expression based
+ * String Filter.
+ *
+ * @param filter A String Filter.
+ * @return A File Filter.
+ */
+ public static Filter<File> toNormalizedFileFilter(final Filter<String> filter) {
+ return new Filter<File>() {
+ public boolean filter(File file) {
+ String path = file.getPath();
+ path = path.replace('\\', '/');
+ return filter.filter(path);
+ }
+
+ public String toString() {
+ return filter.toString();
+ }
+ };
+ }
+
+ /**
+ * Given a String Filter, expose as a Filter on another type. The
+ * <code>toString()</code> method is called on the objects of the other
+ * type and delegated to the String Filter.
+ * @param <T> The desired type.
+ * @param filter The existing String Filter.
+ * @return A Filter on the desired type.
+ */
+ public static <T> Filter<T> fromStringFilter(final Filter<String> filter) {
+ return new Filter<T>() {
+ public boolean filter(T obj) {
+ return filter.filter(obj.toString());
+ }
+
+ public String toString() {
+ return filter.toString();
+ }
+ };
+ }
+
+ /**
+ * Given a File Filter, expose as a FilenameFilter.
+ * @param filter The File Filter.
+ * @return A FilenameFilter.
+ */
+ public static FilenameFilter toFilenameFilter(final Filter<File> filter) {
+ return new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return filter.filter(new File(dir, name));
+ }
+
+ public String toString() {
+ return filter.toString();
+ }
+ };
+ }
+
+ /**
+ * Given a FilenameFilter, expose as a File Filter.
+ * @param filter The FilenameFilter.
+ * @return A File Filter.
+ */
+ public static Filter<File> toFileFilter(final FilenameFilter filter) {
+ return new Filter<File>() {
+ public boolean filter(File file) {
+ return filter.accept(file.getParentFile(), file.getName());
+ }
+
+ public String toString() {
+ return filter.toString();
+ }
+ };
+ }
+
+ /**
+ * Construct a String Filter using set of include and exclude regular
+ * expressions. If there are no include regular expressions provide, then
+ * a regular expression is added which matches every String by default.
+ * A String is included as long as it matches an include regular expression
+ * and does not match an exclude regular expression.
+ * <p>
+ * In other words, exclude patterns override include patterns.
+ *
+ * @param includeRegexes The include regular expressions. May be <code>null</code>.
+ * @param excludeRegexes The exclude regular expressions. May be <code>null</code>.
+ * @return A String Filter.
+ */
+ public static Filter<String> buildRegexFilterExcludeOverInclude(List<String> includeRegexes,
+ List<String> excludeRegexes) {
+ OrFilter<String> includeFilter = new OrFilter<String>();
+ if (includeRegexes == null || includeRegexes.size() == 0) {
+ includeFilter.addFilter(new RegexStringFilter(".*"));
+ } else {
+ for (String includeRegex : includeRegexes) {
+ includeFilter.addFilter(new RegexStringFilter(includeRegex));
+ }
+ }
+
+ OrFilter<String> excludeFilter = new OrFilter<String>();
+ if (excludeRegexes != null) {
+ for (String excludeRegex : excludeRegexes) {
+ excludeFilter.addFilter(new RegexStringFilter(excludeRegex));
+ }
+ }
+
+ return new AndFilter<String>(includeFilter, new NotFilter<String>(excludeFilter));
+ }
+
+ /**
+ * Construct a String Filter using set of include and exclude regular
+ * expressions. If there are no include regular expressions provide, then
+ * a regular expression is added which matches every String by default.
+ * A String is included as long as the case that there is an include which
+ * matches or there is not an exclude which matches.
+ * <p>
+ * In other words, include patterns override exclude patterns.
+ *
+ * @param includeRegexes The include regular expressions. May be <code>null</code>.
+ * @param excludeRegexes The exclude regular expressions. May be <code>null</code>.
+ * @return A String Filter.
+ */
+ public static Filter<String> buildRegexFilterIncludeOverExclude(List<String> includeRegexes,
+ List<String> excludeRegexes) {
+ OrFilter<String> includeFilter = new OrFilter<String>();
+ if (includeRegexes != null) {
+ for (String includeRegex : includeRegexes) {
+ includeFilter.addFilter(new RegexStringFilter(includeRegex));
+ }
+ }
+
+ OrFilter<String> excludeFilter = new OrFilter<String>();
+ if (excludeRegexes != null) {
+ for (String excludeRegex : excludeRegexes) {
+ excludeFilter.addFilter(new RegexStringFilter(excludeRegex));
+ }
+ }
+
+ return new OrFilter<String>(includeFilter, new NotFilter<String>(excludeFilter));
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/NotFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/NotFilter.java
new file mode 100644
index 00000000000..437e3524805
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/NotFilter.java
@@ -0,0 +1,25 @@
+package net.sourceforge.pmd.util.filter;
+
+/**
+ * A logical NEGATION of a Filter.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public class NotFilter<T> extends AbstractDelegateFilter<T> {
+ public NotFilter() {
+ super();
+ }
+
+ public NotFilter(Filter<T> filter) {
+ super(filter);
+ }
+
+ public boolean filter(T obj) {
+ return !filter.filter(obj);
+ }
+
+ public String toString() {
+ return "not (" + filter + ")";
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/OrFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/OrFilter.java
new file mode 100644
index 00000000000..2647e2d98ab
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/OrFilter.java
@@ -0,0 +1,34 @@
+package net.sourceforge.pmd.util.filter;
+
+/**
+ * A logical OR of a list of Filters. This implementation is short circuiting.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public class OrFilter<T> extends AbstractCompoundFilter<T> {
+
+ public OrFilter() {
+ super();
+ }
+
+ public OrFilter(Filter<T>... filters) {
+ super(filters);
+ }
+
+ public boolean filter(T obj) {
+ boolean match = false;
+ for (Filter<T> filter : filters) {
+ if (filter.filter(obj)) {
+ match = true;
+ break;
+ }
+ }
+ return match;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "or";
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/RegexStringFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/RegexStringFilter.java
new file mode 100644
index 00000000000..7f883212589
--- /dev/null
+++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/RegexStringFilter.java
@@ -0,0 +1,40 @@
+package net.sourceforge.pmd.util.filter;
+
+import java.util.regex.Pattern;
+
+/**
+ * A filter to which uses a regular expression to match upon Strings.
+ */
+public class RegexStringFilter implements Filter<String> {
+
+ protected String regex;
+
+ protected Pattern pattern;
+
+ public RegexStringFilter() {
+ }
+
+ public RegexStringFilter(String regex) {
+ this.regex = regex;
+ }
+
+ public String getRegex() {
+ return regex;
+ }
+
+ public void setRegex(String regex) {
+ this.regex = regex;
+ this.pattern = null;
+ }
+
+ public boolean filter(String obj) {
+ if (pattern == null) {
+ pattern = Pattern.compile(regex);
+ }
+ return pattern.matcher(obj).matches();
+ }
+
+ public String toString() {
+ return "matches " + regex;
+ }
+}
diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CPD.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CPD.java
new file mode 100644
index 00000000000..f8b88745233
--- /dev/null
+++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CPD.java
@@ -0,0 +1,114 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package org.sonar.duplications.cpd;
+
+import net.sourceforge.pmd.cpd.*;
+import net.sourceforge.pmd.util.FileFinder;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.*;
+
+public class CPD {
+
+ private Map<String, SourceCode> source = new HashMap<String, SourceCode>();
+ private CPDListener listener = new CPDNullListener();
+ private Tokens tokens = new Tokens();
+ private int minimumTileSize;
+ private MatchAlgorithm matchAlgorithm;
+ private Language language;
+ private boolean skipDuplicates;
+ public static boolean debugEnable = false;
+ private boolean loadSourceCodeSlices = true;
+ private String encoding = System.getProperty("file.encoding");
+
+ public CPD(int minimumTileSize, Language language) {
+ TokenEntry.clearImages(); // workaround for bug 1947823
+ this.minimumTileSize = minimumTileSize;
+ this.language = language;
+ }
+
+ public void skipDuplicates() {
+ this.skipDuplicates = true;
+ }
+
+ public void setCpdListener(CPDListener cpdListener) {
+ this.listener = cpdListener;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public void setLoadSourceCodeSlices(boolean loadSourceCodeSlices) {
+ this.loadSourceCodeSlices = loadSourceCodeSlices;
+ }
+
+ public void go() {
+ TokenEntry.clearImages();
+ matchAlgorithm = new MatchAlgorithm(source, tokens, minimumTileSize, listener);
+ matchAlgorithm.setLoadSourceCodeSlices(loadSourceCodeSlices);
+ matchAlgorithm.findMatches();
+ }
+
+ public Iterator<Match> getMatches() {
+ return matchAlgorithm.matches();
+ }
+
+ public void add(File file) throws IOException {
+ add(1, file);
+ }
+
+ public void addAllInDirectory(String dir) throws IOException {
+ addDirectory(dir, false);
+ }
+
+ public void addRecursively(String dir) throws IOException {
+ addDirectory(dir, true);
+ }
+
+ public void add(List<File> files) throws IOException {
+ for (File f : files) {
+ add(files.size(), f);
+ }
+ }
+
+ private void addDirectory(String dir, boolean recurse) throws IOException {
+ if ( !(new File(dir)).exists()) {
+ throw new FileNotFoundException("Couldn't find directory " + dir);
+ }
+ FileFinder finder = new FileFinder();
+ // TODO - could use SourceFileSelector here
+ add(finder.findFilesFrom(dir, language.getFileFilter(), recurse));
+ }
+
+ private Set<String> current = new HashSet<String>();
+
+ private void add(int fileCount, File file) throws IOException {
+
+ if (skipDuplicates) {
+ // TODO refactor this thing into a separate class
+ String signature = file.getName() + '_' + file.length();
+ if (current.contains(signature)) {
+ System.err.println("Skipping " + file.getAbsolutePath()
+ + " since it appears to be a duplicate file and --skip-duplicate-files is set");
+ return;
+ }
+ current.add(signature);
+ }
+
+ if ( !file.getCanonicalPath().equals(new File(file.getAbsolutePath()).getCanonicalPath())) {
+ System.err.println("Skipping " + file + " since it appears to be a symlink");
+ return;
+ }
+
+ listener.addedFile(fileCount, file);
+ SourceCode sourceCode = new SourceCode(new FileCodeLoaderWithoutCache(file, encoding));
+ language.getTokenizer().tokenize(sourceCode, tokens);
+ source.put(sourceCode.getFileName(), sourceCode);
+ }
+
+
+}
diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CodeLoaderWithoutCache.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CodeLoaderWithoutCache.java
new file mode 100644
index 00000000000..f436768c929
--- /dev/null
+++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CodeLoaderWithoutCache.java
@@ -0,0 +1,31 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.duplications.cpd;
+
+import java.util.List;
+
+import net.sourceforge.pmd.cpd.SourceCode.CodeLoader;
+
+public abstract class CodeLoaderWithoutCache extends CodeLoader {
+
+ public final List<String> getCode() {
+ return load();
+ }
+}
diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/FileCodeLoaderWithoutCache.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/FileCodeLoaderWithoutCache.java
new file mode 100644
index 00000000000..fe63482d46b
--- /dev/null
+++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/FileCodeLoaderWithoutCache.java
@@ -0,0 +1,44 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.duplications.cpd;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+public class FileCodeLoaderWithoutCache extends CodeLoaderWithoutCache {
+
+ private File file;
+ private String encoding;
+
+ public FileCodeLoaderWithoutCache(File file, String encoding) {
+ this.file = file;
+ this.encoding = encoding;
+ }
+
+ public Reader getReader() throws Exception {
+ return new InputStreamReader(new FileInputStream(file), encoding);
+ }
+
+ public String getFileName() {
+ return this.file.getAbsolutePath();
+ }
+}
diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/Match.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/Match.java
new file mode 100644
index 00000000000..777f8617b2a
--- /dev/null
+++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/Match.java
@@ -0,0 +1,171 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package org.sonar.duplications.cpd;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+
+import net.sourceforge.pmd.cpd.TokenEntry;
+
+public class Match implements Comparable<Match> {
+
+ public static final String EOL = System.getProperty("line.separator", "\n");
+
+ private int tokenCount;
+ private int lineCount;
+ private Set<TokenEntry> markSet = new TreeSet<TokenEntry>();
+ private TokenEntry[] marks = new TokenEntry[2];
+ private String code;
+ private MatchCode mc;
+ private String label;
+
+ public static final Comparator<Match> MatchesComparator = new Comparator<Match>() {
+
+ public int compare(Match ma, Match mb) {
+ return mb.getMarkCount() - ma.getMarkCount();
+ }
+ };
+
+ public static final Comparator<Match> LinesComparator = new Comparator<Match>() {
+
+ public int compare(Match ma, Match mb) {
+ return mb.getLineCount() - ma.getLineCount();
+ }
+ };
+
+ public static final Comparator<Match> LabelComparator = new Comparator<Match>() {
+
+ public int compare(Match ma, Match mb) {
+ if (ma.getLabel() == null)
+ return 1;
+ if (mb.getLabel() == null)
+ return -1;
+ return mb.getLabel().compareTo(ma.getLabel());
+ }
+ };
+
+ public static final Comparator<Match> LengthComparator = new Comparator<Match>() {
+
+ public int compare(Match ma, Match mb) {
+ return mb.getLineCount() - ma.getLineCount();
+ }
+ };
+
+ public static class MatchCode {
+
+ private int first;
+ private int second;
+
+ public MatchCode() {
+ }
+
+ public MatchCode(TokenEntry m1, TokenEntry m2) {
+ first = m1.getIndex();
+ second = m2.getIndex();
+ }
+
+ public int hashCode() {
+ return first + 37 * second;
+ }
+
+ public boolean equals(Object other) {
+ MatchCode mc = (MatchCode) other;
+ return mc.first == first && mc.second == second;
+ }
+
+ public void setFirst(int first) {
+ this.first = first;
+ }
+
+ public void setSecond(int second) {
+ this.second = second;
+ }
+
+ }
+
+ public Match(int tokenCount, TokenEntry first, TokenEntry second) {
+ markSet.add(first);
+ markSet.add(second);
+ marks[0] = first;
+ marks[1] = second;
+ this.tokenCount = tokenCount;
+ }
+
+ public int getMarkCount() {
+ return markSet.size();
+ }
+
+ public void setLineCount(int lineCount) {
+ this.lineCount = lineCount;
+ }
+
+ public int getLineCount() {
+ return this.lineCount;
+ }
+
+ public int getTokenCount() {
+ return this.tokenCount;
+ }
+
+ public String getSourceCodeSlice() {
+ return this.code;
+ }
+
+ public void setSourceCodeSlice(String code) {
+ this.code = code;
+ }
+
+ public Iterator<TokenEntry> iterator() {
+ return markSet.iterator();
+ }
+
+ public int compareTo(Match other) {
+ int diff = other.getTokenCount() - getTokenCount();
+ if (diff != 0) {
+ return diff;
+ }
+ return other.getFirstMark().getIndex() - getFirstMark().getIndex();
+ }
+
+ public TokenEntry getFirstMark() {
+ return marks[0];
+ }
+
+ public TokenEntry getSecondMark() {
+ return marks[1];
+ }
+
+ public String toString() {
+ return "Match: " + EOL + "tokenCount = " + tokenCount + EOL + "marks = " + markSet.size();
+ }
+
+ public Set<TokenEntry> getMarkSet() {
+ return markSet;
+ }
+
+ public MatchCode getMatchCode() {
+ if (mc == null) {
+ mc = new MatchCode(marks[0], marks[1]);
+ }
+ return mc;
+ }
+
+ public int getEndIndex() {
+ return marks[1].getIndex() + getTokenCount() - 1;
+ }
+
+ public void setMarkSet(Set<TokenEntry> markSet) {
+ this.markSet = markSet;
+ }
+
+ public void setLabel(String aLabel) {
+ label = aLabel;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+} \ No newline at end of file
diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchAlgorithm.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchAlgorithm.java
new file mode 100644
index 00000000000..fce761146dc
--- /dev/null
+++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchAlgorithm.java
@@ -0,0 +1,131 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package org.sonar.duplications.cpd;
+
+import net.sourceforge.pmd.cpd.*;
+
+import java.util.*;
+
+public class MatchAlgorithm {
+
+ private final static int MOD = 37;
+ private int lastHash;
+ private int lastMod = 1;
+
+ private List<Match> matches;
+ private Map<String, SourceCode> source;
+ private Tokens tokens;
+ private List<TokenEntry> code;
+ private CPDListener cpdListener;
+ private int min;
+ private boolean loadSourceCodeSlices = true;
+
+ public MatchAlgorithm(Map<String, SourceCode> sourceCode, Tokens tokens, int min) {
+ this(sourceCode, tokens, min, new CPDNullListener());
+ }
+
+ public MatchAlgorithm(Map<String, SourceCode> sourceCode, Tokens tokens, int min, CPDListener listener) {
+ this.source = sourceCode;
+ this.tokens = tokens;
+ this.code = tokens.getTokens();
+ this.min = min;
+ this.cpdListener = listener;
+ for (int i = 0; i < min; i++) {
+ lastMod *= MOD;
+ }
+ }
+
+ public void setLoadSourceCodeSlices(boolean loadSourceCodeSlices) {
+ this.loadSourceCodeSlices = loadSourceCodeSlices;
+ }
+
+ public void setListener(CPDListener listener) {
+ this.cpdListener = listener;
+ }
+
+ public Iterator<Match> matches() {
+ return matches.iterator();
+ }
+
+ public TokenEntry tokenAt(int offset, TokenEntry m) {
+ return code.get(offset + m.getIndex());
+ }
+
+ public int getMinimumTileSize() {
+ return this.min;
+ }
+
+ public void findMatches() {
+ cpdListener.phaseUpdate(CPDListener.HASH);
+ Map<TokenEntry, Object> markGroups = hash();
+
+ cpdListener.phaseUpdate(CPDListener.MATCH);
+ MatchCollector matchCollector = new MatchCollector(this);
+ for (Iterator<Object> i = markGroups.values().iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof List) {
+ List<TokenEntry> l = (List<TokenEntry>) o;
+
+ Collections.reverse(l);
+ matchCollector.collect(l);
+ }
+ i.remove();
+ }
+ cpdListener.phaseUpdate(CPDListener.GROUPING);
+ matches = matchCollector.getMatches();
+ matchCollector = null;
+ for (Match match : matches) {
+ for (Iterator<TokenEntry> occurrences = match.iterator(); occurrences.hasNext();) {
+ TokenEntry mark = occurrences.next();
+ match.setLineCount(tokens.getLineCount(mark, match));
+ if (loadSourceCodeSlices && !occurrences.hasNext()) {
+ int start = mark.getBeginLine();
+ int end = start + match.getLineCount() - 1;
+ SourceCode sourceCode = source.get(mark.getTokenSrcID());
+ match.setSourceCodeSlice(sourceCode.getSlice(start, end));
+ }
+ }
+ }
+ cpdListener.phaseUpdate(CPDListener.DONE);
+ }
+
+ @SuppressWarnings("PMD.JumbledIncrementer")
+ private Map<TokenEntry, Object> hash() {
+ Map<TokenEntry, Object> markGroups = new HashMap<TokenEntry, Object>(tokens.size());
+ for (int i = code.size() - 1; i >= 0; i--) {
+ TokenEntry token = code.get(i);
+ if (token != TokenEntry.EOF) {
+ int last = tokenAt(min, token).getIdentifier();
+ lastHash = MOD * lastHash + token.getIdentifier() - lastMod * last;
+ token.setHashCode(lastHash);
+ Object o = markGroups.get(token);
+
+ // Note that this insertion method is worthwhile since the vast majority
+ // markGroup keys will have only one value.
+ if (o == null) {
+ markGroups.put(token, token);
+ } else if (o instanceof TokenEntry) {
+ List<TokenEntry> l = new ArrayList<TokenEntry>();
+ l.add((TokenEntry) o);
+ l.add(token);
+ markGroups.put(token, l);
+ } else {
+ List<TokenEntry> l = (List<TokenEntry>) o;
+ l.add(token);
+ }
+ } else {
+ lastHash = 0;
+ for (int end = Math.max(0, i - min + 1); i > end; i--) {
+ token = code.get(i - 1);
+ lastHash = MOD * lastHash + token.getIdentifier();
+ if (token == TokenEntry.EOF) {
+ break;
+ }
+ }
+ }
+ }
+ return markGroups;
+ }
+
+}
diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchCollector.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchCollector.java
new file mode 100644
index 00000000000..6bbb825b025
--- /dev/null
+++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchCollector.java
@@ -0,0 +1,167 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package org.sonar.duplications.cpd;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.sourceforge.pmd.cpd.TokenEntry;
+
+public class MatchCollector {
+
+ private MatchAlgorithm ma;
+ private Map<Match.MatchCode, Match> startMap = new HashMap<Match.MatchCode, Match>();
+ private Map<String, List<Match>> fileMap = new HashMap<String, List<Match>>();
+
+ public MatchCollector(MatchAlgorithm ma) {
+ this.ma = ma;
+ }
+
+ public void collect(List<TokenEntry> marks) {
+ // first get a pairwise collection of all maximal matches
+ for (int i = 0; i < marks.size() - 1; i++) {
+ TokenEntry mark1 = marks.get(i);
+ for (int j = i + 1; j < marks.size(); j++) {
+ TokenEntry mark2 = marks.get(j);
+ int diff = mark1.getIndex() - mark2.getIndex();
+ if ( -diff < ma.getMinimumTileSize()) {
+ continue;
+ }
+ if (hasPreviousDupe(mark1, mark2)) {
+ continue;
+ }
+
+ // "match too small" check
+ int dupes = countDuplicateTokens(mark1, mark2);
+ if (dupes < ma.getMinimumTileSize()) {
+ continue;
+ }
+ // is it still too close together
+ if (diff + dupes >= 1) {
+ continue;
+ }
+ determineMatch(mark1, mark2, dupes);
+ }
+ }
+ }
+
+ @SuppressWarnings("PMD.CompareObjectsWithEquals")
+ public List<Match> getMatches() {
+ List<Match> matchList = new ArrayList<Match>(startMap.values());
+ Collections.sort(matchList);
+ Set<Match.MatchCode> matchSet = new HashSet<Match.MatchCode>();
+ Match.MatchCode matchCode = new Match.MatchCode();
+ for (int i = matchList.size(); i > 1; i--) {
+ Match match1 = matchList.get(i - 1);
+ TokenEntry mark1 = match1.getMarkSet().iterator().next();
+ matchSet.clear();
+ matchSet.add(match1.getMatchCode());
+ for (int j = i - 1; j > 0; j--) {
+ Match match2 = matchList.get(j - 1);
+ if (match1.getTokenCount() != match2.getTokenCount()) {
+ break;
+ }
+ TokenEntry mark2 = null;
+ for (Iterator<TokenEntry> iter = match2.getMarkSet().iterator(); iter.hasNext();) {
+ mark2 = iter.next();
+ if (mark2 != mark1) {
+ break;
+ }
+ }
+ int dupes = countDuplicateTokens(mark1, mark2);
+ if (dupes < match1.getTokenCount()) {
+ break;
+ }
+ matchSet.add(match2.getMatchCode());
+ match1.getMarkSet().addAll(match2.getMarkSet());
+ matchList.remove(i - 2);
+ i--;
+ }
+ if (matchSet.size() == 1) {
+ continue;
+ }
+ // prune the mark set
+ Set<TokenEntry> pruned = match1.getMarkSet();
+ boolean done = false;
+ ArrayList<TokenEntry> a1 = new ArrayList<TokenEntry>(match1.getMarkSet());
+ Collections.sort(a1);
+ for (int outer = 0; outer < a1.size() - 1 && !done; outer++) {
+ TokenEntry cmark1 = a1.get(outer);
+ for (int inner = outer + 1; inner < a1.size() && !done; inner++) {
+ TokenEntry cmark2 = a1.get(inner);
+ matchCode.setFirst(cmark1.getIndex());
+ matchCode.setSecond(cmark2.getIndex());
+ if ( !matchSet.contains(matchCode)) {
+ if (pruned.size() > 2) {
+ pruned.remove(cmark2);
+ }
+ if (pruned.size() == 2) {
+ done = true;
+ }
+ }
+ }
+ }
+ }
+ return matchList;
+ }
+
+ /**
+ * A greedy algorithm for determining non-overlapping matches
+ */
+ private void determineMatch(TokenEntry mark1, TokenEntry mark2, int dupes) {
+ Match match = new Match(dupes, mark1, mark2);
+ String fileKey = mark1.getTokenSrcID() + mark2.getTokenSrcID();
+ List<Match> pairMatches = fileMap.get(fileKey);
+ if (pairMatches == null) {
+ pairMatches = new ArrayList<Match>();
+ fileMap.put(fileKey, pairMatches);
+ }
+ boolean add = true;
+ for (int i = 0; i < pairMatches.size(); i++) {
+ Match other = pairMatches.get(i);
+ if (other.getFirstMark().getIndex() + other.getTokenCount() - mark1.getIndex() > 0) {
+ boolean ordered = other.getSecondMark().getIndex() - mark2.getIndex() < 0;
+ if ((ordered && (other.getEndIndex() - mark2.getIndex() > 0))
+ || ( !ordered && (match.getEndIndex() - other.getSecondMark().getIndex()) > 0)) {
+ if (other.getTokenCount() >= match.getTokenCount()) {
+ add = false;
+ break;
+ } else {
+ pairMatches.remove(i);
+ startMap.remove(other.getMatchCode());
+ }
+ }
+ }
+ }
+ if (add) {
+ pairMatches.add(match);
+ startMap.put(match.getMatchCode(), match);
+ }
+ }
+
+ private boolean hasPreviousDupe(TokenEntry mark1, TokenEntry mark2) {
+ if (mark1.getIndex() == 0) {
+ return false;
+ }
+ return !matchEnded(ma.tokenAt( -1, mark1), ma.tokenAt( -1, mark2));
+ }
+
+ private int countDuplicateTokens(TokenEntry mark1, TokenEntry mark2) {
+ int index = 0;
+ while ( !matchEnded(ma.tokenAt(index, mark1), ma.tokenAt(index, mark2))) {
+ index++;
+ }
+ return index;
+ }
+
+ private boolean matchEnded(TokenEntry token1, TokenEntry token2) {
+ return token1.getIdentifier() != token2.getIdentifier() || token1 == TokenEntry.EOF || token2 == TokenEntry.EOF;
+ }
+} \ No newline at end of file
diff --git a/sonar-duplications/src/test/java/org/sonar/duplications/cpd/CPDTest.java b/sonar-duplications/src/test/java/org/sonar/duplications/cpd/CPDTest.java
new file mode 100644
index 00000000000..f0f561091b2
--- /dev/null
+++ b/sonar-duplications/src/test/java/org/sonar/duplications/cpd/CPDTest.java
@@ -0,0 +1,90 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.duplications.cpd;
+
+import net.sourceforge.pmd.cpd.AbstractLanguage;
+import net.sourceforge.pmd.cpd.JavaTokenizer;
+import net.sourceforge.pmd.cpd.TokenEntry;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class CPDTest {
+
+ @Test
+ public void testSetLoadSourceCodeSlicesToFalse() throws IOException {
+ TokenEntry.clearImages();
+ AbstractLanguage cpdLanguage = new AbstractLanguage(new JavaTokenizer()) {
+ };
+ CPD cpd = new CPD(20, cpdLanguage);
+ cpd.setEncoding(Charset.defaultCharset().name());
+ cpd.setLoadSourceCodeSlices(false);
+ cpd.add(new File("test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java"));
+ cpd.add(new File("test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java"));
+ cpd.go();
+
+ List<Match> matches = getMatches(cpd);
+ assertThat(matches.size(), is(1));
+
+ org.sonar.duplications.cpd.Match match = matches.get(0);
+ assertThat(match.getLineCount(), is(26));
+ assertThat(match.getFirstMark().getBeginLine(), is(16));
+ assertThat(match.getSourceCodeSlice(), is(nullValue()));
+ }
+
+ @Test
+ public void testDuplicationOnSameFile() throws IOException {
+ TokenEntry.clearImages();
+ AbstractLanguage cpdLanguage = new AbstractLanguage(new JavaTokenizer()) {
+ };
+ CPD cpd = new CPD(20, cpdLanguage);
+ cpd.setEncoding(Charset.defaultCharset().name());
+ cpd.setLoadSourceCodeSlices(false);
+ cpd.add(new File("test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java"));
+ cpd.go();
+
+ List<Match> matches = getMatches(cpd);
+ assertThat(matches.size(), is(1));
+
+ org.sonar.duplications.cpd.Match match = matches.get(0);
+ assertThat(match.getLineCount(), is(16));
+ assertThat(match.getFirstMark().getBeginLine(), is(29));
+ assertThat(match.getSourceCodeSlice(), is(nullValue()));
+ }
+
+ private List<Match> getMatches(CPD cpd) {
+ List<Match> matches = new ArrayList<org.sonar.duplications.cpd.Match>();
+ Iterator<Match> matchesIter = cpd.getMatches();
+ while (matchesIter.hasNext()) {
+ matches.add(matchesIter.next());
+ }
+ return matches;
+ }
+
+}
diff --git a/sonar-duplications/test-resources/README.txt b/sonar-duplications/test-resources/README.txt
new file mode 100644
index 00000000000..3f09e6215df
--- /dev/null
+++ b/sonar-duplications/test-resources/README.txt
@@ -0,0 +1,2 @@
+This directory is a workaround for opening the project into Intellij Idea.
+Indeed it tries to compile Java sources found in src/test/resources, and fail because of syntax errors or specific encoding. \ No newline at end of file
diff --git a/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java
new file mode 100644
index 00000000000..75e2b77b0dc
--- /dev/null
+++ b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java
@@ -0,0 +1,41 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd.fork;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.pmd.cpd.CPDListener;
+import net.sourceforge.pmd.cpd.CPDNullListener;
+import net.sourceforge.pmd.cpd.Language;
+import net.sourceforge.pmd.cpd.SourceCode;
+import net.sourceforge.pmd.cpd.Tokens;
+import org.sonar.duplications.cpd.MatchAlgorithm;
+
+public class CPDFile1 {
+
+ private Map<String, SourceCode> source = new HashMap<String, SourceCode>();
+ private CPDListener listener = new CPDNullListener();
+ private Tokens tokens = new Tokens();
+ private int minimumTileSize;
+ private MatchAlgorithm matchAlgorithm;
+ private Language language;
+ private boolean skipDuplicates;
+ public static boolean debugEnable = false;
+ private boolean loadSourceCodeSlices = true;
+ private String encoding = System.getProperty("file.encoding");
+
+ public CPD(int minimumTileSize, Language language) {
+ this.minimumTileSize = minimumTileSize;
+ this.language = language;
+ }
+
+ public void skipDuplicates() {
+ this.skipDuplicates = true;
+ }
+
+ public void setCpdListener(CPDListener cpdListener) {
+ this.listener = cpdListener;
+ }
+}
diff --git a/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java
new file mode 100644
index 00000000000..cdd67488f6a
--- /dev/null
+++ b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java
@@ -0,0 +1,41 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd.fork;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.pmd.cpd.CPDListener;
+import net.sourceforge.pmd.cpd.CPDNullListener;
+import net.sourceforge.pmd.cpd.Language;
+import net.sourceforge.pmd.cpd.SourceCode;
+import net.sourceforge.pmd.cpd.Tokens;
+import org.sonar.duplications.cpd.MatchAlgorithm;
+
+public class CPDFile2 {
+
+ private Map<String, SourceCode> source = new HashMap<String, SourceCode>();
+ private CPDListener listener = new CPDNullListener();
+ private Tokens tokens = new Tokens();
+ private int minimumTileSize;
+ private MatchAlgorithm matchAlgorithm;
+ private Language language;
+ private boolean skipDuplicates;
+ public static boolean debugEnable = false;
+ private boolean loadSourceCodeSlices = true;
+ private String encoding = System.getProperty("file.encoding");
+
+ public CPD(int minimumTileSize, Language language) {
+ this.minimumTileSize = minimumTileSize;
+ this.language = language;
+ }
+
+ public void skipDuplicates() {
+ this.skipDuplicates = true;
+ }
+
+ public void setCpdListener(CPDListener cpdListener) {
+ this.listener = cpdListener;
+ }
+}
diff --git a/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java
new file mode 100644
index 00000000000..8ba22b82a07
--- /dev/null
+++ b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java
@@ -0,0 +1,63 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+package net.sourceforge.pmd.cpd.fork;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.pmd.cpd.CPDListener;
+import net.sourceforge.pmd.cpd.CPDNullListener;
+import net.sourceforge.pmd.cpd.Language;
+import net.sourceforge.pmd.cpd.SourceCode;
+import net.sourceforge.pmd.cpd.Tokens;
+
+import org.apache.commons.io.FileUtils;
+import org.sonar.duplications.cpd.CPD;
+import org.sonar.duplications.cpd.Match;
+import org.sonar.duplications.cpd.MatchAlgorithm;
+
+public class CPDFile2 {
+
+
+ public void method1(){
+ CPD cpd = new CPD(20, cpdLanguage);
+ cpd.setEncoding(Charset.defaultCharset().name());
+ cpd.setLoadSourceCodeSlices(false);
+ cpd.add(FileUtils.toFile(CPD.class.getResource("/org/sonar/duplications/cpd/CPDTest/CPDFile1.java")));
+ cpd.add(FileUtils.toFile(CPD.class.getResource("/org/sonar/duplications/cpd/CPDTest/CPDFile2.java")));
+ cpd.go();
+
+ List<Match> matches = getMatches(cpd);
+ assertThat(matches.size(), is(1));
+
+ org.sonar.duplications.cpd.Match match = matches.get(0);
+ assertThat(match.getLineCount(), is(26));
+ assertThat(match.getFirstMark().getBeginLine(), is(16));
+ assertThat(match.getSourceCodeSlice(), is(nullValue()));
+ }
+
+ public void method1Duplicated(){
+ CPD cpd = new CPD(20, cpdLanguage);
+ cpd.setEncoding(Charset.defaultCharset().name());
+ cpd.setLoadSourceCodeSlices(false);
+ cpd.add(FileUtils.toFile(CPD.class.getResource("/org/sonar/duplications/cpd/CPDTest/CPDFile1.java")));
+ cpd.add(FileUtils.toFile(CPD.class.getResource("/org/sonar/duplications/cpd/CPDTest/CPDFile2.java")));
+ cpd.go();
+
+ List<Match> matches = getMatches(cpd);
+ assertThat(matches.size(), is(1));
+
+ org.sonar.duplications.cpd.Match match = matches.get(0);
+ assertThat(match.getLineCount(), is(26));
+ assertThat(match.getFirstMark().getBeginLine(), is(16));
+ assertThat(match.getSourceCodeSlice(), is(nullValue()));
+ }
+
+}