3 attr_accessor :to_state
4 def initialize(to_state)
9 def transition_to(state)
10 StateTransition.new(state)
15 $anywhere_transitions = {
16 0x18 => [:execute, transition_to(:GROUND)],
17 0x1a => [:execute, transition_to(:GROUND)],
18 0x80..0x8f => [:execute, transition_to(:GROUND)],
19 0x91..0x97 => [:execute, transition_to(:GROUND)],
20 0x99 => [:execute, transition_to(:GROUND)],
21 0x9a => [:execute, transition_to(:GROUND)],
22 0x9c => transition_to(:GROUND),
23 0x1b => transition_to(:ESCAPE),
24 0x98 => transition_to(:SOS_PM_APC_STRING),
25 0x9e => transition_to(:SOS_PM_APC_STRING),
26 0x9f => transition_to(:SOS_PM_APC_STRING),
27 0x90 => transition_to(:DCS_ENTRY),
28 0x9d => transition_to(:OSC_STRING),
29 0x9b => transition_to(:CSI_ENTRY),
33 0x00..0x17 => :execute,
35 0x1c..0x1f => :execute,
41 0x00..0x17 => :execute,
43 0x1c..0x1f => :execute,
45 0x20..0x2f => [:collect, transition_to(:ESCAPE_INTERMEDIATE)],
46 0x30..0x4f => [:esc_dispatch, transition_to(:GROUND)],
47 0x51..0x57 => [:esc_dispatch, transition_to(:GROUND)],
48 0x59 => [:esc_dispatch, transition_to(:GROUND)],
49 0x5a => [:esc_dispatch, transition_to(:GROUND)],
50 0x5c => [:esc_dispatch, transition_to(:GROUND)],
51 0x60..0x7e => [:esc_dispatch, transition_to(:GROUND)],
52 0x5b => transition_to(:CSI_ENTRY),
53 0x5d => transition_to(:OSC_STRING),
54 0x50 => transition_to(:DCS_ENTRY),
55 0x58 => transition_to(:SOS_PM_APC_STRING),
56 0x5e => transition_to(:SOS_PM_APC_STRING),
57 0x5f => transition_to(:SOS_PM_APC_STRING),
60 $states[:ESCAPE_INTERMEDIATE] = {
61 0x00..0x17 => :execute,
63 0x1c..0x1f => :execute,
64 0x20..0x2f => :collect,
66 0x30..0x7e => [:esc_dispatch, transition_to(:GROUND)]
69 $states[:CSI_ENTRY] = {
71 0x00..0x17 => :execute,
73 0x1c..0x1f => :execute,
75 0x20..0x2f => [:collect, transition_to(:CSI_INTERMEDIATE)],
76 0x3a => transition_to(:CSI_IGNORE),
77 0x30..0x39 => [:param, transition_to(:CSI_PARAM)],
78 0x3b => [:param, transition_to(:CSI_PARAM)],
79 0x3c..0x3f => [:collect, transition_to(:CSI_PARAM)],
80 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)]
83 $states[:CSI_IGNORE] = {
84 0x00..0x17 => :execute,
86 0x1c..0x1f => :execute,
87 0x20..0x3f => :ignore,
89 0x40..0x7e => transition_to(:GROUND),
92 $states[:CSI_PARAM] = {
93 0x00..0x17 => :execute,
95 0x1c..0x1f => :execute,
99 0x3a => transition_to(:CSI_IGNORE),
100 0x3c..0x3f => transition_to(:CSI_IGNORE),
101 0x20..0x2f => [:collect, transition_to(:CSI_INTERMEDIATE)],
102 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)]
105 $states[:CSI_INTERMEDIATE] = {
106 0x00..0x17 => :execute,
108 0x1c..0x1f => :execute,
109 0x20..0x2f => :collect,
111 0x30..0x3f => transition_to(:CSI_IGNORE),
112 0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)],
115 $states[:DCS_ENTRY] = {
117 0x00..0x17 => :ignore,
119 0x1c..0x1f => :ignore,
121 0x3a => transition_to(:DCS_IGNORE),
122 0x20..0x2f => [:collect, transition_to(:DCS_INTERMEDIATE)],
123 0x30..0x39 => [:param, transition_to(:DCS_PARAM)],
124 0x3b => [:param, transition_to(:DCS_PARAM)],
125 0x3c..0x3f => [:collect, transition_to(:DCS_PARAM)],
126 0x40..0x7e => [transition_to(:DCS_PASSTHROUGH)]
129 $states[:DCS_INTERMEDIATE] = {
130 0x00..0x17 => :ignore,
132 0x1c..0x1f => :ignore,
133 0x20..0x2f => :collect,
135 0x30..0x3f => transition_to(:DCS_IGNORE),
136 0x40..0x7e => transition_to(:DCS_PASSTHROUGH)
139 $states[:DCS_IGNORE] = {
140 0x00..0x17 => :ignore,
142 0x1c..0x1f => :ignore,
143 0x20..0x7f => :ignore,
146 $states[:DCS_PARAM] = {
147 0x00..0x17 => :ignore,
149 0x1c..0x1f => :ignore,
150 0x30..0x39 => :param,
153 0x3a => transition_to(:DCS_IGNORE),
154 0x3c..0x3f => transition_to(:DCS_IGNORE),
155 0x20..0x2f => [:collect, transition_to(:DCS_INTERMEDIATE)],
156 0x40..0x7e => transition_to(:DCS_PASSTHROUGH)
159 $states[:DCS_PASSTHROUGH] = {
169 $states[:SOS_PM_APC_STRING] = {
170 0x00..0x17 => :ignore,
172 0x1c..0x1f => :ignore,
173 0x20..0x7f => :ignore,
176 $states[:OSC_STRING] = {
177 :on_entry => :osc_start,
178 0x00..0x17 => :ignore,
180 0x1c..0x1f => :ignore,
181 0x20..0x7f => :osc_put,
186 # get the list of actions implicit in the tables
189 $states.each { |state, transitions|
190 transitions.each { |keys, actions|
191 actions = [actions] if !actions.kind_of?(Array)
192 actions.each { |action|
193 if action.kind_of?(Symbol)
194 action_names[action] = 1
200 # establish an ordering to the states and actions
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 }
208 # Expand the above range-based data structures (which are convenient
209 # to write) into fully expanded tables (which are easier to use).
214 def expand_ranges(hash_with_ranges_as_keys)
216 hash_with_ranges_as_keys.each { |range, val|
217 if range.kind_of?(Range)
221 elsif range.kind_of?(Fixnum)
229 $states.each { |state, transitions|
230 $state_tables[state] = expand_ranges(transitions)
233 # seed all the states with the anywhere transitions
234 $anywhere_transitions = expand_ranges($anywhere_transitions)
236 $state_tables.each { |state, transitions|
237 $anywhere_transitions.each_with_index { |transition, i|
238 next if transition.nil?
240 raise "State #{state} already had a transition defined for 0x#{i.to_s(16)}, but " + \
241 "that transition is also an anywhere transition!"
243 transitions[i] = transition
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] }