1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 Purpose: Config file read-in class
10 --------------------------------------------------------------------------------
13 --------------------------------------------------------------------------------
14 03/16/2000 JSB Created
16 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
18 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
20 #include "FGConfigFile.h"
26 static const char *IdSrc = "$Id$";
27 static const char *IdHdr = ID_CONFIGFILE;
29 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
33 FGConfigFile::FGConfigFile(string cfgFileName)
35 #if defined ( sgi ) && !defined( __GNUC__ )
36 cfgfile.open(cfgFileName.c_str(), ios::in );
38 cfgfile.open(cfgFileName.c_str(), ios::in | ios::binary );
43 #if defined ( sgi ) && !defined( __GNUC__ )
44 if (!cfgfile.fail() && !cfgfile.eof()) GetNextConfigLine();
46 if (cfgfile.is_open()) GetNextConfigLine();
53 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 FGConfigFile::~FGConfigFile()
61 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 string FGConfigFile::GetNextConfigLine(void)
65 int comment_starts_at;
69 bool start_comment, end_comment;
70 string CommentStringTemp;
73 CurrentLine = GetLine();
74 line_length = CurrentLine.length();
75 comment_starts_at = CurrentLine.find("<!--");
77 if (comment_starts_at >= 0) start_comment = true;
78 else start_comment = false;
80 comment_ends_at = CurrentLine.find("-->");
82 if (comment_ends_at >= 0) end_comment = true;
83 else end_comment = false;
85 if (!start_comment && !end_comment) { // command comment
86 if (CommentsOn) CommentStringTemp = CurrentLine;
87 CommentString += CommentStringTemp + "\r\n";
88 } else if (start_comment && comment_ends_at > comment_starts_at) { // <!-- ... -->
90 comment_length = comment_ends_at + 2 - comment_starts_at + 1;
91 LineComment = CurrentLine.substr(comment_starts_at+4, comment_length-4-3);
92 CurrentLine.erase(comment_starts_at, comment_length);
93 if (CurrentLine.find_first_not_of(" ") == string::npos) {
96 } else if ( start_comment && !end_comment) { // <!-- ...
98 comment_length = line_length - comment_starts_at;
99 CommentStringTemp = CurrentLine.substr(comment_starts_at+4, comment_length-4);
100 CommentString = CommentStringTemp + "\r\n";
101 CurrentLine.erase(comment_starts_at, comment_length);
102 } else if (!start_comment && end_comment) { // ... -->
104 comment_length = comment_ends_at + 2 + 1;
105 CommentStringTemp = CurrentLine.substr(0, comment_length-4);
106 CommentString += CommentStringTemp + "\r\n";
107 CurrentLine.erase(0, comment_length);
108 } else if (start_comment && comment_ends_at < comment_starts_at) { // --> command <!--
109 cerr << "Old comment ends and new one starts - bad JSBSim config file form." << endl;
111 comment_length = comment_ends_at + 2 + 1;
112 CommentStringTemp = CurrentLine.substr(0, comment_length-4);
113 CommentString += CommentStringTemp + "\r\n";
114 CurrentLine.erase(0, comment_length);
116 } while (CommentsOn);
119 if (CurrentLine.length() == 0) {
125 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 string FGConfigFile::GetValue(string val)
129 string::size_type pos, p1, p2, ptest;
131 if (val == "") { // this call is to return the tag value
132 pos = CurrentLine.find("<");
133 if (pos != CurrentLine.npos) { // beginning brace found "<"
134 p1 = CurrentLine.find_first_not_of(" ",pos+1);
135 if (p1 != CurrentLine.npos) { // found first character of tag
136 p2 = CurrentLine.find_first_of(" >",p1+1);
137 if (p2 == CurrentLine.npos) p2 = p1+1;
138 return CurrentLine.substr(p1,p2-p1);
140 } else { // beginning brace "<" not found; this is a regular data line
141 pos = CurrentLine.find_first_not_of(" ");
142 if (pos != CurrentLine.npos) { // first character in line found
143 p2 = CurrentLine.find_first_of(" ",pos+1);
144 if (p2 != CurrentLine.npos) {
145 return CurrentLine.substr(pos,p2-pos);
147 return CurrentLine.substr(pos,CurrentLine.length()-pos);
151 } else { // return a value for a specific tag
152 pos = CurrentLine.find(val);
153 if (pos != CurrentLine.npos) {
154 pos = CurrentLine.find("=",pos);
155 if (pos != CurrentLine.npos) {
156 ptest = CurrentLine.find_first_not_of(" ",pos+1);
157 if (ptest != CurrentLine.npos) {
159 if (CurrentLine[ptest] == '"') { // quoted
160 p2 = CurrentLine.find_first_of("\"",p1);
161 } else { // not quoted
162 p2 = CurrentLine.find_first_of(" ",p1);
164 if (p2 != CurrentLine.npos) {
165 return CurrentLine.substr(p1,p2-p1);
168 } else { // "=" not found
169 pos = CurrentLine.find(val);
170 pos = CurrentLine.find_first_of(" ",pos+1);
171 ptest = CurrentLine.find_first_not_of(" ",pos+1);
172 if (ptest != CurrentLine.npos) {
173 if (CurrentLine[ptest] == '"') { // quoted
175 p2 = CurrentLine.find_first_of("\"",p1);
176 } else { // not quoted
178 p2 = CurrentLine.find_first_of(" ",p1);
180 if (p2 != CurrentLine.npos) {
181 return CurrentLine.substr(p1,p2-p1);
183 p2 = CurrentLine.length();
184 return CurrentLine.substr(p1,p2-p1);
194 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 string FGConfigFile::GetValue(void)
201 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203 string FGConfigFile::GetLine(void)
208 while ((test = cfgfile.get()) != EOF) {
209 if (test >= 0x20 || test == 0x09) {
211 scratch += (char)0x20;
213 scratch += (char)test;
216 if ((test = cfgfile.get()) != EOF) { // get *next* character
217 #if defined ( sgi ) && !defined( __GNUC__ )
218 if (test >= 0x20 || test == 0x09) cfgfile.putback(test);
220 if (test >= 0x20 || test == 0x09) cfgfile.unget();
227 int index = scratch.find_last_not_of(" ");
228 if (index != string::npos && index < (scratch.size()-1)) {
229 scratch = scratch.substr(0,index+1);
232 if (cfgfile.eof() && scratch.empty()) return string("EOF");
236 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 FGConfigFile& FGConfigFile::operator>>(double& val)
240 string::size_type pos, end;
242 pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
243 if (pos == CurrentLine.npos) pos = CurrentLine.length();
244 end = CurrentLine.find_first_of(", ",pos+1);
245 if (end == CurrentLine.npos) end = CurrentLine.length();
246 string str = CurrentLine.substr(pos, end - pos);
247 val = strtod(str.c_str(),NULL);
248 CurrentIndex = end+1;
253 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
258 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 FGConfigFile& FGConfigFile::operator>>(int& val)
262 string::size_type pos, end;
264 pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
265 if (pos == CurrentLine.npos) pos = CurrentLine.length();
266 end = CurrentLine.find_first_of(", ",pos+1);
267 if (end == CurrentLine.npos) end = CurrentLine.length();
268 string str = CurrentLine.substr(pos, end - pos);
269 val = atoi(str.c_str());
270 CurrentIndex = end+1;
275 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
280 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 FGConfigFile& FGConfigFile::operator>>(string& str)
284 string::size_type pos, end;
286 pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
287 if (pos == CurrentLine.npos) pos = CurrentLine.length();
288 end = CurrentLine.find_first_of(", ",pos+1);
289 if (end == CurrentLine.npos) end = CurrentLine.length();
290 str = CurrentLine.substr(pos, end - pos);
291 CurrentIndex = end+1;
296 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
301 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 void FGConfigFile::ResetLineIndexToZero(void)
308 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309 // The bitmasked value choices are as follows:
310 // unset: In this case (the default) JSBSim would only print
311 // out the normally expected messages, essentially echoing
312 // the config files as they are read. If the environment
313 // variable is not set, debug_lvl is set to 1 internally
314 // 0: This requests JSBSim not to output any messages
316 // 1: This value explicity requests the normal JSBSim
318 // 2: This value asks for a message to be printed out when
319 // a class is instantiated
320 // 4: When this value is set, a message is displayed when a
321 // FGModel object executes its Run() method
322 // 8: When this value is set, various runtime state variables
323 // are printed out periodically
324 // 16: When set various parameters are sanity checked and
325 // a message is printed out when they go out of bounds
327 void FGConfigFile::Debug(int from)
329 if (debug_lvl <= 0) return;
331 if (debug_lvl & 1) { // Standard console startup message output
333 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
334 if (from == 0) cout << "Instantiated: FGConfigFile" << endl;
335 if (from == 1) cout << "Destroyed: FGConfigFile" << endl;
337 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
339 if (debug_lvl & 8 ) { // Runtime state variables
341 if (debug_lvl & 16) { // Sanity checking
343 if (debug_lvl & 64) {
344 if (from == 0) { // Constructor
345 cout << IdSrc << endl;
346 cout << IdHdr << endl;