The improved Calculator model with QMsm state machine implementation strategy, no "me->" pointer, and Sub-Machines. Calculator state machine the single inst of the Calc class constructor : QMsm(&initial) // guard function to evaluate the current expression // taking into account the precedence of operands. // return: true if evaluation successfull // false when error encountered double result; if ((oper == KEY_NULL) || (oper == KEY_PLUS) || (oper == KEY_MINUS)) { switch (m_oper2) { case KEY_MULT: { m_op2 *= op; break; } case KEY_DIVIDE: { if ((-1e-30 < op) && (op < 1e-30)) { BSP_display_error(" Error 0 "); // divide by zero return false; } m_op2 /= op; break; } default: { /* no op2 yet */ m_op2 = op; m_oper2 = oper; break; } } switch (m_oper1) { case KEY_PLUS: { m_op1 += m_op2; break; } case KEY_MINUS: { m_op1 -= m_op2; break; } case KEY_MULT: { m_op1 *= m_op2; break; } case KEY_DIVIDE: { if ((-1e-30 < m_op2) && (m_op2 < 1e-30)) { BSP_display_error(" Error 0 "); // divide by zero return false; } m_op1 /= m_op2; break; } default: { Q_ERROR(); break; } } m_oper1 = oper; m_oper2 = KEY_NULL; result = m_op1; } else { // (oper == KEY_MULT) || (oper == KEY_DIV) switch (m_oper2) { case KEY_MULT: { m_op2 *= op; break; } case KEY_DIVIDE: { if ((-1e-30 < op) && (op < 1e-30)) { BSP_display_error(" Error 0 "); // divide by zero return false; } m_op2 /= op; break; } default: { // oper2 not provided yet m_op2 = op; break; } } m_oper2 = oper; result = m_op2; } if ((result < -99999999.0) || (99999999.0 < result)) { BSP_display_error(" Error 1 "); // out of range return false; } if ((-0.0000001 < result) && (result < 0.0000001)) { result = 0.0; } BSP_display(result); return true; BSP_clear(); (void)e; // unused parameter BSP_message("on-ENTRY;"); BSP_message("on-EXIT;"); BSP_message("on-INIT;"); BSP_clear(); BSP_message("ready-ENTRY;"); m_oper2 = KEY_NULL; BSP_message("ready-EXIT;"); BSP_message("ready-INIT;"); BSP_clear(); BSP_clear(); BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); BSP_clear(); BSP_insert((int)'0'); BSP_insert((int)'.'); m_op1 = BSP_get_value(); m_oper1 = Q_EVT_CAST(CalcEvt)->key_code; BSP_message("result-ENTRY;"); BSP_message("result-EXIT;"); BSP_message("begin-ENTRY;"); BSP_message("begin-EXIT;"); Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS else BSP_message("operand1:XP-CE;"); m_op1 = BSP_get_value(); m_oper1 = Q_EVT_CAST(CalcEvt)->key_code; BSP_message("opEntered-ENTRY;"); BSP_message("opEntered-EXIT;"); BSP_clear(); BSP_clear(); BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); BSP_clear(); BSP_insert((int)'0'); BSP_insert((int)'.'); Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS else BSP_message("operand2:XP-CE;"); else eval(BSP_get_value(), Q_EVT_CAST(CalcEvt)->key_code) else eval(BSP_get_value(), KEY_NULL) BSP_message("error-ENTRY;"); BSP_message("error-EXIT;"); BSP_message("final-ENTRY;"); BSP_exit(); BSP_message("operand-ENTRY;"); BSP_message("operand-EXIT;"); BSP_message("operand::EP-zero;"); BSP_message("operand::EP-intgr;"); BSP_message("operand::EP-frac;"); BSP_message("operand::EP-neg;"); BSP_message("operand-INIT;"); BSP_message("operand::CE;"); BSP_clear(); BSP_message("operand::zero-ENTRY;"); BSP_message("operand::zero-EXIT;"); ; BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); BSP_insert((int)'0'); BSP_insert((int)'.'); BSP_message("operand::intgr-ENTRY;"); BSP_message("operand::intgr-EXIT;"); BSP_insert((int)'.'); BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); BSP_message("operand::frac-ENTRY;"); BSP_message("operand::frac-EXIT;"); ; BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); BSP_message("operand::neg-ENTRY;"); BSP_negate(); BSP_message("operand::neg-EXIT;"); BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); else Q_EVT_CAST(CalcEvt)->key_code == KEY_MINUS ; opaque pointer to the Calc state machine = &Calc::inst; #ifndef CALC1_SUB_HPP #define CALC1_SUB_HPP enum CalcSignals { C_SIG = QP::Q_USER_SIG, CE_SIG, DIGIT_0_SIG, DIGIT_1_9_SIG, POINT_SIG, OPER_SIG, EQUALS_SIG, OFF_SIG }; $declare${Events::CalcEvt} $declare${SMs::the_calc} #endif // CALC1_SUB_HPP #include "qpcpp.hpp" // QP/C++ API #include "bsp.hpp" // board support package #include "calc1_sub.hpp" // application Q_DEFINE_THIS_FILE #define KEY_NULL '\0' #define KEY_PLUS '+' #define KEY_MINUS '-' #define KEY_MULT '*' #define KEY_DIVIDE '/' $declare${SMs::Calc} $define${SMs::the_calc} $define${SMs::Calc}