/* This file is part of tdepim. Copyright (c) 2004 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "printer.h" #include #include #include #include using namespace KODE; Printer::Printer() : mCreationWarning( false ), mGenerator( "libkode" ) { } Printer::Printer( const Style &style ) : mStyle( style ), mCreationWarning( false ), mGenerator( "libkode" ) { } void Printer::setCreationWarning( bool v ) { mCreationWarning = v; } void Printer::setGenerator( const TQString &g ) { mGenerator = g; } void Printer::setOutputDirectory( const TQString &o ) { mOutputDirectory = o; } void Printer::setSourceFile( const TQString &s ) { mSourceFile = s; } TQString Printer::functionSignature( const Function &f, const TQString &className, bool includeClassQualifier ) { TQString s; if ( f.isStatic() && !includeClassQualifier ) { s += "static "; } TQString ret = f.returnType(); if ( !ret.isEmpty() ) { s += ret; if ( ret.right( 1 ) != "*" && ret.right( 1 ) != "&" ) { s += " "; } } if ( includeClassQualifier ) { s += mStyle.className( className ) + "::"; } if ( className == f.name() ) { // Constructor s += mStyle.className( f.name() ); } else { s += f.name(); } s += "("; if ( !f.arguments().isEmpty() ) { s += " " + f.arguments().join( ", " ) + " "; } s += ")"; if ( f.isConst() ) s += " const"; return s; } TQString Printer::creationWarning() { // Create warning about generated file TQString str = "// This file is generated by " + mGenerator; if ( !mSourceFile.isEmpty() ) { str += " from " + mSourceFile; } str += ".\n"; str += "// All changes you do to this file will be lost."; return str; } TQString Printer::licenseHeader( const File &file ) { Code code; code += "/*"; code.setIndent( 4 ); code += "This file is part of " + file.project() + "."; code.newLine(); TQStringList copyrights = file.copyrightStrings(); if ( !copyrights.isEmpty() ) { code.addBlock( copyrights.join( "\n" ) ); code.newLine(); } code.addBlock( file.license().text() ); code.setIndent( 0 ); code += "*/"; return code.text(); } Code Printer::functionHeaders( const Function::List &functions, const TQString &className, int access ) { bool needNewLine = false; bool hasAccess = false; Code code; Function::List::ConstIterator it; for( it = functions.begin(); it != functions.end(); ++it ) { Function f = *it; if ( f.access() == access ) { if ( !hasAccess ) { code += f.accessAsString() + ":"; hasAccess = true; } code.indent(); if ( !(*it).docs().isEmpty() ) { code += "/**"; code.indent(); code.addFormattedText( (*it).docs() ); code.unindent(); code += "*/"; } code += functionSignature( *it, className ) + ";"; code.unindent(); needNewLine = true; } } if ( needNewLine ) code.newLine(); return code; } TQString Printer::classHeader( const Class &c ) { Code code; if ( !c.docs().isEmpty() ) { code += "/**"; code.indent(); code.addFormattedText( c.docs() ); code.unindent(); code += "*/"; } TQString txt = "class " + mStyle.className( c.name() ); Class::List baseClasses = c.baseClasses(); if ( !baseClasses.isEmpty() ) { txt += " : "; Class::List::ConstIterator it; for( it = baseClasses.begin(); it != baseClasses.end(); ++it ) { Class bc = *it; if ( it != baseClasses.begin() ) txt +=", "; txt += "public "; if ( !bc.nameSpace().isEmpty() ) txt += bc.nameSpace() + "::"; txt += bc.name(); } } code += txt; code += "{"; code.indent(); if ( c.isTQObject() ) { code += "Q_OBJECT"; code.newLine(); code += ""; code.newLine(); } Function::List functions = c.functions(); Typedef::List typedefs = c.typedefs(); if ( typedefs.count() > 0 ) { code += "public:"; code.indent(); Typedef::List::ConstIterator it; for( it = typedefs.begin(); it != typedefs.end(); ++it ) { code += (*it).declaration(); } code.unindent(); code.newLine(); } Enum::List enums = c.enums(); if ( enums.count() > 0 ) { code += "public:"; code.indent(); Enum::List::ConstIterator it; for( it = enums.begin(); it != enums.end(); ++it ) { code += (*it).declaration(); } code.unindent(); code.newLine(); } code.addBlock( functionHeaders( functions, c.name(), Function::Public ) ); code.addBlock( functionHeaders( functions, c.name(), Function::Public | Function::Slot ) ); code.addBlock( functionHeaders( functions, c.name(), Function::Signal ) ); code.addBlock( functionHeaders( functions, c.name(), Function::Protected ) ); code.addBlock( functionHeaders( functions, c.name(), Function::Protected | Function::Slot ) ); code.addBlock( functionHeaders( functions, c.name(), Function::Private ) ); code.addBlock( functionHeaders( functions, c.name(), Function::Private | Function::Slot ) ); if ( !c.memberVariables().isEmpty() ) { Function::List::ConstIterator it; for( it = functions.begin(); it != functions.end(); ++it ) { if ( (*it).access() == Function::Private ) break; } if ( it == functions.end() ) code += "private:"; code.indent(); MemberVariable::List variables = c.memberVariables(); MemberVariable::List::ConstIterator it2; for( it2 = variables.begin(); it2 != variables.end(); ++it2 ) { MemberVariable v = *it2; TQString decl; if ( v.isStatic() ) decl += "static "; decl += v.type(); if ( v.type().right( 1 ) != "*" && v.type().right( 1 ) != "&" ) { decl += " "; } decl += v.name() + ";"; code += decl; } } code.setIndent( 0 ); code += "};"; return code.text(); } TQString Printer::classImplementation( const Class &c ) { Code code; bool needNewLine = false; MemberVariable::List vars = c.memberVariables(); MemberVariable::List::ConstIterator itV; for( itV = vars.begin(); itV != vars.end(); ++itV ) { MemberVariable v = *itV; if ( !v.isStatic() ) continue; code += v.type() + c.name() + "::" + v.name() + " = " + v.initializer() + ";"; needNewLine = true; } if ( needNewLine ) code.newLine(); Function::List functions = c.functions(); Function::List::ConstIterator it; for( it = functions.begin(); it != functions.end(); ++it ) { Function f = *it; // Omit signals if ( f.access() == Function::Signal ) continue; code += functionSignature( f, c.name(), true ); if ( !f.initializers().isEmpty() ) { code += ": " + f.initializers().join( ", " ); } code += "{"; code.addBlock( f.body(), 2 ); code += "}"; code += ""; } if ( c.isTQObject() ) { code.newLine(); code += "#include \"" + c.name().lower() + ".moc\""; } return code.text(); } void Printer::printHeader( const File &f ) { Code out; if ( mCreationWarning ) out += creationWarning(); out.addBlock( licenseHeader( f ) ); // Create include guard TQString className = f.filename(); className.replace( "-", "_" ); TQString includeGuard; if ( !f.nameSpace().isEmpty() ) includeGuard += f.nameSpace().upper() + "_"; includeGuard += className.upper() + "_H"; out += "#ifndef " + includeGuard; out += "#define " + includeGuard; out.newLine(); // Create includes TQStringList processed; Class::List classes = f.classes(); Class::List::ConstIterator it; for( it = classes.begin(); it != classes.end(); ++it ) { TQStringList includes = (*it).headerIncludes(); TQStringList::ConstIterator it2; for( it2 = includes.begin(); it2 != includes.end(); ++it2 ) { if ( processed.find( *it2 ) == processed.end() ) { out += "#include <" + *it2 + ">"; processed.append( *it2 ); } } } if ( !processed.isEmpty() ) out.newLine(); // Create forward declarations processed.clear(); for( it = classes.begin(); it != classes.end(); ++it ) { TQStringList decls = (*it).forwardDeclarations(); TQStringList::ConstIterator it2; for( it2 = decls.begin(); it2 != decls.end(); ++it2 ) { if ( processed.find( *it2 ) == processed.end() ) { out += "class " + *it2 + ";"; processed.append( *it2 ); } } } if ( !processed.isEmpty() ) out.newLine(); if ( !f.nameSpace().isEmpty() ) { out += "namespace " + f.nameSpace() + " {"; out.newLine(); } // Create content for( it = classes.begin(); it != classes.end(); ++it ) { out.addBlock( classHeader( *it ) ); out.newLine(); } if ( !f.nameSpace().isEmpty() ) { out += "}"; out.newLine(); } // Finish file out += "#endif"; // Print to file TQString filename = f.filename() + ".h"; if ( !mOutputDirectory.isEmpty() ) filename.prepend( mOutputDirectory + "/" ); KSaveFile::backupFile( filename, TQString(), ".backup" ); TQFile header( filename ); if ( !header.open( IO_WriteOnly ) ) { kdError() << "Can't open '" << filename << "' for writing." << endl; return; } TQTextStream h( &header ); h << out.text(); header.close(); } void Printer::printImplementation( const File &f, bool createHeaderInclude ) { Code out; if ( mCreationWarning ) out += creationWarning(); out.addBlock( licenseHeader( f ) ); out.newLine(); // Create includes if ( createHeaderInclude ) { out += "#include \"" + f.filename() + ".h\""; out.newLine(); } TQStringList includes = f.includes(); TQStringList::ConstIterator it2; for( it2 = includes.begin(); it2 != includes.end(); ++it2 ) { out += "#include <" + *it2 + ">"; } if ( !includes.isEmpty() ) out.newLine(); // Create class includes TQStringList processed; Class::List classes = f.classes(); Class::List::ConstIterator it; for( it = classes.begin(); it != classes.end(); ++it ) { TQStringList includes = (*it).includes(); TQStringList::ConstIterator it2; for( it2 = includes.begin(); it2 != includes.end(); ++it2 ) { if ( processed.find( *it2 ) == processed.end() ) { out += "#include <" + *it2 + ">"; processed.append( *it2 ); } } } if ( !processed.isEmpty() ) out.newLine(); if ( !f.nameSpace().isEmpty() ) { out += "using namespace " + f.nameSpace() + ";"; out.newLine(); } // 'extern "C"' declarations TQStringList externCDeclarations = f.externCDeclarations(); if ( !externCDeclarations.isEmpty() ) { out += "extern \"C\" {"; TQStringList::ConstIterator it; for( it = externCDeclarations.begin(); it != externCDeclarations.end(); ++it ) { out += *it + ";"; } out += "}"; out.newLine(); } // File variables Variable::List vars = f.fileVariables(); Variable::List::ConstIterator itV; for( itV = vars.begin(); itV != vars.end(); ++itV ) { Variable v = *itV; TQString str; if ( v.isStatic() ) str += "static "; str += v.type() + " " + v.name() + ";"; out += str; } if ( !vars.isEmpty() ) out.newLine(); // File code if ( !f.fileCode().isEmpty() ) { out += f.fileCode(); out.newLine(); } // File functions Function::List funcs = f.fileFunctions(); Function::List::ConstIterator itF; for( itF = funcs.begin(); itF != funcs.end(); ++itF ) { Function f = *itF; out += functionSignature( f ); out += "{"; out.addBlock( f.body(), 2 ); out += "}"; out.newLine(); } // Classes for( it = classes.begin(); it != classes.end(); ++it ) { TQString str = classImplementation( *it ); if ( !str.isEmpty() ) out += classImplementation( *it ); } // Print to file TQString filename = f.filename() + ".cpp"; if ( !mOutputDirectory.isEmpty() ) filename.prepend( mOutputDirectory + "/" ); KSaveFile::backupFile( filename, TQString(), ".backup" ); TQFile implementation( filename ); if ( !implementation.open( IO_WriteOnly ) ) { kdError() << "Can't open '" << filename << "' for writing." << endl; return; } TQTextStream h( &implementation ); h << out.text(); implementation.close(); } void Printer::printAutoMakefile( const AutoMakefile &am ) { TQString filename = "Makefile.am"; if ( !mOutputDirectory.isEmpty() ) filename.prepend( mOutputDirectory + "/" ); KSaveFile::backupFile( filename, TQString(), ".backup" ); TQFile file( filename ); if ( !file.open( IO_WriteOnly ) ) { kdError() << "Can't open '" << filename << "' for writing." << endl; return; } TQTextStream ts( &file ); ts << am.text(); }