diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 0000000..bdc1919 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,41 @@ +name: OS Starter Project + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install GNU pth (userland threads example) + run: sudo apt install libpth-dev + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Build + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Test + working-directory: ${{github.workspace}}/build + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + #run: ctest -C ${{env.BUILD_TYPE}} + run: for test_bin in bin/*tests; do "./$test_bin"; done \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e5481d --- /dev/null +++ b/.gitignore @@ -0,0 +1,77 @@ +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +build/ + +# Backups +*~ +*.orig +*.swp + +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Targets to ignore +bin/ +lib/ + +# IntelliJ/CLion + +.idea/ +*-debug/ \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..157bd90 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,10 @@ +# This configuration file was automatically generated by Gitpod. +# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file) +# and commit this file to your remote git repository to share the goodness with others. + +tasks: + - init: | + sudo apt update -q && sudo apt upgrade -y -q + sudo apt install cmake -y + cmake -DCMAKE_BUILD_TYPE=Debug -S . -B build + cmake --build build \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ef6140e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.5) + +project(OperatingSystemsStarter) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +set(CMAKE_CXX_STANDARD 17) + +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0 +) + +# Windows workaround (don't ask) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +FetchContent_MakeAvailable(googletest) +include_directories(${GTEST_INCLUDE_DIRS}) + +add_subdirectory(hello) +add_subdirectory(hello-lib) +add_subdirectory(lwlog-lib) +add_subdirectory(lwlog-demo) +add_subdirectory(gtest-demo) + +# You can use add_subdirectory() to add your own work. +# Please don't remove the existing subdirectories. \ No newline at end of file diff --git a/README.md b/README.md index 26bd4df..e69de29 100644 --- a/README.md +++ b/README.md @@ -1 +0,0 @@ -[![Open in Codespaces](https://classroom.github.com/assets/launch-codespace-7f7980b617ed060a017424585567c406b6ee15c891e84e1186181d67ecf80aa0.svg)](https://classroom.github.com/open-in-codespaces?assignment_repo_id=13588010) diff --git a/gtest-demo/CMakeLists.txt b/gtest-demo/CMakeLists.txt new file mode 100644 index 0000000..f138bb3 --- /dev/null +++ b/gtest-demo/CMakeLists.txt @@ -0,0 +1,38 @@ +FetchContent_MakeAvailable(googletest) + +enable_testing() + +add_executable( + square_root_app + square_root_app.c + square_root.c) + +add_executable( + countbits_app + countbits_app.c + countbits.c) + +add_executable( + square_root_tests + square_root_tests.cc + square_root.c) + +add_executable( + countbits_tests + countbits_tests.cc + countbits.c) + +target_link_libraries(square_root_app + -lpthread + -lm) + +target_link_libraries(square_root_tests + gtest_main + -lpthread + -lm) + +target_link_libraries(countbits_tests + gtest_main + -lpthread + -lm) +include(GoogleTest) \ No newline at end of file diff --git a/gtest-demo/Dockerfile b/gtest-demo/Dockerfile new file mode 100644 index 0000000..9329c65 --- /dev/null +++ b/gtest-demo/Dockerfile @@ -0,0 +1,19 @@ +# +# Run Google Tests in Docker +# Any executable ending with _tests is automatically found (using find) and run +# + +FROM coenvl/googletest + +ENV BUILD /sandbox/build + +WORKDIR /sandbox + +ADD . /sandbox + +RUN rm -f ${BUILD}/CMakeCache.txt && \ + mkdir -p ${BUILD} && \ + cd ${BUILD} && \ + cmake .. && \ + make && \ + find ${BUILD} -name '*_tests' -exec {} \; \ No newline at end of file diff --git a/gtest-demo/countbits.c b/gtest-demo/countbits.c new file mode 100644 index 0000000..6ccc52d --- /dev/null +++ b/gtest-demo/countbits.c @@ -0,0 +1,20 @@ +/* + * countbits(n) tells how many bits are set in the (unsigned) integer n. + */ + + +#include +#include + +#include "countbits.h" + +int count_bits(unsigned long n) +{ + int number_set=0; + unsigned long number = n; + while (number > 0) { + number_set += (number & 0x1); + number >>= 1; + } + return number_set; +} \ No newline at end of file diff --git a/gtest-demo/countbits.h b/gtest-demo/countbits.h new file mode 100644 index 0000000..4dbb88d --- /dev/null +++ b/gtest-demo/countbits.h @@ -0,0 +1,5 @@ +#ifndef _COUNTBITS_H_ + +extern int count_bits(unsigned long n); + +#endif \ No newline at end of file diff --git a/gtest-demo/countbits.hh b/gtest-demo/countbits.hh new file mode 100644 index 0000000..fbef0f2 --- /dev/null +++ b/gtest-demo/countbits.hh @@ -0,0 +1,16 @@ +// square_root.hh +// This header ensures C linkage is enforced when running C++ unit tessts on C code. + +#include + +#ifdef __cplusplus + +extern "C" { +#include "countbits.h" +} + +#else + +#include "countbits.h" + +#endif \ No newline at end of file diff --git a/gtest-demo/countbits_app.c b/gtest-demo/countbits_app.c new file mode 100644 index 0000000..2505e72 --- /dev/null +++ b/gtest-demo/countbits_app.c @@ -0,0 +1,16 @@ +/* + * countbits(n) tells how many bits are set in the (unsigned) integer n. + */ + + +#include +#include + +#include "countbits.h" + +int main(int argc, char *argv[]) { + for (int i=1; i < argc; i++) { + unsigned long value = atol(argv[i]); + printf("%ld has %d bits set\n", value, count_bits(value)); + } +} \ No newline at end of file diff --git a/gtest-demo/countbits_tests.cc b/gtest-demo/countbits_tests.cc new file mode 100644 index 0000000..f45fc41 --- /dev/null +++ b/gtest-demo/countbits_tests.cc @@ -0,0 +1,34 @@ +/* test cases */ + +#include + +#include "countbits.hh" + +TEST(SquareRootTest, Simple) { + + ASSERT_EQ(4, count_bits(0xF)); + ASSERT_EQ(8, count_bits(0xFF)); + ASSERT_EQ(32, count_bits(0xFFFFFFFF)); +} + +TEST(SquareRootTest, Complex) { + unsigned long values[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; + int bits[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; + + int num_values = sizeof(values) / sizeof(unsigned long); + for (int i=0; i < num_values; i++) { + ASSERT_EQ(bits[i], count_bits(values[i])); + } + + // use individual nibbles (hex digits) to generate a 32-bit value and see if bits add up + unsigned long value = values[0] + (values[3] << 8) + (values[6] << 16) + (values[9] << 24); + unsigned long value_bits = bits[0] + bits[3] + bits[6] + bits[9]; + ASSERT_EQ(value_bits, count_bits(value)); + + +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/gtest-demo/square_root.c b/gtest-demo/square_root.c new file mode 100644 index 0000000..6aa03e2 --- /dev/null +++ b/gtest-demo/square_root.c @@ -0,0 +1,14 @@ +/* module to be tested */ + +#include + +#include "square_root.h" + +double square_root(const double a) { + double b = sqrt(a); + if(b != b) { // nan check + return -1.0; + } else { + return sqrt(a); + } +} \ No newline at end of file diff --git a/gtest-demo/square_root.h b/gtest-demo/square_root.h new file mode 100644 index 0000000..bad90bd --- /dev/null +++ b/gtest-demo/square_root.h @@ -0,0 +1,5 @@ +// square_root.cc + +#include + +extern double square_root(const double a); \ No newline at end of file diff --git a/gtest-demo/square_root.hh b/gtest-demo/square_root.hh new file mode 100644 index 0000000..841ac20 --- /dev/null +++ b/gtest-demo/square_root.hh @@ -0,0 +1,15 @@ +// square_root.hh +// This header ensures C linkage is enforced when running C++ unit tessts on C code. + +#include + +#ifdef __cplusplus +extern "C" { +#include "square_root.h" +} + +#else + +#include "square_root.h" + +#endif \ No newline at end of file diff --git a/gtest-demo/square_root_app.c b/gtest-demo/square_root_app.c new file mode 100644 index 0000000..759d4cd --- /dev/null +++ b/gtest-demo/square_root_app.c @@ -0,0 +1,9 @@ +/* standalone app not requiring tests to run */ + +#include + +#include "square_root.h" + +int main(int argc, char* argv[]) { + printf("sqrt(2) = %.5f\n", square_root(2.0)); +} \ No newline at end of file diff --git a/gtest-demo/square_root_tests.cc b/gtest-demo/square_root_tests.cc new file mode 100644 index 0000000..bef274e --- /dev/null +++ b/gtest-demo/square_root_tests.cc @@ -0,0 +1,22 @@ +/* test cases */ + +#include + +#include "square_root.hh" + +TEST(SquareRootTest, PositiveNos) { + ASSERT_EQ(6, square_root(36.0)); + ASSERT_EQ(18.0, square_root(324.0)); + ASSERT_EQ(25.4, square_root(645.16)); + ASSERT_EQ(0, square_root(0.0)); +} + +TEST(SquareRootTest, NegativeNos) { + ASSERT_EQ(-1.0, square_root(-15.0)); + ASSERT_EQ(-1.0, square_root(-0.2)); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/hello-lib/CMakeLists.txt b/hello-lib/CMakeLists.txt new file mode 100644 index 0000000..191da47 --- /dev/null +++ b/hello-lib/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library (hello-lib hello.c) + +target_include_directories (hello-lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/hello-lib/hello.c b/hello-lib/hello.c new file mode 100644 index 0000000..7299bb0 --- /dev/null +++ b/hello-lib/hello.c @@ -0,0 +1,7 @@ +#include +#include "hello.h" + +void say_hi(char* person) +{ + printf("Hello, %s\n", person); +} \ No newline at end of file diff --git a/hello-lib/hello.h b/hello-lib/hello.h new file mode 100644 index 0000000..c93c05d --- /dev/null +++ b/hello-lib/hello.h @@ -0,0 +1,7 @@ +#ifndef _HELLO_H_ + +#define _HELLO_H_ + +extern void say_hi(char* person); + +#endif diff --git a/hello/CMakeLists.txt b/hello/CMakeLists.txt new file mode 100644 index 0000000..1896a89 --- /dev/null +++ b/hello/CMakeLists.txt @@ -0,0 +1,8 @@ +add_executable (hello-world hello.c) + + + +# Link the executable to the Hello library. Since the Hello library has +# public include directories we will use those link directories when building +# helloDemo +target_link_libraries (hello-world LINK_PUBLIC hello-lib) \ No newline at end of file diff --git a/hello/hello.c b/hello/hello.c new file mode 100644 index 0000000..3b2d9bf --- /dev/null +++ b/hello/hello.c @@ -0,0 +1,6 @@ +#include "hello.h" + +int main(int argc, char** argv) +{ + say_hi("George"); +} \ No newline at end of file diff --git a/lwlog-demo/CMakeLists.txt b/lwlog-demo/CMakeLists.txt new file mode 100644 index 0000000..53aaf2b --- /dev/null +++ b/lwlog-demo/CMakeLists.txt @@ -0,0 +1,8 @@ +add_executable (lwlog-demo lwlog-demo.c) + + + +# Link the executable to the Hello library. Since the Hello library has +# public include directories we will use those link directories when building +# helloDemo +target_link_libraries (lwlog-demo LINK_PUBLIC lwlog-lib) \ No newline at end of file diff --git a/lwlog-demo/lwlog-demo.c b/lwlog-demo/lwlog-demo.c new file mode 100644 index 0000000..d1258f3 --- /dev/null +++ b/lwlog-demo/lwlog-demo.c @@ -0,0 +1,29 @@ +/* + * @file test.c + * + * @author Akagi201 + * @date 2014/11/30 + * + * test program for lwlog.h + */ + +/* Set LOG_LEVEL and LOG_COLOR before including lwlog.h */ + +#define LOG_COLOR (1) // 0: off, 1: on, default: 1 +#define LOG_LEVEL (7) // -1: off, 0~7: different log levels, default: 7 + +#include "lwlog.h" + +int main(void) +{ + lwlog_emerg("This a emerge log."); + lwlog_alert("This a alert log."); + lwlog_crit("This a crit log."); + lwlog_err("This a err log."); + lwlog_warning("This a warning log."); + lwlog_notice("This a notice log."); + lwlog_info("This a info log."); + lwlog_debug("This a debug log."); + + return 0; +} \ No newline at end of file diff --git a/lwlog-lib/CMakeLists.txt b/lwlog-lib/CMakeLists.txt new file mode 100644 index 0000000..c7dd77e --- /dev/null +++ b/lwlog-lib/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library (lwlog-lib lwlog-lib.c) + +target_include_directories (lwlog-lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/lwlog-lib/LICENSE b/lwlog-lib/LICENSE new file mode 100644 index 0000000..a3d5633 --- /dev/null +++ b/lwlog-lib/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Bob Liu + +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. \ No newline at end of file diff --git a/lwlog-lib/README b/lwlog-lib/README new file mode 100644 index 0000000..aded9f8 --- /dev/null +++ b/lwlog-lib/README @@ -0,0 +1,3 @@ +lwlog is a nice (less is more) header-only logging project available at https://github.com/Akagi201/lwlog.git. + +This will replace my own home-rolled versions. Having the color support provides eye candy that students/learners will appreciate! diff --git a/lwlog-lib/lwlog-lib.c b/lwlog-lib/lwlog-lib.c new file mode 100644 index 0000000..3e94347 --- /dev/null +++ b/lwlog-lib/lwlog-lib.c @@ -0,0 +1,28 @@ +/* + * @file test.c + * + * @author Akagi201 + * @date 2014/11/30 + * + * test program for lwlog.h + */ + +/* Set LOG_LEVEL and LOG_COLOR before including lwlog.h */ + +#define LOG_COLOR (1) // 0: off, 1: on, default: 1 +#define LOG_LEVEL (7) // -1: off, 0~7: different log levels, default: 7 + +#include "lwlog.h" + +int lwlog_demo(void) +{ + lwlog_emerg("This a emerge log."); + lwlog_alert("This a alert log."); + lwlog_crit("This a crit log."); + lwlog_err("This a err log."); + lwlog_warning("This a warning log."); + lwlog_notice("This a notice log."); + lwlog_info("This a info log."); + lwlog_debug("This a debug log."); + return 0; +} \ No newline at end of file diff --git a/lwlog-lib/lwlog.h b/lwlog-lib/lwlog.h new file mode 100644 index 0000000..350393c --- /dev/null +++ b/lwlog-lib/lwlog.h @@ -0,0 +1,147 @@ +/* + * @file lwlog.h + * @auther Akagi201 + * + * @date 2014/11/30 + */ + +#ifndef LWLOG_H_ +#define LWLOG_H_ (1) + +#include +#include +#include + +#ifndef LOG_LEVEL +#define LOG_LEVEL (7) +#endif + +#ifndef LOG_COLOR +#define LOG_COLOR (1) +#endif + +// log levels the same as syslog +#define EMERG (0) +#define ALERT (1) +#define CRIT (2) +#define ERR (3) +#define WARNING (4) +#define NOTICE (5) +#define INFO (6) +#define DEBUG (7) + +// colors +#define NONE "\e[0m" +#define BLACK "\e[0;30m" +#define L_BLACK "\e[1;30m" +#define RED "\e[0;31m" +#define L_RED "\e[1;31m" +#define GREEN "\e[0;32m" +#define L_GREEN "\e[1;32m" +#define BROWN "\e[0;33m" +#define YELLOW "\e[1;33m" +#define BLUE "\e[0;34m" +#define L_BLUE "\e[1;34m" +#define PURPLE "\e[0;35m" +#define L_PURPLE "\e[1;35m" +#define CYAN "\e[0;36m" +#define L_CYAN "\e[1;36m" +#define GRAY "\e[0;37m" +#define WHITE "\e[1;37m" + +#define BOLD "\e[1m" +#define UNDERLINE "\e[4m" +#define BLINK "\e[5m" +#define REVERSE "\e[7m" +#define HIDE "\e[8m" +#define CLEAR "\e[2J" +#define CLRLINE "\r\e[K" //or "\e[1K\r" + +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) + +/* safe readable version of errno */ +#define clean_errno() (errno == 0 ? "None" : strerror(errno)) + +#define lwlog_emerg(M, ...) do { fprintf(stderr, RED "[EMERG] " "%s (%s:%d) " NONE M YELLOW " errno: %s\n" NONE, __func__, __FILE__, __LINE__, ##__VA_ARGS__, clean_errno()); } while(0) +#define lwlog_alert(M, ...) do { fprintf(stderr, PURPLE "[ALERT] " "%s (%s:%d) " NONE M YELLOW " errno: %s\n" NONE, __func__, __FILE__, __LINE__, ##__VA_ARGS__, clean_errno()); } while(0) +#define lwlog_crit(M, ...) do { fprintf(stderr, YELLOW "[CRIT] " "%s (%s:%d) " NONE M YELLOW " errno: %s\n" NONE, __func__, __FILE__, __LINE__, ##__VA_ARGS__, clean_errno()); } while(0) +#define lwlog_err(M, ...) do { fprintf(stderr, BROWN "[ERR] " "%s (%s:%d) " NONE M YELLOW " errno: %s\n" NONE, __func__, __FILE__, __LINE__, ##__VA_ARGS__, clean_errno()); } while(0) +#define lwlog_warning(M, ...) do { fprintf(stderr, BLUE "[WARNING] " "%s (%s:%d) " NONE M YELLOW " errno: %s\n" NONE, __func__, __FILE__, __LINE__, ##__VA_ARGS__, clean_errno()); } while(0) +#define lwlog_notice(M, ...) do { fprintf(stderr, CYAN "[NOTICE] " "%s (%s:%d) " NONE M YELLOW " errno: %s\n" NONE, __func__, __FILE__, __LINE__, ##__VA_ARGS__, clean_errno()); } while(0) +#define lwlog_info(M, ...) do { fprintf(stderr, GREEN "[INFO] " "%s (%s:%d) " NONE M "\n", __func__, __FILE__, __LINE__, ##__VA_ARGS__); } while(0) +#define lwlog_debug(M, ...) do { fprintf(stderr, GRAY "[DEBUG] " "%s (%s:%d) " NONE M "\n", __func__, __FILE__, __LINE__, ##__VA_ARGS__); } while(0) + +/* LOG_LEVEL controls */ +#if LOG_LEVEL < DEBUG +#undef lwlog_debug +#define lwlog_debug(M, ...) do{}while(0) +#endif + +#if LOG_LEVEL < INFO +#undef lwlog_info +#define lwlog_info(M, ...) do{}while(0) +#endif + +#if LOG_LEVEL < NOTICE +#undef lwlog_notice +#define lwlog_notice(M, ...) do{}while(0) +#endif + +#if LOG_LEVEL < WARNING +#undef lwlog_warning +#define lwlog_warning(M, ...) do{}while(0) +#endif + +#if LOG_LEVEL < ERR +#undef lwlog_err +#define lwlog_err(M, ...) do{}while(0) +#endif + +#if LOG_LEVEL < CRIT +#undef lwlog_crit +#define lwlog_crit(M, ...) do{}while(0) +#endif + +#if LOG_LEVEL < ALERT +#undef lwlog_alert +#define lwlog_alert(M, ...) do{}while(0) +#endif + +#if LOG_LEVEL < EMERG +#undef lwlog_emerg +#define lwlog_emerg(M, ...) do{}while(0) +#endif + +/* LOG_COLOR controls */ +#if LOG_COLOR < 1 + +#undef NONE +#define NONE + +#undef RED +#define RED + +#undef PURPLE +#define PURPLE + +#undef YELLOW +#define YELLOW + +#undef BROWN +#define BROWN + +#undef GREEN +#define GREEN + +#undef CYAN +#define CYAN + +#undef BLUE +#define BLUE + +#undef GRAY +#define GRAY + +#endif + +#endif // LWLOG_H_ \ No newline at end of file