sbus_codegen revision b699c4d7f85a5404be1d1ee9450331aea869b886
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#!/usr/bin/python
297be3708069ef31814d6d75c0d71a50a78feb03Mark Andrews
75c0816e8295e180f4bc7f10db3d0d880383bc1cMark Andrews#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Authors:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Stef Walter <stefw@redhat.com>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Copyright (C) 2014 Red Hat
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# This program is free software; you can redistribute it and/or modify
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# it under the terms of the GNU General Public License as published by
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# the Free Software Foundation; either version 3 of the License, or
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# (at your option) any later version.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# This program is distributed in the hope that it will be useful,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# but WITHOUT ANY WARRANTY; without even the implied warranty of
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9011c72c568aedd03709f56f21d639fd55944a74Automatic Updater# GNU General Public License for more details.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# You should have received a copy of the GNU General Public License
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# along with this program. If not, see <http://www.gnu.org/licenses/>.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
e21a2904f02a03fa06b6db04d348f65fe9c67b2bMark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Some parser code from GLib
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Copyright (C) 2008-2011 Red Hat, Inc.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# This library is free software; you can redistribute it and/or
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# modify it under the terms of the GNU Lesser General Public
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# License as published by the Free Software Foundation; either
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews# version 2 of the License, or (at your option) any later version.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# This library is distributed in the hope that it will be useful,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# but WITHOUT ANY WARRANTY; without even the implied warranty of
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Lesser General Public License for more details.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# You should have received a copy of the GNU Lesser General
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Public License along with this library; if not, write to the
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Boston, MA 02111-1307, USA.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Portions by: David Zeuthen <davidz@redhat.com>
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# DBus interfaces are defined here:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater# The introspection data format has become the standard way to represent a
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# DBus interface. For many examples see /usr/share/dbus-1/interfaces/ on a
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# typical linux machine.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater# A word about annotations. These are extra flags or values that can be
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# assigned to anything. So far, the codegen supports this annotation:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater# org.freedesktop.DBus.GLib.CSymbol
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# - An annotation specified in the specification that tells us what C symbol
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# to generate for a given interface or method. By default the codegen will
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater# build up a symbol name from the DBus name.
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater#
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updaterimport optparse
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updaterimport os
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updaterimport re
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updaterimport StringIO
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinimport sys
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updaterimport xml.parsers.expat
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater# -----------------------------------------------------------------------------
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater# Objects
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updaterclass DBusXmlException(Exception):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein line = 0
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein file = None
aeb7938001b22e811a910e1b36cdf452f9193865Automatic Updater
aeb7938001b22e811a910e1b36cdf452f9193865Automatic Updater # Lets us print problems like a compiler would
c6d486af36165da7eb970354981d145249e342e4Mark Andrews def __str__(self):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein message = Exception.__str__(self)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if self.file and self.line:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein return "%s:%d: %s" % (self.file, self.line, message)
aeb7938001b22e811a910e1b36cdf452f9193865Automatic Updater elif self.file:
aeb7938001b22e811a910e1b36cdf452f9193865Automatic Updater return "%s: %s" % (self.file, message)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein return message
aeb7938001b22e811a910e1b36cdf452f9193865Automatic Updater
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinclass Base:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def __init__(self, name):
aeb7938001b22e811a910e1b36cdf452f9193865Automatic Updater if not name:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein raise DBusXmlException('No name on element')
9011c72c568aedd03709f56f21d639fd55944a74Automatic Updater self.name = name
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.annotations = { }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def c_name(self):
9011c72c568aedd03709f56f21d639fd55944a74Automatic Updater return self.annotations.get("org.freedesktop.DBus.GLib.CSymbol", self.name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
9011c72c568aedd03709f56f21d639fd55944a74Automatic Updaterclass Arg(Base):
aeb7938001b22e811a910e1b36cdf452f9193865Automatic Updater def __init__(self, method, name, signature):
9011c72c568aedd03709f56f21d639fd55944a74Automatic Updater Base.__init__(self, name)
7208386cd37a2092c70eddf80cf29519b16c4c80Mark Andrews self.method = method
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.signature = signature
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinclass Method(Base):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def __init__(self, iface, name):
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews Base.__init__(self, name)
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews self.iface = iface
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.in_args = []
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews self.out_args = []
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews def fq_c_name(self):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein return "%s_%s" % (self.iface.c_name(), self.c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrewsclass Signal(Base):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def __init__(self, iface, name):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Base.__init__(self, name)
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews self.iface = iface
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.args = []
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def fq_c_name(self):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein return "%s_%s" % (self.iface.c_name(), self.c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinclass Property(Base):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def __init__(self, iface, name, signature, access):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Base.__init__(self, name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.iface = iface
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews self.signature = signature
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.readable = False
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.writable = False
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if access == 'readwrite':
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.readable = True
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.writable = True
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif access == 'read':
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.readable = True
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif access == 'write':
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.writable = True
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein raise DBusXmlException('Invalid access type %s'%self.access)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def fq_c_name(self):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein return "%s_%s" % (self.iface.c_name(), self.c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinclass Interface(Base):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def __init__(self, name):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Base.__init__(self, name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.methods = []
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.signals = []
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.properties = []
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def c_name(self):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein return self.annotations.get("org.freedesktop.DBus.GLib.CSymbol",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.name.replace(".", "_"))
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# -----------------------------------------------------------------------------
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# Code Generation
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindef out(format, *args):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein str = format % args
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein sys.stdout.write(str)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein sys.stdout.write("\n")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindef source_args(parent, args, suffix):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("/* arguments for %s.%s */", parent.iface.name, parent.name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("const struct sbus_arg_meta %s%s[] = {", parent.fq_c_name(), suffix)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for arg in args:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" { \"%s\", \"%s\" },", arg.name, arg.signature)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out(" { NULL, }")
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out("};")
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrewsdef source_methods(iface, methods):
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews for meth in methods:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if meth.in_args:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews source_args(meth, meth.in_args, "__in")
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if meth.out_args:
b05bdb520d83f7ecaad708fe305268c3420be01dMark Andrews source_args(meth, meth.out_args, "__out")
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out("")
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out("/* methods for %s */", iface.name)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out("const struct sbus_method_meta %s__methods[] = {", iface.c_name())
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews for meth in methods:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out(" {")
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews out(" \"%s\", /* name */", meth.name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if meth.in_args:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" %s__in,", meth.fq_c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" NULL, /* no in_args */")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if meth.out_args:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" %s__out,", meth.fq_c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" NULL, /* no out_args */")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" },")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" { NULL, }")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("};")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindef source_signals(iface, signals):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for sig in iface.signals:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if sig.args:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein source_args(sig, sig.args, "__args")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("/* signals for %s */", iface.name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("const struct sbus_signal_meta %s__signals[] = {", iface.c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for sig in signals:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" {")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" \"%s\", /* name */", sig.name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if sig.args:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" %s__args", sig.fq_c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" NULL, /* no args */")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" },")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" { NULL, }")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("};")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindef source_properties(iface, properties):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("/* property info for %s */", iface.name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("const struct sbus_property_meta %s__properties[] = {", iface.c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for prop in properties:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" {")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" \"%s\", /* name */", prop.name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" \"%s\", /* signature */", prop.signature)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if prop.readable and prop.writable:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" SBUS_PROPERTY_READABLE | SBUS_PROPERTY_WRITABLE,")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif prop.readable:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" SBUS_PROPERTY_READABLE,")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif prop.writable:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" SBUS_PROPERTY_WRITABLE,")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein assert False, "should not be reached"
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" },")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" { NULL, }")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out("};")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrewsdef header_interface(iface):
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out("")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out("/* interface info for %s */", iface.name)
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out("extern const struct sbus_interface_meta %s_meta;", iface.c_name())
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrewsdef source_interface(iface):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out("/* interface info for %s */", iface.name)
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out("const struct sbus_interface_meta %s_meta = {", iface.c_name())
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" \"%s\", /* name */", iface.name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if iface.methods:
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" %s__methods,", iface.c_name())
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews else:
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" NULL, /* no methods */")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if iface.signals:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" %s__signals,", iface.c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" NULL, /* no signals */")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if iface.properties:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" %s__properties", iface.c_name())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" NULL, /* no propetries */")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("};")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindef generate_source(ifaces, filename):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein basename = os.path.basename(filename)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("/* The following definitions are auto-generated from %s */", basename)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("#include \"util/util.h\"")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("#include \"sbus/sssd_dbus.h\"")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("#include \"sbus/sssd_dbus_meta.h\"")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for iface in ifaces:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein # The methods
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if iface.methods:
bea931e17b7567f09107f93ab7e25c7f00abeb9cMark Andrews source_methods(iface, iface.methods)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein # The signals array
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if iface.signals:
b05bdb520d83f7ecaad708fe305268c3420be01dMark Andrews source_signals(iface, iface.signals)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein # The properties array
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if iface.properties:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein source_properties(iface, iface.properties)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein # The sbus_interface structure
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein source_interface(iface)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindef generate_header(ifaces, filename):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein basename = os.path.basename(filename)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein guard = "__%s__" % re.sub(r'([^_A-Z0-9])', "_", basename.upper())
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("/* The following declarations are auto-generated from %s */", basename)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("#ifndef %s", guard)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("#define %s", guard)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("#include \"sbus/sssd_dbus.h\"")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("/* ------------------------------------------------------------------------")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" * DBus Interface Metadata")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" *")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" * These structure definitions are filled in with the information about")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" * the interfaces, methods, properties and so on.")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" *")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" * The actual definitions are found in the accompanying C file next")
ceeb18e6907a10547859faa340ecad83bedae90cMark Andrews out(" * to this header.")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out(" */")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for iface in ifaces:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein header_interface(iface)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out("#endif /* %s */", guard)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# -----------------------------------------------------------------------------
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein# XML Interface Parsing
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_TOP = 'top'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_NODE = 'node'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_INTERFACE = 'interface'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_METHOD = 'method'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_SIGNAL = 'signal'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_PROPERTY = 'property'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_ARG = 'arg'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_ANNOTATION = 'annotation'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob AusteinSTATE_IGNORED = 'ignored'
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindef expect_attr(attrs, name):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if name not in attrs:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein raise DBusXmlException("Missing attribute '%s'" % name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if attrs[name] == "":
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein raise DBusXmlException("Empty attribute '%s'" % name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein return attrs[name]
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinclass DBusXMLParser:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def __init__(self, filename):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser = xml.parsers.expat.ParserCreate()
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser.CommentHandler = self.handle_comment
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser.CharacterDataHandler = self.handle_char_data
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser.StartElementHandler = self.handle_start_element
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser.EndElementHandler = self.handle_end_element
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.parsed_interfaces = []
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = None
b05bdb520d83f7ecaad708fe305268c3420be01dMark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_TOP
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state_stack = []
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = None
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object_stack = []
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.arg_count = 0
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein try:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein with open(filename, "r") as f:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser.ParseFile(f)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein except DBusXmlException, ex:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein ex.line = parser.CurrentLineNumber
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein ex.file = filename
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein raise
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein except xml.parsers.expat.ExpatError, ex:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein exc = DBusXmlException(str(ex))
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein exc.line = ex.lineno
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein exc.file = filename
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein raise exc
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def handle_comment(self, data):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein pass
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def handle_char_data(self, data):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein pass
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def handle_start_element(self, name, attrs):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein old_state = self.state
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein old_cur_object = self.cur_object
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if self.state == STATE_IGNORED:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_IGNORED
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews elif self.cur_object and name == STATE_ANNOTATION:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein val = attrs.get('value', '')
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object.annotations[expect_attr(attrs, 'name')] = val
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_IGNORED
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif self.state == STATE_TOP:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if name == STATE_NODE:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_NODE
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews else:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews self.state = STATE_IGNORED
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews elif self.state == STATE_NODE:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if name == STATE_INTERFACE:
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews self.state = STATE_INTERFACE
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews iface = Interface(expect_attr(attrs, 'name'))
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = iface
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.parsed_interfaces.append(iface)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_IGNORED
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif self.state == STATE_INTERFACE:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if name == STATE_METHOD:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_METHOD
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein method = Method(self.cur_object, expect_attr(attrs, 'name'))
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object.methods.append(method)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = method
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.arg_count = 0
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif name == STATE_SIGNAL:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_SIGNAL
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein signal = Signal(self.cur_object, expect_attr(attrs, 'name'))
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object.signals.append(signal)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = signal
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.arg_count = 0
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif name == STATE_PROPERTY:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_PROPERTY
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein prop = Property(self.cur_object,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein expect_attr(attrs, 'name'),
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein expect_attr(attrs, 'type'),
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein expect_attr(attrs, 'access'))
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object.properties.append(prop)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = prop
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_IGNORED
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif self.state == STATE_METHOD:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if name == STATE_ARG:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_ARG
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein arg = Arg(self.cur_object,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein expect_attr(attrs, 'name'),
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein expect_attr(attrs, 'type'))
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein direction = attrs.get('direction', 'in')
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if direction == 'in':
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object.in_args.append(arg)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif direction == 'out':
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object.out_args.append(arg)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein raise DBusXmlException('Invalid direction "%s"' % direction)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = arg
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_IGNORED
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif self.state == STATE_SIGNAL:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if name == STATE_ARG:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_ARG
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein arg = Arg(self.cur_object,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein expect_attr(attrs, 'name'),
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein expect_attr(attrs, 'type'))
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater self.cur_object.args.append(arg)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = arg
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_IGNORED
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif self.state == STATE_PROPERTY:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = STATE_IGNORED
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein elif self.state == STATE_ARG:
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater self.state = STATE_IGNORED
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein else:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein assert False, 'Unhandled state "%s" while entering element with name "%s"' % (self.state, name)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews self.state_stack.append(old_state)
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews self.cur_object_stack.append(old_cur_object)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein def handle_end_element(self, name):
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.state = self.state_stack.pop()
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein self.cur_object = self.cur_object_stack.pop()
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindef parse_options():
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser = optparse.OptionParser("usage: %prog [options] introspect.xml ...")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser.set_description("sbus_codegen generates sbus interface structures \
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein from standard XML Introspect data.")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser.add_option("--mode",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dest="mode", default="header",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein help="'header' or 'source' (default: header)",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein metavar="MODE")
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein parser.add_option("--output",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dest="output", default=None,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein help="Set output file name (default: stdout)",
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews metavar="FILE")
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews (options, args) = parser.parse_args()
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if not args:
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein print >> sys.stderr, "sbus_codegen: no input file specified"
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein sys.exit(2)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews if options.mode not in ["header", "source"]:
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews print >> sys.stderr, "sbus_codegen: specify --mode=header or --mode=source"
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein return options, args
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrewsdef main():
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews options, args = parse_options()
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews if options.output:
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews sys.stdout = buf = StringIO.StringIO()
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein for filename in args:
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews parser = DBusXMLParser(filename)
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if options.mode == "header":
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein generate_header(parser.parsed_interfaces, filename)
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews elif options.mode == "source":
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews generate_source(parser.parsed_interfaces, filename)
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews else:
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews assert False, "should not be reached"
68b30890ebd441a6a1ae3fdf71744d07d02cd030Mark Andrews
68b30890ebd441a6a1ae3fdf71744d07d02cd030Mark Andrews # Write output at end to be nice to 'make'
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews if options.output:
68b30890ebd441a6a1ae3fdf71744d07d02cd030Mark Andrews output = open(options.output, "w")
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews output.write(buf.getvalue())
68b30890ebd441a6a1ae3fdf71744d07d02cd030Mark Andrews output.close()
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrewsif __name__ == "__main__":
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews try:
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews main()
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews except DBusXmlException, ex:
4556ad3a270bf049b3225433a402666aaffe3c36Mark Andrews print >> sys.stderr, str(ex)
035992291cb70ec3be4046fcea921b4a6acb1c77Mark Andrews sys.exit(1)
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein