1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-26 11:52:10 +01:00
LibrePilot/ground/src/libs/uavobjgenerator/uavobjectgenerator.cpp
vassilis df573fdad5 GCS/UAVObjectGenerator: Added support for settings objects
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@406 ebee16cc-31ac-478f-84a7-5cbb03baadba
2010-03-28 22:19:32 +00:00

235 lines
9.2 KiB
C++

/**
******************************************************************************
*
* @file uavobjectgenerator.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief UAVObjectGenerator, generates UAVObjects from XML files.
*
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* The following is done by the object generator:
* - Read all XML files in the XML source directory
* - Process each XML and extract the information for all defined objects
* - Generate the unique objects IDs and check for collisions
* - Generate the GCS and Flight UAVObject code based on the supplied template source files
* - Update the object initialization source files for both the GCS and Flight code
*/
#include "uavobjectgenerator.h"
/**
* Constructor
* @param basepath The base directory where the 'flight' and 'gcs' folders are located (the SVN structure is expected)
* @param out The stdout file
*/
UAVObjectGenerator::UAVObjectGenerator(QString& basepath, FILE* out) :
basepath(basepath),
sout(out)
{
xmlPath = QDir( basepath + QString("ground/src/shared/uavobjectdefinition"));
flightCodePath = QDir( basepath + QString("flight/OpenPilot/UAVObjects"));
gcsCodePath = QDir( basepath + QString("ground/src/plugins/uavobjects"));
objectTemplateFilename = QString("uavobjecttemplate");
objectsInitTemplateFilename = QString("uavobjectsinittemplate");
objectsInitFilename = QString("uavobjectsinit");
sout << "- OpenPilot UAVObject Generator -" << endl;
}
/**
* Process all XML files and generate object code.
*/
bool UAVObjectGenerator::processAll()
{
// Read the template files
QString flightCodeTemplate = readFile( flightCodePath.absoluteFilePath(objectTemplateFilename + ".c") );
QString flightIncludeTemplate = readFile( flightCodePath.absoluteFilePath("inc/" + objectTemplateFilename + ".h") );
QString flightInitTemplate = readFile( flightCodePath.absoluteFilePath(objectsInitTemplateFilename + ".c") );
QString gcsCodeTemplate = readFile( gcsCodePath.absoluteFilePath(objectTemplateFilename + ".cpp") );
QString gcsIncludeTemplate = readFile( gcsCodePath.absoluteFilePath(objectTemplateFilename + ".h") );
QString gcsInitTemplate = readFile( gcsCodePath.absoluteFilePath(objectsInitTemplateFilename + ".cpp") );
if ( flightCodeTemplate.isNull() || flightIncludeTemplate.isNull() ||
gcsCodeTemplate.isNull() || gcsIncludeTemplate.isNull() ||
flightInitTemplate.isNull() || gcsInitTemplate.isNull() )
{
sout << "Error: Could not open template files." << endl;
return false;
}
// Get all XML files
QStringList filters;
filters.append("*.xml");
xmlPath.setNameFilters(filters);
QFileInfoList xmlList = xmlPath.entryInfoList();
// Read in each XML file and parse it
QList<UAVObjectParser*> parsers;
for (int n = 0; n < xmlList.length(); ++n)
{
QFileInfo fileinfo = xmlList[n];
QString filename = fileinfo.fileName();
QString xmlstr = readFile(fileinfo.absoluteFilePath());
UAVObjectParser* parser = new UAVObjectParser();
sout << "Parsing XML file: " << fileinfo.fileName() << endl;
QString res = parser->parseXML(xmlstr, filename);
if (!res.isNull())
{
sout << "Error: " << res << endl;
return false;
}
parsers.append(parser);
}
// Generate the code for each object and write it to the destination directory
QList<quint32> objIDList;
QString objInc;
QString flightObjInit;
QString gcsObjInit;
bool res;
for (int parseridx = 0; parseridx < parsers.length(); ++ parseridx)
{
UAVObjectParser* parser = parsers[parseridx];
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx)
{
QString name = parser->getObjectName(objidx);
QString namelc = name.toLower();
sout << "Generating code for object: " << name << endl;
// Check for object ID conflicts
quint32 id = parser->getObjectID(objidx);
if ( objIDList.contains(id) )
{
sout << "Error: Object ID collision found in object " << name << ", modify object name" << endl;
return false;
}
else
{
objIDList.append(id);
}
// Generate the flight code
QString flightCode;
QString flightInclude;
res = parser->generateFlightObject(objidx, flightIncludeTemplate, flightCodeTemplate,
flightInclude, flightCode);
if (!res)
{
sout << "Error: Improperly formatted flight object template file" << endl;
return false;
}
// Generate the GCS code
QString gcsCode;
QString gcsInclude;
res = parser->generateGCSObject(objidx, gcsIncludeTemplate, gcsCodeTemplate,
gcsInclude, gcsCode);
if (!res)
{
sout << "Error: Improperly formatted GCS object template file" << endl;
return false;
}
// Write the flight code
// TODO: Only write file if modified
res = writeFile( flightCodePath.absolutePath() + "/" + namelc + ".c", flightCode );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
res = writeFile( flightCodePath.absolutePath() + "/inc/" + namelc + ".h", flightInclude );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Write the GCS code
// TODO: Only write file if modified
res = writeFile( gcsCodePath.absolutePath() + "/" + namelc + ".cpp", gcsCode );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
res = writeFile( gcsCodePath.absolutePath() + "/" + namelc + ".h", gcsInclude );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Update strings for the object initialization
objInc.append("#include \"" + namelc + ".h\"\n");
flightObjInit.append(" " + name + "Initialize();\n");
gcsObjInit.append(" objMngr->registerObject( new " + name + "() );\n");
}
}
// Write the flight object inialization files
sout << "Updating object initialization files" << endl;
flightInitTemplate.replace( QString("$(OBJINC)"), objInc);
flightInitTemplate.replace( QString("$(OBJINIT)"), flightObjInit);
res = writeFile( flightCodePath.absolutePath() + "/" + objectsInitFilename + ".c",
flightInitTemplate );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Write the gcs object inialization files
gcsInitTemplate.replace( QString("$(OBJINC)"), objInc);
gcsInitTemplate.replace( QString("$(OBJINIT)"), gcsObjInit);
res = writeFile( gcsCodePath.absolutePath() + "/" + objectsInitFilename + ".cpp",
gcsInitTemplate );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Done
sout << "Done: processed " << xmlList.length() << " XML files and generated "
<< objIDList.length() << " objects with no ID collisions." << endl;
return true;
}
/**
* Read a file and return its contents as a string
*/
QString UAVObjectGenerator::readFile(QString name)
{
QFile file(name);
if (!file.open(QFile::ReadOnly)) return QString();
QTextStream fileStr(&file);
QString str = fileStr.readAll();
file.close();
return str;
}
/**
* Write contents of string to file
*/
bool UAVObjectGenerator::writeFile(QString name, QString& str)
{
QFile file(name);
if (!file.open(QFile::WriteOnly)) return false;
QTextStream fileStr(&file);
fileStr << str;
file.close();
return true;
}