private void InternalValidateCodes(List <CodeCommand> codes, List <LogInfo> logs) { foreach (CodeCommand cmd in codes) { switch (cmd.Type) { case CodeType.If: { Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_If)); CodeInfo_If info = cmd.Info as CodeInfo_If; if (info.Condition.Type == BranchConditionType.ExistSection) { // Exception Handling for 1-files.script // If,ExistSection,%ScriptFile%,Cache_Delete_B,Run,%ScriptFile%,Cache_Delete_B if (info.Condition.Arg1.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase)) { if (info.Embed.Type == CodeType.Run || info.Embed.Type == CodeType.Exec) { Debug.Assert(info.Embed.Info.GetType() == typeof(CodeInfo_RunExec)); CodeInfo_RunExec subInfo = info.Embed.Info as CodeInfo_RunExec; if (subInfo.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase)) { if (info.Condition.Arg2.Equals(subInfo.SectionName, StringComparison.OrdinalIgnoreCase)) { continue; } } } } } InternalValidateCodes(info.Link, logs); } break; case CodeType.Else: { Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Else)); CodeInfo_Else info = cmd.Info as CodeInfo_Else; InternalValidateCodes(info.Link, logs); } break; case CodeType.Run: case CodeType.Exec: { Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_RunExec)); CodeInfo_RunExec info = cmd.Info as CodeInfo_RunExec; // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase)) { if (p.Sections.ContainsKey(info.SectionName)) { logs.AddRange(ValidateCodeSection(p.Sections[info.SectionName])); } else if (CodeParser.StringContainsVariable(info.SectionName) == false) { logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", cmd)); } } } break; case CodeType.Loop: { Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Loop)); CodeInfo_Loop info = cmd.Info as CodeInfo_Loop; if (info.Break) { continue; } // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase)) { if (p.Sections.ContainsKey(info.SectionName)) { logs.AddRange(ValidateCodeSection(p.Sections[info.SectionName])); } else if (CodeParser.StringContainsVariable(info.SectionName) == false) { logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", cmd)); } } } break; default: break; } } }
public static void Loop(EngineState s, CodeCommand cmd) { Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Loop)); CodeInfo_Loop info = cmd.Info as CodeInfo_Loop; if (info.Break) { if (s.LoopState == LoopState.Off) { s.Logger.Build_Write(s, new LogInfo(LogState.Error, "Loop is not running", cmd, s.CurDepth)); } else { s.LoopState = LoopState.Off; s.Logger.Build_Write(s, new LogInfo(LogState.Info, "Breaking loop", cmd, s.CurDepth)); // Reset LoopCounter, to be sure s.LoopLetter = ' '; s.LoopCounter = 0; } } else if (s.LoopState != LoopState.Off) { // If loop is already turned on, throw error s.Logger.Build_Write(s, new LogInfo(LogState.Error, "Nested loop is not supported", cmd, s.CurDepth)); } else { string startStr = StringEscaper.Preprocess(s, info.StartIdx); string endStr = StringEscaper.Preprocess(s, info.EndIdx); // Prepare Loop string scriptFile = StringEscaper.Preprocess(s, info.ScriptFile); string sectionName = StringEscaper.Preprocess(s, info.SectionName); List <string> paramList = StringEscaper.Preprocess(s, info.Parameters); Script p = Engine.GetScriptInstance(s, cmd, s.CurrentScript.FullPath, scriptFile, out bool inCurrentScript); // Does section exists? if (!p.Sections.ContainsKey(sectionName)) { throw new ExecuteException($"[{scriptFile}] does not have section [{sectionName}]"); } // Section Parameter Dictionary <int, string> paramDict = new Dictionary <int, string>(); for (int i = 0; i < paramList.Count; i++) { paramDict[i + 1] = paramList[i]; } long loopCount = 0; long startIdx = 0, endIdx = 0; char startLetter = ' ', endLetter = ' '; switch (cmd.Type) { case CodeType.Loop: { // Integer Index if (!NumberHelper.ParseInt64(startStr, out startIdx)) { throw new ExecuteException($"Argument [{startStr}] is not a valid integer"); } if (!NumberHelper.ParseInt64(endStr, out endIdx)) { throw new ExecuteException($"Argument [{endStr}] is not a valid integer"); } loopCount = endIdx - startIdx + 1; } break; case CodeType.LoopLetter: { // Drive Letter if (!(startStr.Length == 1 && StringHelper.IsAlphabet(startStr[0]))) { throw new ExecuteException($"Argument [{startStr}] is not a valid drive letter"); } if (!(endStr.Length == 1 && StringHelper.IsAlphabet(endStr[0]))) { throw new ExecuteException($"Argument [{endStr}] is not a valid drive letter"); } startLetter = char.ToUpper(startStr[0]); endLetter = char.ToUpper(endStr[0]); if (endLetter < startLetter) { throw new ExecuteException($"StartLetter must be smaller than EndLetter in lexicographic order"); } loopCount = endLetter - startLetter + 1; } break; default: throw new InternalException("Internal Logic Error at CommandBranch.Loop"); } // Log Messages string logMessage; if (inCurrentScript) { logMessage = $"Loop Section [{sectionName}] [{loopCount}] times"; } else { logMessage = $"Loop [{p.Title}]'s Section [{sectionName}] [{loopCount}] times"; } s.Logger.Build_Write(s, new LogInfo(LogState.Info, logMessage, cmd, s.CurDepth)); // Loop it SectionAddress nextAddr = new SectionAddress(p, p.Sections[sectionName]); int loopIdx = 1; switch (cmd.Type) { case CodeType.Loop: for (s.LoopCounter = startIdx; s.LoopCounter <= endIdx; s.LoopCounter++) { // Counter Variable is [#c] s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"Entering Loop with [{s.LoopCounter}] ({loopIdx}/{loopCount})", cmd, s.CurDepth)); s.Logger.LogSectionParameter(s, s.CurDepth, paramDict, cmd); int depthBackup = s.CurDepth; s.LoopState = LoopState.OnIndex; Engine.RunSection(s, nextAddr, paramDict, s.CurDepth + 1, true); if (s.LoopState == LoopState.Off) // Loop,Break { break; } s.LoopState = LoopState.Off; s.CurDepth = depthBackup; s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"End of Loop with [{s.LoopCounter}] ({loopIdx}/{loopCount})", cmd, s.CurDepth)); loopIdx += 1; } break; case CodeType.LoopLetter: for (s.LoopLetter = startLetter; s.LoopLetter <= endLetter; s.LoopLetter++) { // Counter Variable is [#c] s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"Entering Loop with [{s.LoopLetter}] ({loopIdx}/{loopCount})", cmd, s.CurDepth)); s.Logger.LogSectionParameter(s, s.CurDepth, paramDict, cmd); int depthBackup = s.CurDepth; s.LoopState = LoopState.OnDriveLetter; Engine.RunSection(s, nextAddr, paramDict, s.CurDepth + 1, true); if (s.LoopState == LoopState.Off) // Loop,Break { break; } s.LoopState = LoopState.Off; s.CurDepth = depthBackup; s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"End of Loop with [{s.LoopLetter}] ({loopIdx}/{loopCount})", cmd, s.CurDepth)); loopIdx += 1; } break; default: throw new InternalException("Internal Logic Error at CommandBranch.Loop"); } // Reset LoopCounter, to be sure s.LoopLetter = ' '; s.LoopCounter = 0; } }
public static void Loop(EngineState s, CodeCommand cmd) { Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Loop)); CodeInfo_Loop info = cmd.Info as CodeInfo_Loop; if (info.Break) { if (s.LoopRunning) { s.LoopRunning = false; s.Logger.Build_Write(s, new LogInfo(LogState.Info, "Breaking Loop", cmd, s.CurDepth)); } else { s.Logger.Build_Write(s, new LogInfo(LogState.Error, "Loop is not running", cmd, s.CurDepth)); } } else { string startIdxStr = StringEscaper.Preprocess(s, info.StartIdx); if (NumberHelper.ParseInt64(startIdxStr, out long startIdx) == false) { throw new ExecuteException($"Argument [{startIdxStr}] is not a valid integer"); } string endIdxStr = StringEscaper.Preprocess(s, info.EndIdx); if (NumberHelper.ParseInt64(endIdxStr, out long endIdx) == false) { throw new ExecuteException($"Argument [{endIdxStr}] is not a valid integer"); } long loopCount = endIdx - startIdx + 1; // Prepare Loop string pluginFile = StringEscaper.Preprocess(s, info.PluginFile); string sectionName = StringEscaper.Preprocess(s, info.SectionName); List <string> paramList = StringEscaper.Preprocess(s, info.Parameters); Plugin p = Engine.GetPluginInstance(s, cmd, s.CurrentPlugin.FullPath, pluginFile, out bool inCurrentPlugin); // Does section exists? if (!p.Sections.ContainsKey(sectionName)) { throw new ExecuteException($"[{pluginFile}] does not have section [{sectionName}]"); } string logMessage; if (inCurrentPlugin) { logMessage = $"Loop Section [{sectionName}] [{loopCount}] times"; } else { logMessage = $"Loop [{p.Title}]'s Section [{sectionName}] [{loopCount}] times"; } s.Logger.Build_Write(s, new LogInfo(LogState.Info, logMessage, cmd, s.CurDepth)); // Section Parameter Dictionary <int, string> paramDict = new Dictionary <int, string>(); for (int i = 0; i < paramList.Count; i++) { paramDict[i + 1] = paramList[i]; } // Loop it SectionAddress nextAddr = new SectionAddress(p, p.Sections[sectionName]); for (s.LoopCounter = startIdx; s.LoopCounter <= endIdx; s.LoopCounter++) { // Counter Variable is [#c] s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"Entering Loop [{s.LoopCounter}/{loopCount}]", cmd, s.CurDepth)); s.Logger.LogSectionParameter(s, s.CurDepth, paramDict, cmd); int depthBackup = s.CurDepth; s.LoopRunning = true; Engine.RunSection(s, nextAddr, paramDict, s.CurDepth + 1, true); if (s.LoopRunning == false) // Loop,Break { break; } s.LoopRunning = false; s.CurDepth = depthBackup; s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"End of Loop [{s.LoopCounter}/{loopCount}]", cmd, s.CurDepth)); } } }
private void RecursiveFindCodeSection(IReadOnlyList <CodeCommand> codes, List <LogInfo> logs) { string targetCodeSection = null; string targetInterfaceSection = null; foreach (CodeCommand cmd in codes) { switch (cmd.Type) { #region Check CodeSections case CodeType.If: { CodeInfo_If info = cmd.Info.Cast <CodeInfo_If>(); if (info.Condition.Type == BranchConditionType.ExistSection) { // For recursive section call // Ex) If,ExistSection,%ScriptFile%,DoWork,Run,%ScriptFile%,DoWork if (info.Condition.Arg1.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) && info.Embed.Type == CodeType.Run || info.Embed.Type == CodeType.RunEx || info.Embed.Type == CodeType.Exec) { CodeInfo_RunExec subInfo = info.Embed.Info.Cast <CodeInfo_RunExec>(); if (subInfo.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase)) { if (info.Condition.Arg2.Equals(subInfo.SectionName, StringComparison.OrdinalIgnoreCase)) { continue; } } } } RecursiveFindCodeSection(info.Link, logs); } break; case CodeType.Else: { CodeInfo_Else info = cmd.Info.Cast <CodeInfo_Else>(); RecursiveFindCodeSection(info.Link, logs); } break; case CodeType.Run: case CodeType.Exec: case CodeType.RunEx: { CodeInfo_RunExec info = cmd.Info.Cast <CodeInfo_RunExec>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) && !CodeParser.StringContainsVariable(info.SectionName)) { targetCodeSection = info.SectionName; } } break; case CodeType.Loop: case CodeType.LoopLetter: case CodeType.LoopEx: case CodeType.LoopLetterEx: { CodeInfo_Loop info = cmd.Info.Cast <CodeInfo_Loop>(); if (info.Break) { continue; } // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) && !CodeParser.StringContainsVariable(info.SectionName)) { targetCodeSection = info.SectionName; } } break; case CodeType.UserInput: { CodeInfo_UserInput info = cmd.Info.Cast <CodeInfo_UserInput>(); UserInputType type = info.Type; switch (type) { case UserInputType.DirPath: case UserInputType.FilePath: { UserInputInfo_DirFile subInfo = info.SubInfo.Cast <UserInputInfo_DirFile>(); if (info.Type == UserInputType.FilePath) { // Select File if (subInfo.Filter != null) { string filter = StringEscaper.Unescape(subInfo.Filter); if (StringEscaper.IsFileFilterValid(filter) == false) { logs.Add(new LogInfo(LogState.Error, $"File filter pattern [{filter}] is invalid", cmd)); } } } else { // Select Folder if (subInfo.Filter != null) { logs.Add(new LogInfo(LogState.Warning, $"File filters cannot be used for folder selection", cmd)); } } } break; } } break; #endregion #region Check InterfaceSections case CodeType.AddInterface: { CodeInfo_AddInterface info = cmd.Info.Cast <CodeInfo_AddInterface>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) && !CodeParser.StringContainsVariable(info.Section)) { targetInterfaceSection = info.Section; } } break; case CodeType.ReadInterface: { CodeInfo_ReadInterface info = cmd.Info.Cast <CodeInfo_ReadInterface>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) && !CodeParser.StringContainsVariable(info.Section)) { targetInterfaceSection = info.Section; } } break; case CodeType.WriteInterface: { CodeInfo_WriteInterface info = cmd.Info.Cast <CodeInfo_WriteInterface>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) && !CodeParser.StringContainsVariable(info.Section)) { targetInterfaceSection = info.Section; } } break; case CodeType.IniWrite: { // To detect multi-interface without `InterfaceList=`, // Inspect pattern `IniWrite,%ScriptFile%,Main,Interface,<NewInterfaceSection>` CodeInfo_IniWrite info = cmd.Info.Cast <CodeInfo_IniWrite>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.FileName.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) && info.Section.Equals(ScriptSection.Names.Main, StringComparison.OrdinalIgnoreCase) && info.Key.Equals(ScriptSection.Names.Interface, StringComparison.OrdinalIgnoreCase) && !CodeParser.StringContainsVariable(info.Value)) { targetInterfaceSection = info.Value; } } break; #endregion } if (targetCodeSection != null) { if (_sc.Sections.ContainsKey(targetCodeSection)) { logs.AddRange(CheckCodeSection(_sc.Sections[targetCodeSection], cmd.RawCode, cmd.LineIdx)); } else { logs.Add(new LogInfo(LogState.Error, $"Section [{targetCodeSection}] does not exist", cmd)); } } if (targetInterfaceSection != null) { if (_sc.Sections.ContainsKey(targetInterfaceSection)) { logs.AddRange(CheckInterfaceSection(_sc.Sections[targetInterfaceSection], cmd.RawCode, cmd.LineIdx)); } else { logs.Add(new LogInfo(LogState.Error, $"Section [{targetInterfaceSection}] does not exist", cmd)); } } } }
private void InternalValidateCodes(CodeCommand[] codes, List <LogInfo> logs) { string targetCodeSection = null; string targetInterfaceSection = null; foreach (CodeCommand cmd in codes) { switch (cmd.Type) { #region Check CodeSections case CodeType.If: { CodeInfo_If info = cmd.Info.Cast <CodeInfo_If>(); if (info.Condition.Type == BranchConditionType.ExistSection) { // For recursive section call // Ex) If,ExistSection,%ScriptFile%,DoWork,Run,%ScriptFile%,DoWork if (info.Condition.Arg1.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) && info.Embed.Type == CodeType.Run || info.Embed.Type == CodeType.Exec) { CodeInfo_RunExec subInfo = info.Embed.Info.Cast <CodeInfo_RunExec>(); if (subInfo.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase)) { if (info.Condition.Arg2.Equals(subInfo.SectionName, StringComparison.OrdinalIgnoreCase)) { continue; } } } } InternalValidateCodes(info.Link.ToArray(), logs); } break; case CodeType.Else: { CodeInfo_Else info = cmd.Info.Cast <CodeInfo_Else>(); InternalValidateCodes(info.Link.ToArray(), logs); } break; case CodeType.Run: case CodeType.Exec: case CodeType.RunEx: { CodeInfo_RunExec info = cmd.Info.Cast <CodeInfo_RunExec>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) && !CodeParser.StringContainsVariable(info.SectionName)) { targetCodeSection = info.SectionName; } } break; case CodeType.Loop: case CodeType.LoopLetter: case CodeType.LoopEx: case CodeType.LoopLetterEx: { CodeInfo_Loop info = cmd.Info.Cast <CodeInfo_Loop>(); if (info.Break) { continue; } // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) && !CodeParser.StringContainsVariable(info.SectionName)) { targetCodeSection = info.SectionName; } } break; #endregion #region Check InterfaceSections case CodeType.AddInterface: { CodeInfo_AddInterface info = cmd.Info.Cast <CodeInfo_AddInterface>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) && CodeParser.StringContainsVariable(info.Section)) { targetInterfaceSection = info.Section; } } break; case CodeType.ReadInterface: { CodeInfo_ReadInterface info = cmd.Info.Cast <CodeInfo_ReadInterface>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) && CodeParser.StringContainsVariable(info.Section)) { targetInterfaceSection = info.Section; } } break; case CodeType.WriteInterface: { CodeInfo_WriteInterface info = cmd.Info.Cast <CodeInfo_WriteInterface>(); // CodeValidator does not have Variable information, so just check with predefined literal if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) && CodeParser.StringContainsVariable(info.Section)) { targetInterfaceSection = info.Section; } } break; #endregion } if (targetCodeSection != null && !_visitedSections.Contains(targetCodeSection)) { _visitedSections.Add(targetCodeSection); if (_sc.Sections.ContainsKey(targetCodeSection)) { logs.AddRange(ValidateCodeSection(_sc.Sections[targetCodeSection], cmd.RawCode, cmd.LineIdx)); } else { logs.Add(new LogInfo(LogState.Error, $"Section [{targetCodeSection}] does not exist", cmd)); } } if (targetInterfaceSection != null && !_visitedSections.Contains(targetInterfaceSection)) { _visitedSections.Add(targetInterfaceSection); if (_sc.Sections.ContainsKey(targetInterfaceSection)) { logs.AddRange(ValidateInterfaceSection(_sc.Sections[targetInterfaceSection], cmd.RawCode, cmd.LineIdx)); } else { logs.Add(new LogInfo(LogState.Error, $"Section [{targetInterfaceSection}] does not exist", cmd)); } } } }