void LocationTable::splitByAnchors(const PreprocessedContents& text, const Anchor& textStartPosition, QList<PreprocessedContents>& strings, QList<Anchor>& anchors) const { Anchor currentAnchor = Anchor(textStartPosition); size_t currentOffset = 0; QMapIterator<std::size_t, Anchor> it = m_offsetTable; while (currentOffset < (size_t)text.size()) { Anchor nextAnchor(KDevelop::CursorInRevision::invalid()); size_t nextOffset; if(it.hasNext()) { it.next(); nextOffset = it.key(); nextAnchor = it.value(); }else{ nextOffset = text.size(); nextAnchor = Anchor(KDevelop::CursorInRevision::invalid()); } if( nextOffset-currentOffset > 0 ) { strings.append(text.mid(currentOffset, nextOffset-currentOffset)); anchors.append(currentAnchor); } currentOffset = nextOffset; currentAnchor = nextAnchor; } }
LocationTable::LocationTable(const PreprocessedContents& contents) : m_positionAtLastOffset(EMPTY_CACHE) { anchor(0, Anchor(0,0), 0); const unsigned int newline = indexFromCharacter('\n'); int line = 0; for (std::size_t i = 0; i < (std::size_t)contents.size(); ++i) if (contents.at(i) == newline) anchor(i + 1, Anchor(++line, 0), 0); }
void pp::handle_include(bool skip_current_path, Stream& input, Stream& output) { if (isLetter(input.current()) || input == '_') { pp_macro_expander expand_include(this); Anchor inputPosition = input.inputPosition(); SimpleCursor originalInputPosition = input.originalInputPosition(); PreprocessedContents includeString; { Stream cs(&includeString); expand_include(input, cs); } skip_blanks(input, devnull()); RETURN_ON_FAIL(!includeString.isEmpty() && (includeString.first() == indexFromCharacter('<') || includeString.first() == indexFromCharacter('"'))); Stream newInput(&includeString, inputPosition); newInput.setOriginalInputPosition(originalInputPosition); handle_include(skip_current_path, newInput, output); return; } RETURN_ON_FAIL(input == '<' || input == '"'); char quote((input == '"') ? '"' : '>'); ++input; PreprocessedContents includeNameB; while (!input.atEnd() && input != quote) { RETURN_ON_FAIL(input != '\n'); includeNameB.append(input); ++input; } QString includeName(QString::fromUtf8(stringFromContents(includeNameB))); Stream* include = m_preprocessor->sourceNeeded(includeName, quote == '"' ? Preprocessor::IncludeLocal : Preprocessor::IncludeGlobal, input.inputPosition().line, skip_current_path); if (include && !include->atEnd()) { // m_files.push(IndexedString(includeName)); // output.mark(Anchor(0, 0)); operator()(*include, output); // restore the file name and sync the buffer // output.mark(input.inputPosition()); } delete include; }
void pp::processFileInternal(const QString& fileName, const QByteArray& fileContents, PreprocessedContents& result) { m_files.push(IndexedString(fileName)); // Guestimate as to how much expansion will occur result.reserve(int(fileContents.length() * 1.2)); PreprocessedContents contents = convertFromByteArray(fileContents); { Stream is(&contents); Stream rs(&result, m_environment->locationTable()); operator () (is, rs); } result.squeeze(); }
PreprocessedContents tokenizeFromByteArray(const QByteArray& array) { PreprocessedContents to; const char* data = array.constData(); const char* dataEnd = data + array.size(); //unsigned int* target = to.data(); KDevVarLengthArray<char, 100> identifier; KDevelop::IndexedString::RunningHash hash; bool tokenizing = false; while(data < dataEnd) { if(!tokenizing) { if(isLetter(*data) || *data == '_') tokenizing = true; } if(tokenizing) { if(isLetterOrNumber(*data) || *data == '_') { hash.append(*data); identifier.append(*data); }else{ //End of token to.append( KDevelop::IndexedString(identifier.constData(), identifier.size(), hash.hash).index() ); //kDebug() << "word" << "\"" + KDevelop::IndexedString(to.back()).str() + "\""; hash.clear(); identifier.clear(); tokenizing = false; } } if(!tokenizing) to.append( indexFromCharacter(*data) ); ++data; } if(tokenizing) to.append( KDevelop::IndexedString(identifier.constData(), identifier.size(), hash.hash).index() ); /* kDebug() << QString::fromUtf8(stringFromContents(to)); kDebug() << QString::fromUtf8(array); Q_ASSERT(stringFromContents(to) == array);*/ return to; }
PreprocessedContents convertFromByteArray(const QByteArray& array) { PreprocessedContents to; to.resize(array.size()); const char* data = array.constData(); const char* dataEnd = data + array.size(); unsigned int* target = to.data(); while(data < dataEnd) { *target = indexFromCharacter(*data); ++data; ++target; } return to; }
QByteArray stringFromContents(const PreprocessedContents& contents, int offset, int count) { QByteArray ret; for(int a = offset; a < (count ? offset+count : contents.size()); ++a) { if(isCharacter(contents[a])) ret.append(characterFromIndex(contents[a])); else ret += KDevelop::IndexedString::fromIndex(contents[a]).byteArray(); } return ret; }
void pp::handle_include(bool skip_current_path, Stream& input, Stream& output) { if (input.atEnd()) { createProblem(input, i18n("invalid include directive")); return; } QByteArray bytes = KDevelop::IndexedString::fromIndex(input.current()).byteArray(); if (bytes.size() > 0 && (isLetter(bytes.at(0)) || bytes.at(0) == '_')) { pp_macro_expander expand_include(this); Anchor inputPosition = input.inputPosition(); KDevelop::CursorInRevision originalInputPosition = input.originalInputPosition(); PreprocessedContents includeString; { Stream cs(&includeString); expand_include(input, cs); } skip_blanks(input, devnull()); RETURN_ON_FAIL(!includeString.isEmpty() && (includeString.first() == indexFromCharacter('<') || includeString.first() == indexFromCharacter('"'))); // Filter out whitespaces PreprocessedContents filteredIncludeString; if(!includeString.empty() && includeString.front() == indexFromCharacter('"')) { // Don't filter if it is a string token filteredIncludeString = includeString; } else { // Filter out whitespaces, as the preprocessor adds them in random places to prevent implicit token merging foreach(uint index, includeString) if(index != indexFromCharacter(' ')) filteredIncludeString.push_back(index); } Stream newInput(&filteredIncludeString, inputPosition); newInput.setOriginalInputPosition(originalInputPosition); handle_include(skip_current_path, newInput, output); return; }