diff --git a/bin/bootstrap.nut b/bin/bootstrap.nut
new file mode 100644
index 00000000..dfe80e8d
--- /dev/null
+++ b/bin/bootstrap.nut
@@ -0,0 +1 @@
+print("Hello World");
\ No newline at end of file
diff --git a/bin/plugins/placeholder b/bin/plugins/placeholder
new file mode 100644
index 00000000..5dd98699
--- /dev/null
+++ b/bin/plugins/placeholder
@@ -0,0 +1 @@
+Keep me!
\ No newline at end of file
diff --git a/bin/sqmod.ini b/bin/sqmod.ini
new file mode 100644
index 00000000..890b6281
--- /dev/null
+++ b/bin/sqmod.ini
@@ -0,0 +1,7 @@
+[Config]
+StackSize=2048
+
+[Scripts]
+Source=bootstrap.nut
+
+[Options]
diff --git a/cbp/Common.cbp b/cbp/Common.cbp
deleted file mode 100644
index a7794c8b..00000000
--- a/cbp/Common.cbp
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/cbp/Hash.cbp b/cbp/Hash.cbp
new file mode 100644
index 00000000..243a9207
--- /dev/null
+++ b/cbp/Hash.cbp
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cbp/Module.cbp b/cbp/Module.cbp
index 5626dd81..cbf68ea3 100644
--- a/cbp/Module.cbp
+++ b/cbp/Module.cbp
@@ -7,124 +7,195 @@
-
+
-
+
+
-
-
-
-
+
-
-
-
-
+
+
+
+
-
+
-
+
-
-
-
+
-
+
-
-
-
+
+
+
-
+
-
+
+
-
-
-
-
-
+
-
-
-
-
+
+
+
+
-
+
-
+
-
-
-
+
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
@@ -137,35 +208,30 @@
+
-
-
+
+
-
-
-
-
-
+
-
-
-
-
+
+
@@ -174,26 +240,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -202,24 +254,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -232,39 +272,25 @@
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
+
diff --git a/cbp/SQLite.cbp b/cbp/SQLite.cbp
index e46221f3..12c1e541 100644
--- a/cbp/SQLite.cbp
+++ b/cbp/SQLite.cbp
@@ -7,71 +7,160 @@
-
+
-
+
+
-
+
+
+
-
+
+
+
-
+
-
+
-
+
+
-
+
+
+
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
@@ -82,7 +171,6 @@
-
diff --git a/cbp/Sandbox.cbp b/cbp/Sandbox.cbp
index 08c96845..b8f4905b 100644
--- a/cbp/Sandbox.cbp
+++ b/cbp/Sandbox.cbp
@@ -8,58 +8,160 @@
-
-
+
+
-
+
-
-
-
+
+
-
-
+
+
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
diff --git a/cbp/Squirrel.cbp b/cbp/Squirrel.cbp
index 2380dd6d..edf0dbe7 100644
--- a/cbp/Squirrel.cbp
+++ b/cbp/Squirrel.cbp
@@ -7,73 +7,155 @@
-
+
-
+
+
-
-
+
+
+
-
+
+
-
-
+
-
+
-
+
+
-
-
+
+
+
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -83,6 +165,7 @@
+
diff --git a/cbp/default.workspace b/cbp/default.workspace
index a39d562b..76bb1e41 100644
--- a/cbp/default.workspace
+++ b/cbp/default.workspace
@@ -3,8 +3,8 @@
-
+
diff --git a/config/common/pugiconfig.hpp b/config/common/pugiconfig.hpp
deleted file mode 100644
index e50b580b..00000000
--- a/config/common/pugiconfig.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * pugixml parser - version 1.7
- * --------------------------------------------------------
- * Copyright (C) 2006-2015, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
- * Report bugs and download new versions at http://pugixml.org/
- *
- * This library is distributed under the MIT License. See notice at the end
- * of this file.
- *
- * This work is based on the pugxml parser, which is:
- * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
- */
-
-#ifndef HEADER_PUGICONFIG_HPP
-#define HEADER_PUGICONFIG_HPP
-
-// Uncomment this to enable wchar_t mode
-// #define PUGIXML_WCHAR_MODE
-
-// Uncomment this to enable compact mode
-// #define PUGIXML_COMPACT
-
-// Uncomment this to disable XPath
-// #define PUGIXML_NO_XPATH
-
-// Uncomment this to disable STL
-// #define PUGIXML_NO_STL
-
-// Uncomment this to disable exceptions
-// #define PUGIXML_NO_EXCEPTIONS
-
-// Set this to control attributes for public classes/functions, i.e.:
-// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
-// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
-// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
-// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
-
-// Tune these constants to adjust memory-related behavior
-// #define PUGIXML_MEMORY_PAGE_SIZE 32768
-// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
-// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
-
-// Uncomment this to switch to header-only version
-// #define PUGIXML_HEADER_ONLY
-
-// Uncomment this to enable long long support
-// #define PUGIXML_HAS_LONG_LONG
-
-#endif
-
-/**
- * Copyright (c) 2006-2015 Arseny Kapoulkine
- *
- * 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.
- */
diff --git a/config/common/sqconfig.h b/config/common/sqconfig.h
index 0ec7ae57..c26a1ac4 100644
--- a/config/common/sqconfig.h
+++ b/config/common/sqconfig.h
@@ -60,7 +60,11 @@ typedef wchar_t SQChar;
#define scstrcmp wcscmp
-#define scsprintf swprintf
+#ifdef _MSC_VER
+#define scsprintf _snwprintf
+#else
+#define scsprintf snwprintf
+#endif
#define scstrlen wcslen
#define scstrtod wcstod
#ifdef _SQ64
@@ -95,7 +99,7 @@ typedef wchar_t SQChar;
#define scisalnum iswalnum
-
+#define sq_rsl(l) ((l)< header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-/* #undef HAVE_LOCALTIME_R */
-
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
- to 0 otherwise. */
-#define HAVE_MALLOC 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `socket' function. */
-/* #undef HAVE_SOCKET */
-
-/* Define to 1 if `stat' has the bug that it succeeds when given the
- zero-length file name argument. */
-/* #undef HAVE_STAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if stdbool.h conforms to C99. */
-#define HAVE_STDBOOL_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_SELECT_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_SOCKET_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if the system has the type `_Bool'. */
-#define HAVE__BOOL 1
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
- slash. */
-/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gyunaev@ulduzsoft.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libircclient"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libircclient 1.3"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libircclient"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.3"
-
-/* Define to the type of arg 1 for `select'. */
-#define SELECT_TYPE_ARG1 int
-
-/* Define to the type of args 2, 3 and 4 for `select'. */
-#define SELECT_TYPE_ARG234 (int *)
-
-/* Define to the type of arg 5 for `select'. */
-#define SELECT_TYPE_ARG5 (struct timeval *)
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if you can safely include both and . */
-#define TIME_WITH_SYS_TIME 1
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to rpl_malloc if the replacement function should be used. */
-/* #undef malloc */
-
-/* Define to `unsigned int' if does not define. */
-/* #undef size_t */
diff --git a/config/mingw64/config.h b/config/mingw64/config.h
deleted file mode 100644
index d1910322..00000000
--- a/config/mingw64/config.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* src/config.h. Generated from config.h.in by configure. */
-/* include/config.h.in. Generated from configure.in by autoheader. */
-
-/* Define to 1 if you have the `getaddrinfo' function. */
-/* #undef HAVE_GETADDRINFO */
-
-/* Define to 1 if you have the `gethostbyname_r' function. */
-/* #undef HAVE_GETHOSTBYNAME_R */
-
-/* Define to 1 if you have the `inet_ntoa' function. */
-/* #undef HAVE_INET_NTOA */
-
-/* Define to 1 if you have the `inet_pton' function. */
-/* #undef HAVE_INET_PTON */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-/* #undef HAVE_LOCALTIME_R */
-
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
- to 0 otherwise. */
-#define HAVE_MALLOC 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `socket' function. */
-/* #undef HAVE_SOCKET */
-
-/* Define to 1 if `stat' has the bug that it succeeds when given the
- zero-length file name argument. */
-/* #undef HAVE_STAT_EMPTY_STRING_BUG */
-
-/* Define to 1 if stdbool.h conforms to C99. */
-#define HAVE_STDBOOL_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_SELECT_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_SOCKET_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if the system has the type `_Bool'. */
-#define HAVE__BOOL 1
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
- slash. */
-/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "gyunaev@ulduzsoft.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libircclient"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libircclient 1.3"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libircclient"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.3"
-
-/* Define to the type of arg 1 for `select'. */
-#define SELECT_TYPE_ARG1 int
-
-/* Define to the type of args 2, 3 and 4 for `select'. */
-#define SELECT_TYPE_ARG234 (int *)
-
-/* Define to the type of arg 5 for `select'. */
-#define SELECT_TYPE_ARG5 (struct timeval *)
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if you can safely include both and . */
-#define TIME_WITH_SYS_TIME 1
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to rpl_malloc if the replacement function should be used. */
-/* #undef malloc */
-
-/* Define to `unsigned int' if does not define. */
-/* #undef size_t */
diff --git a/external/Common/posix.cc b/external/Common/posix.cc
deleted file mode 100644
index d36871f4..00000000
--- a/external/Common/posix.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- A C++ interface to POSIX functions.
-
- Copyright (c) 2014 - 2015, Victor Zverovich
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// Disable bogus MSVC warnings.
-#ifndef _CRT_SECURE_NO_WARNINGS
-# define _CRT_SECURE_NO_WARNINGS
-#endif
-
-#include "posix.h"
-
-#include
-#include
-#include
-
-#ifndef _WIN32
-# include
-#else
-# include
-# include
-
-# define O_CREAT _O_CREAT
-# define O_TRUNC _O_TRUNC
-
-# ifndef S_IRUSR
-# define S_IRUSR _S_IREAD
-# endif
-
-# ifndef S_IWUSR
-# define S_IWUSR _S_IWRITE
-# endif
-
-# ifdef __MINGW32__
-# define _SH_DENYNO 0x40
-# undef fileno
-# endif
-
-#endif // _WIN32
-
-namespace {
-#ifdef _WIN32
-// Return type of read and write functions.
-typedef int RWResult;
-
-// On Windows the count argument to read and write is unsigned, so convert
-// it from size_t preventing integer overflow.
-inline unsigned convert_rwcount(std::size_t count) {
- return count <= UINT_MAX ? static_cast(count) : UINT_MAX;
-}
-#else
-// Return type of read and write functions.
-typedef ssize_t RWResult;
-
-inline std::size_t convert_rwcount(std::size_t count) { return count; }
-#endif
-}
-
-fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT {
- if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
- fmt::report_system_error(errno, "cannot close file");
-}
-
-fmt::BufferedFile::BufferedFile(
- fmt::CStringRef filename, fmt::CStringRef mode) {
- FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
- if (!file_)
- throw SystemError(errno, "cannot open file {}", filename);
-}
-
-void fmt::BufferedFile::close() {
- if (!file_)
- return;
- int result = FMT_SYSTEM(fclose(file_));
- file_ = 0;
- if (result != 0)
- throw SystemError(errno, "cannot close file");
-}
-
-// A macro used to prevent expansion of fileno on broken versions of MinGW.
-#define FMT_ARGS
-
-int fmt::BufferedFile::fileno() const {
- int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
- if (fd == -1)
- throw SystemError(errno, "cannot get file descriptor");
- return fd;
-}
-
-fmt::File::File(fmt::CStringRef path, int oflag) {
- int mode = S_IRUSR | S_IWUSR;
-#if defined(_WIN32) && !defined(__MINGW32__)
- fd_ = -1;
- FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
-#else
- FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
-#endif
- if (fd_ == -1)
- throw SystemError(errno, "cannot open file {}", path);
-}
-
-fmt::File::~File() FMT_NOEXCEPT {
- // Don't retry close in case of EINTR!
- // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
- if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
- fmt::report_system_error(errno, "cannot close file");
-}
-
-void fmt::File::close() {
- if (fd_ == -1)
- return;
- // Don't retry close in case of EINTR!
- // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
- int result = FMT_POSIX_CALL(close(fd_));
- fd_ = -1;
- if (result != 0)
- throw SystemError(errno, "cannot close file");
-}
-
-fmt::LongLong fmt::File::size() const {
-#ifdef _WIN32
- // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
- // is less than 0x0500 as is the case with some default MinGW builds.
- // Both functions support large file sizes.
- DWORD size_upper = 0;
- HANDLE handle = reinterpret_cast(_get_osfhandle(fd_));
- DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper));
- if (size_lower == INVALID_FILE_SIZE) {
- DWORD error = GetLastError();
- if (error != NO_ERROR)
- throw WindowsError(GetLastError(), "cannot get file size");
- }
- fmt::ULongLong long_size = size_upper;
- return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
-#else
- typedef struct stat Stat;
- Stat file_stat = Stat();
- if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
- throw SystemError(errno, "cannot get file attributes");
- FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
- "return type of File::size is not large enough");
- return file_stat.st_size;
-#endif
-}
-
-std::size_t fmt::File::read(void *buffer, std::size_t count) {
- RWResult result = 0;
- FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
- if (result < 0)
- throw SystemError(errno, "cannot read from file");
- return result;
-}
-
-std::size_t fmt::File::write(const void *buffer, std::size_t count) {
- RWResult result = 0;
- FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
- if (result < 0)
- throw SystemError(errno, "cannot write to file");
- return result;
-}
-
-fmt::File fmt::File::dup(int fd) {
- // Don't retry as dup doesn't return EINTR.
- // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
- int new_fd = FMT_POSIX_CALL(dup(fd));
- if (new_fd == -1)
- throw SystemError(errno, "cannot duplicate file descriptor {}", fd);
- return File(new_fd);
-}
-
-void fmt::File::dup2(int fd) {
- int result = 0;
- FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
- if (result == -1) {
- throw SystemError(errno,
- "cannot duplicate file descriptor {} to {}", fd_, fd);
- }
-}
-
-void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT {
- int result = 0;
- FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
- if (result == -1)
- ec = ErrorCode(errno);
-}
-
-void fmt::File::pipe(File &read_end, File &write_end) {
- // Close the descriptors first to make sure that assignments don't throw
- // and there are no leaks.
- read_end.close();
- write_end.close();
- int fds[2] = {};
-#ifdef _WIN32
- // Make the default pipe capacity same as on Linux 2.6.11+.
- enum { DEFAULT_CAPACITY = 65536 };
- int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
-#else
- // Don't retry as the pipe function doesn't return EINTR.
- // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
- int result = FMT_POSIX_CALL(pipe(fds));
-#endif
- if (result != 0)
- throw SystemError(errno, "cannot create pipe");
- // The following assignments don't throw because read_fd and write_fd
- // are closed.
- read_end = File(fds[0]);
- write_end = File(fds[1]);
-}
-
-fmt::BufferedFile fmt::File::fdopen(const char *mode) {
- // Don't retry as fdopen doesn't return EINTR.
- FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
- if (!f)
- throw SystemError(errno, "cannot associate stream with file descriptor");
- BufferedFile file(f);
- fd_ = -1;
- return file;
-}
-
-long fmt::getpagesize() {
-#ifdef _WIN32
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- return si.dwPageSize;
-#else
- long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
- if (size < 0)
- throw SystemError(errno, "cannot get memory page size");
- return size;
-#endif
-}
diff --git a/external/Common/posix.h b/external/Common/posix.h
deleted file mode 100644
index 722690a8..00000000
--- a/external/Common/posix.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- A C++ interface to POSIX functions.
-
- Copyright (c) 2014 - 2015, Victor Zverovich
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FMT_POSIX_H_
-#define FMT_POSIX_H_
-
-#ifdef __MINGW32__
-// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
-# undef __STRICT_ANSI__
-#endif
-
-#include
-#include // for O_RDONLY
-#include
-
-#include
-
-#include "format.h"
-
-#ifndef FMT_POSIX
-# if defined(_WIN32) && !defined(__MINGW32__)
-// Fix warnings about deprecated symbols.
-# define FMT_POSIX(call) _##call
-# else
-# define FMT_POSIX(call) call
-# endif
-#endif
-
-// Calls to system functions are wrapped in FMT_SYSTEM for testability.
-#ifdef FMT_SYSTEM
-# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
-#else
-# define FMT_SYSTEM(call) call
-# ifdef _WIN32
-// Fix warnings about deprecated symbols.
-# define FMT_POSIX_CALL(call) ::_##call
-# else
-# define FMT_POSIX_CALL(call) ::call
-# endif
-#endif
-
-#if FMT_GCC_VERSION >= 407
-# define FMT_UNUSED __attribute__((unused))
-#else
-# define FMT_UNUSED
-#endif
-
-#if FMT_USE_STATIC_ASSERT || FMT_HAS_CPP_ATTRIBUTE(cxx_static_assert) || \
- (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
-# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
-#else
-# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
-# define FMT_STATIC_ASSERT(cond, message) \
- typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
-#endif
-
-// Retries the expression while it evaluates to error_result and errno
-// equals to EINTR.
-#ifndef _WIN32
-# define FMT_RETRY_VAL(result, expression, error_result) \
- do { \
- result = (expression); \
- } while (result == error_result && errno == EINTR)
-#else
-# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
-#endif
-
-#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
-
-namespace fmt {
-
-// An error code.
-class ErrorCode {
- private:
- int value_;
-
- public:
- explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
-
- int get() const FMT_NOEXCEPT { return value_; }
-};
-
-// A buffered file.
-class BufferedFile {
- private:
- FILE *file_;
-
- friend class File;
-
- explicit BufferedFile(FILE *f) : file_(f) {}
-
- public:
- // Constructs a BufferedFile object which doesn't represent any file.
- BufferedFile() FMT_NOEXCEPT : file_(0) {}
-
- // Destroys the object closing the file it represents if any.
- ~BufferedFile() FMT_NOEXCEPT;
-
-#if !FMT_USE_RVALUE_REFERENCES
- // Emulate a move constructor and a move assignment operator if rvalue
- // references are not supported.
-
- private:
- // A proxy object to emulate a move constructor.
- // It is private to make it impossible call operator Proxy directly.
- struct Proxy {
- FILE *file;
- };
-
-public:
- // A "move constructor" for moving from a temporary.
- BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
-
- // A "move constructor" for for moving from an lvalue.
- BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
- f.file_ = 0;
- }
-
- // A "move assignment operator" for moving from a temporary.
- BufferedFile &operator=(Proxy p) {
- close();
- file_ = p.file;
- return *this;
- }
-
- // A "move assignment operator" for moving from an lvalue.
- BufferedFile &operator=(BufferedFile &other) {
- close();
- file_ = other.file_;
- other.file_ = 0;
- return *this;
- }
-
- // Returns a proxy object for moving from a temporary:
- // BufferedFile file = BufferedFile(...);
- operator Proxy() FMT_NOEXCEPT {
- Proxy p = {file_};
- file_ = 0;
- return p;
- }
-
-#else
- private:
- FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
-
- public:
- BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
- other.file_ = 0;
- }
-
- BufferedFile& operator=(BufferedFile &&other) {
- close();
- file_ = other.file_;
- other.file_ = 0;
- return *this;
- }
-#endif
-
- // Opens a file.
- BufferedFile(CStringRef filename, CStringRef mode);
-
- // Closes the file.
- void close();
-
- // Returns the pointer to a FILE object representing this file.
- FILE *get() const FMT_NOEXCEPT { return file_; }
-
- // We place parentheses around fileno to workaround a bug in some versions
- // of MinGW that define fileno as a macro.
- int (fileno)() const;
-
- void print(CStringRef format_str, const ArgList &args) {
- fmt::print(file_, format_str, args);
- }
- FMT_VARIADIC(void, print, CStringRef)
-};
-
-// A file. Closed file is represented by a File object with descriptor -1.
-// Methods that are not declared with FMT_NOEXCEPT may throw
-// fmt::SystemError in case of failure. Note that some errors such as
-// closing the file multiple times will cause a crash on Windows rather
-// than an exception. You can get standard behavior by overriding the
-// invalid parameter handler with _set_invalid_parameter_handler.
-class File {
- private:
- int fd_; // File descriptor.
-
- // Constructs a File object with a given descriptor.
- explicit File(int fd) : fd_(fd) {}
-
- public:
- // Possible values for the oflag argument to the constructor.
- enum {
- RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
- WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
- RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
- };
-
- // Constructs a File object which doesn't represent any file.
- File() FMT_NOEXCEPT : fd_(-1) {}
-
- // Opens a file and constructs a File object representing this file.
- File(CStringRef path, int oflag);
-
-#if !FMT_USE_RVALUE_REFERENCES
- // Emulate a move constructor and a move assignment operator if rvalue
- // references are not supported.
-
- private:
- // A proxy object to emulate a move constructor.
- // It is private to make it impossible call operator Proxy directly.
- struct Proxy {
- int fd;
- };
-
- public:
- // A "move constructor" for moving from a temporary.
- File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
-
- // A "move constructor" for for moving from an lvalue.
- File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
- other.fd_ = -1;
- }
-
- // A "move assignment operator" for moving from a temporary.
- File &operator=(Proxy p) {
- close();
- fd_ = p.fd;
- return *this;
- }
-
- // A "move assignment operator" for moving from an lvalue.
- File &operator=(File &other) {
- close();
- fd_ = other.fd_;
- other.fd_ = -1;
- return *this;
- }
-
- // Returns a proxy object for moving from a temporary:
- // File file = File(...);
- operator Proxy() FMT_NOEXCEPT {
- Proxy p = {fd_};
- fd_ = -1;
- return p;
- }
-
-#else
- private:
- FMT_DISALLOW_COPY_AND_ASSIGN(File);
-
- public:
- File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
- other.fd_ = -1;
- }
-
- File& operator=(File &&other) {
- close();
- fd_ = other.fd_;
- other.fd_ = -1;
- return *this;
- }
-#endif
-
- // Destroys the object closing the file it represents if any.
- ~File() FMT_NOEXCEPT;
-
- // Returns the file descriptor.
- int descriptor() const FMT_NOEXCEPT { return fd_; }
-
- // Closes the file.
- void close();
-
- // Returns the file size.
- LongLong size() const;
-
- // Attempts to read count bytes from the file into the specified buffer.
- std::size_t read(void *buffer, std::size_t count);
-
- // Attempts to write count bytes from the specified buffer to the file.
- std::size_t write(const void *buffer, std::size_t count);
-
- // Duplicates a file descriptor with the dup function and returns
- // the duplicate as a file object.
- static File dup(int fd);
-
- // Makes fd be the copy of this file descriptor, closing fd first if
- // necessary.
- void dup2(int fd);
-
- // Makes fd be the copy of this file descriptor, closing fd first if
- // necessary.
- void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
-
- // Creates a pipe setting up read_end and write_end file objects for reading
- // and writing respectively.
- static void pipe(File &read_end, File &write_end);
-
- // Creates a BufferedFile object associated with this file and detaches
- // this File object from the file.
- BufferedFile fdopen(const char *mode);
-};
-
-// Returns the memory page size.
-long getpagesize();
-} // namespace fmt
-
-#if !FMT_USE_RVALUE_REFERENCES
-namespace std {
-// For compatibility with C++98.
-inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
-inline fmt::File &move(fmt::File &f) { return f; }
-}
-#endif
-
-#endif // FMT_POSIX_H_
diff --git a/external/CppFormat/License.txt b/external/CppFormat/License.txt
deleted file mode 100644
index b1c96ca0..00000000
--- a/external/CppFormat/License.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright (c) 2012 - 2015, Victor Zverovich
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/external/CppFormat/format.cc b/external/CppFormat/format.cc
deleted file mode 100644
index 5f696799..00000000
--- a/external/CppFormat/format.cc
+++ /dev/null
@@ -1,1330 +0,0 @@
-/*
- Formatting library for C++
-
- Copyright (c) 2012 - 2015, Victor Zverovich
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "format.h"
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#if defined(_WIN32) && defined(__MINGW32__)
-# include
-#endif
-
-#if FMT_USE_WINDOWS_H
-# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
-# include
-# else
-# define NOMINMAX
-# include
-# undef NOMINMAX
-# endif
-#endif
-
-using fmt::internal::Arg;
-
-// Check if exceptions are disabled.
-#if __GNUC__ && !__EXCEPTIONS
-# define FMT_EXCEPTIONS 0
-#endif
-#if _MSC_VER && !_HAS_EXCEPTIONS
-# define FMT_EXCEPTIONS 0
-#endif
-#ifndef FMT_EXCEPTIONS
-# define FMT_EXCEPTIONS 1
-#endif
-
-#if FMT_EXCEPTIONS
-# define FMT_TRY try
-# define FMT_CATCH(x) catch (x)
-#else
-# define FMT_TRY if (true)
-# define FMT_CATCH(x) if (false)
-#endif
-
-#ifndef FMT_THROW
-# if FMT_EXCEPTIONS
-# define FMT_THROW(x) throw x
-# else
-# define FMT_THROW(x) assert(false)
-# endif
-#endif
-
-#ifdef FMT_HEADER_ONLY
-# define FMT_FUNC inline
-#else
-# define FMT_FUNC
-#endif
-
-#if _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4127) // conditional expression is constant
-# pragma warning(disable: 4702) // unreachable code
-// Disable deprecation warning for strerror. The latter is not called but
-// MSVC fails to detect it.
-# pragma warning(disable: 4996)
-#endif
-
-// Dummy implementations of strerror_r and strerror_s called if corresponding
-// system functions are not available.
-static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
- return fmt::internal::Null<>();
-}
-static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
- return fmt::internal::Null<>();
-}
-
-namespace fmt {
-namespace {
-
-#ifndef _MSC_VER
-# define FMT_SNPRINTF snprintf
-#else // _MSC_VER
-inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
- va_list args;
- va_start(args, format);
- int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
- va_end(args);
- return result;
-}
-# define FMT_SNPRINTF fmt_snprintf
-#endif // _MSC_VER
-
-#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
-# define FMT_SWPRINTF snwprintf
-#else
-# define FMT_SWPRINTF swprintf
-#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
-
-// Checks if a value fits in int - used to avoid warnings about comparing
-// signed and unsigned integers.
-template
-struct IntChecker {
- template
- static bool fits_in_int(T value) {
- unsigned max = INT_MAX;
- return value <= max;
- }
- static bool fits_in_int(bool) { return true; }
-};
-
-template <>
-struct IntChecker {
- template
- static bool fits_in_int(T value) {
- return value >= INT_MIN && value <= INT_MAX;
- }
- static bool fits_in_int(int) { return true; }
-};
-
-const char RESET_COLOR[] = "\x1b[0m";
-
-typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
-
-// Portable thread-safe version of strerror.
-// Sets buffer to point to a string describing the error code.
-// This can be either a pointer to a string stored in buffer,
-// or a pointer to some static immutable string.
-// Returns one of the following values:
-// 0 - success
-// ERANGE - buffer is not large enough to store the error message
-// other - failure
-// Buffer should be at least of size 1.
-int safe_strerror(
- int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
- FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
-
- class StrError {
- private:
- int error_code_;
- char *&buffer_;
- std::size_t buffer_size_;
-
- // A noop assignment operator to avoid bogus warnings.
- void operator=(const StrError &) {}
-
- // Handle the result of XSI-compliant version of strerror_r.
- int handle(int result) {
- // glibc versions before 2.13 return result in errno.
- return result == -1 ? errno : result;
- }
-
- // Handle the result of GNU-specific version of strerror_r.
- int handle(char *message) {
- // If the buffer is full then the message is probably truncated.
- if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
- return ERANGE;
- buffer_ = message;
- return 0;
- }
-
- // Handle the case when strerror_r is not available.
- int handle(fmt::internal::Null<>) {
- return fallback(strerror_s(buffer_, buffer_size_, error_code_));
- }
-
- // Fallback to strerror_s when strerror_r is not available.
- int fallback(int result) {
- // If the buffer is full then the message is probably truncated.
- return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
- ERANGE : result;
- }
-
- // Fallback to strerror if strerror_r and strerror_s are not available.
- int fallback(fmt::internal::Null<>) {
- errno = 0;
- buffer_ = strerror(error_code_);
- return errno;
- }
-
- public:
- StrError(int err_code, char *&buf, std::size_t buf_size)
- : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
-
- int run() {
- strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
- return handle(strerror_r(error_code_, buffer_, buffer_size_));
- }
- };
- return StrError(error_code, buffer, buffer_size).run();
-}
-
-void format_error_code(fmt::Writer &out, int error_code,
- fmt::StringRef message) FMT_NOEXCEPT {
- // Report error code making sure that the output fits into
- // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
- // bad_alloc.
- out.clear();
- static const char SEP[] = ": ";
- static const char ERROR_STR[] = "error ";
- fmt::internal::IntTraits::MainType ec_value = error_code;
- // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
- std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
- error_code_size += fmt::internal::count_digits(ec_value);
- if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
- out << message << SEP;
- out << ERROR_STR << error_code;
- assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
-}
-
-void report_error(FormatFunc func,
- int error_code, fmt::StringRef message) FMT_NOEXCEPT {
- fmt::MemoryWriter full_message;
- func(full_message, error_code, message);
- // Use Writer::data instead of Writer::c_str to avoid potential memory
- // allocation.
- std::fwrite(full_message.data(), full_message.size(), 1, stderr);
- std::fputc('\n', stderr);
-}
-
-// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
-class IsZeroInt : public fmt::internal::ArgVisitor {
- public:
- template
- bool visit_any_int(T value) { return value == 0; }
-};
-
-// Parses an unsigned integer advancing s to the end of the parsed input.
-// This function assumes that the first character of s is a digit.
-template
-int parse_nonnegative_int(const Char *&s) {
- assert('0' <= *s && *s <= '9');
- unsigned value = 0;
- do {
- unsigned new_value = value * 10 + (*s++ - '0');
- // Check if value wrapped around.
- if (new_value < value) {
- value = UINT_MAX;
- break;
- }
- value = new_value;
- } while ('0' <= *s && *s <= '9');
- if (value > INT_MAX)
- FMT_THROW(fmt::FormatError("number is too big"));
- return value;
-}
-
-template
-inline bool is_name_start(Char c) {
- return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
-}
-
-inline void require_numeric_argument(const Arg &arg, char spec) {
- if (arg.type > Arg::LAST_NUMERIC_TYPE) {
- std::string message =
- fmt::format("format specifier '{}' requires numeric argument", spec);
- FMT_THROW(fmt::FormatError(message));
- }
-}
-
-template
-void check_sign(const Char *&s, const Arg &arg) {
- char sign = static_cast(*s);
- require_numeric_argument(arg, sign);
- if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
- FMT_THROW(fmt::FormatError(fmt::format(
- "format specifier '{}' requires signed argument", sign)));
- }
- ++s;
-}
-
-// Checks if an argument is a valid printf width specifier and sets
-// left alignment if it is negative.
-class WidthHandler : public fmt::internal::ArgVisitor {
- private:
- fmt::FormatSpec &spec_;
-
- FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
-
- public:
- explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
-
- void report_unhandled_arg() {
- FMT_THROW(fmt::FormatError("width is not integer"));
- }
-
- template
- unsigned visit_any_int(T value) {
- typedef typename fmt::internal::IntTraits::MainType UnsignedType;
- UnsignedType width = value;
- if (fmt::internal::is_negative(value)) {
- spec_.align_ = fmt::ALIGN_LEFT;
- width = 0 - width;
- }
- if (width > INT_MAX)
- FMT_THROW(fmt::FormatError("number is too big"));
- return static_cast(width);
- }
-};
-
-class PrecisionHandler :
- public fmt::internal::ArgVisitor {
- public:
- void report_unhandled_arg() {
- FMT_THROW(fmt::FormatError("precision is not integer"));
- }
-
- template
- int visit_any_int(T value) {
- if (!IntChecker::is_signed>::fits_in_int(value))
- FMT_THROW(fmt::FormatError("number is too big"));
- return static_cast(value);
- }
-};
-
-// Converts an integer argument to an integral type T for printf.
-template
-class ArgConverter : public fmt::internal::ArgVisitor, void> {
- private:
- fmt::internal::Arg &arg_;
- wchar_t type_;
-
- FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
-
- public:
- ArgConverter(fmt::internal::Arg &arg, wchar_t type)
- : arg_(arg), type_(type) {}
-
- template
- void visit_any_int(U value) {
- bool is_signed = type_ == 'd' || type_ == 'i';
- using fmt::internal::Arg;
- if (sizeof(T) <= sizeof(int)) {
- // Extra casts are used to silence warnings.
- if (is_signed) {
- arg_.type = Arg::INT;
- arg_.int_value = static_cast(static_cast(value));
- } else {
- arg_.type = Arg::UINT;
- arg_.uint_value = static_cast(
- static_cast::Type>(value));
- }
- } else {
- if (is_signed) {
- arg_.type = Arg::LONG_LONG;
- arg_.long_long_value =
- static_cast::Type>(value);
- } else {
- arg_.type = Arg::ULONG_LONG;
- arg_.ulong_long_value =
- static_cast::Type>(value);
- }
- }
- }
-};
-
-// Converts an integer argument to char for printf.
-class CharConverter : public fmt::internal::ArgVisitor {
- private:
- fmt::internal::Arg &arg_;
-
- FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
-
- public:
- explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
-
- template
- void visit_any_int(T value) {
- arg_.type = Arg::CHAR;
- arg_.int_value = static_cast(value);
- }
-};
-} // namespace
-
-namespace internal {
-
-template
-class BasicArgFormatter : public ArgVisitor {
- private:
- BasicWriter &writer_;
- FormatSpec &spec_;
-
- FMT_DISALLOW_COPY_AND_ASSIGN(BasicArgFormatter);
-
- protected:
- BasicWriter &writer() { return writer_; }
- const FormatSpec &spec() const { return spec_; }
-
- public:
- BasicArgFormatter(BasicWriter &w, FormatSpec &s)
- : writer_(w), spec_(s) {}
-
- template
- void visit_any_int(T value) { writer_.write_int(value, spec_); }
-
- template
- void visit_any_double(T value) { writer_.write_double(value, spec_); }
-
- void visit_bool(bool value) {
- if (spec_.type_) {
- writer_.write_int(value, spec_);
- return;
- }
- const char *str_value = value ? "true" : "false";
- Arg::StringValue str = { str_value, strlen(str_value) };
- writer_.write_str(str, spec_);
- }
-
- void visit_char(int value) {
- if (spec_.type_ && spec_.type_ != 'c') {
- spec_.flags_ |= CHAR_FLAG;
- writer_.write_int(value, spec_);
- return;
- }
- if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
- FMT_THROW(FormatError("invalid format specifier for char"));
- typedef typename BasicWriter::CharPtr CharPtr;
- Char fill = internal::CharTraits::cast(spec_.fill());
- CharPtr out = CharPtr();
- const unsigned CHAR_WIDTH = 1;
- if (spec_.width_ > CHAR_WIDTH) {
- out = writer_.grow_buffer(spec_.width_);
- if (spec_.align_ == ALIGN_RIGHT) {
- std::fill_n(out, spec_.width_ - CHAR_WIDTH, fill);
- out += spec_.width_ - CHAR_WIDTH;
- } else if (spec_.align_ == ALIGN_CENTER) {
- out = writer_.fill_padding(out, spec_.width_,
- internal::check(CHAR_WIDTH), fill);
- } else {
- std::fill_n(out + CHAR_WIDTH, spec_.width_ - CHAR_WIDTH, fill);
- }
- } else {
- out = writer_.grow_buffer(CHAR_WIDTH);
- }
- *out = internal::CharTraits::cast(value);
- }
-
- void visit_string(Arg::StringValue value) {
- writer_.write_str(value, spec_);
- }
-
- using ArgVisitor::visit_wstring;
-
- void visit_wstring(Arg::StringValue value) {
- writer_.write_str(value, spec_);
- }
-
- void visit_pointer(const void *value) {
- if (spec_.type_ && spec_.type_ != 'p')
- report_unknown_type(spec_.type_, "pointer");
- spec_.flags_ = HASH_FLAG;
- spec_.type_ = 'x';
- writer_.write_int(reinterpret_cast(value), spec_);
- }
-};
-
-// An argument formatter.
-template
-class ArgFormatter : public BasicArgFormatter, Char> {
- private:
- BasicFormatter &formatter_;
- const Char *format_;
-
- public:
- ArgFormatter(BasicFormatter &f, FormatSpec &s, const Char *fmt)
- : BasicArgFormatter, Char>(f.writer(), s),
- formatter_(f), format_(fmt) {}
-
- void visit_custom(Arg::CustomValue c) {
- c.format(&formatter_, c.value, &format_);
- }
-};
-
-template
-class PrintfArgFormatter :
- public BasicArgFormatter, Char> {
- public:
- PrintfArgFormatter(BasicWriter &w, FormatSpec &s)
- : BasicArgFormatter, Char>(w, s) {}
-
- void visit_char(int value) {
- const FormatSpec &fmt_spec = this->spec();
- BasicWriter &w = this->writer();
- if (fmt_spec.type_ && fmt_spec.type_ != 'c')
- w.write_int(value, fmt_spec);
- typedef typename BasicWriter::CharPtr CharPtr;
- CharPtr out = CharPtr();
- if (fmt_spec.width_ > 1) {
- Char fill = ' ';
- out = w.grow_buffer(fmt_spec.width_);
- if (fmt_spec.align_ != ALIGN_LEFT) {
- std::fill_n(out, fmt_spec.width_ - 1, fill);
- out += fmt_spec.width_ - 1;
- } else {
- std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
- }
- } else {
- out = w.grow_buffer(1);
- }
- *out = static_cast(value);
- }
-
- void visit_custom(Arg::CustomValue c) {
- BasicFormatter formatter(ArgList(), this->writer());
- const Char format_str[] = {'}', 0};
- const Char *format = format_str;
- c.format(&formatter, c.value, &format);
- }
-};
-} // namespace internal
-} // namespace fmt
-
-FMT_FUNC void fmt::SystemError::init(
- int err_code, CStringRef format_str, ArgList args) {
- error_code_ = err_code;
- MemoryWriter w;
- internal::format_system_error(w, err_code, format(format_str, args));
- std::runtime_error &base = *this;
- base = std::runtime_error(w.str());
-}
-
-template
-int fmt::internal::CharTraits::format_float(
- char *buffer, std::size_t size, const char *format,
- unsigned width, int precision, T value) {
- if (width == 0) {
- return precision < 0 ?
- FMT_SNPRINTF(buffer, size, format, value) :
- FMT_SNPRINTF(buffer, size, format, precision, value);
- }
- return precision < 0 ?
- FMT_SNPRINTF(buffer, size, format, width, value) :
- FMT_SNPRINTF(buffer, size, format, width, precision, value);
-}
-
-template
-int fmt::internal::CharTraits::format_float(
- wchar_t *buffer, std::size_t size, const wchar_t *format,
- unsigned width, int precision, T value) {
- if (width == 0) {
- return precision < 0 ?
- FMT_SWPRINTF(buffer, size, format, value) :
- FMT_SWPRINTF(buffer, size, format, precision, value);
- }
- return precision < 0 ?
- FMT_SWPRINTF(buffer, size, format, width, value) :
- FMT_SWPRINTF(buffer, size, format, width, precision, value);
-}
-
-template
-const char fmt::internal::BasicData::DIGITS[] =
- "0001020304050607080910111213141516171819"
- "2021222324252627282930313233343536373839"
- "4041424344454647484950515253545556575859"
- "6061626364656667686970717273747576777879"
- "8081828384858687888990919293949596979899";
-
-#define FMT_POWERS_OF_10(factor) \
- factor * 10, \
- factor * 100, \
- factor * 1000, \
- factor * 10000, \
- factor * 100000, \
- factor * 1000000, \
- factor * 10000000, \
- factor * 100000000, \
- factor * 1000000000
-
-template
-const uint32_t fmt::internal::BasicData::POWERS_OF_10_32[] = {
- 0, FMT_POWERS_OF_10(1)
-};
-
-template
-const uint64_t fmt::internal::BasicData::POWERS_OF_10_64[] = {
- 0,
- FMT_POWERS_OF_10(1),
- FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
- // Multiply several constants instead of using a single long long constant
- // to avoid warnings about C++98 not supporting long long.
- fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
-};
-
-FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
- (void)type;
- if (std::isprint(static_cast(code))) {
- FMT_THROW(fmt::FormatError(
- fmt::format("unknown format code '{}' for {}", code, type)));
- }
- FMT_THROW(fmt::FormatError(
- fmt::format("unknown format code '\\x{:02x}' for {}",
- static_cast(code), type)));
-}
-
-#if FMT_USE_WINDOWS_H
-
-FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
- static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
- if (s.size() > INT_MAX)
- FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
- int s_size = static_cast(s.size());
- int length = MultiByteToWideChar(
- CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
- if (length == 0)
- FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
- buffer_.resize(length + 1);
- length = MultiByteToWideChar(
- CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
- if (length == 0)
- FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
- buffer_[length] = 0;
-}
-
-FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
- if (int error_code = convert(s)) {
- FMT_THROW(WindowsError(error_code,
- "cannot convert string from UTF-16 to UTF-8"));
- }
-}
-
-FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
- if (s.size() > INT_MAX)
- return ERROR_INVALID_PARAMETER;
- int s_size = static_cast(s.size());
- int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
- if (length == 0)
- return GetLastError();
- buffer_.resize(length + 1);
- length = WideCharToMultiByte(
- CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
- if (length == 0)
- return GetLastError();
- buffer_[length] = 0;
- return 0;
-}
-
-FMT_FUNC void fmt::WindowsError::init(
- int err_code, CStringRef format_str, ArgList args) {
- error_code_ = err_code;
- MemoryWriter w;
- internal::format_windows_error(w, err_code, format(format_str, args));
- std::runtime_error &base = *this;
- base = std::runtime_error(w.str());
-}
-
-FMT_FUNC void fmt::internal::format_windows_error(
- fmt::Writer &out, int error_code,
- fmt::StringRef message) FMT_NOEXCEPT {
- class String {
- private:
- LPWSTR str_;
-
- public:
- String() : str_() {}
- ~String() { LocalFree(str_); }
- LPWSTR *ptr() { return &str_; }
- LPCWSTR c_str() const { return str_; }
- };
- FMT_TRY {
- String system_message;
- if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
- error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- reinterpret_cast(system_message.ptr()), 0, 0)) {
- UTF16ToUTF8 utf8_message;
- if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
- out << message << ": " << utf8_message;
- return;
- }
- }
- } FMT_CATCH(...) {}
- format_error_code(out, error_code, message);
-}
-
-#endif // FMT_USE_WINDOWS_H
-
-FMT_FUNC void fmt::internal::format_system_error(
- fmt::Writer &out, int error_code,
- fmt::StringRef message) FMT_NOEXCEPT {
- FMT_TRY {
- MemoryBuffer buffer;
- buffer.resize(INLINE_BUFFER_SIZE);
- for (;;) {
- char *system_message = &buffer[0];
- int result = safe_strerror(error_code, system_message, buffer.size());
- if (result == 0) {
- out << message << ": " << system_message;
- return;
- }
- if (result != ERANGE)
- break; // Can't get error message, report error code instead.
- buffer.resize(buffer.size() * 2);
- }
- } FMT_CATCH(...) {}
- format_error_code(out, error_code, message);
-}
-
-template
-void fmt::internal::ArgMap::init(const ArgList &args) {
- if (!map_.empty())
- return;
- typedef internal::NamedArg NamedArg;
- const NamedArg *named_arg = 0;
- bool use_values =
- args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
- if (use_values) {
- for (unsigned i = 0;/*nothing*/; ++i) {
- internal::Arg::Type arg_type = args.type(i);
- switch (arg_type) {
- case internal::Arg::NONE:
- return;
- case internal::Arg::NAMED_ARG:
- named_arg = static_cast(args.values_[i].pointer);
- map_.insert(Pair(named_arg->name, *named_arg));
- break;
- default:
- /*nothing*/;
- }
- }
- return;
- }
- for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
- internal::Arg::Type arg_type = args.type(i);
- if (arg_type == internal::Arg::NAMED_ARG) {
- named_arg = static_cast(args.args_[i].pointer);
- map_.insert(Pair(named_arg->name, *named_arg));
- }
- }
- for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
- switch (args.args_[i].type) {
- case internal::Arg::NONE:
- return;
- case internal::Arg::NAMED_ARG:
- named_arg = static_cast(args.args_[i].pointer);
- map_.insert(Pair(named_arg->name, *named_arg));
- break;
- default:
- /*nothing*/;
- }
- }
-}
-
-template
-void fmt::internal::FixedBuffer::grow(std::size_t) {
- FMT_THROW(std::runtime_error("buffer overflow"));
-}
-
-template
-template
-void fmt::BasicWriter::write_str(
- const Arg::StringValue &s, const FormatSpec &spec) {
- // Check if StrChar is convertible to Char.
- internal::CharTraits::convert(StrChar());
- if (spec.type_ && spec.type_ != 's')
- internal::report_unknown_type(spec.type_, "string");
- const StrChar *str_value = s.value;
- std::size_t str_size = s.size;
- if (str_size == 0) {
- if (!str_value) {
- FMT_THROW(FormatError("string pointer is null"));
- return;
- }
- if (*str_value)
- str_size = std::char_traits::length(str_value);
- }
- std::size_t precision = spec.precision_;
- if (spec.precision_ >= 0 && precision < str_size)
- str_size = spec.precision_;
- write_str(str_value, str_size, spec);
-}
-
-template
-inline Arg fmt::BasicFormatter::get_arg(
- BasicStringRef arg_name, const char *&error) {
- if (check_no_auto_index(error)) {
- map_.init(args());
- const Arg *arg = map_.find(arg_name);
- if (arg)
- return *arg;
- error = "argument not found";
- }
- return Arg();
-}
-
-template
-inline Arg fmt::BasicFormatter::parse_arg_index(const Char *&s) {
- const char *error = 0;
- Arg arg = *s < '0' || *s > '9' ?
- next_arg(error) : get_arg(parse_nonnegative_int(s), error);
- if (error) {
- FMT_THROW(FormatError(
- *s != '}' && *s != ':' ? "invalid format string" : error));
- }
- return arg;
-}
-
-template
-inline Arg fmt::BasicFormatter::parse_arg_name(const Char *&s) {
- assert(is_name_start(*s));
- const Char *start = s;
- Char c;
- do {
- c = *++s;
- } while (is_name_start(c) || ('0' <= c && c <= '9'));
- const char *error = 0;
- Arg arg = get_arg(fmt::BasicStringRef(start, s - start), error);
- if (error)
- FMT_THROW(fmt::FormatError(error));
- return arg;
-}
-
-FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
- unsigned arg_index, const char *&error) {
- Arg arg = args_[arg_index];
- switch (arg.type) {
- case Arg::NONE:
- error = "argument index out of range";
- break;
- case Arg::NAMED_ARG:
- arg = *static_cast(arg.pointer);
- default:
- /*nothing*/;
- }
- return arg;
-}
-
-inline Arg fmt::internal::FormatterBase::next_arg(const char *&error) {
- if (next_arg_index_ >= 0)
- return do_get_arg(next_arg_index_++, error);
- error = "cannot switch from manual to automatic argument indexing";
- return Arg();
-}
-
-inline bool fmt::internal::FormatterBase::check_no_auto_index(
- const char *&error) {
- if (next_arg_index_ > 0) {
- error = "cannot switch from automatic to manual argument indexing";
- return false;
- }
- next_arg_index_ = -1;
- return true;
-}
-
-inline Arg fmt::internal::FormatterBase::get_arg(
- unsigned arg_index, const char *&error) {
- return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
-}
-
-template
-void fmt::internal::PrintfFormatter::parse_flags(
- FormatSpec &spec, const Char *&s) {
- for (;;) {
- switch (*s++) {
- case '-':
- spec.align_ = ALIGN_LEFT;
- break;
- case '+':
- spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
- break;
- case '0':
- spec.fill_ = '0';
- break;
- case ' ':
- spec.flags_ |= SIGN_FLAG;
- break;
- case '#':
- spec.flags_ |= HASH_FLAG;
- break;
- default:
- --s;
- return;
- }
- }
-}
-
-template
-Arg fmt::internal::PrintfFormatter::get_arg(
- const Char *s, unsigned arg_index) {
- (void)s;
- const char *error = 0;
- Arg arg = arg_index == UINT_MAX ?
- next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
- if (error)
- FMT_THROW(FormatError(!*s ? "invalid format string" : error));
- return arg;
-}
-
-template
-unsigned fmt::internal::PrintfFormatter::parse_header(
- const Char *&s, FormatSpec &spec) {
- unsigned arg_index = UINT_MAX;
- Char c = *s;
- if (c >= '0' && c <= '9') {
- // Parse an argument index (if followed by '$') or a width possibly
- // preceded with '0' flag(s).
- unsigned value = parse_nonnegative_int(s);
- if (*s == '$') { // value is an argument index
- ++s;
- arg_index = value;
- } else {
- if (c == '0')
- spec.fill_ = '0';
- if (value != 0) {
- // Nonzero value means that we parsed width and don't need to
- // parse it or flags again, so return now.
- spec.width_ = value;
- return arg_index;
- }
- }
- }
- parse_flags(spec, s);
- // Parse width.
- if (*s >= '0' && *s <= '9') {
- spec.width_ = parse_nonnegative_int(s);
- } else if (*s == '*') {
- ++s;
- spec.width_ = WidthHandler(spec).visit(get_arg(s));
- }
- return arg_index;
-}
-
-template
-void fmt::internal::PrintfFormatter::format(
- BasicWriter &writer, BasicCStringRef format_str) {
- const Char *start = format_str.c_str();
- const Char *s = start;
- while (*s) {
- Char c = *s++;
- if (c != '%') continue;
- if (*s == c) {
- write(writer, start, s);
- start = ++s;
- continue;
- }
- write(writer, start, s - 1);
-
- FormatSpec spec;
- spec.align_ = ALIGN_RIGHT;
-
- // Parse argument index, flags and width.
- unsigned arg_index = parse_header(s, spec);
-
- // Parse precision.
- if (*s == '.') {
- ++s;
- if ('0' <= *s && *s <= '9') {
- spec.precision_ = parse_nonnegative_int(s);
- } else if (*s == '*') {
- ++s;
- spec.precision_ = PrecisionHandler().visit(get_arg(s));
- }
- }
-
- Arg arg = get_arg(s, arg_index);
- if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
- spec.flags_ &= ~HASH_FLAG;
- if (spec.fill_ == '0') {
- if (arg.type <= Arg::LAST_NUMERIC_TYPE)
- spec.align_ = ALIGN_NUMERIC;
- else
- spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
- }
-
- // Parse length and convert the argument to the required type.
- switch (*s++) {
- case 'h':
- if (*s == 'h')
- ArgConverter(arg, *++s).visit(arg);
- else
- ArgConverter(arg, *s).visit(arg);
- break;
- case 'l':
- if (*s == 'l')
- ArgConverter(arg, *++s).visit(arg);
- else
- ArgConverter(arg, *s).visit(arg);
- break;
- case 'j':
- ArgConverter(arg, *s).visit(arg);
- break;
- case 'z':
- ArgConverter(arg, *s).visit(arg);
- break;
- case 't':
- ArgConverter(arg, *s).visit(arg);
- break;
- case 'L':
- // printf produces garbage when 'L' is omitted for long double, no
- // need to do the same.
- break;
- default:
- --s;
- ArgConverter(arg, *s).visit(arg);
- }
-
- // Parse type.
- if (!*s)
- FMT_THROW(FormatError("invalid format string"));
- spec.type_ = static_cast(*s++);
- if (arg.type <= Arg::LAST_INTEGER_TYPE) {
- // Normalize type.
- switch (spec.type_) {
- case 'i': case 'u':
- spec.type_ = 'd';
- break;
- case 'c':
- // TODO: handle wchar_t
- CharConverter(arg).visit(arg);
- break;
- }
- }
-
- start = s;
-
- // Format argument.
- internal::PrintfArgFormatter(writer, spec).visit(arg);
- }
- write(writer, start, s);
-}
-
-template
-const Char *fmt::BasicFormatter::format(
- const Char *&format_str, const Arg &arg) {
- const Char *s = format_str;
- FormatSpec spec;
- if (*s == ':') {
- if (arg.type == Arg::CUSTOM) {
- arg.custom.format(this, arg.custom.value, &s);
- return s;
- }
- ++s;
- // Parse fill and alignment.
- if (Char c = *s) {
- const Char *p = s + 1;
- spec.align_ = ALIGN_DEFAULT;
- do {
- switch (*p) {
- case '<':
- spec.align_ = ALIGN_LEFT;
- break;
- case '>':
- spec.align_ = ALIGN_RIGHT;
- break;
- case '=':
- spec.align_ = ALIGN_NUMERIC;
- break;
- case '^':
- spec.align_ = ALIGN_CENTER;
- break;
- }
- if (spec.align_ != ALIGN_DEFAULT) {
- if (p != s) {
- if (c == '}') break;
- if (c == '{')
- FMT_THROW(FormatError("invalid fill character '{'"));
- s += 2;
- spec.fill_ = c;
- } else ++s;
- if (spec.align_ == ALIGN_NUMERIC)
- require_numeric_argument(arg, '=');
- break;
- }
- } while (--p >= s);
- }
-
- // Parse sign.
- switch (*s) {
- case '+':
- check_sign(s, arg);
- spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
- break;
- case '-':
- check_sign(s, arg);
- spec.flags_ |= MINUS_FLAG;
- break;
- case ' ':
- check_sign(s, arg);
- spec.flags_ |= SIGN_FLAG;
- break;
- }
-
- if (*s == '#') {
- require_numeric_argument(arg, '#');
- spec.flags_ |= HASH_FLAG;
- ++s;
- }
-
- // Parse zero flag.
- if (*s == '0') {
- require_numeric_argument(arg, '0');
- spec.align_ = ALIGN_NUMERIC;
- spec.fill_ = '0';
- ++s;
- }
-
- // Parse width.
- if ('0' <= *s && *s <= '9') {
- spec.width_ = parse_nonnegative_int(s);
- } else if (*s == '{') {
- ++s;
- Arg width_arg = is_name_start(*s) ?
- parse_arg_name(s) : parse_arg_index(s);
- if (*s++ != '}')
- FMT_THROW(FormatError("invalid format string"));
- ULongLong value = 0;
- switch (width_arg.type) {
- case Arg::INT:
- if (width_arg.int_value < 0)
- FMT_THROW(FormatError("negative width"));
- value = width_arg.int_value;
- break;
- case Arg::UINT:
- value = width_arg.uint_value;
- break;
- case Arg::LONG_LONG:
- if (width_arg.long_long_value < 0)
- FMT_THROW(FormatError("negative width"));
- value = width_arg.long_long_value;
- break;
- case Arg::ULONG_LONG:
- value = width_arg.ulong_long_value;
- break;
- default:
- FMT_THROW(FormatError("width is not integer"));
- }
- if (value > INT_MAX)
- FMT_THROW(FormatError("number is too big"));
- spec.width_ = static_cast(value);
- }
-
- // Parse precision.
- if (*s == '.') {
- ++s;
- spec.precision_ = 0;
- if ('0' <= *s && *s <= '9') {
- spec.precision_ = parse_nonnegative_int(s);
- } else if (*s == '{') {
- ++s;
- Arg precision_arg =
- is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
- if (*s++ != '}')
- FMT_THROW(FormatError("invalid format string"));
- ULongLong value = 0;
- switch (precision_arg.type) {
- case Arg::INT:
- if (precision_arg.int_value < 0)
- FMT_THROW(FormatError("negative precision"));
- value = precision_arg.int_value;
- break;
- case Arg::UINT:
- value = precision_arg.uint_value;
- break;
- case Arg::LONG_LONG:
- if (precision_arg.long_long_value < 0)
- FMT_THROW(FormatError("negative precision"));
- value = precision_arg.long_long_value;
- break;
- case Arg::ULONG_LONG:
- value = precision_arg.ulong_long_value;
- break;
- default:
- FMT_THROW(FormatError("precision is not integer"));
- }
- if (value > INT_MAX)
- FMT_THROW(FormatError("number is too big"));
- spec.precision_ = static_cast(value);
- } else {
- FMT_THROW(FormatError("missing precision specifier"));
- }
- if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
- FMT_THROW(FormatError(
- fmt::format("precision not allowed in {} format specifier",
- arg.type == Arg::POINTER ? "pointer" : "integer")));
- }
- }
-
- // Parse type.
- if (*s != '}' && *s)
- spec.type_ = static_cast(*s++);
- }
-
- if (*s++ != '}')
- FMT_THROW(FormatError("missing '}' in format string"));
-
- // Format argument.
- internal::ArgFormatter(*this, spec, s - 1).visit(arg);
- return s;
-}
-
-template
-void fmt::BasicFormatter::format(BasicCStringRef format_str) {
- const Char *s = format_str.c_str();
- const Char *start = s;
- while (*s) {
- Char c = *s++;
- if (c != '{' && c != '}') continue;
- if (*s == c) {
- write(writer_, start, s);
- start = ++s;
- continue;
- }
- if (c == '}')
- FMT_THROW(FormatError("unmatched '}' in format string"));
- write(writer_, start, s - 1);
- Arg arg = is_name_start(*s) ? parse_arg_name(s) : parse_arg_index(s);
- start = s = format(s, arg);
- }
- write(writer_, start, s);
-}
-
-FMT_FUNC void fmt::report_system_error(
- int error_code, fmt::StringRef message) FMT_NOEXCEPT {
- report_error(internal::format_system_error, error_code, message);
-}
-
-#if FMT_USE_WINDOWS_H
-FMT_FUNC void fmt::report_windows_error(
- int error_code, fmt::StringRef message) FMT_NOEXCEPT {
- report_error(internal::format_windows_error, error_code, message);
-}
-#endif
-
-FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
- MemoryWriter w;
- w.write(format_str, args);
- std::fwrite(w.data(), 1, w.size(), f);
-}
-
-FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
- print(stdout, format_str, args);
-}
-
-FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) {
- MemoryWriter w;
- w.write(format_str, args);
- os.write(w.data(), w.size());
-}
-
-FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
- char escape[] = "\x1b[30m";
- escape[3] = '0' + static_cast(c);
- std::fputs(escape, stdout);
- print(format, args);
- std::fputs(RESET_COLOR, stdout);
-}
-
-FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
- MemoryWriter w;
- printf(w, format, args);
- std::size_t size = w.size();
- return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast(size);
-}
-
-#ifndef FMT_HEADER_ONLY
-
-template struct fmt::internal::BasicData;
-
-// Explicit instantiations for char.
-
-template void fmt::internal::FixedBuffer::grow(std::size_t);
-
-template const char *fmt::BasicFormatter::format(
- const char *&format_str, const fmt::internal::Arg &arg);
-
-template void fmt::BasicFormatter::format(CStringRef format);
-
-template void fmt::internal::PrintfFormatter::format(
- BasicWriter &writer, CStringRef format);
-
-template int fmt::internal::CharTraits::format_float(
- char *buffer, std::size_t size, const char *format,
- unsigned width, int precision, double value);
-
-template int fmt::internal::CharTraits::format_float(
- char *buffer, std::size_t size, const char *format,
- unsigned width, int precision, long double value);
-
-// Explicit instantiations for wchar_t.
-
-template void fmt::internal::FixedBuffer::grow(std::size_t);
-
-template const wchar_t *fmt::BasicFormatter::format(
- const wchar_t *&format_str, const fmt::internal::Arg &arg);
-
-template void fmt::BasicFormatter::format(
- BasicCStringRef format);
-
-template void fmt::internal::PrintfFormatter::format(
- BasicWriter &writer, WCStringRef format);
-
-template int fmt::internal::CharTraits::format_float(
- wchar_t *buffer, std::size_t size, const wchar_t *format,
- unsigned width, int precision, double value);
-
-template int fmt::internal::CharTraits::format_float(
- wchar_t *buffer, std::size_t size, const wchar_t *format,
- unsigned width, int precision, long double value);
-
-#endif // FMT_HEADER_ONLY
-
-#if _MSC_VER
-# pragma warning(pop)
-#endif
diff --git a/external/Common/crc32.cpp b/external/Hash/crc32.cpp
similarity index 100%
rename from external/Common/crc32.cpp
rename to external/Hash/crc32.cpp
diff --git a/external/Common/crc32.h b/external/Hash/crc32.h
similarity index 100%
rename from external/Common/crc32.h
rename to external/Hash/crc32.h
diff --git a/external/Common/digest.cpp b/external/Hash/digest.cpp
similarity index 100%
rename from external/Common/digest.cpp
rename to external/Hash/digest.cpp
diff --git a/external/Common/endian.h b/external/Hash/endian.h
similarity index 100%
rename from external/Common/endian.h
rename to external/Hash/endian.h
diff --git a/external/Common/hash.h b/external/Hash/hash.h
similarity index 100%
rename from external/Common/hash.h
rename to external/Hash/hash.h
diff --git a/external/Common/hash_license.txt b/external/Hash/hash_license.txt
similarity index 100%
rename from external/Common/hash_license.txt
rename to external/Hash/hash_license.txt
diff --git a/external/Common/hmac.h b/external/Hash/hmac.h
similarity index 100%
rename from external/Common/hmac.h
rename to external/Hash/hmac.h
diff --git a/external/Common/keccak.cpp b/external/Hash/keccak.cpp
similarity index 100%
rename from external/Common/keccak.cpp
rename to external/Hash/keccak.cpp
diff --git a/external/Common/keccak.h b/external/Hash/keccak.h
similarity index 100%
rename from external/Common/keccak.h
rename to external/Hash/keccak.h
diff --git a/external/Common/md5.cpp b/external/Hash/md5.cpp
similarity index 100%
rename from external/Common/md5.cpp
rename to external/Hash/md5.cpp
diff --git a/external/Common/md5.h b/external/Hash/md5.h
similarity index 100%
rename from external/Common/md5.h
rename to external/Hash/md5.h
diff --git a/external/Common/sha1.cpp b/external/Hash/sha1.cpp
similarity index 100%
rename from external/Common/sha1.cpp
rename to external/Hash/sha1.cpp
diff --git a/external/Common/sha1.h b/external/Hash/sha1.h
similarity index 100%
rename from external/Common/sha1.h
rename to external/Hash/sha1.h
diff --git a/external/Common/sha256.cpp b/external/Hash/sha256.cpp
similarity index 100%
rename from external/Common/sha256.cpp
rename to external/Hash/sha256.cpp
diff --git a/external/Common/sha256.h b/external/Hash/sha256.h
similarity index 100%
rename from external/Common/sha256.h
rename to external/Hash/sha256.h
diff --git a/external/Common/sha3.cpp b/external/Hash/sha3.cpp
similarity index 100%
rename from external/Common/sha3.cpp
rename to external/Hash/sha3.cpp
diff --git a/external/Common/sha3.h b/external/Hash/sha3.h
similarity index 100%
rename from external/Common/sha3.h
rename to external/Hash/sha3.h
diff --git a/external/IRC/LICENSE b/external/IRC/LICENSE
deleted file mode 100644
index 161a3d1d..00000000
--- a/external/IRC/LICENSE
+++ /dev/null
@@ -1,482 +0,0 @@
- GNU LIBRARY GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL. It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it. You can use it for
-your libraries, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
- Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library. If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software. To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
- Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs. This
-license, the GNU Library General Public License, applies to certain
-designated libraries. This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
- The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it. Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program. However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
- Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries. We
-concluded that weaker conditions might promote sharing better.
-
- However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves. This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them. (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.) The hope is that this
-will lead to faster development of free libraries.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, while the latter only
-works together with the library.
-
- Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
- GNU LIBRARY GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License"). Each licensee is
-addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- c) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- d) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- Appendix: How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- , 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/external/IRC/colors.c b/external/IRC/colors.c
deleted file mode 100644
index 6e31b132..00000000
--- a/external/IRC/colors.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or (at your
- * option) any later version.
- *
- * This library 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 Lesser General Public
- * License for more details.
- */
-
-#include
-
-#define LIBIRC_COLORPARSER_BOLD (1<<1)
-#define LIBIRC_COLORPARSER_UNDERLINE (1<<2)
-#define LIBIRC_COLORPARSER_REVERSE (1<<3)
-#define LIBIRC_COLORPARSER_COLOR (1<<4)
-
-#define LIBIRC_COLORPARSER_MAXCOLORS 15
-
-
-static const char * color_replacement_table[] =
-{
- "WHITE",
- "BLACK",
- "DARKBLUE",
- "DARKGREEN",
- "RED",
- "BROWN",
- "PURPLE",
- "OLIVE",
- "YELLOW",
- "GREEN",
- "TEAL",
- "CYAN",
- "BLUE",
- "MAGENTA",
- "DARKGRAY",
- "LIGHTGRAY",
- 0
-};
-
-
-static inline void libirc_colorparser_addorcat (char ** destline, unsigned int * destlen, const char * str)
-{
- unsigned int len = strlen(str);
-
- if ( *destline )
- {
- strcpy (*destline, str);
- *destline += len;
- }
- else
- *destlen += len;
-}
-
-
-static void libirc_colorparser_applymask (unsigned int * mask,
- char ** destline, unsigned int * destlen,
- unsigned int bitmask, const char * start, const char * end)
-{
- if ( (*mask & bitmask) != 0 )
- {
- *mask &= ~bitmask;
- libirc_colorparser_addorcat (destline, destlen, end);
- }
- else
- {
- *mask |= bitmask;
- libirc_colorparser_addorcat (destline, destlen, start);
- }
-}
-
-
-static void libirc_colorparser_applycolor (unsigned int * mask,
- char ** destline, unsigned int * destlen,
- unsigned int colorid, unsigned int bgcolorid)
-{
- const char * end = "[/COLOR]";
- char startbuf[64];
-
- if ( bgcolorid != 0 )
- sprintf (startbuf, "[COLOR=%s/%s]", color_replacement_table[colorid], color_replacement_table[bgcolorid]);
- else
- sprintf (startbuf, "[COLOR=%s]", color_replacement_table[colorid]);
-
- if ( (*mask & LIBIRC_COLORPARSER_COLOR) != 0 )
- libirc_colorparser_addorcat (destline, destlen, end);
-
- *mask |= LIBIRC_COLORPARSER_COLOR;
- libirc_colorparser_addorcat (destline, destlen, startbuf);
-}
-
-
-static void libirc_colorparser_closetags (unsigned int * mask,
- char ** destline, unsigned int * destlen)
-{
- if ( *mask & LIBIRC_COLORPARSER_BOLD )
- libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_BOLD, 0, "[/B]");
-
- if ( *mask & LIBIRC_COLORPARSER_UNDERLINE )
- libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_UNDERLINE, 0, "[/U]");
-
- if ( *mask & LIBIRC_COLORPARSER_REVERSE )
- libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_REVERSE, 0, "[/I]");
-
- if ( *mask & LIBIRC_COLORPARSER_COLOR )
- libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_COLOR, 0, "[/COLOR]");
-}
-
-
-
-/*
- * IRC to [code] color conversion. Or strip.
- */
-static char * libirc_colorparser_irc2code (const char * source, int strip)
-{
- unsigned int mask = 0, destlen = 0;
- char * destline = 0, *d = 0;
- const char *p;
- int current_bg = 0;
-
- /*
- * There will be two passes. First pass calculates the total length of
- * the destination string. The second pass allocates memory for the string,
- * and fills it.
- */
- while ( destline == 0 ) // destline will be set after the 2nd pass
- {
- if ( destlen > 0 )
- {
- // This is the 2nd pass; allocate memory.
- if ( (destline = malloc (destlen)) == 0 )
- return 0;
-
- d = destline;
- }
-
- for ( p = source; *p; p++ )
- {
- switch (*p)
- {
- case 0x02: // bold
- if ( strip )
- continue;
-
- libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_BOLD, "[B]", "[/B]");
- break;
-
- case 0x1F: // underline
- if ( strip )
- continue;
-
- libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_UNDERLINE, "[U]", "[/U]");
- break;
-
- case 0x16: // reverse
- if ( strip )
- continue;
-
- libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_REVERSE, "[I]", "[/I]");
- break;
-
- case 0x0F: // reset colors
- if ( strip )
- continue;
-
- libirc_colorparser_closetags (&mask, &d, &destlen);
- break;
-
- case 0x03: // set color
- if ( isdigit (p[1]) )
- {
- // Parse
- int bgcolor = -1, color = p[1] - 0x30;
- p++;
-
- if ( isdigit (p[1]) )
- {
- color = color * 10 + (p[1] - 0x30);
- p++;
- }
-
- // If there is a comma, search for the following
- // background color
- if ( p[1] == ',' && isdigit (p[2]) )
- {
- bgcolor = p[2] - 0x30;
- p += 2;
-
- if ( isdigit (p[1]) )
- {
- bgcolor = bgcolor * 10 + (p[1] - 0x30);
- p++;
- }
- }
-
- // Check for range
- if ( color <= LIBIRC_COLORPARSER_MAXCOLORS
- && bgcolor <= LIBIRC_COLORPARSER_MAXCOLORS )
- {
- if ( strip )
- continue;
-
- if ( bgcolor != -1 )
- current_bg = bgcolor;
-
- libirc_colorparser_applycolor (&mask, &d, &destlen, color, current_bg);
- }
- }
- break;
-
- default:
- if ( destline )
- *d++ = *p;
- else
- destlen++;
- break;
- }
- }
-
- // Close all the opened tags
- libirc_colorparser_closetags (&mask, &d, &destlen);
- destlen++; // for 0-terminator
- }
-
- *d = '\0';
- return destline;
-}
-
-
-static int libirc_colorparser_colorlookup (const char * color)
-{
- int i;
- for ( i = 0; color_replacement_table[i]; i++ )
- if ( !strcmp (color, color_replacement_table[i]) )
- return i;
-
- return -1;
-}
-
-
-/*
- * [code] to IRC color conversion.
- */
-char * irc_color_convert_to_mirc (const char * source)
-{
- unsigned int destlen = 0;
- char * destline = 0, *d = 0;
- const char *p1, *p2, *cur;
-
- /*
- * There will be two passes. First pass calculates the total length of
- * the destination string. The second pass allocates memory for the string,
- * and fills it.
- */
- while ( destline == 0 ) // destline will be set after the 2nd pass
- {
- if ( destlen > 0 )
- {
- // This is the 2nd pass; allocate memory.
- if ( (destline = malloc (destlen)) == 0 )
- return 0;
-
- d = destline;
- }
-
- cur = source;
- while ( (p1 = strchr (cur, '[')) != 0 )
- {
- const char * replacedval = 0;
- p2 = 0;
-
- // Check if the closing bracket is available after p1
- // and the tag length is suitable
- if ( p1[1] != '\0'
- && (p2 = strchr (p1, ']')) != 0
- && (p2 - p1) > 1
- && (p2 - p1) < 31 )
- {
- // Get the tag
- char tagbuf[32];
- int taglen = p2 - p1 - 1;
-
- memcpy (tagbuf, p1 + 1, taglen);
- tagbuf[taglen] = '\0';
-
- if ( !strcmp (tagbuf, "/COLOR") )
- replacedval = "\x0F";
- else if ( strstr (tagbuf, "COLOR=") == tagbuf )
- {
- int color, bgcolor = -2;
- char * bcol;
-
- bcol = strchr (tagbuf + 6, '/');
-
- if ( bcol )
- {
- *bcol++ = '\0';
- bgcolor = libirc_colorparser_colorlookup (bcol);
- }
-
- color = libirc_colorparser_colorlookup (tagbuf + 6);
-
- if ( color != -1 && bgcolor == -2 )
- {
- sprintf (tagbuf, "\x03%02d", color);
- replacedval = tagbuf;
- }
- else if ( color != -1 && bgcolor >= 0 )
- {
- sprintf (tagbuf, "\x03%02d,%02d", color, bgcolor);
- replacedval = tagbuf;
- }
- }
- else if ( !strcmp (tagbuf, "B") || !strcmp (tagbuf, "/B") )
- replacedval = "\x02";
- else if ( !strcmp (tagbuf, "U") || !strcmp (tagbuf, "/U") )
- replacedval = "\x1F";
- else if ( !strcmp (tagbuf, "I") || !strcmp (tagbuf, "/I") )
- replacedval = "\x16";
- }
-
- if ( replacedval )
- {
- // add a part before the tag
- int partlen = p1 - cur;
-
- if ( destline )
- {
- memcpy (d, cur, partlen);
- d += partlen;
- }
- else
- destlen += partlen;
-
- // Add the replacement
- libirc_colorparser_addorcat (&d, &destlen, replacedval);
-
- // And move the pointer
- cur = p2 + 1;
- }
- else
- {
- // add a whole part before the end tag
- int partlen;
-
- if ( !p2 )
- p2 = cur + strlen(cur);
-
- partlen = p2 - cur + 1;
-
- if ( destline )
- {
- memcpy (d, cur, partlen);
- d += partlen;
- }
- else
- destlen += partlen;
-
- // And move the pointer
- cur = p2 + 1;
- }
- }
-
- // Add the rest of string
- libirc_colorparser_addorcat (&d, &destlen, cur);
- destlen++; // for 0-terminator
- }
-
- *d = '\0';
- return destline;
-}
-
-
-char * irc_color_strip_from_mirc (const char * message)
-{
- return libirc_colorparser_irc2code (message, 1);
-}
-
-
-char * irc_color_convert_from_mirc (const char * message)
-{
- return libirc_colorparser_irc2code (message, 0);
-}
diff --git a/external/IRC/dcc.c b/external/IRC/dcc.c
deleted file mode 100644
index 00ccb5f6..00000000
--- a/external/IRC/dcc.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
- * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or (at your
- * option) any later version.
- *
- * This library 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 Lesser General Public
- * License for more details.
- */
-
-#define LIBIRC_DCC_CHAT 1
-#define LIBIRC_DCC_SENDFILE 2
-#define LIBIRC_DCC_RECVFILE 3
-
-
-static irc_dcc_session_t * libirc_find_dcc_session (irc_session_t * session, irc_dcc_t dccid, int lock_list)
-{
- irc_dcc_session_t * s, *found = 0;
-
- if ( lock_list )
- libirc_mutex_lock (&session->mutex_dcc);
-
- for ( s = session->dcc_sessions; s; s = s->next )
- {
- if ( s->id == dccid )
- {
- found = s;
- break;
- }
- }
-
- if ( found == 0 && lock_list )
- libirc_mutex_unlock (&session->mutex_dcc);
-
- return found;
-}
-
-
-static void libirc_dcc_destroy_nolock (irc_session_t * session, irc_dcc_t dccid)
-{
- irc_dcc_session_t * dcc = libirc_find_dcc_session (session, dccid, 0);
-
- if ( dcc )
- {
- if ( dcc->sock >= 0 )
- socket_close (&dcc->sock);
-
- dcc->state = LIBIRC_STATE_REMOVED;
- }
-}
-
-
-static void libirc_remove_dcc_session (irc_session_t * session, irc_dcc_session_t * dcc, int lock_list)
-{
- if ( dcc->sock >= 0 )
- socket_close (&dcc->sock);
-
- if ( dcc->dccsend_file_fp )
- fclose (dcc->dccsend_file_fp);
-
- dcc->dccsend_file_fp = 0;
-
- libirc_mutex_destroy (&dcc->mutex_outbuf);
-
- if ( lock_list )
- libirc_mutex_lock (&session->mutex_dcc);
-
- if ( session->dcc_sessions != dcc )
- {
- irc_dcc_session_t * s;
- for ( s = session->dcc_sessions; s; s = s->next )
- {
- if ( s->next == dcc )
- {
- s->next = dcc->next;
- break;
- }
- }
- }
- else
- session->dcc_sessions = dcc->next;
-
- if ( lock_list )
- libirc_mutex_unlock (&session->mutex_dcc);
-
- free (dcc);
-}
-
-
-static void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set, int * maxfd)
-{
- irc_dcc_session_t * dcc, *dcc_next;
- time_t now = time (0);
-
- libirc_mutex_lock (&ircsession->mutex_dcc);
-
- // Preprocessing DCC list:
- // - ask DCC send callbacks for data;
- // - remove unused DCC structures
- for ( dcc = ircsession->dcc_sessions; dcc; dcc = dcc_next )
- {
- dcc_next = dcc->next;
-
- // Remove timed-out sessions
- if ( (dcc->state == LIBIRC_STATE_CONNECTING
- || dcc->state == LIBIRC_STATE_INIT
- || dcc->state == LIBIRC_STATE_LISTENING)
- && now - dcc->timeout > ircsession->dcc_timeout )
- {
- // Inform the caller about DCC timeout.
- // Do not inform when state is LIBIRC_STATE_INIT - session
- // was initiated from someone else, and callbacks aren't set yet.
- if ( dcc->state != LIBIRC_STATE_INIT )
- {
- libirc_mutex_unlock (&ircsession->mutex_dcc);
-
- if ( dcc->cb )
- (*dcc->cb)(ircsession, dcc->id, LIBIRC_ERR_TIMEOUT, dcc->ctx, 0, 0);
-
- libirc_mutex_lock (&ircsession->mutex_dcc);
- }
-
- libirc_remove_dcc_session (ircsession, dcc, 0);
- }
-
- /*
- * If we're sending file, and the output buffer is empty, we need
- * to provide some data.
- */
- if ( dcc->state == LIBIRC_STATE_CONNECTED
- && dcc->dccmode == LIBIRC_DCC_SENDFILE
- && dcc->dccsend_file_fp
- && dcc->outgoing_offset == 0 )
- {
- int len = fread (dcc->outgoing_buf, 1, sizeof (dcc->outgoing_buf), dcc->dccsend_file_fp);
-
- if ( len <= 0 )
- {
- int err = (len < 0 ? LIBIRC_ERR_READ : 0);
-
- libirc_mutex_unlock (&ircsession->mutex_dcc);
-
- (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, 0, 0);
- libirc_mutex_lock (&ircsession->mutex_dcc);
- libirc_dcc_destroy_nolock (ircsession, dcc->id);
- }
- else
- dcc->outgoing_offset = len;
- }
-
- // Clean up unused sessions
- if ( dcc->state == LIBIRC_STATE_REMOVED )
- libirc_remove_dcc_session (ircsession, dcc, 0);
- }
-
- for ( dcc = ircsession->dcc_sessions; dcc; dcc = dcc->next )
- {
- switch (dcc->state)
- {
- case LIBIRC_STATE_LISTENING:
- // While listening, only in_set descriptor should be set
- libirc_add_to_set (dcc->sock, in_set, maxfd);
- break;
-
- case LIBIRC_STATE_CONNECTING:
- // While connection, only out_set descriptor should be set
- libirc_add_to_set (dcc->sock, out_set, maxfd);
- break;
-
- case LIBIRC_STATE_CONNECTED:
- // Add input descriptor if there is space in input buffer
- // and it is DCC chat (during DCC send, there is nothing to recv)
- if ( dcc->incoming_offset < sizeof(dcc->incoming_buf) - 1 )
- libirc_add_to_set (dcc->sock, in_set, maxfd);
-
- // Add output descriptor if there is something in output buffer
- libirc_mutex_lock (&dcc->mutex_outbuf);
-
- if ( dcc->outgoing_offset > 0 )
- libirc_add_to_set (dcc->sock, out_set, maxfd);
-
- libirc_mutex_unlock (&dcc->mutex_outbuf);
- break;
-
- case LIBIRC_STATE_CONFIRM_SIZE:
- /*
- * If we're receiving file, then WE should confirm the transferred
- * part (so we have to sent data). But if we're sending the file,
- * then RECEIVER should confirm the packet, so we have to receive
- * data.
- *
- * We don't need to LOCK_DCC_OUTBUF - during file transfer, buffers
- * can't change asynchronously.
- */
- if ( dcc->dccmode == LIBIRC_DCC_RECVFILE && dcc->outgoing_offset > 0 )
- libirc_add_to_set (dcc->sock, out_set, maxfd);
-
- if ( dcc->dccmode == LIBIRC_DCC_SENDFILE && dcc->incoming_offset < 4 )
- libirc_add_to_set (dcc->sock, in_set, maxfd);
- }
- }
-
- libirc_mutex_unlock (&ircsession->mutex_dcc);
-}
-
-
-static void libirc_dcc_process_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set)
-{
- irc_dcc_session_t * dcc;
-
- /*
- * We need to use such a complex scheme here, because on every callback
- * a number of DCC sessions could be destroyed.
- */
- libirc_mutex_lock (&ircsession->mutex_dcc);
-
- for ( dcc = ircsession->dcc_sessions; dcc; dcc = dcc->next )
- {
- if ( dcc->state == LIBIRC_STATE_LISTENING
- && FD_ISSET (dcc->sock, in_set) )
- {
- socklen_t len = sizeof(dcc->remote_addr);
- int nsock, err = 0;
-
- // New connection is available; accept it.
- if ( socket_accept (&dcc->sock, (socket_t*)&nsock, (struct sockaddr *) &dcc->remote_addr, &len) )
- err = LIBIRC_ERR_ACCEPT;
-
- // On success, change the active socket and change the state
- if ( err == 0 )
- {
- // close the listen socket, and replace it by a newly
- // accepted
- socket_close (&dcc->sock);
- dcc->sock = nsock;
- dcc->state = LIBIRC_STATE_CONNECTED;
- }
-
- // If this is DCC chat, inform the caller about accept()
- // success or failure.
- // Otherwise (DCC send) there is no reason.
- if ( dcc->dccmode == LIBIRC_DCC_CHAT )
- {
- libirc_mutex_unlock (&ircsession->mutex_dcc);
- (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, 0, 0);
- libirc_mutex_lock (&ircsession->mutex_dcc);
- }
-
- if ( err )
- libirc_dcc_destroy_nolock (ircsession, dcc->id);
- }
-
- if ( dcc->state == LIBIRC_STATE_CONNECTING
- && FD_ISSET (dcc->sock, out_set) )
- {
- // Now we have to determine whether the socket is connected
- // or the connect is failed
- struct sockaddr_in saddr;
- socklen_t slen = sizeof(saddr);
- int err = 0;
-
- if ( getpeername (dcc->sock, (struct sockaddr*)&saddr, &slen) < 0 )
- err = LIBIRC_ERR_CONNECT;
-
- // On success, change the state
- if ( err == 0 )
- dcc->state = LIBIRC_STATE_CONNECTED;
-
- // If this is DCC chat, inform the caller about connect()
- // success or failure.
- // Otherwise (DCC send) there is no reason.
- if ( dcc->dccmode == LIBIRC_DCC_CHAT )
- {
- libirc_mutex_unlock (&ircsession->mutex_dcc);
- (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, 0, 0);
- libirc_mutex_lock (&ircsession->mutex_dcc);
- }
-
- if ( err )
- libirc_dcc_destroy_nolock (ircsession, dcc->id);
- }
-
- if ( dcc->state == LIBIRC_STATE_CONNECTED
- || dcc->state == LIBIRC_STATE_CONFIRM_SIZE )
- {
- if ( FD_ISSET (dcc->sock, in_set) )
- {
- int length, offset = 0, err = 0;
-
- unsigned int amount = sizeof (dcc->incoming_buf) - dcc->incoming_offset;
-
- length = socket_recv (&dcc->sock, dcc->incoming_buf + dcc->incoming_offset, amount);
-
- if ( length < 0 )
- {
- err = LIBIRC_ERR_READ;
- }
- else if ( length == 0 )
- {
- err = LIBIRC_ERR_CLOSED;
-
- if ( dcc->dccsend_file_fp )
- {
- fclose (dcc->dccsend_file_fp);
- dcc->dccsend_file_fp = 0;
- }
- }
- else
- {
- dcc->incoming_offset += length;
-
- if ( dcc->dccmode != LIBIRC_DCC_CHAT )
- offset = dcc->incoming_offset;
- else
- offset = libirc_findcrorlf (dcc->incoming_buf, dcc->incoming_offset);
-
- /*
- * In LIBIRC_STATE_CONFIRM_SIZE state we don't call any
- * callbacks (except there is an error). We just receive
- * the data, and compare it with the amount sent.
- */
- if ( dcc->state == LIBIRC_STATE_CONFIRM_SIZE )
- {
- if ( dcc->dccmode != LIBIRC_DCC_SENDFILE )
- abort();
-
- if ( dcc->incoming_offset == 4 )
- {
- // The order is big-endian
- const unsigned char * bptr = (const unsigned char *) dcc->incoming_buf;
- unsigned int received_size = (bptr[0] << 24) | (bptr[1] << 16) | (bptr[2] << 8) | bptr[3];
-
- // Sent size confirmed
- if ( dcc->file_confirm_offset == received_size )
- {
- dcc->state = LIBIRC_STATE_CONNECTED;
- dcc->incoming_offset = 0;
- }
- else
- err = LIBIRC_ERR_WRITE;
- }
- }
- else
- {
- /*
- * If it is DCC_CHAT, we send a 0-terminated string
- * (which is smaller than offset). Otherwise we send
- * a full buffer.
- */
- libirc_mutex_unlock (&ircsession->mutex_dcc);
-
- if ( dcc->dccmode != LIBIRC_DCC_CHAT )
- {
- if ( dcc->dccmode != LIBIRC_DCC_RECVFILE )
- abort();
-
- (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, dcc->incoming_buf, offset);
-
- /*
- * If the session is not terminated in callback,
- * put the sent amount into the sent_packet_size_net_byteorder
- */
- if ( dcc->state != LIBIRC_STATE_REMOVED )
- {
- dcc->state = LIBIRC_STATE_CONFIRM_SIZE;
- dcc->file_confirm_offset += offset;
-
- // Store as big endian
- dcc->outgoing_buf[0] = (char) dcc->file_confirm_offset >> 24;
- dcc->outgoing_buf[1] = (char) dcc->file_confirm_offset >> 16;
- dcc->outgoing_buf[2] = (char) dcc->file_confirm_offset >> 8;
- dcc->outgoing_buf[3] = (char) dcc->file_confirm_offset;
- dcc->outgoing_offset = 4;
- }
- }
- else
- (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, dcc->incoming_buf, strlen(dcc->incoming_buf));
-
- libirc_mutex_lock (&ircsession->mutex_dcc);
-
- if ( dcc->incoming_offset - offset > 0 )
- memmove (dcc->incoming_buf, dcc->incoming_buf + offset, dcc->incoming_offset - offset);
-
- dcc->incoming_offset -= offset;
- }
- }
-
- /*
- * If error arises somewhere above, we inform the caller
- * of failure, and destroy this session.
- */
- if ( err )
- {
- libirc_mutex_unlock (&ircsession->mutex_dcc);
- (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, 0, 0);
- libirc_mutex_lock (&ircsession->mutex_dcc);
- libirc_dcc_destroy_nolock (ircsession, dcc->id);
- }
- }
-
- /*
- * Session might be closed (with sock = -1) after the in_set
- * processing, so before out_set processing we should check
- * for this case
- */
- if ( dcc->state == LIBIRC_STATE_REMOVED )
- continue;
-
- /*
- * Write bit set - we can send() something, and it won't block.
- */
- if ( FD_ISSET (dcc->sock, out_set) )
- {
- int length, offset, err = 0;
-
- /*
- * Because in some cases outgoing_buf could be changed
- * asynchronously (by another thread), we should lock
- * it.
- */
- libirc_mutex_lock (&dcc->mutex_outbuf);
-
- offset = dcc->outgoing_offset;
-
- if ( offset > 0 )
- {
- length = socket_send (&dcc->sock, dcc->outgoing_buf, offset);
-
- if ( length < 0 )
- err = LIBIRC_ERR_WRITE;
- else if ( length == 0 )
- err = LIBIRC_ERR_CLOSED;
- else
- {
- /*
- * If this was DCC_SENDFILE, and we just sent a packet,
- * change the state to wait for confirmation (and store
- * sent packet size)
- */
- if ( dcc->state == LIBIRC_STATE_CONNECTED
- && dcc->dccmode == LIBIRC_DCC_SENDFILE )
- {
- dcc->file_confirm_offset += offset;
- dcc->state = LIBIRC_STATE_CONFIRM_SIZE;
-
- libirc_mutex_unlock (&ircsession->mutex_dcc);
- libirc_mutex_unlock (&dcc->mutex_outbuf);
- (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, 0, offset);
- libirc_mutex_lock (&ircsession->mutex_dcc);
- libirc_mutex_lock (&dcc->mutex_outbuf);
- }
-
- if ( dcc->outgoing_offset - length > 0 )
- memmove (dcc->outgoing_buf, dcc->outgoing_buf + length, dcc->outgoing_offset - length);
-
- dcc->outgoing_offset -= length;
-
- /*
- * If we just sent the confirmation data, change state
- * back.
- */
- if ( dcc->state == LIBIRC_STATE_CONFIRM_SIZE
- && dcc->dccmode == LIBIRC_DCC_RECVFILE
- && dcc->outgoing_offset == 0 )
- {
- /*
- * If the file is already received, we should inform
- * the caller, and close the session.
- */
- if ( dcc->received_file_size == dcc->file_confirm_offset )
- {
- libirc_mutex_unlock (&ircsession->mutex_dcc);
- libirc_mutex_unlock (&dcc->mutex_outbuf);
- (*dcc->cb)(ircsession, dcc->id, 0, dcc->ctx, 0, 0);
- libirc_dcc_destroy_nolock (ircsession, dcc->id);
- }
- else
- {
- /* Continue to receive the file */
- dcc->state = LIBIRC_STATE_CONNECTED;
- }
- }
- }
- }
-
- libirc_mutex_unlock (&dcc->mutex_outbuf);
-
- /*
- * If error arises somewhere above, we inform the caller
- * of failure, and destroy this session.
- */
- if ( err )
- {
- libirc_mutex_unlock (&ircsession->mutex_dcc);
- (*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, 0, 0);
- libirc_mutex_lock (&ircsession->mutex_dcc);
-
- libirc_dcc_destroy_nolock (ircsession, dcc->id);
- }
- }
- }
- }
-
- libirc_mutex_unlock (&ircsession->mutex_dcc);
-}
-
-
-static int libirc_new_dcc_session (irc_session_t * session, unsigned long ip, unsigned short port, int dccmode, void * ctx, irc_dcc_session_t ** pdcc)
-{
- irc_dcc_session_t * dcc = malloc (sizeof(irc_dcc_session_t));
-
- if ( !dcc )
- return LIBIRC_ERR_NOMEM;
-
- // setup
- memset (dcc, 0, sizeof(irc_dcc_session_t));
-
- dcc->dccsend_file_fp = 0;
-
- if ( libirc_mutex_init (&dcc->mutex_outbuf) )
- goto cleanup_exit_error;
-
- if ( socket_create (PF_INET, SOCK_STREAM, &dcc->sock) )
- goto cleanup_exit_error;
-
- if ( !ip )
- {
- unsigned long arg = 1;
-
- setsockopt (dcc->sock, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, sizeof(arg));
-
-#if defined (ENABLE_IPV6)
- if ( session->flags & SESSIONFL_USES_IPV6 )
- {
- struct sockaddr_in6 saddr6;
-
- memset (&saddr6, 0, sizeof(saddr6));
- saddr6.sin6_family = AF_INET6;
- memcpy (&saddr6.sin6_addr, &session->local_addr6, sizeof(session->local_addr6));
- saddr6.sin6_port = htons (0);
-
- if ( bind (dcc->sock, (struct sockaddr *) &saddr6, sizeof(saddr6)) < 0 )
- goto cleanup_exit_error;
- }
- else
-#endif
- {
- struct sockaddr_in saddr;
- memset (&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- memcpy (&saddr.sin_addr, &session->local_addr, sizeof(session->local_addr));
- saddr.sin_port = htons (0);
-
- if ( bind (dcc->sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0 )
- goto cleanup_exit_error;
- }
-
- if ( listen (dcc->sock, 5) < 0 )
- goto cleanup_exit_error;
-
- dcc->state = LIBIRC_STATE_LISTENING;
- }
- else
- {
- // make socket non-blocking, so connect() call won't block
- if ( socket_make_nonblocking (&dcc->sock) )
- goto cleanup_exit_error;
-
- memset (&dcc->remote_addr, 0, sizeof(dcc->remote_addr));
- dcc->remote_addr.sin_family = AF_INET;
- dcc->remote_addr.sin_addr.s_addr = htonl (ip); // what idiot came up with idea to send IP address in host-byteorder?
- dcc->remote_addr.sin_port = htons(port);
-
- dcc->state = LIBIRC_STATE_INIT;
- }
-
- dcc->dccmode = dccmode;
- dcc->ctx = ctx;
- time (&dcc->timeout);
-
- // and store it
- libirc_mutex_lock (&session->mutex_dcc);
-
- dcc->id = session->dcc_last_id++;
- dcc->next = session->dcc_sessions;
- session->dcc_sessions = dcc;
-
- libirc_mutex_unlock (&session->mutex_dcc);
-
- *pdcc = dcc;
- return 0;
-
-cleanup_exit_error:
- if ( dcc->sock >= 0 )
- socket_close (&dcc->sock);
-
- free (dcc);
- return LIBIRC_ERR_SOCKET;
-}
-
-
-int irc_dcc_destroy (irc_session_t * session, irc_dcc_t dccid)
-{
- // This function doesn't actually destroy the session; it just changes
- // its state to "removed" and closes the socket. The memory is actually
- // freed after the processing loop.
- irc_dcc_session_t * dcc = libirc_find_dcc_session (session, dccid, 1);
-
- if ( !dcc )
- return 1;
-
- if ( dcc->sock >= 0 )
- socket_close (&dcc->sock);
-
- dcc->state = LIBIRC_STATE_REMOVED;
-
- libirc_mutex_unlock (&session->mutex_dcc);
- return 0;
-}
-
-
-int irc_dcc_chat (irc_session_t * session, void * ctx, const char * nick, irc_dcc_callback_t callback, irc_dcc_t * dccid)
-{
- struct sockaddr_in saddr;
- socklen_t len = sizeof(saddr);
- char cmdbuf[128], notbuf[128];
- irc_dcc_session_t * dcc;
- int err;
-
- if ( session->state != LIBIRC_STATE_CONNECTED )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- err = libirc_new_dcc_session (session, 0, 0, LIBIRC_DCC_CHAT, ctx, &dcc);
-
- if ( err )
- {
- session->lasterror = err;
- return 1;
- }
-
- if ( getsockname (dcc->sock, (struct sockaddr*) &saddr, &len) < 0 )
- {
- session->lasterror = LIBIRC_ERR_SOCKET;
- libirc_remove_dcc_session (session, dcc, 1);
- return 1;
- }
-
- sprintf (notbuf, "DCC Chat (%s)", inet_ntoa (saddr.sin_addr));
- sprintf (cmdbuf, "DCC CHAT chat %lu %u", (unsigned long) ntohl (saddr.sin_addr.s_addr), ntohs (saddr.sin_port));
-
- if ( irc_cmd_notice (session, nick, notbuf)
- || irc_cmd_ctcp_request (session, nick, cmdbuf) )
- {
- libirc_remove_dcc_session (session, dcc, 1);
- return 1;
- }
-
- *dccid = dcc->id;
- dcc->cb = callback;
- dcc->dccmode = LIBIRC_DCC_CHAT;
-
- return 0;
-}
-
-
-int irc_dcc_msg (irc_session_t * session, irc_dcc_t dccid, const char * text)
-{
- irc_dcc_session_t * dcc = libirc_find_dcc_session (session, dccid, 1);
-
- if ( !dcc )
- return 1;
-
- if ( dcc->dccmode != LIBIRC_DCC_CHAT )
- {
- session->lasterror = LIBIRC_ERR_INVAL;
- libirc_mutex_unlock (&session->mutex_dcc);
- return 1;
- }
-
- if ( (strlen(text) + 2) >= (sizeof(dcc->outgoing_buf) - dcc->outgoing_offset) )
- {
- session->lasterror = LIBIRC_ERR_NOMEM;
- libirc_mutex_unlock (&session->mutex_dcc);
- return 1;
- }
-
- libirc_mutex_lock (&dcc->mutex_outbuf);
-
- strcpy (dcc->outgoing_buf + dcc->outgoing_offset, text);
- dcc->outgoing_offset += strlen (text);
- dcc->outgoing_buf[dcc->outgoing_offset++] = 0x0D;
- dcc->outgoing_buf[dcc->outgoing_offset++] = 0x0A;
-
- libirc_mutex_unlock (&dcc->mutex_outbuf);
- libirc_mutex_unlock (&session->mutex_dcc);
-
- return 0;
-}
-
-
-static void libirc_dcc_request (irc_session_t * session, const char * nick, const char * req)
-{
- char filenamebuf[256];
- unsigned long ip, size;
- unsigned short port;
-
- if ( sscanf (req, "DCC CHAT chat %lu %hu", &ip, &port) == 2 )
- {
- if ( session->callbacks.event_dcc_chat_req )
- {
- irc_dcc_session_t * dcc;
-
- int err = libirc_new_dcc_session (session, ip, port, LIBIRC_DCC_CHAT, 0, &dcc);
- if ( err )
- {
- session->lasterror = err;
- return;
- }
-
- (*session->callbacks.event_dcc_chat_req) (session,
- nick,
- inet_ntoa (dcc->remote_addr.sin_addr),
- dcc->id);
- }
-
- return;
- }
- else if ( sscanf (req, "DCC SEND %s %lu %hu %lu", filenamebuf, &ip, &port, &size) == 4 )
- {
- if ( session->callbacks.event_dcc_send_req )
- {
- irc_dcc_session_t * dcc;
-
- int err = libirc_new_dcc_session (session, ip, port, LIBIRC_DCC_RECVFILE, 0, &dcc);
- if ( err )
- {
- session->lasterror = err;
- return;
- }
-
- (*session->callbacks.event_dcc_send_req) (session,
- nick,
- inet_ntoa (dcc->remote_addr.sin_addr),
- filenamebuf,
- size,
- dcc->id);
-
- dcc->received_file_size = size;
- }
-
- return;
- }
-#if defined (ENABLE_DEBUG)
- fprintf (stderr, "BUG: Unhandled DCC message: %s\n", req);
- abort();
-#endif
-}
-
-
-int irc_dcc_accept (irc_session_t * session, irc_dcc_t dccid, void * ctx, irc_dcc_callback_t callback)
-{
- irc_dcc_session_t * dcc = libirc_find_dcc_session (session, dccid, 1);
-
- if ( !dcc )
- return 1;
-
- if ( dcc->state != LIBIRC_STATE_INIT )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- libirc_mutex_unlock (&session->mutex_dcc);
- return 1;
- }
-
- dcc->cb = callback;
- dcc->ctx = ctx;
-
- // Initiate the connect
- if ( socket_connect (&dcc->sock, (struct sockaddr *) &dcc->remote_addr, sizeof(dcc->remote_addr)) )
- {
- libirc_dcc_destroy_nolock (session, dccid);
- libirc_mutex_unlock (&session->mutex_dcc);
- session->lasterror = LIBIRC_ERR_CONNECT;
- return 1;
- }
-
- dcc->state = LIBIRC_STATE_CONNECTING;
- libirc_mutex_unlock (&session->mutex_dcc);
- return 0;
-}
-
-
-int irc_dcc_decline (irc_session_t * session, irc_dcc_t dccid)
-{
- irc_dcc_session_t * dcc = libirc_find_dcc_session (session, dccid, 1);
-
- if ( !dcc )
- return 1;
-
- if ( dcc->state != LIBIRC_STATE_INIT )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- libirc_mutex_unlock (&session->mutex_dcc);
- return 1;
- }
-
- libirc_dcc_destroy_nolock (session, dccid);
- libirc_mutex_unlock (&session->mutex_dcc);
- return 0;
-}
-
-
-int irc_dcc_sendfile (irc_session_t * session, void * ctx, const char * nick, const char * filename, irc_dcc_callback_t callback, irc_dcc_t * dccid)
-{
- struct sockaddr_in saddr;
- socklen_t len = sizeof(saddr);
- char cmdbuf[128], notbuf[128];
- irc_dcc_session_t * dcc;
- const char * p;
- int err;
- long filesize;
-
- if ( !session || !dccid || !filename || !callback )
- {
- session->lasterror = LIBIRC_ERR_INVAL;
- return 1;
- }
-
- if ( session->state != LIBIRC_STATE_CONNECTED )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- if ( (err = libirc_new_dcc_session (session, 0, 0, LIBIRC_DCC_SENDFILE, ctx, &dcc)) != 0 )
- {
- session->lasterror = err;
- return 1;
- }
-
- if ( (dcc->dccsend_file_fp = fopen (filename, "rb")) == 0 )
- {
- libirc_remove_dcc_session (session, dcc, 1);
- session->lasterror = LIBIRC_ERR_OPENFILE;
- return 1;
- }
-
- /* Get file length */
- if ( fseek (dcc->dccsend_file_fp, 0, SEEK_END)
- || (filesize = ftell (dcc->dccsend_file_fp)) == -1
- || fseek (dcc->dccsend_file_fp, 0, SEEK_SET) )
- {
- libirc_remove_dcc_session (session, dcc, 1);
- session->lasterror = LIBIRC_ERR_NODCCSEND;
- return 1;
- }
-
- if ( getsockname (dcc->sock, (struct sockaddr*) &saddr, &len) < 0 )
- {
- libirc_remove_dcc_session (session, dcc, 1);
- session->lasterror = LIBIRC_ERR_SOCKET;
- return 1;
- }
-
- // Remove path from the filename
- if ( (p = strrchr (filename, '\\')) == 0
- && (p = strrchr (filename, '/')) == 0 )
- p = filename;
- else
- p++; // skip directory slash
-
- sprintf (notbuf, "DCC Send %s (%s)", p, inet_ntoa (saddr.sin_addr));
- sprintf (cmdbuf, "DCC SEND %s %lu %u %ld", p, (unsigned long) ntohl (saddr.sin_addr.s_addr), ntohs (saddr.sin_port), filesize);
-
- if ( irc_cmd_notice (session, nick, notbuf)
- || irc_cmd_ctcp_request (session, nick, cmdbuf) )
- {
- libirc_remove_dcc_session (session, dcc, 1);
- return 1;
- }
-
- *dccid = dcc->id;
- dcc->cb = callback;
-
- return 0;
-}
diff --git a/external/IRC/dcc.h b/external/IRC/dcc.h
deleted file mode 100644
index deb3355f..00000000
--- a/external/IRC/dcc.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or (at your
- * option) any later version.
- *
- * This library 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 Lesser General Public
- * License for more details.
- */
-
-#ifndef INCLUDE_IRC_DCC_H
-#define INCLUDE_IRC_DCC_H
-
-
-/*
- * This structure keeps the state of a single DCC connection.
- */
-struct irc_dcc_session_s
-{
- irc_dcc_session_t * next;
-
- irc_dcc_t id;
- void * ctx;
- socket_t sock; /*!< DCC socket */
- int dccmode; /*!< Boolean value to differ chat vs send
- requests. Changes the cb behavior - when
- it is chat, data is sent by lines with
- stripped CRLFs. In file mode, the data
- is sent as-is */
- int state;
- time_t timeout;
-
- FILE * dccsend_file_fp;
- unsigned int received_file_size;
- unsigned int file_confirm_offset;
-
- struct sockaddr_in remote_addr;
-
- char incoming_buf[LIBIRC_DCC_BUFFER_SIZE];
- unsigned int incoming_offset;
-
- char outgoing_buf[LIBIRC_DCC_BUFFER_SIZE];
- unsigned int outgoing_offset;
- port_mutex_t mutex_outbuf;
-
- irc_dcc_callback_t cb;
-};
-
-
-#endif /* INCLUDE_IRC_DCC_H */
diff --git a/external/IRC/errors.c b/external/IRC/errors.c
deleted file mode 100644
index 6533b898..00000000
--- a/external/IRC/errors.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or (at your
- * option) any later version.
- *
- * This library 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 Lesser General Public
- * License for more details.
- */
-
-static const char * libirc_strerror[LIBIRC_ERR_MAX] =
-{
- "No error",
- "Invalid argument",
- "Host not resolved",
- "Socket error",
- "Could not connect",
- "Remote connection closed",
- "Out of memory",
- "Could not accept new connection",
- "Object not found",
- "Could not DCC send this object",
- "Read error",
- "Write error",
- "Illegal operation for this state",
- "Timeout error",
- "Could not open file",
- "IRC session terminated",
- "IPv6 not supported",
- "SSL not supported",
- "SSL initialization failed",
- "SSL connection failed",
- "SSL certificate verify failed",
-};
-
-
-int irc_errno (irc_session_t * session)
-{
- return session->lasterror;
-}
-
-
-const char * irc_strerror (int ircerrno)
-{
- if ( ircerrno >= 0 && ircerrno < LIBIRC_ERR_MAX )
- return libirc_strerror[ircerrno];
- else
- return "Invalid irc_errno value";
-}
-
diff --git a/external/IRC/libircclient.c b/external/IRC/libircclient.c
deleted file mode 100644
index caf16b1f..00000000
--- a/external/IRC/libircclient.c
+++ /dev/null
@@ -1,1258 +0,0 @@
-/*
- * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or (at your
- * option) any later version.
- *
- * This library 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 Lesser General Public
- * License for more details.
- */
-
-#define IS_DEBUG_ENABLED(s) ((s)->options & LIBIRC_OPTION_DEBUG)
-
-#include "portable.c"
-#include "sockets.c"
-
-#include "libircclient.h"
-#include "session.h"
-
-#include "utils.c"
-#include "errors.c"
-#include "colors.c"
-#include "dcc.c"
-#include "ssl.c"
-
-
-#ifdef _MSC_VER
- /*
- * The debugger of MSVC 2005 does not like strdup.
- * It complains about heap corruption when free is called.
- * Use _strdup instead.
- */
- #undef strdup
- #define strdup _strdup
-#endif
-
-
-irc_session_t * irc_create_session (irc_callbacks_t * callbacks)
-{
- irc_session_t * session = malloc (sizeof(irc_session_t));
-
- if ( !session )
- return 0;
-
- memset (session, 0, sizeof(irc_session_t));
- session->sock = -1;
-
- if ( libirc_mutex_init (&session->mutex_session)
- || libirc_mutex_init (&session->mutex_dcc) )
- {
- free (session);
- return 0;
- }
-
- session->dcc_last_id = 1;
- session->dcc_timeout = 60;
-
- memcpy (&session->callbacks, callbacks, sizeof(irc_callbacks_t));
-
- if ( !session->callbacks.event_ctcp_req )
- session->callbacks.event_ctcp_req = libirc_event_ctcp_internal;
-
- return session;
-}
-
-static void free_ircsession_strings (irc_session_t * session)
-{
- if ( session->realname )
- free (session->realname);
-
- if ( session->username )
- free (session->username);
-
- if ( session->nick )
- free (session->nick);
-
- if ( session->server )
- free (session->server);
-
- if ( session->server_password )
- free (session->server_password);
-
- session->realname = 0;
- session->username = 0;
- session->nick = 0;
- session->server = 0;
- session->server_password = 0;
-}
-
-void irc_destroy_session (irc_session_t * session)
-{
- free_ircsession_strings( session );
-
- // The CTCP VERSION must be freed only now
- if ( session->ctcp_version )
- free (session->ctcp_version);
-
- if ( session->sock >= 0 )
- socket_close (&session->sock);
-
-#if defined (ENABLE_THREADS)
- libirc_mutex_destroy (&session->mutex_session);
-#endif
-
-#if defined (ENABLE_SSL)
- if ( session->ssl )
- SSL_free( session->ssl );
-#endif
-
- /*
- * delete DCC data
- * libirc_remove_dcc_session removes the DCC session from the list.
- */
- while ( session->dcc_sessions )
- libirc_remove_dcc_session (session, session->dcc_sessions, 0);
-
- libirc_mutex_destroy (&session->mutex_dcc);
-
- free (session);
-}
-
-
-int irc_connect (irc_session_t * session,
- const char * server,
- unsigned short port,
- const char * server_password,
- const char * nick,
- const char * username,
- const char * realname)
-{
- struct sockaddr_in saddr;
- char * p;
-
- // Check and copy all the specified fields
- if ( !server || !nick )
- {
- session->lasterror = LIBIRC_ERR_INVAL;
- return 1;
- }
-
- if ( session->state != LIBIRC_STATE_INIT )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- // Free the strings if defined; may be the case when the session is reused after the connection fails
- free_ircsession_strings( session );
-
- // Handle the server # prefix (SSL)
- if ( server[0] == SSL_PREFIX )
- {
-#if defined (ENABLE_SSL)
- server++;
- session->flags |= SESSIONFL_SSL_CONNECTION;
-#else
- session->lasterror = LIBIRC_ERR_SSL_NOT_SUPPORTED;
- return 1;
-#endif
- }
-
- if ( username )
- session->username = strdup (username);
-
- if ( server_password )
- session->server_password = strdup (server_password);
-
- if ( realname )
- session->realname = strdup (realname);
-
- session->nick = strdup (nick);
- session->server = strdup (server);
-
- // If port number is zero and server contains the port, parse it
- if ( port == 0 && (p = strchr( session->server, ':' )) != 0 )
- {
- // Terminate the string and parse the port number
- *p++ = '\0';
- port = atoi( p );
- }
-
- // IPv4 address resolving
- memset( &saddr, 0, sizeof(saddr) );
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons (port);
- saddr.sin_addr.s_addr = inet_addr( session->server );
-
- if ( saddr.sin_addr.s_addr == INADDR_NONE )
- {
- struct hostent *hp;
-#if defined HAVE_GETHOSTBYNAME_R
- int tmp_errno;
- struct hostent tmp_hostent;
- char buf[2048];
-
- if ( gethostbyname_r (session->server, &tmp_hostent, buf, sizeof(buf), &hp, &tmp_errno) )
- hp = 0;
-#else
- hp = gethostbyname (session->server);
-#endif // HAVE_GETHOSTBYNAME_R
- if ( !hp )
- {
- session->lasterror = LIBIRC_ERR_RESOLV;
- return 1;
- }
-
- memcpy (&saddr.sin_addr, hp->h_addr, (size_t) hp->h_length);
- }
-
- // create the IRC server socket
- if ( socket_create( PF_INET, SOCK_STREAM, &session->sock)
- || socket_make_nonblocking (&session->sock) )
- {
- session->lasterror = LIBIRC_ERR_SOCKET;
- return 1;
- }
-
-#if defined (ENABLE_SSL)
- // Init the SSL stuff
- if ( session->flags & SESSIONFL_SSL_CONNECTION )
- {
- int rc = ssl_init( session );
-
- if ( rc != 0 )
- {
- session->lasterror = rc;
- return 1;
- }
- }
-#endif
-
- // and connect to the IRC server
- if ( socket_connect (&session->sock, (struct sockaddr *) &saddr, sizeof(saddr)) )
- {
- session->lasterror = LIBIRC_ERR_CONNECT;
- return 1;
- }
-
- session->state = LIBIRC_STATE_CONNECTING;
- session->flags = SESSIONFL_USES_IPV6; // reset in case of reconnect
- return 0;
-}
-
-
-int irc_connect6 (irc_session_t * session,
- const char * server,
- unsigned short port,
- const char * server_password,
- const char * nick,
- const char * username,
- const char * realname)
-{
-#if defined (ENABLE_IPV6)
- struct sockaddr_in6 saddr;
- struct addrinfo ainfo, *res = NULL;
- char portStr[32], *p;
-#if defined (_WIN32)
- int addrlen = sizeof(saddr);
- HMODULE hWsock;
- getaddrinfo_ptr_t getaddrinfo_ptr;
- freeaddrinfo_ptr_t freeaddrinfo_ptr;
- int resolvesuccess = 0;
-#endif
-
- // Check and copy all the specified fields
- if ( !server || !nick )
- {
- session->lasterror = LIBIRC_ERR_INVAL;
- return 1;
- }
-
- if ( session->state != LIBIRC_STATE_INIT )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- // Free the strings if defined; may be the case when the session is reused after the connection fails
- free_ircsession_strings( session );
-
- // Handle the server # prefix (SSL)
- if ( server[0] == SSL_PREFIX )
- {
-#if defined (ENABLE_SSL)
- server++;
- session->flags |= SESSIONFL_SSL_CONNECTION;
-#else
- session->lasterror = LIBIRC_ERR_SSL_NOT_SUPPORTED;
- return 1;
-#endif
- }
-
- if ( username )
- session->username = strdup (username);
-
- if ( server_password )
- session->server_password = strdup (server_password);
-
- if ( realname )
- session->realname = strdup (realname);
-
- session->nick = strdup (nick);
- session->server = strdup (server);
-
- // If port number is zero and server contains the port, parse it
- if ( port == 0 && (p = strchr( session->server, ':' )) != 0 )
- {
- // Terminate the string and parse the port number
- *p++ = '\0';
- port = atoi( p );
- }
-
- memset( &saddr, 0, sizeof(saddr) );
- saddr.sin6_family = AF_INET6;
- saddr.sin6_port = htons (port);
-
- sprintf( portStr, "%u", (unsigned)port );
-
-#if defined (_WIN32)
- if ( WSAStringToAddressA( (LPSTR)session->server, AF_INET6, NULL, (struct sockaddr *)&saddr, &addrlen ) == SOCKET_ERROR )
- {
- hWsock = LoadLibraryA("ws2_32");
-
- if (hWsock)
- {
- /* Determine functions at runtime, because windows systems < XP do not
- * support getaddrinfo. */
- getaddrinfo_ptr = (getaddrinfo_ptr_t)GetProcAddress(hWsock, "getaddrinfo");
- freeaddrinfo_ptr = (freeaddrinfo_ptr_t)GetProcAddress(hWsock, "freeaddrinfo");
-
- if (getaddrinfo_ptr && freeaddrinfo_ptr)
- {
- memset(&ainfo, 0, sizeof(ainfo));
- ainfo.ai_family = AF_INET6;
- ainfo.ai_socktype = SOCK_STREAM;
- ainfo.ai_protocol = 0;
-
- if ( getaddrinfo_ptr(session->server, portStr, &ainfo, &res) == 0 && res )
- {
- resolvesuccess = 1;
- memcpy( &saddr, res->ai_addr, res->ai_addrlen );
- freeaddrinfo_ptr( res );
- }
- }
- FreeLibrary(hWsock);
- }
- if (!resolvesuccess)
- {
- session->lasterror = LIBIRC_ERR_RESOLV;
- return 1;
- }
- }
-#else
- if ( inet_pton( AF_INET6, session->server, (void*) &saddr.sin6_addr ) <= 0 )
- {
- memset( &ainfo, 0, sizeof(ainfo) );
- ainfo.ai_family = AF_INET6;
- ainfo.ai_socktype = SOCK_STREAM;
- ainfo.ai_protocol = 0;
-
- if ( getaddrinfo( session->server, portStr, &ainfo, &res ) || !res )
- {
- session->lasterror = LIBIRC_ERR_RESOLV;
- return 1;
- }
-
- memcpy( &saddr, res->ai_addr, res->ai_addrlen );
- freeaddrinfo( res );
- }
-#endif
-
- // create the IRC server socket
- if ( socket_create( PF_INET6, SOCK_STREAM, &session->sock)
- || socket_make_nonblocking (&session->sock) )
- {
- session->lasterror = LIBIRC_ERR_SOCKET;
- return 1;
- }
-
-#if defined (ENABLE_SSL)
- // Init the SSL stuff
- if ( session->flags & SESSIONFL_SSL_CONNECTION )
- {
- int rc = ssl_init( session );
-
- if ( rc != 0 )
- return rc;
- }
-#endif
-
- // and connect to the IRC server
- if ( socket_connect (&session->sock, (struct sockaddr *) &saddr, sizeof(saddr)) )
- {
- session->lasterror = LIBIRC_ERR_CONNECT;
- return 1;
- }
-
- session->state = LIBIRC_STATE_CONNECTING;
- session->flags = 0; // reset in case of reconnect
- return 0;
-#else
- session->lasterror = LIBIRC_ERR_NOIPV6;
- return 1;
-#endif
-}
-
-
-int irc_is_connected (irc_session_t * session)
-{
- return (session->state == LIBIRC_STATE_CONNECTED
- || session->state == LIBIRC_STATE_CONNECTING) ? 1 : 0;
-}
-
-
-int irc_run (irc_session_t * session)
-{
- if ( session->state != LIBIRC_STATE_CONNECTING )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- while ( irc_is_connected(session) )
- {
- struct timeval tv;
- fd_set in_set, out_set;
- int maxfd = 0;
-
- tv.tv_usec = 250000;
- tv.tv_sec = 0;
-
- // Init sets
- FD_ZERO (&in_set);
- FD_ZERO (&out_set);
-
- irc_add_select_descriptors (session, &in_set, &out_set, &maxfd);
-
- if ( select (maxfd + 1, &in_set, &out_set, 0, &tv) < 0 )
- {
- if ( socket_error() == EINTR )
- continue;
-
- session->lasterror = LIBIRC_ERR_TERMINATED;
- return 1;
- }
-
- if ( irc_process_select_descriptors (session, &in_set, &out_set) )
- return 1;
- }
-
- return 0;
-}
-
-
-int irc_add_select_descriptors (irc_session_t * session, fd_set *in_set, fd_set *out_set, int * maxfd)
-{
- if ( session->sock < 0
- || session->state == LIBIRC_STATE_INIT
- || session->state == LIBIRC_STATE_DISCONNECTED )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- libirc_mutex_lock (&session->mutex_session);
-
- switch (session->state)
- {
- case LIBIRC_STATE_CONNECTING:
- // While connection, only out_set descriptor should be set
- libirc_add_to_set (session->sock, out_set, maxfd);
- break;
-
- case LIBIRC_STATE_CONNECTED:
- // Add input descriptor if there is space in input buffer
- if ( session->incoming_offset < (sizeof (session->incoming_buf) - 1)
- || (session->flags & SESSIONFL_SSL_WRITE_WANTS_READ) != 0 )
- libirc_add_to_set (session->sock, in_set, maxfd);
-
- // Add output descriptor if there is something in output buffer
- if ( libirc_findcrlf (session->outgoing_buf, session->outgoing_offset) > 0
- || (session->flags & SESSIONFL_SSL_READ_WANTS_WRITE) != 0 )
- libirc_add_to_set (session->sock, out_set, maxfd);
-
- break;
- }
-
- libirc_mutex_unlock (&session->mutex_session);
-
- libirc_dcc_add_descriptors (session, in_set, out_set, maxfd);
- return 0;
-}
-
-
-static void libirc_process_incoming_data (irc_session_t * session, size_t process_length)
-{
- #define MAX_PARAMS_ALLOWED 10
- char buf[2*512], *p, *s;
- const char * command = 0, *prefix = 0, *params[MAX_PARAMS_ALLOWED+1];
- int code = 0, paramindex = 0;
- char *buf_end = buf + process_length;
-
- if ( process_length > sizeof(buf) )
- abort(); // should be impossible
-
- memcpy (buf, session->incoming_buf, process_length);
- buf[process_length] = '\0';
-
- memset ((char *)params, 0, sizeof(params));
- p = buf;
-
- /*
- * From RFC 1459:
- * ::= [':' ]
- * ::= | [ '!' ] [ '@' ]
- * ::= { } |
- * ::= ' ' { ' ' }
- * ::= [ ':' | ]
- * ::=
- * ::=
- */
-
- // Parse
- if ( buf[0] == ':' )
- {
- while ( *p && *p != ' ')
- p++;
-
- *p++ = '\0';
-
- // we use buf+1 to skip the leading colon
- prefix = buf + 1;
-
- // If LIBIRC_OPTION_STRIPNICKS is set, we should 'clean up' nick
- // right here
- if ( session->options & LIBIRC_OPTION_STRIPNICKS )
- {
- for ( s = buf + 1; *s; s++ )
- {
- if ( *s == '@' || *s == '!' )
- {
- *s = '\0';
- break;
- }
- }
- }
- }
-
- // Parse
- if ( isdigit (p[0]) && isdigit (p[1]) && isdigit (p[2]) )
- {
- p[3] = '\0';
- code = atoi (p);
- p += 4;
- }
- else
- {
- s = p;
-
- while ( *p && *p != ' ')
- p++;
-
- *p++ = '\0';
-
- command = s;
- }
-
- // Parse middle/params
- while ( *p && paramindex < MAX_PARAMS_ALLOWED )
- {
- // beginning from ':', this is the last param
- if ( *p == ':' )
- {
- params[paramindex++] = p + 1; // skip :
- break;
- }
-
- // Just a param
- for ( s = p; *p && *p != ' '; p++ )
- ;
-
- params[paramindex++] = s;
-
- if ( !*p )
- break;
-
- *p++ = '\0';
- }
-
- // Handle PING/PONG
- if ( command && !strncmp (command, "PING", buf_end - command) && params[0] )
- {
- irc_send_raw (session, "PONG %s", params[0]);
- return;
- }
-
- // and dump
- if ( code )
- {
- // We use SESSIONFL_MOTD_RECEIVED flag to check whether it is the first
- // RPL_ENDOFMOTD or ERR_NOMOTD after the connection.
- if ( (code == 1 || code == 376 || code == 422) && !(session->flags & SESSIONFL_MOTD_RECEIVED ) )
- {
- session->flags |= SESSIONFL_MOTD_RECEIVED;
-
- if ( session->callbacks.event_connect )
- (*session->callbacks.event_connect) (session, "CONNECT", prefix, params, paramindex);
- }
-
- if ( session->callbacks.event_numeric )
- (*session->callbacks.event_numeric) (session, code, prefix, params, paramindex);
- }
- else
- {
- if ( !strncmp (command, "NICK", buf_end - command) )
- {
- /*
- * If we're changed our nick, we should save it.
- */
- char nickbuf[256];
-
- irc_target_get_nick (prefix, nickbuf, sizeof(nickbuf));
-
- if ( !strncmp (nickbuf, session->nick, strlen(session->nick)) && paramindex > 0 )
- {
- free (session->nick);
- session->nick = strdup (params[0]);
- }
-
- if ( session->callbacks.event_nick )
- (*session->callbacks.event_nick) (session, command, prefix, params, paramindex);
- }
- else if ( !strncmp (command, "QUIT", buf_end - command) )
- {
- if ( session->callbacks.event_quit )
- (*session->callbacks.event_quit) (session, command, prefix, params, paramindex);
- }
- else if ( !strncmp (command, "JOIN", buf_end - command) )
- {
- if ( session->callbacks.event_join )
- (*session->callbacks.event_join) (session, command, prefix, params, paramindex);
- }
- else if ( !strncmp (command, "PART", buf_end - command) )
- {
- if ( session->callbacks.event_part )
- (*session->callbacks.event_part) (session, command, prefix, params, paramindex);
- }
- else if ( !strncmp (command, "MODE", buf_end - command) )
- {
- if ( paramindex > 0 && !strncmp (params[0], session->nick, strlen(session->nick)) )
- {
- params[0] = params[1];
- paramindex = 1;
-
- if ( session->callbacks.event_umode )
- (*session->callbacks.event_umode) (session, command, prefix, params, paramindex);
- }
- else
- {
- if ( session->callbacks.event_mode )
- (*session->callbacks.event_mode) (session, command, prefix, params, paramindex);
- }
- }
- else if ( !strncmp (command, "TOPIC", buf_end - command) )
- {
- if ( session->callbacks.event_topic )
- (*session->callbacks.event_topic) (session, command, prefix, params, paramindex);
- }
- else if ( !strncmp (command, "KICK", buf_end - command) )
- {
- if ( session->callbacks.event_kick )
- (*session->callbacks.event_kick) (session, command, prefix, params, paramindex);
- }
- else if ( !strncmp (command, "PRIVMSG", buf_end - command) )
- {
- if ( paramindex > 1 )
- {
- size_t msglen = strlen (params[1]);
-
- /*
- * Check for CTCP request (a CTCP message starts from 0x01
- * and ends by 0x01
- */
- if ( params[1][0] == 0x01 && params[1][msglen-1] == 0x01 )
- {
- char ctcp_buf[128];
-
- msglen -= 2;
- if ( msglen > sizeof(ctcp_buf) - 1 )
- msglen = sizeof(ctcp_buf) - 1;
-
- memcpy (ctcp_buf, params[1] + 1, msglen);
- ctcp_buf[msglen] = '\0';
-
- if ( !strncasecmp(ctcp_buf, "DCC ", 4) )
- libirc_dcc_request (session, prefix, ctcp_buf);
- else if ( !strncasecmp( ctcp_buf, "ACTION ", 7)
- && session->callbacks.event_ctcp_action )
- {
- params[1] = ctcp_buf + 7; // the length of "ACTION "
- paramindex = 2;
-
- (*session->callbacks.event_ctcp_action) (session, "ACTION", prefix, params, paramindex);
- }
- else
- {
- params[0] = ctcp_buf;
- paramindex = 1;
-
- if ( session->callbacks.event_ctcp_req )
- (*session->callbacks.event_ctcp_req) (session, "CTCP", prefix, params, paramindex);
- }
- }
- else if ( !strncasecmp (params[0], session->nick, strlen(session->nick) ) )
- {
- if ( session->callbacks.event_privmsg )
- (*session->callbacks.event_privmsg) (session, "PRIVMSG", prefix, params, paramindex);
- }
- else
- {
- if ( session->callbacks.event_channel )
- (*session->callbacks.event_channel) (session, "CHANNEL", prefix, params, paramindex);
- }
- }
- }
- else if ( !strncmp (command, "NOTICE", buf_end - command) )
- {
- size_t msglen = strlen (params[1]);
-
- /*
- * Check for CTCP request (a CTCP message starts from 0x01
- * and ends by 0x01
- */
- if ( paramindex > 1 && params[1][0] == 0x01 && params[1][msglen-1] == 0x01 )
- {
- char ctcp_buf[512];
-
- msglen -= 2;
- if ( msglen > sizeof(ctcp_buf) - 1 )
- msglen = sizeof(ctcp_buf) - 1;
-
- memcpy (ctcp_buf, params[1] + 1, msglen);
- ctcp_buf[msglen] = '\0';
-
- params[0] = ctcp_buf;
- paramindex = 1;
-
- if ( session->callbacks.event_ctcp_rep )
- (*session->callbacks.event_ctcp_rep) (session, "CTCP", prefix, params, paramindex);
- }
- else if ( !strncasecmp (params[0], session->nick, strlen(session->nick) ) )
- {
- if ( session->callbacks.event_notice )
- (*session->callbacks.event_notice) (session, command, prefix, params, paramindex);
- } else {
- if ( session->callbacks.event_channel_notice )
- (*session->callbacks.event_channel_notice) (session, command, prefix, params, paramindex);
- }
- }
- else if ( !strncmp (command, "INVITE", buf_end - command) )
- {
- if ( session->callbacks.event_invite )
- (*session->callbacks.event_invite) (session, command, prefix, params, paramindex);
- }
- else if ( !strncmp (command, "KILL", buf_end - command) )
- {
- ; /* ignore this event - not all servers generate this */
- }
- else
- {
- /*
- * The "unknown" event is triggered upon receipt of any number of
- * unclassifiable miscellaneous messages, which aren't handled by
- * the library.
- */
-
- if ( session->callbacks.event_unknown )
- (*session->callbacks.event_unknown) (session, command, prefix, params, paramindex);
- }
- }
-}
-
-
-int irc_process_select_descriptors (irc_session_t * session, fd_set *in_set, fd_set *out_set)
-{
- char buf[256], hname[256];
-
- if ( session->sock < 0
- || session->state == LIBIRC_STATE_INIT
- || session->state == LIBIRC_STATE_DISCONNECTED )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- session->lasterror = 0;
- libirc_dcc_process_descriptors (session, in_set, out_set);
-
- // Handle "connection succeed" / "connection failed"
- if ( session->state == LIBIRC_STATE_CONNECTING
- && FD_ISSET (session->sock, out_set) )
- {
- // Now we have to determine whether the socket is connected
- // or the connect is failed
- struct sockaddr_storage saddr, laddr;
- socklen_t slen = sizeof(saddr);
- socklen_t llen = sizeof(laddr);
-
- if ( getsockname (session->sock, (struct sockaddr*)&laddr, &llen) < 0
- || getpeername (session->sock, (struct sockaddr*)&saddr, &slen) < 0 )
- {
- // connection failed
- session->lasterror = LIBIRC_ERR_CONNECT;
- session->state = LIBIRC_STATE_DISCONNECTED;
- return 1;
- }
-
- if (saddr.ss_family == AF_INET)
- memcpy (&session->local_addr, &((struct sockaddr_in *)&laddr)->sin_addr, sizeof(struct in_addr));
- else
- memcpy (&session->local_addr, &((struct sockaddr_in6 *)&laddr)->sin6_addr, sizeof(struct in6_addr));
-
-#if defined (ENABLE_DEBUG)
- if ( IS_DEBUG_ENABLED(session) )
- fprintf (stderr, "[DEBUG] Detected local address: %s\n", inet_ntoa(session->local_addr));
-#endif
-
- session->state = LIBIRC_STATE_CONNECTED;
-
- // Get the hostname
- if ( gethostname (hname, sizeof(hname)) < 0 )
- strcpy (hname, "unknown");
-
- // Prepare the data, which should be sent to the server
- if ( session->server_password )
- {
- snprintf (buf, sizeof(buf), "PASS %s", session->server_password);
- irc_send_raw (session, buf);
- }
-
- snprintf (buf, sizeof(buf), "NICK %s", session->nick);
- irc_send_raw (session, buf);
-
- /*
- * RFC 1459 states that "hostname and servername are normally
- * ignored by the IRC server when the USER command comes from
- * a directly connected client (for security reasons)", therefore
- * we don't need them.
- */
- snprintf (buf, sizeof(buf), "USER %s unknown unknown :%s",
- session->username ? session->username : "nobody",
- session->realname ? session->realname : "noname");
- irc_send_raw (session, buf);
-
- return 0;
- }
-
- if ( session->state != LIBIRC_STATE_CONNECTED )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- // Hey, we've got something to read!
- if ( FD_ISSET (session->sock, in_set) )
- {
- int offset, length = session_socket_read( session );
-
- if ( length < 0 )
- {
- if ( session->lasterror == 0 )
- session->lasterror = (length == 0 ? LIBIRC_ERR_CLOSED : LIBIRC_ERR_TERMINATED);
-
- session->state = LIBIRC_STATE_DISCONNECTED;
- return 1;
- }
-
- session->incoming_offset += length;
-
- // process the incoming data
- while ( (offset = libirc_findcrlf (session->incoming_buf, session->incoming_offset)) > 0 )
- {
-#if defined (ENABLE_DEBUG)
- if ( IS_DEBUG_ENABLED(session) )
- libirc_dump_data ("RECV", session->incoming_buf, offset);
-#endif
- // parse the string
- libirc_process_incoming_data (session, offset);
-
- offset = libirc_findcrlf_offset(session->incoming_buf, offset, session->incoming_offset);
-
- if ( session->incoming_offset - offset > 0 )
- memmove (session->incoming_buf, session->incoming_buf + offset, session->incoming_offset - offset);
-
- session->incoming_offset -= offset;
- }
- }
-
- // We can write a stored buffer
- if ( FD_ISSET (session->sock, out_set) )
- {
- int length;
-
- // Because outgoing_buf could be changed asynchronously, we should lock any change
- libirc_mutex_lock (&session->mutex_session);
- length = session_socket_write( session );
-
- if ( length < 0 )
- {
- if ( session->lasterror == 0 )
- session->lasterror = (length == 0 ? LIBIRC_ERR_CLOSED : LIBIRC_ERR_TERMINATED);
-
- session->state = LIBIRC_STATE_DISCONNECTED;
-
- libirc_mutex_unlock (&session->mutex_session);
- return 1;
- }
-
-#if defined (ENABLE_DEBUG)
- if ( IS_DEBUG_ENABLED(session) )
- libirc_dump_data ("SEND", session->outgoing_buf, length);
-#endif
-
- if ( length > 0 && session->outgoing_offset - length > 0 )
- memmove (session->outgoing_buf, session->outgoing_buf + length, session->outgoing_offset - length);
-
- session->outgoing_offset -= length;
- libirc_mutex_unlock (&session->mutex_session);
- }
-
- return 0;
-}
-
-
-int irc_send_raw (irc_session_t * session, const char * format, ...)
-{
- char buf[1024];
- va_list va_alist;
-
- if ( session->state != LIBIRC_STATE_CONNECTED )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- va_start (va_alist, format);
- vsnprintf (buf, sizeof(buf), format, va_alist);
- va_end (va_alist);
-
- libirc_mutex_lock (&session->mutex_session);
-
- if ( (strlen(buf) + 2) >= (sizeof(session->outgoing_buf) - session->outgoing_offset) )
- {
- libirc_mutex_unlock (&session->mutex_session);
- session->lasterror = LIBIRC_ERR_NOMEM;
- return 1;
- }
-
- strcpy (session->outgoing_buf + session->outgoing_offset, buf);
- session->outgoing_offset += strlen (buf);
- session->outgoing_buf[session->outgoing_offset++] = 0x0D;
- session->outgoing_buf[session->outgoing_offset++] = 0x0A;
-
- libirc_mutex_unlock (&session->mutex_session);
- return 0;
-}
-
-
-int irc_cmd_quit (irc_session_t * session, const char * reason)
-{
- return irc_send_raw (session, "QUIT :%s", reason ? reason : "quit");
-}
-
-
-int irc_cmd_join (irc_session_t * session, const char * channel, const char * key)
-{
- if ( !channel )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- if ( key )
- return irc_send_raw (session, "JOIN %s :%s", channel, key);
- else
- return irc_send_raw (session, "JOIN %s", channel);
-}
-
-
-int irc_cmd_part (irc_session_t * session, const char * channel)
-{
- if ( !channel )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- return irc_send_raw (session, "PART %s", channel);
-}
-
-
-int irc_cmd_topic (irc_session_t * session, const char * channel, const char * topic)
-{
- if ( !channel )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- if ( topic )
- return irc_send_raw (session, "TOPIC %s :%s", channel, topic);
- else
- return irc_send_raw (session, "TOPIC %s", channel);
-}
-
-int irc_cmd_names (irc_session_t * session, const char * channel)
-{
- if ( !channel )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- return irc_send_raw (session, "NAMES %s", channel);
-}
-
-
-int irc_cmd_list (irc_session_t * session, const char * channel)
-{
- if ( channel )
- return irc_send_raw (session, "LIST %s", channel);
- else
- return irc_send_raw (session, "LIST");
-}
-
-
-int irc_cmd_invite (irc_session_t * session, const char * nick, const char * channel)
-{
- if ( !channel || !nick )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- return irc_send_raw (session, "INVITE %s %s", nick, channel);
-}
-
-
-int irc_cmd_kick (irc_session_t * session, const char * nick, const char * channel, const char * comment)
-{
- if ( !channel || !nick )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- if ( comment )
- return irc_send_raw (session, "KICK %s %s :%s", channel, nick, comment);
- else
- return irc_send_raw (session, "KICK %s %s", channel, nick);
-}
-
-
-int irc_cmd_msg (irc_session_t * session, const char * nch, const char * text)
-{
- if ( !nch || !text )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- return irc_send_raw (session, "PRIVMSG %s :%s", nch, text);
-}
-
-
-int irc_cmd_notice (irc_session_t * session, const char * nch, const char * text)
-{
- if ( !nch || !text )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- return irc_send_raw (session, "NOTICE %s :%s", nch, text);
-}
-
-void irc_target_get_nick (const char * target, char *nick, size_t size)
-{
- char *p = strstr (target, "!");
- unsigned int len;
-
- if ( p )
- len = p - target;
- else
- len = strlen (target);
-
- if ( len > size-1 )
- len = size - 1;
-
- memcpy (nick, target, len);
- nick[len] = '\0';
-}
-
-
-void irc_target_get_host (const char * target, char *host, size_t size)
-{
- unsigned int len;
- const char *p = strstr (target, "!");
-
- if ( !p )
- p = target;
-
- len = strlen (p);
-
- if ( len > size-1 )
- len = size - 1;
-
- memcpy (host, p, len);
- host[len] = '\0';
-}
-
-
-int irc_cmd_ctcp_request (irc_session_t * session, const char * nick, const char * reply)
-{
- if ( !nick || !reply )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- return irc_send_raw (session, "PRIVMSG %s :\x01%s\x01", nick, reply);
-}
-
-
-int irc_cmd_ctcp_reply (irc_session_t * session, const char * nick, const char * reply)
-{
- if ( !nick || !reply )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- return irc_send_raw (session, "NOTICE %s :\x01%s\x01", nick, reply);
-}
-
-
-void irc_get_version (unsigned int * high, unsigned int * low)
-{
- *high = LIBIRC_VERSION_HIGH;
- *low = LIBIRC_VERSION_LOW;
-}
-
-
-void irc_set_ctx (irc_session_t * session, void * ctx)
-{
- session->ctx = ctx;
-}
-
-
-void * irc_get_ctx (irc_session_t * session)
-{
- return session->ctx;
-}
-
-
-void irc_set_ctcp_version (irc_session_t * session, const char * version)
-{
- if ( session->ctcp_version )
- free(session->ctcp_version);
-
- session->ctcp_version = strdup(version);
-}
-
-
-void irc_disconnect (irc_session_t * session)
-{
- if ( session->sock >= 0 )
- socket_close (&session->sock);
-
- session->sock = -1;
- session->state = LIBIRC_STATE_INIT;
-}
-
-
-int irc_cmd_me (irc_session_t * session, const char * nch, const char * text)
-{
- if ( !nch || !text )
- {
- session->lasterror = LIBIRC_ERR_STATE;
- return 1;
- }
-
- return irc_send_raw (session, "PRIVMSG %s :\x01" "ACTION %s\x01", nch, text);
-}
-
-
-void irc_option_set (irc_session_t * session, unsigned int option)
-{
- session->options |= option;
-}
-
-
-void irc_option_reset (irc_session_t * session, unsigned int option)
-{
- session->options &= ~option;
-}
-
-
-int irc_cmd_channel_mode (irc_session_t * session, const char * channel, const char * mode)
-{
- if ( !channel )
- {
- session->lasterror = LIBIRC_ERR_INVAL;
- return 1;
- }
-
- if ( mode )
- return irc_send_raw (session, "MODE %s %s", channel, mode);
- else
- return irc_send_raw (session, "MODE %s", channel);
-}
-
-
-int irc_cmd_user_mode (irc_session_t * session, const char * mode)
-{
- if ( mode )
- return irc_send_raw (session, "MODE %s %s", session->nick, mode);
- else
- return irc_send_raw (session, "MODE %s", session->nick);
-}
-
-
-int irc_cmd_nick (irc_session_t * session, const char * newnick)
-{
- if ( !newnick )
- {
- session->lasterror = LIBIRC_ERR_INVAL;
- return 1;
- }
-
- return irc_send_raw (session, "NICK %s", newnick);
-}
-
-int irc_cmd_whois (irc_session_t * session, const char * nick)
-{
- if ( !nick )
- {
- session->lasterror = LIBIRC_ERR_INVAL;
- return 1;
- }
-
- return irc_send_raw (session, "WHOIS %s %s", nick, nick);
-}
diff --git a/external/IRC/params.h b/external/IRC/params.h
deleted file mode 100644
index 2b57c530..00000000
--- a/external/IRC/params.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or (at your
- * option) any later version.
- *
- * This library 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 Lesser General Public
- * License for more details.
- */
-
-#ifndef INCLUDE_IRC_PARAMS_H
-#define INCLUDE_IRC_PARAMS_H
-
-
-#define LIBIRC_VERSION_HIGH 1
-#define LIBIRC_VERSION_LOW 8
-
-#define LIBIRC_BUFFER_SIZE 1024
-#define LIBIRC_DCC_BUFFER_SIZE 1024
-
-#define LIBIRC_STATE_INIT 0
-#define LIBIRC_STATE_LISTENING 1
-#define LIBIRC_STATE_CONNECTING 2
-#define LIBIRC_STATE_CONNECTED 3
-#define LIBIRC_STATE_DISCONNECTED 4
-#define LIBIRC_STATE_CONFIRM_SIZE 5 // Used only by DCC send to confirm the amount of sent data
-#define LIBIRC_STATE_REMOVED 10 // this state is used only in DCC
-
-
-#define SSL_PREFIX '#'
-
-#endif /* INCLUDE_IRC_PARAMS_H */
diff --git a/external/IRC/portable.c b/external/IRC/portable.c
deleted file mode 100644
index 7b6f72bd..00000000
--- a/external/IRC/portable.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or (at your
- * option) any later version.
- *
- * This library 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 Lesser General Public
- * License for more details.
- */
-
-#if !defined (_WIN32)
- #include "config.h"
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #if defined (ENABLE_THREADS)
- #include
- typedef pthread_mutex_t port_mutex_t;
-
- #if !defined (PTHREAD_MUTEX_RECURSIVE) && defined (PTHREAD_MUTEX_RECURSIVE_NP)
- #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
- #endif
- #endif
-#else
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #if defined (ENABLE_THREADS)
- typedef CRITICAL_SECTION port_mutex_t;
- #endif
-
- #define inline
- #define snprintf _snprintf
- #define vsnprintf _vsnprintf
- #define strncasecmp _strnicmp
-#endif
-
-
-#if defined (ENABLE_SSL)
- #include