/*=====================================================================
QGroundControl Open Source Ground Control Station
( c ) 2009 - 2011 QGROUNDCONTROL PROJECT < http : //www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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 3 of the License , or
( at your option ) any later version .
QGROUNDCONTROL 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 QGROUNDCONTROL . If not , see < http : //www.gnu.org/licenses/>.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
/**
* @ file
* @ brief Implementation of class MAVLinkXMLParserV10
* @ author Lorenz Meier < mail @ qgroundcontrol . org >
*/
# include <QFile>
# include <QDir>
# include <QPair>
# include <QList>
# include <QMap>
# include <QDateTime>
# include <QLocale>
# include "MAVLinkXMLParserV10.h"
# include <QDebug>
MAVLinkXMLParserV10 : : MAVLinkXMLParserV10 ( QDomDocument * document , QString outputDirectory , QObject * parent ) : QObject ( parent ) ,
doc ( document ) ,
outputDirName ( outputDirectory ) ,
fileName ( " " )
{
}
MAVLinkXMLParserV10 : : MAVLinkXMLParserV10 ( QString document , QString outputDirectory , QObject * parent ) : QObject ( parent )
{
doc = new QDomDocument ( ) ;
QFile file ( document ) ;
if ( file . open ( QIODevice : : ReadOnly | QIODevice : : Text ) )
{
const QString instanceText ( QString : : fromUtf8 ( file . readAll ( ) ) ) ;
doc - > setContent ( instanceText ) ;
}
fileName = document ;
outputDirName = outputDirectory ;
}
MAVLinkXMLParserV10 : : ~ MAVLinkXMLParserV10 ( )
{
}
/**
*
* CALCULATE THE CHECKSUM
*
*/
# define X25_INIT_CRC 0xffff
# define X25_VALIDATE_CRC 0xf0b8
/**
* The checksum function adds the hash of one char at a time to the
* 16 bit checksum ( uint16_t ) .
*
* @ param data new char to hash
* @ param crcAccum the already accumulated checksum
* */
void MAVLinkXMLParserV10 : : crcAccumulate ( uint8_t data , uint16_t * crcAccum )
{
/*Accumulate one byte of data into the CRC*/
uint8_t tmp ;
tmp = data ^ ( uint8_t ) ( * crcAccum & 0xff ) ;
tmp ^ = ( tmp < < 4 ) ;
* crcAccum = ( * crcAccum > > 8 ) ^ ( tmp < < 8 ) ^ ( tmp < < 3 ) ^ ( tmp > > 4 ) ;
}
/**
* @ param crcAccum the 16 bit X .25 CRC
*/
void MAVLinkXMLParserV10 : : crcInit ( uint16_t * crcAccum )
{
* crcAccum = X25_INIT_CRC ;
}
/**
* Generate C - code ( C - 89 compliant ) out of the XML protocol specs .
*/
bool MAVLinkXMLParserV10 : : generate ( )
{
// Process result
bool success = true ;
// Only generate if output dir is correctly set
if ( outputDirName = = " " )
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: No output directory given. \n Abort.</font> " ) ) ;
return false ;
}
QString topLevelOutputDirName = outputDirName ;
// print out the element names of all elements that are direct children
// of the outermost element.
QDomElement docElem = doc - > documentElement ( ) ;
QDomNode n = docElem ; //.firstChild();
QDomNode p = docElem ;
// Sanity check variables
QList < int > * usedMessageIDs = new QList < int > ( ) ;
QMap < QString , QString > * usedMessageNames = new QMap < QString , QString > ( ) ;
QMap < QString , QString > * usedEnumNames = new QMap < QString , QString > ( ) ;
QList < QPair < QString , QString > > cFiles ;
QString lcmStructDefs = " " ;
QString pureFileName ;
QString pureIncludeFileName ;
QFileInfo fInfo ( this - > fileName ) ;
pureFileName = fInfo . baseName ( ) . split ( " . " , QString : : SkipEmptyParts ) . first ( ) ;
// XML parsed and converted to C code. Now generating the files
outputDirName + = QDir : : separator ( ) + pureFileName ;
QDateTime now = QDateTime : : currentDateTime ( ) . toUTC ( ) ;
QLocale loc ( QLocale : : English ) ;
QString dateFormat = " dddd, MMMM d yyyy, hh:mm UTC " ;
QString date = loc . toString ( now , dateFormat ) ;
QString includeLine = " #include \" %1 \" \n " ;
QString mainHeaderName = pureFileName + " .h " ;
QString messagesDirName = " . " ; //"generated";
QDir dir ( outputDirName + " / " + messagesDirName ) ;
int mavlinkVersion = 0 ;
// Start main header
QString mainHeader = QString ( " /** @file \n * \t @brief MAVLink comm protocol. \n * \t @see http://qgroundcontrol.org/mavlink/ \n * \t Generated on %1 \n */ \n #ifndef " + pureFileName . toUpper ( ) + " _H \n #define " + pureFileName . toUpper ( ) + " _H \n \n " ) . arg ( date ) ; // The main header includes all messages
// Mark all code as C code
mainHeader + = " #ifdef __cplusplus \n extern \" C \" { \n #endif \n \n " ;
mainHeader + = " \n #include \" ../protocol.h \" \n " ;
mainHeader + = " \n #define MAVLINK_ENABLED_ " + pureFileName . toUpper ( ) + " \n \n " ;
QString enums ;
// Run through root children
while ( ! n . isNull ( ) )
{
// Each child is a message
QDomElement e = n . toElement ( ) ; // try to convert the node to an element.
if ( ! e . isNull ( ) )
{
if ( e . tagName ( ) = = " mavlink " )
{
p = n ;
n = n . firstChild ( ) ;
while ( ! n . isNull ( ) )
{
e = n . toElement ( ) ;
if ( ! e . isNull ( ) )
{
// Handle all include tags
if ( e . tagName ( ) = = " include " )
{
QString incFileName = e . text ( ) ;
// Load file
//QDomDocument includeDoc = QDomDocument();
// Prepend file path if it is a relative path and
// make it relative to opened file
QFileInfo fInfo ( incFileName ) ;
QString incFilePath ;
if ( fInfo . isRelative ( ) )
{
QFileInfo rInfo ( this - > fileName ) ;
incFilePath = rInfo . absoluteDir ( ) . canonicalPath ( ) + " / " + incFileName ;
pureIncludeFileName = fInfo . baseName ( ) . split ( " . " , QString : : SkipEmptyParts ) . first ( ) ;
}
QFile file ( incFilePath ) ;
if ( file . open ( QIODevice : : ReadOnly | QIODevice : : Text ) )
{
emit parseState ( QString ( " <font color= \" green \" >Included messages from file: %1</font> " ) . arg ( incFileName ) ) ;
// NEW MODE: CREATE INDIVIDUAL FOLDERS
// Create new output directory, parse included XML and generate C-code
MAVLinkXMLParserV10 includeParser ( incFilePath , topLevelOutputDirName , this ) ;
connect ( & includeParser , SIGNAL ( parseState ( QString ) ) , this , SIGNAL ( parseState ( QString ) ) ) ;
// Generate and write
includeParser . generate ( ) ;
mainHeader + = " \n #include \" ../ " + pureIncludeFileName + " / " + pureIncludeFileName + " .h \" \n " ;
emit parseState ( QString ( " <font color= \" green \" >End of inclusion from file: %1</font> " ) . arg ( incFileName ) ) ;
}
else
{
// Include file could not be opened
emit parseState ( QString ( " <font color= \" red \" >ERROR: Failed including file: %1, file is not readable. Wrong/misspelled filename? \n Abort.</font> " ) . arg ( fileName ) ) ;
return false ;
}
}
// Handle all enum tags
else if ( e . tagName ( ) = = " version " )
{
//QString fieldType = e.attribute("type", "");
//QString fieldName = e.attribute("name", "");
QString fieldText = e . text ( ) ;
// Check if version has been previously set
if ( mavlinkVersion ! = 0 )
{
emit parseState ( QString ( " <font color= \" red \" >ERROR: Protocol version tag set twice, please use it only once. First version was %1, second version is %2. \n Abort.</font> " ) . arg ( mavlinkVersion ) . arg ( fieldText ) ) ;
return false ;
}
bool ok ;
int version = fieldText . toInt ( & ok ) ;
if ( ok & & ( version > 0 ) & & ( version < 256 ) )
{
// Set MAVLink version
mavlinkVersion = version ;
}
else
{
emit parseState ( QString ( " <font color= \" red \" >ERROR: Reading version string failed: %1, string is not an integer number between 1 and 255. \n Abort.</font> " ) . arg ( fieldText ) ) ;
return false ;
}
}
// Handle all enum tags
else if ( e . tagName ( ) = = " enums " )
{
// One down into the enums list
p = n ;
n = n . firstChild ( ) ;
while ( ! n . isNull ( ) )
{
e = n . toElement ( ) ;
QString currEnum ;
QString currEnumEnd ;
// Comment
QString comment ;
if ( ! e . isNull ( ) & & e . tagName ( ) = = " enum " )
{
// Get enum name
QString enumName = e . attribute ( " name " , " " ) . toLower ( ) ;
if ( enumName . size ( ) = = 0 )
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: Missing required name= \" \" attribute for tag %2 near line %1 \n Abort.</font> " ) . arg ( QString : : number ( e . lineNumber ( ) ) , e . tagName ( ) ) ) ;
return false ;
}
else
{
// Sanity check: Accept only enum names not used previously
if ( usedEnumNames - > contains ( enumName ) )
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: Enum name %1 used twice, second occurence near line %2 of file %3 \n Abort.</font> " ) . arg ( enumName , QString : : number ( e . lineNumber ( ) ) , fileName ) ) ;
return false ;
}
else
{
usedEnumNames - > insert ( enumName , QString : : number ( e . lineNumber ( ) ) ) ;
}
// Everything sane, starting with enum content
currEnum = " enum " + enumName . toUpper ( ) + " \n { \n " ;
currEnumEnd = QString ( " \t %1_ENUM_END \n }; \n \n " ) . arg ( enumName . toUpper ( ) ) ;
int nextEnumValue = 0 ;
// Get the enum fields
QDomNode f = e . firstChild ( ) ;
while ( ! f . isNull ( ) )
{
QDomElement e2 = f . toElement ( ) ;
if ( ! e2 . isNull ( ) & & e2 . tagName ( ) = = " entry " )
{
QString fieldValue = e2 . attribute ( " value " , " " ) ;
// If value was given, use it, if not, use the enum iterator
// value. The iterator value gets reset by manual values
QString fieldName = e2 . attribute ( " name " , " " ) ;
if ( fieldValue . length ( ) = = 0 )
{
fieldValue = QString : : number ( nextEnumValue ) ;
nextEnumValue + + ;
}
else
{
bool ok ;
nextEnumValue = fieldValue . toInt ( & ok ) + 1 ;
if ( ! ok )
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: Enum entry %1 has not a valid number (%2) in the value field . \ nAbort . < / font > " ).arg(fieldName, fieldValue)) ;
return false ;
}
}
// Add comment of field if there is one
QString fieldComment ;
if ( e2 . text ( ) . length ( ) > 0 )
{
QString sep ( " | " ) ;
QDomNode pp = e2 . firstChild ( ) ;
while ( ! pp . isNull ( ) )
{
QDomElement pp2 = pp . toElement ( ) ;
if ( pp2 . isText ( ) | | pp2 . isCDATASection ( ) )
{
// If this is the only field, don't add the separator
if ( pp . nextSibling ( ) . isNull ( ) )
{
fieldComment + = pp2 . nodeValue ( ) ;
}
else
{
fieldComment + = pp2 . nodeValue ( ) + sep ;
}
}
else if ( pp2 . isElement ( ) )
{
// If this is the only field, don't add the separator
if ( pp . nextSibling ( ) . isNull ( ) )
{
fieldComment + = pp2 . text ( ) ;
}
else
{
fieldComment + = pp2 . text ( ) + sep ;
}
}
pp = pp . nextSibling ( ) ;
}
fieldComment = fieldComment . replace ( " \n " , " " ) ;
fieldComment = " /* " + fieldComment . simplified ( ) + " */ " ;
}
currEnum + = " \t " + fieldName . toUpper ( ) + " = " + fieldValue + " , " + fieldComment + " \n " ;
}
else if ( ! e2 . isNull ( ) & & e2 . tagName ( ) = = " description " )
{
comment = " " + e2 . text ( ) . replace ( " \n " , " " ) + comment ;
}
f = f . nextSibling ( ) ;
}
}
// Add the last parsed enum
// Remove the last comma, as the last value has none
// ENUM END MARKER IS LAST ENTRY, COMMA REMOVAL NOT NEEDED
//int commaPosition = currEnum.lastIndexOf(",");
//currEnum.remove(commaPosition, 1);
enums + = " /** @brief " + comment . simplified ( ) + " */ \n " + currEnum + currEnumEnd ;
} // Element is non-zero and element name is <enum>
n = n . nextSibling ( ) ;
} // While through <enums>
// One up, back into the <mavlink> structure
n = p ;
}
// Handle all message tags
else if ( e . tagName ( ) = = " messages " )
{
p = n ;
n = n . firstChild ( ) ;
while ( ! n . isNull ( ) )
{
e = n . toElement ( ) ;
if ( ! e . isNull ( ) )
{
//if (e.isNull()) continue;
// Get message name
QString messageName = e . attribute ( " name " , " " ) . toLower ( ) ;
if ( messageName . size ( ) = = 0 )
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: Missing required name= \" \" attribute for tag %2 near line %1 \n Abort.</font> " ) . arg ( QString : : number ( e . lineNumber ( ) ) , e . tagName ( ) ) ) ;
return false ;
}
else
{
// Get message id
bool ok ;
int messageId = e . attribute ( " id " , " -1 " ) . toInt ( & ok , 10 ) ;
emit parseState ( tr ( " Compiling message <strong>%1 \t (#%3) < / strong > \ tnear line % 2 " ).arg(messageName, QString::number(n.lineNumber()), QString::number(messageId))) ;
// Sanity check: Accept only message IDs not used previously
if ( usedMessageIDs - > contains ( messageId ) )
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: Message ID %1 used twice, second occurence near line %2 of file %3 \n Abort.</font> " ) . arg ( QString : : number ( messageId ) , QString : : number ( e . lineNumber ( ) ) , fileName ) ) ;
return false ;
}
else
{
usedMessageIDs - > append ( messageId ) ;
}
// Sanity check: Accept only message names not used previously
if ( usedMessageNames - > contains ( messageName ) )
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: Message name %1 used twice, second occurence near line %2 of file %3 \n Abort.</font> " ) . arg ( messageName , QString : : number ( e . lineNumber ( ) ) , fileName ) ) ;
return false ;
}
else
{
usedMessageNames - > insert ( messageName , QString : : number ( e . lineNumber ( ) ) ) ;
}
QString channelType ( " mavlink_channel_t " ) ;
QString messageType ( " mavlink_message_t " ) ;
QString headerType ( " mavlink_header_t " ) ;
// Build up function call
QString commentContainer ( " /** \n * @brief Pack a %1 message \n * @param system_id ID of this system \n * @param component_id ID of this component (e.g. 200 for IMU) \ n * @ param msg The MAVLink message to compress the data into \ n * \ n % 2 * @ return length of the message in bytes ( excluding serial stream start sign ) \ n */ \ n " ) ;
QString commentPackChanContainer ( " /** \n * @brief Pack a %1 message \n * @param system_id ID of this system \n * @param component_id ID of this component (e.g. 200 for IMU) \ n * @ param chan The MAVLink channel this message was sent over \ n * @ param msg The MAVLink message to compress the data into \ n % 2 * @ return length of the message in bytes ( excluding serial stream start sign ) \ n */ \ n " ) ;
QString commentSendContainer ( " /** \n * @brief Send a %1 message \n * @param chan MAVLink channel to send the message \n * \n %2 */ \n " ) ;
QString commentEncodeContainer ( " /** \n * @brief Encode a %1 struct into a message \n * \n * @param system_id ID of this system \n * @param component_id ID of this component (e.g. 200 for IMU) \ n * @ param msg The MAVLink message to compress the data into \ n * @ param % 1 C - struct to read the message contents from \ n */ \ n " ) ;
QString commentDecodeContainer ( " /** \n * @brief Decode a %1 message into a struct \n * \n * @param msg The message to decode \n * @param %1 C-struct to decode the message contents into \n */ \n " ) ;
QString commentEntry ( " * @param %1 %2 \n " ) ;
QString idDefine = QString ( " #define MAVLINK_MSG_ID_%1 %2 \n #define MAVLINK_MSG_ID_%1_LEN %3 \n #define MAVLINK_MSG_%2_LEN %3 " ) ;
QString arrayDefines ;
QString cStructName = QString ( " mavlink_%1_t " ) . arg ( messageName ) ;
QString cStruct ( " typedef struct __%1 \n { \n %2 \n } %1; " ) ;
QString cStructLines ;
QString encode ( " static inline uint16_t mavlink_msg_%1_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const %2* %1) \ n { \ n \ treturn mavlink_msg_ % 1 _pack ( % 3 ) ; \ n } \ n " );
// QString decode("static inline void mavlink_msg_%1_decode(const mavlink_message_t* msg, %2* %1)\n{\n%3}\n");
QString decode ( " static inline void mavlink_msg_%1_decode(const mavlink_message_t* msg, %2* %1) \ n { \ n \ tmemcpy ( % 1 , msg - > payload , sizeof ( % 2 ) ) ; \ n } \ n " );
// QString pack("static inline uint16_t mavlink_msg_%1_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg%2)\n{\n\tuint16_t i = 0;\n\tmsg->msgid = MAVLINK_MSG_ID_%3;\n\n%4\n\treturn mavlink_finalize_message(msg, system_id, component_id, i);\n}\n\n");
QString pack ( " static inline uint16_t mavlink_msg_%1_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg%2) \ n { \ n \ tmavlink_ % 1 _t * p = ( mavlink_ % 1 _t * ) & msg - > payload [ 0 ] ; \ n \ tmsg - > msgid = MAVLINK_MSG_ID_ % 3 ; \ n \ n % 4 \ n \ treturn mavlink_finalize_message ( msg , system_id , component_id , MAVLINK_MSG_ID_ % 3 _LEN ) ; \ n } \ n \ n " );
// QString packChan("static inline uint16_t mavlink_msg_%1_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, mavlink_message_t* msg%2)\n{\n\tuint16_t i = 0;\n\tmsg->msgid = MAVLINK_MSG_ID_%3;\n\n%4\n\treturn mavlink_finalize_message_chan(msg, system_id, component_id, chan, i);\n}\n\n");
QString packChan ( " static inline uint16_t mavlink_msg_%1_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, mavlink_message_t* msg%2) \ n { \ n \ tmavlink_ % 1 _t * p = ( mavlink_ % 1 _t * ) & msg - > payload [ 0 ] ; \ n \ tmsg - > msgid = MAVLINK_MSG_ID_ % 3 ; \ n \ n % 4 \ n \ treturn mavlink_finalize_message_chan ( msg , system_id , component_id , chan , MAVLINK_MSG_ID_ % 3 _LEN ) ; \ n } \ n \ n " );
//QString compactStructSend = "#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS\n\nstatic inline void mavlink_msg_%3_struct_send(%1 chan%5)\n{\n\t%2 msg;\n\tmavlink_msg_%3_encode(mavlink_system.sysid, mavlink_system.compid, &msg%4);\n\tmavlink_send_uart(chan, &msg);\n}\n\n#endif";
QString unpacking ;
QString prepends ;
QString packParameters ;
QString packArguments ( " system_id, component_id, msg " ) ;
QString packLines ;
QString decodeLines ;
QString sendArguments ;
QString commentLines ;
int calculatedLength = 0 ;
// Get the message fields
QDomNode f = e . firstChild ( ) ;
// The field types and order are hashed with a checksum
// Initialize CRC
uint16_t fieldHash ;
crcInit ( & fieldHash ) ;
while ( ! f . isNull ( ) )
{
QDomElement e2 = f . toElement ( ) ;
if ( ! e2 . isNull ( ) & & e2 . tagName ( ) = = " field " )
{
QString fieldType = e2 . attribute ( " type " , " " ) ;
QString fieldName = e2 . attribute ( " name " , " " ) ;
QString fieldOffset = e2 . attribute ( " offset " , " " ) ;
QString fieldText = e2 . text ( ) ;
QString unpackingCode ;
QString unpackingComment = QString ( " /** \n * @brief Get field %1 from %2 message \n * \n * @return %3 \n */ \n " ) . arg ( fieldName , messageName , fieldText ) ;
// Send arguments do not work for the version field
if ( ! fieldType . contains ( " uint8_t_mavlink_version " ) )
{
// Send arguments are the same for integral types and arrays
sendArguments + = " , " + fieldName ;
commentLines + = commentEntry . arg ( fieldName , fieldText . replace ( " \n " , " " ) ) ;
}
// MAVLink version field
// this is a special field always containing the version define
if ( fieldType . contains ( " uint8_t_mavlink_version " ) )
{
// Add field to C structure
cStructLines + = QString ( " \t %1 %2; ///< %3 \n " ) . arg ( " uint8_t " , fieldName , fieldText ) ;
calculatedLength + = 1 ;
// Add pack line to message_xx_pack function
// packLines += QString("\ti += put_uint8_t_by_index(%1, i, msg->payload); // %2\n").arg(mavlinkVersion).arg(fieldText);
packLines + = QString ( " \n \t p->%2 = MAVLINK_VERSION; // %1:%3 " ) . arg ( fieldType , fieldName , e2 . text ( ) ) ;
// Add decode function for this type
decodeLines + = QString ( " \n \t %1->%2 = mavlink_msg_%1_get_%2(msg); " ) . arg ( messageName , fieldName ) ;
if ( fieldOffset ! = " " ) { // does not use the number - always moves up one slot
QStringList itemList ;
// Swap field in C structure
itemList = cStructLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ; else ;
cStructLines = itemList . join ( " \n " ) + " \n " ;
// Swap line in message_xx_pack function
itemList = packLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ; else ;
packLines = itemList . join ( " \n " ) + " \n " ;
// Swap line in decode function for this type
itemList = decodeLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ; else ;
decodeLines = itemList . join ( " \n " ) + " \n " ;
}
}
// ARRAYS are not longer supported - leave error message in here to inform users!
else if ( fieldType . startsWith ( " array " ) )
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: In message %1 deprecated type <array> used near line %2 of file %3. Please change from array[size] to uint8_t[size] to get the same behaviour. \n Abort.</font> " ) . arg ( messageName , QString : : number ( e . lineNumber ( ) ) , fileName ) ) ;
return false ;
}
else if ( fieldType . startsWith ( " string " ) )
{
int arrayLength = QString ( fieldType . split ( " [ " ) . at ( 1 ) . split ( " ] " ) . first ( ) ) . toInt ( ) ;
// String array is always unsigned char, so bytes
calculatedLength + = arrayLength ;
packParameters + = QString ( " , const " ) + QString ( " char* " ) + " " + fieldName ;
packArguments + = " , " + messageName + " -> " + fieldName ;
// Add field to C structure
cStructLines + = QString ( " \t %1 %2[%3]; ///< %4 \n " ) . arg ( " char " , fieldName , QString : : number ( arrayLength ) , fieldText ) ;
// Add pack line to message_xx_pack function
// packLines += QString("\ti += put_%1_by_index(%2, %3, i, msg->payload); // %4\n").arg(arrayType, fieldName, QString::number(arrayLength), e2.text());
packLines + = QString ( " \t strncpy( p->%2, %2, sizeof(p->%2)); // %1[%3]:%4 \n " ) . arg ( " char " , fieldName , QString : : number ( arrayLength ) , fieldText ) ;
// Add decode function for this type
decodeLines + = QString ( " \t mavlink_msg_%1_get_%2(msg, %1->%2); \n " ) . arg ( messageName , fieldName ) ;
arrayDefines + = QString ( " #define MAVLINK_MSG_%1_FIELD_%2_LEN %3 \n " ) . arg ( messageName . toUpper ( ) , fieldName . toUpper ( ) , QString : : number ( arrayLength ) ) ;
if ( fieldOffset ! = " " )
{ // does not use the number - always moves up one slot
QStringList itemList ;
// Swap field in C structure
itemList = cStructLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ;
cStructLines = itemList . join ( " \n " ) + " \n " ;
// Swap line in message_xx_pack function
itemList = packLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ;
packLines = itemList . join ( " \n " ) + " \n " ;
// Swap line in decode function for this type
itemList = decodeLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ;
decodeLines = itemList . join ( " \n " ) + " \n " ;
}
}
// Expand array handling to all valid mavlink data types
else if ( fieldType . contains ( ' [ ' ) & & fieldType . contains ( ' ] ' ) )
{
int arrayLength = QString ( fieldType . split ( " [ " ) . at ( 1 ) . split ( " ] " ) . first ( ) ) . toInt ( ) ;
QString arrayType = fieldType . split ( " [ " ) . first ( ) ;
if ( arrayType . contains ( " array " ) )
{
calculatedLength + = arrayLength ;
}
else if ( arrayType . contains ( " char " ) )
{
calculatedLength + = arrayLength ;
}
else if ( arrayType . contains ( " int8 " ) )
{
calculatedLength + = arrayLength ;
}
else if ( arrayType . contains ( " int16 " ) )
{
calculatedLength + = arrayLength * 2 ;
}
else if ( arrayType . contains ( " int32 " ) )
{
calculatedLength + = arrayLength * 4 ;
}
else if ( arrayType . contains ( " int64 " ) )
{
calculatedLength + = arrayLength * 8 ;
}
else if ( arrayType = = " float " )
{
calculatedLength + = arrayLength * 4 ;
}
else
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: In message %1 invalid array type %4 used near line %2 of file %3 \n Abort.</font> " ) . arg ( messageName , QString : : number ( e . lineNumber ( ) ) , fileName , arrayType ) ) ;
return false ;
}
packParameters + = QString ( " , const " ) + arrayType + " * " + fieldName ;
packArguments + = " , " + messageName + " -> " + fieldName ;
// Add field to C structure
cStructLines + = QString ( " \t %1 %2[%3]; ///< %4 \n " ) . arg ( arrayType , fieldName , QString : : number ( arrayLength ) , fieldText ) ;
// Add pack line to message_xx_pack function
// packLines += QString("\ti += put_array_by_index((const int8_t*)%1, sizeof(%2)*%3, i, msg->payload); // %4\n").arg(fieldName, arrayType, QString::number(arrayLength), fieldText);
packLines + = QString ( " \t memcpy(p->%2, %2, sizeof(p->%2)); // %1[%3]:%4 \n " ) . arg ( arrayType , fieldName , QString : : number ( arrayLength ) , fieldText ) ;
// Add decode function for this type
decodeLines + = QString ( " \n \t mavlink_msg_%1_get_%2(msg, %1->%2); " ) . arg ( messageName , fieldName ) ;
if ( fieldOffset ! = " " )
{ // does not use the number - always moves up one slot
QStringList itemList ;
// Swap field in C structure
itemList = cStructLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ;
cStructLines = itemList . join ( " \n " ) + " \n " ;
// Swap line in message_xx_pack function
itemList = packLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ;
packLines = itemList . join ( " \n " ) + " \n " ;
// Swap line in decode function for this type
itemList = decodeLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ;
decodeLines = itemList . join ( " \n " ) + " \n " ;
}
arrayDefines + = QString ( " #define MAVLINK_MSG_%1_FIELD_%2_LEN %3 \n " ) . arg ( messageName . toUpper ( ) , fieldName . toUpper ( ) , QString : : number ( arrayLength ) ) ;
// unpackingCode = QString("\n\tmemcpy(r_data, msg->payload%1, sizeof(%2)*%3);\n\treturn sizeof(%2)*%3;").arg(prepends, arrayType, QString::number(arrayLength));
unpackingCode = QString ( " \n \t memcpy(%1, p->%1, sizeof(p->%1)); \n \t return sizeof(p->%1); " ) . arg ( fieldName ) ;
// unpacking += unpackingComment + QString("static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, %3* r_data)\n{\n%4\n}\n\n").arg(messageName, fieldName, arrayType, unpackingCode);
unpacking + = unpackingComment + QString ( " static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, %3* %2) \n { \n \t mavlink_%1_t *p = (mavlink_%1_t *)&msg->payload[0]; \n %4 \n } \n \n " ) . arg ( messageName , fieldName , arrayType , unpackingCode ) ;
// decodeLines += "";
prepends + = QString ( " +sizeof(%1)*%2 " ) . arg ( arrayType , QString : : number ( arrayLength ) ) ;
}
else
// Handle simple types like integers and floats
{
packParameters + = " , " + fieldType + " " + fieldName ;
packArguments + = " , " + messageName + " -> " + fieldName ;
// Add field to C structure
cStructLines + = QString ( " \t %1 %2; ///< %3 \n " ) . arg ( fieldType , fieldName , fieldText ) ;
// Add pack line to message_xx_pack function
// packLines += QString("\ti += put_%1_by_index(%2, i, msg->payload); // %3\n").arg(fieldType, fieldName, e2.text());
packLines + = QString ( " \t p->%2 = %2; // %1:%3 \n " ) . arg ( fieldType , fieldName , e2 . text ( ) ) ;
// Add decode function for this type
// decodeLines += QString("\t%1->%2 = mavlink_msg_%1_get_%2(msg);\n").arg(messageName, fieldName);
decodeLines + = QString ( " \n \t %1 = p->%1; " ) . arg ( fieldName ) ;
if ( fieldOffset ! = " " ) { // does not use the number - always moves up one slot
QStringList itemList ;
// Swap field in C structure
itemList = cStructLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ; else ;
cStructLines = itemList . join ( " \n " ) + " \n " ;
// Swap line in message_xx_pack function
itemList = packLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ; else ;
packLines = itemList . join ( " \n " ) + " \n " ;
// Swap line in decode function for this type
itemList = decodeLines . split ( " \n " , QString : : SkipEmptyParts ) ;
if ( itemList . size ( ) > 1 ) itemList . swap ( itemList . size ( ) - 1 , itemList . size ( ) - 2 ) ; else ;
decodeLines = itemList . join ( " \n " ) + " \n " ;
}
if ( fieldType . contains ( " char " ) )
{
calculatedLength + = 1 ;
}
else if ( fieldType . contains ( " int8 " ) )
{
calculatedLength + = 1 ;
}
else if ( fieldType . contains ( " int16 " ) )
{
calculatedLength + = 2 ;
}
else if ( fieldType . contains ( " int32 " ) )
{
calculatedLength + = 4 ;
}
else if ( fieldType . contains ( " int64 " ) )
{
calculatedLength + = 8 ;
}
else if ( fieldType = = " float " )
{
calculatedLength + = 4 ;
}
else
{
emit parseState ( tr ( " <font color= \" red \" >ERROR: In message %1 inavlid type %4 used near line %2 of file %3 \n Abort.</font> " ) . arg ( messageName , QString : : number ( e . lineNumber ( ) ) , fileName , fieldType ) ) ;
return false ;
}
}
//
// QString unpackingCode;
if ( fieldType = = " uint8_t_mavlink_version " )
{
// unpackingCode = QString("\treturn (%1)(msg->payload%2)[0];").arg("uint8_t", prepends);
unpackingCode = QString ( " \t return (%1)(p->%2); " ) . arg ( " uint8_t " , fieldName ) ;
}
else if ( fieldType = = " uint8_t " | | fieldType = = " int8_t " )
{
// unpackingCode = QString("\treturn (%1)(msg->payload%2)[0];").arg(fieldType, prepends);
unpackingCode = QString ( " \t return (%1)(p->%2); " ) . arg ( fieldType , fieldName ) ;
}
else if ( fieldType = = " uint16_t " | | fieldType = = " int16_t " )
{
// unpackingCode = QString("\tgeneric_16bit r;\n\tr.b[1] = (msg->payload%1)[0];\n\tr.b[0] = (msg->payload%1)[1];\n\treturn (%2)r.s;").arg(prepends).arg(fieldType);
unpackingCode = QString ( " \t return (%1)(p->%2); " ) . arg ( fieldType , fieldName ) ;
}
else if ( fieldType = = " uint32_t " | | fieldType = = " int32_t " )
{
// unpackingCode = QString("\tgeneric_32bit r;\n\tr.b[3] = (msg->payload%1)[0];\n\tr.b[2] = (msg->payload%1)[1];\n\tr.b[1] = (msg->payload%1)[2];\n\tr.b[0] = (msg->payload%1)[3];\n\treturn (%2)r.i;").arg(prepends).arg(fieldType);
unpackingCode = QString ( " \t return (%1)(p->%2); " ) . arg ( fieldType , fieldName ) ;
}
else if ( fieldType = = " float " )
{
// unpackingCode = QString("\tgeneric_32bit r;\n\tr.b[3] = (msg->payload%1)[0];\n\tr.b[2] = (msg->payload%1)[1];\n\tr.b[1] = (msg->payload%1)[2];\n\tr.b[0] = (msg->payload%1)[3];\n\treturn (%2)r.f;").arg(prepends).arg(fieldType);
unpackingCode = QString ( " \t return (%1)(p->%2); " ) . arg ( fieldType , fieldName ) ;
}
else if ( fieldType = = " uint64_t " | | fieldType = = " int64_t " )
{
// unpackingCode = QString("\tgeneric_64bit r;\n\tr.b[7] = (msg->payload%1)[0];\n\tr.b[6] = (msg->payload%1)[1];\n\tr.b[5] = (msg->payload%1)[2];\n\tr.b[4] = (msg->payload%1)[3];\n\tr.b[3] = (msg->payload%1)[4];\n\tr.b[2] = (msg->payload%1)[5];\n\tr.b[1] = (msg->payload%1)[6];\n\tr.b[0] = (msg->payload%1)[7];\n\treturn (%2)r.ll;").arg(prepends).arg(fieldType);
unpackingCode = QString ( " \t return (%1)(p->%2); " ) . arg ( fieldType , fieldName ) ;
}
else if ( fieldType . startsWith ( " array " ) )
{ // fieldtype formatis string[n] where n is the number of bytes, extract n from field type string
// unpackingCode = QString("\n\tmemcpy(r_data, msg->payload%1, %2);\n\treturn %2;").arg(filedName, prepends, fieldType.split("[").at(1).split("]").first());
unpackingCode = QString ( " \n \t memcpy(%1, p->%1, sizeof(p->%1)); \n \t return sizeof(p->%1); " ) . arg ( fieldName ) ;
}
else if ( fieldType . startsWith ( " string " ) )
{ // fieldtype formatis string[n] where n is the number of bytes, extract n from field type string
// unpackingCode = QString("\n\tstrcpy(r_data, msg->payload%1, %2);\n\treturn %2;").arg(prepends, fieldType.split("[").at(1).split("]").first());
unpackingCode = QString ( " \n \t strncpy(%1, p->%1, sizeof(p->%1)); \n \t return sizeof(p->%1); " ) . arg ( fieldName ) ;
}
// Generate the message decoding function
if ( fieldType . contains ( " uint8_t_mavlink_version " ) )
{
// unpacking += unpackingComment + QString("static inline %1 mavlink_msg_%2_get_%3(const mavlink_message_t* msg)\n{\n%4\n}\n\n").arg("uint8_t", messageName, fieldName, unpackingCode);
unpacking + = unpackingComment + QString ( " static inline %1 mavlink_msg_%2_get_%3(const mavlink_message_t* msg) \n { \n \t mavlink_%2_t *p = (mavlink_%2_t *)&msg->payload[0]; \n %4 \n } \n \n " ) . arg ( " uint8_t " , messageName , fieldName , unpackingCode ) ;
decodeLines + = " " ;
prepends + = " +sizeof(uint8_t) " ;
}
// Array handling is different from simple types
else if ( fieldType . startsWith ( " array " ) )
{
// unpacking += unpackingComment + QString("static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, int8_t* r_data)\n{\n%4\n}\n\n").arg(messageName, fieldName, unpackingCode);
unpacking + = unpackingComment + QString ( " static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, int8_t* %2) \n { \n \t mavlink_%1_t *p = (mavlink_%1_t *)&msg->payload[0]; \n %3 \n } \n \n " ) . arg ( messageName , fieldName , unpackingCode ) ;
decodeLines + = " " ;
QString arrayLength = QString ( fieldType . split ( " [ " ) . at ( 1 ) . split ( " ] " ) . first ( ) ) ;
prepends + = " + " + arrayLength ;
}
else if ( fieldType . startsWith ( " string " ) )
{
// unpacking += unpackingComment + QString("static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, char* r_data)\n{\n%4\n}\n\n").arg(messageName, fieldName, unpackingCode);
unpacking + = unpackingComment + QString ( " static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, char* %2) \n { \n \t mavlink_%1 *p = (mavlink_%1 *)&msg->payload[0]; \n %3 \n } \n \n " ) . arg ( messageName , fieldName , unpackingCode ) ;
decodeLines + = " " ;
QString arrayLength = QString ( fieldType . split ( " [ " ) . at ( 1 ) . split ( " ] " ) . first ( ) ) ;
prepends + = " + " + arrayLength ;
}
else if ( fieldType . contains ( ' [ ' ) & & fieldType . contains ( ' ] ' ) )
{
// prevent this case from being caught in the following else
}
else
{
// unpacking += unpackingComment + QString("static inline %1 mavlink_msg_%2_get_%3(const mavlink_message_t* msg)\n{\n%4\n}\n\n").arg(fieldType, messageName, fieldName, unpackingCode);
unpacking + = unpackingComment + QString ( " static inline %1 mavlink_msg_%2_get_%3(const mavlink_message_t* msg) \n { \n \t mavlink_%2_t *p = (mavlink_%2_t *)&msg->payload[0]; \n %4 \n } \n \n " ) . arg ( fieldType , messageName , fieldName , unpackingCode ) ;
decodeLines + = " " ;
prepends + = " +sizeof( " + e2 . attribute ( " type " , " void " ) + " ) " ;
}
}
f = f . nextSibling ( ) ;
}
// cStruct = cStruct.arg(cStructName, cStructLines, QString::number(calculatedLength) );
cStruct = cStruct . arg ( cStructName , cStructLines ) ;
lcmStructDefs . append ( " \n " ) . append ( cStruct ) . append ( " \n " ) ;
pack = pack . arg ( messageName , packParameters , messageName . toUpper ( ) , packLines ) ;
packChan = packChan . arg ( messageName , packParameters , messageName . toUpper ( ) , packLines ) ;
encode = encode . arg ( messageName ) . arg ( cStructName ) . arg ( packArguments ) ;
// decode = decode.arg(messageName).arg(cStructName).arg(decodeLines);
decode = decode . arg ( messageName ) . arg ( cStructName ) ;
// QString compactSend("#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS\n\nstatic inline void mavlink_msg_%3_send(%1 chan%5)\n{\n\t%2 msg;\n\tmavlink_msg_%3_pack_chan(mavlink_system.sysid, mavlink_system.compid, chan, &msg%4);\n\tmavlink_send_uart(chan, &msg);\n}\n\n#endif");
QString compactSend ( " #ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS \n static inline void mavlink_msg_%3_send(%1 chan%5) \ n { \ n \ t % 2 msg ; \ n \ tuint16_t checksum ; \ n \ tmavlink_ % 3 _t * p = ( mavlink_ % 3 _t * ) & msg . payload [ 0 ] ; \ n \ n % 6 \ n \ tmsg . STX = MAVLINK_STX ; \ n \ tmsg . len = MAVLINK_MSG_ID_ % 4 _LEN ; \ n \ tmsg . msgid = MAVLINK_MSG_ID_ % 4 ; \ n " );
QString compactSend2 ( " \t msg.sysid = mavlink_system.sysid; \n \t msg.compid = mavlink_system.compid; \n \t msg.seq = mavlink_get_channel_status(chan)->current_tx_seq; \n \t mavlink_get_channel_status(chan)->current_tx_seq = msg.seq + 1; \n " ) ;
QString compactSend3 ( " \t checksum = crc_calculate_msg(&msg, msg.len + MAVLINK_CORE_HEADER_LEN) ; \ n \ tmsg . ck_a = ( uint8_t ) ( checksum & 0xFF ) ; ///< Low byte\n\tmsg.ck_b = (uint8_t)(checksum >> 8); ///< High byte\n\n\tmavlink_send_msg(chan, &msg);\n}\n\n#endif");
// compactSend = compactSend.arg(channelType, messageType, messageName, sendArguments, packParameters );
compactSend = compactSend . arg ( channelType , messageType , messageName , messageName . toUpper ( ) , packParameters , packLines ) + compactSend2 + compactSend3 ;
QString compact2Send ( " \n \n #ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS_SMALL \n static inline void mavlink_msg_%3_send(%1 chan%5) \ n { \ n \ t % 2 hdr ; \ n \ tmavlink_ % 3 _t payload ; \ n \ tuint16_t checksum ; \ n \ tmavlink_ % 3 _t * p = & payload ; \ n \ n % 6 \ n \ thdr . STX = MAVLINK_STX ; \ n \ thdr . len = MAVLINK_MSG_ID_ % 4 _LEN ; \ n \ thdr . msgid = MAVLINK_MSG_ID_ % 4 ; \ n " );
QString compact2Send2 ( " \t hdr.sysid = mavlink_system.sysid; \n \t hdr.compid = mavlink_system.compid; \n \t hdr.seq = mavlink_get_channel_status(chan)->current_tx_seq; \n \t mavlink_get_channel_status(chan)->current_tx_seq = hdr.seq + 1; \n \t mavlink_send_mem(chan, (uint8_t *)&hdr.STX, MAVLINK_NUM_HEADER_BYTES ); \n " ) ;
QString compact2Send3 ( " \n \t crc_init(&checksum) ; \ n \ tchecksum = crc_calculate_mem ( ( uint8_t * ) & hdr . len , & checksum , MAVLINK_CORE_HEADER_LEN ) ; \ n \ tchecksum = crc_calculate_mem ( ( uint8_t * ) & payload , & checksum , hdr . len ) ; \ n \ thdr . ck_a = ( uint8_t ) ( checksum & 0xFF ) ; ///< Low byte\n\thdr.ck_b = (uint8_t)(checksum >> 8); ///< High byte\n\n\tmavlink_send_mem(chan, (uint8_t *)&payload, hdr.len);\n\tmavlink_send_mem(chan, (uint8_t *)&hdr.ck_a, MAVLINK_NUM_CHECKSUM_BYTES);\n}\n\n#endif");
compact2Send = compact2Send . arg ( channelType , headerType , messageName , messageName . toUpper ( ) , packParameters , packLines ) + compact2Send2 + compact2Send3 ;
QString cFile = " // MESSAGE " + messageName . toUpper ( ) + " PACKING \n \n " + idDefine . arg ( messageName . toUpper ( ) , QString : : number ( messageId ) , QString : : number ( calculatedLength ) ) + " \n \n " + cStruct + " \n " + arrayDefines + " \n " + commentContainer . arg ( messageName . toLower ( ) , commentLines ) + pack + commentPackChanContainer . arg ( messageName . toLower ( ) , commentLines ) + packChan + commentEncodeContainer . arg ( messageName . toLower ( ) ) + encode + " \n " + commentSendContainer . arg ( messageName . toLower ( ) , commentLines ) + compactSend + compact2Send + " \n " + " // MESSAGE " + messageName . toUpper ( ) + " UNPACKING \n \n " + unpacking + commentDecodeContainer . arg ( messageName . toLower ( ) ) + decode ;
cFiles . append ( qMakePair ( QString ( " mavlink_msg_%1.h " ) . arg ( messageName ) , cFile ) ) ;
} // Check if tag = message
} // Check if e = NULL
n = n . nextSibling ( ) ;
} // While through <message>
n = p ;
} // Check if tag = messages
} // Check if e = NULL
n = n . nextSibling ( ) ;
} // While through include and messages
// One up - current node = parent
n = p ;
} // Check if tag = mavlink
} // Check if e = NULL
n = n . nextSibling ( ) ;
} // While through root children
// Add version to main header
mainHeader + = " // MAVLINK VERSION \n \n " ;
mainHeader + = QString ( " #ifndef MAVLINK_VERSION \n #define MAVLINK_VERSION %1 \n #endif \n \n " ) . arg ( mavlinkVersion ) ;
mainHeader + = QString ( " #if (MAVLINK_VERSION == 0) \n #undef MAVLINK_VERSION \n #define MAVLINK_VERSION %1 \n #endif \n \n " ) . arg ( mavlinkVersion ) ;
// Add enums to main header
mainHeader + = " // ENUM DEFINITIONS \n \n " ;
mainHeader + = enums ;
mainHeader + = " \n " ;
mainHeader + = " // MESSAGE DEFINITIONS \n \n " ;
// Create directory if it doesn't exist, report result in success
if ( ! dir . exists ( ) ) success = success & & dir . mkpath ( outputDirName + " / " + messagesDirName ) ;
for ( int i = 0 ; i < cFiles . size ( ) ; i + + )
{
QFile rawFile ( dir . filePath ( cFiles . at ( i ) . first ) ) ;
bool ok = rawFile . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ;
success = success & & ok ;
rawFile . write ( cFiles . at ( i ) . second . toLatin1 ( ) ) ;
rawFile . close ( ) ;
mainHeader + = includeLine . arg ( messagesDirName + " / " + cFiles . at ( i ) . first ) ;
}
mainHeader + = " #ifdef __cplusplus \n } \n #endif \n " ;
mainHeader + = " #endif " ;
// Newline to make compiler happy
mainHeader + = " \n " ;
// Write main header
QFile rawHeader ( outputDirName + " / " + mainHeaderName ) ;
bool ok = rawHeader . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ;
success = success & & ok ;
rawHeader . write ( mainHeader . toLatin1 ( ) ) ;
rawHeader . close ( ) ;
// Write alias mavlink header
QFile mavlinkHeader ( outputDirName + " /mavlink.h " ) ;
ok = mavlinkHeader . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ;
success = success & & ok ;
QString mHeader = QString ( " /** @file \n * \t @brief MAVLink comm protocol. \n * \t @see http://pixhawk.ethz.ch/software/mavlink \n * \t Generated on %1 \n */ \n #ifndef MAVLINK_H \n #define MAVLINK_H \n \n " ) . arg ( date ) ; // The main header includes all messages
// Mark all code as C code
// mHeader += "\n#include \"" + mainHeaderName + "\"\n\n";
mHeader + = " #pragma pack(push,1) \n #include \" " + mainHeaderName + " \" \n #ifdef MAVLINK_CHECK_LENGTH \n #include \" lengths.h \" \n #endif \n #pragma pack(pop) \n " ;
mHeader + = " #endif \n " ;
mavlinkHeader . write ( mHeader . toLatin1 ( ) ) ;
mavlinkHeader . close ( ) ;
// Write C structs / lcm definitions
// QFile lcmStructs(outputDirName + "/mavlink.lcm");
// ok = lcmStructs.open(QIODevice::WriteOnly | QIODevice::Text);
// success = success && ok;
// lcmStructs.write(lcmStructDefs.toLatin1());
return success ;
}