Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.debug.examples.core/src_ant/org/eclipse/debug/examples/ant/tasks/PreProcessor.java')
-rw-r--r--org.eclipse.debug.examples.core/src_ant/org/eclipse/debug/examples/ant/tasks/PreProcessor.java292
1 files changed, 292 insertions, 0 deletions
diff --git a/org.eclipse.debug.examples.core/src_ant/org/eclipse/debug/examples/ant/tasks/PreProcessor.java b/org.eclipse.debug.examples.core/src_ant/org/eclipse/debug/examples/ant/tasks/PreProcessor.java
new file mode 100644
index 000000000..30495d3f4
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src_ant/org/eclipse/debug/examples/ant/tasks/PreProcessor.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.ant.tasks;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.util.FileUtils;
+
+/**
+ * Java preprocessor for code examples. Used to export source code for
+ * example plug-ins with parts of code missing/inserted etc., for
+ * various exercises.
+ * <p>
+ * The preprocessor looks for #ifdef statements in java comments, and is
+ * run with a set of symbols. For example:
+ * <pre>
+ * //#ifdef ex1
+ * ... code to insert when 'ex1' symbol is on
+ * //#else
+ * ... code to insert when not 'ex1'
+ * //#endif
+ * </pre>
+ * </p>
+ */
+public class PreProcessor extends Task {
+
+ private Vector fFileSets = new Vector();
+ private File fDestDir = null;
+ private Set fSymbols = new HashSet();
+ private FileUtils fUtils = FileUtils.getFileUtils();
+
+ // possible states
+ private static final int STATE_OUTSIDE_CONDITION = 0;
+ private static final int STATE_TRUE_CONDITION = 1;
+ private static final int STATE_FALSE_CONDITION = 2;
+ private static final int STATE_POST_TRUE_CONDITION = 3;
+
+ // matchers
+ private Matcher IF_DEF_MATCHER = Pattern.compile("#ifdef\\s+\\w+").matcher("");
+ private Matcher ELSE_IF_MATCHER = Pattern.compile("#elseif\\s+\\w+").matcher("");
+ private Matcher ELSE_MATCHER = Pattern.compile("#else$|#else\\W+").matcher("");
+ private Matcher END_MATCHER = Pattern.compile("#endif").matcher("");
+
+
+ /**
+ * Constructs a new preprocessor task
+ */
+ public PreProcessor() {
+ }
+
+ /**
+ * Adds a set of files to process.
+ *
+ * @param set a set of files to process
+ */
+ public void addFileset(FileSet set) {
+ fFileSets.addElement(set);
+ }
+
+ /**
+ * Sets the destination directory for processed files.
+ *
+ * @param destDir destination directory for processed files
+ */
+ public void setDestdir(File destDir) {
+ fDestDir = destDir;
+ }
+
+ /**
+ * Sets the symbols that are "on" for the preprocessing.
+ *
+ * @param symbols symbols that are "on" for the preprocessing
+ */
+ public void setSymbols(String symbols) {
+ String[] strings = symbols.split(",");
+ for (int i = 0; i < strings.length; i++) {
+ String string = strings[i].trim();
+ if (string.length() > 0) {
+ fSymbols.add(string);
+ }
+ }
+ }
+
+ public void execute() throws BuildException {
+ if (fSymbols.size() == 0) {
+ throw new BuildException("No symbols specified for preprocessor");
+ }
+ if (fFileSets.isEmpty()) {
+ throw new BuildException("No filesets specified for processing");
+ }
+ if (!fDestDir.exists()) {
+ throw new BuildException("destdir does not exist: " + fDestDir.getAbsolutePath());
+ }
+ StringBuffer buf = new StringBuffer("Symbols: ");
+ String[] symbols = (String[]) fSymbols.toArray(new String[fSymbols.size()]);
+ for (int i = 0; i < symbols.length; i++) {
+ String symbol = symbols[i];
+ buf.append(symbol);
+ if(i < (symbols.length -1)) {
+ buf.append(", ");
+ }
+ }
+ log(buf.toString());
+
+ Iterator fileSets = fFileSets.iterator();
+ while (fileSets.hasNext()) {
+ FileSet fileSet = (FileSet) fileSets.next();
+ DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
+ String[] includedFiles = scanner.getIncludedFiles();
+ File baseDir = fileSet.getDir(getProject());
+ for (int i = 0; i < includedFiles.length; i++) {
+ String fileName = includedFiles[i];
+ processFile(baseDir, fileName, fDestDir);
+ }
+ }
+
+ }
+
+ /**
+ * Process the file
+ * @param baseDir base directory source file is relative to
+ * @param fileName source file name
+ * @param destDir root destination directory
+ */
+ private void processFile(File baseDir, String fileName, File destDir) throws BuildException {
+ File destFile = new File(destDir, fileName);
+ File srcFile = new File(baseDir, fileName);
+ File dir = destFile.getParentFile();
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ String contents = null;
+ if (fileName.endsWith(".java")) {
+ contents = preProcessFile(srcFile, "//#");
+ } else if (fileName.equals("plugin.xml")) {
+ contents = preProcessFile(srcFile, null);
+ }
+ if (contents == null) {
+ // no change, just copy file
+ try {
+ fUtils.copyFile(srcFile, destFile);
+ } catch (IOException e) {
+ throw new BuildException(e);
+ }
+ } else {
+ // write new file
+ FileWriter writer;
+ try {
+ writer = new FileWriter(destFile);
+ writer.write(contents);
+ writer.close();
+ } catch (IOException e) {
+ throw new BuildException(e);
+ }
+
+ }
+ }
+
+ /**
+ * Preprocesses a file
+ *
+ * @param srcFile the file to process
+ * @param strip chars to stip off lines in a true condition, or <code>null</code>
+ * @return
+ */
+ public String preProcessFile(File srcFile, String strip) {
+ try {
+ FileReader fileReader = new FileReader(srcFile);
+ BufferedReader reader = new BufferedReader(fileReader);
+ StringBuffer buffer = new StringBuffer();
+ String line = reader.readLine();
+ String activeSymbol = null;
+ int state = STATE_OUTSIDE_CONDITION;
+ boolean changed = false;
+ while (line != null) {
+ boolean ifdef = IF_DEF_MATCHER.reset(line).find();
+ boolean elseif = ELSE_IF_MATCHER.reset(line).find();
+ boolean elze = ELSE_MATCHER.reset(line).find();
+ boolean endif = END_MATCHER.reset(line).find();
+ boolean commandLine = ifdef || elseif || elze || endif;
+ boolean written = false;
+ switch (state) {
+ case STATE_OUTSIDE_CONDITION:
+ if (ifdef) {
+ String condition = line.substring(IF_DEF_MATCHER.start(), IF_DEF_MATCHER.end());
+ String[] strings = condition.split("\\s+");
+ activeSymbol = strings[1].trim();
+ if (fSymbols.contains(activeSymbol)) {
+ state = STATE_TRUE_CONDITION;
+ } else {
+ state = STATE_FALSE_CONDITION;
+ }
+ } else if (elseif) {
+ throw new BuildException("#elseif encountered without corresponding #ifdef");
+ } else if (elze) {
+ throw new BuildException("#else encountered without corresponding #ifdef (" + srcFile.getPath() + ")");
+ } else if (endif) {
+ throw new BuildException("#endif encountered without corresponding #ifdef");
+ }
+ break;
+ case STATE_TRUE_CONDITION:
+ if (elze || elseif) {
+ state = STATE_POST_TRUE_CONDITION;
+ break;
+ } else if (endif) {
+ state = STATE_OUTSIDE_CONDITION;
+ break;
+ } else if (ifdef) {
+ throw new BuildException("illegal nested #ifdef");
+ }
+ case STATE_FALSE_CONDITION:
+ if (elseif) {
+ String condition = line.substring(ELSE_IF_MATCHER.start(), ELSE_IF_MATCHER.end());
+ String[] strings = condition.split("\\s+");
+ activeSymbol = strings[1].trim();
+ if (fSymbols.contains(activeSymbol)) {
+ state = STATE_TRUE_CONDITION;
+ } else {
+ state = STATE_FALSE_CONDITION;
+ }
+ } else if (elze) {
+ state = STATE_TRUE_CONDITION;
+ break;
+ } else if (endif) {
+ state = STATE_OUTSIDE_CONDITION;
+ break;
+ } else if (ifdef) {
+ throw new BuildException("illegal nested #ifdef");
+ }
+ case STATE_POST_TRUE_CONDITION:
+ if (endif) {
+ state = STATE_OUTSIDE_CONDITION;
+ break;
+ } else if (ifdef) {
+ throw new BuildException("illegal nested #ifdef");
+ }
+ }
+ if (!commandLine) {
+ if (state == STATE_OUTSIDE_CONDITION || state == STATE_TRUE_CONDITION) {
+ if (state == STATE_TRUE_CONDITION && strip != null) {
+ if (line.startsWith(strip)) {
+ line = line.substring(strip.length());
+ }
+ }
+ buffer.append(line);
+ buffer.append("\n");
+ written = true;
+ }
+ }
+ changed = changed || !written;
+ line = reader.readLine();
+ }
+ if (!changed) {
+ return null;
+ }
+ return buffer.toString();
+ } catch (IOException e) {
+ throw new BuildException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ PreProcessor processor = new PreProcessor();
+ processor.setSymbols("ex2");
+ String string = processor.preProcessFile(new File("c:\\eclipse3.1\\dev\\example.debug.core\\src\\example\\debug\\core\\launcher\\PDALaunchDelegate.java"), "//#");
+ //String string = processor.preProcessFile(new File("c:\\eclipse3.1\\dev\\example.debug.core\\plugin.xml"), null);
+ System.out.println(string);
+ }
+}

Back to the top