diff options
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.java | 292 |
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); + } +} |