// // Поиск присвоения значений переменным в процедурах // public void FindAssignments() { // процедуры, создающие массивы (если они не объявлены) string[] aprocedures = { "ACOPY", "ACLASS", "ADATABASES", "ADBOBJECTS", "ADIR", "ADLLS", "ADOCKSTATE", "AELEMENT", "AERROR", "AEVENTS", "AFIELDS", "AFONT", "AGETCLASS", "AGETFILEVERSION", "AINSTANCE", "ALANGUAGE", "ALINES", "AMEMBERS", "AMOUSEOBJ", "ANETRESOURCES", "APRINTERS", "APROCINFO", "ASELOBJ", "ASESSIONS", "ASQLHANDLES", "ASTACKINFO", "ATAGINFO", "AUSED", "AVCXCLASSES" }; foreach (var proc in Procedures) { for (int i = proc.begin_line; i <= proc.end_line; i++) { CLine line = Lines[i]; int offset = 0; // VARIABLE = ... (явное присвоение) int pos = line.content.IndexOf('='); if (pos > 0) { string str = line.content.Substring(0, pos); if (!StartWith(str, "IF")) { // FOR ... if (str.StartsWith("FOR ", StringComparison.OrdinalIgnoreCase)) { str = str.Substring(4).Trim(); } str = FormatVarName(str); string[] columns = str.Split(new[] { '=', ' ' }, StringSplitOptions.RemoveEmptyEntries); if (columns.Length == 1) { str = str.Trim(); if (checkIncorrectVarNames && !CheckName(str)) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, str); } proc.AddAssignment(line.number, str); } } } // STORE ... TO ... if (line.content.StartsWith("STORE ", StringComparison.OrdinalIgnoreCase)) { string str = line.content.Substring(6); int pos2 = str.IndexOf(" TO ", StringComparison.OrdinalIgnoreCase); if (pos2 >= 0) { str = str.Substring(pos2 + 4).Trim(); string[] columns = str.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < columns.Length; j++) { if (checkIncorrectVarNames && !CheckName(columns[j])) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, columns[j]); } proc.AddAssignment(line.number, columns[j]); } } } // CATCH TO ... else if (line.content.StartsWith("CATCH TO ", StringComparison.OrdinalIgnoreCase)) { string str = line.content.Substring(9).Trim(); if (str != "") { if (checkIncorrectVarNames && !CheckName(str)) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, str); } proc.AddAssignment(line.number, str); } } // FOR EACH ... else if (line.content.StartsWith("FOR EACH ", StringComparison.OrdinalIgnoreCase)) { string [] words = line.content.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (words.Length > 2) { if (checkIncorrectVarNames && !CheckName(words[2])) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, words[2]); } proc.AddAssignment(line.number, words[2]); } } // CALCULATE ... TO ... else if (line.content.StartsWith("CALCULATE ", StringComparison.OrdinalIgnoreCase)) { string str = line.content.Substring(10); int pos2 = str.IndexOf(" TO ", StringComparison.OrdinalIgnoreCase); if (pos2 >= 0) { str = str.Substring(pos2 + 4).Trim(); int len = str.IndexOf(" IN ", StringComparison.OrdinalIgnoreCase); if (len > 0) { str = str.Substring(0, len); } pos2 = str.IndexOf("ARRAY ", StringComparison.OrdinalIgnoreCase); if (pos2 >= 0) { str = str.Substring(pos2 + 6).Trim(); } string[] columns = str.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < columns.Length; j++) { if (checkIncorrectVarNames && !CheckName(columns[j])) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, columns[j]); } proc.AddAssignment(line.number, columns[j]); } } } // DO FORM ... NAME ... TO ... else if (line.content.StartsWith("DO FORM ", StringComparison.OrdinalIgnoreCase)) { string str = line.content.Substring(8); int pos2 = str.IndexOf(" NAME ", StringComparison.OrdinalIgnoreCase); if (pos2 >= 0) { str = str.Substring(pos2 + 6).Trim(); string[] columns = str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); int len = columns.Length; if (len > 0) { if (checkIncorrectVarNames && !CheckName(columns[0])) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, columns[0]); } proc.AddAssignment(line.number, columns[0]); } } pos2 = str.IndexOf(" TO ", StringComparison.OrdinalIgnoreCase); if (pos2 >= 0) { str = str.Substring(pos2 + 4).Trim(); string[] columns = str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); int len = columns.Length; if (len > 0) { if (checkIncorrectVarNames && !CheckName(columns[0])) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, columns[0]); } proc.AddAssignment(line.number, columns[0]); } } } // ON ERROR VAR = VALUE else if (line.content.StartsWith("ON ERROR ", StringComparison.OrdinalIgnoreCase)) { string[] words = line.content.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if ((words.Length > 4) && (words[3] == "=")) { if (checkIncorrectVarNames && !CheckName(words[2])) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, words[2]); } proc.AddAssignment(line.number, words[2]); } } // A... procedures else if ((offset = IndexOf(line.content, aprocedures)) >= 0) { string str = line.content.Substring(offset); int num = str.StartsWith("ACOPY", StringComparison.OrdinalIgnoreCase) ? 2 : 1; // для ACOPY проверяем 2-й параметр string[] words = str.Split(new[] { ' ', '(', ')', ',' }, StringSplitOptions.RemoveEmptyEntries); if (words.Length > 1) { if (checkIncorrectVarNames && !CheckName(words[num])) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, words[num]); } proc.AddAssignment(line.number, words[num]); } } // SELECT ... FROM XXX INTO ARRAY YYY else if (line.content.StartsWith("SELECT ", StringComparison.OrdinalIgnoreCase)) { string[] words = line.content.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); int len = words.Length; if (len > 6) { if (String.Compare(words[0], "SELECT", true) == 0) { if (String.Compare(words[len - 3], "INTO", true) == 0) { if (String.Compare(words[len - 2], "ARRAY", true) == 0) { if (checkIncorrectVarNames && !CheckName(words[len - 1])) { CLog.Print("{0}: {1}: Недопустимое имя переменной при присваивании \"{2}\"", fileName, line.number, words[len - 1]); } proc.AddAssignment(line.number, words[len - 1]); } } } } } } } }
// // Недостижимый код // public void CheckUnreachableCode() { if (!checkUnreachableCode) { return; } foreach (var proc in Procedures) { int cond_count = 0; for (int i = proc.begin_line; i <= proc.end_line; i++) { CLine line = Lines[i]; if (line.content.StartsWith("IF ", StringComparison.OrdinalIgnoreCase)) { cond_count++; } if (line.content.StartsWith("ENDIF", StringComparison.OrdinalIgnoreCase)) { cond_count--; } if (line.content.StartsWith("FOR ", StringComparison.OrdinalIgnoreCase)) { cond_count++; } if (line.content.StartsWith("ENDFOR", StringComparison.OrdinalIgnoreCase)) { cond_count--; } if (line.content.StartsWith("DO WHILE ", StringComparison.OrdinalIgnoreCase)) { cond_count++; } if (line.content.StartsWith("ENDDO", StringComparison.OrdinalIgnoreCase)) { cond_count--; } if (line.content.StartsWith("DO CASE", StringComparison.OrdinalIgnoreCase)) { cond_count++; } if (line.content.StartsWith("ENDCASE", StringComparison.OrdinalIgnoreCase)) { cond_count--; } if (line.content.StartsWith("SCAN", StringComparison.OrdinalIgnoreCase)) { cond_count++; } if (line.content.StartsWith("ENDSCAN", StringComparison.OrdinalIgnoreCase)) { cond_count--; } // // ПРИМЕЧАНИЕ: // В данном месте наличие RETURN меджу TRY/ENDTRY не считаем ошибкой // Ошибка на недопустимость использования RETURN проверяется в CheckTryEndtry // if (line.content.StartsWith("TRY", StringComparison.OrdinalIgnoreCase)) { cond_count++; } if (line.content.StartsWith("ENDTRY", StringComparison.OrdinalIgnoreCase)) { cond_count--; } if (line.content.StartsWith("RETURN", StringComparison.OrdinalIgnoreCase)) { if (cond_count == 0 && i < proc.end_line) { if (!(Lines[i + 1].content.StartsWith("ENDFUNC", StringComparison.OrdinalIgnoreCase) || Lines[i + 1].content.StartsWith("ENDPROC", StringComparison.OrdinalIgnoreCase) || Lines[i + 1].content.StartsWith("ENDWITH", StringComparison.OrdinalIgnoreCase))) { CLog.Print("{0}: {1}: Недостижимый код", fileName, Lines[i + 1].number); } } } } } }
// // Поиск процедур (разбивка содержимого на процедуры) // // ПРИМЕЧАНИЕ: FUNCTION/PROCEDURE - ENDFUNC/ENDPROC включаются в содержимое процедуры // void FindProcedures() { CProcedure proc = null; string class_name = ""; for (int i = 0; i < Lines.Count; i++) { CLine line = Lines[i]; // TODO: тут же в этом месте надо разобрать параметры переданные не через PARAMETES/LPARAMETERS, а как func( param1, param2, ... ) string[] words = line.content.Split(new[] { ',', ' ', '(', ')' }, StringSplitOptions.RemoveEmptyEntries); if (words.Length > 1) { if (words.Length > 2) { if (String.Compare(words[0], "DEFINE", true) == 0 && String.Compare(words[1], "class", true) == 0) { class_name = words[2]; } } if (String.Compare(words[0], "ENDDEFINE", true) == 0) { class_name = ""; } int procWord = (String.Compare(words[0], "HIDDEN", true) == 0 || String.Compare(words[0], "PROTECTED", true) == 0) ? 1 : 0; if (procWord == 1 && words.Length < 3) { continue; } // procedure/function if (String.Compare(words[procWord], "PROCEDURE", true) == 0 || String.Compare(words[procWord], "FUNCTION", true) == 0) { if (proc != null) // значит не обнаружен endproc/endfunc { proc.end_line = i; CLog.Print("{0}: {1}: Отсутствует ENDPROC/ENDFUNC в предшествующей процедуре", fileName, line.number); } proc = new CProcedure(class_name, words[procWord + 1], i, -1); // конечную строку еще не знаем Procedures.Add(proc); } } if (words.Length > 0) { // endproc/endfunc if (String.Compare(words[0], "ENDPROC", true) == 0 || String.Compare(words[0], "endfunc", true) == 0) { if (proc != null) { proc.end_line = i; // конечная строка proc = null; } } } } // Еслм нет описания ни одной процедуры, считаем что файл и есть процедура if (Lines.Count > 0 && Procedures.Count == 0) { Procedures.Add(new CProcedure("", Path.GetFileNameWithoutExtension(fileName), 0, Lines.Count - 1)); } }