35 bool read_until(std::istream &ist,
const char *st) {
36 int i = 0, l = int(strlen(st));
char c;
37 while (!ist.eof() && i < l)
38 { ist.get(c);
if (toupper(c) == toupper(st[i])) i++;
else i = 0; }
39 if (ist.eof())
return false;
else return true;
42 #define get_c__(r, c) { ist.get(c); \
43 if (ist.eof()) { if (!st.size()) st.push_back('\n'); return r; } \
44 if (to_up) c = char(toupper(c)); }
46 #define sdouble__(c, e) { st.push_back(c); get_c__(5, d); \
47 if (d == e) { st.push_back(e); return 6; } \
48 else { ist.putback(d); return 5; } } \
51 bool ignore_cr,
bool to_up,
bool read_un_pm,
int *linenb) {
53 char c = char(-1), d, e;
58 if (!ignore_cr && c ==
'\n') {
if (linenb) (*linenb)++;
return 1; }
59 if (isspace(c)) {
while (isspace(c)) get_c__(0, c); }
60 else if (c ==
'%') {
while (c !=
'\n') get_c__(0, c); }
62 if (ist.eof())
break;
else {
64 if (d ==
'.' && !ist.eof()) {
67 while (c !=
'\n') get_c__(0, c);
68 if (linenb) (*linenb)++;
71 else { ist.putback(e); ist.putback(d);
break; }
73 else { ist.putback(d);
break; }
80 if (c ==
'-' || c ==
'+') {
82 if (isdigit(d) || d ==
'.') { st.push_back(c); c = d; }
86 if (isdigit(c) || c ==
'.') {
87 while (isdigit(c) || c ==
'.' || c ==
'e' || c ==
'E') {
89 if (c ==
'e' || c ==
'E') {
91 if (c ==
'+' || c ==
'-') st.push_back(c);
103 if (c ==
'\"' || c ==
'\n')
return 3;
104 if (c ==
'\\') { st.push_back(c); get_c__(3, c); }
114 if (c ==
'\'' || c ==
'\n')
return 3;
115 if (c ==
'\\') { st.push_back(c); get_c__(3, c); }
122 if (isalpha(c) || c ==
'_') {
123 while (isalnum(c) || c ==
'_') {
131 if (c ==
'|') sdouble__(c,
'|');
132 if (c ==
'&') sdouble__(c,
'&');
133 if (c ==
'=') sdouble__(c,
'=');
134 if (c ==
'~') sdouble__(c,
'=');
135 if (c ==
'<') sdouble__(c,
'=');
136 if (c ==
'>') sdouble__(c,
'=');
138 st.push_back(c);
return 5;
141 std::istream& operator>>(std::istream& is,
const skip& t) {
144 while (!is.get(c).eof() && isspace(c)) ;
145 for (i=0; t.s[i]; ++i) {
147 GMM_ASSERT1(toupper(c) == toupper(t.s[i]) && !is.eof(),
148 "expected token '" << t.s <<
"' not found");
153 int casecmp(
const char *a,
const char *b,
unsigned n) {
155 for (i=0; i < n && a[i] && b[i]; ++i) {
156 if (toupper(a[i]) < toupper(b[i]))
return -1;
157 else if (toupper(a[i]) > toupper(b[i]))
return -1;
160 else if (b[i])
return -1;
164 void md_param::parse_error(
const std::string &t) {
165 GMM_ASSERT1(
false,
"Parse error reading "
166 << current_file <<
" line " << current_line <<
" near " << t);
169 void md_param::syntax_error(
const std::string &t) {
170 GMM_ASSERT1(
false,
"Error reading "
171 << current_file <<
" line " << current_line <<
" : " << t);
174 int md_param::get_next_token(std::istream &f) {
175 static int token_type = 0;
177 token_type =
get_token(f, temp_string,
false,
false,
false,
179 token_is_valid =
false;
183 void md_param::valid_token() { token_is_valid =
true; }
185 std::ostream &
operator <<(std::ostream &o,
const md_param::param_value& p) {
186 switch (p.type_of_param()) {
187 case md_param::REAL_VALUE : o << p.real();
break;
188 case md_param::STRING_VALUE : o <<
'\'' << p.string() <<
'\'';
break;
189 case md_param::ARRAY_VALUE :
191 if (p.array().size()) o << p.array()[0];
192 for (
unsigned i = 1; i < p.array().size(); ++i)
193 o <<
", " << p.array()[i];
199 md_param::param_value md_param::read_expression(std::istream &f,
202 int i = get_next_token(f);
204 result = param_value(::strtod(temp_string.c_str(), 0));
207 result = param_value(temp_string);
208 int j = get_next_token(f);
210 result.string() += temp_string;
211 j = get_next_token(f);
216 std::string name(temp_string);
217 if (parameters.find(name) != parameters.end())
218 result = parameters[name];
220 std::stringstream s; s <<
"Parameter " << name <<
" not found";
221 syntax_error(s.str());
225 switch (temp_string[0]) {
228 result = read_expression_list(f, skipped);
229 int j = get_next_token(f);
230 if (j != 5 || temp_string[0] !=
')') parse_error(temp_string);
234 result = read_expression(f, skipped);
235 if (result.type_of_param() != REAL_VALUE)
236 syntax_error(
"Sorry, unary + does not support string "
240 result = read_expression(f, skipped);
241 if (result.type_of_param() != REAL_VALUE)
242 syntax_error(
"Sorry, unary - does not support string "
244 result.real() *= -1.0;
247 result = read_expression(f, skipped);
248 if (result.type_of_param() != REAL_VALUE)
249 syntax_error(
"Sorry, unary ! does not support string "
251 result.real() = !(result.real());
256 result = param_value(ARRAY_VALUE);
258 int j = get_next_token(f);
259 if (j == 5 && temp_string[0] ==
']')
break;
260 if (!first && temp_string[0] !=
',') parse_error(temp_string);
261 if (first) valid_token();
262 result.array().push_back(read_expression_list(f, skipped));
267 default : parse_error(temp_string);
270 else parse_error(temp_string);
275 static void operator_priority_ftool(
int i,
char c,
int &prior,
int &op) {
278 case '*' : prior = 1; op = 1;
return;
279 case '/' : prior = 1; op = 2;
return;
280 case '+' : prior = 2; op = 3;
return;
281 case '-' : prior = 2; op = 4;
return;
282 case '<' : prior = 3; op = 5;
return;
283 case '>' : prior = 3; op = 6;
return;
287 case '<' : prior = 3; op = 7;
return;
288 case '>' : prior = 3; op = 8;
return;
289 case '=' : prior = 3; op = 9;
return;
290 case '~' : prior = 3; op = 10;
return;
291 case '&' : prior = 4; op = 11;
return;
292 case '|' : prior = 4; op = 12;
return;
297 void md_param::do_bin_op(std::vector<md_param::param_value> &value_list,
298 std::vector<int> &op_list,
299 std::vector<int> &prior_list) {
300 param_value &p1(*(value_list.end() - 2));
301 param_value &p2(*(value_list.end() - 1));
302 if (p1.type_of_param() != REAL_VALUE || p2.type_of_param() != REAL_VALUE)
303 syntax_error(
"Sorry, binary operators does not support string "
306 switch (op_list.back()) {
307 case 1 : p1.real() *= p2.real();
break;
308 case 2 : p1.real() /= p2.real();
break;
309 case 3 : p1.real() += p2.real();
break;
310 case 4 : p1.real() -= p2.real();
break;
311 case 5 : p1.real() = (p1.real() < p2.real());
break;
312 case 6 : p1.real() = (p1.real() > p2.real());
break;
313 case 7 : p1.real() = (p1.real() <= p2.real());
break;
314 case 8 : p1.real() = (p1.real() >= p2.real());
break;
315 case 9 : p1.real() = (p1.real() == p2.real());
break;
316 case 10 : p1.real() = (p1.real() != p2.real());
break;
317 case 11 : p1.real() = ((p1.real() != 0.0) && (p2.real() != 0.0));
break;
318 case 12 : p1.real() = ((p1.real() != 0.0) || (p2.real() != 0.0));
break;
320 value_list.pop_back(); op_list.pop_back(); prior_list.pop_back();
324 md_param::param_value md_param::read_expression_list(std::istream &f,
326 std::vector<param_value> value_list;
327 value_list.push_back(read_expression(f, skipped));
328 std::vector<int> op_list, prior_list;
329 int i = get_next_token(f), prior, op;
330 operator_priority_ftool(i, temp_string[0], prior, op);
332 while (!prior_list.empty() && prior_list.back() <= prior)
333 do_bin_op(value_list, op_list, prior_list);
335 value_list.push_back(read_expression(f, skipped));
336 op_list.push_back(op);
337 prior_list.push_back(prior);
339 i = get_next_token(f);
340 operator_priority_ftool(i, temp_string[0], prior, op);
344 while (!prior_list.empty()) do_bin_op(value_list, op_list, prior_list);
346 return value_list[0];
349 int md_param::read_instruction(std::istream &f,
bool skipped) {
351 while (i == 1 || (i == 5 && temp_string[0] ==
';')) i = get_next_token(f);
352 if (i == 0)
return 1;
353 if (i != 4) parse_error(temp_string);
354 if (temp_string ==
"end")
return 1;
355 if (temp_string ==
"else")
return 2;
356 if (temp_string ==
"elseif")
return 3;
357 if (temp_string ==
"if") {
358 param_value p = read_expression_list(f, skipped);
359 if (p.type_of_param() != REAL_VALUE)
360 syntax_error(
"if instruction needs a condition");
361 bool b = (p.real() != 0.0);
362 int j = read_instruction_list(f, !b || skipped);
363 if (j == 0) syntax_error(
"Unterminated if");
365 int k = read_instruction_list(f, b || skipped);
366 if (k != 1) syntax_error(
"Unterminated else");
371 if (b) skipped =
true;
372 p = read_expression_list(f, skipped);
373 if (p.type_of_param() != REAL_VALUE)
374 syntax_error(
"elseif instruction needs a condition");
375 b = (p.real() != 0.0);
376 k = read_instruction_list(f, !b || skipped);
378 k = read_instruction_list(f, b || skipped);
382 if (k != 1) syntax_error(
"Unterminated elseif");
386 if (temp_string ==
"error") {
387 param_value p = read_expression_list(f, skipped);
388 GMM_ASSERT1(skipped,
"Error in parameter file: " << p);
391 std::string name(temp_string);
392 i = get_next_token(f);
393 if (i != 5 || temp_string[0] !=
'=') parse_error(temp_string);
394 param_value result = read_expression_list(f, skipped);
395 i = get_next_token(f);
396 if (i != 0 && i != 1 && (i != 5 || temp_string[0] !=
';'))
397 parse_error(temp_string);
398 if (!skipped) parameters[name]=result;
402 int md_param::read_instruction_list(std::istream &f,
bool skipped) {
403 int i;
while (!(i = read_instruction(f, skipped))) { }
407 void md_param::read_param_file(std::istream &f) {
409 token_is_valid =
false; current_line = 1;
410 if (read_instruction_list(f) > 1)
411 syntax_error(
"Parameter file terminated by an else");
414 void md_param::read_command_line(
int argc,
char *argv[]) {
416 for (
int aa = 1; aa < argc; aa++) {
417 if (argv[aa][0] !=
'-') {
418 current_file = std::string(argv[aa]);
419 std::ifstream f1(current_file.c_str());
420 if (f1) { read_param_file(f1); f1.close(); }
422 std::string r = current_file;
423 current_file +=
".param";
424 std::ifstream f2(current_file.c_str());
425 if (f2) { read_param_file(f2); f2.close(); }
426 else GMM_ASSERT1(
false,
"Parameter file " << r <<
"not found");
429 else if (argv[aa][1] ==
'd') {
430 current_file =
"command line";
431 if (strlen(argv[aa]) == 2)
432 { std::stringstream ss(argv[++aa]); read_param_file(ss); }
434 { std::stringstream ss(&(argv[aa][2])); read_param_file(ss); }
439 double md_param::real_value(
const std::string &name,
const char *comment,
440 double default_val) {
441 if (parameters.find(name) == parameters.end()) {
447 cout <<
"No parameter " << name <<
" found, please enter its value\n";
448 cout << comment <<
" : "; cin >> f;
449 parameters[name] = param_value(f);
452 param_value &p(parameters[name]);
453 GMM_ASSERT1(p.type_of_param() == REAL_VALUE,
454 "Parameter " << name <<
" is not real");
458 long md_param::int_value(
const std::string &name,
const char *comment,
460 if (parameters.find(name) == parameters.end()) {
466 cout <<
"No parameter " << name <<
" found, please enter its value\n";
467 cout << comment <<
" : "; cin >> f;
468 parameters[name] = param_value(
double(f));
471 param_value &p(parameters[name]);
472 GMM_ASSERT1(p.type_of_param() == REAL_VALUE,
473 "Parameter " << name <<
" is not real");
474 return long(p.real());
477 const std::string &md_param::string_value(
const std::string &name,
479 const std::string &default_val) {
480 if (parameters.find(name) == parameters.end()) {
486 cout <<
"No parameter " << name <<
" found, please enter its value\n";
487 cout << comment <<
" : "; cin >> s;
488 parameters[name] = param_value(s);
491 param_value &p(parameters[name]);
492 GMM_ASSERT1(p.type_of_param() == STRING_VALUE,
"Parameter " << name
493 <<
" is not a character string");
497 const std::vector<md_param::param_value> &
498 md_param::array_value(
const std::string &name,
const char *comment) {
500 static std::vector<md_param::param_value> empty_array;
501 if (parameters.find(name) == parameters.end()) {
502 if (comment == 0)
return empty_array;
506 cout <<
"No parameter " << name <<
" found, please enter its value\n";
507 cout << comment <<
" : "; cin >> s;
508 parameters[name] = param_value(s);
511 param_value &p(parameters[name]);
512 GMM_ASSERT1(p.type_of_param() == ARRAY_VALUE,
"Parameter " << name
513 <<
" is not an array");