diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index cdc0d8a7..b52c3ebe 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -7,6 +7,64 @@ CppPreprocessor::CppPreprocessor(QObject *parent) : QObject(parent) { } +void CppPreprocessor::clear() +{ + mIncludes.clear(); + mDefines.clear(); + mHardDefines.clear(); + mProcessed.clear(); + mFileDefines.clear(); + mBranchResults.clear(); + mResult.clear(); + mCurrentIncludes.reset(); + mScannedFiles.reset(); +} + +void CppPreprocessor::addDefineByParts(const QString &name, const QString &args, const QString &value, bool hardCoded) +{ + // Check for duplicates + PDefine define = std::make_shared(); + define->name = name; + define->args = args; + define->value = value; + define->filename = mFileName; + //define->argList; + define->formatValue = value; + define->hardCoded = hardCoded; + if (!args.isEmpty()) + parseArgs(define); + if (hardCoded) + mHardDefines.insert(name,define); + else { + PDefineMap defineMap = mFileDefines.value(mFileName,PDefineMap()); + if (!defineMap) { + defineMap = std::make_shared(); + mFileDefines.insert(mFileName,defineMap); + } + defineMap->insert(define->name,define); + mDefines.insert(name,define); + } +} + +void CppPreprocessor::getDefineParts(const QString &Input, QString &name, QString &args, QString &value) +{ + +} + +void CppPreprocessor::addDefineByLine(const QString &line, bool hardCoded) +{ + // Remove define + constexpr int DEFINE_LEN=6; + QString s = line.mid(DEFINE_LEN,0).trimmed(); + + QString name, args, value; + // Get parts from generalized function + getDefineParts(s, name, args, value); + + // Add to the list + addDefineByParts(name, args, value, hardCoded); +} + QString CppPreprocessor::getNextPreprocessor() { @@ -20,10 +78,14 @@ QString CppPreprocessor::getNextPreprocessor() // Calculate index to insert defines in in result file mPreProcIndex = (mResult.count() - 1) + 1; // offset by one for #include rootfile - // Assemble whole line, including newlines + // Assemble whole line, convert newlines to space QString result; for (int i=preProcFrom;i<=preProcTo;i++) { - result+=mBuffer[i]+'\n'; + if (mBuffer[i].endsWith('/')) { + result+=mBuffer[i].mid(0,mBuffer[i].size()-1)+' '; + } else { + result+=mBuffer[i]+' '; + } mResult.append("");// defines resolve into empty files, except #define and #include } // Step over @@ -31,6 +93,12 @@ QString CppPreprocessor::getNextPreprocessor() return result; } +void CppPreprocessor::simplify(QString &output) +{ + // Remove # + output = output.mid(1).trimmed(); +} + void CppPreprocessor::handleBranch(const QString &line) { if (line.startsWith("ifdef")) { @@ -222,14 +290,14 @@ void CppPreprocessor::expandMacro(const QString &line, QString &newLine, QString } else { int index; PDefine define = getDefine(word,index); - if (define && define->args=="" && (!define->isMultiLine)) { + if (define && define->args=="" ) { //newLine:=newLine+RemoveGCCAttributes(define^.Value); if (define->value != word ) newLine += expandMacros(define->value,depth+1); else newLine += word; - } else if (define && (!define->isMultiLine) && (define->args!="")) { + } else if (define && (define->args!="")) { while ((ifileIncludes = mCurrentIncludes; // Don't parse stuff we have already parsed - if ((!bufferedText.isEmpty()) || !mScannedFiles.contains(fileName)) { + if ((!bufferedText.isEmpty()) || !mScannedFiles->contains(fileName)) { // Parse ONCE //if not Assigned(Stream) then - mScannedFiles.insert(fileName); + mScannedFiles->insert(fileName); // Only load up the file if we are allowed to parse it bool isSystemFile = isSystemHeaderFile(fileName, mIncludePaths); @@ -433,7 +552,7 @@ void CppPreprocessor::addDefinesInFile(const QString &fileName) mProcessed.insert(fileName); //todo: why test this? - if (!mScannedFiles.contains(fileName)) + if (!mScannedFiles->contains(fileName)) return; //May be redefined, so order is important @@ -454,6 +573,78 @@ void CppPreprocessor::addDefinesInFile(const QString &fileName) } } +void CppPreprocessor::parseArgs(PDefine define) +{ + QString args=define->args.mid(1,define->args.length()-2).trimmed(); // remove '(' ')' + + if(args=="") + return ; + define->argList = args.split(','); + for (int i;iargList.size();i++) { + define->argList[i]=define->argList[i].trimmed(); + } + QStringList tokens = tokenizeValue(define->value); + + QString formatStr = ""; + QString lastToken = "##"; + for (QString token: tokens) { + if (lastToken != "##" && token!="##") { + formatStr += ' '; + } + int index = define->argList.indexOf(token); + if (index>=0) { + if (lastToken == "#") { + formatStr+= "\"%"+QString("%1").arg(index+1)+"\""; + } else { + formatStr+= "%"+QString("%1").arg(index+1); + } + } else if (token == "%"){ + formatStr+="%%"; + } + lastToken = token; + } + define->formatValue = formatStr; +} + +QStringList CppPreprocessor::tokenizeValue(const QString &value) +{ + int i=0; + QString token; + QStringList tokens; + while (i='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9')) { @@ -795,8 +1004,10 @@ QString CppPreprocessor::expandFunction(PDefine define, QString args) QStringList argValues = args.split(","); for (QString argValue:argValues) { - result=result.arg(argValue); + result=result.arg(argValue.trimmed()); } + result.replace("%%","%"); + return result; } diff --git a/RedPandaIDE/parser/cpppreprocessor.h b/RedPandaIDE/parser/cpppreprocessor.h index f3a38b07..0f18a89f 100644 --- a/RedPandaIDE/parser/cpppreprocessor.h +++ b/RedPandaIDE/parser/cpppreprocessor.h @@ -67,7 +67,8 @@ private: QString expandMacros(const QString& line, int depth); void expandMacro(const QString& line, QString& newLine, QString& word, int& i, int depth); QString removeGCCAttributes(const QString& line); - QString removeSuffixes(const QString& input); + void removeGCCAttribute(const QString&line, QString& newLine, int &i, const QString& word); + // current file stuff PParsedFile getInclude(int index); void openInclude(const QString& fileName, QStringList bufferedText=QStringList()); @@ -77,11 +78,14 @@ private: bool getCurrentBranch(); void setCurrentBranch(bool value); void removeCurrentBranch(); - QString getResult(); + QStringList getResult(); // include stuff PFileIncludes getFileIncludesEntry(const QString& FileName); void addDefinesInFile(const QString& fileName); + void parseArgs(PDefine define); + QStringList tokenizeValue(const QString& value); + QStringList removeComments(const QStringList& text); /* * '_','a'..'z','A'..'Z','0'..'9' @@ -159,7 +163,7 @@ private: QStringList mProjectIncludePaths; bool mParseSystem; bool mParseLocal; - QSet mScannedFiles; + std::shared_ptr> mScannedFiles; QSet mProcessed; // dictionary to save filename already processed }; diff --git a/RedPandaIDE/parser/utils.h b/RedPandaIDE/parser/utils.h index c0c70f53..8dce390f 100644 --- a/RedPandaIDE/parser/utils.h +++ b/RedPandaIDE/parser/utils.h @@ -10,7 +10,6 @@ struct Define { QString args; QString value; QString filename; - bool isMultiLine; // if true the expanded macro will span multiline bool hardCoded;// if true, don't free memory (points to hard defines) QStringList argList; // args list to format values QString formatValue; // format template to format values