Boost logo

Boost :

From: Phil Endecott (spam_from_boost_dev_at_[hidden])
Date: 2008-08-18 17:25:10


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.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk