public LinkedList<class_types.m_variable> SortVariables(class_types.m_file_data m_file) { //-----variables need sorting, so they are declared and aligned in Matlab--------- LinkedList<class_types.m_variable> result = new LinkedList<class_types.m_variable>(); int length = m_file.variables.Count(); class_types.m_variable[] variables_to_sort = new class_types.m_variable[length]; variables_to_sort = m_file.variables.ToArray(); while (true) { int wrong = 0; for (int i = 0; i < (length - 1); i++) { int comparison; comparison = String.Compare(variables_to_sort[i].name, variables_to_sort[i + 1].name); if (comparison == 1) { class_types.m_variable bubble_temp; bubble_temp = variables_to_sort[i + 1]; variables_to_sort[i + 1] = variables_to_sort[i]; variables_to_sort[i] = bubble_temp; wrong++; } } if (wrong == 0) break; } for (int i = 0; i < variables_to_sort.Length; i++) result.AddLast(variables_to_sort[i]); return result; }
// function to read a block of variables class_types.read_function_output ReadVariables(LinkedList<string> InCode, class_types.m_file_data m_file_input, int current_line) { class_types.read_function_output result; class_types.CodeResult TempCodeComment; class_types.m_variable var_temp = new class_types.m_variable(); int wrong_spaces = 0; string IO_type = ""; int colon_index, semicolon_index, colon_2_index = 0; result.lines_forward = 1; result.success = false; result.message = ""; result.m_file = m_file_input; //comments "(* comment *)" removal and adding to var block comment TempCodeComment = RemoveComment(InCode.First()); if (TempCodeComment.success == false)//check for malformed comments { result.success = false; result.message += "Error in comments at line " + (current_line + current_line ) + ". "; return result; } //var block's comment line is here string temp =TempCodeComment.comment; //if (TempCodeComment.comment != "") // result.m_file.var_block_comments.AddLast(TempCodeComment.comment); InCode.RemoveFirst(); InCode.AddFirst(TempCodeComment.code); //account for empty lines while (InCode.First() == "") { InCode.RemoveFirst(); result.lines_forward++; if (InCode.Count <= 0) //in case the EOF is encountered while searching for non-empty lines { result.success = false; result.message += "Sudden end of file at line " + (current_line + result.lines_forward + 1) + ". "; return result; } } while (InCode.First().Substring(wrong_spaces, 1) == " " && wrong_spaces < InCode.First().Length)//clean up wrong spaces wrong_spaces++; //code line clean, onto var block definition (IO type) int IO_case = -1; int before_retention = 0; class_types.m_variable var_temp_vector = new class_types.m_variable(); if (InCode.First().Length > 8 && InCode.First().Substring(0, 9) == "VAR_INPUT") IO_case = 0; else { if (InCode.First().Length > 9 && InCode.First().Substring(0, 10) == "VAR_OUTPUT") IO_case = 1; else { if (InCode.First().Length > 9 && InCode.First().Substring(0, 10) == "VAR_GLOBAL") IO_case = 2; else { if (InCode.First().Length > 2 && InCode.First().Substring(0, 3) == "VAR") IO_case = 2; } } } switch (IO_case) { case 0: IO_type = "input"; before_retention = 8; break; case 1: IO_type = "output"; before_retention = 9; break; case 2: IO_type = "global"; before_retention = 9; break; } //Check for retention parameters if (InCode.First().Length > (before_retention + 7))//"RETAIN" { wrong_spaces = 0; while (InCode.First().Substring(wrong_spaces + before_retention + 1, 1) == " " && wrong_spaces < InCode.First().Length - before_retention - 1)//clean up wrong spaces wrong_spaces++; if (InCode.First().Substring(wrong_spaces + before_retention + 1, 6) == "RETAIN") var_temp.retain = true; else var_temp.retain = false; } if (IO_type == "") //case no type of variable is understood { result.success = false; result.message = result.message + "Error: invalid variable IO option at line " + (current_line + result.lines_forward + 1) + ". "; return result; } else { //complete var block's comment if (temp!="") result.m_file.var_block_comments.AddLast(IO_type + " block's comment: " + temp); } InCode.RemoveFirst(); result.lines_forward++; //account for empty lines while (InCode.First() == "") { InCode.RemoveFirst(); result.lines_forward++; if (InCode.Count <= 0) //in case the EOF is encountered while searching for non-empty lines { result.success = false; result.message += "Sudden end of file at line " + (current_line + result.lines_forward + 1) + ". "; return result; } } //vars declaration loop while (InCode.First() != "" && InCode.First().Substring(0, 7) != "END_VAR") { wrong_spaces = 0; colon_index = 0; colon_2_index = 0; semicolon_index = 0; while (InCode.First().Substring(wrong_spaces, 1) == " " && wrong_spaces < InCode.First().Length)//clean up wrong spaces wrong_spaces++; if (InCode.First().Substring(wrong_spaces, 7) == "END_VAR")//end current variable block; { result.success = true; break; } else//here is the process to read variable information { //comments "(* comment *)" removal and adding var_temp.comment = RemoveComment(InCode.First()).comment; //write variable's comment TempCodeComment = RemoveComment(InCode.First()); if (TempCodeComment.success == false)//check for malformed comments { result.success = false; result.message += "Error in comments at line " + (current_line + result.lines_forward + 1) + ". "; return result; } InCode.RemoveFirst(); InCode.AddFirst(RemoveSpaces(TempCodeComment.code));//code line clean from comments and empty spaces //TODO pointer type variables are diferent in declaration, add those if (!(InCode.First().Contains(":") && InCode.First().Contains(";")))//in case the declaration line is not valid { result.success = false; result.message += "Error: invalid declaration at line " + (current_line + result.lines_forward + 1) + ". "; return result; } //the declaration line must have all of these elements in order to be valid colon_index = InCode.First().IndexOf(":"); semicolon_index = InCode.First().IndexOf(";"); //check for consistency of elements' order in declaration if (InCode.First().Contains(":="))//if we have two colons, then we have an initial value declared { colon_2_index = InCode.First().IndexOf(":="); if (colon_2_index > semicolon_index || colon_index > colon_2_index || colon_index > semicolon_index)//smaller index protection against EOL error; { result.success = false; result.message += "Error: invalid declaration at line " + (current_line + result.lines_forward + 1) + ". "; return result; } } else { if (colon_index > semicolon_index)//smaller index protection against EOL error; { result.success = false; result.message += "Error: invalid declaration at line " + (current_line + result.lines_forward + 1) + ". "; return result; } } //all is good, just read the values var_temp.name = ReplaceIllegalChars(InCode.First().Substring(0, colon_index)); if (colon_2_index > 0) { var_temp.type = InCode.First().Substring(colon_index + 1, colon_2_index - colon_index - 1); var_temp.value = InCode.First().Substring(colon_2_index + 2, semicolon_index - colon_2_index - 2);//write initial value if (var_temp.type == "BOOL")//TODO: check this { //Boolean values conversion from TRUE, FALSE to 1, 0; if (var_temp.value == "TRUE") var_temp.value = "1"; if (var_temp.value == "FALSE") var_temp.value = "0"; } var_temp.IO_type = IO_type;//write the variable's IO type result.m_file.variables.AddLast(var_temp); } else//no initial value declared { var_temp.type = InCode.First().Substring(colon_index + 1, semicolon_index - colon_index - 1); string default_value = "0"; //aplicable for most var types, just check the exceptions if (var_temp.type=="TIME") { var_temp.type = "INT"; } if (var_temp.type == "CTU" || var_temp.type == "CTD" || var_temp.type == "TON") //FB variable, declare vector of variables required for FB call to work { switch (var_temp.type) { case "TON": TIMER_ON_flag = true; var_temp_vector = new class_types.m_variable(); var_temp_vector.IO_type = IO_type; var_temp_vector.retain = false; var_temp_vector.comment = ""; var_temp_vector.type = "INT"; var_temp_vector.value = "[1,0,0,0,0,0]"; var_temp_vector.name = var_temp.name; result.m_file.variables.AddLast(var_temp_vector); //FB identifier var_temp_vector.comment = "FB identifier"; var_temp_vector.type = "STRING"; var_temp_vector.value = "'TIMER_ON'"; var_temp_vector.name = var_temp.name + "_FBID"; result.m_file.variables.AddLast(var_temp_vector);//FB identifier break; case "CTU": COUNTER_UP_flag = true; var_temp_vector = new class_types.m_variable(); var_temp_vector.IO_type = IO_type; var_temp_vector.retain = false; var_temp_vector.comment = ""; var_temp_vector.type = "INT"; var_temp_vector.value = "[0,0,0,0,0,0]"; var_temp_vector.name = var_temp.name; result.m_file.variables.AddLast(var_temp_vector); //FB identifier var_temp_vector.comment = "FB identifier"; var_temp_vector.type = "STRING"; var_temp_vector.value = "'COUNTER_UP'"; var_temp_vector.name = var_temp.name + "_FBID"; result.m_file.variables.AddLast(var_temp_vector);//FB identifier break; case "CTD": COUNTER_DOWN_flag = true; var_temp_vector = new class_types.m_variable(); var_temp_vector.IO_type = IO_type; var_temp_vector.retain = false; var_temp_vector.comment = ""; var_temp_vector.type = "INT"; var_temp_vector.value = "[0,0,0,0,0,0]"; var_temp_vector.name = var_temp.name; result.m_file.variables.AddLast(var_temp_vector); //FB identifier var_temp_vector.comment = "FB identifier"; var_temp_vector.type = "STRING"; var_temp_vector.value = "'COUNTER_DOWN'"; var_temp_vector.name = var_temp.name + "_FBID"; result.m_file.variables.AddLast(var_temp_vector);//FB identifier break; default: break; } } else { switch (var_temp.type) //for every simple type, there is a different defaul initial value { case "BOOL"://TODO ADD THE REMAINING VARIABLE TYPE'S DEFAULT VALUE default_value = "0"; break; case "STRING": default_value = "''"; break; case "CHAR": default_value = "''"; break; case "WORD": default_value = "0"; break; case "INT": default_value = "0"; break; } var_temp.value=default_value; var_temp.IO_type = IO_type;//write the variable's IO type result.m_file.variables.AddLast(var_temp); } } //check for approved variable types if (!(var_temp.type == "TON" || var_temp.type == "CTD" || var_temp.type == "CTU" || var_temp.type == "WORD" || var_temp.type == "BOOL" || var_temp.type == "BYTE" || var_temp.type == "LWORD" || var_temp.type == "DWORD" || var_temp.type == "SINT" || var_temp.type == "INT" || var_temp.type == "DINT" || var_temp.type == "LINT" || var_temp.type == "USINT" || var_temp.type == "UINT" || var_temp.type == "UDINT" || var_temp.type == "ULINT" || var_temp.type == "REAL" || var_temp.type == "LREAL" || var_temp.type == "DATE" || var_temp.type == "TOD" || var_temp.type == "DT" || var_temp.type == "TIME" || var_temp.type == "STRING" || var_temp.type == "WSTRING")) { result.success = false; result.message = result.message + "Error: invalid variable type declaration at line " + (current_line + result.lines_forward + 1) + ". "; return result; } result.success = true; InCode.RemoveFirst();//onto next line result.lines_forward++; } } //account for empty lines while (InCode.First() == "") { InCode.RemoveFirst(); result.lines_forward++; if (InCode.Count <= 0) //in case the EOF is encountered while searching for non-empty lines { result.success = false; result.message += "Sudden end of file at line " + (current_line + result.lines_forward + 1) + ". "; return result; } } wrong_spaces = 0; while (InCode.First().Substring(wrong_spaces, 1) == " " && wrong_spaces < InCode.First().Length) //clean up wrong spaces wrong_spaces++; //reached END_VAR instruction if (InCode.First().Substring(wrong_spaces, 7) == "END_VAR") { InCode.RemoveFirst();//onto next line, END_VAR marks the success of the variable declaration result.lines_forward++; result.success = true; } else { result.success = false; result.message += "Error: 'END_VAR' expected at " + (current_line + result.lines_forward + 1) + ". "; } return result; }