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.
piklab/src/xml_to_data/prog_xml_to_data.h

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