summaryrefslogtreecommitdiff
path: root/tools/dfagen/dfagen/output/c.py
diff options
context:
space:
mode:
authorNicolas Schodet2009-05-08 23:07:25 +0200
committerNicolas Schodet2009-05-08 23:07:25 +0200
commitb566e4bcd0c7cb3c90ad941b37db223134090ded (patch)
tree7d3f24a25860e17e7fa9cd017ad2d8bd8c0bd227 /tools/dfagen/dfagen/output/c.py
parent6b3d5061623a35c96e66e25fc14af6a9323f81b0 (diff)
* tools/dfagen:
- added state attributes. - added support for more than one initial state. - added table of transitions with only one default branch. - added state and event template parameter. - added --output-dir. - make template directory relative to config file. - more options checking. - added transition attributes and callback definition. - conserve input file order in output. - added --dump and more option checking. - fixed missing newline.
Diffstat (limited to 'tools/dfagen/dfagen/output/c.py')
-rw-r--r--tools/dfagen/dfagen/output/c.py160
1 files changed, 132 insertions, 28 deletions
diff --git a/tools/dfagen/dfagen/output/c.py b/tools/dfagen/dfagen/output/c.py
index 099302f9..5a44d0e3 100644
--- a/tools/dfagen/dfagen/output/c.py
+++ b/tools/dfagen/dfagen/output/c.py
@@ -1,48 +1,108 @@
import os.path
+import re
+
+class StateData:
+ """Data associated with a state when enumerating, used with templates."""
+
+ def __init__ (self, state, prefix):
+ self.state = state
+ self.dict = dict (
+ state = state.name,
+ prefix = prefix,
+ PREFIX = prefix.upper (),
+ )
+
+ def __getitem__ (self, key):
+ # Second argument may be a default value.
+ key = key.split ('|', 1) + [ '' ]
+ key, default = key[0], key[1]
+ val = None
+ # Get value.
+ if key in self.dict:
+ val = self.dict[key]
+ elif key == '@':
+ val = self.state.attributes
+ elif key.startswith ('@'):
+ if self.state.attributes is not None:
+ a = dict (p.split ('=')
+ for p in self.state.attributes.split ())
+ try:
+ val = a[key[1:]]
+ except KeyError:
+ pass
+ else:
+ raise KeyError, key
+ # Test for empty value, and return.
+ if val is None:
+ val = default
+ return val
+
class WriterData:
+ callback_re = re.compile ('^\w+$')
+
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.states = self.automaton.iter_states
+ self.initials = self.automaton.iter_initials
+ self.events = self.automaton.iter_events
self.dict = dict (
prefix = prefix,
PREFIX = prefix.upper (),
name = automaton.name,
comments = automaton.comments,
- initial = automaton.initial.name,
states = self.list_states,
+ initials = self.list_initials,
events = self.list_events,
states_names = self.list_states_names,
events_names = self.list_events_names,
+ initials_nb = str (len (automaton.initials)),
branches = self.list_branches,
+ only_branch_table = self.only_branch_table,
transition_table = self.transition_table,
states_template = self.states_template,
)
+ if len (automaton.initials) == 1:
+ self.dict['initial'] = automaton.initials[0].name
+
+ def list_states_sub (self, iter, template = None):
+ if template is None:
+ template = '%(PREFIX)s_STATE_%(state)s'
+ return ''.join (' '
+ + template % StateData (s, self.prefix)
+ + ',\n' for s in iter ())
+
+ def list_states (self, template = None):
+ return self.list_states_sub (self.states, template)
- def list_states (self):
- return ''.join ([' ' + self.prefix.upper () + '_STATE_' + s.name
- + ',\n' for s in self.states])
+ def list_initials (self, template = None):
+ return self.list_states_sub (self.initials, template)
- def list_events (self):
- return ''.join ([' ' + self.prefix.upper () + '_EVENT_'
- + e.name.replace (' ', '_') + ',\n' for e in self.events])
+ def list_events (self, template = None):
+ if template is None:
+ template = '%(PREFIX)s_EVENT_%(event)s'
+ return ''.join (' '
+ + template % dict (
+ PREFIX = self.prefix.upper (),
+ event = e.name.replace (' ', '_')
+ )
+ + ',\n' for e in self.events ())
def list_states_names (self):
- return ''.join ([' "' + s.name + '",\n' for s in self.states])
+ return ''.join (' "' + s.name + '",\n' for s in self.states ())
def list_events_names (self):
- return ''.join ([' "' + e.name.replace (' ', '_') + '",\n'
- for e in self.events])
+ return ''.join (' "' + 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 ():
+ for s in self.states ():
+ for tr in s.iter_transitions ():
+ for br in tr.iter_branches ():
n = dict (
PREFIX = self.prefix.upper (),
state = s.name,
@@ -55,15 +115,54 @@ class WriterData:
+ '_BRANCH (%(state)s, %(event)s, %(to)s),\n') % n
return l
+ def only_branch_table (self, template = None, null = None):
+ if template is None:
+ template = '%(PREFIX)s_STATE_%(state)s'
+ if null is None:
+ null = template
+ r = ''
+ for s in self.states ():
+ r += ' { '
+ es = [ ]
+ for e in self.events ():
+ to = None
+ t = None
+ if e in s.transitions and None in s.transitions[e].branches:
+ br = s.transitions[e].branches[None]
+ to = br.to and br.to.name or s.name
+ t = template
+ else:
+ to = 'NB'
+ t = null
+ es.append (t % dict (
+ PREFIX = self.prefix.upper (),
+ state = to,
+ ))
+ r += ',\n '.join (es)
+ r += ' },\n'
+ return r
+
+ def transition_callback (self, state, event):
+ attr = state.transitions[event].get_attributes ()
+ if attr:
+ assert len (attr) == 1, ("multiple callbacks for transition on "
+ + "event %s for state %s" % (event.name, state.name))
+ callback = attr[0]
+ assert self.callback_re.match (callback), ("bad callback name %s"
+ % callback)
+ return callback
+ else:
+ return (self.prefix + '__' + state.name + '__'
+ + event.name.replace (' ', '_'))
+
def transition_table (self):
r = ''
- for s in self.states:
+ for s in self.states ():
r += ' { '
es = [ ]
- for e in self.events:
+ for e in self.events ():
if e in s.transitions:
- es.append (self.prefix + '__' + s.name + '__'
- + e.name.replace (' ', '_'))
+ es.append (self.transition_callback (s, e))
else:
es.append ('NULL')
r += ',\n '.join (es)
@@ -75,8 +174,8 @@ class WriterData:
tt = t.read ()
t.close ()
exp = ''
- for s in self.states:
- for tr in s.transitions.values ():
+ for s in self.states ():
+ for tr in s.iter_transitions ():
d = WriterData (self.prefix, self.automaton, self.user)
branches_to = '\n'.join (
[(br.name and br.name or '')
@@ -84,7 +183,7 @@ class WriterData:
+ (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 ()])
+ for br in tr.iter_branches ()])
returns = '\n'.join (
[' return ' + self.prefix + '_next'
+ (br.name and '_branch' or '')
@@ -93,7 +192,7 @@ class WriterData:
+ (br.name and ', ' + br.name.replace (' ', '_')
or '')
+ ');'
- for br in tr.branches.values ()])
+ for br in tr.iter_branches ()])
d.dict = dict (
prefix = self.prefix,
user = self.user,
@@ -101,6 +200,7 @@ class WriterData:
event = tr.event.name.replace (' ', '_'),
branches_to = branches_to,
returns = returns,
+ callback = self.transition_callback (s, tr.event),
)
exp += tt % d
return exp
@@ -131,17 +231,18 @@ class WriterData:
class Writer:
- def __init__ (self, data, templatedir):
+ def __init__ (self, data, templatedir, outputdir):
data.templatedir = templatedir
self.data = data
self.templatedir = templatedir
+ self.outputdir = outputdir
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 = open (os.path.join (self.outputdir, output), 'w')
o.write (exp)
o.close ()
@@ -157,8 +258,11 @@ class Writer:
for (t, f) in templates.iteritems ():
self.write_template (t, f.replace ('%', self.data.prefix))
-def write (prefix, automaton, user):
- w = Writer (WriterData (prefix, automaton, user), 'template-dir' in user
- and user['template-dir'] or os.path.splitext (__file__)[0])
+def write (prefix, automaton, user, outputdir):
+ templatedir = os.path.splitext (__file__)[0]
+ if 'template-dir' in user:
+ templatedir = os.path.join (os.path.split (user.file)[0],
+ user['template-dir'])
+ w = Writer (WriterData (prefix, automaton, user), templatedir, outputdir)
w.write ()