Changeset - r25044:b22efcf16422
[Not reviewed]
master
0 1 0
Patric Stout - 3 years ago 2021-03-12 08:23:03
truebrain@openttd.org
Fix: calling "exec" from script never returned

Example:

exec other.script
echo hello

The "echo" was never executed.
1 file changed with 11 insertions and 5 deletions:
0 comments (0 inline, 0 general)
src/console_cmds.cpp
Show inline comments
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file console_cmds.cpp Implementation of the console hooks. */
 

	
 
#include "stdafx.h"
 
#include "console_internal.h"
 
#include "debug.h"
 
#include "engine_func.h"
 
#include "landscape.h"
 
#include "saveload/saveload.h"
 
#include "network/network.h"
 
#include "network/network_func.h"
 
#include "network/network_base.h"
 
#include "network/network_admin.h"
 
#include "network/network_client.h"
 
#include "command_func.h"
 
#include "settings_func.h"
 
#include "fios.h"
 
#include "fileio_func.h"
 
#include "screenshot.h"
 
#include "genworld.h"
 
#include "strings_func.h"
 
#include "viewport_func.h"
 
#include "window_func.h"
 
#include "date_func.h"
 
#include "company_func.h"
 
#include "gamelog.h"
 
#include "ai/ai.hpp"
 
#include "ai/ai_config.hpp"
 
#include "newgrf.h"
 
#include "newgrf_profiling.h"
 
#include "console_func.h"
 
#include "engine_base.h"
 
#include "road.h"
 
#include "rail.h"
 
#include "game/game.hpp"
 
#include "table/strings.h"
 
#include <time.h>
 

	
 
#include "safeguards.h"
 

	
 
/* scriptfile handling */
 
static bool _script_running; ///< Script is running (used to abort execution when #ConReturn is encountered).
 
static uint _script_current_depth; ///< Depth of scripts running (used to abort execution when #ConReturn is encountered).
 

	
 
/** File list storage for the console, for caching the last 'ls' command. */
 
class ConsoleFileList : public FileList {
 
public:
 
	ConsoleFileList() : FileList()
 
	{
 
		this->file_list_valid = false;
 
	}
 

	
 
	/** Declare the file storage cache as being invalid, also clears all stored files. */
 
	void InvalidateFileList()
 
	{
 
		this->Clear();
 
		this->file_list_valid = false;
 
	}
 

	
 
	/**
 
	 * (Re-)validate the file storage cache. Only makes a change if the storage was invalid, or if \a force_reload.
 
	 * @param force_reload Always reload the file storage cache.
 
	 */
 
	void ValidateFileList(bool force_reload = false)
 
	{
 
		if (force_reload || !this->file_list_valid) {
 
			this->BuildFileList(FT_SAVEGAME, SLO_LOAD);
 
			this->file_list_valid = true;
 
		}
 
	}
 

	
 
	bool file_list_valid; ///< If set, the file list is valid.
 
};
 

	
 
static ConsoleFileList _console_file_list; ///< File storage cache for the console.
 

	
 
/* console command defines */
 
#define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
 
#define DEF_CONSOLE_HOOK(function) static ConsoleHookResult function(bool echo)
 

	
 

	
 
/****************
 
 * command hooks
 
 ****************/
 

	
 
/**
 
 * Check network availability and inform in console about failure of detection.
 
 * @return Network availability.
 
 */
 
static inline bool NetworkAvailable(bool echo)
 
