Skip to content

Commit 23bb74a

Browse files
author
Joshua Haberman
committed
Git rid of "Anywhere" state and instead seed real states with Anywhere transitions.
This reduces the size of the table slightly, and makes the code a bit simpler. This change was suggested by Paul Williams, because the anywhere transitions and the real transitions should be mutually exclusive.
1 parent c8771ad commit 23bb74a

File tree

4 files changed

+35
-40
lines changed

4 files changed

+35
-40
lines changed

vtparse.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ static void do_state_change(vtparse_t *parser, state_change_t change, char ch)
105105
* 3. the entry action of the new state
106106
*/
107107

108-
vtparse_action_t exit_action = EXIT_ACTIONS[parser->state];
109-
vtparse_action_t entry_action = ENTRY_ACTIONS[new_state];
108+
vtparse_action_t exit_action = EXIT_ACTIONS[parser->state-1];
109+
vtparse_action_t entry_action = ENTRY_ACTIONS[new_state-1];
110110

111111
if(exit_action)
112112
do_action(parser, exit_action, 0);
@@ -131,16 +131,8 @@ void vtparse(vtparse_t *parser, unsigned char *data, int len)
131131
for(i = 0; i < len; i++)
132132
{
133133
unsigned char ch = data[i];
134-
135-
/* If a transition is defined from the "anywhere" state, always
136-
* use that. Otherwise use the transition from the current state. */
137-
138-
state_change_t change = STATE_TABLE[VTPARSE_STATE_ANYWHERE][ch];
139-
140-
if(!change)
141-
change = STATE_TABLE[parser->state][ch];
142-
143-
do_state_change(parser, change, data[i]);
134+
state_change_t change = STATE_TABLE[parser->state-1][ch];
135+
do_state_change(parser, change, ch);
144136
}
145137
}
146138

vtparse_check_tables.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,9 @@
88

99
table = {}
1010

