gv_fsm 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2896e7f9617c0ed1a9917e78cd947d1da5ceef2d8554727a4db268a7f70e6229
4
- data.tar.gz: 63d897002c102d5291ecbfd7b4c854f8c9fc029e01155ba573d13e2043621afb
3
+ metadata.gz: 3579818099a2f3e8d172c9534af08877f3e4b27f4fc09f9c9aa77c6275256ce3
4
+ data.tar.gz: 5b4acdd1da41b63fbac514f2a481766c5b5c08ba34881ef708d11871910e8d0d
5
5
  SHA512:
6
- metadata.gz: ae5be7ee072d06983c139320227c6b234d703b2556071df085cb3f6a3365d3d1c6a8cf38f9f6daac0b866ed5b77c4726933eee69eda7aa8d9ffe17b9f2c2ca0b
7
- data.tar.gz: bd1129ccf730d930b42a8ba53f83eb2adeb6d66368ebd9aab6466c69e2b951d6b461d0e04579254153d2c753c390f16f023806040615e6ac52d53f3b2f60c71a
6
+ metadata.gz: 5f481dacfc667927287eecc1b5f901fd915a593ab533b6de35f573e0cb1b66219c5cd37e24f9c54095e1049f8a7f3f67094530338a9c653cbb72585d1ccbcdf3
7
+ data.tar.gz: 4b835c1bc4f03a6d80e37f64f219b0801756ffaeeedbd7da20f53ffbc428b48efd92ac075c189b5379d30ef125ebaf4417e259b0729d1c9e9ac0a94db08b3e14
data/bin/gv_fsm CHANGED
@@ -6,7 +6,7 @@ require 'optparse'
6
6
  sm = GV_FSM::FSM.new
7
7
 
8
8
  options = {header: true, source: true}
9
- OptionParser.new do |parser|
9
+ op = OptionParser.new do |parser|
10
10
  parser.banner =<<~EOB
11
11
  Graphviz to Finite State Machine generator
12
12
  Version: #{GV_FSM::VERSION}
@@ -40,21 +40,48 @@ OptionParser.new do |parser|
40
40
  sm.prefix = p
41
41
  end
42
42
 
43
- end.parse!
43
+ parser.on("-i", "--ino", "Generate a single .ino file (for Arduino)") do
44
+ sm.ino = true
45
+ end
44
46
 
45
- raise ArgumentError, "I need the path to a Graphviz file!" unless ARGV[0]
46
- raise ArgumentError, "#{ARGV[0]} does not look like a Graphviz file!" unless File.extname(ARGV[0]) == ".dot"
47
+ parser.on("-l", "--no-syslog", "Omit syslog calls in stub functions") do
48
+ sm.syslog = false
49
+ end
47
50
 
48
- sm.parse(ARGV[0])
51
+ parser.on("-h", "--help", "Prints this help") do
52
+ puts parser
53
+ exit
54
+ end
49
55
 
50
- puts "Parsed #{sm.dotfile}.\nGenerating C stub for states: #{sm.states_list.join(", ")}."
51
- if options[:header] then
52
- sm.generate_h
53
- puts "Generated header #{sm.cname}.h"
54
56
  end
55
- if options[:source] then
56
- sm.generate_c
57
- puts "Generated source #{sm.cname}.c"
57
+
58
+ op.parse!
59
+
60
+ unless ARGV[0]
61
+ STDERR.puts "ERROR: I need the path to a Graphviz file!\n\n"
62
+ STDERR.puts op
63
+ exit
64
+ end
65
+ unless File.extname(ARGV[0]) == ".dot"
66
+ STDERR.puts "ERROR: #{ARGV[0]} does not look like a Graphviz file!\n\n"
67
+ STDERR.puts op
68
+ exit
58
69
  end
59
70
 
71
+ sm.parse(ARGV[0])
72
+
73
+ puts "Parsed #{sm.dotfile}.\nGenerating C stub for states: #{sm.states_list.join(", ")}."
74
+ if sm.ino then
75
+ sm.generate_ino
76
+ puts "Generated .ino file #{sm.cname}.ino"
77
+ else
78
+ if options[:header] then
79
+ sm.generate_h
80
+ puts "Generated header #{sm.cname}.h"
81
+ end
82
+ if options[:source] then
83
+ sm.generate_c
84
+ puts "Generated source #{sm.cname}.c"
85
+ end
86
+ end
60
87
 
@@ -9,11 +9,13 @@ require File.expand_path("../version.rb", __FILE__)
9
9
  module GV_FSM
10
10
  class FSM
11
11
  attr_reader :states, :transitions, :dotfile, :prefix
12
- attr_accessor :project_name, :description, :cname
12
+ attr_accessor :project_name, :description, :cname, :syslog, :ino
13
13
  include GV_FSM::Templates
14
14
 
15
15
  def initialize(filename = nil)
16
16
  @prefix = ""
17
+ @syslog = true
18
+ @ino = false
17
19
  parse(filename) if filename
18
20
  end
19
21
 
@@ -36,7 +38,10 @@ module GV_FSM
36
38
  g.each_edge do |e|
37
39
  from = e.node_one
38
40
  to = e.node_two
39
- next unless e[:label]
41
+ unless e[:label] then
42
+ @transitions << {from: from, to: to, function: nil}
43
+ next
44
+ end
40
45
  case e[:label].source
41
46
  when ""
42
47
  label = nil
@@ -61,7 +66,7 @@ module GV_FSM
61
66
  def transition_functions_list
62
67
  lst = []
63
68
  @transitions.each do |t|
64
- if !lst.include? t[:function] then
69
+ if t[:function] and !lst.include? t[:function] then
65
70
  lst << (t[:function] or "NULL")
66
71
  end
67
72
  end
@@ -110,6 +115,15 @@ module GV_FSM
110
115
  f.puts ERB.new(HH, 0, "<>").result(binding)
111
116
  end
112
117
  end
118
+
119
+ def generate_ino(filename=@cname)
120
+ @syslog = false
121
+ File.open("#{filename}.ino", "w") do |f|
122
+ f.puts ERB.new(HEADER, 0, "<>").result(binding)
123
+ f.puts ERB.new(HH, 0, "<>").result(binding)
124
+ f.puts ERB.new(CC, 0, "<>").result(binding)
125
+ end
126
+ end
113
127
  end
114
128
 
115
129
  end
@@ -13,7 +13,6 @@ module GV_FSM
13
13
  Generated from: <%= @dotfile %>
14
14
  The finite state machine has:
15
15
  <%= @states.count %> states
16
- <%= @transitions.count %> transitions
17
16
  <%= transition_functions_list.select {|e| e != 'NULL'}.count %> transition functions
18
17
  <% if @prefix != '' %>
19
18
  Functions and types have been generated with prefix "<%= @prefix %>"
@@ -23,16 +22,20 @@ module GV_FSM
23
22
  EOHEADER
24
23
 
25
24
  HH =<<~EOH
25
+ <% if !@ino then %>
26
26
  #ifndef <%= @cname.upcase %>_H
27
27
  #define <%= @cname.upcase %>_H
28
28
  #include <stdlib.h>
29
+ <% end %>
29
30
 
30
31
  // State data object
31
32
  // By default set to void; override this typedef or load the proper
32
33
  // header if you need
33
34
  typedef void <%= @prefix %>state_data_t;
34
-
35
+ <% if !@ino then %>
36
+
35
37
  // NOTHING SHALL BE CHANGED AFTER THIS LINE!
38
+ <% end %>
36
39
 
37
40
  // List of states
38
41
  typedef enum {
@@ -43,24 +46,41 @@ module GV_FSM
43
46
  <%= @prefix.upcase %>NO_CHANGE
44
47
  } <%= @prefix %>state_t;
45
48
 
49
+ // State human-readable names
46
50
  const char *state_names[] = {<%= states_list.map {|sn| '"'+sn+'"'}.join(", ") %>};
47
-
51
+
52
+ <% if transition_functions_list.count > 0 then %>
48
53
  // State function and state transition prototypes
49
54
  typedef <%= @prefix %>state_t state_func_t(<%= @prefix %>state_data_t *data);
50
55
  typedef void transition_func_t(<%= @prefix %>state_data_t *data);
56
+ <% else %>
57
+ // State function prototype
58
+ typedef <%= @prefix %>state_t state_func_t(<%= @prefix %>state_data_t *data);
59
+ <%end %>
51
60
 
52
61
  // State functions
62
+ <% dest = destinations.dup %>
53
63
  <% @states.each do |s| %>
64
+ <% stable = true if dest[s[:id]].include? s[:id] %>
65
+ <% dest[s[:id]].map! {|n| (@prefix+"STATE_"+n).upcase} %>
66
+ <% if dest[s[:id]].empty? or stable then
67
+ dest[s[:id]].unshift @prefix.upcase+"NO_CHANGE"
68
+ end %>
69
+ // Function to be executed in state <%= s[:id] %>
70
+ // valid return states: <%= dest[s[:id]].join(", ") %>
54
71
  <%= @prefix %>state_t <%= s[:function] %>(<%= @prefix %>state_data_t *data);
55
72
  <% end %>
56
73
 
74
+
57
75
  // List of state functions
76
+ <% fw = state_functions_list.max {|a, b| a.length <=> b.length}.length %>
58
77
  state_func_t *const <%= @prefix %>state_table[<%= @prefix.upcase %>NUM_STATES] = {
59
78
  <% @states.each do |s| %>
60
- <%= s[:function] %>, // in state <%= s[:id] %>
79
+ <%= (s[:function] + ',').ljust(fw+1) %> // in state <%= s[:id] %>
61
80
  <% end %>
62
81
  };
63
82
 
83
+
64
84
  <% if transition_functions_list.count > 0 then %>
65
85
  // Transition functions
66
86
  <% transition_functions_list.each do |t| %>
@@ -85,12 +105,18 @@ module GV_FSM
85
105
  // state manager
86
106
  <%= @prefix %>state_t <%= @prefix %>run_state(<%= @prefix %>state_t cur_state, void *data);
87
107
 
108
+ <% if !@ino then %>
88
109
  #endif
110
+ <% end %>
89
111
  EOH
90
112
 
91
113
  CC =<<~EOC
114
+ <% if !@ino then %>
115
+ <% if @syslog then %>
92
116
  #include <syslog.h>
117
+ <% end %>
93
118
  #include "<%= @cname %>.h"
119
+ <% end %>
94
120
 
95
121
  <% placeholder = "Your Code Here" %>
96
122
  // SEARCH FOR <%= placeholder %> FOR CODE INSERTION POINTS!
@@ -115,20 +141,24 @@ module GV_FSM
115
141
  dest[s[:id]].unshift @prefix.upcase+"NO_CHANGE"
116
142
  end %>
117
143
  // Function to be executed in state <%= s[:id] %>
144
+ // valid return states: <%= dest[s[:id]].join(", ") %>
118
145
  <%= @prefix %>state_t <%= s[:function] %>(<%= @prefix %>state_data_t *data) {
119
146
  <%= @prefix %>state_t next_state = <%= dest[s[:id]].first %>;
120
147
 
148
+ <% if @syslog then %>
121
149
  syslog(LOG_INFO, "[FSM] In state <%= s[:id] %>");
150
+ <% end %>
122
151
  /* <%= placeholder %> */
123
152
 
124
- // valid return states: <%= dest[s[:id]].join(", ") %>
125
153
  switch (next_state) {
126
154
  <% dest[s[:id]].each do |str| %>
127
155
  case <%= str %>:
128
156
  <% end %>
129
157
  break;
130
158
  default:
159
+ <% if @syslog then %>
131
160
  syslog(LOG_WARNING, "[FSM] Cannot pass from <%= s[:id] %> to %s, remaining in this state", state_names[next_state]);
161
+ <% end %>
132
162
  next_state = <%= @prefix.upcase %>NO_CHANGE;
133
163
  }
134
164
  return next_state;
@@ -158,7 +188,9 @@ module GV_FSM
158
188
  // <%= i+1 %>. from <%= e[:from] %> to <%= e[:to] %>
159
189
  <% end %>
160
190
  void <%= t %>(<%= @prefix %>state_data_t *data) {
191
+ <% if @syslog then %>
161
192
  syslog(LOG_INFO, "[FSM] State transition <%= t %>");
193
+ <% end %>
162
194
  /* <%= placeholder %> */
163
195
  }
164
196
 
@@ -188,20 +220,29 @@ module GV_FSM
188
220
  return new_state == <%= @prefix.upcase %>NO_CHANGE ? cur_state : new_state;
189
221
  };
190
222
 
191
-
223
+ <% if @ino then %>
224
+ /* Example usage:
225
+ <% else %>
192
226
  #ifdef TEST_MAIN
193
227
  #include <unistd.h>
194
228
  int main() {
229
+ <% end %>
195
230
  <%= @prefix %>state_t cur_state = <%= @prefix.upcase %>STATE_INIT;
231
+ <% if @syslog then %>
196
232
  openlog("SM", LOG_PID | LOG_PERROR, LOG_USER);
197
233
  syslog(LOG_INFO, "Starting SM");
234
+ <% end %>
198
235
  do {
199
236
  cur_state = <%= @prefix %>run_state(cur_state, NULL);
200
237
  sleep(1);
201
238
  } while (cur_state != <%= @prefix.upcase %>STATE_STOP);
239
+ <% if !@ino then %>
202
240
  return 0;
203
241
  }
204
242
  #endif
243
+ <% else %>
244
+ */
245
+ <% end %>
205
246
  EOC
206
247
  end
207
248
  end
@@ -1,3 +1,3 @@
1
1
  module GV_FSM
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gv_fsm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paolo Bosetti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-08 00:00:00.000000000 Z
11
+ date: 2020-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-graphviz