1 // ONELAB - Copyright (C) 2010-2012 C. Geuzaine, F. Henrotte
2 //
3 // See the README.txt file for license information. Please report all
4 // issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5
6 #include <algorithm>
7 #include "mathex.h"
8
9 #include "OnelabClients.h"
10
11 // reserved keywords for the onelab parser
12
13 namespace olkey {
14 static std::string deflabel("onelab.tags");
15 static std::string label("OL."), comment("#"), separator(";");
16 static std::string line(label + "line");
17 static std::string begin(label + "block");
18 static std::string end(label + "endblock");
19 static std::string include(label + "include");
20 static std::string message(label + "msg");
21 static std::string showParam(label + "show");
22 static std::string showGmsh(label + "merge");
23 static std::string dump(label + "dump");
24 static std::string ifcond(label + "if");
25 static std::string iftrue(label + "iftrue"), ifntrue(label + "ifntrue");
26 static std::string olelse(label + "else"), olendif(label + "endif");
27 static std::string getValue(label + "get");
28 static std::string mathex(label + "eval");
29 } // namespace olkey
30
31 // Client member functions defined here because they use parser commands
32
findCommandLine(const std::string & client,const std::string & host)33 bool MetaModel::findCommandLine(const std::string &client,
34 const std::string &host)
35 {
36 std::string fileName;
37 size_t pos;
38
39 // std::cout << "FHF search cmdl: " << client << " , " << host << std::endl;
40
41 fileName = getWorkingDir() + genericNameFromArgs + onelabExtension + ".save";
42
43 std::ifstream infile(fileName.c_str());
44 if(infile.is_open()) {
45 while(infile.good()) {
46 std::string line;
47 getline(infile, line);
48 if((pos = line.find(olkey::separator)) != std::string::npos) {
49 std::string name, action;
50 std::vector<std::string> args;
51 extract(line.substr(0, pos), name, action, args);
52 // (name, action, args) = client.commandLine(cmdl{,rhost{,rdir}})
53 std::string cmdl = "", rhost = "localhost", rdir = "";
54 cmdl = args[0];
55 if(args.size() > 1) rhost = args[1];
56 if(args.size() > 2) rdir = args[2];
57
58 if(name == client) {
59 if((host.empty() && (rhost != "localhost")) ||
60 (host.size() && (rhost == host))) {
61 OLMsg::SetOnelabString(name + "/CommandLine", cmdl, false);
62 if(rhost.compare("localhost")) {
63 OLMsg::SetOnelabString(name + "/HostName", rhost, false);
64 if(rdir.size())
65 OLMsg::SetOnelabString(name + "/RemoteDir", rdir, false);
66 }
67 // std::cout << "FHF found cmdl: " << cmdl << "," << rhost <<
68 // std::endl;
69 return true;
70 }
71 }
72 }
73 }
74 }
75 infile.close();
76 return false;
77 }
78
toChar()79 std::string localSolverClient::toChar()
80 {
81 std::ostringstream sstream;
82
83 if(getCommandLine().size()) {
84 sstream << getName() << ".commandLine(" << getCommandLine();
85 std::string host = OLMsg::GetOnelabString(getName() + "/HostName");
86 if(host.size() && host.compare("localhost")) {
87 sstream << "," << host;
88 std::string rdir = OLMsg::GetOnelabString(getName() + "/RemoteDir");
89 if(rdir.size()) sstream << "," << rdir;
90 }
91 sstream << ");" << std::endl;
92 }
93 return sstream.str();
94 }
95
saveCommandLines()96 void MetaModel::saveCommandLines()
97 {
98 std::vector<std::string> arguments, buffer;
99 std::string fileName;
100 fileName = getWorkingDir() + genericNameFromArgs + onelabExtension + ".save";
101
102 std::ifstream infile(fileName.c_str());
103 if(infile.is_open()) {
104 while(infile.good()) {
105 std::string line;
106 getline(infile, line);
107 size_t pos;
108 if((pos = line.find(olkey::separator)) != std::string::npos) {
109 std::string name, action;
110 std::vector<std::string> args;
111 extract(line.substr(0, pos), name, action, args);
112 std::string host = OLMsg::GetOnelabString(name + "/HostName");
113 std::string rhost = (args.size() >= 2) ? args[1] : "";
114 bool keep = rhost.compare(host);
115 if(keep) buffer.push_back(line);
116 }
117 }
118 }
119 else
120 OLMsg::Warning("The file <%s> cannot be opened", fileName.c_str());
121 infile.close();
122
123 // save client command lines
124 std::ofstream outfile(fileName.c_str());
125 if(outfile.is_open()) {
126 for(citer it = _clients.begin(); it != _clients.end(); it++) {
127 outfile << (*it)->toChar();
128 }
129 for(std::vector<std::string>::const_iterator it = buffer.begin();
130 it != buffer.end(); it++) {
131 outfile << (*it) << std::endl;
132 }
133 }
134 else
135 OLMsg::Error("The file <%s> cannot be opened", fileName.c_str());
136 outfile.close();
137 }
138
enclosed(const std::string & in,std::vector<std::string> & arguments,size_t & end)139 int enclosed(const std::string &in, std::vector<std::string> &arguments,
140 size_t &end)
141 {
142 // syntax: (arguments[Ø], arguments[1], ... , arguments[n])
143 // arguments[i] may contain parenthesis
144
145 size_t pos, cursor;
146 arguments.resize(0);
147
148 pos = 0;
149 if(in[pos] != '(') {
150 OLMsg::Error("Syntax error: <%s>", in.c_str());
151 return 0;
152 }
153 pos++; // skips '('
154 int count = 1;
155 cursor = pos;
156 do {
157 if(in[pos] == '(')
158 count++;
159 else if(in[pos] == ')')
160 count--;
161 else if(in[pos] == ',') {
162 if(count == 1) {
163 arguments.push_back(removeBlanks(in.substr(cursor, pos - cursor)));
164 cursor = pos + 1; // skips ','
165 }
166 else {
167 // ignore this comma
168 }
169 }
170 pos++;
171 } while(count && (pos < in.size()));
172
173 // count is 0 when the closing brace has been found.
174 if(count && pos == in.size()) {
175 OLMsg::Error("Syntax error: <%s>", in.c_str());
176 return 0;
177 }
178 else
179 arguments.push_back(removeBlanks(in.substr(cursor, pos - 1 - cursor)));
180 end = pos;
181 return arguments.size();
182 }
183
extract(const std::string & in,std::string & paramName,std::string & action,std::vector<std::string> & arguments)184 int extract(const std::string &in, std::string ¶mName, std::string &action,
185 std::vector<std::string> &arguments)
186 {
187 // syntax: paramName.action( arg1, arg2, ... )
188 size_t pos, cursor;
189 cursor = 0;
190 if((pos = in.find(".", cursor)) == std::string::npos) {
191 OLMsg::Error("Syntax error: <%s>", in.c_str());
192 return 0;
193 }
194 else
195 paramName.assign(sanitize(in.substr(cursor, pos - cursor)));
196 cursor = pos + 1; // skips '.'
197 if((pos = in.find("(", cursor)) == std::string::npos) {
198 OLMsg::Error("Syntax error: <%s>", in.c_str());
199 return 0;
200 }
201 else
202 action.assign(sanitize(in.substr(cursor, pos - cursor)));
203 cursor = pos;
204
205 int NumArg = enclosed(in.substr(cursor), arguments, pos);
206 // std::cout << "FHF=" << in.substr(cursor+pos) << std::endl;
207 if((in.find_first_not_of(" \t", cursor + pos + 1)) != std::string::npos) {
208 OLMsg::Error("Syntax error in <%s> (forgot a %s ?)",
209 in.substr(cursor + pos + 1).c_str(), olkey::separator.c_str());
210 return 0;
211 }
212 if(!NumArg) OLMsg::Error("Syntax error: <%s>", in.c_str());
213 return NumArg;
214 }
215
extractLogic(const std::string & in,std::vector<std::string> & arguments)216 int extractLogic(const std::string &in, std::vector<std::string> &arguments)
217 {
218 // syntax: ( argument[0], argument[1]\in{<,>,<=,>=,==,!=}, arguments[2])
219 size_t pos, cursor;
220 arguments.resize(0);
221 cursor = 0;
222 if((pos = in.find("(", cursor)) == std::string::npos) {
223 OLMsg::Error("Syntax error: <%s>", in.c_str());
224 return 0;
225 }
226
227 unsigned int count = 1;
228 pos++; // skips '('
229 cursor = pos;
230 do {
231 if(in[pos] == '(') count++;
232 if(in[pos] == ')') count--;
233 if((in[pos] == '<') || (in[pos] == '=') || (in[pos] == '>') ||
234 (in[pos] == '!')) {
235 arguments.push_back(removeBlanks(in.substr(cursor, pos - cursor)));
236 if(count != 1) OLMsg::Error("Syntax error: <%s>", in.c_str());
237 cursor = pos;
238 if(in[pos + 1] == '=') {
239 arguments.push_back(in.substr(cursor, 2));
240 pos++;
241 }
242 else {
243 arguments.push_back(in.substr(cursor, 1));
244 }
245 cursor = pos + 1;
246 }
247 pos++;
248 } while(count && (pos != std::string::npos));
249 // count is 0 when the closing brace is found.
250
251 if(count)
252 OLMsg::Error("Syntax error: mismatched parenthesis in <%s>", in.c_str());
253 else
254 arguments.push_back(removeBlanks(in.substr(cursor, pos - 1 - cursor)));
255
256 if((arguments.size() != 1) && (arguments.size() != 3))
257 OLMsg::Error("Syntax error: <%s>", in.c_str());
258 return arguments.size();
259 }
260
extractExpandPattern(const std::string & str)261 std::string extractExpandPattern(const std::string &str)
262 {
263 size_t posa, posb;
264 posa = str.find_first_of("\"\'<");
265 posb = str.find_last_of("\"\'>");
266 std::string pattern = str.substr(posa + 1, posb - posa - 1);
267 posa = pattern.find("comma");
268 if(posa != std::string::npos) pattern.replace(posa, 5, ",");
269 if(pattern.size() != 3)
270 OLMsg::Error("Incorrect expand pattern <%s>", str.c_str());
271 return pattern;
272 }
273
longName(const std::string name)274 std::string localSolverClient::longName(const std::string name)
275 {
276 std::set<std::string, ShortNameLessThan>::iterator it;
277 std::string fullName;
278 if((it = _parameters.find(name)) != _parameters.end())
279 fullName.assign(OLMsg::obtainFullName(*it));
280 else
281 fullName.assign(OLMsg::obtainFullName(name));
282 return fullName;
283 }
284
resolveString(const std::string & line)285 std::string localSolverClient::resolveString(const std::string &line)
286 {
287 // looks for the first OL.get() statement,
288 // returns a onelab::string value from the server, if any, or "" otherwise
289 // if no OL.get() statement found, returns line unchanged.
290 std::vector<onelab::string> strings;
291 std::vector<std::string> arguments;
292 size_t pos, cursor;
293
294 if((pos = line.find(olkey::getValue)) != std::string::npos) {
295 cursor = pos + olkey::getValue.length();
296 int NumArg = enclosed(line.substr(cursor), arguments, pos);
297 if(NumArg < 1) {
298 OLMsg::Error("Malformed %s statement: <%s>", olkey::getValue.c_str(),
299 line.c_str());
300 return "??";
301 }
302 std::string paramName = longName(arguments[0]);
303 get(strings, paramName);
304 if(strings.size())
305 return strings[0].getValue();
306 else
307 return "";
308 }
309 return line;
310 }
311
resolveGetVal(std::string line)312 std::string localSolverClient::resolveGetVal(std::string line)
313 {
314 // looks for OL.get() statements, substitute values from server
315 // then evaluate the resulting string with mathex.
316 // OL.get(name
317 // {, {choices|range}.{size|comp|expand|index}|attributes.get(args)})
318 std::vector<onelab::number> numbers;
319 std::vector<onelab::string> strings;
320 std::vector<std::string> arguments;
321 std::string buff;
322 size_t pos, pos0, cursor;
323
324 cursor = 0;
325 while((pos = line.find(olkey::getValue, cursor)) != std::string::npos) {
326 pos0 = pos; // for further use
327 cursor = pos + olkey::getValue.length();
328 int NumArg = enclosed(line.substr(cursor), arguments, pos);
329 if(NumArg < 1) {
330 OLMsg::Error("Malformed %s statement: <%s>", olkey::getValue.c_str(),
331 line.c_str());
332 return "??";
333 }
334 std::string paramName = longName(arguments[0]);
335 get(numbers, paramName);
336 if(numbers.size()) {
337 std::stringstream Num;
338 if(NumArg == 1) {
339 Num << numbers[0].getValue();
340 buff.assign(Num.str());
341 }
342 else if(NumArg == 2) {
343 std::string name, action;
344 std::vector<std::string> args;
345 extract(arguments[1], name, action, args);
346 if(!name.compare("choices")) {
347 std::vector<double> choices = numbers[0].getChoices();
348 if(!action.compare("size")) { buff.assign(ftoa(choices.size())); }
349 else if(!action.compare("begin")) {
350 buff.assign(ftoa(*choices.begin()));
351 }
352 else if(!action.compare("rbegin")) {
353 buff.assign(ftoa(*choices.rbegin()));
354 }
355 else if(!action.compare("comp")) {
356 int i = atoi(args[0].c_str());
357 if((i >= 0) && (i < (int)choices.size())) Num << choices[i];
358 buff.assign(ftoa(choices[i]));
359 }
360 else if(!action.compare("expand")) {
361 std::string pattern;
362 pattern.assign(extractExpandPattern(args[0]));
363 // OLMsg::Info("Expand parameter <%s> with pattern <%s>",
364 // paramName.c_str(),pattern.c_str());
365 buff.assign(1, pattern[0]);
366 for(std::vector<double>::iterator it = choices.begin();
367 it != choices.end(); it++) {
368 if(it != choices.begin()) buff.append(1, pattern[1]);
369 buff.append(ftoa(*it));
370 }
371 buff.append(1, pattern[2]);
372 }
373 else if(!action.compare("index")) {
374 Num << numbers[0].getIndex();
375 buff.assign(Num.str());
376 }
377 else
378 OLMsg::Error("Unknown action <%s> in %s statement", action.c_str(),
379 olkey::getValue.c_str());
380 }
381 else if(!name.compare("range")) {
382 double stp = numbers[0].getStep();
383 double min = numbers[0].getMin();
384 double max = numbers[0].getMax();
385
386 if((stp == 0) || (min == -onelab::parameter::maxNumber()) ||
387 (max == onelab::parameter::maxNumber()))
388 OLMsg::Error("Invalid range description for parameter <%s>",
389 paramName.c_str());
390 if(!action.compare("size")) {
391 buff.assign(ftoa(fabs((max - min) / stp)));
392 }
393 else if(!action.compare("comp")) {
394 int i = atof(args[0].c_str());
395 if(stp > 0)
396 Num << min + i * stp;
397 else if(stp < 0)
398 Num << max - i * stp;
399 }
400 else if(!action.compare("expand")) {
401 }
402 else
403 OLMsg::Error("Unknown action <%s> in %s statement", action.c_str(),
404 olkey::getValue.c_str());
405 }
406 else if(!name.compare(0, 6, "attrib")) {
407 if(!action.compare("get")) {
408 buff.assign(numbers[0].getAttribute(args[0]));
409 }
410 }
411 }
412 }
413 else {
414 get(strings, paramName);
415 if(strings.size())
416 buff.assign(strings[0].getValue());
417 else {
418 OLMsg::Error("resolveGetVal: unknown variable: <%s>",
419 paramName.c_str());
420 return "??";
421 }
422 }
423 line.replace(pos0, cursor + pos - pos0, buff);
424 cursor = pos0 + buff.length();
425 }
426
427 // Check now wheter the line contains OL.eval's and resolve them
428 cursor = 0;
429 while((pos = line.find(olkey::mathex, cursor)) != std::string::npos) {
430 size_t pos0 = pos;
431 cursor = pos + olkey::mathex.length();
432 if(enclosed(line.substr(cursor), arguments, pos) != 1) {
433 OLMsg::Error("Malformed %s statement: <%s>", olkey::mathex.c_str(),
434 line.c_str());
435 return "??";
436 }
437 // std::cout << "MathEx evaluates now <"<< arguments[0]<< "> " << std::endl;
438 smlib::mathex *mathExp = new smlib::mathex();
439 mathExp->expression(arguments[0]);
440 double val = mathExp->eval();
441 // std::cout << "MathEx <" << arguments[0] << "> ="<< val << std::endl;
442 line.replace(pos0, cursor + pos - pos0, ftoa(val));
443 }
444
445 // Check now wheter the line still contains OL.
446 if((pos = line.find(olkey::label)) != std::string::npos)
447 OLMsg::Error("Unidentified onelab command in <%s>", line.c_str());
448
449 return line;
450 }
451
resolveLogicExpr(std::vector<std::string> arguments)452 bool localSolverClient::resolveLogicExpr(std::vector<std::string> arguments)
453 {
454 std::vector<onelab::number> numbers;
455
456 double val1, val2;
457 std::string str1, str2;
458 bool condition = false;
459
460 if(arguments.size() == 1) {
461 str1.assign(resolveString(arguments[0]));
462 if(str1.size()) return true;
463 val1 = atof(resolveGetVal(arguments[0]).c_str());
464 return (bool)val1;
465 }
466 else if(arguments.size() == 3) {
467 str1.assign(resolveString(arguments[0]));
468 str2.assign(resolveString(arguments[2]));
469 if(str1.size() && str2.size()) {
470 if(!arguments[1].compare("=="))
471 condition = !str1.compare(str2);
472 else if(!arguments[1].compare("!="))
473 condition = str1.compare(str2);
474 else
475 OLMsg::Error("Unknown logical operator <%s> for strings",
476 arguments[1].c_str());
477 }
478 else {
479 val1 = atof(resolveGetVal(arguments[0]).c_str());
480 val2 = atof(resolveGetVal(arguments[2]).c_str());
481 if(!arguments[1].compare("<"))
482 condition = (val1 < val2);
483 else if(!arguments[1].compare("<="))
484 condition = (val1 <= val2);
485 else if(!arguments[1].compare(">"))
486 condition = (val1 > val2);
487 else if(!arguments[1].compare(">="))
488 condition = (val1 >= val2);
489 else if(!arguments[1].compare("=="))
490 condition = (val1 == val2);
491 else if(!arguments[1].compare("!="))
492 condition = (val1 != val2);
493 else
494 OLMsg::Error("Unknown logical operator <%s>", arguments[1].c_str());
495 }
496 }
497 else
498 OLMsg::Error("Invalid logical expression");
499 return condition;
500 }
501
resolveRange(const std::string & in,std::vector<double> & arguments)502 bool localSolverClient::resolveRange(const std::string &in,
503 std::vector<double> &arguments)
504 {
505 // syntax: a:b:c or a:b|n with a,b,c numbers and n integer
506 double val;
507 size_t pos, cursor;
508 arguments.resize(0);
509 cursor = 0;
510 if((pos = in.find(":", cursor)) == std::string::npos) {
511 OLMsg::Error("Syntax error in range <%s>", in.c_str());
512 return 0;
513 }
514 else {
515 val = atof(resolveGetVal(in.substr(cursor, pos - cursor)).c_str());
516 arguments.push_back(val);
517 }
518 cursor = pos + 1; // skips ':'
519 if((pos = in.find(":", cursor)) != std::string::npos) {
520 // arguments.push_back(atof(in.substr(cursor,pos-cursor).c_str()));
521 // arguments.push_back(atof(in.substr(pos+1).c_str()));
522 val = atof(resolveGetVal(in.substr(cursor, pos - cursor)).c_str());
523 arguments.push_back(val);
524 val = atof(resolveGetVal(in.substr(pos + 1)).c_str());
525 arguments.push_back(val);
526 }
527 else if((pos = in.find("|", cursor)) != std::string::npos) {
528 // arguments.push_back(atof(in.substr(cursor,pos-cursor).c_str()));
529 // double NumStep = atof(in.substr(pos+1).c_str());
530 // arguments.push_back((arguments[1]-arguments[0])/((NumStep==0)?1:NumStep));
531 val = atof(resolveGetVal(in.substr(cursor, pos - cursor)).c_str());
532 arguments.push_back(val);
533 double NumStep = atof(in.substr(pos + 1).c_str());
534 arguments.push_back((arguments[1] - arguments[0]) /
535 ((NumStep == 0) ? 1 : NumStep));
536 }
537 else
538 OLMsg::Error("Syntax error in range <%s>", in.c_str());
539 return (arguments.size() == 3);
540 }
541
parse_sentence(std::string line)542 void localSolverClient::parse_sentence(std::string line)
543 {
544 size_t pos, cursor;
545 std::string name, action, path;
546 std::vector<std::string> arguments;
547 std::vector<onelab::number> numbers;
548 std::vector<onelab::string> strings;
549
550 cursor = 0;
551 while((pos = line.find(olkey::separator, cursor)) != std::string::npos) {
552 std::string name, action;
553 // std::cout << "line=" << line << std::endl;
554
555 extract(line.substr(cursor, pos - cursor), name, action, arguments);
556 if(!action.compare("number")) {
557 // syntax: paramName.number(val,path,help,range(optional))
558 double val = 0.0;
559 if(arguments.size() > 1) name.assign(FixOLPath(arguments[1]) + name);
560 _parameters.insert(name);
561 OLMsg::recordFullName(name);
562 get(numbers, name);
563 if(numbers.empty()) {
564 numbers.resize(1);
565 numbers[0].setName(name);
566 if(arguments[0].empty()) {
567 numbers[0].setReadOnly(true);
568 numbers[0].setNeverChanged(true);
569 }
570 else
571 val = atof(resolveGetVal(arguments[0]).c_str());
572 numbers[0].setValue(val);
573 }
574 // else if(arguments[0].empty()) // resets read only parameters
575 // numbers[0].setValue(val);
576
577 if(arguments.size() > 2) numbers[0].setLabel(unquote(arguments[2]));
578 if(arguments.size() > 3) {
579 std::vector<double> bounds;
580 if(resolveRange(arguments[3], bounds)) {
581 numbers[0].setMin(bounds[0]);
582 numbers[0].setMax(bounds[1]);
583 numbers[0].setStep(bounds[2]);
584 }
585 }
586 set(numbers[0]);
587 }
588 else if(!action.compare("string")) {
589 // syntax: paramName.string(val,path,help)
590 std::string val = "";
591 if(arguments.size() > 1)
592 name.assign(FixOLPath(arguments[1]) + name); // append path
593 _parameters.insert(name);
594 OLMsg::recordFullName(name);
595 get(strings, name);
596 if(strings.empty()) {
597 strings.resize(1);
598 strings[0].setName(name);
599 if(arguments[0].empty()) {
600 strings[0].setReadOnly(true);
601 strings[0].setNeverChanged(true);
602 }
603 else
604 val = resolveGetVal(arguments[0]);
605 strings[0].setValue(val);
606 }
607 // choices list is reset
608 std::vector<std::string> choices;
609 strings[0].setChoices(choices);
610
611 if(arguments.size() > 2) strings[0].setLabel(unquote(arguments[2]));
612 set(strings[0]);
613 }
614 else if(!action.compare("radioButton")) {
615 // syntax: paramName.radioButton(val,path,label)
616 double val = 0;
617 if(arguments[0].empty())
618 OLMsg::Error("No value given for param <%s>", name.c_str());
619 else
620 val = atof(arguments[0].c_str());
621 if(arguments.size() > 1) name.assign(FixOLPath(arguments[1]) + name);
622 _parameters.insert(name);
623 OLMsg::recordFullName(name);
624 get(numbers, name);
625 if(numbers.size()) {
626 val = numbers[0].getValue(); // use value from server
627 }
628 else {
629 numbers.resize(1);
630 numbers[0].setName(name);
631 numbers[0].setValue(val);
632 }
633 if(arguments.size() > 2) numbers[0].setLabel(unquote(arguments[2]));
634 std::vector<double> choices;
635 choices.push_back(0);
636 choices.push_back(1);
637 numbers[0].setChoices(choices);
638 set(numbers[0]);
639 }
640 else if(!action.compare("range")) {
641 // set the range of an existing number
642 // syntax: paramName.range({a:b:c|a:b#n|min,max,step})
643 if(arguments[0].empty())
644 OLMsg::Error("No argument given for MinMax <%s>", name.c_str());
645 else {
646 name.assign(longName(name));
647 get(numbers, name);
648 if(numbers.size()) { // parameter must exist
649 if(arguments.size() == 1) {
650 std::vector<double> bounds;
651 if(resolveRange(arguments[0], bounds)) {
652 numbers[0].setMin(bounds[0]);
653 numbers[0].setMax(bounds[1]);
654 numbers[0].setStep(bounds[2]);
655 }
656 }
657 else if(arguments.size() == 3) {
658 numbers[0].setMin(atof(arguments[0].c_str()));
659 numbers[0].setMax(atof(arguments[1].c_str()));
660 numbers[0].setStep(atof(arguments[2].c_str()));
661 }
662 else
663 OLMsg::Error("Wrong number of arguments for range <%s>",
664 name.c_str());
665 set(numbers[0]);
666 }
667 else
668 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
669 }
670 }
671 else if(!action.compare("withinRange")) {
672 // ensure the value is in the prescribed range
673 name.assign(longName(name));
674 get(numbers, name);
675 if(numbers.size()) { // parameter must exist
676 if((numbers[0].getMin() != -onelab::parameter::maxNumber()) &&
677 (numbers[0].getValue() < numbers[0].getMin()))
678 numbers[0].setValue(numbers[0].getMin());
679 if((numbers[0].getMax() != onelab::parameter::maxNumber()) &&
680 (numbers[0].getValue() > numbers[0].getMax()))
681 numbers[0].setValue(numbers[0].getMax());
682 set(numbers[0]);
683 }
684 else
685 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
686 }
687 else if(!action.compare("setValue")) {
688 // a set request together with a setReadOnly(1) forces
689 // the value on server to be changed.
690 name.assign(longName(name));
691 get(numbers, name);
692 if(numbers.size()) {
693 if(arguments[0].size())
694 numbers[0].setValue(atof(resolveGetVal(arguments[0]).c_str()));
695 numbers[0].setReadOnly(1);
696 set(numbers[0]);
697 }
698 else {
699 get(strings, name);
700 if(strings.size()) {
701 if(arguments[0].empty()) // resets an empty string
702 strings[0].setValue("");
703 else
704 strings[0].setValue(arguments[0]);
705 strings[0].setReadOnly(1);
706 set(strings[0]);
707 }
708 else
709 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
710 }
711 }
712 else if(!action.compare("resetChoices")) {
713 name.assign(longName(name));
714 get(numbers, name);
715
716 if(numbers.size()) { // parameter must exist
717 std::vector<double> choices;
718 numbers[0].setChoices(choices);
719 std::map<double, std::string> valuelabels;
720 numbers[0].setValueLabels(valuelabels);
721 set(numbers[0]);
722 }
723 else {
724 get(strings, name);
725 if(strings.size()) {
726 std::vector<std::string> choices;
727 strings[0].setChoices(choices);
728 set(strings[0]);
729 }
730 else {
731 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
732 }
733 }
734 }
735 else if(!action.compare("addChoices")) {
736 name.assign(longName(name));
737 get(numbers, name);
738 if(numbers.size()) { // parameter must exist
739 std::vector<double> choices = numbers[0].getChoices();
740 for(unsigned int i = 0; i < arguments.size(); i++) {
741 double val = atof(resolveGetVal(arguments[i]).c_str());
742 // if(std::find(choices.begin(),choices.end(),val)==choices.end())
743 choices.push_back(val);
744 }
745 numbers[0].setChoices(choices);
746 set(numbers[0]);
747 }
748 else {
749 get(strings, name);
750 if(strings.size()) {
751 std::vector<std::string> choices = strings[0].getChoices();
752 for(unsigned int i = 0; i < arguments.size(); i++)
753 if(std::find(choices.begin(), choices.end(), arguments[i]) ==
754 choices.end())
755 choices.push_back(arguments[i]);
756 strings[0].setChoices(choices);
757 set(strings[0]);
758 }
759 else {
760 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
761 }
762 }
763 }
764 else if(!action.compare("valueLabels")) {
765 name.assign(longName(name));
766 get(numbers, name);
767 if(numbers.size()) { // parameter must exist
768 if(arguments.size() % 2) {
769 OLMsg::Error("Nb of labels does not match nb of choices for <%s>",
770 name.c_str());
771 }
772 else {
773 std::vector<double> choices = numbers[0].getChoices();
774 for(unsigned int i = 0; i < arguments.size(); i = i + 2) {
775 double val = atof(resolveGetVal(arguments[i]).c_str());
776 if(std::find(choices.begin(), choices.end(), val) == choices.end())
777 choices.push_back(val);
778 numbers[0].setValueLabel(val, unquote(arguments[i + 1]));
779 }
780 numbers[0].setChoices(choices);
781 set(numbers[0]);
782 }
783 }
784 else
785 OLMsg::Error("The number <%s> does not exist", name.c_str());
786 }
787 else if(!action.compare("setVisible")) {
788 if(arguments[0].empty())
789 OLMsg::Error("Missing argument SetVisible <%s>", name.c_str());
790 else {
791 name.assign(longName(name));
792 get(numbers, name);
793 if(numbers.size()) {
794 numbers[0].setVisible(atof(resolveGetVal(arguments[0]).c_str()));
795 set(numbers[0]);
796 }
797 else {
798 get(strings, name);
799 if(strings.size()) {
800 strings[0].setVisible(atof(resolveGetVal(arguments[0]).c_str()));
801 set(strings[0]);
802 }
803 else {
804 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
805 }
806 }
807 }
808 }
809 else if(!action.compare("setReadOnly")) {
810 if(arguments[0].empty())
811 OLMsg::Error("Missing argument SetReadOnly <%s>", name.c_str());
812 else {
813 name.assign(longName(name));
814 get(numbers, name);
815 if(numbers.size()) {
816 numbers[0].setReadOnly(atof(resolveGetVal(arguments[0]).c_str()));
817 set(numbers[0]);
818 }
819 else {
820 get(strings, name);
821 if(strings.size()) {
822 strings[0].setReadOnly(atof(resolveGetVal(arguments[0]).c_str()));
823 set(strings[0]);
824 }
825 else {
826 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
827 }
828 }
829 }
830 }
831 else if(!action.compare("layout")) {
832 name.assign(longName(name));
833 get(numbers, name);
834 if(numbers.size()) {
835 numbers[0].setReadOnly(0);
836 numbers[0].setAttribute("Highlight", "Ivory");
837 set(numbers[0]);
838 }
839 else {
840 get(strings, name);
841 if(strings.size()) {
842 strings[0].setReadOnly(0);
843 strings[0].setAttribute("Highlight", "Ivory");
844 set(strings[0]);
845 }
846 else {
847 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
848 }
849 }
850 }
851 else if(!action.compare("setAttribute")) {
852 if(arguments.size() != 2)
853 OLMsg::Error("SetAttribute <%s> needs two arguments %d", name.c_str(),
854 arguments.size());
855 else {
856 name.assign(longName(name));
857 get(numbers, name);
858 if(numbers.size()) {
859 numbers[0].setAttribute(arguments[0].c_str(),
860 resolveGetVal(arguments[1]).c_str());
861 set(numbers[0]);
862 }
863 else {
864 get(strings, name);
865 if(strings.size()) {
866 strings[0].setAttribute(arguments[0].c_str(), arguments[1].c_str());
867 set(strings[0]);
868 }
869 else {
870 OLMsg::Error("The parameter <%s> does not exist", name.c_str());
871 }
872 }
873 }
874 }
875 else {
876 client_sentence(name, action, arguments);
877 }
878 cursor = pos + 1;
879 }
880 // check whether
881 if((line.find_first_not_of(" \t", cursor)) != std::string::npos) {
882 OLMsg::Error("Syntax error in <%s> (forgot a %s ?)",
883 line.substr(cursor).c_str(), olkey::separator.c_str());
884 }
885 }
886
modify_tags(const std::string lab,const std::string com)887 void localSolverClient::modify_tags(const std::string lab,
888 const std::string com)
889 {
890 bool changed = false;
891 if(lab.compare(olkey::label) && lab.size()) {
892 changed = true;
893 olkey::label.assign(lab);
894 olkey::line.assign(olkey::label + "line");
895 olkey::begin.assign(olkey::label + "block");
896 olkey::end.assign(olkey::label + "endblock");
897 olkey::include.assign(olkey::label + "include");
898 olkey::message.assign(olkey::label + "msg");
899 olkey::showParam.assign(olkey::label + "show");
900 olkey::showGmsh.assign(olkey::label + "merge");
901 olkey::dump.assign(olkey::label + "dump");
902 olkey::ifcond.assign(olkey::label + "if");
903 olkey::iftrue.assign(olkey::label + "iftrue");
904 olkey::ifntrue.assign(olkey::label + "ifntrue");
905 olkey::olelse.assign(olkey::label + "else");
906 olkey::olendif.assign(olkey::label + "endif");
907 olkey::getValue.assign(olkey::label + "get");
908 olkey::mathex.assign(olkey::label + "eval");
909 }
910 if(com.compare(olkey::comment) && com.size()) {
911 changed = true;
912 olkey::comment.assign(com);
913 }
914
915 if(changed)
916 OLMsg::Info("Using now onelab tags <%s,%s>", olkey::label.c_str(),
917 olkey::comment.c_str());
918 }
919
parse_oneline(std::string line,std::ifstream & infile)920 void localSolverClient::parse_oneline(std::string line, std::ifstream &infile)
921 {
922 size_t pos, cursor;
923 std::vector<std::string> arguments;
924 std::vector<onelab::number> numbers;
925 std::vector<onelab::string> strings;
926
927 if((pos = line.find_first_not_of(" \t")) == std::string::npos) {
928 // empty line, skip
929 }
930 else if(!line.compare(pos, olkey::comment.size(), olkey::comment)) {
931 // commented out line, skip
932 }
933 else if((pos = line.find(olkey::deflabel)) != std::string::npos) {
934 // onelab.tags(label,comment);
935 // onelab.tags(); -> reset to default
936 cursor = pos + olkey::deflabel.length();
937 int NumArg = enclosed(line.substr(cursor), arguments, pos);
938 if((NumArg == 1) && arguments[0].empty())
939 modify_tags("", "");
940 else if(NumArg == 2)
941 modify_tags(arguments[0], arguments[1]);
942 else
943 OLMsg::Error("Malformed <%s> statement", olkey::deflabel.c_str());
944 }
945 else if((pos = line.find(olkey::begin)) != std::string::npos) {
946 // onelab.block
947 if(!parse_block(infile))
948 OLMsg::Error("Malformed <%s> block <%s>", olkey::begin.c_str(),
949 olkey::end.c_str());
950 }
951 else if((pos = line.find(olkey::iftrue)) != std::string::npos) {
952 // onelab.iftrue
953 cursor = pos + olkey::iftrue.length();
954 bool condition = false;
955 if(enclosed(line.substr(cursor), arguments, pos) < 1)
956 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::iftrue.c_str(),
957 line.c_str());
958 else {
959 get(strings, longName(arguments[0]));
960 if(strings.size())
961 condition = true;
962 else {
963 get(numbers, longName(arguments[0]));
964 if(numbers.size())
965 condition = (bool)numbers[0].getValue();
966 else
967 OLMsg::Error("Unknown parameter <%s> in <%s> statement",
968 arguments[0].c_str(), olkey::iftrue.c_str());
969 }
970 if(!parse_ifstatement(infile, condition))
971 OLMsg::Error("Malformed <%s> statement: <%s>", olkey::iftrue.c_str(),
972 arguments[0].c_str());
973 }
974 }
975 else if((pos = line.find(olkey::ifntrue)) != std::string::npos) {
976 // onelab.ifntrue
977 cursor = pos + olkey::ifntrue.length();
978 bool condition = false;
979 if(enclosed(line.substr(cursor), arguments, pos) < 1)
980 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::ifntrue.c_str(),
981 line.c_str());
982 else {
983 get(strings, longName(arguments[0]));
984 if(strings.size())
985 condition = true;
986 else {
987 get(numbers, longName(arguments[0]));
988 if(numbers.size())
989 condition = (bool)numbers[0].getValue();
990 else {
991 condition = false;
992 // OLMsg::Warning("Unknown parameter <%s> in <%s> statement",
993 // arguments[0].c_str(),olkey::ifntrue.c_str());
994 }
995 }
996 if(!parse_ifstatement(infile, !condition))
997 OLMsg::Error("Malformed <%s> statement: <%s>", olkey::ifntrue.c_str(),
998 arguments[0].c_str());
999 }
1000 }
1001 else if((pos = line.find(olkey::ifcond)) != std::string::npos) {
1002 // onelab.ifcond
1003 cursor = pos + olkey::ifcond.length();
1004 extractLogic(line.substr(cursor), arguments);
1005 bool condition = resolveLogicExpr(arguments);
1006 if(!parse_ifstatement(infile, condition)) {
1007 OLMsg::Error("Malformed %s statement: <%s>", olkey::ifcond.c_str(),
1008 line.c_str());
1009 }
1010 }
1011 else if((pos = line.find(olkey::include)) != std::string::npos) {
1012 // onelab.include
1013 cursor = pos + olkey::include.length();
1014 if(enclosed(line.substr(cursor), arguments, pos) < 1)
1015 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::include.c_str(),
1016 line.c_str());
1017 else {
1018 std::string filename = getWorkingDir() + resolveGetVal(arguments[0]);
1019 OLMsg::Info("Parse file <%s> %s", filename.c_str(),
1020 parse_onefile(filename) ? "done" : "failed");
1021 }
1022 }
1023 else if((pos = line.find(olkey::message)) != std::string::npos) {
1024 // onelab.message
1025 cursor = pos + olkey::message.length();
1026 if(enclosed(line.substr(cursor), arguments, pos) < 1)
1027 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::message.c_str(),
1028 line.c_str());
1029 else {
1030 std::string msg = resolveGetVal(arguments[0]);
1031 OLMsg::Info("%s", msg.c_str());
1032 }
1033 }
1034 else if((pos = line.find(olkey::showParam)) != std::string::npos) {
1035 // onelab.showParam
1036 cursor = pos + olkey::showParam.length();
1037 if(enclosed(line.substr(cursor), arguments, pos) < 1)
1038 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::showParam.c_str(),
1039 line.c_str());
1040 for(unsigned int i = 0; i < arguments.size(); i++) {
1041 std::string lname = longName(arguments[i]);
1042 std::string msg;
1043 get(numbers, lname);
1044 if(numbers.size())
1045 msg.assign(numbers[0].toChar());
1046 else {
1047 get(strings, lname);
1048 if(strings.size())
1049 msg.assign(strings[0].toChar());
1050 else
1051 OLMsg::Error("Unknown parameter <%s> in <%s> statement",
1052 arguments[i].c_str(), olkey::showParam.c_str());
1053 }
1054 for(unsigned int j = 0; j < msg.size(); j++)
1055 if(msg[j] == onelab::parameter::charSep()) msg[j] = '|';
1056 OLMsg::Info("%s", msg.c_str());
1057 }
1058 }
1059 else if((pos = line.find(olkey::showGmsh)) != std::string::npos) {
1060 // onelab.showGmsh
1061 cursor = pos + olkey::showGmsh.length();
1062 if(enclosed(line.substr(cursor), arguments, pos) < 1)
1063 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::showGmsh.c_str(),
1064 line.c_str());
1065 else {
1066 std::string fileName = resolveGetVal(arguments[0]);
1067 OLMsg::MergeFile(getWorkingDir() + fileName);
1068 }
1069 }
1070 else if((pos = line.find(olkey::dump)) != std::string::npos) {
1071 // onelab.dump
1072 cursor = pos + olkey::dump.length();
1073 if(enclosed(line.substr(cursor), arguments, pos) < 1) {
1074 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::dump.c_str(),
1075 line.c_str());
1076 }
1077 else {
1078 FILE *fp = fopen(resolveGetVal(arguments[0]).c_str(), "wb");
1079 if(fp) {
1080 onelab::server::instance()->toFile(fp);
1081 fclose(fp);
1082 }
1083 }
1084 }
1085 else if(isOnelabBlock() ||
1086 (!isOnelabBlock() &&
1087 ((pos = line.find(olkey::line)) != std::string::npos))) {
1088 // either any line with no "OL." within a onelabBlock or a line
1089 // introduced by a "onelab.line" tag not within a onelabBlock
1090 std::string cmds = "", cmd;
1091 size_t posa, posb;
1092 int NbLines = 1;
1093 bool err = false, terminated = false;
1094 do {
1095 // skip tag 'olkey::line' if any
1096 if((pos = line.find(olkey::line)) != std::string::npos)
1097 posa = pos + olkey::line.size();
1098 else
1099 posa = 0;
1100
1101 // skip trailing comments if any
1102 posb = line.find(olkey::comment);
1103 if(posb == std::string::npos)
1104 cmd.assign(line.substr(posa));
1105 else
1106 cmd.assign(line.substr(posa, posb - posa));
1107
1108 cmds.append(cmd);
1109
1110 // check whether "cmd" ends with "olkey::separator"
1111 pos = cmd.find_last_of(olkey::separator);
1112 terminated = (pos != std::string::npos);
1113
1114 // std::cout << "cmds=<" << cmds << ">" << terminated << std::endl;
1115
1116 if(!terminated) {
1117 // not found olkey::separator => append the next nonempty line
1118 while(infile.good()) {
1119 getline(infile, line);
1120 NbLines++; // command should not span over more than 20 nonempty lines
1121 if(line.find_first_not_of(" \t") != std::string::npos) break;
1122 }
1123
1124 if(infile.good()) {
1125 // check that no OL. commands is found except OL.get or OL.eval
1126 if((pos = line.find(olkey::getValue)) != std::string::npos) {
1127 err = false;
1128 }
1129 else if((pos = line.find(olkey::mathex)) != std::string::npos) {
1130 err = false;
1131 }
1132 else if((pos = line.find(olkey::end)) != std::string::npos) {
1133 err = true;
1134 closeOnelabBlock();
1135 }
1136 else if((pos = line.find(olkey::label)) != std::string::npos) {
1137 err = true;
1138 }
1139 }
1140 }
1141 } while(infile.good() && !err && !terminated && NbLines <= 20);
1142
1143 if(!terminated) {
1144 if(NbLines >= 20)
1145 OLMsg::Error("Command <%s> should not span over more than 20 lines",
1146 cmds.c_str());
1147 else
1148 OLMsg::Error("Unterminated command <%s>", cmds.c_str());
1149 return;
1150 }
1151 else
1152 parse_sentence(cmds);
1153 }
1154 else if((pos = line.find(olkey::getValue)) != std::string::npos) {
1155 // onelab.getValue: nothing to do
1156 }
1157 else if((pos = line.find(olkey::mathex)) != std::string::npos) {
1158 // onelab.mathex: nothing to do
1159 }
1160 else if((pos = line.find(olkey::label)) != std::string::npos) {
1161 OLMsg::Error("Unknown ONELAB keyword in <%s>", line.c_str());
1162 }
1163 else {
1164 // not a onelab line, skip
1165 }
1166 }
1167
parse_block(std::ifstream & infile)1168 bool localSolverClient::parse_block(std::ifstream &infile)
1169 {
1170 size_t pos;
1171 std::string line;
1172 openOnelabBlock();
1173 while(infile.good()) {
1174 getline(infile, line);
1175 if((pos = line.find_first_not_of(" \t")) == std::string::npos)
1176 continue; // skip empty line
1177 if((pos = line.find(olkey::end)) != std::string::npos) {
1178 closeOnelabBlock();
1179 return true;
1180 }
1181 parse_oneline(line, infile);
1182 }
1183 return false;
1184 }
1185
parse_ifstatement(std::ifstream & infile,bool condition)1186 bool localSolverClient::parse_ifstatement(std::ifstream &infile, bool condition)
1187 {
1188 int level;
1189 size_t pos;
1190 std::string line;
1191
1192 bool trueclause = true;
1193 level = 1;
1194 while(infile.good() && level) {
1195 getline(infile, line);
1196 if(((pos = line.find(olkey::olelse)) != std::string::npos) && (level == 1))
1197 trueclause = false;
1198 else if((pos = line.find(olkey::olendif)) != std::string::npos)
1199 level--;
1200 else if(!(trueclause ^ condition)) // xor bitwise operator
1201 parse_oneline(line, infile);
1202 else { // check for opening if statements
1203 if((pos = line.find(olkey::iftrue)) != std::string::npos)
1204 level++;
1205 else if((pos = line.find(olkey::ifntrue)) != std::string::npos)
1206 level++;
1207 else if((pos = line.find(olkey::ifcond)) != std::string::npos)
1208 level++;
1209 }
1210 }
1211 return level ? false : true;
1212 }
1213
parse_onefile(std::string fileName,bool mandatory)1214 bool localSolverClient::parse_onefile(std::string fileName, bool mandatory)
1215 {
1216 std::ifstream infile(fileName.c_str());
1217 if(infile.is_open()) {
1218 while(infile.good()) {
1219 std::string line;
1220 getline(infile, line);
1221 parse_oneline(line, infile);
1222 }
1223 infile.close();
1224 return true;
1225 }
1226 else {
1227 return !mandatory;
1228 // if(mandatory)
1229 // OLMsg::Error("The file <%s> does not exist",fileName.c_str());
1230 // else
1231 // OLMsg::Warning("The file <%s> does not exist",fileName.c_str());
1232 }
1233 }
1234
convert_ifstatement(std::ifstream & infile,std::ofstream & outfile,bool condition)1235 bool localSolverClient::convert_ifstatement(std::ifstream &infile,
1236 std::ofstream &outfile,
1237 bool condition)
1238 {
1239 int level;
1240 size_t pos;
1241 std::string line;
1242
1243 bool trueclause = true;
1244 level = 1;
1245 while(infile.good() && level) {
1246 getline(infile, line);
1247 if(((pos = line.find(olkey::olelse)) != std::string::npos) && (level == 1))
1248 trueclause = false;
1249 else if((pos = line.find(olkey::olendif)) != std::string::npos)
1250 level--;
1251 else if(!(trueclause ^ condition)) // xor bitwise operator
1252 convert_oneline(line, infile, outfile);
1253 else { // check for opening if statements
1254 if((pos = line.find(olkey::iftrue)) != std::string::npos)
1255 level++;
1256 else if((pos = line.find(olkey::ifntrue)) != std::string::npos)
1257 level++;
1258 else if((pos = line.find(olkey::ifcond)) != std::string::npos)
1259 level++;
1260 }
1261 }
1262 return level ? false : true;
1263 }
1264
convert_oneline(std::string line,std::ifstream & infile,std::ofstream & outfile)1265 void localSolverClient::convert_oneline(std::string line, std::ifstream &infile,
1266 std::ofstream &outfile)
1267 {
1268 size_t pos, cursor;
1269 std::vector<std::string> arguments;
1270 std::vector<onelab::number> numbers;
1271 std::vector<onelab::string> strings;
1272
1273 if((pos = line.find_first_not_of(" \t")) == std::string::npos) {
1274 // empty line, we keep them
1275 outfile << line << std::endl;
1276 }
1277 else if(!line.compare(pos, olkey::comment.size(), olkey::comment)) {
1278 // commented out, skip the line
1279 }
1280 else if((pos = line.find(olkey::deflabel)) != std::string::npos) {
1281 // onelab.tags(label,comment,separator)
1282 cursor = pos + olkey::deflabel.length();
1283 int NumArg = enclosed(line.substr(cursor), arguments, pos);
1284 if(NumArg == 0)
1285 modify_tags("", "");
1286 else if(NumArg == 2)
1287 modify_tags(arguments[0], arguments[1]);
1288 else
1289 OLMsg::Error("Malformed <%s> statement", olkey::deflabel.c_str());
1290 }
1291 else if((pos = line.find(olkey::begin)) != std::string::npos) {
1292 // onelab.begin
1293 while(infile.good()) {
1294 getline(infile, line);
1295 if((pos = line.find(olkey::end)) != std::string::npos) return;
1296 }
1297 OLMsg::Error("Malformed <%s> block <%s>", olkey::begin.c_str(),
1298 olkey::end.c_str());
1299 }
1300 else if((pos = line.find(olkey::iftrue)) != std::string::npos) {
1301 // onelab.iftrue
1302 cursor = pos + olkey::iftrue.length();
1303 bool condition = false;
1304 if(enclosed(line.substr(cursor), arguments, pos) < 1)
1305 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::iftrue.c_str(),
1306 line.c_str());
1307 else {
1308 get(strings, longName(arguments[0]));
1309 if(strings.size())
1310 condition = strings[0].getValue().size();
1311 else {
1312 get(numbers, longName(arguments[0]));
1313 if(numbers.size())
1314 condition = (bool)numbers[0].getValue();
1315 else {
1316 OLMsg::Warning("Unknown parameter <%s> in <%s> statement",
1317 arguments[0].c_str(), olkey::iftrue.c_str());
1318 }
1319 }
1320 if(!convert_ifstatement(infile, outfile, condition))
1321 OLMsg::Error("Malformed <%s> statement: %s", olkey::iftrue.c_str(),
1322 arguments[0].c_str());
1323 }
1324 }
1325 else if((pos = line.find(olkey::ifntrue)) != std::string::npos) {
1326 // onelab.ifntrue
1327 cursor = pos + olkey::ifntrue.length();
1328 bool condition = false;
1329 if(enclosed(line.substr(cursor), arguments, pos) < 1)
1330 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::ifntrue.c_str(),
1331 line.c_str());
1332 else {
1333 get(strings, longName(arguments[0]));
1334 if(strings.size())
1335 condition = strings[0].getValue().size();
1336 else {
1337 get(numbers, longName(arguments[0]));
1338 if(numbers.size())
1339 condition = (bool)numbers[0].getValue();
1340 else {
1341 OLMsg::Warning("Unknown parameter <%s> in <%s> statement",
1342 arguments[0].c_str(), olkey::ifntrue.c_str());
1343 }
1344 }
1345 if(!convert_ifstatement(infile, outfile, !condition))
1346 OLMsg::Error("Malformed <%s> statement: %s", olkey::ifntrue.c_str(),
1347 arguments[0].c_str());
1348 }
1349 }
1350 else if((pos = line.find(olkey::ifcond)) != std::string::npos) {
1351 // onelab.ifcond
1352 cursor = pos + olkey::ifcond.length();
1353 extractLogic(line.substr(cursor), arguments);
1354 bool condition = resolveLogicExpr(arguments);
1355 if(!convert_ifstatement(infile, outfile, condition))
1356 OLMsg::Error("Malformed %s statement: <%s>", olkey::ifcond.c_str(),
1357 line.c_str());
1358 }
1359 else if((pos = line.find(olkey::include)) != std::string::npos) {
1360 // onelab.include
1361 cursor = pos + olkey::include.length();
1362 if(enclosed(line.substr(cursor), arguments, pos) < 1)
1363 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::include.c_str(),
1364 line.c_str());
1365 else {
1366 std::string filename = getWorkingDir() + resolveGetVal(arguments[0]);
1367 convert_onefile(filename, outfile);
1368 }
1369 }
1370 else if((pos = line.find(olkey::message)) != std::string::npos) {
1371 // onelab.message
1372 cursor = pos + olkey::message.length();
1373 if(enclosed(line.substr(cursor), arguments, pos) < 1)
1374 OLMsg::Error("Malformed <%s> statement: (%s)", olkey::message.c_str(),
1375 line.c_str());
1376 else {
1377 std::string msg = resolveGetVal(arguments[0]);
1378 OLMsg::Info("%s", msg.c_str());
1379 }
1380 }
1381 else if((pos = line.find(olkey::getValue)) != std::string::npos) {
1382 outfile << resolveGetVal(line) << std::endl;
1383 }
1384 else if((pos = line.find(olkey::label)) != std::string::npos) {
1385 OLMsg::Error("Unidentified onelab command in <%s>", line.c_str());
1386 }
1387 else {
1388 outfile << line << std::endl;
1389 }
1390 }
1391
preProcess(const std::string & client,const std::string & fullName)1392 void preProcess(const std::string &client, const std::string &fullName)
1393 {
1394 std::vector<std::string> split = SplitOLFileName(fullName);
1395 std::string ifileName = split[1] + split[2]; // remove heading "_" if any
1396 std::string ofileName = split[0] + split[1]; // remove trailing ".ol"
1397
1398 std::string workDir = SplitFileName(split[1])[0];
1399 localSolverClient *c = new InterfacedClient(client, "", workDir);
1400
1401 std::ifstream infile(ifileName.c_str());
1402 if(infile.is_open()) {
1403 std::ofstream outfile(ofileName.c_str());
1404 if(outfile.is_open()) {
1405 OLMsg::Info("Preprocess file <%s> into <%s>", ifileName.c_str(),
1406 ofileName.c_str());
1407 while(infile.good()) {
1408 std::string line;
1409 getline(infile, line);
1410 c->convert_oneline(line, infile, outfile);
1411 }
1412 outfile.close();
1413 }
1414 else
1415 OLMsg::Error("The file <%s> cannot be opened", ofileName.c_str());
1416 infile.close();
1417 }
1418 else
1419 OLMsg::Error("The file <%s> cannot be opened", ifileName.c_str());
1420 delete c;
1421 }
1422
convert_onefile(std::string fileName,std::ofstream & outfile)1423 void localSolverClient::convert_onefile(std::string fileName,
1424 std::ofstream &outfile)
1425 {
1426 std::ifstream infile(fileName.c_str());
1427 if(infile.is_open()) {
1428 OLMsg::Info("Convert file <%s>", fileName.c_str());
1429 while(infile.good()) {
1430 std::string line;
1431 getline(infile, line);
1432 convert_oneline(line, infile, outfile);
1433 }
1434 infile.close();
1435 }
1436 else
1437 OLMsg::Error("The file <%s> cannot be opened", fileName.c_str());
1438 }
1439
client_sentence(const std::string & name,const std::string & action,const std::vector<std::string> & arguments)1440 void localSolverClient::client_sentence(
1441 const std::string &name, const std::string &action,
1442 const std::vector<std::string> &arguments)
1443 {
1444 OLMsg::Error("The action <%s> is unknown in this context", action.c_str());
1445 }
1446
client_sentence(const std::string & name,const std::string & action,const std::vector<std::string> & arguments)1447 void MetaModel::client_sentence(const std::string &name,
1448 const std::string &action,
1449 const std::vector<std::string> &arguments)
1450 {
1451 std::vector<onelab::string> strings;
1452
1453 if(!action.compare("register")) {
1454 if(isTodo(REGISTER)) {
1455 std::string type = "", cmdl = "", host = "", rdir = "";
1456 // syntax name.register([interf...|native]{,cmdl}) ;
1457 if(!findClientByName(name)) {
1458 OLMsg::Info("Define client <%s>", name.c_str());
1459 if(arguments.size() >= 1) type.assign(resolveGetVal(arguments[0]));
1460 if(arguments.size() >= 2) cmdl.assign(resolveGetVal(arguments[1]));
1461 if(arguments.size() >= 3)
1462 OLMsg::Warning("Unused arguments for client <%s>", name.c_str());
1463
1464 // if argument 'cmdl' is empty,
1465 // 1. look on server for one remote host cmdl
1466 // defined by a previous .remote() sentence
1467 // 2. look in the .save file for a local host cmdl
1468 // 3. create an empty parameter restore control to the GUI
1469
1470 host = OLMsg::GetOnelabString(name + "/HostName");
1471 rdir = OLMsg::GetOnelabString(name + "/RemoteDir");
1472 if(cmdl.empty()) cmdl = OLMsg::GetOnelabString(name + "/CommandLine");
1473
1474 if(cmdl.empty()) {
1475 host = "localhost";
1476 if(findCommandLine(name, host))
1477 cmdl = OLMsg::GetOnelabString(name + "/CommandLine");
1478 }
1479 if(cmdl.empty()) {
1480 if(OLMsg::hasGmsh) {
1481 onelab::string str;
1482 str.setName(name + "/CommandLine");
1483 str.setKind("file");
1484 str.setVisible(true);
1485 str.setAttribute("Highlight", "Ivory");
1486 set(str);
1487 OLMsg::Error("No commandline found for client <%s>", name.c_str());
1488 }
1489 else { // asks the user in console mode
1490 std::cout << "\nONELAB: Enter pathname of the executable file for <"
1491 << name << ">" << std::endl;
1492 std::getline(std::cin, cmdl);
1493 OLMsg::SetOnelabString(name + "/CommandLine", cmdl);
1494 }
1495 }
1496 registerClient(name, type, cmdl, host, rdir);
1497 }
1498 else
1499 OLMsg::Error("Redefinition of client <%s>", name.c_str());
1500 }
1501 }
1502 else if(!action.compare("remote") || !action.compare("hostname")) {
1503 if(isTodo(REGISTER)) {
1504 std::string host = "", rdir = "";
1505 if(arguments.size() >= 1) host.assign(resolveGetVal(arguments[0]));
1506 if(arguments.size() >= 2) rdir.assign(resolveGetVal(arguments[1]));
1507 if(arguments.size() >= 3)
1508 OLMsg::Warning("Unused arguments for client <%s>", name.c_str());
1509
1510 if(host.size()) {
1511 OLMsg::SetOnelabString(name + "/HostName", host, false);
1512 if(rdir.size())
1513 OLMsg::SetOnelabString(name + "/RemoteDir", rdir, false);
1514 }
1515 else {
1516 std::string in = OLMsg::GetOnelabString(name + "/HostName");
1517 if(in.size()) {
1518 std::vector<std::string> split = SplitOLHostName(in);
1519 host = split[0];
1520 rdir = split[1];
1521 OLMsg::SetOnelabString(name + "/HostName", host, false);
1522 if(rdir.size())
1523 OLMsg::SetOnelabString(name + "/RemoteDir", rdir, false);
1524 }
1525 if(!findCommandLine(name, host)) {
1526 if(OLMsg::hasGmsh) {
1527 onelab::string str;
1528 str.setName(name + "/HostName");
1529 str.setVisible(true);
1530 str.setAttribute("Highlight", "Ivory");
1531 set(str);
1532 OLMsg::Error("No hostname found for remote client <%s>",
1533 name.c_str());
1534 }
1535 else { // asks the user in console mode
1536 std::cout << "\nONELAB: Enter remote host for <" << name
1537 << "> (name@host:dir)" << std::endl;
1538 std::string in;
1539 std::getline(std::cin, in);
1540 if(in.size()) {
1541 std::vector<std::string> split = SplitOLHostName(in);
1542 OLMsg::SetOnelabString(name + "/HostName", split[0], false);
1543 if(split[1].size())
1544 OLMsg::SetOnelabString(name + "/RemoteDir", split[1], false);
1545 }
1546 }
1547 }
1548 }
1549 }
1550 }
1551 else if(!action.compare("workingSubdir")) {
1552 localSolverClient *c;
1553 if((c = findClientByName(name)))
1554 c->setWorkingDir(c->getWorkingDir() + arguments[0]);
1555 else
1556 OLMsg::Error("Unknown client <%s>", name.c_str());
1557 }
1558 else if(!action.compare("active")) {
1559 localSolverClient *c;
1560 if(arguments[0].size()) {
1561 if((c = findClientByName(name))) {
1562 c->setActive(atof(resolveGetVal(arguments[0]).c_str()));
1563 // onelab::server::instance()->setChanged(true, c->getName());
1564 }
1565 else
1566 OLMsg::Error("Unknown client <%s>", name.c_str());
1567 }
1568 else
1569 OLMsg::Error("No argument for <%s.Active> statement", name.c_str());
1570 }
1571 else if(!action.compare("in")) {
1572 if(isTodo(REGISTER)) {
1573 get(strings, name + "/InputFiles");
1574 if(strings.empty()) {
1575 strings.resize(1);
1576 strings[0].setName(name + "/InputFiles");
1577 }
1578 strings[0].setKind("file");
1579 strings[0].setVisible(false);
1580 std::vector<std::string> choices;
1581 if(arguments[0].size()) {
1582 for(unsigned int i = 0; i < arguments.size(); i++) {
1583 std::string fileName = resolveGetVal(arguments[i]);
1584 if(std::find(choices.begin(), choices.end(), fileName) ==
1585 choices.end())
1586 choices.push_back(fileName);
1587 }
1588 strings[0].setValue(resolveGetVal(arguments[0]));
1589 }
1590 strings[0].setChoices(choices);
1591 set(strings[0]);
1592 }
1593 }
1594 else if(!action.compare("out")) {
1595 if(isTodo(REGISTER)) {
1596 get(strings, name + "/OutputFiles");
1597 if(strings.empty()) {
1598 strings.resize(1);
1599 strings[0].setName(name + "/OutputFiles");
1600 }
1601 strings[0].setKind("file");
1602 strings[0].setVisible(false);
1603 std::vector<std::string> choices;
1604 if(arguments[0].size()) {
1605 for(unsigned int i = 0; i < arguments.size(); i++) {
1606 std::string fileName = resolveGetVal(arguments[i]);
1607 if(std::find(choices.begin(), choices.end(), fileName) ==
1608 choices.end())
1609 choices.push_back(fileName);
1610 }
1611 strings[0].setValue(resolveGetVal(arguments[0]));
1612 }
1613 strings[0].setChoices(choices);
1614 set(strings[0]);
1615 }
1616 }
1617 else if(!action.compare("run")) {
1618 if(isTodo(REGISTER)) {
1619 if(arguments[0].size()) {
1620 get(strings, name + "/Arguments");
1621 if(strings.empty()) {
1622 strings.resize(1);
1623 strings[0].setName(name + "/Arguments");
1624 }
1625 strings[0].setValue(resolveGetVal(arguments[0]));
1626 strings[0].setVisible(false);
1627 set(strings[0]);
1628 }
1629 if(!OLMsg::GetErrorCount()) {
1630 localSolverClient *c;
1631 if((c = findClientByName(name)))
1632 if(c->checkCommandLine()) c->analyze();
1633 }
1634 }
1635 else if(isTodo(ANALYZE)) {
1636 localSolverClient *c;
1637 if((c = findClientByName(name))) c->analyze();
1638 }
1639 else if(isTodo(COMPUTE)) {
1640 localSolverClient *c;
1641 if((c = findClientByName(name))) {
1642 // onelab::server::instance()->setChanged(false, getName());
1643 bool changed = onelab::server::instance()->getChanged(c->getName());
1644 bool started = isStarted(changed);
1645
1646 // if(OLMsg::GetVerbosity())
1647 // std::cout << c->getName() << " active="
1648 // << c->getActive() << " changed="
1649 // << changed << " started="
1650 // << started << " errors=" << OLMsg::GetErrorCount() << std::endl;
1651 if(c->getActive() || started) c->compute();
1652 }
1653 }
1654 }
1655 else if(!action.compare("up")) {
1656 if(arguments.size() % 4 == 0) {
1657 if(isTodo(REGISTER)) {}
1658 else if(isTodo(COMPUTE) && !OLMsg::GetErrorCount()) {
1659 std::vector<std::string> choices;
1660 for(unsigned int i = 0; i < arguments.size(); i++) {
1661 std::string str = resolveGetVal(arguments[i]);
1662 OLMsg::recordFullName(str);
1663 choices.push_back(str);
1664 }
1665 localSolverClient *c;
1666 if((c = findClientByName(name))) c->PostArray(choices);
1667 }
1668 }
1669 else
1670 OLMsg::Error("Wrong number of arguments <%d> for <%s>", arguments.size(),
1671 action.c_str());
1672 }
1673 else if(!action.compare("alwaysCompute") || !action.compare("preCompute")) {
1674 if(isTodo(REGISTER)) {
1675 localSolverClient *c;
1676 if((c = findClientByName(name))) {
1677 c->compute();
1678 // onelab::server::instance()->setChanged(false, c->getName());
1679 }
1680 else
1681 OLMsg::Error("Unknown client <%s>", name.c_str());
1682 }
1683 }
1684 else if(!action.compare("merge")) {
1685 if(arguments.size() && isTodo(COMPUTE) && !OLMsg::GetErrorCount() &&
1686 (OLMsg::hasGmsh)) {
1687 std::vector<std::string> choices;
1688 for(unsigned int i = 0; i < arguments.size(); i++) {
1689 choices.push_back(resolveGetVal(arguments[i]));
1690 }
1691 localSolverClient *c;
1692 if((c = findClientByName(name))) {
1693 c->GmshMerge(choices);
1694 OLMsg::SetOnelabNumber("Gmsh/NeedReloadGeom", 1, false);
1695 }
1696 else
1697 OLMsg::Error("Unknown client <%s>", name.c_str());
1698 }
1699 }
1700 else if(!action.compare("frontPage")) {
1701 if(isTodo(REGISTER) && OLMsg::hasGmsh && arguments.size() &&
1702 !OLMsg::GetErrorCount()) {
1703 std::vector<std::string> choices;
1704 for(unsigned int i = 0; i < arguments.size(); i++) {
1705 choices.push_back(resolveGetVal(arguments[i]));
1706 }
1707 localSolverClient *c;
1708 if((c = findClientByName(name))) {
1709 c->GmshMerge(choices);
1710 OLMsg::SetOnelabNumber("Gmsh/NeedReloadGeom", 1, false);
1711 }
1712 else
1713 OLMsg::Error("Unknown client <%s>", name.c_str());
1714 }
1715 }
1716 else if(!action.compare("clientStatus")) {
1717 showClientStatus();
1718 }
1719 else
1720 OLMsg::Error("Unknown action <%s>", action.c_str());
1721 }
1722