1 # |
|
2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 |
|
17 ''' |
|
18 Finite State Machine generator for Symbian OS projects. |
|
19 |
|
20 Just define fsmName, actionsIfaceName and stt and the script generates the |
|
21 needed files for you. |
|
22 |
|
23 The files are: |
|
24 - State Machine header file (including state classes, overwrites the existing file) |
|
25 - State Machine source file (including state classes, overwrites the existing file) |
|
26 - Actions interface header (abstract M-class, overwrites the existing file) |
|
27 - Header file for tracing (will be generated only if missing) |
|
28 |
|
29 |
|
30 Version 1: 22-Jun-2006, Jaakko Vuori, Initial version |
|
31 Version 2: 26-Jun-2006, Jaakko Vuori, Added argument passing |
|
32 Version 3: 27-Jun-2006, Jaakko Vuori, Changed state classes nested in FSM class |
|
33 |
|
34 ''' |
|
35 from sets import Set |
|
36 import os, re, string |
|
37 |
|
38 #------------------------------------------------------------------------ |
|
39 #State machine name |
|
40 fsmName = "Popup" |
|
41 |
|
42 #Actions interface name |
|
43 actionsIfaceName = "PopupFSMActions" |
|
44 |
|
45 #State transition table |
|
46 stt=[ #source state #event #dest state #actions |
|
47 ("NotSetOffFocus", [ |
|
48 ("HandleUpdate()", "SetOffFocus", ["IssueCleanCaption()"]), |
|
49 ("HandleGotFocus()", "NotSetOnFocus", []), |
|
50 ("HandleForeground()", "NotSetOffFocus", ["IssuePublishCaption()"]), |
|
51 ]), |
|
52 |
|
53 ("SetOffFocus", [ |
|
54 ("HandleGotFocus()", "GettingFocus", ["StartShortTimer()"]), |
|
55 ("HandleReset()", "NotSetOffFocus", ["IssuePublishCaption()"]), |
|
56 ]), |
|
57 |
|
58 ("GettingFocus", [ |
|
59 ("HandleRequestCompleted()", "Visible", ["IssuePublishPopup()", "StartLongTimer()"]), |
|
60 ("HandleReset()", "NotSetOnFocus", ["IssuePublishCaption()", "CancelRequest()"]), |
|
61 ("HandleLostFocus()", "SetOffFocus", ["CancelRequest()"]), |
|
62 ]), |
|
63 |
|
64 ("LosingFocus", [ |
|
65 ("HandleRequestCompleted()", "SetOffFocus", ["IssueCleanPopup()"]), |
|
66 ("HandleReset()", "NotSetOffFocus", ["IssuePublishCaption()", "CancelRequest()"]), |
|
67 ("HandleGotFocus()", "Visible", ["CancelRequest()", "StartLongTimer()"]), |
|
68 ]), |
|
69 |
|
70 ("NotSetOnFocus", [ |
|
71 ("HandleUpdate()", "Visible", ["IssueCleanCaption()", "IssuePublishPopup()", "StartLongTimer()"]), |
|
72 ("HandleLostFocus()", "NotSetOffFocus", []), |
|
73 ("HandleBackground()", "BackgroundNotSetOnFocus", []), |
|
74 ("HandleForeground()", "NotSetOnFocus", ["IssuePublishCaption()"]), |
|
75 ]), |
|
76 |
|
77 ("Visible", [ |
|
78 ("HandleUpdate()", "Visible", ["IssueCleanCaption()", "IssuePublishPopup()", "StartLongTimer()"]), |
|
79 ("HandleReset()", "NotSetOnFocus", ["IssuePublishCaption()", "IssueCleanPopup()", "CancelRequest()"]), |
|
80 ("HandleLostFocus()", "LosingFocus", ["CancelRequest()", "CompleteSelf()"]), |
|
81 ("HandleRequestCompleted()", "NotVisible", ["IssueCleanPopup()"]), |
|
82 ("HandleBackground()", "BackgroundSetOnFocus", ["CancelRequest()", "IssueCleanPopup()"]), |
|
83 ]), |
|
84 |
|
85 ("NotVisible", [ |
|
86 ("HandleUpdate()", "Visible", ["IssueCleanCaption()", "IssuePublishPopup()", "StartLongTimer()"]), |
|
87 ("HandleReset()", "NotSetOnFocus", ["IssuePublishCaption()"]), |
|
88 ("HandleLostFocus()", "SetOffFocus", []), |
|
89 ]), |
|
90 |
|
91 ("BackgroundNotSetOnFocus", [ |
|
92 ("HandleForeground()", "NotSetOnFocus", ["IssuePublishCaption()"]), |
|
93 ("HandleUpdate()", "BackgroundSetOnFocus", ["IssueCleanCaption()"]), |
|
94 ]), |
|
95 |
|
96 ("BackgroundSetOnFocus", [ |
|
97 ("HandleReset()", "BackgroundNotSetOnFocus", ["IssuePublishCaption()"]), |
|
98 ("HandleForeground()", "Visible", ["IssuePublishPopup()", "StartLongTimer()"]), |
|
99 ]), |
|
100 |
|
101 ] |
|
102 #------------------------------------------------------------------------ |
|
103 |
|
104 def write( s ): |
|
105 f.write( s + '\n' ) |
|
106 |
|
107 def writeHeader(): |
|
108 global f |
|
109 fname = '%sFSM.h' % (fsmName) |
|
110 print "Generating %s..." % (fname) |
|
111 f = open( fname, 'w' ) |
|
112 |
|
113 write( "#ifndef %sFSM_H" % ( fsmName.upper() ) ) |
|
114 write( "#define %sFSM_H" % ( fsmName.upper() ) ) |
|
115 write( "" ) |
|
116 write( "// EXTERNAL INCLUDES" ) |
|
117 write( "#include <e32base.h>" ) |
|
118 write( "" ) |
|
119 write( "// FORWARD DECLARATIONS" ) |
|
120 write( "class T%sFSM;" % (fsmName) ) |
|
121 write( "class M%s;" % (actionsIfaceName) ) |
|
122 write( "" ) |
|
123 write( "// CLASS DEFINITIONS" ) |
|
124 |
|
125 write( "/**" ) |
|
126 write( " * %s state machine" % (fsmName) ) |
|
127 write( " */" ) |
|
128 write( "class T%sFSM" % (fsmName) ) |
|
129 write( " {" ) |
|
130 |
|
131 write( " /**" ) |
|
132 write( " * Base class for states" ) |
|
133 write( " */" ) |
|
134 write( " class T%sStateBase" % (fsmName) ) |
|
135 write( " {" ) |
|
136 write( " public: // New methods" ) |
|
137 |
|
138 events=[] |
|
139 for s in stt: |
|
140 for e in s[1]: |
|
141 events.append( e[0] ) |
|
142 for event in Set(events): |
|
143 fname, args = re.match('(.*?)[(](.*?)[)]',event).groups() |
|
144 if len(args)>0: |
|
145 write( " virtual void %s( T%sFSM* a%sFSM, M%s& a%s,%s);" % (fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName,args) ) |
|
146 else: |
|
147 write( " virtual void %s( T%sFSM* a%sFSM, M%s& a%s );" % (fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName) ) |
|
148 |
|
149 |
|
150 write( " };" ) |
|
151 write( "" ) |
|
152 |
|
153 for s in stt: |
|
154 write( " /**" ) |
|
155 write( " * State class T%s" % (s[0]) ) |
|
156 write( " */" ) |
|
157 write( " class T%s : public T%sStateBase" % (s[0],fsmName) ) |
|
158 write( " {" ) |
|
159 write( " protected: // Methods derived from T%sState" % (fsmName)) |
|
160 for event in s[1]: |
|
161 fname, args = re.match('(.*?)[(](.*?)[)]',event[0]).groups() |
|
162 if len(args)>0: |
|
163 write( " void %s( T%sFSM* a%sFSM, M%s& a%s,%s);" % (fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName,args) ) |
|
164 else: |
|
165 write( " void %s( T%sFSM* a%sFSM, M%s& a%s );" % (fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName) ) |
|
166 |
|
167 write( " };" ) |
|
168 write( "" ) |
|
169 |
|
170 write( "" ) |
|
171 write( " public: // Constructors" ) |
|
172 write( " T%sFSM( M%s& a%s );" % (fsmName,actionsIfaceName,actionsIfaceName)) |
|
173 write( "" ) |
|
174 write( " public: // New methods" ) |
|
175 for event in Set(events): |
|
176 write( " void %s;" % (event)) |
|
177 write( "" ) |
|
178 write( " private: // New methods" ) |
|
179 write( " void SetState( T%sStateBase* aNewState );" % (fsmName) ) |
|
180 write( "" ) |
|
181 write( " private: // Data" ) |
|
182 write( " //Ref:" ) |
|
183 write( " T%sStateBase* iCurrentState;" % (fsmName)) |
|
184 write( " M%s& i%s;" % (actionsIfaceName,actionsIfaceName)) |
|
185 write( "" ) |
|
186 write( " //Own:" ) |
|
187 for s in stt: |
|
188 write( " T%s i%s;" % (s[0],s[0])) |
|
189 |
|
190 write( " private: // Friend class definitions" ) |
|
191 for s in stt: |
|
192 write( " friend class T%s;" % (s[0])) |
|
193 |
|
194 write( " };" ) |
|
195 write( "" ) |
|
196 write( "#endif // %sFSM_H" % (fsmName.upper()) ) |
|
197 write( "" ) |
|
198 write( "// End of file" ) |
|
199 f.close() |
|
200 |
|
201 |
|
202 def writeSource(): |
|
203 global f |
|
204 fname = '%sFSM.cpp' % (fsmName) |
|
205 print "Generating %s..." % (fname) |
|
206 f = open( fname, 'w' ) |
|
207 |
|
208 write( '#include "%sFSM.h"' % (fsmName) ) |
|
209 write( '#include "M%s.h"' % (actionsIfaceName) ) |
|
210 write( '#include "%sTrace.h"' % (fsmName) ) |
|
211 write( '' ) |
|
212 write( '#pragma warning( disable:4100 )' ) |
|
213 write( '#pragma warning( disable:4068 )' ) |
|
214 write( '#pragma warn_unusedarg off' ) |
|
215 |
|
216 write( '' ) |
|
217 write( 'T%sFSM::T%sFSM( M%s& a%s ) : ' % (fsmName,fsmName,actionsIfaceName,actionsIfaceName) ) |
|
218 write( ' iCurrentState( &i%s ),' % (stt[0][0]) ) |
|
219 write( ' i%s( a%s )' % (actionsIfaceName,actionsIfaceName) ) |
|
220 write( ' {' ) |
|
221 write( ' }' ) |
|
222 write( '' ) |
|
223 |
|
224 events=[] |
|
225 for s in stt: |
|
226 for e in s[1]: |
|
227 events.append( e[0] ) |
|
228 |
|
229 for event in Set(events): |
|
230 fname, args = re.match('(.*?)[(](.*?)[)]',event).groups() |
|
231 if len(args)>0: |
|
232 write( 'void T%sFSM::T%sStateBase::%s( T%sFSM* /*a%sFSM*/, M%s& /*a%s*/,%s )' % (fsmName,fsmName,fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName,args)) |
|
233 else: |
|
234 write( 'void T%sFSM::T%sStateBase::%s( T%sFSM* /*a%sFSM*/, M%s& /*a%s*/ )' % (fsmName,fsmName,fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName)) |
|
235 write( ' {' ) |
|
236 write( ' TRACE( _L("T%sStateBase::%s") );' % (fsmName,event)) |
|
237 write( ' }' ) |
|
238 write( '' ) |
|
239 |
|
240 for event in Set(events): |
|
241 fname, args = re.match('(.*?)[(](.*?)[)]',event).groups() |
|
242 write( 'void T%sFSM::%s(%s)' % (fsmName,fname,args) ) |
|
243 write( ' {' ) |
|
244 arglist=args.split(',') |
|
245 argnames = string.join([arg.split()[-1:][0] for arg in arglist if arg!=""], ', ') |
|
246 if len(argnames)>0: |
|
247 write( ' iCurrentState->%s( this, i%s, %s );' % (fname,actionsIfaceName,argnames) ) |
|
248 else: |
|
249 write( ' iCurrentState->%s( this, i%s );' % (fname,actionsIfaceName) ) |
|
250 write( ' }' ) |
|
251 write( '' ) |
|
252 |
|
253 write( 'void T%sFSM::SetState( T%sStateBase* aNewState )' % (fsmName,fsmName) ) |
|
254 write( ' {' ) |
|
255 write( ' iCurrentState = aNewState;' ) |
|
256 write( ' }' ) |
|
257 write( '' ) |
|
258 |
|
259 for s in stt: |
|
260 stateName, events = s |
|
261 for event in events: |
|
262 eventName = event[0] |
|
263 destState = event[1] |
|
264 actions = event[2] |
|
265 fname, args = re.match('(.*?)[(](.*?)[)]',eventName).groups() |
|
266 if len(actions)>0: |
|
267 if len(args)>0: |
|
268 write( 'void T%sFSM::T%s::%s( T%sFSM* a%sFSM, M%s& a%s,%s )' % (fsmName,stateName,fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName,args) ) |
|
269 else: |
|
270 write( 'void T%sFSM::T%s::%s( T%sFSM* a%sFSM, M%s& a%s )' % (fsmName,stateName,fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName) ) |
|
271 else: |
|
272 if len(args)>0: |
|
273 write( 'void T%sFSM::T%s::%s( T%sFSM* a%sFSM, M%s& /*a%s*/,%s )' % (fsmName,stateName,fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName,args) ) |
|
274 else: |
|
275 write( 'void T%sFSM::T%s::%s( T%sFSM* a%sFSM, M%s& /*a%s*/ )' % (fsmName,stateName,fname,fsmName,fsmName,actionsIfaceName,actionsIfaceName) ) |
|
276 |
|
277 write( ' {' ) |
|
278 write( ' TRACE( _L("T%s::%s") );' % (stateName, eventName) ) |
|
279 write( ' a%sFSM->SetState( &a%sFSM->i%s );' % (fsmName,fsmName,destState) ) |
|
280 for action in actions: |
|
281 fname, args = re.match('(.*?)[(](.*?)[)]',action).groups() |
|
282 if len(args)>0: |
|
283 arglist=args.split(',') |
|
284 argnames = string.join([arg.split()[-1:][0] for arg in arglist if arg!=""], ', ') |
|
285 write( ' a%s.%s( %s );' % (actionsIfaceName,fname,argnames) ) |
|
286 else: |
|
287 write( ' a%s.%s();' % (actionsIfaceName,fname) ) |
|
288 write( ' }' ) |
|
289 write( '' ) |
|
290 |
|
291 write( '// End of file' ) |
|
292 |
|
293 |
|
294 def writeTraceHeader(): |
|
295 if not os.path.isfile( '%sTrace.h' % (fsmName) ): |
|
296 global f |
|
297 fname = '%sTrace.h' % (fsmName) |
|
298 print "Generating %s..." % (fname) |
|
299 f = open( fname, 'w' ) |
|
300 write( '#ifndef %sTRACE_H' % (fsmName.upper()) ) |
|
301 write( '#define %sTRACE_H' % (fsmName.upper()) ) |
|
302 write( '' ) |
|
303 write( '// MACROS' ) |
|
304 write( '#define TRACE' ) |
|
305 write( '' ) |
|
306 write( '#endif // %sTRACE_H' % (fsmName.upper()) ) |
|
307 write( '' ) |
|
308 write( '// End of file' ) |
|
309 f.close() |
|
310 |
|
311 |
|
312 def writeActionsIface(): |
|
313 global f |
|
314 fname = 'M%s.h' % (actionsIfaceName) |
|
315 print "Generating %s..." % (fname) |
|
316 f = open( fname, 'w' ) |
|
317 |
|
318 write( '#ifndef M%s_H' % (actionsIfaceName.upper()) ) |
|
319 write( '#define M%s_H' % (actionsIfaceName.upper()) ) |
|
320 write( '' ) |
|
321 write( '// EXTERNAL INCLUDES' ) |
|
322 write( '#include <e32def.h>' ) |
|
323 write( '' ) |
|
324 write( '// CLASS DEFINITION' ) |
|
325 write( '/**' ) |
|
326 write( ' * M%s actions.' % (actionsIfaceName) ) |
|
327 write( ' * Note: This file has been generated automatically. Do not edit!' ) |
|
328 write( ' */' ) |
|
329 write( 'class M%s' % (actionsIfaceName) ) |
|
330 write( ' {' ) |
|
331 write( ' public: // Abstract methods' ) |
|
332 |
|
333 actions=[] |
|
334 for s in stt: |
|
335 for e in s[1]: |
|
336 actions.extend( e[2] ) |
|
337 for action in Set(actions): |
|
338 write( ' virtual void %s = 0;' % (action)) |
|
339 write( ' };' ) |
|
340 write( '' ) |
|
341 write( '#endif // M%s_H' % (actionsIfaceName.upper()) ) |
|
342 write( '' ) |
|
343 write( '// End of file' ) |
|
344 f.close() |
|
345 |
|
346 if __name__ == "__main__": |
|
347 writeHeader() |
|
348 writeSource() |
|
349 writeTraceHeader() |
|
350 writeActionsIface() |
|