summaryrefslogtreecommitdiff
path: root/tools/dfagen/dfagen/output
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dfagen/dfagen/output')
-rw-r--r--tools/dfagen/dfagen/output/__init__.py24
-rw-r--r--tools/dfagen/dfagen/output/c.py154
-rw-r--r--tools/dfagen/dfagen/output/c/template.c39
-rw-r--r--tools/dfagen/dfagen/output/c/template.h59
-rw-r--r--tools/dfagen/dfagen/output/c/template_cb.h12
-rw-r--r--tools/dfagen/dfagen/output/c/template_cb_decl.h6
-rw-r--r--tools/dfagen/dfagen/output/c/template_cb_impl.c9
-rw-r--r--tools/dfagen/dfagen/output/c/template_cb_skel.c9
-rw-r--r--tools/dfagen/dfagen/output/dot.py19
9 files changed, 331 insertions, 0 deletions
diff --git a/tools/dfagen/dfagen/output/__init__.py b/tools/dfagen/dfagen/output/__init__.py
new file mode 100644
index 00000000..be71aef7
--- /dev/null
+++ b/tools/dfagen/dfagen/output/__init__.py
@@ -0,0 +1,24 @@
+from ConfigParser import ConfigParser
+
+class UserConfig:
+ def __init__ (self, file):
+ if file:
+ f = open (file, 'r')
+ cp = ConfigParser ()
+ cp.readfp (f)
+ f.close ()
+ self.dict = dict (cp.items ('user'))
+
+ def __getitem__ (self, key):
+ return self.dict[key]
+
+import c
+import dot
+
+outputs = dict (
+ c = c,
+ dot = dot,
+ )
+
+def get_output (name):
+ return outputs[name];
diff --git a/tools/dfagen/dfagen/output/c.py b/tools/dfagen/dfagen/output/c.py
new file mode 100644
index 00000000..e19ca713
--- /dev/null
+++ b/tools/dfagen/dfagen/output/c.py
@@ -0,0 +1,154 @@
+import os.path
+
+class WriterData:
+
+ def __init__ (self, prefix, automaton, user):
+ self.prefix = prefix
+ self.automaton = automaton
+ self.user = user
+ self.states = self.automaton.states.values ()
+ self.events = self.automaton.events.values ()
+ self.dict = dict (
+ prefix = prefix,
+ PREFIX = prefix.upper (),
+ name = automaton.name,
+ comments = automaton.comments,
+ initial = automaton.initial.name,
+ states = self.list_states,
+ events = self.list_events,
+ branches = self.list_branches,
+ transition_table = self.transition_table,
+ cb_impl = self.cb_impl,
+ cb_decl = self.cb_decl,
+ )
+
+ def list_states (self):
+ return ''.join ([' ' + self.prefix.upper () + '_STATE_' + s.name
+ + ',\n' for s in self.states])
+
+ def list_events (self):
+ return ''.join ([' ' + self.prefix.upper () + '_EVENT_'
+ + e.name.replace (' ', '_') + ',\n' for e in self.events])
+
+ def list_branches (self):
+ l = ''
+ for s in self.states:
+ for tr in s.transitions.values ():
+ for br in tr.branches.values ():
+ n = dict (
+ PREFIX = self.prefix.upper (),
+ state = s.name,
+ event = tr.event.name.replace (' ', '_'),
+ branch = (br.name and br.name.replace (' ', '_')
+ or ''),
+ to = (br.to and br.to.name or s.name),
+ )
+ l += (' %(PREFIX)s_BRANCH__%(state)s__%(event)s__%(branch)s = '
+ + '_BRANCH (%(state)s, %(event)s, %(to)s),\n') % n
+ return l
+
+ def transition_table (self):
+ r = ''
+ for s in self.states:
+ r += ' { '
+ es = [ ]
+ for e in self.events:
+ if e in s.transitions:
+ es.append (self.prefix + '__' + s.name + '__'
+ + e.name.replace (' ', '_'))
+ else:
+ es.append ('NULL')
+ r += ',\n '.join (es)
+ r += ' },\n'
+ return r
+
+ def states_template (self, template):
+ t = open (os.path.join (self.templatedir, template), 'r')
+ tt = t.read ()
+ t.close ()
+ exp = ''
+ for s in self.states:
+ for tr in s.transitions.values ():
+ d = WriterData (self.prefix, self.automaton, self.user)
+ branches_to = '\n'.join (
+ [(br.name and br.name or '')
+ + ' => '
+ + (br.to and br.to.name or s.name)
+ + (br.comments and ('\n '
+ + br.comments.replace ('\n', '\n ')) or '')
+ for br in tr.branches.values ()])
+ returns = '\n'.join (
+ [' return ' + self.prefix + '_next'
+ + (br.name and '_branch' or '')
+ + ' (' + s.name + ', '
+ + tr.event.name.replace (' ', '_')
+ + (br.name and ', ' + br.name.replace (' ', '_')
+ or '')
+ + ');'
+ for br in tr.branches.values ()])
+ d.dict = dict (
+ prefix = self.prefix,
+ user = self.user,
+ state = s.name,
+ event = tr.event.name.replace (' ', '_'),
+ branches_to = branches_to,
+ returns = returns,
+ )
+ exp += tt % d
+ return exp
+
+ def cb_impl (self):
+ return self.states_template ('template_cb_impl.c')
+
+ def cb_decl (self):
+ return self.states_template ('template_cb_decl.h')
+
+ def __getitem__ (self, key):
+ preproc = lambda v: v
+ if key.startswith ('*'):
+ key = key[1:]
+ preproc = lambda v: ' * ' + v.replace ('\n', '\n * ') + '\n'
+ if key.startswith ('_'):
+ key = key[1:]
+ preproc = lambda v: v and v + '\n' or ''
+ val = None
+ if key in self.dict:
+ try:
+ val = self.dict[key] ()
+ except TypeError:
+ val = self.dict[key]
+ elif key.startswith ('user.'):
+ val = self.user[key[5:]]
+ val = preproc (val)
+ if val is None:
+ raise KeyError, key
+ return val
+
+class Writer:
+
+ def __init__ (self, data, templatedir):
+ data.templatedir = templatedir
+ self.data = data
+ self.templatedir = templatedir
+
+ def write_template (self, template, output):
+ t = open (os.path.join (self.templatedir, template), 'r')
+ tt = t.read ()
+ t.close ()
+ exp = tt % self.data
+ o = open (output, 'w')
+ o.write (exp)
+ o.close ()
+
+ def write (self):
+ self.write_template ('template.h', self.data.prefix + '.h')
+ self.write_template ('template.c', self.data.prefix + '.c')
+ self.write_template ('template_cb.h', self.data.prefix + '_cb.h')
+ self.write_template ('template_cb_skel.c',
+ self.data.prefix + '_cb_skel.c')
+
+def write (prefix, automaton, user):
+ w = Writer (WriterData (prefix, automaton, user),
+ os.path.splitext (__file__)[0])
+ w.write ()
+
diff --git a/tools/dfagen/dfagen/output/c/template.c b/tools/dfagen/dfagen/output/c/template.c
new file mode 100644
index 00000000..a8679046
--- /dev/null
+++ b/tools/dfagen/dfagen/output/c/template.c
@@ -0,0 +1,39 @@
+/*
+ * THIS IS AN AUTOMATICALLY GENERATED FILE, DO NOT EDIT!
+ *
+ * %(name)s
+ *
+%(*comments)s */
+#include "%(prefix)s_cb.h"
+#include <stddef.h>
+#include <assert.h>
+
+%(_user.type-decl)s
+/* %(name)s transition table. */
+static const %(prefix)s_transition_t
+%(prefix)s_transition_table[%(PREFIX)s_STATE_NB][%(PREFIX)s_EVENT_NB] = {
+%(transition_table)s};
+
+/* Initialise %(name)s automaton. */
+void
+%(prefix)s_init (%(user.type)s *user)
+{
+ user->%(user.field)s = %(PREFIX)s_STATE_%(initial)s;
+}
+
+/* Handle events on %(name)s automaton. */
+void
+%(prefix)s_handle_event (%(user.type)s *user, %(prefix)s_event_t event)
+{
+ assert (user);
+ %(prefix)s_state_t state = user->%(user.field)s;
+ assert (state < %(PREFIX)s_STATE_NB);
+ assert (event < %(PREFIX)s_EVENT_NB);
+ %(prefix)s_transition_t tr = %(prefix)s_transition_table[state][event];
+ assert (tr);
+ %(prefix)s_branch_t br = tr (user);
+ assert (((br >> 16) & 0xff) == state);
+ assert (((br >> 8) & 0xff) == event);
+ user->%(user.field)s = br & 0xff;
+}
+
diff --git a/tools/dfagen/dfagen/output/c/template.h b/tools/dfagen/dfagen/output/c/template.h
new file mode 100644
index 00000000..2be89f31
--- /dev/null
+++ b/tools/dfagen/dfagen/output/c/template.h
@@ -0,0 +1,59 @@
+#ifndef %(prefix)s_h
+#define %(prefix)s_h
+/*
+ * THIS IS AN AUTOMATICALLY GENERATED FILE, DO NOT EDIT!
+ *
+ * %(name)s
+ *
+%(*comments)s */
+
+%(_user.type-forward-decl)s
+/* %(name)s states. */
+enum %(prefix)s_state_t
+{
+%(states)s %(PREFIX)s_STATE_NB
+};
+typedef enum %(prefix)s_state_t %(prefix)s_state_t;
+
+/* %(name)s events. */
+enum %(prefix)s_event_t
+{
+%(events)s %(PREFIX)s_EVENT_NB
+};
+typedef enum %(prefix)s_event_t %(prefix)s_event_t;
+
+/* This macro enables checks for branches used in the wrong state/event
+ * combination. */
+#define _BRANCH(state, event, to) \
+ ((%(PREFIX)s_STATE_ ## state) << 16 \
+ | (%(PREFIX)s_EVENT_ ## event) << 8 \
+ | (%(PREFIX)s_STATE_ ## to))
+
+/* %(name)s branches. */
+enum %(prefix)s_branch_t
+{
+%(branches)s};
+typedef enum %(prefix)s_branch_t %(prefix)s_branch_t;
+
+#undef _BRANCH
+
+/* %(name)s transition type. */
+typedef %(prefix)s_branch_t (*%(prefix)s_transition_t) (%(user.type)s *user);
+
+/* Initialise %(name)s automaton. */
+void
+%(prefix)s_init (%(user.type)s *user);
+
+/* Handle events on %(name)s automaton. */
+void
+%(prefix)s_handle_event (%(user.type)s *user, %(prefix)s_event_t event);
+
+/* Value to return to follow the only branch. */
+#define %(prefix)s_next(state, event) \
+ %(PREFIX)s_BRANCH__ ## state ## __ ## event ## __
+
+/* Value to return to follow a given branch. */
+#define %(prefix)s_next_branch(state, event, branch) \
+ %(PREFIX)s_BRANCH__ ## state ## __ ## event ## __ ## branch
+
+#endif /* %(prefix)s_h */
diff --git a/tools/dfagen/dfagen/output/c/template_cb.h b/tools/dfagen/dfagen/output/c/template_cb.h
new file mode 100644
index 00000000..6252b28c
--- /dev/null
+++ b/tools/dfagen/dfagen/output/c/template_cb.h
@@ -0,0 +1,12 @@
+#ifndef %(prefix)s_cb_h
+#define %(prefix)s_cb_h
+/*
+ * THIS IS AN AUTOMATICALLY GENERATED FILE, DO NOT EDIT!
+ *
+ * %(name)s callbacks declaration.
+ *
+%(*comments)s */
+
+#include "%(prefix)s.h"
+
+%(cb_decl)s#endif /* %(prefix)s_cb_h */
diff --git a/tools/dfagen/dfagen/output/c/template_cb_decl.h b/tools/dfagen/dfagen/output/c/template_cb_decl.h
new file mode 100644
index 00000000..a1e7c0f2
--- /dev/null
+++ b/tools/dfagen/dfagen/output/c/template_cb_decl.h
@@ -0,0 +1,6 @@
+/*
+ * %(state)s =%(event)s=>
+%(*branches_to)s */
+%(prefix)s_branch_t
+%(prefix)s__%(state)s__%(event)s (%(user.type)s *user);
+
diff --git a/tools/dfagen/dfagen/output/c/template_cb_impl.c b/tools/dfagen/dfagen/output/c/template_cb_impl.c
new file mode 100644
index 00000000..ffd9720f
--- /dev/null
+++ b/tools/dfagen/dfagen/output/c/template_cb_impl.c
@@ -0,0 +1,9 @@
+/*
+ * %(state)s =%(event)s=>
+%(*branches_to)s */
+%(prefix)s_branch_t
+%(prefix)s__%(state)s__%(event)s (%(user.type)s *user)
+{
+%(returns)s
+}
+
diff --git a/tools/dfagen/dfagen/output/c/template_cb_skel.c b/tools/dfagen/dfagen/output/c/template_cb_skel.c
new file mode 100644
index 00000000..95abbd42
--- /dev/null
+++ b/tools/dfagen/dfagen/output/c/template_cb_skel.c
@@ -0,0 +1,9 @@
+/*
+ * THIS IS AN AUTOMATICALLY GENERATED FILE, DO NOT EDIT!
+ *
+ * Skeleton for %(name)s callbacks implementation.
+ *
+%(*comments)s */
+#include "%(prefix)s_cb.h"
+
+%(cb_impl)s
diff --git a/tools/dfagen/dfagen/output/dot.py b/tools/dfagen/dfagen/output/dot.py
new file mode 100644
index 00000000..100cbb8f
--- /dev/null
+++ b/tools/dfagen/dfagen/output/dot.py
@@ -0,0 +1,19 @@
+
+def write (prefix, automaton, user):
+ output = prefix + '.dot'
+ o = open (output, 'w')
+ o.write ('digraph %s {' % prefix)
+ for s in automaton.states.values ():
+ o.write (' %s\n' % s.name)
+ for tr in s.transitions.values ():
+ for br in tr.branches.values ():
+ o.write (' %(state)s -> %(to)s [ label = "%(event)s" ];\n'
+ % dict (
+ state = s.name,
+ event = tr.event.name
+ + (br.name and ': ' + br.name or ''),
+ to = (br.to and br.to.name or s.name),
+ )
+ )
+ o.write ('}')
+ o.close ()