/* * Copyright 2010 Pablo Arrighi, Alex Concha, Miguel Lezama for version 1. * Copyright 2013 Pablo Arrighi, Miguel Lezama, Kevin Mazet for version 2. * * This file is part of GOOL. * * GOOL is free software: you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation, version 3. * * GOOL 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 General Public License version 3 for more details. * * You should have received a copy of the GNU General Public License along with GOOL, * in the file COPYING.txt. If not, see <http://www.gnu.org/licenses/>. */ /** * Creates C++ files during the C++ generation process */ package gool.generator.cpp; import gool.ast.core.ClassDef; import gool.generator.common.CodePrinter; import gool.generator.common.GeneratorMatcher; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.List; import logger.Log; import org.apache.commons.lang.StringUtils; /** * Provides the basic functionality to generate C++ code from a list of GOOL * classes. */ public class CppCodePrinter extends CodePrinter { private static final String TEMPLATE_DIR = "gool/generator/cpp/templates/"; private void createFinallyInclude(File outputDir) { FileOutputStream goolHelperOut; byte[] buffer = new byte[1024]; int noOfBytes; // Helpers to create by copying the resource List<String> goolHelperIn = new ArrayList<String>(); goolHelperIn.add("finally.h"); if (!outputDir.isDirectory() && !outputDir.mkdirs()) { Log.e(String.format("Impossible to create the directory '%s'", outputDir)); } else { // Print finally for (String in : goolHelperIn) { InputStream helper; try { helper = CppPlatform.class.getResource(in).openStream(); goolHelperOut = new FileOutputStream(outputDir + "/" + in); while ((noOfBytes = helper.read(buffer)) != -1) { goolHelperOut.write(buffer, 0, noOfBytes); } goolHelperOut.close(); helper.close(); } catch (IOException e) { Log.e(String.format("Impossible to create the file '%s'", in)); } } } } public CppCodePrinter(File outputDir, Collection<File> myF) { super(new CppGenerator(), outputDir, myF); createFinallyInclude(outputDir); } @Override public String getTemplateDir() { return TEMPLATE_DIR; } @Override public List<File> print(ClassDef pclass) throws FileNotFoundException { // GOOL library classes are printed in a different manner if (pclass.isGoolLibraryClass()) { return printGoolLibraryClass(pclass); } /* * In C++ the parent class and the interfaces are used in the same * statement. Example: class Foo : public ClassBar1, InterfaceBar2 ... * {} */ if (pclass.getParentClass() != null) { pclass.getInterfaces().add(0, pclass.getParentClass()); } String headerFile = processTemplate("header.vm", pclass); PrintWriter writer; File dir = new File(getOutputDir().getAbsolutePath(), StringUtils.replace(pclass.getPackageName(), ".", File.separator)); dir.mkdirs(); File classFile = new File(dir, pclass.getName() + ".h"); writer = new PrintWriter(classFile); writer.println(headerFile); writer.close(); /* * Only generate header files if this element is an interface or an * enumeration. */ if (pclass.isEnum() || pclass.isInterface()) { List<File> r = new ArrayList<File>(); r.add(classFile); return r; } else { return super.print(pclass); } } @Override public List<File> printGoolLibraryClass(ClassDef pclass) throws FileNotFoundException { String goolClass = pclass.getPackageName() + "." + pclass.getName(); ArrayList<String> goolClassImplems = new ArrayList<String>(); for (String Import : GeneratorMatcher.matchImports(goolClass)) if (Import.startsWith("+")) goolClassImplems.add(Import.substring(1)); List<File> result = new ArrayList<File>(); for (String goolClassImplem : goolClassImplems) { String goolClassImplemName = goolClassImplem .substring(goolClassImplem.lastIndexOf(".") + 1); String goolClassImplemPackage = goolClassImplem.substring(0, goolClassImplem.lastIndexOf(".")); String implemFileName = goolClassImplemName+".cpp"; String headerFileName = goolClassImplemName+".h"; String codeImplem = GeneratorMatcher.matchGoolClassImplementation( goolClass, implemFileName); String codeHeader = GeneratorMatcher.matchGoolClassImplementation( goolClass, headerFileName); File dir = new File(getOutputDir().getAbsolutePath(), StringUtils.replace(goolClassImplemPackage, ".", File.separator)); dir.mkdirs(); File implemFile = new File(dir, implemFileName); File headerFile = new File(dir, headerFileName); //print implementation file PrintWriter writer = new PrintWriter(implemFile); writer.println(codeImplem); writer.close(); //print header file writer = new PrintWriter(headerFile); writer.println(codeHeader); writer.close(); } printedClasses.add(pclass); return result; } @Override public String getFileName(String className) { return className + ".cpp"; } }