You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1711 lines
60 KiB
1711 lines
60 KiB
/***************************************************************************
|
|
* Copyright (C) 2006 by Andreas Pakulat *
|
|
* apaku@gmx.de *
|
|
* *
|
|
* This program 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; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "scope.h"
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tqfile.h>
|
|
#include <tqfileinfo.h>
|
|
#include <tqdir.h>
|
|
#include <tqpair.h>
|
|
#include <qmakedriver.h>
|
|
#include <tqregexp.h>
|
|
#include <tqtimer.h>
|
|
|
|
#include <kdirwatch.h>
|
|
|
|
#include <kmessagebox.h>
|
|
#include <klocale.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "urlutil.h"
|
|
#include "trollprojectpart.h"
|
|
#include "qmakedefaultopts.h"
|
|
|
|
const TQStringList Scope::KnownVariables = TQStringList() << "QT" << "CONFIG" << "TEMPLATE" << "SUBDIRS" << "VERSION" << "LIBS" << "target.path" << "INSTALLS" << "MAKEFILE" << "TARGETDEPS" << "INCLUDEPATH" << "TARGET" << "DESTDIR" << "DEFINES" << "QMAKE_CXXFLAGS_DEBUG" << "QMAKE_CXXFLAGS_RELEASE" << "OBJECTS_DIR" << "UI_DIR" << "QMOC_DIR" << "IDL_COMPILER" << "IDL_OPTIONS" << "RCC_DIR" << "IDLS" << "RESOURCES" << "IMAGES" << "LEXSOURCES" << "DISTFILES" << "YACCSOURCES" << "TRANSLATIONS" << "HEADERS" << "SOURCES" << "INTERFACES" << "FORMS" ;
|
|
|
|
const TQStringList Scope::KnownConfigValues = TQStringList() << "debug" << "release" << "debug_and_release" << "warn_on" << "warn_off" << "staticlib" << "dll" << "plugin" << "designer" << "create_pkgconf" << "create_libtool" << "qt" << "console" << "windows" << "x11" << "thread" << "exceptions" << "stl" << "rtti" << "opengl" << "thread" << "ordered" << "precompile_header" << "qtestlib" << "uitools" << "dbus" << "assistant" << "build_all" << "help";
|
|
|
|
Scope::Scope( const TQMap<TQString, TQString>& env, const TQString &filename, TrollProjectPart* part )
|
|
: m_root( 0 ), m_incast( 0 ), m_parent( 0 ), m_num(0), m_isEnabled( true ), m_part(part), m_defaultopts(0), m_environment( env )
|
|
{
|
|
if ( !loadFromFile( filename ) )
|
|
{
|
|
if( !TQFileInfo( filename ).exists() )
|
|
{
|
|
m_root = new TQMake::ProjectAST();
|
|
m_root->setFileName( filename );
|
|
}else
|
|
{
|
|
delete m_root;
|
|
m_root = 0;
|
|
}
|
|
}
|
|
loadDefaultOpts();
|
|
if( m_root )
|
|
{
|
|
m_part->dirWatch()->addFile(filename);
|
|
}
|
|
init();
|
|
}
|
|
|
|
Scope::~Scope()
|
|
{
|
|
TQMap<unsigned int, Scope*>::iterator it;
|
|
for ( it = m_scopes.begin() ; it != m_scopes.end() ; ++it )
|
|
{
|
|
Scope* s = it.data();
|
|
delete s;
|
|
}
|
|
m_scopes.clear();
|
|
|
|
m_customVariables.clear();
|
|
if ( m_root && m_root->isProject() && !m_incast )
|
|
{
|
|
delete m_root;
|
|
m_root = 0;
|
|
delete m_defaultopts;
|
|
m_defaultopts = 0;
|
|
}
|
|
|
|
}
|
|
|
|
// Simple/Function Scopes
|
|
Scope::Scope( const TQMap<TQString, TQString>& env, unsigned int num, Scope* parent, TQMake::ProjectAST* scope,
|
|
TQMakeDefaultOpts* defaultopts, TrollProjectPart* part )
|
|
: m_root( scope ), m_incast( 0 ), m_parent( parent ), m_num(num), m_isEnabled( true ),
|
|
m_part(part), m_defaultopts(defaultopts), m_environment( env )
|
|
{
|
|
init();
|
|
}
|
|
|
|
//Subdirs
|
|
Scope::Scope( const TQMap<TQString, TQString>& env, unsigned int num, Scope* parent, const TQString& filename,
|
|
TrollProjectPart* part, bool isEnabled )
|
|
: m_root( 0 ), m_incast( 0 ), m_parent( parent ), m_num(num), m_isEnabled( isEnabled ),
|
|
m_part(part), m_defaultopts(0), m_environment( env )
|
|
{
|
|
if ( !loadFromFile( filename ) )
|
|
{
|
|
if( !TQFileInfo( filename ).exists() && TQFileInfo( TQFileInfo( filename ).dirPath( true ) ).exists() )
|
|
{
|
|
m_root = new TQMake::ProjectAST();
|
|
m_root->setFileName( filename );
|
|
}else
|
|
{
|
|
delete m_root;
|
|
m_root = 0;
|
|
m_isEnabled = false;
|
|
}
|
|
}
|
|
loadDefaultOpts();
|
|
if( m_root )
|
|
m_part->dirWatch()->addFile(filename);
|
|
init();
|
|
}
|
|
|
|
//Include Scope
|
|
Scope::Scope( const TQMap<TQString, TQString>& env, unsigned int num, Scope* parent, TQMake::IncludeAST* incast, const TQString& path,
|
|
const TQString& incfile, TQMakeDefaultOpts* defaultopts, TrollProjectPart* part )
|
|
: m_root( 0 ), m_incast( incast ), m_parent( parent ), m_num(num), m_isEnabled( true ),
|
|
m_part(part), m_defaultopts(defaultopts), m_environment( env )
|
|
{
|
|
TQString absfilename;
|
|
TQString tmp = incfile.stripWhiteSpace();
|
|
if( tmp.contains(")" ) )
|
|
tmp = tmp.mid(0, tmp.find(")") );
|
|
|
|
if( tmp.startsWith( "\"" ) )
|
|
tmp = tmp.mid( 1, tmp.length()-2 );
|
|
|
|
if( TQFileInfo(tmp).isRelative() )
|
|
{
|
|
absfilename = TQDir::cleanDirPath( path + TQString( TQChar( TQDir::separator() ) ) + tmp );
|
|
}else
|
|
absfilename = TQDir::cleanDirPath( tmp );
|
|
if ( !loadFromFile( absfilename ) )
|
|
{
|
|
if( !TQFileInfo( absfilename ).exists() && TQFileInfo( TQFileInfo( absfilename ).dirPath( true ) ).exists() )
|
|
{
|
|
m_root = new TQMake::ProjectAST();
|
|
m_root->setFileName( absfilename );
|
|
}else
|
|
{
|
|
delete m_root;
|
|
m_root = 0;
|
|
m_isEnabled = false;
|
|
}
|
|
}
|
|
if( m_root )
|
|
m_part->dirWatch()->addFile( m_root->fileName() );
|
|
init();
|
|
}
|
|
|
|
bool Scope::loadFromFile( const TQString& filename )
|
|
{
|
|
if ( !TQFileInfo(filename).exists() || TQMake::Driver::parseFile( filename, &m_root, 0 ) != 0 )
|
|
{
|
|
kdDebug( 9024 ) << "Couldn't parse project: " << filename << endl;
|
|
if( DomUtil::readBoolEntry( *m_part->projectDom(),
|
|
"/kdevtrollproject/qmake/showParseErrors", true ) )
|
|
{
|
|
KMessageBox::error( 0, i18n( "Could not parse project file: %1" ).tqarg( filename ),
|
|
i18n( "Could not parse project file" ) );
|
|
}
|
|
m_root = 0;
|
|
return false;
|
|
}
|
|
// init();
|
|
return true;
|
|
}
|
|
|
|
void Scope::saveToFile() const
|
|
{
|
|
if ( !m_root )
|
|
return ;
|
|
|
|
if ( scopeType() != ProjectScope && scopeType() != IncludeScope )
|
|
{
|
|
m_parent->saveToFile();
|
|
return;
|
|
}
|
|
|
|
TQString filename;
|
|
if ( scopeType() == ProjectScope )
|
|
filename = m_root->fileName() ;
|
|
else if ( scopeType() == IncludeScope )
|
|
filename = m_parent->projectDir() + TQString( TQChar( TQDir::separator() ) ) + m_incast->projectName;
|
|
if ( filename.isEmpty() )
|
|
return ;
|
|
m_part->dirWatch()->stopScan();
|
|
TQFile file( filename );
|
|
if ( file.open( IO_WriteOnly ) )
|
|
{
|
|
|
|
TQTextStream out( &file );
|
|
TQString astbuffer;
|
|
m_root->writeBack( astbuffer );
|
|
out << astbuffer;
|
|
file.close();
|
|
}else
|
|
{
|
|
KMessageBox::error( 0, i18n( "Could not write project file: %1" ).tqarg( filename ),
|
|
i18n( "Could not write project file" ) );
|
|
}
|
|
#ifdef DEBUG
|
|
Scope::PrintAST pa;
|
|
pa.processProject(m_root);
|
|
#endif
|
|
m_part->dirWatch()->startScan();
|
|
}
|
|
|
|
void Scope::addToPlusOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if ( !m_root )
|
|
return ;
|
|
|
|
updateVariable( variable, "+=", values, false );
|
|
}
|
|
|
|
void Scope::removeFromPlusOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if ( !m_root )
|
|
return ;
|
|
|
|
updateVariable( variable, "+=", values, true );
|
|
}
|
|
|
|
|
|
void Scope::addToMinusOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if ( !m_root )
|
|
return ;
|
|
|
|
updateVariable( variable, "-=", values, false );
|
|
}
|
|
|
|
void Scope::removeFromMinusOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if ( !m_root )
|
|
return ;
|
|
|
|
updateVariable( variable, "-=", values, true );
|
|
}
|
|
|
|
void Scope::addToEqualOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if ( !m_root )
|
|
return ;
|
|
|
|
updateVariable( variable, "=", values, false );
|
|
}
|
|
|
|
void Scope::removeFromEqualOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if ( !m_root )
|
|
return ;
|
|
|
|
updateVariable( variable, "=", values, true );
|
|
}
|
|
|
|
void Scope::setPlusOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if( !m_root || Scope::listsEqual(values, variableValuesForOp(variable, "+=") ) )
|
|
return;
|
|
|
|
updateVariable( variable, "+=", variableValuesForOp( variable, "+=" ), true );
|
|
updateVariable( variable, "+=", values, false );
|
|
}
|
|
|
|
void Scope::setEqualOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if( !m_root || Scope::listsEqual(values, variableValuesForOp(variable, "=") ) )
|
|
return;
|
|
|
|
updateVariable( variable, "=", variableValuesForOp( variable, "=" ), true );
|
|
updateVariable( variable, "=", values, false );
|
|
}
|
|
|
|
void Scope::setMinusOp( const TQString& variable, const TQStringList& values )
|
|
{
|
|
if( !m_root || Scope::listsEqual(values, variableValuesForOp(variable, "-=") ) )
|
|
return;
|
|
|
|
updateVariable( variable, "-=", variableValuesForOp( variable, "-=" ), true );
|
|
updateVariable( variable, "-=", values, false );
|
|
}
|
|
|
|
TQStringList Scope::variableValuesForOp( const TQString& variable , const TQString& op ) const
|
|
{
|
|
TQStringList result;
|
|
|
|
if( !m_root )
|
|
return result;
|
|
|
|
TQValueList<TQMake::AST*>::const_iterator it;
|
|
for ( it = m_root->m_tqchildren.begin(); it != m_root->m_tqchildren.end(); ++it )
|
|
{
|
|
TQMake::AST* ast = *it;
|
|
if ( ast->nodeType() == TQMake::AST::AssignmentAST )
|
|
{
|
|
TQMake::AssignmentAST * assign = static_cast<TQMake::AssignmentAST*>( ast );
|
|
if ( assign->scopedID == variable && assign->op == op )
|
|
{
|
|
result += assign->values;
|
|
}
|
|
}
|
|
}
|
|
result = cleanStringList(result);
|
|
return result;
|
|
}
|
|
|
|
TQStringList Scope::variableValues( const TQString& variable, bool checkIncParent, bool fetchFromParent, bool evaluateSubScopes )
|
|
{
|
|
TQStringList result;
|
|
|
|
if ( !m_root )
|
|
return result;
|
|
|
|
if( m_varCache.contains( variable ) && fetchFromParent && ( checkIncParent || scopeType() != Scope::IncludeScope ) )
|
|
{
|
|
return m_varCache[variable];
|
|
}
|
|
|
|
calcValuesFromStatements( variable, result, checkIncParent, 0, fetchFromParent, true, evaluateSubScopes );
|
|
result = cleanStringList(result);
|
|
if( ( scopeType() != Scope::IncludeScope || checkIncParent ) && fetchFromParent )
|
|
{
|
|
m_varCache[ variable ] = result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Scope::calcValuesFromStatements( const TQString& variable, TQStringList& result, bool checkIncParent, TQMake::AST* stopHere, bool fetchFromParent, bool setDefault, bool evaluateSubScopes ) const
|
|
{
|
|
if( !m_root )
|
|
return;
|
|
|
|
/* For variables that we don't know and which are not QT/CONFIG find the default value */
|
|
if( setDefault && m_defaultopts
|
|
&& m_defaultopts->variables().findIndex(variable) != -1
|
|
&& ( variable == "TEMPLATE" || variable == "QT" || KnownVariables.findIndex(variable) == -1 || variable == "CONFIG" ) )
|
|
{
|
|
result = m_defaultopts->variableValues(variable);
|
|
}
|
|
|
|
if ( ( scopeType() == FunctionScope || scopeType() == SimpleScope ) && fetchFromParent )
|
|
{
|
|
m_parent->calcValuesFromStatements( variable, result, checkIncParent, this->m_root, fetchFromParent, setDefault, evaluateSubScopes );
|
|
}
|
|
else if ( scopeType() == IncludeScope && checkIncParent && fetchFromParent )
|
|
{
|
|
m_parent->calcValuesFromStatements( variable, result, true, this->m_incast, fetchFromParent, setDefault, evaluateSubScopes );
|
|
}
|
|
|
|
TQValueList<TQMake::AST*>::const_iterator it;
|
|
for ( it = m_root->m_tqchildren.begin(); it != m_root->m_tqchildren.end(); ++it )
|
|
{
|
|
if ( stopHere && *it == stopHere )
|
|
return ;
|
|
TQMake::AST* ast = *it;
|
|
if ( ast->nodeType() == TQMake::AST::AssignmentAST )
|
|
{
|
|
TQMake::AssignmentAST * assign = static_cast<TQMake::AssignmentAST*>( ast );
|
|
if ( assign->scopedID == variable )
|
|
{
|
|
if ( assign->op == "=" )
|
|
{
|
|
result = assign->values;
|
|
}
|
|
else if ( assign->op == "+=" )
|
|
{
|
|
for ( TQStringList::const_iterator sit = assign->values.begin(); sit != assign->values.end() ; ++sit )
|
|
{
|
|
if ( result.findIndex( *sit ) == -1 )
|
|
result.append( *sit );
|
|
}
|
|
}
|
|
else if ( assign->op == "-=" )
|
|
{
|
|
for ( TQStringList::const_iterator sit = assign->values.begin(); sit != assign->values.end() ; ++sit )
|
|
{
|
|
if ( result.findIndex( *sit ) != -1 )
|
|
result.remove( *sit );
|
|
}
|
|
}
|
|
}
|
|
}else if( evaluateSubScopes )
|
|
{
|
|
if( ast->nodeType() == TQMake::AST::IncludeAST )
|
|
{
|
|
TQMake::IncludeAST* iast = static_cast<TQMake::IncludeAST*>(ast);
|
|
TQValueList<unsigned int> l = m_scopes.keys();
|
|
for( unsigned int i = 0; i < l.count(); ++i )
|
|
{
|
|
int num = l[ i ];
|
|
if( m_scopes.contains( num ) )
|
|
{
|
|
Scope* s = m_scopes[num];
|
|
if( s && s->scopeType() == IncludeScope && s->m_incast == iast )
|
|
{
|
|
s->calcValuesFromStatements( variable, result, false, 0, false, false, evaluateSubScopes );
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else if( ast->nodeType() == TQMake::AST::ProjectAST )
|
|
{
|
|
TQMake::ProjectAST* past = static_cast<TQMake::ProjectAST*>(ast);
|
|
if( past->isFunctionScope() || past->isScope() )
|
|
{
|
|
TQValueList<unsigned int> l = m_scopes.keys();
|
|
for( unsigned int i = 0; i < l.count(); ++i )
|
|
{
|
|
int num = l[ i ];
|
|
if( m_scopes.contains( num ) )
|
|
{
|
|
Scope* s = m_scopes[num];
|
|
if( s && s->m_root == past && s->m_root->scopedID == past->scopedID )
|
|
{
|
|
s->calcValuesFromStatements( variable, result, false, 0, false, false, evaluateSubScopes );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
result = cleanStringList( result );
|
|
return ;
|
|
}
|
|
|
|
Scope::ScopeType Scope::scopeType() const
|
|
{
|
|
if ( !m_root )
|
|
return InvalidScope;
|
|
else if ( m_incast )
|
|
return IncludeScope;
|
|
else if ( m_root->isProject() )
|
|
return ProjectScope;
|
|
else if ( m_root->isScope() )
|
|
return SimpleScope;
|
|
else if ( m_root->isFunctionScope() )
|
|
return FunctionScope;
|
|
return InvalidScope;
|
|
}
|
|
|
|
TQString Scope::scopeName() const
|
|
{
|
|
if ( !m_root )
|
|
return "";
|
|
if ( m_incast )
|
|
return "include<" + m_incast->projectName + ">";
|
|
else if ( m_root->isFunctionScope() )
|
|
return funcScopeKey( m_root );
|
|
else if ( m_root->isScope() )
|
|
return m_root->scopedID;
|
|
else if ( m_root->isProject() )
|
|
{
|
|
if( m_parent && TQDir::cleanDirPath( m_parent->projectDir() ) != TQDir::cleanDirPath( projectDir() ) )
|
|
{
|
|
return URLUtil::getRelativePath( m_parent->projectDir(), projectDir() );
|
|
}else if ( m_parent && TQDir::cleanDirPath( m_parent->projectDir() ) == TQDir::cleanDirPath( projectDir() ) )
|
|
{
|
|
return fileName();
|
|
}else
|
|
return TQFileInfo( projectDir() ).fileName() ;
|
|
}
|
|
return TQString();
|
|
}
|
|
|
|
TQString Scope::fileName() const
|
|
{
|
|
if( !m_root )
|
|
return "";
|
|
if ( m_incast )
|
|
return m_incast->projectName;
|
|
else if ( m_root->isProject() )
|
|
return TQFileInfo( m_root->fileName() ).fileName();
|
|
else
|
|
return m_parent->fileName();
|
|
}
|
|
|
|
Scope* Scope::createFunctionScope( const TQString& funcName, const TQString& args )
|
|
{
|
|
if ( !m_root )
|
|
return 0;
|
|
|
|
TQMake::ProjectAST* ast = new TQMake::ProjectAST( TQMake::ProjectAST::FunctionScope );
|
|
ast->scopedID = funcName;
|
|
ast->args = args;
|
|
ast->setDepth( m_root->depth() );
|
|
ast->addChildAST( new TQMake::NewLineAST() );
|
|
m_root->addChildAST( ast );
|
|
m_root->addChildAST( new TQMake::NewLineAST() );
|
|
Scope* funcScope = new Scope( m_environment, getNextScopeNum(), this, ast, m_defaultopts, m_part );
|
|
if( funcScope->scopeType() != Scope::InvalidScope )
|
|
{
|
|
m_scopes.insert( getNextScopeNum(), funcScope );
|
|
return funcScope;
|
|
}else
|
|
delete funcScope;
|
|
return 0;
|
|
}
|
|
|
|
Scope* Scope::createSimpleScope( const TQString& scopename )
|
|
{
|
|
if ( !m_root )
|
|
return 0;
|
|
|
|
TQMake::ProjectAST* ast = new TQMake::ProjectAST( TQMake::ProjectAST::Scope );
|
|
ast->scopedID = scopename;
|
|
ast->addChildAST( new TQMake::NewLineAST() );
|
|
ast->setDepth( m_root->depth() );
|
|
m_root->addChildAST( ast );
|
|
m_root->addChildAST( new TQMake::NewLineAST() );
|
|
/* We can't unconditionally add the scope name to CONFIG, scope might be win32 which may only be in CONFIG under windows.
|
|
if ( m_part->isTQt4Project() )
|
|
addToPlusOp( "CONFIG", TQStringList( scopename ) );
|
|
*/
|
|
Scope* simpleScope = new Scope( m_environment, getNextScopeNum(), this, ast, m_defaultopts, m_part );
|
|
|
|
if( simpleScope->scopeType() != Scope::InvalidScope )
|
|
{
|
|
m_scopes.insert( getNextScopeNum(), simpleScope );
|
|
return simpleScope;
|
|
}else
|
|
delete simpleScope;
|
|
return 0;
|
|
|
|
}
|
|
|
|
Scope* Scope::createIncludeScope( const TQString& includeFile, bool negate )
|
|
{
|
|
if ( !m_root )
|
|
return 0;
|
|
|
|
Scope* funcScope;
|
|
if ( negate )
|
|
{
|
|
funcScope = createFunctionScope( "!include", includeFile );
|
|
}
|
|
else
|
|
{
|
|
funcScope = createFunctionScope( "include", includeFile );
|
|
}
|
|
if( funcScope == 0 )
|
|
return 0;
|
|
|
|
TQMake::IncludeAST* ast = new TQMake::IncludeAST();
|
|
ast->setDepth( m_root->depth() );
|
|
ast->projectName = includeFile;
|
|
Scope* incScope = new Scope( m_environment, funcScope->getNextScopeNum(), funcScope, ast, projectDir(), resolveVariables( ast->projectName ), m_defaultopts, m_part );
|
|
if ( incScope->scopeType() != InvalidScope )
|
|
{
|
|
funcScope->m_root->addChildAST( ast );
|
|
funcScope->m_scopes.insert( funcScope->getNextScopeNum(), incScope );
|
|
return funcScope;
|
|
}
|
|
else
|
|
{
|
|
deleteFunctionScope( m_scopes.keys().last() );
|
|
delete incScope;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
Scope* Scope::createSubProject( const TQString& projname )
|
|
{
|
|
if( !m_root )
|
|
return 0;
|
|
|
|
if( variableValuesForOp( "SUBDIRS", "-=").findIndex( projname ) != -1 )
|
|
removeFromMinusOp( "SUBDIRS", projname );
|
|
|
|
TQString realprojname = resolveVariables(projname);
|
|
|
|
if( variableValuesForOp( "SUBDIRS", "-=").findIndex( realprojname ) != -1 )
|
|
removeFromMinusOp( "SUBDIRS", realprojname );
|
|
|
|
TQDir curdir( projectDir() );
|
|
|
|
if ( variableValues("TEMPLATE").findIndex( "subdirs" ) != -1 )
|
|
{
|
|
TQString filename;
|
|
if( !realprojname.endsWith(".pro") )
|
|
{
|
|
if ( !curdir.exists( realprojname ) )
|
|
if ( !curdir.mkdir( realprojname ) )
|
|
return 0;
|
|
curdir.cd( realprojname );
|
|
TQStringList entries = curdir.entryList("*.pro", TQDir::Files);
|
|
|
|
if ( !entries.isEmpty() && entries.findIndex( curdir.dirName()+".pro" ) == -1 )
|
|
filename = curdir.absPath() + TQString(TQChar(TQDir::separator()))+entries.first();
|
|
else
|
|
filename = curdir.absPath() + TQString(TQChar(TQDir::separator()))+curdir.dirName()+".pro";
|
|
}else
|
|
filename = curdir.absPath() + TQString(TQChar(TQDir::separator())) + realprojname;
|
|
|
|
kdDebug( 9024 ) << "Creating subproject with filename:" << filename << endl;
|
|
|
|
Scope* s = new Scope( m_environment, getNextScopeNum(), this, filename, m_part );
|
|
s->loadDefaultOpts();
|
|
if ( s->scopeType() != InvalidScope )
|
|
{
|
|
if( s->variableValues("TEMPLATE").isEmpty() )
|
|
s->setEqualOp("TEMPLATE", TQStringList("app"));
|
|
s->saveToFile();
|
|
addToPlusOp( "SUBDIRS", TQStringList( realprojname ) );
|
|
m_scopes.insert( getNextScopeNum(), s );
|
|
return s;
|
|
} else
|
|
{
|
|
delete s;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool Scope::deleteFunctionScope( unsigned int num )
|
|
{
|
|
if ( !m_root || !m_scopes.contains( num ) )
|
|
return false;
|
|
|
|
Scope* funcScope = m_scopes[ num ];
|
|
if ( funcScope )
|
|
{
|
|
TQMake::AST* ast = m_root->m_tqchildren[ m_root->m_tqchildren.findIndex( funcScope->m_root ) ];
|
|
if( !ast )
|
|
return false;
|
|
m_scopes.remove( num );
|
|
m_root->removeChildAST( funcScope->m_root );
|
|
delete funcScope;
|
|
delete ast;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Scope::deleteSimpleScope( unsigned int num )
|
|
{
|
|
if ( !m_root || !m_scopes.contains( num ) )
|
|
return false;
|
|
|
|
Scope* simpleScope = m_scopes[ num ];
|
|
if ( simpleScope )
|
|
{
|
|
TQMake::AST* ast = m_root->m_tqchildren[ m_root->m_tqchildren.findIndex( simpleScope->m_root ) ];
|
|
if( !ast )
|
|
return false;
|
|
m_scopes.remove( num );
|
|
removeFromPlusOp( "CONFIG", simpleScope->m_root->scopedID );
|
|
m_root->removeChildAST( simpleScope->m_root );
|
|
delete simpleScope;
|
|
delete ast;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Scope::deleteIncludeScope( unsigned int num )
|
|
{
|
|
if ( !m_root || !m_scopes.contains( num ) )
|
|
return false;
|
|
|
|
Scope * incScope = m_scopes[ num ];
|
|
if( !incScope )
|
|
return false;
|
|
TQMake::AST* ast = incScope->m_incast;
|
|
if( !ast )
|
|
return false;
|
|
m_scopes.remove( num );
|
|
m_root->removeChildAST( incScope->m_incast);
|
|
delete incScope;
|
|
delete ast;
|
|
|
|
return m_parent->deleteFunctionScope( getNum() );
|
|
}
|
|
|
|
bool Scope::deleteSubProject( unsigned int num, bool deleteSubdir )
|
|
{
|
|
if ( !m_root || !m_scopes.contains( num ) )
|
|
return false;
|
|
|
|
TQValueList<TQMake::AST*>::iterator it = findExistingVariable( "TEMPLATE" );
|
|
if ( it != m_root->m_tqchildren.end() )
|
|
{
|
|
TQMake::AssignmentAST * tempast = static_cast<TQMake::AssignmentAST*>( *it );
|
|
if ( tempast->values.findIndex( "subdirs" ) != -1 || findExistingVariable( "TEMPLATE" ) != m_root->m_tqchildren.end() )
|
|
{
|
|
Scope* project = m_scopes[ num ];
|
|
if( !project )
|
|
return false;
|
|
|
|
TQString projdir = project->scopeName();
|
|
if ( deleteSubdir )
|
|
{
|
|
TQDir projdir = TQDir( projectDir() );
|
|
TQString dir = project->scopeName();
|
|
if( !dir.endsWith(".pro") )
|
|
{
|
|
TQDir subdir = TQDir( projectDir() + TQString( TQChar( TQDir::separator() ) ) + dir );
|
|
if ( subdir.exists() )
|
|
{
|
|
TQStringList entries = subdir.entryList();
|
|
for ( TQStringList::iterator eit = entries.begin() ; eit != entries.end() ; ++eit )
|
|
{
|
|
if( *eit == "." || *eit == ".." )
|
|
continue;
|
|
if( !subdir.remove( *eit ) )
|
|
kdDebug( 9024 ) << "Couldn't delete " << *eit << " from " << subdir.absPath() << endl;
|
|
}
|
|
if( !projdir.rmdir( dir ) )
|
|
kdDebug( 9024 ) << "Couldn't delete " << dir << " from " << projdir.absPath() << endl;
|
|
}
|
|
}else
|
|
{
|
|
TQDir d( project->projectDir() );
|
|
kdDebug(9024) << "removed subproject?:" << d.remove( dir ) << endl;
|
|
}
|
|
}
|
|
TQValueList<TQMake::AST*>::iterator foundit = findExistingVariable( "SUBDIRS" );
|
|
if ( foundit != m_root->m_tqchildren.end() )
|
|
{
|
|
TQMake::AssignmentAST * ast = static_cast<TQMake::AssignmentAST*>( *foundit );
|
|
updateValues( ast->values, TQStringList( projdir ), true, ast->indent );
|
|
if( m_varCache.contains( "SUBDIRS" ) )
|
|
m_varCache.erase( "SUBDIRS" );
|
|
}else
|
|
return false;
|
|
m_scopes.remove( num );
|
|
delete project;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Scope::updateValues( TQStringList& origValues, const TQStringList& newValues, bool remove, TQString indent )
|
|
{
|
|
if( !m_root )
|
|
return;
|
|
|
|
for ( TQStringList::const_iterator it = newValues.begin(); it != newValues.end() ; ++it )
|
|
{
|
|
if ( origValues.findIndex( *it ) == -1 && !remove )
|
|
{
|
|
while ( !origValues.isEmpty() && origValues.last() == getLineEndingString() )
|
|
origValues.pop_back();
|
|
if ( origValues.count() > 0 && !containsContinue( origValues.last() ) && !isComment( origValues.last() ) )
|
|
{
|
|
origValues.append( " " );
|
|
origValues.append( "\\"+getLineEndingString() );
|
|
if( indent != "" )
|
|
origValues.append( indent );
|
|
}else if ( !origValues.isEmpty() && containsContinue( origValues.last() ) && !isComment( origValues.last() ) )
|
|
{
|
|
if( indent != "" )
|
|
origValues.append( indent );
|
|
}else if ( !origValues.isEmpty() && isComment( origValues.last() ) )
|
|
{
|
|
origValues[origValues.count()-1] = "\\ "+origValues[origValues.count()-1];
|
|
if( indent != "" )
|
|
origValues.append( indent );
|
|
}else if ( origValues.isEmpty() )
|
|
origValues.append(" ");
|
|
TQString newval = *it;
|
|
TQRegExp re("([^$])\\$([^$\\(\\)\\{\\} /]*)( |\\)|/)");
|
|
newval.replace(re, "\\1$(\\2)\\3");
|
|
if( (newval).contains(" ") || (newval).contains("\t") || (newval).contains( getLineEndingString() ) || (newval).contains("#") )
|
|
origValues.append( "\""+newval+"\"" );
|
|
else
|
|
origValues.append( newval );
|
|
origValues.append( getLineEndingString() );
|
|
} else if ( origValues.findIndex( *it ) != -1 && remove )
|
|
{
|
|
TQStringList::iterator posit = origValues.find( *it );
|
|
posit = origValues.remove( posit );
|
|
while( posit != origValues.end() && ( (*posit).find( TQRegExp("\\\\[\\s]*"+getLineEndingString() ) ) != -1
|
|
|| (*posit).stripWhiteSpace() == "" ) )
|
|
{
|
|
posit = origValues.remove( posit );
|
|
}
|
|
}
|
|
}
|
|
while( !origValues.isEmpty() && (origValues.last() == "\\"+getLineEndingString()
|
|
|| origValues.last() == getLineEndingString()
|
|
|| origValues.last().stripWhiteSpace() == "" ) && !origValues.isEmpty() )
|
|
origValues.pop_back();
|
|
if( !origValues.isEmpty() && origValues.last().find( TQRegExp("\\\\[ \t]*#") ) != -1 )
|
|
origValues[origValues.count()-1] = origValues[origValues.count()-1].mid(origValues[origValues.count()-1].find( "#") );
|
|
if( !origValues.isEmpty() && origValues.last().find( getLineEndingString() ) == -1 )
|
|
origValues.append(getLineEndingString());
|
|
}
|
|
|
|
void Scope::updateVariable( const TQString& variable, const TQString& op, const TQStringList& values, bool removeFromOp )
|
|
{
|
|
if ( !m_root || listIsEmpty( values ) )
|
|
return ;
|
|
|
|
if( m_varCache.contains( variable ) )
|
|
m_varCache.erase( variable );
|
|
|
|
for ( int i = m_root->m_tqchildren.count() - 1; i >= 0; --i )
|
|
{
|
|
if ( m_root->m_tqchildren[ i ] ->nodeType() == TQMake::AST::AssignmentAST )
|
|
{
|
|
TQMake::AssignmentAST * assignment = static_cast<TQMake::AssignmentAST*>( m_root->m_tqchildren[ i ] );
|
|
if ( assignment->scopedID == variable && Scope::isCompatible( assignment->op, op ) )
|
|
{
|
|
updateValues( assignment->values, values, removeFromOp, assignment->indent );
|
|
if ( removeFromOp && listIsEmpty( assignment->values ) )
|
|
{
|
|
m_root->removeChildAST( assignment );
|
|
delete assignment;
|
|
}
|
|
return ;
|
|
}
|
|
else if ( assignment->scopedID == variable && !Scope::isCompatible( assignment->op, op ) )
|
|
{
|
|
for ( TQStringList::const_iterator it = values.begin() ; it != values.end() ; ++it )
|
|
{
|
|
if ( op == "+=" && !removeFromOp && assignment->values.findIndex( *it ) != -1 )
|
|
{
|
|
if ( assignment->op == "=" )
|
|
{
|
|
updateValues( assignment->values, values, false, assignment->indent );
|
|
return ;
|
|
}
|
|
else if ( assignment->op == "-=" )
|
|
{
|
|
updateValues( assignment->values, TQStringList( *it ), true, assignment->indent );
|
|
if ( listIsEmpty( assignment->values ) )
|
|
{
|
|
m_root->removeChildAST( assignment );
|
|
delete assignment;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if ( op == "-=" && !removeFromOp && assignment->values.findIndex( *it ) != -1 )
|
|
{
|
|
updateValues( assignment->values, TQStringList( *it ), true, assignment->indent );
|
|
if ( listIsEmpty( assignment->values ) )
|
|
{
|
|
m_root->removeChildAST( assignment );
|
|
delete assignment;
|
|
break;
|
|
}
|
|
}
|
|
else if ( op == "=" )
|
|
{
|
|
if ( !removeFromOp )
|
|
{
|
|
m_root->removeChildAST( assignment );
|
|
delete assignment;
|
|
}
|
|
else if ( assignment->op == "+=" && assignment->values.findIndex( *it ) != -1 )
|
|
{
|
|
updateValues( assignment->values, TQStringList( *it ), true, assignment->indent );
|
|
if ( listIsEmpty( assignment->values ) )
|
|
{
|
|
m_root->removeChildAST( assignment );
|
|
delete assignment;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !removeFromOp )
|
|
{
|
|
TQMake::AssignmentAST * ast = new TQMake::AssignmentAST();
|
|
ast->scopedID = variable;
|
|
ast->op = op;
|
|
updateValues( ast->values, values );
|
|
if( scopeType() == ProjectScope )
|
|
ast->setDepth( m_root->depth() );
|
|
else
|
|
ast->setDepth( m_root->depth()+1 );
|
|
m_root->addChildAST( ast );
|
|
if ( values.findIndex( getLineEndingString() ) == -1 )
|
|
{
|
|
ast->values.append( getLineEndingString() );
|
|
}
|
|
}
|
|
}
|
|
|
|
TQValueList<TQMake::AST*>::iterator Scope::findExistingVariable( const TQString& variable )
|
|
{
|
|
TQValueList<TQMake::AST*>::iterator it;
|
|
TQStringList ops;
|
|
ops << "=" << "+=";
|
|
|
|
for ( it = m_root->m_tqchildren.begin(); it != m_root->m_tqchildren.end() ; ++it )
|
|
{
|
|
if ( ( *it ) ->nodeType() == TQMake::AST::AssignmentAST )
|
|
{
|
|
TQMake::AssignmentAST * assignment = static_cast<TQMake::AssignmentAST*>( *it );
|
|
if ( assignment->scopedID == variable && ops.findIndex( assignment->op ) != -1 )
|
|
{
|
|
return it;
|
|
}
|
|
}
|
|
}
|
|
return m_root->m_tqchildren.end();
|
|
}
|
|
|
|
void Scope::init()
|
|
{
|
|
if( !m_root )
|
|
return;
|
|
|
|
kdDebug(9024) << "Initializing Scope: " << scopeName() << this << endl;
|
|
m_maxCustomVarNum = 1;
|
|
|
|
TQValueList<TQMake::AST*>::const_iterator it;
|
|
for ( it = m_root->m_tqchildren.begin(); it != m_root->m_tqchildren.end(); ++it )
|
|
{
|
|
if ( ( *it ) ->nodeType() == TQMake::AST::ProjectAST )
|
|
{
|
|
TQMake::ProjectAST * p = static_cast<TQMake::ProjectAST*>( *it );
|
|
m_scopes.insert( getNextScopeNum(), new Scope( m_environment, getNextScopeNum(), this, p, m_defaultopts, m_part ) );
|
|
}
|
|
else if ( ( *it ) ->nodeType() == TQMake::AST::IncludeAST )
|
|
{
|
|
TQMake::IncludeAST * i = static_cast<TQMake::IncludeAST*>( *it );
|
|
TQString filename = i->projectName;
|
|
if( i->projectName.stripWhiteSpace().startsWith("$") )
|
|
{
|
|
filename = resolveVariables(i->projectName, *it);
|
|
}
|
|
m_scopes.insert( getNextScopeNum(), new Scope( m_environment, getNextScopeNum(), this, i, projectDir(), filename, m_defaultopts, m_part ) );
|
|
}
|
|
else if ( ( *it ) ->nodeType() == TQMake::AST::AssignmentAST )
|
|
{
|
|
TQMake::AssignmentAST * m = static_cast<TQMake::AssignmentAST*>( *it );
|
|
// Check wether TEMPLATE==subdirs here too!
|
|
if ( m->scopedID == "SUBDIRS" && variableValues("TEMPLATE").findIndex("subdirs") != -1 )
|
|
{
|
|
for ( TQStringList::const_iterator sit = m->values.begin() ; sit != m->values.end(); ++sit )
|
|
{
|
|
TQString str = *sit;
|
|
if ( containsContinue( str ) || isComment( str ) || str == getLineEndingString() || str == "." || str == "./" || (str).stripWhiteSpace() == "" )
|
|
continue;
|
|
TQDir subproject;
|
|
TQString projectfile;
|
|
kdDebug(9024) << "reading subproject: " << str << endl;
|
|
if( str.startsWith("$") )
|
|
str = resolveVariables(str, *it);
|
|
if( str.endsWith(".pro") )
|
|
{
|
|
subproject = TQDir( projectDir(), "*.pro", TQDir::Name | TQDir::IgnoreCase, TQDir::Files );
|
|
projectfile = str;
|
|
}else
|
|
{
|
|
TQString dir = str;
|
|
if( TQFileInfo( dir ).isRelative() )
|
|
dir = projectDir() + TQString( TQChar( TQDir::separator() ) ) + dir;
|
|
subproject = TQDir( dir,
|
|
"*.pro", TQDir::Name | TQDir::IgnoreCase, TQDir::Files );
|
|
if( !subproject.exists() )
|
|
{
|
|
kdDebug(9024) << "Project Dir doesn't exist, trying to find name.subdir variable:" << str << endl;
|
|
if( !variableValues(str+".subdir").isEmpty() )
|
|
{
|
|
kdDebug(9024) << "Found name.subdir variable for " << str << endl;
|
|
subproject = TQDir( projectDir() + TQString( TQChar( TQDir::separator() ) )
|
|
+ variableValues(str+".subdir").first(),
|
|
"*.pro", TQDir::Name | TQDir::IgnoreCase, TQDir::Files );
|
|
}else
|
|
continue;
|
|
}
|
|
if ( subproject.entryList().isEmpty() || subproject.entryList().findIndex( str + ".pro" ) != -1 )
|
|
projectfile = (str) + ".pro";
|
|
else
|
|
projectfile = subproject.entryList().first();
|
|
|
|
}
|
|
kdDebug( 9024 ) << "Parsing subproject: " << projectfile << endl;
|
|
m_scopes.insert( getNextScopeNum(), new Scope( m_environment, getNextScopeNum(), this,
|
|
subproject.absFilePath( projectfile ),
|
|
m_part, ( m->op != "-=" )) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !(
|
|
KnownVariables.findIndex( m->scopedID ) != -1
|
|
&& ( m->op == "=" || m->op == "+=" || m->op == "-=")
|
|
)
|
|
&& !(
|
|
( m->scopedID.contains( ".files" ) || m->scopedID.contains( ".path" ) )
|
|
&& variableValues("INSTALLS").findIndex(m->scopedID.left( m->scopedID.findRev(".") != -1 ) )
|
|
)
|
|
&& !(
|
|
( m->scopedID.contains( ".subdir" ) )
|
|
&& variableValues("SUBDIRS").findIndex(m->scopedID.left( m->scopedID.findRev(".") != -1 ) )
|
|
)
|
|
)
|
|
{
|
|
m_customVariables[ m_maxCustomVarNum++ ] = m;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TQString Scope::projectName() const
|
|
{
|
|
if( !m_root )
|
|
return "";
|
|
|
|
return TQFileInfo( projectDir() ).fileName();
|
|
}
|
|
|
|
TQString Scope::projectDir() const
|
|
{
|
|
if( !m_root )
|
|
return "";
|
|
if ( m_root->isProject() )
|
|
{
|
|
return TQFileInfo( m_root->fileName() ).dirPath( true );
|
|
}
|
|
else
|
|
{
|
|
return m_parent->projectDir();
|
|
}
|
|
}
|
|
|
|
const TQMap<unsigned int, TQMap<TQString, TQString> > Scope::customVariables() const
|
|
{
|
|
TQMap<unsigned int, TQMap<TQString, TQString> > result;
|
|
if( !m_root )
|
|
return result;
|
|
|
|
TQMap<unsigned int, TQMake::AssignmentAST*>::const_iterator it = m_customVariables.begin();
|
|
for ( ; it != m_customVariables.end(); ++it )
|
|
{
|
|
TQMap<TQString,TQString> temp;
|
|
temp[ "var" ] = it.data()->scopedID;
|
|
temp[ "op" ] = it.data()->op;
|
|
temp[ "values" ] = it.data()->values.join("").stripWhiteSpace();
|
|
result[ it.key() ] = temp;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Scope::updateCustomVariable( unsigned int id, const TQString& name, const TQString& newop, const TQString& newvalues )
|
|
{
|
|
if( !m_root )
|
|
return;
|
|
if ( id > 0 && m_customVariables.contains( id ) )
|
|
{
|
|
m_customVariables[ id ] ->values.clear();
|
|
updateValues( m_customVariables[ id ] ->values, newvalues.stripWhiteSpace() );
|
|
if( m_varCache.contains( m_customVariables[ id ]->scopedID ) )
|
|
m_varCache.erase( m_customVariables[ id ]->scopedID );
|
|
m_customVariables[ id ] ->op = newop;
|
|
m_customVariables[ id ] ->scopedID = name;
|
|
}
|
|
}
|
|
|
|
unsigned int Scope::addCustomVariable( const TQString& var, const TQString& op, const TQString& values )
|
|
{
|
|
TQMake::AssignmentAST* newast = new TQMake::AssignmentAST();
|
|
newast->scopedID = var;
|
|
newast->op = op;
|
|
newast->values.append(values.stripWhiteSpace());
|
|
if( scopeType() == ProjectScope )
|
|
newast->setDepth( m_root->depth() );
|
|
else
|
|
newast->setDepth( m_root->depth()+1 );
|
|
m_root->addChildAST( newast );
|
|
m_customVariables[ m_maxCustomVarNum++ ] = newast;
|
|
return (m_maxCustomVarNum-1);
|
|
}
|
|
|
|
void Scope::removeCustomVariable( unsigned int id )
|
|
{
|
|
if( m_customVariables.contains(id) )
|
|
{
|
|
TQMake::AssignmentAST* m = m_customVariables[id];
|
|
m_customVariables.remove(id);
|
|
m_root->m_tqchildren.remove( m );
|
|
}
|
|
}
|
|
|
|
bool Scope::isVariableReset( const TQString& var )
|
|
{
|
|
bool result = false;
|
|
if( !m_root )
|
|
return result;
|
|
TQValueList<TQMake::AST*>::const_iterator it = m_root->m_tqchildren.begin();
|
|
for ( ; it != m_root->m_tqchildren.end(); ++it )
|
|
{
|
|
if ( ( *it ) ->nodeType() == TQMake::AST::AssignmentAST )
|
|
{
|
|
TQMake::AssignmentAST * ast = static_cast<TQMake::AssignmentAST*>( *it );
|
|
if ( ast->scopedID == var && ast->op == "=" )
|
|
{
|
|
result = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Scope::removeVariable( const TQString& var, const TQString& op )
|
|
{
|
|
if ( !m_root )
|
|
return ;
|
|
|
|
TQMake::AssignmentAST* ast = 0;
|
|
|
|
TQValueList<TQMake::AST*>::iterator it = m_root->m_tqchildren.begin();
|
|
for ( ; it != m_root->m_tqchildren.end(); ++it )
|
|
{
|
|
if ( ( *it ) ->nodeType() == TQMake::AST::AssignmentAST )
|
|
{
|
|
ast = static_cast<TQMake::AssignmentAST*>( *it );
|
|
if ( ast->scopedID == var && ast->op == op )
|
|
{
|
|
m_root->m_tqchildren.remove( ast );
|
|
it = m_root->m_tqchildren.begin();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Scope::listIsEmpty( const TQStringList& values )
|
|
{
|
|
if ( values.size() < 1 )
|
|
return true;
|
|
for ( TQStringList::const_iterator it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
if ( ( *it ).stripWhiteSpace() != "" && ( *it ).stripWhiteSpace() != "\\" )
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Scope::isCompatible( const TQString& op1, const TQString& op2)
|
|
{
|
|
if( op1 == "+=" )
|
|
return ( op2 == "+=" || op2 == "=" );
|
|
else if ( op1 == "-=" )
|
|
return ( op2 == "-=" );
|
|
else if ( op1 == "=" )
|
|
return ( op2 == "=" || op2 == "+=" );
|
|
return false;
|
|
}
|
|
|
|
bool Scope::listsEqual(const TQStringList& l1, const TQStringList& l2)
|
|
{
|
|
TQStringList left = l1;
|
|
TQStringList right = l2;
|
|
// left.sort();
|
|
// right.sort();
|
|
return (left == right);
|
|
}
|
|
|
|
TQStringList Scope::cleanStringList(const TQStringList& list) const
|
|
{
|
|
TQStringList result;
|
|
for( TQStringList::const_iterator it = list.begin(); it != list.end(); ++it )
|
|
{
|
|
TQString s = *it;
|
|
if( s.stripWhiteSpace() != ""
|
|
&& !containsContinue(s)
|
|
&& s.stripWhiteSpace() != getLineEndingString()
|
|
&& !isComment(s) )
|
|
result.append(s);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool Scope::isTQt4Project() const
|
|
{
|
|
return m_part->isTQt4Project();
|
|
}
|
|
|
|
void Scope::reloadProject()
|
|
{
|
|
if ( !m_root || !m_root->isProject() )
|
|
return;
|
|
|
|
TQString filename = m_root->fileName();
|
|
TQMap<unsigned int, Scope*>::iterator it;
|
|
for ( it = m_scopes.begin() ; it != m_scopes.end() ; ++it )
|
|
{
|
|
Scope* s = it.data();
|
|
delete s;
|
|
}
|
|
m_scopes.clear();
|
|
|
|
m_customVariables.clear();
|
|
|
|
m_varCache.clear();
|
|
|
|
if ( m_root->isProject() )
|
|
delete m_root;
|
|
if ( !loadFromFile( filename ) && !TQFileInfo( filename ).exists() )
|
|
{
|
|
m_root = new TQMake::ProjectAST();
|
|
m_root->setFileName( filename );
|
|
}
|
|
init();
|
|
}
|
|
|
|
Scope* Scope::disableSubproject( const TQString& dir)
|
|
{
|
|
if( !m_root || ( m_root->isProject() && !m_incast ) )
|
|
return 0;
|
|
|
|
if( scopeType() != Scope::IncludeScope && variableValuesForOp( "SUBDIRS", "+=").findIndex( dir ) != -1 )
|
|
removeFromPlusOp( "SUBDIRS", dir );
|
|
else if( scopeType() != Scope::IncludeScope )
|
|
removeFromPlusOp( "SUBDIRS", dir );
|
|
|
|
TQDir curdir( projectDir() );
|
|
|
|
if ( variableValues("TEMPLATE").findIndex( "subdirs" ) != -1 )
|
|
{
|
|
curdir.cd(dir);
|
|
TQString filename;
|
|
TQStringList entries = curdir.entryList("*.pro", TQDir::Files);
|
|
|
|
if ( !entries.isEmpty() && entries.findIndex( curdir.dirName()+".pro" ) != -1 )
|
|
filename = curdir.absPath() + TQString(TQChar(TQDir::separator()))+entries.first();
|
|
else
|
|
filename = curdir.absPath() + TQString(TQChar(TQDir::separator()))+curdir.dirName()+".pro";
|
|
|
|
kdDebug( 9024 ) << "Disabling subproject with filename:" << filename << endl;
|
|
|
|
Scope* s = new Scope( m_environment, getNextScopeNum(), this, filename, m_part, false );
|
|
addToMinusOp( "SUBDIRS", TQStringList( dir ) );
|
|
m_scopes.insert( getNextScopeNum(), s );
|
|
return s;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
TQString Scope::resolveVariables( const TQString& value ) const
|
|
{
|
|
return resolveVariables(TQStringList(value), 0).front();
|
|
}
|
|
|
|
|
|
TQString Scope::resolveVariables( const TQString& value, TQMake::AST* stopHere ) const
|
|
{
|
|
return resolveVariables(TQStringList(value), stopHere).front();
|
|
}
|
|
|
|
TQStringList Scope::variableValues( const TQString& variable, TQMake::AST* stopHere, bool fetchFromParent ) const
|
|
{
|
|
TQStringList result;
|
|
|
|
if ( !m_root )
|
|
return result;
|
|
|
|
calcValuesFromStatements( variable, result, true, stopHere, fetchFromParent );
|
|
result = cleanStringList(result);
|
|
return result;
|
|
}
|
|
|
|
TQStringList Scope::resolveVariables( const TQStringList& values, TQMake::AST* stopHere ) const
|
|
{
|
|
TQStringList result = values;
|
|
TQMap<TQString, TQStringList> variables;
|
|
for( TQStringList::iterator it = result.begin(); it != result.end(); ++it )
|
|
{
|
|
TQRegExp re("\\$\\$([^{}\\) /]*)( |\\)|/|$)");
|
|
int pos = 0;
|
|
while( pos >= 0 )
|
|
{
|
|
pos = re.search( (*it), pos );
|
|
if( pos > -1 )
|
|
{
|
|
if( !variables.contains( re.cap(1) ) )
|
|
{
|
|
variables[re.cap(1)] = resolveVariables( variableValues( re.cap(1), stopHere ) );
|
|
if( variables[re.cap(1)].isEmpty() && re.cap(1) == "TARGET" )
|
|
{
|
|
variables[re.cap(1)] = TQFileInfo( fileName() ).baseName();
|
|
}
|
|
}
|
|
pos += re.matchedLength();
|
|
}
|
|
}
|
|
re = TQRegExp("\\$\\$\\{([^\\)\\}]*)\\}");
|
|
pos = 0;
|
|
while( pos >= 0 )
|
|
{
|
|
pos = re.search( (*it), pos );
|
|
if( pos > -1 )
|
|
{
|
|
if( !variables.contains( re.cap(1) ) )
|
|
{
|
|
variables[re.cap(1)] = resolveVariables( variableValues( re.cap(1), stopHere ) );
|
|
if( variables[re.cap(1)].isEmpty() && re.cap(1) == "TARGET" )
|
|
{
|
|
variables[re.cap(1)] = TQFileInfo( fileName() ).baseName();
|
|
}
|
|
}
|
|
pos += re.matchedLength();
|
|
}
|
|
}
|
|
re = TQRegExp("\\$\\$\\(([^\\)\\}]*)\\)");
|
|
pos = 0;
|
|
TQMap<TQString, TQString> envvars;
|
|
while( pos >= 0 )
|
|
{
|
|
pos = re.search( (*it), pos );
|
|
if( pos > -1 )
|
|
{
|
|
if( !envvars.contains( re.cap(1) ) )
|
|
if( m_environment.contains( re.cap(1) ) != -1 )
|
|
envvars[re.cap(1)] = m_environment[ re.cap(1) ];
|
|
else if ( ::getenv( re.cap(1).local8Bit() ) != 0 )
|
|
envvars[re.cap(1)] = TQString::fromLocal8Bit( ::getenv( re.cap(1).local8Bit() ) );
|
|
pos += re.matchedLength();
|
|
}
|
|
}
|
|
for( TQMap<TQString, TQString>::const_iterator it2 = envvars.begin(); it2 != envvars.end(); ++it2 )
|
|
{
|
|
(*it).replace("$$("+it2.key()+")", it2.data() );
|
|
}
|
|
for( TQMap<TQString, TQStringList>::const_iterator it2 = variables.begin(); it2 != variables.end(); ++it2 )
|
|
{
|
|
for( TQStringList::const_iterator it3 = it2.data().begin(); it3 != it2.data().end(); ++it3 )
|
|
{
|
|
(*it).replace("$$"+it2.key(), *it3 );
|
|
(*it).replace("$${"+it2.key()+"}", *it3 );
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Scope::allFiles( const TQString& projectDirectory, std::set<TQString>& res )
|
|
{
|
|
|
|
TQString myRelPath = URLUtil::getRelativePath( projectDirectory, projectDir() );
|
|
TQString file;
|
|
TQStringList values;
|
|
TQString header = "";
|
|
if( variableValues("TEMPLATE",false ).findIndex("subdirs") == -1 )
|
|
{
|
|
values = variableValues( "INSTALLS" ,false, false );
|
|
TQStringList::const_iterator it;
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
if ( ( *it ) == "target" )
|
|
continue;
|
|
|
|
TQStringList files = variableValues( *it + ".files" ,false, false );
|
|
TQStringList::iterator filesit = files.begin();
|
|
for ( ;filesit != files.end(); ++filesit )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *filesit;
|
|
file = resolveVariables( file );
|
|
if( file.contains("*") )
|
|
{
|
|
TQFileInfo fi( projectDirectory + TQString( TQChar( TQDir::separator() ) ) + file );
|
|
TQDir absDir = fi.dir( true );
|
|
absDir.setNameFilter( fi.fileName() );
|
|
absDir.setFilter( TQDir::Files | TQDir::Readable | TQDir::NoSymLinks );
|
|
TQStringList list = absDir.entryList();
|
|
for( TQStringList::const_iterator it = list.begin(); it != list.end(); ++it )
|
|
{
|
|
res.insert( TQDir::cleanDirPath( URLUtil::getRelativePath( projectDirectory, absDir.path()+TQString( TQChar( TQDir::separator() ) )+*it ) ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
values = variableValues( "LEXSOURCES" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
|
|
values = variableValues( "YACCSOURCES" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
|
|
values = variableValues( "DISTFILES" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
if( file.contains("*") )
|
|
{
|
|
TQFileInfo fi( projectDirectory + TQString( TQChar( TQDir::separator() ) ) + file );
|
|
TQDir absDir = fi.dir( true );
|
|
absDir.setNameFilter( fi.fileName() );
|
|
absDir.setFilter( TQDir::Files | TQDir::Readable | TQDir::NoSymLinks );
|
|
TQStringList list = absDir.entryList();
|
|
for( TQStringList::const_iterator it = list.begin(); it != list.end(); ++it )
|
|
{
|
|
res.insert( TQDir::cleanDirPath( URLUtil::getRelativePath( projectDirectory, absDir.path()+TQString( TQChar( TQDir::separator() ) )+*it ) ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
}
|
|
|
|
if ( isTQt4Project() )
|
|
{
|
|
values = variableValues( "RESOURCES" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
}
|
|
values = variableValues( "IMAGES" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
|
|
values = variableValues( "TRANSLATIONS" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
|
|
values = variableValues( "IDLS" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
|
|
if ( m_part->isTMakeProject() )
|
|
{
|
|
values = variableValues( "INTERFACES" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
if( TQFileInfo(projectDir()+TQString(TQChar(TQDir::separator())) + *it+".h").exists() )
|
|
res.insert( TQDir::cleanDirPath( file+".h" ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
values = variableValues( "FORMS" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
|
|
if( !m_part->isTQt4Project())
|
|
{
|
|
header = projectDir()+TQString(TQChar(TQDir::separator())) + *it+".h";
|
|
if( TQFileInfo(header).exists() )
|
|
res.insert( TQDir::cleanDirPath( header ) );
|
|
header = projectDir()+TQString(TQChar(TQDir::separator())) + *it+".cpp";
|
|
if( TQFileInfo(header).exists() )
|
|
res.insert( TQDir::cleanDirPath( header ) );
|
|
}
|
|
else
|
|
{
|
|
header = projectDir()+TQString(TQChar(TQDir::separator())) + "ui_" +*it;
|
|
header.replace(TQRegExp("\\.ui$"),".h");
|
|
if( TQFileInfo(header).exists() )
|
|
res.insert( TQDir::cleanDirPath( header ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
values = variableValues( "SOURCES" ,false, false );
|
|
kdDebug(9024) << "scope:" << scopeType() << " found values: " << values << endl;
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
|
|
values = variableValues( "HEADERS" ,false, false );
|
|
for ( it = values.begin(); it != values.end(); ++it )
|
|
{
|
|
file = myRelPath + TQString(TQChar(TQDir::separator())) + *it;
|
|
file = resolveVariables( file );
|
|
res.insert( TQDir::cleanDirPath( file ) );
|
|
}
|
|
}
|
|
TQMap<unsigned int, Scope*>::const_iterator it = m_scopes.begin();
|
|
for( ; it != m_scopes.end(); ++it )
|
|
{
|
|
it.data()->allFiles( projectDirectory, res );
|
|
}
|
|
}
|
|
|
|
TQStringList Scope::allFiles( const TQString& projectDir )
|
|
{
|
|
TQStringList result;
|
|
std::set<TQString> files;
|
|
allFiles( projectDir, files );
|
|
for( std::set<TQString>::const_iterator it = files.begin(); it != files.end() ; ++it )
|
|
result.append( *it );
|
|
kdDebug(9024) << "all files: " << result << endl;
|
|
return result;
|
|
}
|
|
|
|
TQString Scope::findCustomVarForPath( const TQString& path )
|
|
{
|
|
TQString result;
|
|
if( !m_root )
|
|
return result;
|
|
|
|
TQMap<unsigned int, TQMake::AssignmentAST*>::const_iterator it = m_customVariables.begin();
|
|
for( ; it != m_customVariables.end(); ++it )
|
|
{
|
|
kdDebug(9024) << "Checking " << path << " against " << cleanStringList(it.data()->values) << endl;
|
|
if( !it.data()->values.isEmpty() && cleanStringList(it.data()->values).front() == path )
|
|
{
|
|
return it.data()->scopedID;
|
|
}
|
|
}
|
|
if( scopeType() != ProjectScope )
|
|
{
|
|
return parent()->findCustomVarForPath( path );
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Scope::loadDefaultOpts()
|
|
{
|
|
if( !m_defaultopts && m_root )
|
|
{
|
|
m_defaultopts = new TQMakeDefaultOpts();
|
|
if( DomUtil::readBoolEntry( *m_part->projectDom(), "/kdevtrollproject/qmake/disableDefaultOpts", true ) )
|
|
{
|
|
m_defaultopts->readVariables( m_part->qmakePath(), TQFileInfo( m_root->fileName() ).dirPath( true ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
TQString Scope::getLineEndingString() const
|
|
{
|
|
|
|
if( scopeType() == ProjectScope )
|
|
{
|
|
switch( m_root->lineEnding() )
|
|
{
|
|
case TQMake::ProjectAST::Windows:
|
|
return TQString("\r\n");
|
|
break;
|
|
case TQMake::ProjectAST::MacOS:
|
|
return TQString("\r");
|
|
break;
|
|
case TQMake::ProjectAST::Unix:
|
|
return TQString("\n");
|
|
break;
|
|
}
|
|
}else if( m_parent )
|
|
{
|
|
return m_parent->getLineEndingString();
|
|
}
|
|
return "\n";
|
|
}
|
|
|
|
TQString Scope::replaceWs(TQString s)
|
|
{
|
|
return s.replace( getLineEndingString(), "%nl").replace("\t", "%tab").replace(" ", "%spc");
|
|
}
|
|
|
|
bool Scope::containsContinue(const TQString& s ) const
|
|
{
|
|
return( s.find( TQRegExp( "\\\\\\s*"+getLineEndingString() ) ) != -1
|
|
|| s.find( TQRegExp( "\\\\\\s*#" ) ) != -1 );
|
|
}
|
|
|
|
bool Scope::isComment( const TQString& s) const
|
|
{
|
|
return s.startsWith("#");
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
void Scope::printTree()
|
|
{
|
|
PrintAST p;
|
|
p.processProject(m_root);
|
|
}
|
|
|
|
Scope::PrintAST::PrintAST() : TQMake::ASTVisitor()
|
|
{
|
|
indent = 0;
|
|
}
|
|
|
|
void Scope::PrintAST::processProject( TQMake::ProjectAST* p )
|
|
{
|
|
TQMake::ASTVisitor::processProject(p);
|
|
}
|
|
|
|
void Scope::PrintAST::enterRealProject( TQMake::ProjectAST* p )
|
|
{
|
|
kdDebug(9024) << getIndent() << "--------- Entering Project: " << replaceWs(p->fileName()) << " --------------" << endl;
|
|
indent += 4;
|
|
TQMake::ASTVisitor::enterRealProject(p);
|
|
}
|
|
|
|
void Scope::PrintAST::leaveRealProject( TQMake::ProjectAST* p )
|
|
{
|
|
indent -= 4;
|
|
kdDebug(9024) << getIndent() << "--------- Leaving Project: " << replaceWs(p->fileName()) << " --------------" << endl;
|
|
TQMake::ASTVisitor::leaveRealProject(p);
|
|
}
|
|
|
|
void Scope::PrintAST::enterScope( TQMake::ProjectAST* p )
|
|
{
|
|
kdDebug(9024) << getIndent() << "--------- Entering Scope: " << replaceWs(p->scopedID) << " --------------" << endl;
|
|
indent += 4;
|
|
TQMake::ASTVisitor::enterScope(p);
|
|
}
|
|
|
|
void Scope::PrintAST::leaveScope( TQMake::ProjectAST* p )
|
|
{
|
|
indent -= 4;
|
|
kdDebug(9024) << getIndent() << "--------- Leaving Scope: " << replaceWs(p->scopedID) << " --------------" << endl;
|
|
TQMake::ASTVisitor::leaveScope(p);
|
|
}
|
|
|
|
void Scope::PrintAST::enterFunctionScope( TQMake::ProjectAST* p )
|
|
{
|
|
kdDebug(9024) << getIndent() << "--------- Entering FunctionScope: " << replaceWs(p->scopedID) << "(" << replaceWs(p->args) << ")"<< " --------------" << endl;
|
|
indent += 4;
|
|
TQMake::ASTVisitor::enterFunctionScope(p);
|
|
}
|
|
|
|
void Scope::PrintAST::leaveFunctionScope( TQMake::ProjectAST* p )
|
|
{
|
|
indent -= 4;
|
|
kdDebug(9024) << getIndent() << "--------- Leaving FunctionScope: " << replaceWs(p->scopedID) << "(" << replaceWs(p->args) << ")"<< " --------------" << endl;
|
|
TQMake::ASTVisitor::leaveFunctionScope(p);
|
|
}
|
|
|
|
TQString Scope::PrintAST::replaceWs(TQString s)
|
|
{
|
|
return s.replace("\n", "%nl").replace("\t", "%tab").replace(" ", "%spc");
|
|
}
|
|
|
|
void Scope::PrintAST::processAssignment( TQMake::AssignmentAST* a)
|
|
{
|
|
kdDebug(9024) << getIndent() << "Assignment: " << replaceWs(a->scopedID) << " " << replaceWs(a->op) << " "
|
|
<< replaceWs(a->values.join("|"))<< endl;
|
|
TQMake::ASTVisitor::processAssignment(a);
|
|
}
|
|
|
|
void Scope::PrintAST::processNewLine( TQMake::NewLineAST* n)
|
|
{
|
|
kdDebug(9024) << getIndent() << "Newline " << endl;
|
|
TQMake::ASTVisitor::processNewLine(n);
|
|
}
|
|
|
|
void Scope::PrintAST::processComment( TQMake::CommentAST* a)
|
|
{
|
|
kdDebug(9024) << getIndent() << "Comment: " << replaceWs(a->comment) << endl;
|
|
TQMake::ASTVisitor::processComment(a);
|
|
}
|
|
|
|
void Scope::PrintAST::processInclude( TQMake::IncludeAST* a)
|
|
{
|
|
kdDebug(9024) << getIndent() << "Include: " << replaceWs(a->projectName) << endl;
|
|
TQMake::ASTVisitor::processInclude(a);
|
|
}
|
|
|
|
TQString Scope::PrintAST::getIndent()
|
|
{
|
|
TQString ind;
|
|
for( int i = 0 ; i < indent ; i++)
|
|
ind += " ";
|
|
return ind;
|
|
}
|
|
#endif
|
|
|
|
// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on
|