
Andrey Semashev wrote:
Phil Endecott wrote:
Dear All,
Here's another FSM example which I hope is a bit less trivial than the last one. It's for the escape sequence handling in a terminal emulator.
My view is that the ad-hoc version of the code is sufficiently readable and efficient for my needs, and that the Boost.FSM version does not improve on it.
Actually, the ad-hoc code is a good example for what is known as spagetti-style
Can you elaborate on why you say that? To me, "spagetti" code is code where the flow-of-control goes all over the place in a complex and not easily discernible pattern. In my "ad-hoc" implementation, the main flow-of-control is contained in a single function which all fits on the screen at the same time and has if and switch statements nested at most 4 deep. If it's the depth of nesting that you dislike it could easily be flattened like this: void process_control_char(char c) { switch (c) { .... case 13: carriage_return(); break; .... case 26: // This code abandons any escape sequence that is in progress state = normal; break; case 27: // Escape state = esc; break; .... } } void process_char_normal_state(char c) { write_normal_char(c); } void process_char_esc_state(char c) { switch (c) { .... case 'M': cursor_line_up(); state=normal; break; .... case '[': state=csi; nparams=0; break; default: state=normal; break; } } void process_char_csi_state(char c) { // split this up some more if you prefer. if (isdigit(c)) { if (nparams==0) { nparams=1; params[0]=0; } params[nparams-1] = params[nparams1]*10 + (c-'0'); } else if (c==';') { if (nparams>=MAX_PARAMS) { return; } nparams++; params[nparams-1] = 0; } else { switch (c) { .... case 'A': csi_CUU(); break; .... } state = normal; } } void process_char(char c) { // Control chars like tab, newline etc. work even inside // escape sequences: if (c <= 31) { process_control_char(c); } else { switch (state) { case normal: process_char_normal_state(c); break; case esc: process_char_esc_state(c); break; case csi: process_char_csi_state(c); break; } } }
Below is an improved version of the terminal, with corrected mistakes and categorized events.
A couple of questions: - Does it correctly handle digits in normal mode? - How can I access the screen and cursor position from outside? (Or, if I can't access the content of the states from outside, how can I access an externally-stored screen and cursor from inside the states?) Phil.