gv_fsm 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/gv_fsm +5 -0
- data/lib/gv_fsm.rb +8 -3
- data/lib/templates.rb +42 -41
- data/lib/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 450afef3dccacff09f92f297a5b5bcbdfb9d1c960bea0d546bcafe7123f5cebd
|
4
|
+
data.tar.gz: 1fa684d748abecd8c8f17ac2a2b7ca17c83506003eb2cc143596668a32d0a1ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98d883a1bff3afaae6fe1531a8f702b6600c97bd37fa4260b3eef02ecccfaf978ab3a9acc096a0c62d9d95c2b4450df105a5cc38f1a03f624984813c9ac5bcb9
|
7
|
+
data.tar.gz: 20af124b281a5aeba975d5124c4a552480d03ea9d4cb13903f4c60f3408c28876adf12a040455dd48afb98ebed8dedb0ee65121e6e93e0d3c9d854a43e4fea57
|
data/bin/gv_fsm
CHANGED
@@ -36,12 +36,17 @@ OptionParser.new do |parser|
|
|
36
36
|
options[:header] = false
|
37
37
|
end
|
38
38
|
|
39
|
+
parser.on("-x", "--prefix PREFIX", "Prepend PREFIX to names of generated functions and objects") do |p|
|
40
|
+
sm.prefix = p
|
41
|
+
end
|
42
|
+
|
39
43
|
end.parse!
|
40
44
|
|
41
45
|
raise ArgumentError, "I need the path to a Graphviz file!" unless ARGV[0]
|
42
46
|
raise ArgumentError, "#{ARGV[0]} does not look like a Graphviz file!" unless File.extname(ARGV[0]) == ".dot"
|
43
47
|
|
44
48
|
sm.parse(ARGV[0])
|
49
|
+
|
45
50
|
puts "Parsed #{sm.dotfile}.\nGenerating C stub for states: #{sm.states_list.join(", ")}."
|
46
51
|
if options[:header] then
|
47
52
|
sm.generate_h
|
data/lib/gv_fsm.rb
CHANGED
@@ -8,14 +8,19 @@ require File.expand_path("../version.rb", __FILE__)
|
|
8
8
|
|
9
9
|
module GV_FSM
|
10
10
|
class FSM
|
11
|
-
attr_reader :states, :transitions, :dotfile
|
11
|
+
attr_reader :states, :transitions, :dotfile, :prefix
|
12
12
|
attr_accessor :project_name, :description, :cname
|
13
13
|
include GV_FSM::Templates
|
14
14
|
|
15
15
|
def initialize(filename = nil)
|
16
|
+
@prefix = ""
|
16
17
|
parse(filename) if filename
|
17
18
|
end
|
18
19
|
|
20
|
+
def prefix=(v)
|
21
|
+
@prefix = v + '_'
|
22
|
+
end
|
23
|
+
|
19
24
|
def parse(filename)
|
20
25
|
raise ArgumentError, "File must be in .dot format" unless File.extname(filename) == ".dot"
|
21
26
|
@cname = File.basename(filename, ".dot") unless (@cname and ! @cname.empty?)
|
@@ -26,7 +31,7 @@ module GV_FSM
|
|
26
31
|
g.each_node do |id|
|
27
32
|
n = g.get_node(id)
|
28
33
|
label = n[:label].source.empty? ? "do_#{id}" : n[:label].source
|
29
|
-
@states << {id: id, function: label}
|
34
|
+
@states << {id: id, function: @prefix+label}
|
30
35
|
end
|
31
36
|
g.each_edge do |e|
|
32
37
|
from = e.node_one
|
@@ -40,7 +45,7 @@ module GV_FSM
|
|
40
45
|
else
|
41
46
|
label = e[:label].source
|
42
47
|
end
|
43
|
-
@transitions << {from: from, to: to, function: label}
|
48
|
+
@transitions << {from: from, to: to, function: label ? @prefix+label : nil}
|
44
49
|
end
|
45
50
|
end
|
46
51
|
end
|
data/lib/templates.rb
CHANGED
@@ -3,63 +3,64 @@ module GV_FSM
|
|
3
3
|
module Templates
|
4
4
|
HEADER =<<~EOHEADER
|
5
5
|
// Finite State Machine
|
6
|
-
// Project: <%=
|
7
|
-
// Description: <%=
|
6
|
+
// Project: <%= @project_name or @dotfile %>
|
7
|
+
// Description: <%= @description or "<none given>" %>
|
8
8
|
//
|
9
9
|
// Generated by gv_fsm ruby gem, see https://rubygems.org/gems/gv_fsm
|
10
10
|
// gv_fsm version <%= GV_FSM::VERSION %>
|
11
11
|
// Generation date: <%= Time.now %>
|
12
|
-
// Generated from: <%=
|
12
|
+
// Generated from: <%= @dotfile %>
|
13
13
|
// The finite state machine has:
|
14
|
-
// <%=
|
15
|
-
// <%=
|
14
|
+
// <%= @states.count %> states
|
15
|
+
// <%= @transitions.count %> transitions
|
16
|
+
// <%= transition_functions_list.select {|e| e != 'NULL'}.count %> transition functions
|
16
17
|
|
17
18
|
EOHEADER
|
18
19
|
|
19
20
|
HH =<<~EOH
|
20
|
-
#ifndef <%=
|
21
|
-
#define <%=
|
21
|
+
#ifndef <%= @cname.upcase %>_H
|
22
|
+
#define <%= @cname.upcase %>_H
|
22
23
|
#include <stdlib.h>
|
23
24
|
|
24
25
|
// List of states
|
25
26
|
typedef enum {
|
26
|
-
<%
|
27
|
-
STATE_<%= s[:id].upcase %><%= i == 0 ? " = 0" : "" %>,
|
27
|
+
<% @states.each_with_index do |s, i| %>
|
28
|
+
<%= @prefix.upcase %>STATE_<%= s[:id].upcase %><%= i == 0 ? " = 0" : "" %>,
|
28
29
|
<% end %>
|
29
|
-
NUM_STATES,
|
30
|
-
NO_CHANGE
|
30
|
+
<%= @prefix.upcase %>NUM_STATES,
|
31
|
+
<%= @prefix.upcase %>NO_CHANGE
|
31
32
|
} state_t;
|
32
33
|
|
33
|
-
const char *state_names[] = {<%=
|
34
|
+
const char *state_names[] = {<%= states_list.map {|sn| '"'+sn+'"'}.join(", ") %>};
|
34
35
|
|
35
36
|
// State function and state transition prototypes
|
36
37
|
typedef state_t state_func_t(void *data);
|
37
38
|
typedef void transition_func_t(void *data);
|
38
39
|
|
39
40
|
// state functions
|
40
|
-
<%
|
41
|
+
<% @states.each do |s| %>
|
41
42
|
state_t <%= s[:function] %>(void *data);
|
42
43
|
<% end %>
|
43
44
|
|
44
45
|
// List of state functions
|
45
|
-
state_func_t *const state_table[NUM_STATES] = {
|
46
|
-
<%=
|
46
|
+
state_func_t *const <%= @prefix %>state_table[<%= @prefix.upcase %>NUM_STATES] = {
|
47
|
+
<%= state_functions_list.join(",\n ")%>
|
47
48
|
};
|
48
49
|
|
49
|
-
<% if
|
50
|
+
<% if transition_functions_list.count > 0 then %>
|
50
51
|
// transition functions
|
51
|
-
<%
|
52
|
+
<% transition_functions_list.each do |t| %>
|
52
53
|
<% next if t == "NULL" %>
|
53
54
|
void <%= t %>(void *data);
|
54
55
|
<% end %>
|
55
56
|
|
56
57
|
// Table of transition functions
|
57
|
-
transition_func_t *const transition_table[NUM_STATES][NUM_STATES] = {
|
58
|
-
<% sl =
|
59
|
-
<% fw =
|
60
|
-
<% sw =
|
58
|
+
transition_func_t *const <%= @prefix %>transition_table[<%= @prefix.upcase %>NUM_STATES][<%= @prefix.upcase %>NUM_STATES] = {
|
59
|
+
<% sl = states_list %>
|
60
|
+
<% fw = transition_functions_list.max {|a, b| a.length <=> b.length}.length %>
|
61
|
+
<% sw = states_list.max {|a, b| a.length <=> b.length}.length %>
|
61
62
|
/* <%= "states:".ljust(sw) %> <%= sl.map {|e| e.ljust(fw) }.join(", ") %> */
|
62
|
-
<%
|
63
|
+
<% transitions_map.each_with_index do |l, i| %>
|
63
64
|
/* <%= sl[i].ljust(sw) %> */ {<%= l.map {|e| e.ljust(fw)}.join(", ") %>},
|
64
65
|
<% end %>
|
65
66
|
};
|
@@ -68,14 +69,14 @@ module GV_FSM
|
|
68
69
|
<% end %>
|
69
70
|
|
70
71
|
// state manager
|
71
|
-
state_t run_state(state_t cur_state, void *data);
|
72
|
+
state_t <%= @prefix %>run_state(state_t cur_state, void *data);
|
72
73
|
|
73
74
|
#endif
|
74
75
|
EOH
|
75
76
|
|
76
77
|
CC =<<~EOC
|
77
78
|
#include <syslog.h>
|
78
|
-
#include "<%=
|
79
|
+
#include "<%= @cname %>.h"
|
79
80
|
|
80
81
|
// ____ _ _
|
81
82
|
// / ___|| |_ __ _| |_ ___
|
@@ -89,12 +90,12 @@ module GV_FSM
|
|
89
90
|
// | _| |_| | | | | (__| |_| | (_) | | | \\__ \\
|
90
91
|
// |_| \\__,_|_| |_|\\___|\\__|_|\\___/|_| |_|___/
|
91
92
|
//
|
92
|
-
<% dest =
|
93
|
-
<%
|
93
|
+
<% dest = destinations.dup %>
|
94
|
+
<% @states.each do |s| %>
|
94
95
|
<% stable = true if dest[s[:id]].include? s[:id] %>
|
95
|
-
<% dest[s[:id]].map! {|n| "STATE_"+n.upcase} %>
|
96
|
+
<% dest[s[:id]].map! {|n| (@prefix+"STATE_"+n).upcase} %>
|
96
97
|
<% if dest[s[:id]].empty? or stable then
|
97
|
-
dest[s[:id]].unshift "NO_CHANGE"
|
98
|
+
dest[s[:id]].unshift @prefix.upcase+"NO_CHANGE"
|
98
99
|
end %>
|
99
100
|
// To be executed in state <%= s[:id] %>
|
100
101
|
state_t <%= s[:function] %>(void *data) {
|
@@ -111,17 +112,17 @@ module GV_FSM
|
|
111
112
|
break;
|
112
113
|
default:
|
113
114
|
syslog(LOG_WARNING, "[FSM] Cannot pass from <%= s[:id] %> to %s, remaining in this state", state_names[next_state]);
|
114
|
-
next_state = NO_CHANGE;
|
115
|
+
next_state = <%= @prefix.upcase %>NO_CHANGE;
|
115
116
|
}
|
116
117
|
return next_state;
|
117
118
|
}
|
118
119
|
|
119
120
|
<% end %>
|
120
121
|
|
121
|
-
<% if
|
122
|
+
<% if transition_functions_list.count > 0 then %>
|
122
123
|
// _____ _ _ _
|
123
124
|
// |_ _| __ __ _ _ __ ___(_) |_(_) ___ _ __
|
124
|
-
// | || '__/ _` | '_ \\/ __| | __| |/ _ \\| '_ \\
|
125
|
+
// | || '__/ _` | '_ \\/ __| | __| |/ _ \\| '_ \\
|
125
126
|
// | || | | (_| | | | \\__ \\ | |_| | (_) | | | |
|
126
127
|
// |_||_| \\__,_|_| |_|___/_|\\__|_|\\___/|_| |_|
|
127
128
|
//
|
@@ -132,10 +133,10 @@ module GV_FSM
|
|
132
133
|
// |_| \\__,_|_| |_|\\___|\\__|_|\\___/|_| |_|___/
|
133
134
|
//
|
134
135
|
|
135
|
-
<%
|
136
|
+
<% transition_functions_list.each do |t| %>
|
136
137
|
<% next if t == "NULL" %>
|
137
138
|
// This function is called in transitions:
|
138
|
-
<%
|
139
|
+
<% transitions_paths[t].each do |e| %>
|
139
140
|
// from <%= e[:from] %> to <%= e[:to] %>
|
140
141
|
<% end %>
|
141
142
|
void <%= t %>(void *data) {
|
@@ -148,7 +149,7 @@ module GV_FSM
|
|
148
149
|
|
149
150
|
// ____ _ _
|
150
151
|
// / ___|| |_ __ _| |_ ___
|
151
|
-
// \\___ \\| __/ _` | __/ _ \\
|
152
|
+
// \\___ \\| __/ _` | __/ _ \\
|
152
153
|
// ___) | || (_| | || __/
|
153
154
|
// |____/ \\__\\__,_|\\__\\___|
|
154
155
|
//
|
@@ -159,27 +160,27 @@ module GV_FSM
|
|
159
160
|
// |_| |_| |_|\\__,_|_| |_|\\__,_|\\__, |\\___|_|
|
160
161
|
// |___/
|
161
162
|
|
162
|
-
state_t run_state(state_t cur_state, void *data) {
|
163
|
-
state_t new_state = state_table[cur_state](data);
|
164
|
-
<% if
|
165
|
-
transition_func_t *transition = transition_table[cur_state][new_state];
|
163
|
+
state_t <%= @prefix %>run_state(state_t cur_state, void *data) {
|
164
|
+
state_t new_state = <%= @prefix %>state_table[cur_state](data);
|
165
|
+
<% if transition_functions_list.count > 0 then %>
|
166
|
+
transition_func_t *transition = <%= @prefix %>transition_table[cur_state][new_state];
|
166
167
|
if (transition)
|
167
168
|
transition(data);
|
168
169
|
<% end %>
|
169
|
-
return new_state == NO_CHANGE ? cur_state : new_state;
|
170
|
+
return new_state == <%= @prefix.upcase %>NO_CHANGE ? cur_state : new_state;
|
170
171
|
};
|
171
172
|
|
172
173
|
|
173
174
|
#ifdef TEST_MAIN
|
174
175
|
#include <unistd.h>
|
175
176
|
int main() {
|
176
|
-
state_t cur_state = STATE_INIT;
|
177
|
+
state_t cur_state = <%= @prefix.upcase %>STATE_INIT;
|
177
178
|
openlog("SM", LOG_PID | LOG_PERROR, LOG_USER);
|
178
179
|
syslog(LOG_INFO, "Starting SM");
|
179
180
|
do {
|
180
181
|
cur_state = run_state(cur_state, NULL);
|
181
182
|
sleep(1);
|
182
|
-
} while (cur_state != STATE_STOP);
|
183
|
+
} while (cur_state != <%= @prefix.upcase %>STATE_STOP);
|
183
184
|
return 0;
|
184
185
|
}
|
185
186
|
#endif
|
data/lib/version.rb
CHANGED