Merge pull request #11568 from endragor/loggers

Extract logging logic
This commit is contained in:
Andreas Haas 2017-10-02 23:51:26 +02:00 committed by GitHub
commit 132ba0ed97
49 changed files with 948 additions and 332 deletions

View file

@ -29,6 +29,7 @@
/*************************************************************************/
#include "error_macros.h"
#include "io/logger.h"
#include "os/os.h"
bool _err_error_exists = false;
@ -79,7 +80,7 @@ void remove_error_handler(ErrorHandlerList *p_handler) {
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (OS::ErrorType)p_type);
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (Logger::ErrorType)p_type);
_global_lock();
ErrorHandlerList *l = error_handler_list;

View file

@ -76,6 +76,11 @@ protected:
};
public:
void flush() {
f.flush();
};
void store_8(uint8_t p_dest) {
f.store_8(p_dest);

View file

@ -338,6 +338,13 @@ Error FileAccessCompressed::get_error() const {
return read_eof ? ERR_FILE_EOF : OK;
}
void FileAccessCompressed::flush() {
ERR_FAIL_COND(!f);
ERR_FAIL_COND(!writing);
// compressed files keep data in memory till close()
}
void FileAccessCompressed::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);

View file

@ -84,6 +84,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists

View file

@ -268,6 +268,12 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
}
}
void FileAccessEncrypted::flush() {
ERR_FAIL_COND(!writing);
// encrypted files keep data in memory till close()
}
void FileAccessEncrypted::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!writing);

View file

@ -71,6 +71,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes

View file

@ -170,6 +170,10 @@ Error FileAccessMemory::get_error() const {
return pos >= length ? ERR_FILE_EOF : OK;
}
void FileAccessMemory::flush() {
ERR_FAIL_COND(!data);
}
void FileAccessMemory::store_8(uint8_t p_byte) {
ERR_FAIL_COND(!data);

View file

@ -62,6 +62,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_byte); ///< store a byte
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes

View file