11-
anywhere_array = expand_ranges($states[:ANYWHERE])
12-
1311
$state_tables.each { |state, table|
14-
next if state == :ANYWHERE
15-
1612
table.each_with_index { |val, i|
17-
if not (val or $state_tables[:ANYWHERE][i])
13+
if not val
1814
raise "No transition defined from state #{state}, char 0x#{i.to_s(16)}!"
1915
end
2016
}

vtparse_gen_c_tables.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def pad(len)
1010
File.open("vtparse_table.h", "w") { |f|
1111
f.puts "typedef enum {"
1212
$states_in_order.each_with_index { |state, i|
13-
f.puts " VTPARSE_STATE_#{state.to_s.upcase} = #{i},"
13+
f.puts " VTPARSE_STATE_#{state.to_s.upcase} = #{i+1},"
1414
}
1515
f.puts "} vtparse_state_t;"
1616
f.puts
@@ -25,7 +25,7 @@ def pad(len)
2525
f.puts "extern vtparse_action_t ENTRY_ACTIONS[#{$states_in_order.length}];"
2626
f.puts "extern vtparse_action_t EXIT_ACTIONS[#{$states_in_order.length}];"
2727
f.puts "extern char *ACTION_NAMES[#{$actions_in_order.length+1}];"
28-
f.puts "extern char *STATE_NAMES[#{$states_in_order.length}];"
28+
f.puts "extern char *STATE_NAMES[#{$states_in_order.length+1}];"
2929
f.puts
3030
}
3131

@@ -43,14 +43,15 @@ def pad(len)
4343
f.puts "};"
4444
f.puts
4545
f.puts "char *STATE_NAMES[] = {"
46+
f.puts " \"<no state>\","
4647
$states_in_order.each { |state|
4748
f.puts " \"#{state.to_s}\","
4849
}
4950
f.puts "};"
5051
f.puts
5152
f.puts "state_change_t STATE_TABLE[#{$states_in_order.length}][256] = {"
52-
$states_in_order.each { |state|
53-
f.puts " { /* VTPARSE_STATE_#{state.to_s.upcase} */"
53+
$states_in_order.each_with_index { |state, i|
54+
f.puts " { /* VTPARSE_STATE_#{state.to_s.upcase} = #{i} */"
5455
$state_tables[state].each_with_index { |state_change, i|
5556
if not state_change
5657
f.puts " 0,"

vtparse_tables.rb

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ def transition_to(state)
1212

1313
$states = {}
1414

15-
$states[:ANYWHERE] = {
15+
$anywhere_transitions = {
1616
0x18 => [:execute, transition_to(:GROUND)],
1717
0x1a => [:execute, transition_to(:GROUND)],
1818
0x80..0x8f => [:execute, transition_to(:GROUND)],
1919
0x91..0x97 => [:execute, transition_to(:GROUND)],
2020
0x99 => [:execute, transition_to(:GROUND)],
2121
0x9a => [:execute, transition_to(:GROUND)],
22-
0x9c => [:execute, transition_to(:GROUND)],
22+
0x9c => transition_to(:GROUND),
2323
0x1b => transition_to(:ESCAPE),
2424
0x98 => transition_to(:SOS_PM_APC_STRING),
2525
0x9e => transition_to(:SOS_PM_APC_STRING),
@@ -34,9 +34,6 @@ def transition_to(state)
3434
0x19 => :execute,
3535
0x1c..0x1f => :execute,
3636
0x20..0x7f => :print,
37-
0x80..0x8f => :execute,
38-
0x91..0x9a => :execute,
39-
0x9c => :execute
4037
}
4138

4239
$states[:ESCAPE] = {
@@ -144,7 +141,6 @@ def transition_to(state)
144141
0x19 => :ignore,
145142
0x1c..0x1f => :ignore,
146143
0x20..0x7f => :ignore,
147-
0x9c => transition_to(:GROUND)
148144
}
149145

150146
$states[:DCS_PARAM] = {
@@ -167,7 +163,6 @@ def transition_to(state)
167163
0x1c..0x1f => :put,
168164
0x20..0x7e => :put,
169165
0x7f => :ignore,
170-
0x9c => transition_to(:GROUND),
171166
:on_exit => :unhook
172167
}
173168

@@ -176,7 +171,6 @@ def transition_to(state)
176171
0x19 => :ignore,
177172
0x1c..0x1f => :ignore,
178173
0x20..0x7f => :ignore,
179-
0x9c => transition_to(:GROUND)
180174
}
181175

182176
$states[:OSC_STRING] = {
@@ -185,24 +179,16 @@ def transition_to(state)
185179
0x19 => :ignore,
186180
0x1c..0x1f => :ignore,
187181
0x20..0x7f => :osc_put,
188-
0x9c => transition_to(:GROUND),
189182
:on_exit => :osc_end
190183
}
191184

192-
$states.each { |state, transitions|
193-
transitions.each { |keys, actions|
194-
if not actions.kind_of?(Array)
195-
$states[state][keys] = [actions]
196-
end
197-
}
198-
}
199-
200185

201186
# get the list of actions implicit in the tables
202187

203188
action_names = {}
204189
$states.each { |state, transitions|
205190
transitions.each { |keys, actions|
191+
actions = [actions] if !actions.kind_of?(Array)
206192
actions.each { |action|
207193
if action.kind_of?(Symbol)
208194
action_names[action] = 1
@@ -213,8 +199,10 @@ def transition_to(state)
213199

214200
# establish an ordering to the states and actions
215201

216-
$actions_in_order = action_names.keys.sort { |a1, a2| a1.to_s <=> a2.to_s } + [:error]
217-
$states_in_order = $states.keys.sort { |s1, s2| s1.to_s <=> s2.to_s }
202+
$actions_in_order = action_names.keys.sort { |a1, a2| a1.to_s <=> a2.to_s } + [:error]
203+
$states_in_order = $states.keys.sort { |s1, s2| s1.to_s <=> s2.to_s }
204+
205+
218206

219207
#
220208
# Expand the above range-based data structures (which are convenient
@@ -242,4 +230,22 @@ def expand_ranges(hash_with_ranges_as_keys)
242230
$state_tables[state] = expand_ranges(transitions)
243231
}
244232

233+
# seed all the states with the anywhere transitions
234+
$anywhere_transitions = expand_ranges($anywhere_transitions)
235+
236+
$state_tables.each { |state, transitions|
237+
$anywhere_transitions.each_with_index { |transition, i|
238+
next if transition.nil?
239+
if transitions[i]
240+
raise "State #{state} already had a transition defined for 0x#{i.to_s(16)}, but " + \
241+
"that transition is also an anywhere transition!"
242+
end
243+
transitions[i] = transition
244+
}
245+
}
246+
247+
# for consistency, make all transitions *lists* of actions
248+
$state_tables.each { |state, transitions|
249+
transitions.map! { |t| t.kind_of?(Array) ? t : [t] }
250+
}
245251

0 commit comments

Comments
 (0)