Main Page | Modules | Class Hierarchy | Class List | File List | Class Members

calc.cpp

00001 #include "calc.h" 00002 00003 #include <stdio.h> 00004 #include <stdarg.h> 00005 #include <time.h> 00006 #include <sys/time.h> 00007 00008 00009 static void fsm_debug( char* format, ... ) 00010 { 00011 struct timeval tval; 00012 struct tm t; 00013 gettimeofday(&tval,NULL); 00014 localtime_r(&tval.tv_sec, &t); 00015 00016 printf("%02d:%02d:%02d.%lu ", 00017 t.tm_hour, t.tm_min, t.tm_sec, (unsigned long)tval.tv_usec); 00018 00019 va_list ap; 00020 va_start( ap, format ); 00021 vprintf( format, ap ); 00022 va_end( ap ); 00023 fflush( stdout ); 00024 } 00025 00026 00027 void CalculatorFSM::__processEvent( Event e ) 00028 { 00029 States yOld = __Y; 00030 bool pass = false; 00031 fsm_debug( "CalculatorFSM:%#x:event:%s:begin\n", (int)this, eventName(e) ); 00032 switch( __Y ) { //transitions 00033 case Idle: 00034 if( e == Number ) { 00035 fsm_debug( "CalculatorFSM:%#x:state:Idle:leave:begin\n", (int)this ); 00036 //outcome actions 00037 fsm_debug( "CalculatorFSM:%#x:state:Idle:leave:end\n", (int)this ); 00038 fsm_debug( "CalculatorFSM:%#x:transition:0:begin\n", (int)this ); 00039 fsm_debug( "CalculatorFSM:%#x:output:addNumber:begin\n", (int)this ); 00040 addNumber(); 00041 fsm_debug( "CalculatorFSM:%#x:output:addNumber:end\n", (int)this ); 00042 fsm_debug( "CalculatorFSM:%#x:transition:0:end\n", (int)this ); 00043 __Y = EnteringFirstOperand; 00044 pass = true; 00045 } 00046 break; 00047 case EnteringFirstOperand: 00048 if( e == Number ) { 00049 fsm_debug( "CalculatorFSM:%#x:transition:0:begin\n", (int)this ); 00050 fsm_debug( "CalculatorFSM:%#x:output:addNumber:begin\n", (int)this ); 00051 addNumber(); 00052 fsm_debug( "CalculatorFSM:%#x:output:addNumber:end\n", (int)this ); 00053 fsm_debug( "CalculatorFSM:%#x:transition:0:end\n", (int)this ); 00054 pass = false; 00055 } 00056 else if( e == BinaryOp ) { 00057 fsm_debug( "CalculatorFSM:%#x:state:EnteringFirstOperand:leave:begin\n", (int)this ); 00058 //outcome actions 00059 fsm_debug( "CalculatorFSM:%#x:state:EnteringFirstOperand:leave:end\n", (int)this ); 00060 fsm_debug( "CalculatorFSM:%#x:transition:1:begin\n", (int)this ); 00061 fsm_debug( "CalculatorFSM:%#x:output:saveNumber:begin\n", (int)this ); 00062 saveNumber(); 00063 fsm_debug( "CalculatorFSM:%#x:output:saveNumber:end\n", (int)this ); 00064 fsm_debug( "CalculatorFSM:%#x:output:saveOp:begin\n", (int)this ); 00065 saveOp(); 00066 fsm_debug( "CalculatorFSM:%#x:output:saveOp:end\n", (int)this ); 00067 fsm_debug( "CalculatorFSM:%#x:transition:1:end\n", (int)this ); 00068 __Y = EnteringSecondOperand; 00069 pass = true; 00070 } 00071 else if( e == Clear ) { 00072 fsm_debug( "CalculatorFSM:%#x:state:EnteringFirstOperand:leave:begin\n", (int)this ); 00073 //outcome actions 00074 fsm_debug( "CalculatorFSM:%#x:state:EnteringFirstOperand:leave:end\n", (int)this ); 00075 fsm_debug( "CalculatorFSM:%#x:transition:2:begin\n", (int)this ); 00076 fsm_debug( "CalculatorFSM:%#x:output:clear:begin\n", (int)this ); 00077 clear(); 00078 fsm_debug( "CalculatorFSM:%#x:output:clear:end\n", (int)this ); 00079 fsm_debug( "CalculatorFSM:%#x:transition:2:end\n", (int)this ); 00080 __Y = Idle; 00081 pass = true; 00082 } 00083 break; 00084 case Result: 00085 if( e == Number ) { 00086 fsm_debug( "CalculatorFSM:%#x:state:Result:leave:begin\n", (int)this ); 00087 //outcome actions 00088 fsm_debug( "CalculatorFSM:%#x:state:Result:leave:end\n", (int)this ); 00089 fsm_debug( "CalculatorFSM:%#x:transition:0:begin\n", (int)this ); 00090 fsm_debug( "CalculatorFSM:%#x:output:clear:begin\n", (int)this ); 00091 clear(); 00092 fsm_debug( "CalculatorFSM:%#x:output:clear:end\n", (int)this ); 00093 fsm_debug( "CalculatorFSM:%#x:output:addNumber:begin\n", (int)this ); 00094 addNumber(); 00095 fsm_debug( "CalculatorFSM:%#x:output:addNumber:end\n", (int)this ); 00096 fsm_debug( "CalculatorFSM:%#x:transition:0:end\n", (int)this ); 00097 __Y = EnteringFirstOperand; 00098 pass = true; 00099 } 00100 else if( e == BinaryOp ) { 00101 fsm_debug( "CalculatorFSM:%#x:state:Result:leave:begin\n", (int)this ); 00102 //outcome actions 00103 fsm_debug( "CalculatorFSM:%#x:state:Result:leave:end\n", (int)this ); 00104 fsm_debug( "CalculatorFSM:%#x:transition:1:begin\n", (int)this ); 00105 fsm_debug( "CalculatorFSM:%#x:output:saveNumber:begin\n", (int)this ); 00106 saveNumber(); 00107 fsm_debug( "CalculatorFSM:%#x:output:saveNumber:end\n", (int)this ); 00108 fsm_debug( "CalculatorFSM:%#x:output:saveOp:begin\n", (int)this ); 00109 saveOp(); 00110 fsm_debug( "CalculatorFSM:%#x:output:saveOp:end\n", (int)this ); 00111 fsm_debug( "CalculatorFSM:%#x:transition:1:end\n", (int)this ); 00112 __Y = EnteringSecondOperand; 00113 pass = true; 00114 } 00115 else if( e == Clear ) { 00116 fsm_debug( "CalculatorFSM:%#x:state:Result:leave:begin\n", (int)this ); 00117 //outcome actions 00118 fsm_debug( "CalculatorFSM:%#x:state:Result:leave:end\n", (int)this ); 00119 fsm_debug( "CalculatorFSM:%#x:transition:2:begin\n", (int)this ); 00120 fsm_debug( "CalculatorFSM:%#x:output:clear:begin\n", (int)this ); 00121 clear(); 00122 fsm_debug( "CalculatorFSM:%#x:output:clear:end\n", (int)this ); 00123 fsm_debug( "CalculatorFSM:%#x:transition:2:end\n", (int)this ); 00124 __Y = Idle; 00125 pass = true; 00126 } 00127 break; 00128 case EnteringSecondOperand: 00129 if( e == Number ) { 00130 fsm_debug( "CalculatorFSM:%#x:transition:0:begin\n", (int)this ); 00131 fsm_debug( "CalculatorFSM:%#x:output:addNumber:begin\n", (int)this ); 00132 addNumber(); 00133 fsm_debug( "CalculatorFSM:%#x:output:addNumber:end\n", (int)this ); 00134 fsm_debug( "CalculatorFSM:%#x:transition:0:end\n", (int)this ); 00135 pass = false; 00136 } 00137 else if( e == ResultRequested ) { 00138 fsm_debug( "CalculatorFSM:%#x:state:EnteringSecondOperand:leave:begin\n", (int)this ); 00139 //outcome actions 00140 fsm_debug( "CalculatorFSM:%#x:state:EnteringSecondOperand:leave:end\n", (int)this ); 00141 fsm_debug( "CalculatorFSM:%#x:transition:1:begin\n", (int)this ); 00142 fsm_debug( "CalculatorFSM:%#x:transition:1:end\n", (int)this ); 00143 __Y = Result; 00144 pass = true; 00145 } 00146 else if( e == Clear ) { 00147 fsm_debug( "CalculatorFSM:%#x:state:EnteringSecondOperand:leave:begin\n", (int)this ); 00148 //outcome actions 00149 fsm_debug( "CalculatorFSM:%#x:state:EnteringSecondOperand:leave:end\n", (int)this ); 00150 fsm_debug( "CalculatorFSM:%#x:transition:2:begin\n", (int)this ); 00151 fsm_debug( "CalculatorFSM:%#x:output:clear:begin\n", (int)this ); 00152 clear(); 00153 fsm_debug( "CalculatorFSM:%#x:output:clear:end\n", (int)this ); 00154 fsm_debug( "CalculatorFSM:%#x:transition:2:end\n", (int)this ); 00155 __Y = Idle; 00156 pass = true; 00157 } 00158 else if( e == BinaryOp ) { 00159 fsm_debug( "CalculatorFSM:%#x:state:EnteringSecondOperand:leave:begin\n", (int)this ); 00160 //outcome actions 00161 fsm_debug( "CalculatorFSM:%#x:state:EnteringSecondOperand:leave:end\n", (int)this ); 00162 fsm_debug( "CalculatorFSM:%#x:transition:3:begin\n", (int)this ); 00163 fsm_debug( "CalculatorFSM:%#x:self event:BinaryOp\n", (int)this ); 00164 this->A( BinaryOp ); 00165 fsm_debug( "CalculatorFSM:%#x:transition:3:end\n", (int)this ); 00166 __Y = Result; 00167 pass = true; 00168 } 00169 break; 00170 } 00171 00172 if( yOld == __Y && !pass ) { 00173 fsm_debug( "CalculatorFSM:%#x:event:%s:end\n", (int)this, eventName(e) ); 00174 return; 00175 } 00176 00177 switch( __Y ) { // income actions 00178 case Idle: 00179 fsm_debug( "CalculatorFSM:%#x:state:Idle:enter:begin\n", (int)this ); 00180 fsm_debug( "CalculatorFSM:%#x:state:Idle:enter:end\n", (int)this ); 00181 break; 00182 case EnteringFirstOperand: 00183 fsm_debug( "CalculatorFSM:%#x:state:EnteringFirstOperand:enter:begin\n", (int)this ); 00184 fsm_debug( "CalculatorFSM:%#x:state:EnteringFirstOperand:enter:end\n", (int)this ); 00185 break; 00186 case Result: 00187 fsm_debug( "CalculatorFSM:%#x:state:Result:enter:begin\n", (int)this ); 00188 fsm_debug( "CalculatorFSM:%#x:output:showResult:begin\n", (int)this ); 00189 showResult(); 00190 fsm_debug( "CalculatorFSM:%#x:output:showResult:end\n", (int)this ); 00191 fsm_debug( "CalculatorFSM:%#x:state:Result:enter:end\n", (int)this ); 00192 break; 00193 case EnteringSecondOperand: 00194 fsm_debug( "CalculatorFSM:%#x:state:EnteringSecondOperand:enter:begin\n", (int)this ); 00195 fsm_debug( "CalculatorFSM:%#x:state:EnteringSecondOperand:enter:end\n", (int)this ); 00196 break; 00197 } 00198 fsm_debug( "CalculatorFSM:%#x:event:%s:end\n", (int)this, eventName(e) ); 00199 } 00200 00201 void CalculatorFSM::A( Event e ) 00202 { 00203 bool __empty = __events.empty(); 00204 __events.push( e ); 00205 if( __empty ) { 00206 while( !__events.empty() ) { 00207 __processEvent( __events.front() ); 00208 __events.pop(); 00209 } 00210 } 00211 } 00212 00213 bool CalculatorFSM::debug_iNtErNal_input( const char*, const char* name, bool i) 00214 { 00215 fsm_debug( "CalculatorFSM:%#x:input:%s:%s\n", (int)this, name, i ? "true" : "false" ); 00216 return i; 00217 } 00218 const char* CalculatorFSM::eventName( Event e ) 00219 { 00220 switch(e) { 00221 case ResultRequested: 00222 return "ResultRequested"; 00223 case Number: 00224 return "Number"; 00225 case BinaryOp: 00226 return "BinaryOp"; 00227 case Clear: 00228 return "Clear"; 00229 default: 00230 return "Unknown event"; 00231 } 00232 } 00233 00234 const char* CalculatorFSM::stateName( States s ) 00235 { 00236 switch(s) { 00237 case Idle: 00238 return "Idle"; 00239 case EnteringFirstOperand: 00240 return "EnteringFirstOperand"; 00241 case Result: 00242 return "Result"; 00243 case EnteringSecondOperand: 00244 return "EnteringSecondOperand"; 00245 default: 00246 return "Unknown state"; 00247 } 00248 } 00249 void CalculatorFSM::debug_show_fsm_xml() 00250 { 00251 printf( "\nBegin FSM XML:CalculatorFSM\n%s\n\nEnd FSM XML\n\n", 00252 "<!DOCTYPE FSM> <FSM> <statemachine> <name>CalculatorFSM</name> <comment>Quite useless calculator</comment> <initialstate>Idle</initialstate> <event> <name>ResultRequested</name> <comment>A '=' have been entered</comment> </event> <event> <name>Number</name> <comment>A digit have been entered</comment> </event> <event> <name>BinaryOp</name> <comment>Pressed '+', '-', ...</comment> </event> <event> <name>Clear</name> <comment>User have pressed 'C' button. Clear all data</comment> </event> <output> <name>saveNumber</name> <comment>A number have been entered, save it and proceed to the next one</comment> </output> <output> <name>addNumber</name> <comment>Add a number to the current number, for example, if there is '12' on a screen and '3' button pressed, there should be '123' on a screen</comment> </output> <output> <name>clear</name> <comment>Just clear :)</comment> </output> <output> <name>saveOp</name> <comment>Save operation to our stack. This output follows press '+', '-', ...</comment> </output> <output> <name>showResult</name> <comment>Calculate and display result of operation</comment> </output> <state> <name>Idle</name> <comment>A result is displayed</comment> <incomeactions/> <outcomeactions/> <transitions> <transition type=\"simple\" > <name>start</name> <comment>User started to enter a number</comment> <condition>Number</condition> <destination>EnteringFirstOperand</destination> <transite_destination/> <transitionactions> <action type=\"output\" >addNumber</action> </transitionactions> </transition> </transitions> </state> <state> <name>EnteringFirstOperand</name> <comment>A first calculating operand is being entered</comment> <incomeactions/> <outcomeactions/> <transitions> <transition type=\"simple\" > <name>add</name> <comment/> <condition>Number</condition> <destination/> <transite_destination/> <transitionactions> <action type=\"output\" >addNumber</action> </transitionactions> </transition> <transition type=\"simple\" > <name>op</name> <comment/> <condition>BinaryOp</condition> <destination>EnteringSecondOperand</destination> <transite_destination/> <transitionactions> <action type=\"output\" >saveNumber</action> <action type=\"output\" >saveOp</action> </transitionactions> </transition> <transition type=\"simple\" > <name>clear</name> <comment>start from scratch</comment> <condition>Clear</condition> <destination>Idle</destination> <transite_destination/> <transitionactions> <action type=\"output\" >clear</action> </transitionactions> </transition> </transitions> </state> <state> <name>Result</name> <comment>A result is displayed, but there is a result from previous operation</comment> <incomeactions> <action type=\"output\" >showResult</action> </incomeactions> <outcomeactions/> <transitions> <transition type=\"simple\" > <name>from scratch</name> <comment>If user presses a number button when there's a result on a screen, we should clear it and start from scratch</comment> <condition>Number</condition> <destination>EnteringFirstOperand</destination> <transite_destination/> <transitionactions> <action type=\"output\" >clear</action> <action type=\"output\" >addNumber</action> </transitionactions> </transition> <transition type=\"simple\" > <name>next chain</name> <comment>If user presses an action button (+, -, *, /), we should remember it and ask for the second operand</comment> <condition>BinaryOp</condition> <destination>EnteringSecondOperand</destination> <transite_destination/> <transitionactions> <action type=\"output\" >saveNumber</action> <action type=\"output\" >saveOp</action> </transitionactions> </transition> <transition type=\"simple\" > <name>clear</name> <comment/> <condition>Clear</condition> <destination>Idle</destination> <transite_destination/> <transitionactions> <action type=\"output\" >clear</action> </transitionactions> </transition> </transitions> </state> <state> <name>EnteringSecondOperand</name> <comment>User is pressing digits to make second operand</comment> <incomeactions/> <outcomeactions/> <transitions> <transition type=\"simple\" > <name>add</name> <comment/> <condition>Number</condition> <destination/> <transite_destination/> <transitionactions> <action type=\"output\" >addNumber</action> </transitionactions> </transition> <transition type=\"simple\" > <name>result</name> <comment>User pressed '=', we should calculate and show result</comment> <condition>ResultRequested</condition> <destination>Result</destination> <transite_destination/> <transitionactions/> </transition> <transition type=\"simple\" > <name>clear</name> <comment/> <condition>Clear</condition> <destination>Idle</destination> <transite_destination/> <transitionactions> <action type=\"output\" >clear</action> </transitionactions> </transition> <transition type=\"simple\" > <name>next op</name> <comment>Pressing operation button is equal to pressing '=' and then this button</comment> <condition>BinaryOp</condition> <destination>Result</destination> <transite_destination/> <transitionactions> <action type=\"self_event\" >BinaryOp</action> </transitionactions> </transition> </transitions> </state> </statemachine> <graphics> <class classname=\"GStateSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GStateSaver\" > <qstring name=\"stateName\" >Idle</qstring> <QPoint name=\"position\" > <int>5042</int> <int>5045</int> </QPoint> </data> </class> <class classname=\"GStateSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GStateSaver\" > <qstring name=\"stateName\" >EnteringSecondOperand</qstring> <QPoint name=\"position\" > <int>5289</int> <int>5171</int> </QPoint> </data> </class> <class classname=\"GStateSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GStateSaver\" > <qstring name=\"stateName\" >Result</qstring> <QPoint name=\"position\" > <int>5259</int> <int>5034</int> </QPoint> </data> </class> <class classname=\"GStateSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GStateSaver\" > <qstring name=\"stateName\" >EnteringFirstOperand</qstring> <QPoint name=\"position\" > <int>5046</int> <int>5174</int> </QPoint> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >Idle</qstring> <int name=\"transition\" >0</int> <qvaluelist name=\"points\" /> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >EnteringFirstOperand</qstring> <int name=\"transition\" >0</int> <qvaluelist name=\"points\" > <QPoint> <int>5051</int> <int>5237</int> </QPoint> <QPoint> <int>5089</int> <int>5255</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >EnteringFirstOperand</qstring> <int name=\"transition\" >1</int> <qvaluelist name=\"points\" > <QPoint> <int>5206</int> <int>5225</int> </QPoint> <QPoint> <int>5276</int> <int>5225</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >EnteringSecondOperand</qstring> <int name=\"transition\" >0</int> <qvaluelist name=\"points\" > <QPoint> <int>5451</int> <int>5214</int> </QPoint> <QPoint> <int>5425</int> <int>5247</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >EnteringSecondOperand</qstring> <int name=\"transition\" >1</int> <qvaluelist name=\"points\" > <QPoint> <int>5355</int> <int>5108</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >Result</qstring> <int name=\"transition\" >0</int> <qvaluelist name=\"points\" > <QPoint> <int>5171</int> <int>5090</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >Result</qstring> <int name=\"transition\" >1</int> <qvaluelist name=\"points\" > <QPoint> <int>5273</int> <int>5112</int> </QPoint> <QPoint> <int>5278</int> <int>5138</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >EnteringFirstOperand</qstring> <int name=\"transition\" >2</int> <qvaluelist name=\"points\" > <QPoint> <int>5035</int> <int>5131</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >EnteringSecondOperand</qstring> <int name=\"transition\" >2</int> <qvaluelist name=\"points\" > <QPoint> <int>5316</int> <int>5263</int> </QPoint> <QPoint> <int>5105</int> <int>5305</int> </QPoint> <QPoint> <int>4996</int> <int>5258</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >Result</qstring> <int name=\"transition\" >2</int> <qvaluelist name=\"points\" > <QPoint> <int>5155</int> <int>5032</int> </QPoint> </qvaluelist> </data> </class> <class classname=\"GTransitionSaver\" > <meta classname=\"GSaver\" > <data classname=\"GSaver\" /> </meta> <data classname=\"GTransitionSaver\" > <qstring name=\"stateName\" >EnteringSecondOperand</qstring> <int name=\"transition\" >3</int> <qvaluelist name=\"points\" > <QPoint> <int>5426</int> <int>5128</int> </QPoint> <QPoint> <int>5367</int> <int>5061</int> </QPoint> </qvaluelist> </data> </class> </graphics> </FSM>" ); 00253 fflush(stdout); 00254 }

Generated on Fri Oct 29 13:35:13 2004 for Calculator by doxygen 1.3.8