@ -456,6 +456,10 @@ Error FileAccessNetwork::get_error() const {
return pos == total_size ? ERR_FILE_EOF : OK;
}
void FileAccessNetwork::flush() {
ERR_FAIL();
}
void FileAccessNetwork::store_8(uint8_t p_dest) {
ERR_FAIL();

View file

@ -155,6 +155,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists

View file

@ -293,6 +293,11 @@ Error FileAccessPack::get_error() const {
return OK;
}
void FileAccessPack::flush() {
ERR_FAIL();
}
void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL();

View file

@ -161,6 +161,7 @@ public:
virtual Error get_error() const;
virtual void flush();
virtual void store_8(uint8_t p_dest);
virtual void store_buffer(const uint8_t *p_src, int p_length);

View file

@ -353,6 +353,11 @@ Error FileAccessZip::get_error() const {
return OK;
};
void FileAccessZip::flush() {
ERR_FAIL();
}
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();

View file

@ -108,6 +108,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists

252
core/io/logger.cpp Normal file
View file

@ -0,0 +1,252 @@
/*************************************************************************/
/* logger.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "logger.h"
#include "os/dir_access.h"
#include "os/os.h"
#include "print_string.h"
bool Logger::should_log(bool p_err) {
return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
}
void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
if (!should_log(true)) {
return;
}
const char *err_type = "**ERROR**";
switch (p_type) {
case ERR_ERROR: err_type = "**ERROR**"; break;
case ERR_WARNING: err_type = "**WARNING**"; break;
case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
default: ERR_PRINT("Unknown error type"); break;
}
const char *err_details;
if (p_rationale && *p_rationale)
err_details = p_rationale;
else
err_details = p_code;
logf_error("%s: %s\n", err_type, err_details);
logf_error(" At: %s:%i:%s() - %s\n", p_file, p_line, p_function, p_code);
}
void Logger::logf(const char *p_format, ...) {
if (!should_log(false)) {
return;
}
va_list argp;
va_start(argp, p_format);
logv(p_format, argp, false);
va_end(argp);
}
void Logger::logf_error(const char *p_format, ...) {
if (!should_log(true)) {
return;
}
va_list argp;
va_start(argp, p_format);
logv(p_format, argp, true);
va_end(argp);
}
Logger::~Logger() {}
void RotatedFileLogger::close_file() {
if (file) {
memdelete(file);
file = NULL;
}
}
void RotatedFileLogger::clear_old_backups() {
int max_backups = max_files - 1; // -1 for the current file
String basename = base_path.get_basename();
String extension = "." + base_path.get_extension();
DirAccess *da = DirAccess::open(base_path.get_base_dir());
if (!da) {
return;
}
da->list_dir_begin();
String f = da->get_next();
Set<String> backups;
while (f != String()) {
if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path) {
backups.insert(f);
}
f = da->get_next();
}
da->list_dir_end();
if (backups.size() > max_backups) {
// since backups are appended with timestamp and Set iterates them in sorted order,
// first backups are the oldest
int to_delete = backups.size() - max_backups;
for (Set<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) {
da->remove(E->get());
}
}
memdelete(da);
}
void RotatedFileLogger::rotate_file() {
close_file();
if (FileAccess::exists(base_path)) {
if (max_files > 1) {
char timestamp[21];
OS::Date date = OS::get_singleton()->get_date();
OS::Time time = OS::get_singleton()->get_time();
sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day + 1, time.hour, time.min, time.sec);
String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension();
DirAccess *da = DirAccess::open(base_path.get_base_dir());
if (da) {
da->copy(base_path, backup_name);
memdelete(da);
}
clear_old_backups();
}
} else {
DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA);
if (da) {
da->make_dir_recursive(base_path.get_base_dir());
memdelete(da);
}
}
file = FileAccess::open(base_path, FileAccess::WRITE);
}
RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) {
file = NULL;
base_path = p_base_path.simplify_path();
max_files = p_max_files > 0 ? p_max_files : 1;
rotate_file();
}
void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
if (!should_log(p_err)) {
return;
}
if (file) {
const int static_buf_size = 512;
char static_buf[static_buf_size];
char *buf = static_buf;
int len = vsnprintf(buf, static_buf_size, p_format, p_list);
if (len >= static_buf_size) {
buf = (char *)Memory::alloc_static(len + 1);
vsnprintf(buf, len + 1, p_format, p_list);
}
file->store_buffer((uint8_t *)buf, len);
if (len >= static_buf_size) {
Memory::free_static(buf);
}
#ifdef DEBUG_ENABLED
const bool need_flush = true;
#else
bool need_flush = p_err;
#endif
if (need_flush) {
file->flush();
}
}
}
RotatedFileLogger::~RotatedFileLogger() {
close_file();
}
void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
if (!should_log(p_err)) {
return;
}
if (p_err) {
vfprintf(stderr, p_format, p_list);
} else {
vprintf(p_format, p_list);
#ifdef DEBUG_ENABLED
fflush(stdout);
#endif
}
}
StdLogger::~StdLogger() {}
CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) {
loggers = p_loggers;
}
void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {
if (!should_log(p_err)) {
return;
}
for (int i = 0; i < loggers.size(); ++i) {
va_list list_copy;
va_copy(list_copy, p_list);
loggers[i]->logv(p_format, list_copy, p_err);
va_end(list_copy);
}
}
void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
if (!should_log(true)) {
return;
}
for (int i = 0; i < loggers.size(); ++i) {
loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
}
}
CompositeLogger::~CompositeLogger() {
for (int i = 0; i < loggers.size(); ++i) {
memdelete(loggers[i]);
}
}

107
core/io/logger.h Normal file
View file

@ -0,0 +1,107 @@
/*************************************************************************/
/* logger.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef LOGGER_H
#define LOGGER_H
#include "os/file_access.h"
#include "ustring.h"
#include "vector.h"
#include <stdarg.h>
class Logger {
protected:
bool should_log(bool p_err);
public:
enum ErrorType {
ERR_ERROR,
ERR_WARNING,
ERR_SCRIPT,
ERR_SHADER
};
virtual void logv(const char *p_format, va_list p_list, bool p_err) = 0;
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
void logf(const char *p_format, ...);
void logf_error(const char *p_format, ...);
virtual ~Logger();
};
/**
* Writes messages to stdout/stderr.
*/
class StdLogger : public Logger {
public:
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual ~StdLogger();
};
/**
* Writes messages to the specified file. If the file already exists, creates a copy (backup)
* of it with timestamp appended to the file name. Maximum number of backups is configurable.
* When maximum is reached, the oldest backups are erased. With the maximum being equal to 1,
* it acts as a simple file logger.
*/
class RotatedFileLogger : public Logger {
String base_path;
int max_files;
FileAccess *file;
void rotate_file_without_closing();
void close_file();
void clear_old_backups();
void rotate_file();
public:
RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual ~RotatedFileLogger();
};
class CompositeLogger : public Logger {
Vector<Logger *> loggers;
public:
CompositeLogger(Vector<Logger *> p_loggers);
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
virtual ~CompositeLogger();
};
#endif

View file

@ -55,7 +55,7 @@ FileAccess *FileAccess::create(AccessType p_access) {
bool FileAccess::exists(const String &p_name) {
if (PackedData::get_singleton()->has_path(p_name))
if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name))
return true;
FileAccess *f = open(p_name, READ);

View file

@ -119,6 +119,7 @@ public:
virtual Error get_error() const = 0; ///< get last error
virtual void flush() = 0;
virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint

View file

@ -62,20 +62,20 @@ void OS::debug_break(){
// something
};
void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
const char *err_type = "**ERROR**";
switch (p_type) {
case ERR_ERROR: err_type = "**ERROR**"; break;
case ERR_WARNING: err_type = "**WARNING**"; break;
case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
default: ERR_PRINT("Unknown error type"); break;
void OS::_set_logger(Logger *p_logger) {
if (_logger) {
memdelete(_logger);
}
_logger = p_logger;
}
if (p_rationale && *p_rationale)
print("%s: %s\n ", err_type, p_rationale);
print("%s: At: %s:%i:%s() - %s\n", err_type, p_file, p_line, p_function, p_code);
void OS::initialize_logger() {
_set_logger(memnew(StdLogger));
}
void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) {
_logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
}
void OS::print(const char *p_format, ...) {
@ -83,17 +83,16 @@ void OS::print(const char *p_format, ...) {
va_list argp;
va_start(argp, p_format);
vprint(p_format, argp);
_logger->logv(p_format, argp, false);
va_end(argp);
};
void OS::printerr(const char *p_format, ...) {
va_list argp;
va_start(argp, p_format);
vprint(p_format, argp, true);
_logger->logv(p_format, argp, true);
va_end(argp);
};
@ -533,9 +532,12 @@ OS::OS() {
_allow_hidpi = true;
_stack_bottom = (void *)(&stack_bottom);
_logger = NULL;
_set_logger(memnew(StdLogger));
}
OS::~OS() {
memdelete(_logger);
singleton = NULL;
}

View file

@ -32,6 +32,7 @@
#include "engine.h"
#include "image.h"
#include "io/logger.h"
#include "list.h"
#include "os/main_loop.h"
#include "ustring.h"
@ -61,6 +62,11 @@ class OS {
void *_stack_bottom;
Logger *_logger;
protected:
void _set_logger(Logger *p_logger);
public:
typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection);
@ -108,6 +114,7 @@ protected:
virtual int get_audio_driver_count() const = 0;
virtual const char *get_audio_driver_name(int p_driver) const = 0;
virtual void initialize_logger();
virtual void initialize_core() = 0;
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0;
@ -127,18 +134,10 @@ public:
static OS *get_singleton();
enum ErrorType {
ERR_ERROR,
ERR_WARNING,
ERR_SCRIPT,
ERR_SHADER
};
void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR);
void print(const char *p_format, ...);
void printerr(const char *p_format, ...);
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
virtual void print(const char *p_format, ...);
virtual void printerr(const char *p_format, ...);
virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false) = 0;
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0;
virtual String get_stdin_string(bool p_block = true) = 0;

