1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 ------------- Copyright (C) 2000 -------------
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU Lesser General Public License as published by the Free Software
11 Foundation; either version 2 of the License, or (at your option) any later
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA.
23 Further information about the GNU Lesser General Public License can also be found on
24 the world wide web at http://www.gnu.org.
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
30 --------------------------------------------------------------------------------
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 COMMENTS, REFERENCES, and NOTES
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 The switch component is defined as follows (see the API documentation for more
40 <switch name="switch1">
41 <default value="{property|value}"/>
42 <test logic="{AND|OR}" value="{property|value}">
43 {property} {conditional} {property|value}
44 <test logic="{AND|OR}">
45 {property} {conditional} {property|value}
50 <test logic="{AND|OR}" value="{property|value}">
51 {property} {conditional} {property|value}
58 Also, see the header file (FGSwitch.h) for further details.
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
68 static const char *IdSrc = "$Id$";
69 static const char *IdHdr = ID_SWITCH;
71 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
75 FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
78 struct test *current_test;
79 Element *test_element, *condition_element;
81 test_element = element->GetElement();
82 while (test_element) {
83 if (test_element->GetName() == "default") {
84 tests.push_back(test());
85 current_test = &tests.back();
86 current_test->Logic = eDefault;
87 } else if (test_element->GetName() == "test") { // here's a test
88 tests.push_back(test());
89 current_test = &tests.back();
90 logic = test_element->GetAttributeValue("logic");
91 if (logic == "OR") current_test->Logic = eOR;
92 else if (logic == "AND") current_test->Logic = eAND;
93 else if (logic.size() == 0) current_test->Logic = eAND; // default
95 cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl;
97 for (unsigned int i=0; i<test_element->GetNumDataLines(); i++)
98 current_test->conditions.push_back(FGCondition(test_element->GetDataLine(i), PropertyManager));
100 condition_element = test_element->GetElement(); // retrieve condition groups
101 while (condition_element) {
102 current_test->conditions.push_back(FGCondition(condition_element, PropertyManager));
103 condition_element = test_element->GetNextElement();
108 if (test_element->GetName() != "output") { // this is not an output element
109 value = test_element->GetAttributeValue("value");
111 cerr << "No VALUE supplied for switch component: " << Name << endl;
113 if (value.find_first_not_of("-.0123456789eE") == string::npos) {
114 // if true (and execution falls into this block), "value" is a number.
115 current_test->OutputVal = atof(value.c_str());
117 // "value" must be a property if execution passes to here.
118 if (value[0] == '-') {
119 current_test->sign = -1.0;
122 current_test->sign = 1.0;
124 current_test->OutputProp = PropertyManager->GetNode(value);
129 test_element = element->GetNextElement();
132 FGFCSComponent::bind();
137 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139 FGSwitch::~FGSwitch()
144 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146 bool FGSwitch::Run(void )
148 vector <test>::iterator iTests = tests.begin();
149 vector <FGCondition>::iterator iConditions;
152 while (iTests < tests.end()) {
153 iConditions = iTests->conditions.begin();
155 if (iTests->Logic == eDefault) {
156 Output = iTests->GetValue();
157 } else if (iTests->Logic == eAND) {
159 while (iConditions < iTests->conditions.end()) {
160 if (!iConditions->Evaluate()) pass = false;
163 } else if (iTests->Logic == eOR) {
165 while (iConditions < iTests->conditions.end()) {
166 if (iConditions->Evaluate()) pass = true;
170 cerr << "Invalid logic test" << endl;
174 Output = iTests->GetValue();
181 if (IsOutput) SetOutput();
186 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187 // The bitmasked value choices are as follows:
188 // unset: In this case (the default) JSBSim would only print
189 // out the normally expected messages, essentially echoing
190 // the config files as they are read. If the environment
191 // variable is not set, debug_lvl is set to 1 internally
192 // 0: This requests JSBSim not to output any messages
194 // 1: This value explicity requests the normal JSBSim
196 // 2: This value asks for a message to be printed out when
197 // a class is instantiated
198 // 4: When this value is set, a message is displayed when a
199 // FGModel object executes its Run() method
200 // 8: When this value is set, various runtime state variables
201 // are printed out periodically
202 // 16: When set various parameters are sanity checked and
203 // a message is printed out when they go out of bounds
205 void FGSwitch::Debug(int from)
207 vector <test>::iterator iTests = tests.begin();
208 vector <FGCondition>::iterator iConditions;
209 string comp, scratch;
213 if (debug_lvl <= 0) return;
215 if (debug_lvl & 1) { // Standard console startup message output
216 if (from == 0) { // Constructor
217 while (iTests < tests.end()) {
221 switch(iTests->Logic) {
224 cerr << "Unset logic for test condition" << endl;
233 scratch = " by default.";
237 cerr << "Unknown logic for test condition" << endl;
240 if (iTests->OutputProp != 0L)
241 if (iTests->sign < 0)
242 cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;
244 cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;
246 cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;
248 iConditions = iTests->conditions.begin();
250 while (iConditions < iTests->conditions.end()) {
251 if (!first) cout << indent << comp << " ";
252 else cout << indent << " ";
254 iConditions->PrintCondition();
261 if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
264 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
265 if (from == 0) cout << "Instantiated: FGSwitch" << endl;
266 if (from == 1) cout << "Destroyed: FGSwitch" << endl;
268 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
270 if (debug_lvl & 8 ) { // Runtime state variables
272 if (debug_lvl & 16) { // Sanity checking
274 if (debug_lvl & 64) {
275 if (from == 0) { // Constructor
276 cout << IdSrc << endl;
277 cout << IdHdr << endl;