{
 
@@ -915,127 +915,133 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
 
	/* Default settings: default port and new company */
 
	uint16 rport = NETWORK_DEFAULT_PORT;
 
	CompanyID join_as = COMPANY_NEW_COMPANY;
 

	
 
	ParseConnectionString(&company, &port, ip);
 

	
 
	IConsolePrintF(CC_DEFAULT, "Connecting to %s...", ip);
 
	if (company != nullptr) {
 
		join_as = (CompanyID)atoi(company);
 
		IConsolePrintF(CC_DEFAULT, "    company-no: %d", join_as);
 

	
 
		/* From a user pov 0 is a new company, internally it's different and all
 
		 * companies are offset by one to ease up on users (eg companies 1-8 not 0-7) */
 
		if (join_as != COMPANY_SPECTATOR) {
 
			if (join_as > MAX_COMPANIES) return false;
 
			join_as--;
 
		}
 
	}
 
	if (port != nullptr) {
 
		rport = atoi(port);
 
		IConsolePrintF(CC_DEFAULT, "    port: %s", port);
 
	}
 

	
 
	NetworkClientConnectGame(NetworkAddress(ip, rport), join_as);
 

	
 
	return true;
 
}
 

	
 
/*********************************
 
 *  script file console commands
 
 *********************************/
 

	
 
DEF_CONSOLE_CMD(ConExec)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Execute a local script file. Usage: 'exec <script> <?>'");
 
		return true;
 
	}
 

	
 
	if (argc < 2) return false;
 

	
 
	FILE *script_file = FioFOpenFile(argv[1], "r", BASE_DIR);
 

	
 
	if (script_file == nullptr) {
 
		if (argc == 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
 
		return true;
 
	}
 

	
 
	_script_running = true;
 
	_script_current_depth++;
 
	uint script_depth = _script_current_depth;
 

	
 
	char cmdline[ICON_CMDLN_SIZE];
 
	while (_script_running && fgets(cmdline, sizeof(cmdline), script_file) != nullptr) {
 
	while (fgets(cmdline, sizeof(cmdline), script_file) != nullptr) {
 
		/* Remove newline characters from the executing script */
 
		for (char *cmdptr = cmdline; *cmdptr != '\0'; cmdptr++) {
 
			if (*cmdptr == '\n' || *cmdptr == '\r') {
 
				*cmdptr = '\0';
 
				break;
 
			}
 
		}
 
		IConsoleCmdExec(cmdline);
 
		/* Ensure that we are still on the same depth or that we returned via 'return'. */
 
		assert(_script_current_depth == script_depth || _script_current_depth == script_depth - 1);
 

	
 
		/* The 'return' command was executed. */
 
		if (_script_current_depth == script_depth - 1) break;
 
	}
 

	
 
	if (ferror(script_file)) {
 
		IConsoleError("Encountered error while trying to read from script file");
 
	}
 

	
 
	_script_running = false;
 
	if (_script_current_depth == script_depth) _script_current_depth--;
 
	FioFCloseFile(script_file);
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConReturn)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Stop executing a running script. Usage: 'return'");
 
		return true;
 
	}
 

	
 
	_script_running = false;
 
	_script_current_depth--;
 
	return true;
 
}
 

	
 
/*****************************
 
 *  default console commands
 
 ******************************/
 
extern bool CloseConsoleLogIfActive();
 

	
 
DEF_CONSOLE_CMD(ConScript)
 
{
 
	extern FILE *_iconsole_output_file;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("Start or stop logging console output to a file. Usage: 'script <filename>'");
 
		IConsoleHelp("If filename is omitted, a running log is stopped if it is active");
 
		return true;
 
	}
 

	
 
	if (!CloseConsoleLogIfActive()) {
 
		if (argc < 2) return false;
 

	
 
		IConsolePrintF(CC_DEFAULT, "file output started to: %s", argv[1]);
 
		_iconsole_output_file = fopen(argv[1], "ab");
 
		if (_iconsole_output_file == nullptr) IConsoleError("could not open file");
 
	}
 

	
 
	return true;
 
}
 

	
 

	
 
DEF_CONSOLE_CMD(ConEcho)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Print back the first argument to the console. Usage: 'echo <arg>'");
 
		return true;
 
	}
 

	
 
	if (argc < 2) return false;
 
	IConsolePrint(CC_DEFAULT, argv[1]);
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConEchoC)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Print back the first argument to the console in a given colour. Usage: 'echoc <colour> <arg2>'");
 
		return true;
 
	}
0 comments (0 inline, 0 general)