View file

@ -223,6 +223,12 @@ Error FileAccessUnix::get_error() const {
return last_error;
}
void FileAccessUnix::flush() {
ERR_FAIL_COND(!f);
fflush(f);
}
void FileAccessUnix::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);

View file

@ -72,6 +72,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists

View file

@ -64,39 +64,7 @@
#include <string.h>
#include <sys/time.h>
#include <sys/wait.h>
extern bool _print_error_enabled;
void OS_Unix::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
if (!_print_error_enabled)
return;
const char *err_details;
if (p_rationale && p_rationale[0])
err_details = p_rationale;
else
err_details = p_code;
switch (p_type) {
case ERR_ERROR:
print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
print("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_WARNING:
print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
print("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SCRIPT:
print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
print("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SHADER:
print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
print("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
break;
}
}
#include <unistd.h>
void OS_Unix::debug_break() {
@ -165,29 +133,16 @@ void OS_Unix::initialize_core() {
}
}
void OS_Unix::initialize_logger() {
Vector<Logger *> loggers;
loggers.push_back(memnew(UnixTerminalLogger));
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
_set_logger(memnew(CompositeLogger(loggers)));
}
void OS_Unix::finalize_core() {
}
void OS_Unix::vprint(const char *p_format, va_list p_list, bool p_stder) {
if (p_stder) {
vfprintf(stderr, p_format, p_list);
fflush(stderr);
} else {
vprintf(p_format, p_list);
fflush(stdout);
}
}
void OS_Unix::print(const char *p_format, ...) {
va_list argp;
va_start(argp, p_format);
vprintf(p_format, argp);
va_end(argp);
}
void OS_Unix::alert(const String &p_alert, const String &p_title) {
fprintf(stderr, "ERROR: %s\n", p_alert.utf8().get_data());
@ -559,4 +514,38 @@ String OS_Unix::get_executable_path() const {
#endif
}
void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
if (!should_log(true)) {
return;
}
const char *err_details;
if (p_rationale && p_rationale[0])
err_details = p_rationale;
else
err_details = p_code;
switch (p_type) {
case ERR_WARNING:
logf_error("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SCRIPT:
logf_error("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SHADER:
logf_error("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
logf_error("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_ERROR:
default:
logf_error("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
logf_error("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
break;
}
}
UnixTerminalLogger::~UnixTerminalLogger() {}
#endif

View file

@ -54,11 +54,11 @@ protected:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
virtual void initialize_logger();
virtual void initialize_core();
virtual int unix_initialize_audio(int p_audio_driver);
//virtual void initialize(int p_video_driver,int p_audio_driver);
//virtual void finalize();
virtual void finalize_core();
String stdin_buf;
@ -66,10 +66,6 @@ protected:
String get_global_settings_path() const;
public:
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
virtual void print(const char *p_format, ...);
virtual void vprint(const char *p_format, va_list p_list, bool p_stder = false);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual String get_stdin_string(bool p_block);
@ -120,6 +116,12 @@ public:
//virtual void run( MainLoop * p_main_loop );
};
class UnixTerminalLogger : public StdLogger {
public:
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
virtual ~UnixTerminalLogger();
};
#endif
#endif

View file

@ -0,0 +1,71 @@
/*************************************************************************/
/* syslog_logger.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef UNIX_ENABLED
#include "syslog_logger.h"
#include "print_string.h"
#include <syslog.h>
void SyslogLogger::logv(const char *p_format, va_list p_list, bool p_err) {
if (!should_log(p_err)) {
return;
}
vsyslog(p_err ? LOG_ERR : LOG_INFO, p_format, p_list);
}
void SyslogLogger::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
if (!should_log(true)) {
return;
}
const char *err_type = "**ERROR**";
switch (p_type) {
case ERR_ERROR: err_type = "**ERROR**"; break;
case ERR_WARNING: err_type = "**WARNING**"; break;
case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
default: ERR_PRINT("Unknown error type"); break;
}
const char *err_details;
if (p_rationale && *p_rationale)
err_details = p_rationale;
else
err_details = p_code;
syslog(p_type == ERR_WARNING ? LOG_WARNING : LOG_ERR, "%s: %s\n At: %s:%i:%s() - %s", err_type, err_details, p_file, p_line, p_function, p_code);
}
SyslogLogger::~SyslogLogger() {
}
#endif

View file

@ -0,0 +1,48 @@
/*************************************************************************/
/* syslog_logger.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef SYSLOG_LOGGER_H
#define SYSLOG_LOGGER_H
#ifdef UNIX_ENABLED
#include "io/logger.h"
class SyslogLogger : public Logger {
public:
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
virtual ~SyslogLogger();
};
#endif
#endif

View file

@ -162,10 +162,10 @@ Error DirAccessWindows::make_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
p_dir = fix_path(p_dir);
if (p_dir.is_rel_path())
p_dir = get_current_dir().plus_file(p_dir);
p_dir = fix_path(p_dir);
p_dir = p_dir.replace("/", "\\");
bool success;

View file

@ -207,6 +207,12 @@ Error FileAccessWindows::get_error() const {
return last_error;
}
void FileAccessWindows::flush() {
ERR_FAIL_COND(!f);
fflush(f);
}
void FileAccessWindows::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);

View file

@ -64,6 +64,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists

View file

@ -231,7 +231,6 @@ void Main::print_help(const char *p_binary) {
}
Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_phase) {
RID_OwnerBase::init_rid();
OS::get_singleton()->initialize_core();
@ -254,6 +253,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
register_core_settings(); //here globals is present
OS::get_singleton()->initialize_logger();
translation_server = memnew(TranslationServer);
performance = memnew(Performance);
globals->add_singleton(ProjectSettings::Singleton("Performance", performance));

View file

@ -146,6 +146,11 @@ Error FileAccessAndroid::get_error() const {
return eof ? ERR_FILE_EOF : OK; //not sure what else it may happen
}
void FileAccessAndroid::flush() {
ERR_FAIL();
}
void FileAccessAndroid::store_8(uint8_t p_dest) {
ERR_FAIL();

View file

@ -63,6 +63,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists

View file

@ -157,6 +157,9 @@ Error FileAccessJAndroid::get_error() const {
return OK;
}
void FileAccessJAndroid::flush() {
}
void FileAccessJAndroid::store_8(uint8_t p_dest) {
}

View file

@ -67,6 +67,7 @@ public:
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists

View file

@ -47,6 +47,15 @@
#include "file_access_jandroid.h"
#endif
class AndroidLogger : public Logger {
public:
virtual void logv(const char *p_format, va_list p_list, bool p_err) {
__android_log_vprint(p_err ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "godot", p_format, p_list);
}
virtual ~AndroidLogger() {}
};
int OS_Android::get_video_driver_count() const {
return 1;
@ -111,6 +120,13 @@ void OS_Android::initialize_core() {
#endif
}
void OS_Android::initialize_logger() {
Vector<Logger *> loggers;
loggers.push_back(memnew(AndroidLogger));
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
_set_logger(memnew(CompositeLogger(loggers)));
}
void OS_Android::set_opengl_extensions(const char *p_gl_extensions) {
ERR_FAIL_COND(!p_gl_extensions);
@ -162,23 +178,9 @@ void OS_Android::delete_main_loop() {
}
void OS_Android::finalize() {
memdelete(input);
}
void OS_Android::vprint(const char *p_format, va_list p_list, bool p_stderr) {
__android_log_vprint(p_stderr ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "godot", p_format, p_list);
}
void OS_Android::print(const char *p_format, ...) {
va_list argp;
va_start(argp, p_format);
__android_log_vprint(ANDROID_LOG_INFO, "godot", p_format, argp);
va_end(argp);
}
void OS_Android::alert(const String &p_alert, const String &p_title) {
//print("ALERT: %s\n", p_alert.utf8().get_data());
@ -737,6 +739,8 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI
set_keep_screen_on_func = p_set_keep_screen_on_func;
alert_func = p_alert_func;
use_reload_hooks = false;
_set_logger(memnew(AndroidLogger));
}
OS_Android::~OS_Android() {

View file

@ -149,6 +149,7 @@ public:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@ -161,8 +162,6 @@ public:
static OS *get_singleton();
virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
virtual void print(const char *p_format, ...);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual void set_mouse_show(bool p_show);

View file

@ -41,6 +41,7 @@
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/project_settings.h"
#include "drivers/unix/syslog_logger.h"
#include "sem_iphone.h"
@ -98,6 +99,13 @@ void OSIPhone::initialize_core() {
SemaphoreIphone::make_default();
};
void OSIPhone::initialize_logger() {
Vector<Logger *> loggers;
loggers.push_back(memnew(SyslogLogger));
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
_set_logger(memnew(CompositeLogger(loggers)));
}
void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
supported_orientations = 0;
@ -568,6 +576,8 @@ OSIPhone::OSIPhone(int width, int height) {
vm.resizable = false;
set_video_mode(vm);
event_count = 0;
_set_logger(memnew(SyslogLogger));
};
OSIPhone::~OSIPhone() {

View file

@ -90,6 +90,7 @@ private:
virtual VideoMode get_default_video_mode() const;
virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);

View file

@ -85,6 +85,10 @@ void OS_JavaScript::initialize_core() {
FileAccess::make_default<FileAccessBufferedFA<FileAccessUnix> >(FileAccess::ACCESS_RESOURCES);
}
void OS_JavaScript::initialize_logger() {
_set_logger(memnew(StdLogger));
}
void OS_JavaScript::set_opengl_extensions(const char *p_gl_extensions) {
ERR_FAIL_COND(!p_gl_extensions);

View file

@ -92,6 +92,7 @@ public:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@ -104,11 +105,6 @@ public:
//static OS* get_singleton();
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
OS::print_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
}
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual void set_mouse_mode(MouseMode p_mode);

View file

@ -127,6 +127,7 @@ protected:
virtual const char *get_video_driver_name(int p_driver) const;
virtual VideoMode get_default_video_mode() const;
virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
virtual void finalize();
@ -141,8 +142,6 @@ public:
virtual String get_name();
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual void set_cursor_shape(CursorShape p_shape);

View file

@ -1145,43 +1145,67 @@ String OS_OSX::get_name() {
return "OSX";
}
void OS_OSX::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
if (!_print_error_enabled)
return;
class OSXTerminalLogger : public StdLogger {
public:
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR) {
if (!should_log(true)) {
return;
}
const char *err_details;
if (p_rationale && p_rationale[0])
err_details = p_rationale;
else
err_details = p_code;
const char *err_details;
if (p_rationale && p_rationale[0])
err_details = p_rationale;
else
err_details = p_code;
switch (p_type) {
case ERR_ERROR:
os_log_error(OS_LOG_DEFAULT, "ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
print("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_WARNING:
os_log_info(OS_LOG_DEFAULT, "WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
print("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SCRIPT:
os_log_error(OS_LOG_DEFAULT, "SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
print("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SHADER:
os_log_error(OS_LOG_DEFAULT, "SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
print("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
break;
switch (p_type) {
case ERR_WARNING:
os_log_info(OS_LOG_DEFAULT,
"WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
logf_error("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function,
err_details);
logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SCRIPT:
os_log_error(OS_LOG_DEFAULT,
"SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
logf_error("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function,
err_details);
logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SHADER:
os_log_error(OS_LOG_DEFAULT,
"SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
logf_error("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function,
err_details);
logf_error("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_ERROR:
default:
os_log_error(OS_LOG_DEFAULT,
"ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
logf_error("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
logf_error("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
break;
}
}
};
#else
OS_Unix::print_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
typedef UnixTerminalLogger OSXTerminalLogger;
#endif
void OS_OSX::initialize_logger() {
Vector<Logger *> loggers;
loggers.push_back(memnew(OSXTerminalLogger));
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
_set_logger(memnew(CompositeLogger(loggers)));
}
void OS_OSX::alert(const String &p_alert, const String &p_title) {
@ -2016,6 +2040,8 @@ OS_OSX::OS_OSX() {
window_size = Vector2(1024, 600);
zoomed = false;
display_scale = 1.0;
_set_logger(memnew(OSXTerminalLogger));
}
bool OS_OSX::_check_internal_feature_support(const String &p_feature) {

View file

@ -40,6 +40,7 @@
#include "platform/windows/packet_peer_udp_winsock.h"
#include "platform/windows/stream_peer_winsock.h"
#include "platform/windows/tcp_server_winsock.h"
#include "platform/windows/windows_terminal_logger.h"
#include "project_settings.h"
#include "servers/audio_server.h"
#include "servers/visual/visual_server_raster.h"
@ -182,6 +183,13 @@ void OSUWP::initialize_core() {
cursor_shape = CURSOR_ARROW;
}
void OSUWP::initialize_logger() {
Vector<Logger *> loggers;
loggers.push_back(memnew(WindowsTerminalLogger));
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
_set_logger(memnew(CompositeLogger(loggers)));
}
bool OSUWP::can_draw() const {
return !minimized;
@ -371,32 +379,6 @@ void OSUWP::finalize() {
void OSUWP::finalize_core() {
}
void OSUWP::vprint(const char *p_format, va_list p_list, bool p_stderr) {
char buf[16384 + 1];
int len = vsnprintf(buf, 16384, p_format, p_list);
if (len <= 0)
return;
buf[len] = 0;
int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
if (wlen < 0)
return;
wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
wbuf[wlen] = 0;
if (p_stderr)
fwprintf(stderr, L"%s", wbuf);
else
wprintf(L"%s", wbuf);
free(wbuf);
fflush(stdout);
};
void OSUWP::alert(const String &p_alert, const String &p_title) {
Platform::String ^ alert = ref new Platform::String(p_alert.c_str());
@ -520,30 +502,6 @@ OS::VideoMode OSUWP::get_video_mode(int p_screen) const {
void OSUWP::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
}
void OSUWP::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
const char *err_details;
if (p_rationale && p_rationale[0])
err_details = p_rationale;
else
err_details = p_code;
switch (p_type) {
case ERR_ERROR:
print("ERROR: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
case ERR_WARNING:
print("WARNING: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
case ERR_SCRIPT:
print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
}
}
String OSUWP::get_name() {
return "UWP";
@ -890,6 +848,8 @@ OSUWP::OSUWP() {
mouse_mode_changed = CreateEvent(NULL, TRUE, FALSE, L"os_mouse_mode_changed");
AudioDriverManager::add_driver(&audio_driver);
_set_logger(memnew(WindowsTerminalLogger));
}
OSUWP::~OSUWP() {

View file

@ -163,6 +163,7 @@ protected:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@ -180,9 +181,6 @@ public:
// Event to send to the app wrapper
HANDLE mouse_mode_changed;
void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
String get_stdin_string(bool p_block);

View file

@ -19,6 +19,7 @@ common_win = [
"stream_peer_winsock.cpp",
"joypad.cpp",
"power_windows.cpp",
"windows_terminal_logger.cpp"
]
restarget = "godot_res" + env["OBJSUFFIX"]

View file

@ -48,6 +48,7 @@
#include "servers/visual/visual_server_wrap_mt.h"
#include "stream_peer_winsock.h"
#include "tcp_server_winsock.h"
#include "windows_terminal_logger.h"
#include <process.h>
#include <regstr.h>
@ -205,6 +206,13 @@ void OS_Windows::initialize_core() {
cursor_shape = CURSOR_ARROW;
}
void OS_Windows::initialize_logger() {
Vector<Logger *> loggers;
loggers.push_back(memnew(WindowsTerminalLogger));
loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
_set_logger(memnew(CompositeLogger(loggers)));
}
bool OS_Windows::can_draw() const {
return !minimized;
@ -1231,38 +1239,6 @@ void OS_Windows::finalize_core() {
StreamPeerWinsock::cleanup();
}
void OS_Windows::vprint(const char *p_format, va_list p_list, bool p_stderr) {
const unsigned int BUFFER_SIZE = 16384;
char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
if (len <= 0)
return;
if (len >= BUFFER_SIZE)
len = BUFFER_SIZE; // Output is too big, will be truncated
buf[len] = 0;
int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
if (wlen < 0)
return;
wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
wbuf[wlen] = 0;
if (p_stderr)
fwprintf(stderr, L"%ls", wbuf);
else
wprintf(L"%ls", wbuf);
#ifdef STDOUT_FILE
//vwfprintf(stdo,p_format,p_list);
#endif
free(wbuf);
fflush(stdout);
};
void OS_Windows::alert(const String &p_alert, const String &p_title) {
if (!is_no_window_mode_enabled())
@ -1676,107 +1652,6 @@ void OS_Windows::request_attention() {
FlashWindowEx(&info);
}
void OS_Windows::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
if (!hCon || hCon == INVALID_HANDLE_VALUE) {
const char *err_details;
if (p_rationale && p_rationale[0])
err_details = p_rationale;
else
err_details = p_code;
switch (p_type) {
case ERR_ERROR:
print("ERROR: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
case ERR_WARNING:
print("WARNING: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
case ERR_SCRIPT:
print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
case ERR_SHADER:
print("SHADER ERROR: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
}
} else {
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
GetConsoleScreenBufferInfo(hCon, &sbi);
WORD current_fg = sbi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
uint32_t basecol = 0;
switch (p_type) {
case ERR_ERROR: basecol = FOREGROUND_RED; break;
case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
}
basecol |= current_bg;
if (p_rationale && p_rationale[0]) {
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR: print("ERROR: "); break;
case ERR_WARNING: print("WARNING: "); break;
case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
case ERR_SHADER: print("SHADER ERROR: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
print("%s\n", p_rationale);
SetConsoleTextAttribute(hCon, basecol);
switch (p_type) {
case ERR_ERROR: print(" At: "); break;
case ERR_WARNING: print(" At: "); break;
case ERR_SCRIPT: print(" At: "); break;
case ERR_SHADER: print(" At: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg);
print("%s:%i\n", p_file, p_line);
} else {
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR: print("ERROR: %s: ", p_function); break;
case ERR_WARNING: print("WARNING: %s: ", p_function); break;
case ERR_SCRIPT: print("SCRIPT ERROR: %s: ", p_function); break;
case ERR_SHADER: print("SCRIPT ERROR: %s: ", p_function); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
print("%s\n", p_code);
SetConsoleTextAttribute(hCon, basecol);
switch (p_type) {
case ERR_ERROR: print(" At: "); break;
case ERR_WARNING: print(" At: "); break;
case ERR_SCRIPT: print(" At: "); break;
case ERR_SHADER: print(" At: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg);
print("%s:%i\n", p_file, p_line);
}
SetConsoleTextAttribute(hCon, sbi.wAttributes);
}
}
String OS_Windows::get_name() {
return "Windows";
@ -2429,6 +2304,8 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
#ifdef XAUDIO2_ENABLED
AudioDriverManager::add_driver(&driver_xaudio2);
#endif
_set_logger(memnew(WindowsTerminalLogger));
}
OS_Windows::~OS_Windows() {

View file

@ -152,6 +152,7 @@ protected:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@ -180,9 +181,6 @@ protected:
public:
LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
String get_stdin_string(bool p_block);

View file

@ -0,0 +1,157 @@
/*************************************************************************/
/* windows_terminal_logger.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "windows_terminal_logger.h"
#ifdef WINDOWS_ENABLED
#include <stdio.h>
#include <windows.h>
void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_err) {
if (!should_log(p_err)) {
return;
}
const unsigned int BUFFER_SIZE = 16384;
char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
if (len <= 0)
return;
if (len >= BUFFER_SIZE)
len = BUFFER_SIZE; // Output is too big, will be truncated
buf[len] = 0;
int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
if (wlen < 0)
return;
wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
wbuf[wlen] = 0;
if (p_err)
fwprintf(stderr, L"%ls", wbuf);
else
wprintf(L"%ls", wbuf);
free(wbuf);
#ifdef DEBUG_ENABLED
fflush(stdout);
#endif
}
void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
if (!should_log(true)) {
return;
}
#ifndef UWP_ENABLED
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
if (!hCon || hCon == INVALID_HANDLE_VALUE) {
#endif
StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
#ifndef UWP_ENABLED
} else {
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
GetConsoleScreenBufferInfo(hCon, &sbi);
WORD current_fg = sbi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
uint32_t basecol = 0;
switch (p_type) {
case ERR_ERROR: basecol = FOREGROUND_RED; break;
case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
}
basecol |= current_bg;
if (p_rationale && p_rationale[0]) {
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR: logf("ERROR: "); break;
case ERR_WARNING: logf("WARNING: "); break;
case ERR_SCRIPT: logf("SCRIPT ERROR: "); break;
case ERR_SHADER: logf("SHADER ERROR: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
logf("%s\n", p_rationale);
SetConsoleTextAttribute(hCon, basecol);
switch (p_type) {
case ERR_ERROR: logf(" At: "); break;
case ERR_WARNING: logf(" At: "); break;
case ERR_SCRIPT: logf(" At: "); break;
case ERR_SHADER: logf(" At: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg);
logf("%s:%i\n", p_file, p_line);
} else {
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR: logf("ERROR: %s: ", p_function); break;
case ERR_WARNING: logf("WARNING: %s: ", p_function); break;
case ERR_SCRIPT: logf("SCRIPT ERROR: %s: ", p_function); break;
case ERR_SHADER: logf("SCRIPT ERROR: %s: ", p_function); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
logf("%s\n", p_code);
SetConsoleTextAttribute(hCon, basecol);
switch (p_type) {
case ERR_ERROR: logf(" At: "); break;
case ERR_WARNING: logf(" At: "); break;
case ERR_SCRIPT: logf(" At: "); break;
case ERR_SHADER: logf(" At: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg);
logf("%s:%i\n", p_file, p_line);
}
SetConsoleTextAttribute(hCon, sbi.wAttributes);
}
#endif
}
WindowsTerminalLogger::~WindowsTerminalLogger() {}
#endif

View file

@ -0,0 +1,47 @@
/*************************************************************************/
/* windows_terminal_logger.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef WINDOWS_TERMINAL_LOGGER_H
#define WINDOWS_TERMINAL_LOGGER_H
#ifdef WINDOWS_ENABLED
#include "io/logger.h"
class WindowsTerminalLogger : public StdLogger {
public:
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
virtual ~WindowsTerminalLogger();
};
#endif
#endif