25#define XNAME_LENGTH 256
64 char c1, c2, *ps, *pp;
66 if (
str == NULL || pattern == NULL)
71 pp = (
char *) pattern;
74 if (toupper(c1) == toupper(c2)) {
79 if (toupper(c1) != toupper(c2))
97void strsubst(
char *
string,
int size,
const char *pattern,
const char *subst)
104 for (p =
stristr(p, pattern); p != NULL; p =
stristr(p, pattern)) {
106 if (strlen(pattern) == strlen(subst)) {
107 memcpy(p, subst, strlen(subst));
108 }
else if (strlen(pattern) > strlen(subst)) {
109 memcpy(p, subst, strlen(subst));
110 memmove(p + strlen(subst), p + strlen(pattern), strlen(p + strlen(pattern)) + 1);
112 tail = (
char *) malloc(strlen(p) - strlen(pattern) + 1);
113 strcpy(tail, p + strlen(pattern));
114 s = size - (p - string);
115 mstrlcpy(p, subst, s);
116 mstrlcat(p, tail, s);
129 snprintf(buf,
sizeof(buf),
"%d", v);
133static std::string
qtoString(std::string filename,
int line,
int level) {
134 std::string buf =
"l=\"" + std::to_string(line) +
"\"";
135 buf +=
" fn=\"" + filename +
"\"";
137 buf +=
" lvl=\"" + std::to_string(level) +
"\"";
141static std::string
q(
const char *s) {
142 return "\"" + std::string(s) +
"\"";
149 std::stringstream ss;
155 else if (num == 0 && s[0] !=
'0')
181 cm_msg(
MTALK,
"sequencer",
"Sequencer has stopped with error.");
201 for (
i = 0; *p &&
i < size;
i++) {
202 if (*p ==
'"' && !ignore_quotes) {
208 if (*p ==
'"' && *(p + 1) ==
'"') {
211 }
else if (*p ==
'"') {
225 if (*p && strchr(brk, *p))
233 for (
j = 0;
j < (int) strlen(
list[
i]);
j++)
234 if (strchr(brk,
list[
i][
j])) {
239 p += strlen(
list[
i]);
242 if (*p && strchr(brk, *p))
263extern char *
stristr(
const char *
str,
const char *pattern);
271 xpath +=
c->odb_path;
280 while ((i1 = (
int)result.find(
"$")) != (
int)std::string::npos) {
281 std::string s = result.substr(i1 + 1);
282 if (std::isdigit(s[0])) {
284 for (i2 = i1 + 1; std::isdigit(result[i2]);)
288 int index = atoi(s.c_str());
291 std::vector<std::string>
param;
293 while (std::getline(f, sp,
','))
296 throw "Parameter \"$" + std::to_string(
index) +
"\" not valid";
298 if (vsubst[0] ==
'$')
301 throw "Parameter \"$" + std::to_string(
index) +
"\" not valid";
304 for (i2 = i1 + 1; std::isalnum(result[i2]) || result[i2] ==
'_';)
306 s = s.substr(0, i2 - i1 - 1);
307 if (result[i2] ==
'[') {
309 auto sindex = result.substr(i2+1);
310 int i = sindex.find(
']');
311 if (
i == (
int)std::string::npos)
312 throw "Variable \"" + result +
"\" does not contain ']'";
313 sindex = sindex.substr(0,
i);
317 index = std::stoi(sindex);
319 throw "Variable \"" + s +
"\" has invalid index";
324 std::vector<std::string> sv = o;
327 throw "Variable \"" + s +
"\" not found";
329 while (result[i2] && result[i2] !=
']')
332 throw "Variable \"" + result +
"\" does not contain ']'";
333 if (result[i2] ==
']')
338 throw "Variable \"" + s +
"\" not found";
342 throw "Variable \"" + s +
"\" not found";
347 result = result.substr(0, i1) + vsubst + result.substr(i2);
353 if (result.find(
",") != std::string::npos)
358 double r =
te_interp(result.c_str(), &error);
361 if (!std::isdigit(result[0]) && result[0] !=
'-')
364 throw "Error in expression \"" + result +
"\" position " + std::to_string(error - 1);
368 return std::to_string((
int) r);
370 return std::to_string(r);
382 for (
i = 0;
i <
n;
i++) {
384 mstrlcat(result,
str.c_str(), size);
394 double value1, value2;
395 char value1_str[256], value2_str[256],
str[256], op[3], *p;
396 std::string value1_var, value2_var;
399 p = (
char *)condition;
405 if (strchr(
str,
'#'))
406 *strchr(
str,
'#') = 0;
408 while (strlen(
str) > 0 && (
str[strlen(
str)-1] ==
' '))
412 if (
str[0] ==
'(' && strlen(
str) > 0 &&
str[strlen(
str)-1] ==
')') {
413 mstrlcpy(value1_str,
str+1,
sizeof(value1_str));
414 mstrlcpy(
str, value1_str,
sizeof(
str));
421 for (
i = 0;
i < (int) strlen(
str);
i++)
422 if (strchr(
"<>=!&",
str[
i]) != NULL)
424 mstrlcpy(value1_str,
str,
i + 1);
425 while (value1_str[strlen(value1_str) - 1] ==
' ')
426 value1_str[strlen(value1_str) - 1] = 0;
428 if (strchr(
"<>=!&",
str[
i + 1]) != NULL)
431 for (
i++;
str[
i] ==
' ';
i++);
432 mstrlcpy(value2_str,
str +
i,
sizeof(value2_str));
434 value1_var =
eval_var(seq,
c, value1_str);
435 value2_var =
eval_var(seq,
c, value2_str);
439 if (strcmp(op,
"=") == 0)
440 return equal_ustring(value1_var.c_str(), value2_var.c_str()) ? 1 : 0;
441 if (strcmp(op,
"==") == 0)
442 return equal_ustring(value1_var.c_str(), value2_var.c_str()) ? 1 : 0;
443 if (strcmp(op,
"!=") == 0)
444 return equal_ustring(value1_var.c_str(), value2_var.c_str()) ? 0 : 1;
450 value1 = atof(value1_var.c_str());
451 value2 = atof(value2_var.c_str());
454 if (strcmp(op,
"=") == 0)
455 if (value1 == value2)
457 if (strcmp(op,
"==") == 0)
458 if (value1 == value2)
460 if (strcmp(op,
"!=") == 0)
461 if (value1 != value2)
463 if (strcmp(op,
"<") == 0)
466 if (strcmp(op,
">") == 0)
469 if (strcmp(op,
"<=") == 0)
470 if (value1 <= value2)
472 if (strcmp(op,
">=") == 0)
473 if (value1 >= value2)
475 if (strcmp(op,
"&") == 0)
476 if (((
unsigned int) value1 & (
unsigned int) value2) > 0)
484bool loadMSL(MVOdb *o,
const std::string &filename) {
486 std::ifstream
file(filename);
490 std::vector<std::string> lines;
494 while (std::getline(
file, line))
495 lines.push_back(line);
498 o->WSA(
"Script/Lines", lines, 0);
506 char *error,
int error_size,
int *error_line) {
507 char str[256], *pl, *pe;
509 int i,
j,
n, nq, n_lines, endl, line, nest, incl, library;
510 std::string xml, path, fn;
511 char *msl_include, *xml_include, *include_error;
512 int include_error_size;
513 BOOL include_status, rel_path;
516 snprintf(error, error_size,
"More than 10 nested INCLUDE statements exceeded in file \"%s\"", filename);
521 path = std::string(cpath);
522 if (path.length() > 0 && path.back() !=
'/')
525 std::string fullFilename;
527 fullFilename = path + filename;
529 fullFilename = filename;
531 int fhin = open(fullFilename.c_str(), O_RDONLY |
O_TEXT);
533 snprintf(error, error_size,
"Cannot open \"%s\", errno %d (%s)", fullFilename.c_str(), errno, strerror(errno));
537 off_t off = lseek(fhin, 0, SEEK_END);
539 snprintf(error, error_size,
"Cannot find size of \"%s\", lseek(SEEK_END) errno %d (%s)", fullFilename.c_str(), errno, strerror(errno));
544 lseek(fhin, 0, SEEK_SET);
548 s = path + xml_filename;
552 FILE *fout = fopen(s.c_str(),
"wt");
554 snprintf(error, error_size,
"Cannot write to \"%s\", fopen() errno %d (%s)", s.c_str(), errno, strerror(errno));
561 char* buf = (
char *) malloc(size + 1);
562 ssize_t rd =
read(fhin, buf, size);
565 snprintf(error, error_size,
"Cannot read \"%s\", read(%zu) errno %d (%s)", fullFilename.c_str(), size, errno, strerror(errno));
575 lines = (
char **) malloc(
sizeof(
char *));
579 for (n_lines = 0; *pl; n_lines++) {
580 lines = (
char **) realloc(lines,
sizeof(
char *) * (n_lines + 1));
582 if (strchr(pl,
'\n')) {
583 pe = strchr(pl,
'\n');
585 if (*(pe - 1) ==
'\r') {
590 pe = pl + strlen(pl);
591 mstrlcpy(
str, pl,
sizeof(
str));
596 xml +=
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
597 xml +=
"<!DOCTYPE RunSequence [\n";
602 char *reference = strrchr(
list[1],
'/');
608 if (strchr(reference,
'.') && !strstr(reference,
".msl") && !strstr(reference,
".MSL")) {
609 snprintf(error, error_size,
"Include file \"%s\" cannot have an extension other than .msl", reference);
614 if (
list[1][0] ==
'/') {
616 p +=
"userfiles/sequencer";
620 if (!p.empty() && p.back() !=
'/')
632 size = p.length() + 1 + 4;
633 msl_include = (
char *) malloc(size);
634 xml_include = (
char *) malloc(size);
635 mstrlcpy(msl_include, p.c_str(), size);
636 mstrlcpy(xml_include, p.c_str(), size);
637 if (!strstr(msl_include,
".msl"))
638 mstrlcat(msl_include,
".msl", size);
639 mstrlcat(xml_include,
".xml", size);
641 include_error = error + strlen(error);
642 include_error_size = error_size - strlen(error);
645 path +=
"userfiles/sequencer/";
648 include_status =
msl_parse(seq,
c, level+1, path.c_str(), msl_include, xml_include, include_error, include_error_size, error_line);
652 if (!include_status) {
654 *error_line = n_lines + 1;
659 xml +=
"<Library name=\"";
667 }
else if (!library) {
668 xml +=
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
673 xml +=
"<RunSequence xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"\">\n";
676 std::vector<std::string> slines;
677 for (line = 0; line < n_lines; line++) {
678 slines.push_back(lines[line]);
681 c->odbs->WSA(
"Script/Lines", slines, 0);
684 std::string p =
"/" +
c->odb_path +
"/Param/Value";
691 c->odbs->Delete(
"Variables");
692 c->odbs->Delete(
"Param");
695 for (line = 0; line < n_lines; line++) {
696 char *p = lines[line];
699 mstrlcpy(
list[0], p,
sizeof(
list[0]));
700 if (strchr(
list[0],
' '))
701 *strchr(
list[0],
' ') = 0;
702 p += strlen(
list[0]);
706 for (
i = 0;
i <
n;
i++) {
707 if (
list[
i][0] ==
'#') {
708 for (
j =
i;
j <
n;
j++)
715 for (
i = 0;
i <
n;
i++) {
716 if (strchr(
list[
i],
'#'))
717 *strchr(
list[
i],
'#') = 0;
721 for (
i = 0;
i <
n;
i++) {
728 mstrlcpy(
eq, lines[line],
sizeof(
eq));
730 *strchr(
eq,
'#') = 0;
731 for (
i = 0,
n = 0, nq = 0;
i < (int)strlen(
eq);
i++) {
733 nq = (nq == 0 ? 1 : 0);
734 if (
eq[
i] ==
'=' && nq == 0 &&
735 (
i > 0 && (
eq[
i - 1] !=
'!') &&
eq[
i - 1] !=
'<' &&
eq[
i - 1] !=
'>'))
738 if (
n == 1 &&
eq[0] !=
'=') {
740 mstrlcpy(
list[0],
"SET",
sizeof(
list[0]));
744 mstrlcpy(
list[1], p,
sizeof(
list[1]));
745 *strchr(
list[1],
'=') = 0;
746 if (strchr(
list[1],
' '))
747 *strchr(
list[1],
' ') = 0;
748 p = strchr(
eq,
'=')+1;
751 mstrlcpy(
list[2], p,
sizeof(
list[2]));
752 while (strlen(
list[2]) > 0 &&
list[2][strlen(
list[2])-1] ==
' ')
760 char *reference = strrchr(
list[1],
'/');
771 xml +=
"<Call " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
">";
772 for (
i = 2;
i < 100 &&
list[
i][0];
i++) {
781 xml +=
"<Cat " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
">";
782 for (
i = 2;
i < 100 &&
list[
i][0];
i++) {
791 xml +=
"<Comment " +
qtoString(fullFilename, line + 1, level) +
">" +
list[1] +
"</Comment>\n";
794 xml +=
"<Exit " +
qtoString(fullFilename, line + 1, level) +
" />\n";
797 xml +=
"<Goto " +
qtoString(fullFilename, line + 1, level) +
" sline=" +
q(
list[1]) +
" />\n";
800 xml +=
"<If " +
qtoString(fullFilename, line + 1, level) +
" condition=\"";
801 for (
i = 1;
i < 100 &&
list[
i][0] && stricmp(
list[
i],
"THEN") != 0;
i++) {
814 for (
i = line, nest = 0;
i < n_lines;
i++) {
828 if (
list[2][0] == 0) {
829 xml +=
"<Loop " +
qtoString(fullFilename, line + 1, level) +
" le=\"" + std::to_string(endl) +
"\" n=" +
q(
list[1]) +
">\n";
830 }
else if (
list[3][0] == 0) {
831 xml +=
"<Loop " +
qtoString(fullFilename, line + 1, level) +
" le=\"" + std::to_string(endl) +
"\" var=" +
q(
list[1]) +
" n=" +
834 xml +=
"<Loop " +
qtoString(fullFilename, line + 1, level) +
" le=\"" + std::to_string(endl) +
"\" var=" +
q(
list[1]) +
" values=\"";
835 for (
i = 2;
i < 100 &&
list[
i][0];
i++) {
847 xml +=
"<Break "+
qtoString(fullFilename, line + 1, level) +
"></Break>\n";
850 xml +=
"<Message " +
qtoString(fullFilename, line + 1, level);
851 if (
list[2][0] ==
'1')
852 xml +=
" wait=\"1\"";
855 xml +=
"</Message>\n";
859 xml +=
"<Msg " +
qtoString(fullFilename, line + 1, level) +
" type=\""+
list[2]+
"\">" +
list[1] +
"</Msg>\n";
861 xml +=
"<Msg " +
qtoString(fullFilename, line + 1, level) +
">" +
list[1] +
"</Msg>\n";
866 mstrlcpy(
list[2],
"1", 2);
867 xml +=
"<ODBInc " +
qtoString(fullFilename, line + 1, level) +
" path=" +
q(
list[1]) +
">" +
list[2] +
"</ODBInc>\n";
871 xml +=
"<ODBCreate " +
qtoString(fullFilename, line + 1, level) +
" size=" +
q(
list[3]) +
" path=" +
q(
list[1]) +
" type=" +
872 q(
list[2]) +
"></ODBCreate>\n";
874 xml +=
"<ODBCreate " +
qtoString(fullFilename, line + 1, level) +
" path=" +
q(
list[1]) +
" type=" +
q(
list[2]) +
879 xml +=
"<ODBDelete " +
qtoString(fullFilename, line + 1, level) +
">" +
list[1] +
"</ODBDelete>\n";
883 xml +=
"<ODBSet " +
qtoString(fullFilename, line + 1, level) +
" notify=" +
q(
list[3]) +
" path=" +
q(
list[1]) +
">" +
884 list[2] +
"</ODBSet>\n";
886 xml +=
"<ODBSet " +
qtoString(fullFilename, line + 1, level) +
" path=" +
q(
list[1]) +
">" +
list[2] +
"</ODBSet>\n";
891 xml +=
"<ODBLoad " +
qtoString(fullFilename, line + 1, level) +
" path=" +
q(
list[2]) +
">" +
list[1] +
"</ODBLoad>\n";
893 xml +=
"<ODBLoad " +
qtoString(fullFilename, line + 1, level) +
">" +
list[1] +
"</ODBLoad>\n";
897 xml +=
"<ODBGet " +
qtoString(fullFilename, line + 1, level) +
" path=" +
q(
list[1]) +
">" +
list[2] +
"</ODBGet>\n";
900 xml +=
"<ODBLookup " +
qtoString(fullFilename, line + 1, level) +
" path=" +
q(
list[1]) +
901 " string=" +
q(
list[2]) +
">" +
list[3] +
"</ODBLookup>\n";
904 xml +=
"<ODBSave " +
qtoString(fullFilename, line + 1, level) +
" path=" +
q(
list[1]) +
">" +
list[2] +
"</ODBSave>\n";
908 xml +=
"<ODBSubdir " +
qtoString(fullFilename, line + 1, level) +
" notify=" +
q(
list[2]) +
" path=" +
q(
list[1]) +
">\n";
910 xml +=
"<ODBSubdir " +
qtoString(fullFilename, line + 1, level) +
" path=" +
q(
list[1]) +
">\n";
913 xml +=
"</ODBSubdir>\n";
917 snprintf(error, error_size,
"Parameter \"%s\" misses 'comment'",
list[1]);
918 *error_line = line + 1;
922 xml +=
"<Param " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
" type=\"bool\" " +
" comment=" +
q(
list[2]) +
"/>\n";
924 c->odbs->RB((std::string(
"Param/Value/") +
list[1]).c_str(), &v,
true);
925 c->odbs->WS((std::string(
"Param/Comment/") +
list[1]).c_str(),
list[2]);
927 xml +=
"<Param " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
" type=\"bool\" default=" +
q(
list[4]) +
"/>\n";
928 std::string def(
list[3]);
929 bool v(def ==
"1" || def ==
"true" || def ==
"TRUE");
930 c->odbs->RB((std::string(
"Param/Value/") +
list[1]).c_str(), &v,
true);
931 c->odbs->WS((std::string(
"Param/Comment/") +
list[1]).c_str(),
list[2]);
932 c->odbs->WS((std::string(
"Param/Defaults/") +
list[1]).c_str(),
list[3]);
934 }
else if (!
list[3][0]) {
935 xml +=
"<Param " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
" comment=" +
q(
list[2]) +
" />\n";
937 c->odbs->RS((std::string(
"Param/Value/") +
list[1]).c_str(), &v,
true);
938 c->odbs->WS((std::string(
"Param/Comment/") +
list[1]).c_str(),
list[2]);
939 }
else if (!
list[4][0]) {
940 xml +=
"<Param " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
" comment=" +
q(
list[2]) +
" default=" +
q(
list[3]) +
" />\n";
941 std::string v(
list[3]);
942 c->odbs->RS((std::string(
"Param/Value/") +
list[1]).c_str(), &v,
true);
943 c->odbs->WS((std::string(
"Param/Comment/") +
list[1]).c_str(),
list[2]);
944 c->odbs->WS((std::string(
"Param/Defaults/") +
list[1]).c_str(),
list[3]);
947 xml +=
"<Param " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
" comment=" +
q(
list[2]) +
950 c->odbs->RS((std::string(
"Param/Value/") +
list[1]).c_str(), &v,
true);
951 c->odbs->WS((std::string(
"Param/Comment/") +
list[1]).c_str(),
list[2]);
952 std::vector<std::string> options;
953 for (
i = 3;
i < 100 &&
list[
i][0];
i++) {
958 options.push_back(
list[
i]);
961 c->odbs->WSA((std::string(
"Param/Options/") +
list[1]).c_str(), options, 0);
966 std::string ov = oldSeqParam[(
const char *)
list[1]];
967 c->odbs->WS((std::string(
"Param/Value/") +
list[1]).c_str(), ov.c_str());
971 xml +=
"<RunDescription " +
qtoString(fullFilename, line + 1, level) +
">" +
list[1] +
"</RunDescription>\n";
974 if (
list[2][0] == 0) {
975 xml +=
"<Script " +
qtoString(fullFilename, line + 1, level) +
">" +
list[1] +
"</Script>\n";
977 xml +=
"<Script " +
qtoString(fullFilename, line + 1, level) +
" params=\"";
978 for (
i = 2;
i < 100 &&
list[
i][0];
i++) {
986 xml +=
"</Script>\n";
990 xml +=
"<Set " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
">" +
list[2] +
"</Set>\n";
993 xml +=
"\n<Subroutine " +
qtoString(fullFilename, line + 1, level) +
" name=" +
q(
list[1]) +
">\n";
996 xml +=
"</Subroutine>\n";
999 xml +=
"<Transition " +
qtoString(fullFilename, line + 1, level) +
">" +
list[1] +
"</Transition>\n";
1003 xml +=
"<Wait " +
qtoString(fullFilename, line + 1, level) +
" for=\"seconds\">" +
list[1] +
"</Wait>\n";
1004 }
else if (!
list[3][0]) {
1005 xml +=
"<Wait " +
qtoString(fullFilename, line + 1, level) +
" for=" +
q(
list[1]) +
">" +
list[2] +
"</Wait>\n";
1007 xml +=
"<Wait " +
qtoString(fullFilename, line + 1, level) +
" for=" +
q(
list[1]) +
" path=" +
q(
list[2]) +
" op=" +
1008 q(
list[3]) +
">" +
list[4] +
"</Wait>\n";
1011 }
else if (
list[0][0] == 0 ||
list[0][0] ==
'#') {
1014 snprintf(error, error_size,
"Invalid command \"%s\"",
list[0]);
1015 *error_line = line + 1;
1023 xml +=
"\n</Library>\n";
1025 xml +=
"</RunSequence>\n";
1029 fprintf(fout,
"%s", xml.c_str());
1043 cm_msg(
MERROR,
"seq_read",
"Cannot find /Sequencer/State in ODB, db_find_key() status %d",
status);
1050 cm_msg(
MERROR,
"seq_read",
"Cannot get /Sequencer/State from ODB, db_get_record1() status %d",
status);
1061 cm_msg(
MERROR,
"seq_write",
"Cannot find /Sequencer/State in ODB, db_find_key() status %d",
status);
1066 cm_msg(
MERROR,
"seq_write",
"Cannot write to ODB /Sequencer/State, db_set_record() status %d",
status);
1126 midas::odb defaults(std::string(
"/") +
c->odb_path +
"/Param/Defaults");
1128 midas::odb vars(std::string(
"/") +
c->odb_path +
"/Variables");
1132 if (!
param.is_subkey(
d.get_name())) {
1133 mstrlcpy(seq.
error,
"Cannot start script because /Sequencer/Param/Value is incomplete",
sizeof(seq.
error));
1135 cm_msg(
MERROR,
"sequencer",
"Cannot start script because /Sequencer/Param/Value is incomplete");
1141 vars[p.get_name()] = p.
s();
1144 mstrlcpy(seq.
error,
"Cannot start script, no script loaded",
sizeof(seq.
error));
1158 cm_msg(
MTALK,
"sequencer",
"Sequencer started with script \"%s\" in debugging mode.", seq.
filename);
1170 path +=
"userfiles/sequencer/";
1214 for (
int i = 1;
i < mxml_get_line_number_end(mxml_find_node(
c->pnseq,
"RunSequence"));
i++) {
1215 PMXML_NODE pt = mxml_get_node_at_line(
c->pnseq,
i);
1218 if (
equal_ustring(mxml_get_attribute(pt,
"name"),
"ATEXIT")) {
1221 seq_error(seq,
c,
"Maximum subroutine level exceeded");
1268 mxml_free_tree(
c->pnseq);
1271 c->odbs->WS(
"Script/Lines",
"");
1274 int size = (int)strlen(
str) + 1;
1275 char *xml_filename = (
char *) malloc(size);
1276 mstrlcpy(xml_filename,
str, size);
1277 strsubst(xml_filename, size,
".msl",
".xml");
1281 path +=
"userfiles/sequencer/";
1283 if (xml_filename[0] ==
'/') {
1284 path += xml_filename;
1285 path = path.substr(0, path.find_last_of(
'/') + 1);
1286 mstrlcpy(xml_filename, path.substr(path.find_last_of(
'/') + 1).c_str(), size);
1293 std::string fn(path);
1294 if (!fn.empty() && fn.back() !=
'/')
1314 for (
int i=0 ;
i<9 ;
i++)
1333 if (
c->seqp->new_file) {
1334 mstrlcpy(
str,
c->seqp->path,
sizeof(
str));
1337 mstrlcat(
str,
c->seqp->filename,
sizeof(
str));
1355 bool start_script =
false;
1356 bool stop_immediately =
false;
1357 bool stop_after_run =
false;
1358 bool cancel_stop_after_run =
false;
1359 bool pause_script =
false;
1360 bool resume_script =
false;
1361 bool debug_script =
false;
1362 bool step_over =
false;
1363 bool load_new_file =
false;
1365 c->odbs->RB(
"Command/Start script", &start_script);
1366 c->odbs->RB(
"Command/Stop immediately", &stop_immediately);
1367 c->odbs->RB(
"Command/Stop after run", &stop_after_run);
1368 c->odbs->RB(
"Command/Cancel stop after run", &cancel_stop_after_run);
1369 c->odbs->RB(
"Command/Pause script", &pause_script);
1370 c->odbs->RB(
"Command/Resume script", &resume_script);
1371 c->odbs->RB(
"Command/Debug script", &debug_script);
1372 c->odbs->RB(
"Command/Step over", &step_over);
1373 c->odbs->RB(
"Command/Load new file", &load_new_file);
1375 if (load_new_file) {
1376 std::string filename;
1377 c->odbs->RS(
"State/Filename", &filename);
1381 if (filename.find(
"..") != std::string::npos) {
1382 mstrlcpy(seqp->
error,
"Cannot load \"",
sizeof(seqp->
error));
1383 mstrlcat(seqp->
error, filename.c_str(),
sizeof(seqp->
error));
1384 mstrlcat(seqp->
error,
"\": file names with \"..\" is not permitted",
sizeof(seqp->
error));
1386 }
else if (filename.find(
".msl") == std::string::npos) {
1387 mstrlcpy(seqp->
error,
"Cannot load \"",
sizeof(seqp->
error));
1388 mstrlcat(seqp->
error, filename.c_str(),
sizeof(seqp->
error));
1389 mstrlcat(seqp->
error,
"\": file name should end with \".msl\"",
sizeof(seqp->
error));
1394 if (path.length() > 0 && path.back() !=
'/') {
1405 c->odbs->WB(
"Command/Load new file",
false);
1411 c->odbs->WB(
"Command/Start script",
false);
1413 bool seq_running =
false;
1414 c->odbs->RB(
"State/running", &seq_running);
1419 cm_msg(
MTALK,
"sequencer",
"Sequencer is already running");
1423 if (stop_immediately) {
1425 c->odbs->WB(
"Command/Stop immediately",
false);
1427 cm_msg(
MTALK,
"sequencer",
"Sequencer is finished by \"stop immediately\".");
1429 c->odbs->WB(
"Command/Stop immediately",
false);
1430 cm_msg(
MTALK,
"sequencer",
"Sequencer received \"stop immediately\". Executing ATEXIT.");
1434 if (stop_after_run) {
1435 c->odbs->WB(
"Command/Stop after run",
false);
1439 if (cancel_stop_after_run) {
1440 c->odbs->WB(
"Command/Cancel stop after run",
false);
1446 c->odbs->WB(
"Command/Pause script",
false);
1447 cm_msg(
MTALK,
"sequencer",
"Sequencer is paused.");
1450 if (resume_script) {
1452 c->odbs->WB(
"Command/Resume script",
false);
1453 cm_msg(
MTALK,
"sequencer",
"Sequencer is resumed.");
1457 c->odbs->WB(
"Command/Debug script",
false);
1459 bool seq_running =
false;
1460 c->odbs->RB(
"State/running", &seq_running);
1465 cm_msg(
MTALK,
"sequencer",
"Sequencer is already running");
1471 c->odbs->WB(
"Command/Step over",
false);
1480 *index1 = *index2 = 0;
1481 if (odbpath[strlen(odbpath) - 1] ==
']') {
1482 if (strchr(odbpath,
'[')) {
1484 if (strchr((strchr(odbpath,
'[') + 1),
'$')) {
1485 mstrlcpy(
str, strchr(odbpath,
'[') + 1,
sizeof(
str));
1486 if (strchr(
str,
']'))
1487 *strchr(
str,
']') = 0;
1490 *strchr(odbpath,
'[') = 0;
1507 std::vector<HNDLE> keys;
1515 size =
sizeof(
data);
1548 PMXML_NODE
pn, pr, pt, pe;
1549 char odbpath[256],
data[256],
str[1024],
name[32], op[32];
1552 int i,
j, l,
n,
status, size, index1, index2,
state,
run_number, cont;
1563 if (
c->pnseq == NULL) {
1565 mstrlcpy(seq.
error,
"No script loaded",
sizeof(seq.
error));
1580 pr = mxml_find_node(
c->pnseq,
"RunSequence");
1582 seq_error(seq,
c,
"Cannot find <RunSequence> tag in XML file");
1586 int last_line = mxml_get_line_number_end(pr);
1596 cm_msg(
MTALK,
"sequencer",
"Sequencer is finished.");
1616 cm_msg(
MTALK,
"sequencer",
"Sequencer is finished.");
1642 if (mxml_get_attribute(
pn,
"var")) {
1643 mstrlcpy(
name, mxml_get_attribute(
pn,
"var"),
sizeof(
name));
1644 if (mxml_get_attribute(
pn,
"values")) {
1645 mstrlcpy(
data, mxml_get_attribute(
pn,
"values"),
sizeof(
data));
1648 }
else if (mxml_get_attribute(
pn,
"n")) {
1651 sprintf(
str,
"Variables/%s",
name);
1652 size =
value.length() + 1;
1703 if (mxml_get_attribute(
pn,
"l"))
1705 if (mxml_get_attribute(
pn,
"fn")) {
1706 std::string filename = mxml_get_attribute(
pn,
"fn");
1709 if (filename != std::string(seq.
sfilename)) {
1715 if (mxml_get_attribute(
pn,
"l") && (!mxml_get_attribute(
pn,
"lvl") || atoi(mxml_get_attribute(
pn,
"lvl")) == 0))
1724 midas::odb o(
"/" +
c->odb_path +
"/Script/Lines");
1739 if (!mxml_get_attribute(
pn,
"path")) {
1740 seq_error(seq,
c,
"Missing attribute \"path\"");
1743 std::string s = mxml_get_attribute(
pn,
"path");
1744 if (s.find(
'$') != std::string::npos)
1748 if (mxml_get_attribute(
pn,
"notify"))
1757 if (!mxml_get_attribute(
pn,
"path")) {
1758 seq_error(seq,
c,
"Missing attribute \"path\"");
1760 mstrlcpy(odbpath, seq.
subdir,
sizeof(odbpath));
1761 if (strlen(odbpath) > 0 && odbpath[strlen(odbpath) - 1] !=
'/')
1762 mstrlcat(odbpath,
"/",
sizeof(odbpath));
1763 mstrlcat(odbpath, mxml_get_attribute(
pn,
"path"),
sizeof(odbpath));
1765 if (strchr(odbpath,
'$')) {
1766 if (strchr(odbpath,
'[')) {
1768 std::string s(odbpath);
1769 std::string s1 = s.substr(0, s.find(
'['));
1770 std::string s2 = s.substr(s.find(
'['));
1773 mstrlcpy(odbpath, s1.c_str(),
sizeof(odbpath));
1776 std::string s(odbpath);
1778 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
1785 if (mxml_get_attribute(
pn,
"notify"))
1786 notify = atoi(mxml_get_attribute(
pn,
"notify"));
1788 index1 = index2 = 0;
1791 if (index1 < -1 || index2 < 0) {
1792 seq_error(seq,
c,
"Negative index not allowed");
1796 if (index1 > 1E6 || index2 > 1E6) {
1797 seq_error(seq,
c,
"Index too large for ODB");
1810 sprintf(
str,
"ODB key \"%s\" not found", odbpath);
1813 sprintf(
str,
"Invalid index %d for ODB key \"%s\"", index1, odbpath);
1817 sprintf(
str,
"Internal error %d",
status);
1826 if (mxml_get_value(
pn)[0] ==
'/') {
1830 path +=
"userfiles/sequencer/";
1832 value += std::string(mxml_get_value(
pn)+1);
1836 path +=
"userfiles/sequencer/";
1839 if (
value.back() !=
'/')
1844 if (
value.find(
'$') != std::string::npos)
1848 if (mxml_get_attribute(
pn,
"path")) {
1849 mstrlcpy(odbpath, seq.
subdir,
sizeof(odbpath));
1850 if (strlen(odbpath) > 0 && odbpath[strlen(odbpath) - 1] !=
'/')
1851 mstrlcat(odbpath,
"/",
sizeof(odbpath));
1852 mstrlcat(odbpath, mxml_get_attribute(
pn,
"path"),
sizeof(odbpath));
1854 if (strchr(odbpath,
'$')) {
1855 std::string s(odbpath);
1857 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
1881 seq_error(seq,
c,
"Internal error loading ODB file!");
1888 if (mxml_get_value(
pn)[0] ==
'/') {
1892 path +=
"userfiles/sequencer/";
1894 value += std::string(mxml_get_value(
pn)+1);
1898 path +=
"userfiles/sequencer/";
1902 size_t pos =
value.find_last_of(
'/');
1903 if (pos != std::string::npos)
1908 if (
value.find(
'$') != std::string::npos)
1912 if (mxml_get_attribute(
pn,
"path") && *mxml_get_attribute(
pn,
"path")) {
1913 mstrlcpy(odbpath, seq.
subdir,
sizeof(odbpath));
1914 if (strlen(odbpath) > 0 && odbpath[strlen(odbpath) - 1] !=
'/')
1915 mstrlcat(odbpath,
"/",
sizeof(odbpath));
1916 mstrlcat(odbpath, mxml_get_attribute(
pn,
"path"),
sizeof(odbpath));
1918 if (strchr(odbpath,
'$')) {
1919 std::string s(odbpath);
1921 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
1930 if (strstr(
value.c_str(),
".json") || strstr(
value.c_str(),
".JSON") || strstr(
value.c_str(),
".js") || strstr(
value.c_str(),
".JS"))
1932 else if (strstr(
value.c_str(),
".xml") || strstr(
value.c_str(),
".XML"))
1942 seq_error(seq,
c,
"No ODB path specified in ODBSAVE command");
1954 seq_error(seq,
c,
"Internal error loading ODB file!");
1961 if (!mxml_get_attribute(
pn,
"path")) {
1962 seq_error(seq,
c,
"Missing attribute \"path\"");
1964 mstrlcpy(odbpath, seq.
subdir,
sizeof(odbpath));
1965 if (strlen(odbpath) > 0 && odbpath[strlen(odbpath) - 1] !=
'/')
1966 mstrlcat(odbpath,
"/",
sizeof(odbpath));
1967 mstrlcat(odbpath, mxml_get_attribute(
pn,
"path"),
sizeof(odbpath));
1969 if (strchr(odbpath,
'$')) {
1970 if (strchr(odbpath,
'[')) {
1972 std::string s(odbpath);
1973 std::string s1 = s.substr(0, s.find(
'['));
1974 std::string s2 = s.substr(s.find(
'['));
1977 mstrlcpy(odbpath, s1.c_str(),
sizeof(odbpath));
1980 std::string s(odbpath);
1982 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
1987 index1 = index2 = 0;
1990 mstrlcpy(
name, mxml_get_value(
pn),
sizeof(
name));
1997 size =
sizeof(
data);
2001 value = *((
int *)
data) > 0 ?
"1" :
"0";
2005 sprintf(
str,
"Variables/%s",
name);
2006 size =
value.length() + 1;
2020 if (!mxml_get_attribute(
pn,
"path")) {
2021 seq_error(seq,
c,
"Missing attribute \"path\"");
2022 }
else if (!mxml_get_attribute(
pn,
"string")) {
2023 seq_error(seq,
c,
"Missing attribute \"string\"");
2025 mstrlcpy(odbpath, seq.
subdir,
sizeof(odbpath));
2026 if (strlen(odbpath) > 0 && odbpath[strlen(odbpath) - 1] !=
'/')
2027 mstrlcat(odbpath,
"/",
sizeof(odbpath));
2028 mstrlcat(odbpath, mxml_get_attribute(
pn,
"path"),
sizeof(odbpath));
2030 if (strchr(odbpath,
'$')) {
2031 if (strchr(odbpath,
'[')) {
2033 std::string s(odbpath);
2034 std::string s1 = s.substr(0, s.find(
'['));
2035 std::string s2 = s.substr(s.find(
'['));
2038 mstrlcpy(odbpath, s1.c_str(),
sizeof(odbpath));
2041 std::string s(odbpath);
2043 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
2047 mstrlcpy(
name, mxml_get_value(
pn),
sizeof(
name));
2049 auto s =
eval_var(seq,
c, mxml_get_attribute(
pn,
"string"));
2050 mstrlcpy(
str, s.c_str(),
sizeof(
str));
2061 size =
sizeof(
data);
2063 if (strcmp((
const char *)
data,
str) == 0)
2071 snprintf(
str,
sizeof(
str),
"\"ODBLOOKUP %s\" did not find string \"%s\"", odbpath, s.c_str());
2076 snprintf(
str,
sizeof(
str),
"Variables/%s",
name);
2077 size =
value.length() + 1;
2091 if (!mxml_get_attribute(
pn,
"path")) {
2092 seq_error(seq,
c,
"Missing attribute \"path\"");
2094 mstrlcpy(odbpath, seq.
subdir,
sizeof(odbpath));
2095 if (strlen(odbpath) > 0 && odbpath[strlen(odbpath) - 1] !=
'/')
2096 mstrlcat(odbpath,
"/",
sizeof(odbpath));
2097 mstrlcat(odbpath, mxml_get_attribute(
pn,
"path"),
sizeof(odbpath));
2099 if (strchr(odbpath,
'$')) {
2100 if (strchr(odbpath,
'[')) {
2102 std::string s(odbpath);
2103 std::string s1 = s.substr(0, s.find(
'['));
2104 std::string s2 = s.substr(s.find(
'['));
2107 mstrlcpy(odbpath, s1.c_str(),
sizeof(odbpath));
2110 std::string s(odbpath);
2112 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
2116 index1 = index2 = 0;
2126 size =
sizeof(
data);
2131 sprintf(
str,
"%lg",
d);
2132 size =
sizeof(
data);
2138 if (mxml_get_attribute(
pn,
"notify"))
2139 notify = atoi(mxml_get_attribute(
pn,
"notify"));
2149 mstrlcpy(odbpath, seq.
subdir,
sizeof(odbpath));
2150 if (strlen(odbpath) > 0 && odbpath[strlen(odbpath) - 1] !=
'/')
2151 mstrlcat(odbpath,
"/",
sizeof(odbpath));
2152 mstrlcat(odbpath, mxml_get_value(
pn),
sizeof(odbpath));
2154 if (strchr(odbpath,
'$')) {
2155 std::string s(odbpath);
2157 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
2170 if (!mxml_get_attribute(
pn,
"path")) {
2171 seq_error(seq,
c,
"Missing attribute \"path\"");
2172 }
else if (!mxml_get_attribute(
pn,
"type")) {
2173 seq_error(seq,
c,
"Missing attribute \"type\"");
2175 mstrlcpy(odbpath, seq.
subdir,
sizeof(odbpath));
2176 if (strlen(odbpath) > 0 && odbpath[strlen(odbpath) - 1] !=
'/')
2177 mstrlcat(odbpath,
"/",
sizeof(odbpath));
2178 mstrlcat(odbpath, mxml_get_attribute(
pn,
"path"),
sizeof(odbpath));
2180 if (strchr(odbpath,
'$')) {
2181 std::string s(odbpath);
2183 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
2188 for (tid = 0; tid <
TID_LAST; tid++) {
2194 seq_error(seq,
c,
"Type must be one of UINT8,INT8,UINT16,INT16,UINT32,INT32,BOOL,FLOAT,DOUBLE,STRING");
2207 memset(dummy, 0,
sizeof(dummy));
2216 if (mxml_get_attribute(
pn,
"size")) {
2217 i = atoi(
eval_var(seq,
c, mxml_get_attribute(
pn,
"size")).c_str());
2235 sprintf(
str,
"%s", mxml_get_value(
pn));
2237 if (mxml_get_attribute(
pn,
"params")) {
2238 mstrlcpy(
data, mxml_get_attribute(
pn,
"params"),
sizeof(
data));
2240 for (
i = 0;
i <
n;
i++) {
2244 mstrlcat(
str,
" ",
sizeof(
str));
2251 std::string r =
ss_execs(s.c_str());
2264 size =
sizeof(
state);
2276 size =
sizeof(
state);
2286 size =
sizeof(
state);
2298 size =
sizeof(
state);
2313 cm_msg(
MTALK,
"sequencer",
"Sequencer is finished by \"stop after current run\".");
2315 cm_msg(
MTALK,
"sequencer",
"Sequencer is going to finish by \"stop after current run\". Executing ATEXIT.");
2333 n = atoi(
eval_var(seq,
c, mxml_get_value(
pn)).c_str());
2347 }
else if (
equal_ustring(mxml_get_attribute(
pn,
"for"),
"ODBValue")) {
2350 if (!mxml_get_attribute(
pn,
"path")) {
2351 seq_error(seq,
c,
"\"path\" must be given for ODB values");
2354 mstrlcpy(odbpath, mxml_get_attribute(
pn,
"path"),
sizeof(odbpath));
2357 if (strchr(odbpath,
'$')) {
2358 if (strchr(odbpath,
'[')) {
2360 std::string s(odbpath);
2361 std::string s1 = s.substr(0, s.find(
'['));
2362 std::string s2 = s.substr(s.find(
'['));
2365 mstrlcpy(odbpath, s1.c_str(),
sizeof(odbpath));
2368 std::string s(odbpath);
2370 mstrlcpy(odbpath, s.c_str(),
sizeof(odbpath));
2374 index1 = index2 = 0;
2381 if (mxml_get_attribute(
pn,
"op"))
2382 mstrlcpy(op, mxml_get_attribute(
pn,
"op"),
sizeof(op));
2388 size =
sizeof(
data);
2391 value = *((
int *)
data) > 0 ?
"1" :
"0";
2442 seq_error(seq,
c,
msprintf(
"Invalid wait attribute \"%s\"", mxml_get_attribute(
pn,
"for")).c_str());
2455 seq_error(seq,
c,
"Maximum loop nesting exceeded");
2460 if (mxml_get_attribute(
pn,
"l"))
2462 if (mxml_get_attribute(
pn,
"le"))
2466 if (mxml_get_attribute(
pn,
"n")) {
2473 }
else if (mxml_get_attribute(
pn,
"values")) {
2474 mstrlcpy(
data, mxml_get_attribute(
pn,
"values"),
sizeof(
data));
2478 seq_error(seq,
c,
"Missing \"var\" or \"n\" attribute");
2482 if (mxml_get_attribute(
pn,
"var")) {
2483 mstrlcpy(
name, mxml_get_attribute(
pn,
"var"),
sizeof(
name));
2484 sprintf(
str,
"Variables/%s",
name);
2485 size =
value.length() + 1;
2516 seq_error(seq,
c,
"\"Break\" outside any loop");
2529 seq_error(seq,
c,
"Maximum number of nested if..endif exceeded");
2540 pe = mxml_get_node_at_line(
c->pnseq,
j);
2544 j = mxml_get_line_number_end(pe);
2555 mstrlcpy(
str, mxml_get_attribute(
pn,
"condition"),
sizeof(
str));
2558 seq_error(seq,
c,
"Invalid number in comparison");
2585 cm_msg(
MTALK,
"sequencer",
"Sequencer is finished.");
2591 if (!mxml_get_attribute(
pn,
"line") && !mxml_get_attribute(
pn,
"sline")) {
2595 if (mxml_get_attribute(
pn,
"line")) {
2598 if (mxml_get_attribute(
pn,
"sline")) {
2599 mstrlcpy(
str,
eval_var(seq,
c, mxml_get_attribute(
pn,
"sline")).c_str(),
sizeof(
str));
2600 for (
i = 0;
i < last_line;
i++) {
2601 pt = mxml_get_node_at_line(
c->pnseq,
i);
2602 if (pt && mxml_get_attribute(pt,
"l")) {
2603 l = atoi(mxml_get_attribute(pt,
"l"));
2604 if (atoi(
str) == l) {
2633 if (!mxml_get_attribute(
pn,
"name")) {
2637 mstrlcpy(
name, mxml_get_attribute(
pn,
"name"),
sizeof(
name));
2640 if (strchr(
name,
'[')) {
2642 mstrlcpy(
str, strchr(
name,
'[')+1,
sizeof(
str));
2643 if (strchr(
str,
']'))
2644 *strchr(
str,
']') = 0;
2646 *strchr(
name,
'[') = 0;
2647 sprintf(
str,
"Variables/%s",
name);
2653 size =
value.length() + 1;
2658 sprintf(
str,
"Variables/%s",
name);
2659 size =
value.length() + 1;
2669 if (mxml_get_attribute(pr,
"var")) {
2680 if (strchr(mxml_get_value(
pn),
'$'))
2684 const char *wait_attr = mxml_get_attribute(
pn,
"wait");
2687 wait = (atoi(wait_attr) == 1);
2723 if (strchr(mxml_get_value(
pn),
'$'))
2727 std::string
type =
"INFO";
2728 if (mxml_get_attribute(
pn,
"type"))
2729 type = std::string(mxml_get_attribute(
pn,
"type"));
2731 if (
type ==
"ERROR")
2733 else if (
type ==
"DEBUG")
2735 else if (
type ==
"LOG")
2737 else if (
type ==
"TALK")
2747 if (!mxml_get_attribute(
pn,
"name")) {
2751 mstrlcpy(
name, mxml_get_attribute(
pn,
"name"),
sizeof(
name));
2754 sprintf(
str,
"Variables/%s",
name);
2755 size = strlen(
data) + 1;
2766 seq_error(seq,
c,
"Maximum subroutine level exceeded");
2775 for (
i = 1;
i < mxml_get_line_number_end(mxml_find_node(
c->pnseq,
"RunSequence"));
i++) {
2776 pt = mxml_get_node_at_line(
c->pnseq,
i);
2779 if (
equal_ustring(mxml_get_attribute(pt,
"name"), mxml_get_attribute(
pn,
"name"))) {
2785 if (mxml_get_value(
pn)) {
2787 if (strchr(mxml_get_value(
pn),
'$'))
2788 mstrlcpy(p,
eval_var(seq,
c, mxml_get_value(
pn)).c_str(),
sizeof(p));
2790 mstrlcpy(p, mxml_get_value(
pn),
sizeof(p));
2801 if (
i == mxml_get_line_number_end(mxml_find_node(
c->pnseq,
"RunSequence"))) {
2802 seq_error(seq,
c,
msprintf(
"Subroutine '%s' not found", mxml_get_attribute(
pn,
"name")).c_str());
2814 size =
sizeof(seq1);
2825 if (seq.
debug && !skip_step)
2838 c->odbs =
gOdb->Chdir(
c->odb_path.c_str(),
true);
2843 cm_msg(
MERROR,
"init_sequencer",
"Sequencer error: Cannot find /Sequencer, db_find_key() status %d",
status);
2849 cm_msg(
MERROR,
"init_sequencer",
"Sequencer error: mismatching /Sequencer/State structure, db_check_record() status %d",
status);
2855 cm_msg(
MERROR,
"init_sequencer",
"Sequencer error: Cannot find /Sequencer/State, db_find_key() status %d",
status);
2859 int size =
sizeof(seq);
2862 cm_msg(
MERROR,
"init_sequencer",
"Sequencer error: Cannot get /Sequencer/State, db_get_record1() status %d",
status);
2879 cm_msg(
MERROR,
"init_sequencer",
"Sequencer error: Cannot watch /Sequencer/State, db_watch() status %d",
status);
2884 c->odbs->RB(
"Command/Start script", &b,
true);
2886 c->odbs->RB(
"Command/Stop immediately", &b,
true);
2888 c->odbs->RB(
"Command/Stop after run", &b,
true);
2890 c->odbs->RB(
"Command/Cancel stop after run", &b,
true);
2892 c->odbs->RB(
"Command/Pause script", &b,
true);
2894 c->odbs->RB(
"Command/Resume script", &b,
true);
2896 c->odbs->RB(
"Command/Debug script", &b,
true);
2898 c->odbs->RB(
"Command/Step over", &b,
true);
2900 c->odbs->RB(
"Command/Load new file", &b,
true);
2904 cm_msg(
MERROR,
"init_sequencer",
"Sequencer error: Cannot find /Sequencer/Command, db_find_key() status %d",
status);
2910 cm_msg(
MERROR,
"init_sequencer",
"Sequencer error: Cannot watch /Sequencer/Command, db_watch() status %d",
status);
2917int main(
int argc,
const char *argv[]) {
2920 char midas_hostname[256];
2921 char midas_expt[256];
2922 std::string seq_name =
"";
2924 setbuf(stdout, NULL);
2925 setbuf(stderr, NULL);
2928 signal(SIGPIPE, SIG_IGN);
2932 cm_get_environment(midas_hostname,
sizeof(midas_hostname), midas_expt,
sizeof(midas_expt));
2935 for (
int i = 1;
i < argc;
i++) {
2936 if (argv[
i][0] ==
'-' && argv[
i][1] ==
'D') {
2938 }
else if (argv[
i][0] ==
'-') {
2939 if (
i + 1 >= argc || argv[
i + 1][0] ==
'-')
2941 if (argv[
i][1] ==
'h')
2942 mstrlcpy(midas_hostname, argv[++
i],
sizeof(midas_hostname));
2943 else if (argv[
i][1] ==
'e')
2944 mstrlcpy(midas_expt, argv[++
i],
sizeof(midas_hostname));
2945 else if (argv[
i][1] ==
'c')
2946 seq_name = argv[++
i];
2949 printf(
"usage: %s [-h Hostname[:port]] [-e Experiment] [-c Name] [-D]\n\n", argv[0]);
2950 printf(
" -e experiment to connect to\n");
2951 printf(
" -c Name of additional sequencer, i.e. \'Test\'\n");
2952 printf(
" -h connect to midas server (mserver) on given host\n");
2953 printf(
" -D become a daemon\n");
2959 printf(
"Becoming a daemon...\n");
2963 std::string prg_name =
"Sequencer";
2964 std::string odb_path =
"Sequencer";
2966 if (!seq_name.empty()) {
2967 prg_name = std::string(
"Sequencer") + seq_name;
2968 odb_path = std::string(
"Sequencer") + seq_name;
2972 std::string pid_filename;
2973 pid_filename +=
"/var/run/";
2974 pid_filename += prg_name;
2975 pid_filename +=
".pid";
2977 FILE *f = fopen(pid_filename.c_str(),
"w");
3000 printf(
"%s runs already.\n", prg_name.c_str());
3014 c.seq_name = seq_name;
3015 c.prg_name = prg_name;
3016 c.odb_path = odb_path;
3020 if (seq_name.empty()) {
3021 printf(
"Sequencer started. Stop with \"!\"\n");
3023 printf(
"%s started.\n", prg_name.c_str());
3024 printf(
"Set ODB String \"/Alias/Sequencer%s\" to URL \"?cmd=sequencer&seq_name=%s\"\n", seq_name.c_str(), seq_name.c_str());
3025 printf(
"Stop with \"!\"\n");
3038 }
catch (std::string &msg) {
3040 }
catch (
const char *msg) {
3052 if ((
char) ch ==
'!')
static bool exists(const std::string &name)
void set_auto_refresh_read(bool f)
void set_auto_create(bool f)
INT cm_yield(INT millisec)
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag, INT debug_flag)
INT cm_connect_experiment1(const char *host_name, const char *default_exp_name, const char *client_name, void(*func)(char *), INT odb_size, DWORD watchdog_timeout)
std::string cm_expand_env(const char *str)
INT cm_disconnect_experiment(void)
std::string cm_get_path()
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
INT cm_exist(const char *name, BOOL bUnique)
#define CM_DEFERRED_TRANSITION
#define CM_WRONG_PASSWORD
#define DB_STRUCT_MISMATCH
#define DB_INVALID_HANDLE
INT ss_getchar(BOOL reset)
std::string ss_execs(const char *cmd)
std::string ss_replace_env_variables(const std::string &inputPath)
INT ss_daemon_init(BOOL keep_stdout)
INT ss_sleep(INT millisec)
std::string cm_get_error(INT code)
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
INT cm_msg_retrieve(INT n_message, char *message, INT buf_size)
BOOL equal_ustring(const char *str1, const char *str2)
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
INT db_save_json(HNDLE hDB, HNDLE hKey, const char *filename, int flags)
std::string strcomb1(const char **list)
INT db_save_xml(HNDLE hDB, HNDLE hKey, const char *filename)
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
INT db_get_record(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align)
INT db_save(HNDLE hDB, HNDLE hKey, const char *filename, BOOL bRemote)
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
INT db_load(HNDLE hDB, HNDLE hKeyRoot, const char *filename, BOOL bRemote)
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
INT db_watch(HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
INT db_delete(HNDLE hDB, HNDLE hKeyRoot, const char *odb_path)
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
void strarrayindex(char *odbpath, int *index1, int *index2)
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_find_keys(HNDLE hDB, HNDLE hKeyRoot, const char *odbpath, std::vector< HNDLE > &hKeyVector)
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
INT db_set_data_index1(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type, BOOL bNotify)
INT db_sscanf(const char *data_str, void *data, INT *data_size, INT i, DWORD tid)
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
const char * rpc_tid_name(INT id)
static void seq_watch(HNDLE hDB, HNDLE hKeyChanged, int index, void *info)
void seq_array_index(SEQUENCER &seq, SeqCon *c, char *odbpath, int *index1, int *index2)
int concatenate(SEQUENCER &seq, SeqCon *c, char *result, int size, char *value)
static void seq_stop_after_run(SEQUENCER &seq, SeqCon *c)
static void seq_start_next(SEQUENCER &seq, SeqCon *c)
static void seq_stop(SEQUENCER &seq, SeqCon *c)
void seq_write(const SEQUENCER &seq, SeqCon *c)
int strbreak(char *str, char list[][XNAME_LENGTH], int size, const char *brk, BOOL ignore_quotes)
void strsubst(char *string, int size, const char *pattern, const char *subst)
static std::string qtoString(std::string filename, int line, int level)
static void seq_watch_command(HNDLE hDB, HNDLE hKeyChanged, int index, void *info)
char * stristr(const char *str, const char *pattern)
static BOOL goto_at_exit(SEQUENCER &seq, SeqCon *c)
void seq_read(SEQUENCER *seq, SeqCon *c)
static BOOL msl_parse(SEQUENCER &seq, SeqCon *c, int level, const char *cpath, const char *filename, const char *xml_filename, char *error, int error_size, int *error_line)
void init_sequencer(SEQUENCER &seq, SeqCon *c)
static void seq_step_over(SEQUENCER &seq, SeqCon *c)
static void seq_cancel_stop_after_run(SEQUENCER &seq, SeqCon *c)
static void seq_pause(SEQUENCER &seq, SeqCon *c, bool flag)
void sequencer(SEQUENCER &seq, SeqCon *c)
static std::string toString(int v)
void seq_error(SEQUENCER &seq, SeqCon *c, const char *str)
int set_all_matching(HNDLE hDB, HNDLE hBaseKey, const char *odbpath, char *value, int index1, int index2, int notify)
static std::string q(const char *s)
std::string eval_var(SEQUENCER &seq, SeqCon *c, std::string value)
bool loadMSL(MVOdb *o, const std::string &filename)
int eval_condition(SEQUENCER &seq, SeqCon *c, const char *condition)
static void seq_start(SEQUENCER &seq, SeqCon *c, bool debug)
bool is_valid_number(const char *str)
void seq_clear(SEQUENCER &seq)
static void seq_open_file(const char *str, SEQUENCER &seq, SeqCon *c)
BOOL debug
debug printouts
std::string msprintf(const char *format,...)
#define DIR_SEPARATOR_STR
#define DEFAULT_WATCHDOG_TIMEOUT
#define JSFLAG_FOLLOW_LINKS
#define JSFLAG_OMIT_LAST_WRITTEN
#define SEQ_NEST_LEVEL_IF
#define SEQUENCER_STR(_name)
#define SEQ_NEST_LEVEL_LOOP
#define SEQ_NEST_LEVEL_SUB
int if_line[SEQ_NEST_LEVEL_IF]
int loop_end_line[SEQ_NEST_LEVEL_LOOP]
int sloop_start_line[SEQ_NEST_LEVEL_LOOP]
int subroutine_return_line[SEQ_NEST_LEVEL_SUB]
int loop_start_line[SEQ_NEST_LEVEL_LOOP]
int subroutine_end_line[SEQ_NEST_LEVEL_SUB]
int if_else_line[SEQ_NEST_LEVEL_IF]
int sloop_end_line[SEQ_NEST_LEVEL_LOOP]
int if_endif_line[SEQ_NEST_LEVEL_IF]
int subroutine_call_line[SEQ_NEST_LEVEL_SUB]
int loop_n[SEQ_NEST_LEVEL_LOOP]
int ssubroutine_call_line[SEQ_NEST_LEVEL_SUB]
char subroutine_param[SEQ_NEST_LEVEL_SUB][256]
int loop_counter[SEQ_NEST_LEVEL_LOOP]
char next_filename[10][256]
double te_interp(const char *expression, int *error)
static void pn(const te_expr *n, int depth)
static te_expr * list(state *s)