work save
This commit is contained in:
parent
9c42a11c0b
commit
7d30690227
|
@ -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>();
|
||||
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<DefineMap>();
|
||||
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 ((i<lenLine) && (line[i] == ' ' || line[i]=='\t'))
|
||||
i++;
|
||||
int argStart=-1;
|
||||
|
@ -263,6 +331,57 @@ void CppPreprocessor::expandMacro(const QString &line, QString &newLine, QString
|
|||
}
|
||||
}
|
||||
|
||||
QString CppPreprocessor::removeGCCAttributes(const QString &line)
|
||||
{
|
||||
QString newLine = "";
|
||||
QString word = "";
|
||||
int lenLine = line.length();
|
||||
int i=1;
|
||||
while(i< lenLine) {
|
||||
if (isWordChar(line[i])) {
|
||||
word += line[i];
|
||||
} else {
|
||||
if (!word.isEmpty()) {
|
||||
removeGCCAttribute(line,newLine,i,word);
|
||||
}
|
||||
word = "";
|
||||
if (i<=lenLine) {
|
||||
newLine = newLine+line[i];
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!word.isEmpty())
|
||||
removeGCCAttribute(line,newLine,i,word);
|
||||
return newLine;
|
||||
}
|
||||
|
||||
void CppPreprocessor::removeGCCAttribute(const QString &line, QString &newLine, int &i, const QString &word)
|
||||
{
|
||||
int lenLine = line.length();
|
||||
int level = 0;
|
||||
if (word=="__attribute__") {
|
||||
while ( (i<lenLine) && isSpaceChar(line[i]))
|
||||
i++;
|
||||
if ((i<lenLine) && (line[i]=='(')) {
|
||||
level=0;
|
||||
while (i<lenLine) {
|
||||
switch(line[i].unicode()) {
|
||||
case '(': level++;
|
||||
break;
|
||||
case ')': level--;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
if (level==0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newLine += word;
|
||||
}
|
||||
}
|
||||
|
||||
PParsedFile CppPreprocessor::getInclude(int index)
|
||||
{
|
||||
return mIncludes[index];
|
||||
|
@ -328,10 +447,10 @@ void CppPreprocessor::openInclude(const QString &fileName, QStringList bufferedT
|
|||
parsedFile->fileIncludes = 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;i<define->argList.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<value.length()) {
|
||||
QChar ch = value[i];
|
||||
if (isSpaceChar(ch)) {
|
||||
if(!token.isEmpty())
|
||||
tokens.append(token);
|
||||
token = "";
|
||||
i++;
|
||||
} else if (ch=='#') {
|
||||
if(!token.isEmpty())
|
||||
tokens.append(token);
|
||||
token = "";
|
||||
if ((i+1<value.length()) && (value[i+1]=='#')) {
|
||||
i+=2;
|
||||
tokens.append("##");
|
||||
} else {
|
||||
i++;
|
||||
tokens.append("#");
|
||||
}
|
||||
} else if (isWordChar(ch)) {
|
||||
token+=ch;
|
||||
i++;
|
||||
} else {
|
||||
if(!token.isEmpty())
|
||||
tokens.append(token);
|
||||
token = "";
|
||||
tokens.append(ch);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if(!token.isEmpty())
|
||||
tokens.append(token);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
QStringList CppPreprocessor::removeComments(const QStringList &text)
|
||||
{
|
||||
QStringList result;
|
||||
|
@ -461,7 +652,6 @@ QStringList CppPreprocessor::removeComments(const QStringList &text)
|
|||
QString delimiter;
|
||||
|
||||
for (QString line:text) {
|
||||
QChar lastCh;
|
||||
QString s;
|
||||
int pos = 0;
|
||||
bool stopProcess=false;
|
||||
|
@ -578,6 +768,25 @@ void CppPreprocessor::preprocessBuffer()
|
|||
}
|
||||
}
|
||||
|
||||
void CppPreprocessor::skipToEndOfPreprocessor()
|
||||
{
|
||||
// Skip until last char of line is NOT \ anymore
|
||||
while ((mIndex < mBuffer.count()) && mBuffer[mIndex].endsWith('\\'))
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
void CppPreprocessor::skipToPreprocessor()
|
||||
{
|
||||
// Increment until a line begins with a #
|
||||
while ((mIndex < mBuffer.count()) && !mBuffer[mIndex].startsWith('#')) {
|
||||
if (getCurrentBranch()) // if not skipping, expand current macros
|
||||
mResult.append(expandMacros(mBuffer[mIndex],1));
|
||||
else // If skipping due to a failed branch, clear line
|
||||
mResult.append("");
|
||||
mIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
bool CppPreprocessor::isWordChar(const QChar &ch)
|
||||
{
|
||||
if (ch=='_' || (ch>='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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<QString> mScannedFiles;
|
||||
std::shared_ptr<QSet<QString>> mScannedFiles;
|
||||
QSet<QString> mProcessed; // dictionary to save filename already processed
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue