gv_fsm 0.2.1 → 0.2.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 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