From 164ac3a34cbac441e82b256c97cb8784ea9d482c Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Mon, 17 Mar 2008 22:53:01 +0100 Subject: * tools/dfagen: - added dfagen. --- tools/dfagen/dfagen/output/__init__.py | 24 ++++ tools/dfagen/dfagen/output/c.py | 154 ++++++++++++++++++++++++ tools/dfagen/dfagen/output/c/template.c | 39 ++++++ tools/dfagen/dfagen/output/c/template.h | 59 +++++++++ tools/dfagen/dfagen/output/c/template_cb.h | 12 ++ tools/dfagen/dfagen/output/c/template_cb_decl.h | 6 + tools/dfagen/dfagen/output/c/template_cb_impl.c | 9 ++ tools/dfagen/dfagen/output/c/template_cb_skel.c | 9 ++ tools/dfagen/dfagen/output/dot.py | 19 +++ 9 files changed, 331 insertions(+) create mode 100644 tools/dfagen/dfagen/output/__init__.py create mode 100644 tools/dfagen/dfagen/output/c.py create mode 100644 tools/dfagen/dfagen/output/c/template.c create mode 100644 tools/dfagen/dfagen/output/c/template.h create mode 100644 tools/dfagen/dfagen/output/c/template_cb.h create mode 100644 tools/dfagen/dfagen/output/c/template_cb_decl.h create mode 100644 tools/dfagen/dfagen/output/c/template_cb_impl.c create mode 100644 tools/dfagen/dfagen/output/c/template_cb_skel.c create mode 100644 tools/dfagen/dfagen/output/dot.py (limited to 'tools/dfagen/dfagen/output') 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 +#include + +%(_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 () -- cgit v1.2.3