You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
7.3 KiB
219 lines
7.3 KiB
/***************************************************************************
|
|
* Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
|
|
* *
|
|
* 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 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
***************************************************************************/
|
|
#ifndef PROG_XML_TO_DATA_H
|
|
#define PROG_XML_TO_DATA_H
|
|
|
|
#include <tqfile.h>
|
|
#include <tqtextstream.h>
|
|
#include <tqmap.h>
|
|
|
|
#include "xml_to_data.h"
|
|
#include "devices/list/device_list.h"
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class Data>
|
|
class ExtXmlToData : public ::XmlToData
|
|
{
|
|
public:
|
|
ExtXmlToData(const TQString &basename, const TQString &namespac)
|
|
: _basename(basename), _namespace(namespac) {}
|
|
|
|
protected:
|
|
TQString _basename, _namespace;
|
|
virtual bool hasFamilies() const { return true; }
|
|
const TQStringList &families() const { return _families; }
|
|
virtual uint familyIndex(const TQString &family) const { return _families.findIndex(family); }
|
|
virtual void parseData(TQDomElement, Data &) = 0;
|
|
virtual void includes(TQTextStream &) const {}
|
|
virtual void outputData(const Data &, TQTextStream &) const {}
|
|
virtual void outputFunctions(TQTextStream &) const {}
|
|
virtual TQString currentDevice() const { return _current; }
|
|
virtual void parseDevice(TQDomElement element);
|
|
::Group::Support extractSupport(const TQString &s) const;
|
|
bool hasDevice(const TQString &device) const { return _map.contains(device); }
|
|
virtual void parse();
|
|
|
|
protected:
|
|
TQString _current;
|
|
class PData {
|
|
public:
|
|
uint family;
|
|
::Group::Support support;
|
|
Data data;
|
|
};
|
|
TQMap<TQString, PData> _map;
|
|
TQStringList _families;
|
|
|
|
virtual void output();
|
|
};
|
|
|
|
template <class Data>
|
|
Group::Support ExtXmlToData<Data>::extractSupport(const TQString &s) const
|
|
{
|
|
if ( s.isEmpty() ) return Group::Support::Untested;
|
|
Group::Support support = Group::Support::fromKey(s);
|
|
if ( support==Group::Support::None ) qFatal("Cannot be \"not supported\"");
|
|
if ( support==Group::Support::Nb_Types ) qFatal("Unknown support type");
|
|
return support;
|
|
}
|
|
|
|
template <class Data>
|
|
void ExtXmlToData<Data>::parseDevice(TQDomElement element)
|
|
{
|
|
if ( element.nodeName()!="device" ) qFatal("Root node child should be named \"device\"");
|
|
_current = element.attribute("name").upper();
|
|
if ( Device::lister().data(_current)==0 ) qFatal(TQString("Device name \"%1\" unknown").tqarg(_current));
|
|
if ( _map.contains(_current) ) qFatal(TQString("Device \"%1\" already parsed").tqarg(_current));
|
|
PData data;
|
|
if ( hasFamilies() ) {
|
|
TQString family = element.attribute("family");
|
|
if ( family.isEmpty() ) qFatal(TQString("Family is empty").tqarg(family));
|
|
if ( _families.find(family)==_families.end() ) _families.append(family);
|
|
data.family = familyIndex(family);
|
|
}
|
|
data.support = extractSupport(element.attribute("support_type"));
|
|
parseData(element, data.data);
|
|
_map[_current] = data;
|
|
}
|
|
|
|
template <class Data>
|
|
void ExtXmlToData<Data>::parse()
|
|
{
|
|
TQDomDocument doc = parseFile(_basename + ".xml");
|
|
TQDomElement root = doc.documentElement();
|
|
if ( root.nodeName()!="type" ) qFatal("Root node should be \"type\"");
|
|
if ( root.attribute("name")!=_basename ) qFatal(TQString("Root node name is not \"%1\"").tqarg(_basename));
|
|
TQDomNode child = root.firstChild();
|
|
while ( !child.isNull() ) {
|
|
if ( child.isComment() ) qDebug("comment: %s", child.toComment().data().latin1());
|
|
else {
|
|
if ( !child.isElement() ) qFatal("Root node child should be an element");
|
|
parseDevice(child.toElement());
|
|
}
|
|
child = child.nextSibling();
|
|
}
|
|
}
|
|
|
|
template <class Data>
|
|
void ExtXmlToData<Data>::output()
|
|
{
|
|
// write .cpp file
|
|
TQFile file(_basename + "_data.cpp");
|
|
if ( !file.open(IO_WriteOnly) ) qFatal(TQString("Cannot open output file \"%1\"").tqarg(file.name()));
|
|
TQTextStream s(&file);
|
|
s << "// #### Do not edit: this file is autogenerated !!!" << endl << endl;
|
|
s << "#include \"devices/list/device_list.h\"" << endl;
|
|
s << "#include \"" + _basename + ".h\"" << endl;
|
|
s << "#include \"" + _basename + "_data.h\"" << endl;
|
|
includes(s);
|
|
s << endl;
|
|
s << "namespace " << _namespace << endl;
|
|
s << "{" << endl;
|
|
s << "struct CData {" << endl;
|
|
s << " const char *name;" << endl;
|
|
if ( hasFamilies() ) s << " uint family;" << endl;
|
|
s << " uint support;" << endl;
|
|
s << " Data data;" << endl;
|
|
s << "};" << endl;
|
|
s << endl;
|
|
|
|
// data list
|
|
typename TQMap<TQString, PData>::const_iterator it = _map.begin();
|
|
for (; it!=_map.end(); ++it) {
|
|
s << "const CData PIC" << it.key() << "_DATA = {";
|
|
s << " \"" << it.key() << "\", ";
|
|
if ( hasFamilies() ) s << it.data().family << ", ";
|
|
s << it.data().support.type() << ", ";
|
|
s << "{ ";
|
|
outputData(it.data().data, s);
|
|
s << " }";
|
|
s << " };" << endl;
|
|
}
|
|
s << endl;
|
|
s << "const CData *DATA_LIST[] = {" << endl;
|
|
uint i = 0;
|
|
it = _map.begin();
|
|
for (; it!=_map.end(); ++it) {
|
|
s << "&PIC" << it.key() << "_DATA,";
|
|
i++;
|
|
if ( (i%10)==0 ) s << endl;
|
|
}
|
|
s << "0 " << endl;
|
|
s << "};" << endl;
|
|
|
|
// functions
|
|
s << endl;
|
|
s << "const CData *cdata(const TQString &device)" << endl;
|
|
s << "{" << endl;
|
|
s << " for(uint i=0; DATA_LIST[i]; i++)" << endl;
|
|
s << " if ( device==DATA_LIST[i]->name ) return DATA_LIST[i];" << endl;
|
|
s << " return 0;" << endl;
|
|
s << "}" << endl;
|
|
s << "bool isSupported(const TQString &device)" << endl;
|
|
s << "{" << endl;
|
|
s << " return cdata(device);" << endl;
|
|
s << "}" << endl;
|
|
if ( hasFamilies() ) {
|
|
s << "uint family(const TQString &device)" << endl;
|
|
s << "{" << endl;
|
|
s << " return cdata(device)->family;" << endl;
|
|
s << "}" << endl;
|
|
}
|
|
s << "::Group::Support support(const TQString &device)" << endl;
|
|
s << "{" << endl;
|
|
s << " return ::Group::Support::Type(cdata(device)->support);" << endl;
|
|
s << "}" << endl;
|
|
s << "const Data &data(const TQString &device)" << endl;
|
|
s << "{" << endl;
|
|
s << " return cdata(device)->data;" << endl;
|
|
s << "}" << endl;
|
|
s << endl;
|
|
outputFunctions(s);
|
|
s << endl;
|
|
s << "}" << endl;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
namespace Programmer
|
|
{
|
|
template <class Data>
|
|
class XmlToData : public ExtXmlToData<Data>
|
|
{
|
|
public:
|
|
XmlToData(const TQString &basename, const TQString &namespac)
|
|
: ExtXmlToData<Data>(basename, namespac) {}
|
|
|
|
protected:
|
|
virtual void outputFunctions(TQTextStream &s) const;
|
|
virtual void includes(TQTextStream &) const;
|
|
};
|
|
|
|
template <class Data>
|
|
void Programmer::XmlToData<Data>::outputFunctions(TQTextStream &s) const
|
|
{
|
|
s << "void Group::initSupported()" << endl;
|
|
s << "{" << endl;
|
|
s << " for (uint i=0; DATA_LIST[i]; i++) {" << endl;
|
|
s << " const Device::Data *data = Device::lister().data(DATA_LIST[i]->name);" << endl;
|
|
s << " addDevice(data->name(), data, ::Group::Support::Type(DATA_LIST[i]->support));" << endl;
|
|
s << " }" << endl;
|
|
s << "}" << endl;
|
|
s << endl;
|
|
}
|
|
|
|
template <class Data>
|
|
void Programmer::XmlToData<Data>::includes(TQTextStream &s) const
|
|
{
|
|
s << "#include \"" << ExtXmlToData<Data>::_basename << "_prog.h\"" << endl;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
#endif
|