summaryrefslogtreecommitdiff
path: root/tools
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
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')
-rw-r--r--tools/dfagen/dfagen/automaton.py72
-rw-r--r--tools/dfagen/dfagen/command.py16
-rw-r--r--tools/dfagen/dfagen/output/__init__.py1
-rw-r--r--tools/dfagen/dfagen/output/c.py160
-rw-r--r--tools/dfagen/dfagen/output/c/template.c2
-rw-r--r--tools/dfagen/dfagen/output/c/template_cb_decl.h2
-rw-r--r--tools/dfagen/dfagen/output/c/template_cb_impl.c2
-rw-r--r--tools/dfagen/dfagen/output/dot.py11
-rw-r--r--tools/dfagen/dfagen/parser.g16
-rw-r--r--tools/dfagen/examples/ex1_cb.c.patch2
-rw-r--r--tools/dfagen/examples/ex2.fsm8
-rw-r--r--tools/dfagen/examples/ex2_cb.c.patch50
-rw-r--r--tools/dfagen/examples/tpl/template_defs.h9
-rw-r--r--tools/dfagen/examples/tpl/template_table.h16
14 files changed, 273 insertions, 94 deletions
diff --git a/tools/dfagen/dfagen/automaton.py b/tools/dfagen/dfagen/automaton.py
index 05dda350..e0239df7 100644
--- a/tools/dfagen/dfagen/automaton.py
+++ b/tools/dfagen/dfagen/automaton.py
@@ -15,28 +15,40 @@ class Event:
class State:
"""State definition."""
- def __init__ (self, name, comments = ''):
+ def __init__ (self, name, comments = '', initial = False):
self.name = name
self.comments = comments
+ self.initial = initial
self.transitions = { }
+ self.transitions_list = [ ]
+ self.attributes = None
def __str__ (self):
- s = ' ' + self.name + '\n'
+ s = ' ' + self.name
+ if self.attributes:
+ s += ' [ %s ]' % self.attributes
+ s += '\n'
if self.comments:
s += ' ' + self.comments.replace ('\n', '\n ') + '\n'
return s
def add_branch (self, branch):
if branch.event not in self.transitions:
- self.transitions[branch.event] = Transition (branch.event)
+ tr = Transition (branch.event)
+ self.transitions[branch.event] = tr
+ self.transitions_list.append (tr)
self.transitions[branch.event].add_branch (branch)
+ def iter_transitions (self):
+ return iter (self.transitions_list)
+
class Transition:
"""Transition definition."""
def __init__ (self, event):
self.event = event
self.branches = { }
+ self.branches_list = [ ]
def add_branch (self, branch):
assert self.event is branch.event
@@ -47,12 +59,17 @@ class Transition:
if branch.name in self.branches:
raise KeyError (branch.name)
self.branches[branch.name] = branch
+ self.branches_list.append (branch)
+
+ def iter_branches (self):
+ return iter (self.branches_list)
+
+ def get_attributes (self):
+ return [ b.attributes for b in self.iter_branches ()
+ if b.attributes is not None ]
def __str__ (self):
- s = ''
- for br in self.branches.values ():
- s += str (br);
- return s
+ return ''.join (str (br) for br in self.iter_branches ())
class TransitionBranch:
@@ -61,51 +78,68 @@ class TransitionBranch:
self.name = name
self.to = to
self.comments = comments
+ self.attributes = None
def __str__ (self):
s = ' ' + self.event.name
if self.name:
s += ': ' + self.name
- s += ' -> ' + (self.to and self.to.name or '.') + '\n'
+ s += ' -> ' + (self.to and self.to.name or '.')
+ if self.attributes:
+ s += ' [ %s ]' % self.attributes
+ s += '\n'
if self.comments:
s += ' ' + self.comments.replace ('\n', '\n ') + '\n'
return s
class Automaton:
-
+
def __init__ (self, name):
self.name = name
self.comments = ''
- self.initial = None
+ self.initials = [ ]
self.states = { }
+ self.states_list = [ ]
self.events = { }
+ self.events_list = [ ]
def add_state (self, state):
if state.name in self.states:
raise KeyError (state.name)
+ if state.initial:
+ self.initials.append (state)
if not self.states:
- self.initial = state
+ state.initial = True
+ self.initials.append (state)
self.states[state.name] = state
+ self.states_list.append (state)
def add_event (self, event):
if event.name in self.events:
raise KeyError (event.name)
self.events[event.name] = event
+ self.events_list.append (event)
+
+ def iter_states (self):
+ return iter (self.states_list)
+
+ def iter_initials (self):
+ return iter (self.initials)
+
+ def iter_events (self):
+ return iter (self.events_list)
def __str__ (self):
- s = self.name
+ s = self.name + '\n'
if self.comments:
s += ' ' + self.comments.replace ('\n', '\n ') + '\n'
s += '\nStates:\n'
- for state in self.states.values ():
- s += str (state)
+ s += ''.join (str (state) for state in self.iter_states ())
s += '\nEvents:\n'
- for event in self.events.values ():
- s += str (event)
+ s += ''.join (str (state) for state in self.iter_events ())
s += '\n'
- for state in self.states.values ():
+ for state in self.iter_states ():
s += state.name + ':\n'
- for tr in state.transitions.values ():
- s += str (tr)
+ s += ''.join (str (tr) for tr in state.iter_transitions ())
s += '\n'
return s
diff --git a/tools/dfagen/dfagen/command.py b/tools/dfagen/dfagen/command.py
index 8a976023..3325d6c1 100644
--- a/tools/dfagen/dfagen/command.py
+++ b/tools/dfagen/dfagen/command.py
@@ -17,13 +17,25 @@ def run ():
help='read output configuration from FILE', metavar='FILE')
opt.add_option ('-p', '--prefix', dest='prefix',
help='use PREFIX for generated output', metavar='PREFIX')
- # TODO add more error checking.
+ opt.add_option ('-O', '--output-dir', dest='output_dir', default='',
+ help='generate output in DIR', metavar='DIR')
+ opt.add_option ('--dump', action='store_true', default=False,
+ help='dump the read automaton')
(options, args) = opt.parse_args ()
+ if (options.dfa is None
+ or not options.dump and options.output is None
+ or len (args) != 0):
+ opt.error ('bad arguments')
# Read automaton.
f = open (options.dfa, 'r')
a = dfagen.parser.parse ('automaton', f.read ())
f.close ()
+ # Dump automaton.
+ if options.dump:
+ print a
# Read config.
cfg = dfagen.output.UserConfig (options.config)
# Produce output.
- dfagen.output.get_output (options.output).write (options.prefix, a, cfg)
+ if options.output is not None:
+ dfagen.output.get_output (options.output).write (options.prefix, a,
+ cfg, options.output_dir)
diff --git a/tools/dfagen/dfagen/output/__init__.py b/tools/dfagen/dfagen/output/__init__.py
index 567ab745..eadd8c2f 100644
--- a/tools/dfagen/dfagen/output/__init__.py
+++ b/tools/dfagen/dfagen/output/__init__.py
@@ -2,6 +2,7 @@ from ConfigParser import ConfigParser
class UserConfig:
def __init__ (self, file):
+ self.file = file
if file:
f = open (file, 'r')
cp = ConfigParser ()
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 ()
diff --git a/tools/dfagen/dfagen/output/c/template.c b/tools/dfagen/dfagen/output/c/template.c
index a8679046..6beda928 100644
--- a/tools/dfagen/dfagen/output/c/template.c
+++ b/tools/dfagen/dfagen/output/c/template.c
@@ -8,7 +8,7 @@
#include <stddef.h>
#include <assert.h>
-%(_user.type-decl)s
+%(_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] = {
diff --git a/tools/dfagen/dfagen/output/c/template_cb_decl.h b/tools/dfagen/dfagen/output/c/template_cb_decl.h
index a1e7c0f2..3bb0a35f 100644
--- a/tools/dfagen/dfagen/output/c/template_cb_decl.h
+++ b/tools/dfagen/dfagen/output/c/template_cb_decl.h
@@ -2,5 +2,5 @@
* %(state)s =%(event)s=>
%(*branches_to)s */
%(prefix)s_branch_t
-%(prefix)s__%(state)s__%(event)s (%(user.type)s *user);
+%(callback)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
index ffd9720f..e5a4d789 100644
--- a/tools/dfagen/dfagen/output/c/template_cb_impl.c
+++ b/tools/dfagen/dfagen/output/c/template_cb_impl.c
@@ -2,7 +2,7 @@
* %(state)s =%(event)s=>
%(*branches_to)s */
%(prefix)s_branch_t
-%(prefix)s__%(state)s__%(event)s (%(user.type)s *user)
+%(callback)s (%(user.type)s *user)
{
%(returns)s
}
diff --git a/tools/dfagen/dfagen/output/dot.py b/tools/dfagen/dfagen/output/dot.py
index d6cc057c..ce9c4db8 100644
--- a/tools/dfagen/dfagen/output/dot.py
+++ b/tools/dfagen/dfagen/output/dot.py
@@ -1,12 +1,13 @@
+import os.path
-def write (prefix, automaton, user):
+def write (prefix, automaton, user, outputdir):
output = prefix + '.dot'
- o = open (output, 'w')
+ o = open (os.path.join (outputdir, output), 'w')
o.write ('digraph %s {' % prefix)
- for s in automaton.states.values ():
+ for s in automaton.iter_states ():
o.write (' %s\n' % s.name)
- for tr in s.transitions.values ():
- for br in tr.branches.values ():
+ for tr in s.iter_transitions ():
+ for br in tr.iter_branches ():
o.write (' %(state)s -> %(to)s [ label = "%(event)s" ];\n'
% dict (
state = s.name,
diff --git a/tools/dfagen/dfagen/parser.g b/tools/dfagen/dfagen/parser.g
index 62f9f4d1..e510ed22 100644
--- a/tools/dfagen/dfagen/parser.g
+++ b/tools/dfagen/dfagen/parser.g
@@ -10,6 +10,7 @@ parser AutomatonParser:
token EVENT: "\w([\w ]*\w)?"
token QUALIFIER: "\w([\w ]*\w)?"
token ATITLE: ".*?\n"
+ token ATTR: "\w([\w =]*\w)?"
rule automaton: ATITLE {{ a = Automaton (ATITLE.strip ()) }}
( comments {{ a.comments = comments }}
@@ -23,13 +24,19 @@ parser AutomatonParser:
( transdef<<a>>
) *
EOF {{ return a }}
-
- rule statedef: " " STATE {{ s = State (STATE) }}
+
+ rule statedef: {{ initial = False }}
+ " " ( "\*" {{ initial = True }}
+ ) ?
+ STATE {{ s = State (STATE, initial = initial) }}
+ ( "\s*\[\s*"
+ ATTR {{ s.attributes = ATTR }}
+ "\s*\]" ) ?
"\n"
( comments {{ s.comments = comments }}
) ?
{{ return s }}
-
+
rule eventdef: " " EVENT {{ e = Event (EVENT) }}
"\n"
( comments {{ e.comments = comments }}
@@ -52,6 +59,9 @@ parser AutomatonParser:
"\s*->\s*"
( STATE {{ t.to = a.states[STATE] }}
| "\\." )
+ ( "\s*\[\s*"
+ ATTR {{ t.attributes = ATTR }}
+ "\s*\]" ) ?
( comments {{ t.comments = comments }}
) ?
{{ return t }}
diff --git a/tools/dfagen/examples/ex1_cb.c.patch b/tools/dfagen/examples/ex1_cb.c.patch
index bc4cc924..48941dc5 100644
--- a/tools/dfagen/examples/ex1_cb.c.patch
+++ b/tools/dfagen/examples/ex1_cb.c.patch
@@ -7,7 +7,7 @@
+#include <stdio.h>
+
+struct door_t { ex1_state_t fsm; };
-+
++
/*
* OPEN =close=>
* => CLOSED
diff --git a/tools/dfagen/examples/ex2.fsm b/tools/dfagen/examples/ex2.fsm
index e290c05c..8142ad88 100644
--- a/tools/dfagen/examples/ex2.fsm
+++ b/tools/dfagen/examples/ex2.fsm
@@ -3,9 +3,9 @@ Example 2
A barman robot.
States:
- IDLE
+ IDLE [in=hello out=goodbye]
waiting for a command
- DROPPING_ICE
+ DROPPING_ICE [in=hi]
FILLING_GLASS
Events:
@@ -15,13 +15,13 @@ Events:
replace bottle
IDLE:
- command: with ice -> DROPPING_ICE
+ command: with ice -> DROPPING_ICE [ex2_idle_command]
open the ice door
command: without ice -> FILLING_GLASS
start filling
command: empty bottle -> .
display "empty bottle, please replace it"
- replace bottle -> .
+ replace bottle -> . [ex2_idle_replace]
reset glass counter
DROPPING_ICE:
diff --git a/tools/dfagen/examples/ex2_cb.c.patch b/tools/dfagen/examples/ex2_cb.c.patch
index f1402431..09f03791 100644
--- a/tools/dfagen/examples/ex2_cb.c.patch
+++ b/tools/dfagen/examples/ex2_cb.c.patch
@@ -1,5 +1,5 @@
---- ex2_cb_skel.c 2008-01-06 18:02:50.000000000 +0100
-+++ ex2_cb.c 2008-01-06 18:02:50.000000000 +0100
+--- ex2_cb_skel.c 2008-06-10 17:47:09.000000000 +0200
++++ ex2_cb.c 2008-06-10 17:47:09.000000000 +0200
@@ -6,6 +6,9 @@
* A barman robot.
*/
@@ -9,31 +9,14 @@
+#include <stdio.h>
/*
- * FILLING_GLASS =command=>
-@@ -37,6 +40,7 @@
+ * IDLE =command=>
+@@ -19,9 +22,25 @@
ex2_branch_t
- ex2__FILLING_GLASS__glass_filled (robot_t *user)
- {
-+ puts ("stop filling");
- return ex2_next (FILLING_GLASS, glass_filled);
- }
-
-@@ -48,6 +52,8 @@
- ex2_branch_t
- ex2__IDLE__replace_bottle (robot_t *user)
- {
-+ puts ("reset glass counter");
-+ user->bottle = 3;
- return ex2_next (IDLE, replace_bottle);
- }
-
-@@ -63,9 +69,25 @@
- ex2_branch_t
- ex2__IDLE__command (robot_t *user)
+ ex2_idle_command (robot_t *user)
{
-- return ex2_next_branch (IDLE, command, empty_bottle);
-- return ex2_next_branch (IDLE, command, without_ice);
- return ex2_next_branch (IDLE, command, with_ice);
+- return ex2_next_branch (IDLE, command, without_ice);
+- return ex2_next_branch (IDLE, command, empty_bottle);
+ if (user->bottle)
+ {
+ user->bottle--;
@@ -56,7 +39,16 @@
}
/*
-@@ -99,6 +121,8 @@
+@@ -32,6 +51,8 @@
+ ex2_branch_t
+ ex2_idle_replace (robot_t *user)
+ {
++ puts ("reset glass counter");
++ user->bottle = 3;
+ return ex2_next (IDLE, replace_bottle);
+ }
+
+@@ -44,6 +65,8 @@
ex2_branch_t
ex2__DROPPING_ICE__ice_dropped (robot_t *user)
{
@@ -65,3 +57,11 @@
return ex2_next (DROPPING_ICE, ice_dropped);
}
+@@ -77,6 +100,7 @@
+ ex2_branch_t
+ ex2__FILLING_GLASS__glass_filled (robot_t *user)
+ {
++ puts ("stop filling");
+ return ex2_next (FILLING_GLASS, glass_filled);
+ }
+
diff --git a/tools/dfagen/examples/tpl/template_defs.h b/tools/dfagen/examples/tpl/template_defs.h
index 54fabba4..e4e29fd3 100644
--- a/tools/dfagen/examples/tpl/template_defs.h
+++ b/tools/dfagen/examples/tpl/template_defs.h
@@ -15,11 +15,11 @@ enum %(prefix)s_state_t
typedef enum %(prefix)s_state_t %(prefix)s_state_t;
/* %(name)s events. */
-enum %(prefix)s_event_t
+enum %(prefix)s_event_type_t
{
-%(events)s %(PREFIX)s_EVENT_NB
+%(events,%(PREFIX)s_EVENT_TYPE_%(event)s)s %(PREFIX)s_EVENT_TYPE_NB
};
-typedef enum %(prefix)s_event_t %(prefix)s_event_t;
+typedef enum %(prefix)s_event_type_t %(prefix)s_event_type_t;
/* Only care about next state. */
#define _BRANCH(state, event, to) (%(PREFIX)s_STATE_ ## to)
@@ -43,4 +43,7 @@ typedef %(prefix)s_branch_t (*%(prefix)s_transition_t) (void);
#define %(prefix)s_next_branch(state, event, branch) \
%(PREFIX)s_BRANCH__ ## state ## __ ## event ## __ ## branch
+/* Number of initial events. */
+#define %(PREFIX)s_INITIALS_NB %(initials_nb)s
+
#endif /* %(prefix)s_defs_h */
diff --git a/tools/dfagen/examples/tpl/template_table.h b/tools/dfagen/examples/tpl/template_table.h
index 817197fa..39f07bdb 100644
--- a/tools/dfagen/examples/tpl/template_table.h
+++ b/tools/dfagen/examples/tpl/template_table.h
@@ -7,6 +7,20 @@
/* %(name)s transition table. */
static const %(prefix)s_transition_t
-%(prefix)s_transition_table[%(PREFIX)s_STATE_NB][%(PREFIX)s_EVENT_NB] = {
+%(prefix)s_transition_table[%(PREFIX)s_STATE_NB][%(PREFIX)s_EVENT_TYPE_NB] = {
%(transition_table)s};
+/* %(name)s only branch table. */
+static const %(prefix)s_state_t
+%(prefix)s_only_table[%(PREFIX)s_STATE_NB][%(PREFIX)s_EVENT_TYPE_NB] = {
+%(only_branch_table)s};
+
+/* %(name)s initial states. */
+static const %(prefix)s_state_t
+%(prefix)s_initials_table[] = {
+%(initials)s};
+
+/* %(name)s state attributes. */
+static const %(prefix)s_state_t
+%(prefix)s_attr_table[] = {
+%(states,"%(state)s (%(@)s) (%(@in)s) (%(@out|no_out)s)")s};