001/* 002 * Anarres C Preprocessor 003 * Copyright (c) 2007-2015, Shevek 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 014 * or implied. See the License for the specific language governing 015 * permissions and limitations under the License. 016 */ 017package org.anarres.cpp; 018 019import java.io.File; 020import java.io.FileWriter; 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.Enumeration; 025import java.util.List; 026import org.apache.tools.ant.BuildException; 027import org.apache.tools.ant.taskdefs.Copy; 028import org.apache.tools.ant.types.Path; 029 030/** 031 * An ant task for jcpp. 032 */ 033public class CppTask extends Copy { 034 035 private class Listener extends DefaultPreprocessorListener { 036 037 @Override 038 protected void print(String msg) { 039 log(msg); 040 } 041 } 042 043 public static class Macro { 044 045 private String name; 046 private String value; 047 048 public void setName(String name) { 049 this.name = name; 050 } 051 052 public String getName() { 053 return name; 054 } 055 056 public void setValue(String value) { 057 this.value = value; 058 } 059 060 public String getValue() { 061 return value; 062 } 063 } 064 065 private final Listener listener = new Listener(); 066 private final List<Macro> macros = new ArrayList<Macro>(); 067 private Path systemincludepath; 068 private Path localincludepath; 069 070 public void addMacro(Macro macro) { 071 macros.add(macro); 072 } 073 074 public void addSystemincludepath(Path path) { 075 if (systemincludepath == null) 076 systemincludepath = new Path(getProject()); 077 systemincludepath.add(path); 078 } 079 080 public void addLocalincludepath(Path path) { 081 if (localincludepath == null) 082 localincludepath = new Path(getProject()); 083 localincludepath.add(path); 084 } 085 086 /* 087 public void execute() { 088 FileWriter writer = null; 089 try { 090 if (input == null) 091 throw new BuildException("Input not specified"); 092 if (output == null) 093 throw new BuildException("Output not specified"); 094 cpp.addInput(this.input); 095 writer = new FileWriter(this.output); 096 for (;;) { 097 Token tok = cpp.token(); 098 if (tok != null && tok.getType() == Token.EOF) 099 break; 100 writer.write(tok.getText()); 101 } 102 } 103 catch (Exception e) { 104 throw new BuildException(e); 105 } 106 finally { 107 if (writer != null) { 108 try { 109 writer.close(); 110 } 111 catch (IOException e) { 112 } 113 } 114 } 115 } 116 */ 117 private void preprocess(File input, File output) throws Exception { 118 if (input == null) 119 throw new BuildException("Input not specified"); 120 if (output == null) 121 throw new BuildException("Output not specified"); 122 123 Preprocessor cpp = new Preprocessor(); 124 cpp.setListener(listener); 125 for (Macro macro : macros) 126 cpp.addMacro(macro.getName(), macro.getValue()); 127 if (systemincludepath != null) 128 cpp.setSystemIncludePath(Arrays.asList(systemincludepath.list())); 129 if (localincludepath != null) 130 cpp.setQuoteIncludePath(Arrays.asList(localincludepath.list())); 131 132 File dir = output.getParentFile(); 133 if (!dir.exists()) { 134 if (!dir.mkdirs()) 135 throw new BuildException("Failed to make parent directory " + dir); 136 } else if (!dir.isDirectory()) { 137 throw new BuildException("Parent directory of output file " + output + " exists, but is not a directory."); 138 } 139 FileWriter writer = null; 140 try { 141 cpp.addInput(input); 142 writer = new FileWriter(output); 143 for (;;) { 144 Token tok = cpp.token(); 145 if (tok == null) 146 break; 147 if (tok.getType() == Token.EOF) 148 break; 149 writer.write(tok.getText()); 150 } 151 } finally { 152 if (writer != null) { 153 try { 154 writer.close(); 155 } catch (IOException e) { 156 } 157 } 158 } 159 } 160 161 @Override 162 protected void doFileOperations() { 163 if (fileCopyMap.size() > 0) { 164 log("Copying " + fileCopyMap.size() 165 + " file" + (fileCopyMap.size() == 1 ? "" : "s") 166 + " to " + destDir.getAbsolutePath()); 167 168 Enumeration<String> e = fileCopyMap.keys(); 169 170 while (e.hasMoreElements()) { 171 String fromFile = e.nextElement(); 172 String[] toFiles = (String[]) fileCopyMap.get(fromFile); 173 174 for (String toFile : toFiles) { 175 if (fromFile.equals(toFile)) { 176 log("Skipping self-copy of " + fromFile, verbosity); 177 continue; 178 } 179 180 try { 181 log("Copying " + fromFile + " to " + toFile, verbosity); 182 183 /* 184 FilterSetCollection executionFilters 185 = new FilterSetCollection(); 186 if (filtering) { 187 executionFilters 188 .addFilterSet(getProject().getGlobalFilterSet()); 189 } 190 for (Enumeration filterEnum = getFilterSets().elements(); 191 filterEnum.hasMoreElements();) { 192 executionFilters 193 .addFilterSet((FilterSet) filterEnum.nextElement()); 194 } 195 */ 196 File srcFile = new File(fromFile); 197 File dstFile = new File(toFile); 198 preprocess(srcFile, dstFile); 199 } catch (Exception ioe) { 200 // ioe.printStackTrace(); 201 String msg = "Failed to copy " + fromFile + " to " + toFile 202 + " due to " + ioe.getMessage(); 203 File targetFile = new File(toFile); 204 if (targetFile.exists() && !targetFile.delete()) { 205 msg += " and I couldn't delete the corrupt " + toFile; 206 } 207 throw new BuildException(msg, ioe, getLocation()); 208 } 209 } 210 } 211 } 212 213 } 214 215}