diff --git a/projectmanagers/cmake/parser/cmakelistsparser.cpp b/projectmanagers/cmake/parser/cmakelistsparser.cpp index 0f8bbfdabd..e7f334c3cd 100644 --- a/projectmanagers/cmake/parser/cmakelistsparser.cpp +++ b/projectmanagers/cmake/parser/cmakelistsparser.cpp @@ -1,253 +1,253 @@ /* KDevelop CMake Support * * Copyright 2006 Matt Rogers * Copyright 2008 Aleix Pol * * 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. * * This program 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 for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "cmakelistsparser.h" #include #include #include QMap whatToScape() { //Only add those where we're not scaping the next character QMap ret; ret['n']='\n'; ret['r']='\r'; ret['t']='\t'; return ret; } const QMap CMakeFunctionArgument::scapings=whatToScape(); static const QChar scapingChar='\\'; QString CMakeFunctionArgument::unescapeValue(const QString& value) { int firstScape=value.indexOf(scapingChar); if (firstScape<0) { return value; } QString newValue; int last=0; QMap::const_iterator itEnd = scapings.constEnd(); for(int i=firstScape; i=0; i=value.indexOf(scapingChar, i+2)) { - newValue+=value.mid(last, i-last); + newValue+=value.midRef(last, i-last); const QChar current=value[i+1]; QMap::const_iterator it = scapings.constFind(current); if(it!=itEnd) newValue += *it; else newValue += current; last=i+2; } - newValue+=value.mid(last, value.size()); + newValue+=value.midRef(last, value.size()); // qCDebug(CMAKE) << "escapiiiiiiiiing" << value << newValue; return newValue; } void CMakeFunctionDesc::addArguments( const QStringList& args, bool addEvenIfEmpty ) { if(addEvenIfEmpty && args.isEmpty()) arguments += CMakeFunctionArgument(); else foreach( const QString& arg, args ) { CMakeFunctionArgument cmakeArg( arg ); arguments.append( cmakeArg ); } } QString CMakeFunctionDesc::writeBack() const { QString output=name+"( "; foreach(const CMakeFunctionArgument& arg, arguments) { QString o = arg.value; if(arg.quoted) o='"'+o+'"'; output += o+' '; } output += ')'; return output; } namespace CMakeListsParser { static bool readCMakeFunction( cmListFileLexer* lexer, CMakeFunctionDesc& func); CMakeFileContent readCMakeFile(const QString & _fileName) { cmListFileLexer* lexer = cmListFileLexer_New(); if ( !lexer ) return CMakeFileContent(); if ( !cmListFileLexer_SetFileName( lexer, qPrintable( _fileName ), nullptr ) ) { qCDebug(CMAKE) << "cmake read error. could not read " << _fileName; cmListFileLexer_Delete(lexer); return CMakeFileContent(); } CMakeFileContent ret; QString fileName = QDir::cleanPath(_fileName); bool readError = false, haveNewline = true; cmListFileLexer_Token* token; while(!readError && (token = cmListFileLexer_Scan(lexer))) { readError=false; if(token->type == cmListFileLexer_Token_Newline) { readError=false; haveNewline = true; } else if(token->type == cmListFileLexer_Token_Identifier) { if(haveNewline) { haveNewline = false; CMakeFunctionDesc function; function.name = QString::fromLocal8Bit(token->text).toLower(); function.filePath = fileName; function.line = token->line; function.column = token->column; readError = !readCMakeFunction( lexer, function); ret.append(function); if(readError) { qCDebug(CMAKE) << "Error while parsing:" << function.name << "at" << function.line; } } } } cmListFileLexer_Delete(lexer); return ret; } } bool CMakeListsParser::readCMakeFunction(cmListFileLexer *lexer, CMakeFunctionDesc &func) { // Command name has already been parsed. Read the left paren. cmListFileLexer_Token* token; if(!(token = cmListFileLexer_Scan(lexer))) { return false; } if(token->type != cmListFileLexer_Token_ParenLeft) { return false; } // Arguments. int parenthesis=1; while((token = cmListFileLexer_Scan(lexer))) { switch(token->type) { case cmListFileLexer_Token_ParenRight: parenthesis--; if(parenthesis==0) { func.endLine=token->line; func.endColumn=token->column; return true; } else if(parenthesis<0) return false; else func.arguments << CMakeFunctionArgument( QString::fromLocal8Bit(token->text), false, token->line, token->column ); break; case cmListFileLexer_Token_ParenLeft: parenthesis++; func.arguments << CMakeFunctionArgument( QString::fromLocal8Bit(token->text), false, token->line, token->column ); break; case cmListFileLexer_Token_Identifier: case cmListFileLexer_Token_ArgumentUnquoted: func.arguments << CMakeFunctionArgument( QString::fromLocal8Bit(token->text), false, token->line, token->column ); break; case cmListFileLexer_Token_ArgumentQuoted: func.arguments << CMakeFunctionArgument( QString::fromLocal8Bit(token->text), true, token->line, token->column+1 ); break; case cmListFileLexer_Token_Space: case cmListFileLexer_Token_Newline: break; default: return false; } } return false; } CMakeFunctionDesc::CMakeFunctionDesc(const QString& name, const QStringList& args) : name(name) , line(0) , column(0) , endLine(0) , endColumn(0) { addArguments(args); } CMakeFunctionDesc::CMakeFunctionDesc() : line(0) , column(0) , endLine(0) , endColumn(0) {} bool CMakeFunctionDesc::operator==(const CMakeFunctionDesc & other) const { if(other.arguments.count()!=arguments.count() || name!=other.name) return false; QList::const_iterator it=arguments.constBegin(); QList::const_iterator itOther=other.arguments.constBegin(); for(;it!=arguments.constEnd(); ++it, ++itOther) { if(*it!=*itOther) return false; } return true; } /*CMakeFunctionArgument::CMakeFunctionArgument(const CMakeFunctionArgument & r) : value(r.value), quoted(r.quoted), filePath(r.filePath), line(r.line), column(r.column) { value=unescapeValue(value); }*/ CMakeFunctionArgument::CMakeFunctionArgument(const QString& v, bool q, quint32 l, quint32 c) : value(unescapeValue(v)), quoted(q), line(l), column(c) { } CMakeFunctionArgument::CMakeFunctionArgument(const QString& v) : value(v), quoted(false), line(0), column(0) { }