// ************************************************************************** // // (C) Copyright 2009 Swiss SIMTEC AG // // ************************************************************************** // // $HeadURL$ // $LastChangedBy$ // $LastChangedDate$ // $LastChangedRevision$ // // ************************************************************************** // manual class headers #include "LogViewXdrParser.hpp" // from cpp_includes #include "LogViewXdrElement.hpp" #include #include "LogViewXdrStruct.hpp" #include "LogViewField.hpp" #include "LogViewXdrValue.hpp" #include "LogViewXdrType.hpp" #include #include #include namespace N_LogView { LogViewXdrParser::LogViewXdrParser() : m_WithinComment(false) , m_LineNbr(0) , m_DoReadUntilSemicolon(false) , m_WordListIndex(0) , m_ActElement(nullptr) , m_State(e_ParseMain) , m_logger(getLogger("LogViewXdrParser")) {} LogViewXdrParser::~LogViewXdrParser() { for (const auto &elem : m_ElementMap) delete elem.second; } // --------------------------------------------------------------- void LogViewXdrParser::addStandardType(const QString& a_name, const uint16_t a_dataSize, const uint16_t a_realSize, const LogViewXdrStandardType::E_ValueKind a_kind, const LogViewXdrStandardType::E_DynArraySizeMethod a_dynArraySizeMethod, const LogViewXdrStandardType::E_ByteOrder a_byteOrder) { QString name = a_name.trimmed(); auto ptr = new LogViewXdrStandardType(name, a_dataSize, a_realSize, a_kind, a_dynArraySizeMethod, a_byteOrder); if (!addToElementMap(name, ptr)) delete ptr; if ((a_dynArraySizeMethod == LogViewXdrStandardType::e_DynArrayIndex || a_dynArraySizeMethod == LogViewXdrStandardType::e_DynArrayIndexDiv8) && a_kind != LogViewXdrStandardType::e_Unsigned) showErrorMessage(QObject::tr("Standard-typ \'%1\': e_DynArrayIndex oder e_DynArrayIndexDiv darf nur mit e_Unsigned verwendet werden!")); } // --------------------------------------------------------------- void LogViewXdrParser::parseX_File(const QString& a_fileName) { for (const auto &elem : m_ElementMap) delete elem.second; m_ElementMap.clear(); m_DefinesMap.clear(); m_TelegramMap.clear(); m_LineNbr = 0; m_WordListIndex = 0; m_WithinComment = false; m_ActElement = nullptr; m_State = e_ParseMain; // define some (XDR-)standard-types addStandardType(QLatin1String("unsigned short"), 4, 2, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("unsigned int"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("short"), 4, 2, LogViewXdrStandardType::e_Signed); addStandardType(QLatin1String("int"), 4, 4, LogViewXdrStandardType::e_Signed); addStandardType(QLatin1String("u_int"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("char"), 4, 2, LogViewXdrStandardType::e_Character); addStandardType(QLatin1String("unsigned char"), 4, 1, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("unsigned long"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("u_long"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("u_short"), 4, 2, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("float"), 4, 4, LogViewXdrStandardType::e_Float, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderBigEndian); addStandardType(QLatin1String("double"), 8, 8, LogViewXdrStandardType::e_Float, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderBigEndian); addStandardType(QLatin1String("opaque"), 1, 1, LogViewXdrStandardType::e_Data); addStandardType(QLatin1String("string"), 1, 1, LogViewXdrStandardType::e_Character); // for tetra-telegrams addStandardType(QLatin1String("alpha"), 1, 1, LogViewXdrStandardType::e_Character); addStandardType(QLatin1String("UInt8"), 1, 1, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("UInt16"), 2, 2, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("UInt24"), 3, 3, LogViewXdrStandardType::e_Unsigned); addStandardType(QLatin1String("SInt8"), 1, 1, LogViewXdrStandardType::e_Signed); addStandardType(QLatin1String("SInt16"), 2, 2, LogViewXdrStandardType::e_Signed); addStandardType(QLatin1String("SInt24"), 3, 3, LogViewXdrStandardType::e_Signed); // little-endian values (for TETRA-header) addStandardType(QLatin1String("UInt16LE"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian); addStandardType(QLatin1String("UInt32LE"), 4, 4, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian); // index for next dyn. array (only for TETRA) addStandardType(QLatin1String("UInt8Idx"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex); addStandardType(QLatin1String("UInt16Idx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex); addStandardType(QLatin1String("UInt16LEIdx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex, LogViewXdrStandardType::e_ByteOrderLittleEndian); // index (div 8) for next dyn. array (only for TETRA) addStandardType(QLatin1String("UInt8IdxDiv8"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8); addStandardType(QLatin1String("UInt16IdxDiv8"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8); const auto DEFINE_NAME = QLatin1String("%#define"); // parse the file m_Filename = a_fileName; m_State = e_ParseMain; QFile xFile(a_fileName); if (xFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QString lastLines; uint32_t lastLinesCount = 0; QTextStream in(&xFile); while (!in.atEnd()) { m_Line = lastLines + QLatin1Char(' ') + in.readLine(); m_Line = m_Line.simplified(); m_LineNbr++; // INFO_LOG(m_logger) << m_LineNbr << ": " << m_Line.toStdString(); // ignore lines with % if (m_Line.startsWith(QLatin1Char('%')) && !m_Line.startsWith(DEFINE_NAME)) { continue; } // remove comments (sourounded with /* */) const QString cleanLine = removeComments(m_Line).simplified(); // ignore empty lines if (cleanLine.isEmpty()) { continue; } // INFO_LOG(m_logger) << "w/o comment: \'" << cleanLine.toStdString() << "\'"; // read in whole construct if (m_DoReadUntilSemicolon && !cleanLine.endsWith(QLatin1Char(';'))) { lastLines = cleanLine; m_LineNbr--; lastLinesCount++; continue; } lastLines.clear(); // check whether it is the begin of a construct if (e_ParseMain == m_State) { if (cleanLine.startsWith(QLatin1String("union "))) { m_State = e_ParseUnion; } else if (cleanLine.startsWith(QLatin1String("struct "))) { m_State = e_ParseStruct; } } // parse the line when we are within switch (m_State) { case e_ParseUnion: parseUnion(cleanLine); break; case e_ParseStruct: parseStruct(cleanLine); break; case e_ParseEnum: parseEnum(cleanLine); break; default: if (m_Line.startsWith(DEFINE_NAME)) { parseDefine(m_Line.mid(DEFINE_NAME.size())); } else if (cleanLine.startsWith(QLatin1String("typedef "))) { parseTypedef(cleanLine); } else if (cleanLine.startsWith(QLatin1String("enum "))) { parseEnum(cleanLine.mid(5)); } else if (cleanLine.startsWith(QLatin1String("enum8 "))) { parseEnum(cleanLine.mid(6), 1); } else if (cleanLine.startsWith(QLatin1String("enum16 "))) { parseEnum(cleanLine.mid(7), 2); } } if (lastLinesCount > 0) { m_LineNbr += lastLinesCount; lastLinesCount = 0; } } xFile.close(); // erase all parsing-values (otherwise errormessages will have wrong informations) m_LineNbr = 0; m_Line.clear(); } else { QMessageBox::warning(nullptr, QLatin1String("Dateifehler"), QStringLiteral("Konnte die Datei %1 nicht öffnen").arg(a_fileName)); } } // --------------------------------------------------------------- QString LogViewXdrParser::removeComments(const QString& a_line) { static const QChar slash(QLatin1Char('/')); static const QChar asterik(QLatin1Char('*')); // remove comments (sourounded with /* */) QString cleanLine; cleanLine.reserve(a_line.size()); QString::const_iterator iter = a_line.begin(); QString::const_iterator end = a_line.end(); while (iter != end) { if (!m_WithinComment) { // does comment begin? if (slash == *iter) { if (++iter != end) { if (asterik == *iter) { // yes, comment begins m_WithinComment = true; } else { // no comment begin cleanLine.append(slash); cleanLine.append(*iter); } } else { // end of line cleanLine.append(slash); } } else { // no cleanLine.append(*iter); } } else { // does comment end? if (asterik == *iter) { if (++iter != end) { if (slash == *iter) { m_WithinComment = false; } } } } if (iter != end) ++iter; } return cleanLine; } // --------------------------------------------------------------- void LogViewXdrParser::parseTypedef(const QString &a_line) { fillWordList(a_line); // typedef: "typedef telegramm_id_int_et telegramm_id_et;" // ------- // keyword 'typedef' if (isNextWord("typedef")) { // get type bool ok; QString type = getNextType(ok); // fixme: make boolean for structure wrong and gray out telegrams with wrong struct getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure // get name QString name = getNextWord("Name"); if (name.isEmpty()) return; if (!isNextWord(";")) return; // all ok uint16_t dynArrayOffset; uint16_t arraySize = parseArray(name, dynArrayOffset); LogViewXdrType* typedefElement = new LogViewXdrType(name, type, arraySize, dynArrayOffset, LogViewXdrElement::e_KindTypedef); if (!addToElementMap(name, typedefElement)) delete typedefElement; } } // --------------------------------------------------------------- void LogViewXdrParser::parseDefine(const QString &a_line) { const QString line = a_line.trimmed(); int sepPos = line.indexOf(QLatin1Char(' ')); if (sepPos >= 0) { const QString name = line.leftRef(sepPos).trimmed().toString(); QStringRef substitution = line.midRef(sepPos).trimmed(); sepPos = substitution.indexOf(QLatin1Char(' ')); if (sepPos >= 0) substitution = substitution.left(sepPos).trimmed(); // convert to number bool ok = false; const int64_t value = calcValue(substitution.toString(), ok); if (ok) { //INFO_LOG(m_logger) << "Define: name=" << name.toStdString() << " subst=" << substitution.toStdString() << " value=" << value; m_DefinesMap.insert(std::make_pair(name, LogViewXdrValue(name, value, LogViewXdrElement::e_KindDefine))); } } else { showErrorMessage(QObject::tr("Space zwischen define-name und substitution nicht gefunden")); } } // --------------------------------------------------------------- void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSize) { if (QLatin1String("};") != a_line) { switch(m_State) { default: // first line of enum containing the name // i.e.: "enum telegramm_id_int_et {" if (a_line.endsWith(QLatin1String(" {"))) { m_State = e_ParseEnum; const QString name = a_line.leftRef(a_line.length()-2).trimmed().toString(); m_ActElement = new LogViewXdrStruct(name, LogViewXdrElement::e_KindEnum, a_enumSize); if (!addToElementMap(name, m_ActElement)) { delete m_ActElement; m_ActElement = nullptr; return; } } else { showErrorMessage(QObject::tr("Endet nicht mit {")); } break; case e_ParseEnum: { // middle lines of struct containing the elements // i.e.: "MANIPULATIONSMELDUNG = 2," QString name; QString valueText; if (parseEnumLine(a_line, name, valueText)) { // is the valueText a previous enum-element? bool error = true; uint32_t enumValue = m_ActElement->getChildValue(valueText, &error); if (!error) { valueText = QString::number(enumValue); } // calculate bool ok; int64_t value = calcValue(valueText, ok); if (ok) m_ActElement->addElement(name, value, LogViewXdrElement::e_KindEnumElement); else ERROR_LOG(m_logger) << "Problem with converting text to number: name=" << name.toStdString() << " valueText=" << valueText.toStdString(); } } break; } } else { // end of struct m_State = e_ParseMain; //INFO_LOG(m_logger) << "CheckEnum " << m_ActElement->getName().toStdString(); // check(*m_ActElement); } } // --------------------------------------------------------------- void LogViewXdrParser::parseStruct(const QString &a_line) { fillWordList(a_line); if (!m_DoReadUntilSemicolon) { // first line of struct: "struct gef_wirkfeld_flaechendeckendes_feuer_meldung_rt {" // -------------------- // keyword 'union' if (isNextWord("struct")) { // union name QString structName = getNextWord("Struktur-Name"); if (structName.isEmpty()) return; if (!isNextWord("{")) return; // all ok => proceed parsing union m_ActElement = new LogViewXdrStruct(structName, LogViewXdrElement::e_KindStruct); if (!addToElementMap(structName, m_ActElement)) { delete m_ActElement; m_ActElement = nullptr; return; } m_State = e_ParseStruct; m_DoReadUntilSemicolon = true; } } else { if (!isNextWord("}", false)) { // next lines of struct: "gef_header_rt:3..6 header;" // -------------------- // get type bool ok; QString type = getNextType(ok); if (!ok) return; // fixme: make boolean for structure wrong and gray out telegrams with wrong struct if (m_UnionType != type) getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure // get bitfield (if any) ":2..5" int16_t firstBit = -1; int16_t lastBit = -1; bool isLast = true; if (isNextWord(":", false)) { isNextWord(":"); QString bitfield = getNextWord("Bitfield"); isLast = parseBitfield(bitfield, firstBit, lastBit); } // get name QString name = getNextWord("Name"); if (name.isEmpty()) return; if (!isNextWord(";")) return; // all ok uint16_t dynArrayOffset; uint16_t arraySize = parseArray(name, dynArrayOffset); if(firstBit >= 0) DEBUG_LOG(m_logger) << "Add Element " << name << " with type " << type << " array size: " << arraySize << " first:last " << firstBit << ":" << lastBit << " isLast: " << isLast; m_ActElement->addElement(name, type, arraySize, dynArrayOffset, LogViewXdrElement::e_KindStructElement, firstBit, lastBit, isLast); } else { // end of struct "};" if (!isNextWord("}")) return; if (!isNextWord(";")) return; m_State = e_ParseMain; m_DoReadUntilSemicolon = false; // INFO_LOG(m_logger) << "CheckStruct \'" << m_ActElement->getName().toStdString() << "\'"; // if (m_ActElement->getName() != "intern_tele") // fixme: remove this structure from element-map // { // check(*m_ActElement); // } } } } // --------------------------------------------------------------- void LogViewXdrParser::parseUnion(const QString& a_line) { // we can not really parse the union, we expect that only 1 union exists, and this // union holds all the telegrams, which we insert into a telegram-list static const LogViewXdrStruct* telegramIdType = nullptr; fillWordList(a_line); if (!m_DoReadUntilSemicolon) { // first line of union "union gef_tg_nd_ switch (gef_telegramm_id_et telegramm_id) {" // ------------------- // keyword 'union' if (isNextWord("union")) { // union name m_UnionType = getNextWord("Union-Typ"); if (m_UnionType.isEmpty()) return; // keyword 'switch' if (!isNextWord("switch")) return; if (!isNextWord("(")) return; // telegram-id-type getNextEnum(telegramIdType); if (telegramIdType == nullptr) return; // telegram-id-name QString name = getNextWord("Parameter-Name"); if (name.isEmpty()) return; if (!isNextWord(")")) return; if (!isNextWord("{")) return; // all ok => proceed parsing union m_State = e_ParseUnion; m_DoReadUntilSemicolon = true; } } else { if (!isNextWord("}", false)) { QString keyword = getNextWord(); if (keyword == QLatin1String("case")) { // next lines of union "case GEF_INIT: gef_init_meldung_rt init_meldung;" // ------------------- QStringList constExprList; QString type; do { // get constant-expression QString constExpression = getNextWord("Konstanten-Ausdruck"); if (constExpression.isEmpty()) return; constExprList << constExpression; // check double-point if (!isNextWord(":")) return; // get type or another case type = getNextWord("Typ"); if (type.isEmpty()) return; } while (type == QLatin1String("case")); // fixme: make boolean for structure wrong and gray out telegrams with wrong struct getElement(type); // do not abort when type does not exist, otherwise we will never get an error, when we try to show a telegram with a wrong structure // get name QString name = getNextWord("Name"); if (name.isEmpty()) return; // check semicolon if (!isNextWord(";")) return; // all ok => add to telegram-map for (const QString &constExpr : qAsConst(constExprList)) { bool error; int32_t telegramId = static_cast(telegramIdType->getChildValue(constExpr, &error)); if (!error) { m_TelegramMap.insert(std::make_pair(telegramId, LogViewXdrType(constExpr, type, 1, 0, LogViewXdrElement::e_KindEnumElement))); // fixme: e_KindCaseElement und 1 entfernen } else { showErrorMessage(QObject::tr("\'%1\' ist nicht definiert in \'%2\'").arg(constExpr, telegramIdType->getName())); } } } else if (keyword == QLatin1String("default")) { // check double-point if (isNextWord(":")) { QString defaultDefinition = getNextWord(); if (defaultDefinition == QLatin1String("void")) { isNextWord(";"); // all ok } else { showErrorMessage(QObject::tr("default: muss void; enthalten. Falls nicht, muss das richtige Verhalten implementiert werden...")); } } } else { showErrorMessage(QObject::tr("Erwarte Keyword case oder default statt \'%1\'").arg(keyword)); } } else { // end of union "};" if (!isNextWord("}")) return; if (!isNextWord(";")) return; m_State = e_ParseMain; m_DoReadUntilSemicolon = false; //check(*m_ActElement); } } } // --------------------------------------------------------------- bool LogViewXdrParser::parseEnumLine(const QString& a_line, QString& a_name, QString& a_value) const { QString line; if (a_line.endsWith(QLatin1Char(','))) { line = a_line.left(a_line.length()-1); } else { line = a_line; } line = line.trimmed(); int sepPos = line.lastIndexOf(QLatin1Char('=')); if (-1 != sepPos) { a_name = line.leftRef(sepPos).trimmed().toString(); a_value = line.midRef(sepPos+1).trimmed().toString(); return true; // successful } else { showErrorMessage(QObject::tr("konnte Trennzeichen \'=\' zwischen Name und Wert nicht finden!")); } return false; // failure happenend } // --------------------------------------------------------------- // Shows an error-message containing the line-nbr, the line // itself and an additional error-text // --------------------------------------------------------------- void LogViewXdrParser::showErrorMessage(const QString& a_errorText) const { const auto tlws = QApplication::topLevelWidgets(); QMessageBox::warning(tlws.size() ? tlws.first() : nullptr, QObject::tr("Telegram Structure Parser"), QStringLiteral("%4:%1:
%2


