| 1166 | *********************************/ |
| 1167 | |
| 1168 | static bool ConExec(std::span<std::string_view> argv) |
| 1169 | { |
| 1170 | if (argv.empty()) { |
| 1171 | IConsolePrint(CC_HELP, "Execute a local script file. Usage: 'exec <script> [0]'."); |
| 1172 | IConsolePrint(CC_HELP, "By passing '0' after the script name, no warning about a missing script file will be shown."); |
| 1173 | return true; |
| 1174 | } |
| 1175 | |
| 1176 | if (argv.size() < 2) return false; |
| 1177 | |
| 1178 | auto script_file = FioFOpenFile(argv[1], "r", BASE_DIR); |
| 1179 | |
| 1180 | if (!script_file.has_value()) { |
| 1181 | if (argv.size() == 2 || argv[2] != "0") IConsolePrint(CC_ERROR, "Script file '{}' not found.", argv[1]); |
| 1182 | return true; |
| 1183 | } |
| 1184 | |
| 1185 | if (_script_current_depth == 11) { |
| 1186 | IConsolePrint(CC_ERROR, "Maximum 'exec' depth reached; script A is calling script B is calling script C ... more than 10 times."); |
| 1187 | return true; |
| 1188 | } |
| 1189 | |
| 1190 | _script_current_depth++; |
| 1191 | uint script_depth = _script_current_depth; |
| 1192 | |
| 1193 | char buffer[ICON_CMDLN_SIZE]; |
| 1194 | while (fgets(buffer, sizeof(buffer), *script_file) != nullptr) { |
| 1195 | /* Remove newline characters from the executing script */ |
| 1196 | std::string_view cmdline{buffer}; |
| 1197 | auto last_non_newline = cmdline.find_last_not_of("\r\n"); |
| 1198 | if (last_non_newline != std::string_view::npos) cmdline = cmdline.substr(0, last_non_newline + 1); |
| 1199 | |
| 1200 | IConsoleCmdExec(cmdline); |
| 1201 | /* Ensure that we are still on the same depth or that we returned via 'return'. */ |
| 1202 | assert(_script_current_depth == script_depth || _script_current_depth == script_depth - 1); |
| 1203 | |
| 1204 | /* The 'return' command was executed. */ |
| 1205 | if (_script_current_depth == script_depth - 1) break; |
| 1206 | } |
| 1207 | |
| 1208 | if (ferror(*script_file) != 0) { |
| 1209 | IConsolePrint(CC_ERROR, "Encountered error while trying to read from script file '{}'.", argv[1]); |
| 1210 | } |
| 1211 | |
| 1212 | if (_script_current_depth == script_depth) _script_current_depth--; |
| 1213 | return true; |
| 1214 | } |
| 1215 | |
| 1216 | static bool ConSchedule(std::span<std::string_view> argv) |
| 1217 | { |
nothing calls this directly
no test coverage detected