diff --git a/Makefile.main b/Makefile.main index 11da03c..3e554d3 100644 --- a/Makefile.main +++ b/Makefile.main @@ -1,6 +1,24 @@ include $(CONFIG) +BUILD_FOR ?= linux -CPPFLAGS += -Iinclude -I$(OUTDIR) -I$(OUTDIR)/data -DEBCL_BUILD +# Select compiler (g++ for linux, mingw-w64/posix for windows) +ifeq ($(BUILD_FOR),linux) +CXX=x86_64-linux-gnu-g++ +else +ifeq ($(BUILD_FOR),win) +CXX=x86_64-w64-mingw32-g++-posix +else +$(error Invalid target "$(BUILD_FOR)") +endif +endif + +# FIXME: temporarily used for Windows build +ifeq ($(BUILD_FOR),win) +CPPFLAGS += -I/tmp/cppunit/include +LDFLAGS += -L/tmp/cppunit/src/cppunit/.libs/ +endif + +CPPFLAGS += -Iinclude -I$(OUTDIR) -I$(OUTDIR)/data -DEBCL_BUILD -D_USE_MATH_DEFINES CXXFLAGS += -std=c++14 -Wall -Wextra LDFLAGS += -L$(OUTDIR) -pthread @@ -14,9 +32,32 @@ ifeq ($(DEBUG),y) CXXFLAGS += -g endif -CXXFLAGS_LIB = $(CXXFLAGS) +# Libs for either Linux or Windows +ifeq ($(BUILD_FOR),linux) LIBS_LIB = -ldl -latomic -LIB_DYNAMIC = $(OUTDIR)/libebcorelib.so +else +ifeq ($(BUILD_FOR),win) +LIBS_LIB = -latomic +else +$(error Invalid target "$(BUILD_FOR)") +endif +endif + +# Library and progam suffixes +ifeq ($(BUILD_FOR),linux) +SUFFIX_LIB=.so +SUFFIX_EXE= +else +ifeq ($(BUILD_FOR),win) +SUFFIX_LIB=.dll +SUFFIX_EXE=.exe +else +$(error Invalid target "$(BUILD_FOR)") +endif +endif + +CXXFLAGS_LIB = $(CXXFLAGS) +LIB_DYNAMIC = $(OUTDIR)/libebcorelib$(SUFFIX_LIB) LIB_STATIC = $(OUTDIR)/libebcorelib.a LIB_TARGETS = ifeq ($(BUILD_DYNAMIC_LIB),y) @@ -31,8 +72,8 @@ include src/files.mk LIB_OBJS = $(addprefix $(OUTDIR)/,$(addsuffix .o, $(subst src/,, $(basename $(LIB_SOURCES))))) include tests/list.mk -TEST_SUITES := $(addprefix $(OUTDIR)/test-,$(TESTS)) -TEST_ALL := $(OUTDIR)/run-all-tests +TEST_SUITES := $(addsuffix $(SUFFIX_EXE), $(addprefix $(OUTDIR)/test-,$(TESTS))) +TEST_ALL := $(OUTDIR)/run-all-tests$(SUFFIX_EXE) TEST_MAIN := $(OUTDIR)/tests/run-test.o TEST_OBJS := $(addsuffix .o,$(addprefix $(OUTDIR)/tests/,$(TESTS))) $(TEST_MAIN) LIBS_TESTS = -lcppunit @@ -88,7 +129,7 @@ fullclean: clean -rmdir $(sort $(dir $(TEST_OBJS)) $(dir $(LIB_OBJS))) -rmdir $(OUTDIR) -tests: $(LIB_LWLIB) $(TEST_OBJS) $(TEST_SUITES) $(TEST_ALL) +tests: $(TEST_OBJS) $(TEST_SUITES) $(TEST_ALL) .PHONY: all run debug run-tests clean fullclean tests @@ -109,10 +150,10 @@ $(LIB_STATIC): $(LIB_OBJS) ar crD $(LIB_STATIC) $(LIB_OBJS) # Tests -$(TEST_SUITES): $(OUTDIR)/test-%: $(OUTDIR)/tests/%.o $(TEST_MAIN) $(TEST_NEEDS) +$(TEST_SUITES): $(OUTDIR)/test-%$(SUFFIX_EXE): $(OUTDIR)/tests/%.o $(TEST_MAIN) $(TEST_NEEDS) $(CXX) $(LDFLAGS) -o $@ $< $(TEST_MAIN) $(LIBS_TESTS) -$(TEST_ALL): $(TEST_OBJS) $(LIB_LWLIB) +$(TEST_ALL): $(TEST_OBJS) $(CXX) $(LDFLAGS) -o $@ $(TEST_OBJS) $(LIBS_TESTS) diff --git a/TODO b/TODO index 1dafb5d..ac7c01c 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,5 @@ -Tests for T_FSPath -Generalize iterators +* Tests for T_FSPath +* Generalize iterators +* Fix output of appendDouble so it's consistent on both Linux + and Windows +* Reimplement threading so it avoids yet another DLL on windows diff --git a/include/ebcl/Externals.hh b/include/ebcl/Externals.hh index aaff832..ae8c108 100644 --- a/include/ebcl/Externals.hh +++ b/include/ebcl/Externals.hh @@ -19,4 +19,8 @@ #include #include +#ifdef _WIN32 +# include +#endif // _WIN32 + #endif // _H_EBCL_EXTERNALS diff --git a/include/ebcl/SRDData.hh b/include/ebcl/SRDData.hh index 77efaed..ed36f5d 100644 --- a/include/ebcl/SRDData.hh +++ b/include/ebcl/SRDData.hh @@ -118,7 +118,7 @@ M_LSHIFT_OP( T_StringBuilder , T_SRDLocation const& ) noexcept; // Type of an error record enum class E_SRDErrorType { - ERROR , + ERR , WARNING , NOTE }; @@ -137,7 +137,7 @@ class T_SRDError T_SRDError( T_String error , T_SRDLocation location , - E_SRDErrorType type = E_SRDErrorType::ERROR ) noexcept; + E_SRDErrorType type = E_SRDErrorType::ERR ) noexcept; T_SRDError( T_SRDError const& other ) noexcept; T_SRDError& operator= ( T_SRDError const& other ) noexcept; diff --git a/src/DynLib.cc b/src/DynLib.cc index c0de76b..8049144 100644 --- a/src/DynLib.cc +++ b/src/DynLib.cc @@ -7,9 +7,79 @@ using namespace ebcl; #ifdef _WIN32 -# error "Not implemented" -#endif +/*= T_DynLibWindows ==========================================================*/ + +namespace { +struct T_DynLibWindows_ +{ + T_Buffer< char > path; + T_String error; + HMODULE lib; + + explicit T_DynLibWindows_( T_String const& path ) noexcept; + explicit T_DynLibWindows_( char const* const path ) noexcept; + ~T_DynLibWindows_( ) noexcept; + + bool load( ) noexcept; + void unload( ) noexcept; + + bool isLoaded( ) const noexcept; + + void* getSymbol( char const* const symbol ) noexcept; +}; +} // namespace + +/*----------------------------------------------------------------------------*/ + +inline T_DynLibWindows_::T_DynLibWindows_( + T_String const& path ) noexcept + : path( path.toOSString( ) ) , lib( nullptr ) +{ } + +inline T_DynLibWindows_::T_DynLibWindows_( + char const* const path ) noexcept + : path( path , strlen( path ) ) , lib( nullptr ) +{ } + +inline T_DynLibWindows_::~T_DynLibWindows_( ) noexcept +{ + unload( ); +} + +/*----------------------------------------------------------------------------*/ + +inline bool T_DynLibWindows_::load( ) noexcept +{ + lib = LoadLibraryW( (wchar_t const*) path.data( ) ); + return lib != nullptr; +} + +inline void T_DynLibWindows_::unload( ) noexcept +{ + if ( lib != nullptr ) { + FreeLibrary( lib ); + lib = nullptr; + } +} + +inline bool T_DynLibWindows_::isLoaded( ) const noexcept +{ + return lib != nullptr; +} + +/*----------------------------------------------------------------------------*/ + +inline void* T_DynLibWindows_::getSymbol( + char const* const symbol ) noexcept +{ + return (void*) GetProcAddress( lib , symbol ); +} + +using T_DynLibImpl_ = T_DynLibWindows_; + + +#else // ifdef _WIN32 /*= T_DynLibLinux_ ===========================================================*/ @@ -89,11 +159,12 @@ inline void* T_DynLibLinux_::getSymbol( return ptr; } +using T_DynLibImpl_ = T_DynLibLinux_; + +#endif // ifdef _WIN32 /*= T_DynLib =================================================================*/ -using T_DynLibImpl_ = T_DynLibLinux_; // FIXME - T_DynLib::T_DynLib( T_String const& name ) : A_PrivateImplementation( new T_DynLibImpl_( name ) ) diff --git a/src/SRDData.cc b/src/SRDData.cc index cca94a9..fcf07fb 100644 --- a/src/SRDData.cc +++ b/src/SRDData.cc @@ -104,7 +104,7 @@ T_StringBuilder& ebcl::operator<< ( void T_SRDErrors::checkAdded( T_SRDError const& last ) { - if ( last.type( ) != E_SRDErrorType::ERROR + if ( last.type( ) != E_SRDErrorType::ERR || errCount_ >= MAX_ERRORS ) { return; } @@ -129,7 +129,7 @@ void T_SRDErrors::addAll( RPC_SRDLocation lastLocation = nullptr; for ( uint32_t i = 0 ; i < nErrors ; i ++ ) { errors_.add( source[ i ] ); - if ( source[ i ].type( ) == E_SRDErrorType::ERROR ) { + if ( source[ i ].type( ) == E_SRDErrorType::ERR ) { lastLocation = &source[ i ].location( ); } } diff --git a/src/Strings.cc b/src/Strings.cc index 3e1168f..74d2e32 100644 --- a/src/Strings.cc +++ b/src/Strings.cc @@ -1677,14 +1677,16 @@ T_Buffer< char > T_String::toOSString( ) const #ifdef _WIN32 const auto n( data_->length( ) ); - T_Buffer< char > output( ( n + 1 ) * 2 ); + const auto rsz( MultiByteToWideChar( CP_UTF8 , 0 , + data( ) , data_->size( ) , + nullptr , 0 ) ); + T_Buffer< char > output( rsz * 2 ); if ( !MultiByteToWideChar( CP_UTF8 , 0 , data( ) , data_->size( ) , - ( wchar_t* ) output.data( ) , n ) ) + ( wchar_t* ) output.data( ) , rsz * 2 ) ) { return T_Buffer< char >( ); } - output[ n * 2 ] = output[ n * 2 + 1 ] = 0; return output; #else diff --git a/tests/srd-lexer.cc b/tests/srd-lexer.cc index aef548f..b748598 100644 --- a/tests/srd-lexer.cc +++ b/tests/srd-lexer.cc @@ -454,37 +454,37 @@ void SRDLexerTest::testIntegers( ) M_CKLS_( 11 ); M_CKTOK_( 0 , INT , 1 , 1 ); - CPPUNIT_ASSERT_EQUAL( 0l , list[ 0 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , list[ 0 ].longValue( ) ); M_CKTOK_( 1 , INT , 1 , 3 ); - CPPUNIT_ASSERT_EQUAL( 0l , list[ 1 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , list[ 1 ].longValue( ) ); M_CKTOK_( 2 , INT , 1 , 7 ); - CPPUNIT_ASSERT_EQUAL( 0l , list[ 2 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , list[ 2 ].longValue( ) ); M_CKTOK_( 3 , INT , 1 , 10 ); - CPPUNIT_ASSERT_EQUAL( 1l , list[ 3 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( 1 ) , list[ 3 ].longValue( ) ); M_CKTOK_( 4 , INT , 1 , 12 ); - CPPUNIT_ASSERT_EQUAL( -1l , list[ 4 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( -1 ) , list[ 4 ].longValue( ) ); M_CKTOK_( 5 , INT , 1 , 15 ); - CPPUNIT_ASSERT_EQUAL( 123l , list[ 5 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( 123 ) , list[ 5 ].longValue( ) ); M_CKTOK_( 6 , INT , 1 , 19 ); - CPPUNIT_ASSERT_EQUAL( -123l , list[ 6 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( -123 ) , list[ 6 ].longValue( ) ); M_CKTOK_( 7 , LONG , 1 , 24 ); - CPPUNIT_ASSERT_EQUAL( 5000000000l , list[ 7 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( 5000000000 ) , list[ 7 ].longValue( ) ); M_CKTOK_( 8 , LONG , 1 , 35 ); - CPPUNIT_ASSERT_EQUAL( -5000000000l , list[ 8 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( -5000000000 ) , list[ 8 ].longValue( ) ); M_CKTOK_( 9 , INT , 1 , 47 ); - CPPUNIT_ASSERT_EQUAL( 0l , list[ 9 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( 0 ) , list[ 9 ].longValue( ) ); M_CKTOK_( 10 , INT , 1 , 94 ); - CPPUNIT_ASSERT_EQUAL( 123l , list[ 10 ].longValue( ) ); + CPPUNIT_ASSERT_EQUAL( int64_t( 123 ) , list[ 10 ].longValue( ) ); } void SRDLexerTest::testFloatValid( ) diff --git a/tests/strings-builder.cc b/tests/strings-builder.cc index 0d40770..e874fbb 100644 --- a/tests/strings-builder.cc +++ b/tests/strings-builder.cc @@ -537,8 +537,10 @@ void StringsBuilderTest::testAppendUnicode( ) const char t[] = STR; \ const uint32_t sz = sizeof( t ) - 1; \ if ( sz != sbo.size( ) || memcmp( sbo.data( ) , t , sz ) ) { \ - const auto x( T_String( sbo ).toOSString( ) ); \ - printf( "'%s' | expected '%s'\n" , x.data( ) , STR ); \ + char x[ sbo.size( ) + 1 ]; \ + x[ sizeof( x ) - 1 ] = 0; \ + memcpy( x , sbo.data( ) , sizeof( x ) - 1 ); \ + printf( "'%s' | expected '%s'\n" , x , STR ); \ } \ CPPUNIT_ASSERT_EQUAL( sz , sbo.size( ) ); \ CPPUNIT_ASSERT( !memcmp( sbo.data( ) , t , sz ) ); \