%3").arg(m_LineNbr).arg(m_Line, a_errorText, m_Filename)); } // --------------------------------------------------------------- int64_t LogViewXdrParser::calcValue(const QString& a_calcText, bool& a_isOk) { // ignore strings a_isOk = false; int64_t value = 0; if (!a_calcText.startsWith(QLatin1Char('\"'))) { N_SST::IntegerCalculator::E_Error error; std::string errorText; value = calc(a_calcText.toStdString(), error, &errorText); // show error if one happend if (error != N_SST::IntegerCalculator::e_Ok) { switch (error) { case N_SST::IntegerCalculator::e_DivisionByZero: showErrorMessage(QObject::tr("Division durch 0 nicht erlaubt!")); break; case N_SST::IntegerCalculator::e_InvalidOperand: showErrorMessage(QObject::tr("Operand %1 ist fehlerhaft!").arg(QString::fromStdString(errorText))); break; case N_SST::IntegerCalculator::e_MissingLeftParanthesis: showErrorMessage(QObject::tr("Es fehlen Klammer Öffnungen (!")); break; case N_SST::IntegerCalculator::e_MissingRightParanthesis: showErrorMessage(QObject::tr("Es fehlen Klammer Schliessungen )!")); break; case N_SST::IntegerCalculator::e_NoOperandBetweenOperators: showErrorMessage(QObject::tr("Zwei Operationen (%1) nacheinander sind nicht erlaubt!").arg(QString::fromStdString(errorText))); break; case N_SST::IntegerCalculator::e_UnknownOperationOrVariable: showErrorMessage(QObject::tr("Operation oder Variable %1 unbekannt!").arg(QString::fromStdString(errorText))); break; case N_SST::IntegerCalculator::e_UnknownError: showErrorMessage(QObject::tr("Unbekannter Fehler!")); break; default: break; } ERROR_LOG(m_logger) << "Problem with converting '" << a_calcText << "' to integer"; } else { a_isOk = true; } } return value; } // --------------------------------------------------------------- bool LogViewXdrParser::getVariableValue(const std::string& a_variableName, int64_t& a_value) const { return getDefine(QString::fromStdString(a_variableName), a_value); } // --------------------------------------------------------------- // This function delivers the name of the telegram and the // name of its structure. The telegram will be defined with // a_telegramId. // The name will be delivered as return-parameter; the // structure-name as out parameter a_structName. // If the telegram was not found, error-texts instead names // will be returned. // --------------------------------------------------------------- QString LogViewXdrParser::getTelegramName(int a_telegramId) const { const auto iter = m_TelegramMap.find(a_telegramId); if (m_TelegramMap.end() != iter) return iter->second.getName(); return QObject::tr("").arg(a_telegramId); } // --------------------------------------------------------------- QString LogViewXdrParser::getStructName(int a_telegramId) const { const auto iter = m_TelegramMap.find(a_telegramId); if (m_TelegramMap.end() != iter) return iter->second.getType(); return QObject::tr("").arg(a_telegramId); } // --------------------------------------------------------------- bool LogViewXdrParser::getDefine(const QString& a_name, int64_t& a_value) const { const auto iter = m_DefinesMap.find(a_name); if (iter != m_DefinesMap.end()) { a_value = iter->second.getValue(); return true; } return false; } // --------------------------------------------------------------- const LogViewXdrElement* LogViewXdrParser::getElement(const QString& a_name) const { const auto iter = m_ElementMap.find(a_name); if (iter != m_ElementMap.end()) return iter->second; showErrorMessage(QObject::tr("Typ \'%1\' nicht definiert!").arg(a_name)); return nullptr; } // --------------------------------------------------------------- uint16_t LogViewXdrParser::parseArray(QString& a_name, uint16_t& a_dynArrayMsgOffset) const { a_dynArrayMsgOffset = 0; QString oldName = a_name; // is it a static array []? // ------------------------ int pos = a_name.indexOf(QLatin1Char('[')); if (pos >= 0) { int endPos = a_name.indexOf(QLatin1Char(']')); if (endPos > pos) { // get the array-size QString arraySizeText = a_name.mid(pos+1, endPos-pos-1); // set new name a_name = a_name.left(pos); // INFO_LOG(m_logger) << "new a_name=" << a_name.toStdString() << " arraySizeText=" << arraySizeText.toStdString(); int64_t arraySizeValue = 1; // check whether it is a define if (!getDefine(arraySizeText, arraySizeValue)) { bool ok = false; arraySizeValue = arraySizeText.toInt(&ok); if (!ok) { showErrorMessage(QObject::tr("%1: [%2] is not a number").arg(oldName, arraySizeText)); } } // INFO_LOG(m_logger) << "ArraySize=" << arraySizeValue; return arraySizeValue; } else { showErrorMessage(QObject::tr("%1: Did not found expected ']'").arg(oldName)); } } else { // is it an dynamic array <>? // -------------------------- //INFO_LOG(m_logger) << "check for <"; pos = a_name.indexOf(QLatin1Char('<')); if (pos >= 0) { int endPos = a_name.indexOf(QLatin1Char('>')); if (endPos > pos) { // get the array-size QString arraySizeText = a_name.mid(pos+1, endPos-pos-1); //INFO_LOG(m_logger) << "pos=" << pos << " endPos=" << endPos << " => " << arraySizeText.toStdString(); // set new name a_name = a_name.left(pos); // INFO_LOG(m_logger) << "new a_name=" << a_name.toStdString() << " arraySizeText=" << arraySizeText.toStdString(); // check whether it is a define int64_t arraySizeValue = 1; if (!getDefine(arraySizeText, arraySizeValue)) { bool ok = false; arraySizeValue = arraySizeText.toInt(&ok); if (!ok) { showErrorMessage(QObject::tr("%1: \'%2\' is not a number").arg(a_name, arraySizeText)); } else { // INFO_LOG(m_logger) << "a_name=" << a_name.toStdString() << " a_dynArrayMsgOffset=" << a_dynArrayMsgOffset; } } a_dynArrayMsgOffset = arraySizeValue; // INFO_LOG(m_logger) << a_name.toStdString() << " is a dynamic array with size=" << arraySizeValue; return 0; } else { showErrorMessage(QObject::tr("%1: Did not found expected '>'").arg(a_name)); } } } return 1; } // --------------------------------------------------------------- bool LogViewXdrParser::isNextWord(const char *a_word, const bool a_doIncrement) { const QString word = QString::fromUtf8(a_word); bool ok = (m_WordListIndex < m_WordList.size() && m_WordList.at(m_WordListIndex) == word); // show error-message if (!ok && a_doIncrement) { if (m_WordListIndex > 0) showErrorMessage(QObject::tr("Erwarte %1 nach \'%2\'!").arg(word, m_WordList.at(m_WordListIndex-1))); else showErrorMessage(QObject::tr("Erwarte %1!").arg(word)); } if (a_doIncrement) m_WordListIndex++; return ok; } // --------------------------------------------------------------- void LogViewXdrParser::fillWordList(const QString& a_line) { QString line = a_line; line.replace(QLatin1Char('('), QLatin1String(" ( ")); line.replace(QLatin1Char(')'), QLatin1String(" ) ")); line.replace(QLatin1Char('{'), QLatin1String(" { ")); line.replace(QLatin1Char('}'), QLatin1String(" } ")); line.replace(QLatin1Char(':'), QLatin1String(" : ")); line.replace(QLatin1Char(';'), QLatin1String(" ; ")); m_WordList = line.split(QLatin1Char(' '), QString::SkipEmptyParts); m_WordListIndex = 0; // ---------------------- // for debugging only // foreach (const QString &str, qAsConst(m_WordList)) // INFO_LOG(m_logger) << "word=" << str.toStdString(); // ---------------------- } // --------------------------------------------------------------- QString LogViewXdrParser::getNextWord(const char *a_errorText) { QString word; if (m_WordListIndex < m_WordList.size()) word = m_WordList.at(m_WordListIndex); if (word.isEmpty() && a_errorText) { const QString errTxt(QString::fromUtf8(a_errorText)); if (m_WordListIndex > 0) showErrorMessage(QObject::tr("Erwarte %1 nach \'%2\'!").arg(errTxt, m_WordList.at(m_WordListIndex-1))); else showErrorMessage(QObject::tr("Erwarte %1!").arg(errTxt)); } m_WordListIndex++; return word; } // --------------------------------------------------------------- QString LogViewXdrParser::getNextType(bool& a_ok) { a_ok = true; QString type = getNextWord("Typ"); if (type.isEmpty()) a_ok = false; if (type == QLatin1String("unsigned") || type == QLatin1String("signed")) { QString type2 = getNextWord("Typ"); if (type2.isEmpty()) a_ok = false; type = QStringLiteral("%1 %2").arg(type, type2); } return type; } // --------------------------------------------------------------- QString LogViewXdrParser::getNextEnum(const LogViewXdrStruct*& a_enumStruct) { QString type; a_enumStruct = nullptr; if (m_WordListIndex < m_WordList.size()) { type = m_WordList.at(m_WordListIndex); a_enumStruct = static_cast(getElement(type)); if (a_enumStruct) { if (LogViewXdrElement::e_KindEnum != a_enumStruct->getKind()) { showErrorMessage(QObject::tr("Typ \'%1\' muss ein Enum sein!").arg(type)); a_enumStruct = nullptr; } } else showErrorMessage(QObject::tr("Enum \'%1\' nicht definiert!").arg(type)); m_WordListIndex++; } return type; } // --------------------------------------------------------------- bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firstBit, int16_t& a_lastBit) const { // INFO_LOG(m_logger) << "a_fieldText=" << a_fieldText.toStdString(); // bitfield-definition: "0..2" a_firstBit = -1; a_lastBit = -1; bool isLast = true; // first bit int doublePointPos = a_fieldText.indexOf(QLatin1String("..")); if (doublePointPos != -1) { QString bitText = a_fieldText.left(doublePointPos); bool ok; a_firstBit = bitText.toInt(&ok); if (ok) { // last bit bitText = a_fieldText.mid(doublePointPos+2); // is it the last bitfield of this data-value (indicated by !) if (bitText.endsWith(QLatin1Char('!'))) { isLast = true; bitText.chop(1); } else { isLast = false; } a_lastBit = bitText.toInt(&ok); if (ok) { // remove bitfield-stuff // a_line = a_line.remove(bitfieldPos, endPos-bitfieldPos); } else { showErrorMessage(QObject::tr("Bitfeld-Defintion muss folgendes Format haben: :0..2. Zweites Bit (%1) ist keine Zahl!").arg(bitText)); } } else { showErrorMessage(QObject::tr("Bitfeld-Defintion muss folgendes Format haben: :0..2. Erstes Bit (%1) ist keine Zahl!").arg(bitText)); } } else { showErrorMessage(QObject::tr("Bitfeld-Defintion muss folgendes Format haben: :0..2. Habe .. nicht gefunden!")); } return isLast; } // --------------------------------------------------------------- // adds an element to the element-map if it does not already // exist within this map. // If it exists, an error-message will be raised instead and // false will be returned. // --------------------------------------------------------------- bool LogViewXdrParser::addToElementMap(const QString& a_name, LogViewXdrElement* a_element) { if (m_ElementMap.find(a_name) == m_ElementMap.end()) { m_ElementMap.insert(std::make_pair(a_name, a_element)); return true; } showErrorMessage(QObject::tr("Der Typ '%1' wurde bereits frueher definiert => Bitte ein einem Ort entfernen!").arg(a_name)); return false; } } // namespace N_LogView