gv_fsm 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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