pimgen: Combine make_example and pimgen

Change-Id: I1c79fad6a4b70e711c8aad15c9dd86a07b54bff9
diff --git a/pimgen.py b/pimgen.py
index 91d93d6..73e089a 100755
--- a/pimgen.py
+++ b/pimgen.py
@@ -5,6 +5,7 @@
 import re
 import argparse
 import yaml
+import subprocess
 from mako.template import Template
 
 valid_c_name_pattern = re.compile('[\W_]+')
@@ -18,6 +19,7 @@
         e.setdefault('action', {}).setdefault('type', 'noop')
     return e
 
+
 if __name__ == '__main__':
     script_dir = os.path.dirname(os.path.realpath(__file__))
 
@@ -34,6 +36,8 @@
 
     args = parser.parse_args()
 
+    # Aggregate all the event YAML in the events directory
+    # into a single list of events.
     events_dir = os.path.join(args.inputdir, 'events')
     yaml_files = filter(
         lambda x: x.endswith('.yaml'),
@@ -45,16 +49,59 @@
             for e in yaml.load(fd.read()).get('events', {}):
                 events.append(parse_event(e))
 
-    template = os.path.join(script_dir, 'generated.mako.cpp')
-    t = Template(filename=template)
+    # Import interfaces.yaml.
     with open(os.path.join(args.inputdir, 'interfaces.yaml'), 'r') as fd:
         interfaces = yaml.load(fd.read())
 
+    # Render the template with the provided events and interfaces.
+    template = os.path.join(script_dir, 'generated.mako.cpp')
+    t = Template(filename=template)
     with open(os.path.join(args.outputdir, 'generated.cpp'), 'w') as fd:
         fd.write(
             t.render(
                 interfaces=interfaces,
                 events=events))
 
+    # Invoke sdbus++ to generate any extra interface bindings for
+    # extra interfaces that aren't defined externally.
+    yaml_files = []
+    extra_ifaces_dir = os.path.join(args.inputdir, 'interfaces')
+    if os.path.exists(extra_ifaces_dir):
+        for directory, _, files in os.walk(extra_ifaces_dir):
+            if not files:
+                continue
+
+            yaml_files += map(
+                lambda f: os.path.relpath(
+                    os.path.join(directory, f),
+                    extra_ifaces_dir),
+                filter(lambda f: f.endswith('.interface.yaml'), files))
+
+    genfiles = {
+        'server-cpp': lambda x: '%s.cpp' % (
+            x.replace(os.sep, '.')),
+        'server-header': lambda x: os.path.join(
+            os.path.join(
+                *x.split('.')), 'server.hpp')
+    }
+
+    for i in yaml_files:
+        iface = i.replace('.interface.yaml', '').replace(os.sep, '.')
+        for process, f in genfiles.iteritems():
+
+            dest = os.path.join(args.outputdir, f(iface))
+            parent = os.path.dirname(dest)
+            if parent and not os.path.exists(parent):
+                os.makedirs(parent)
+
+            with open(dest, 'w') as fd:
+                subprocess.call([
+                    'sdbus++',
+                    '-r',
+                    extra_ifaces_dir,
+                    'interface',
+                    process,
+                    iface],
+                    stdout=fd)
 
 # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4