initial project setup
This commit is contained in:
parent
dafd1ae93e
commit
a650630f81
66
.clang-format
Normal file
66
.clang-format
Normal file
@ -0,0 +1,66 @@
|
||||
# Generated from CLion C/C++ Code Style settings
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: AcrossComments
|
||||
AlignOperands: true
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 80
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 8
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 0
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
29
.drone.yml
Normal file
29
.drone.yml
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: main
|
||||
|
||||
steps:
|
||||
- name: Tag commit
|
||||
image: alpine
|
||||
commands:
|
||||
- echo This would create a tag
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- main
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: develop
|
||||
|
||||
steps:
|
||||
- name: Tag commit
|
||||
image: kitware/cmake
|
||||
commands:
|
||||
- cmake -DCMAKE_BUILD_TYPE=Debug .
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- main
|
||||
...
|
||||
27
CMakeLists.txt
Normal file
27
CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/project-meta-info.in")
|
||||
|
||||
project(waitui-project
|
||||
VERSION ${project_version}
|
||||
DESCRIPTION ${project_description}
|
||||
HOMEPAGE_URL ${project_homepage}
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(CMAKE_C_STANDARD 17)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
include(CTest)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(app)
|
||||
add_subdirectory(library/log)
|
||||
|
||||
if ((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MODERN_CMAKE_BUILD_TESTING)
|
||||
AND BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif ()
|
||||
@ -1,2 +1,3 @@
|
||||
# waitui
|
||||
|
||||
[](https://drone.riba-interactive.de/rick/waitui)
|
||||
50
app/CMakeLists.txt
Normal file
50
app/CMakeLists.txt
Normal file
@ -0,0 +1,50 @@
|
||||
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
|
||||
|
||||
include("project-meta-info.in")
|
||||
|
||||
project(waitui
|
||||
VERSION ${project_version}
|
||||
DESCRIPTION ${project_description}
|
||||
HOMEPAGE_URL ${project_homepage}
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
add_executable(waitui)
|
||||
|
||||
target_sources(waitui
|
||||
PRIVATE
|
||||
"src/main.c"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/waitui/version.h"
|
||||
)
|
||||
|
||||
target_include_directories(waitui PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
|
||||
target_link_libraries(waitui PRIVATE log)
|
||||
|
||||
find_package(Git)
|
||||
if (GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
include(GetGitRevisionDescription)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD OUTPUT_VARIABLE SHORT_SHA OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
set(REVISION ${SHORT_SHA} CACHE STRING "git short sha" FORCE)
|
||||
|
||||
# only use the plugin to tie the configure state to the sha to force rebuilds
|
||||
# of files that depend on version.h
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(REFSPEC COMMITHASH)
|
||||
else ()
|
||||
message(WARNING "Git not found, cannot set version info")
|
||||
set(REVISION "unknown")
|
||||
endif ()
|
||||
|
||||
if (NOT project_prerelease STREQUAL "")
|
||||
set(WAITUI_VERSION_IS_PRERELEASE ON)
|
||||
endif ()
|
||||
|
||||
math(EXPR PROJECT_VERSION_LONG "${PROJECT_VERSION_MAJOR} * 10000 + ${PROJECT_VERSION_MINOR} * 100 + ${PROJECT_VERSION_PATCH}")
|
||||
|
||||
configure_file(
|
||||
"include/waitui/version.h.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/waitui/version.h"
|
||||
@ONLY
|
||||
)
|
||||
36
app/include/waitui/version.h.in
Normal file
36
app/include/waitui/version.h.in
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file version.h
|
||||
* @author rick
|
||||
* @date 30.07.20
|
||||
* @brief File for the Version implementation
|
||||
*/
|
||||
|
||||
#ifndef WAITUI_VERSION_H
|
||||
#define WAITUI_VERSION_H
|
||||
|
||||
#define WAITUI_VERSION_NAME "@PROJECT_NAME@"
|
||||
|
||||
#define WAITUI_VERSION_MAJOR "@PROJECT_VERSION_MAJOR@"
|
||||
#define WAITUI_VERSION_MINOR "@PROJECT_VERSION_MINOR@"
|
||||
#define WAITUI_VERSION_PATCH "@PROJECT_VERSION_PATCH@"
|
||||
|
||||
#define WAITUI_VERSION_PRERELEASE "@PROJECT_PRERELEASE@"
|
||||
|
||||
#define WAITUI_VERSION_REVISION "@REVISION@"
|
||||
|
||||
#cmakedefine WAITUI_VERSION_IS_PRERELEASE
|
||||
|
||||
#ifdef WAITUI_VERSION_IS_PRERELEASE
|
||||
#define WAITUI_VERSION_STRING \
|
||||
WAITUI_VERSION_MAJOR "." WAITUI_VERSION_MINOR "." WAITUI_VERSION_PATCH \
|
||||
"-" WAITUI_VERSION_PRERELEASE \
|
||||
"+" WAITUI_VERSION_REVISION
|
||||
#else
|
||||
#define WAITUI_VERSION_STRING \
|
||||
WAITUI_VERSION_MAJOR "." WAITUI_VERSION_MINOR "." WAITUI_VERSION_PATCH \
|
||||
"+" WAITUI_VERSION_REVISION
|
||||
#endif
|
||||
|
||||
#define WAITUI_VERSION_LONG @PROJECT_VERSION_LONG@L
|
||||
|
||||
#endif //WAITUI_VERSION_H
|
||||
4
app/project-meta-info.in
Normal file
4
app/project-meta-info.in
Normal file
@ -0,0 +1,4 @@
|
||||
set(project_version 0.0.1)
|
||||
set(project_description "waitui executable")
|
||||
set(project_homepage "http://example.com")
|
||||
set(project_prerelease "")
|
||||
163
app/src/main.c
Normal file
163
app/src/main.c
Normal file
@ -0,0 +1,163 @@
|
||||
#include "waitui/version.h"
|
||||
|
||||
#include <waitui/log.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Local defines
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define WAITUI_SUCCESS 0
|
||||
#define WAITUI_FAILURE 1
|
||||
#define WAITUI_MEMORY_ERROR 2
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Local variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// clang-format off
|
||||
static const char * waitui_shortOptions = "vhqd::";
|
||||
static const struct option waitui_longOptions[] = {
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"quiet", no_argument, 0, 'q'},
|
||||
{"debug", optional_argument, 0,'d'},
|
||||
0
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// clang-format off
|
||||
#define waitui_printLogo(s) \
|
||||
do { \
|
||||
fprintf((s), "\n"); \
|
||||
fprintf((s), "\n"); \
|
||||
fprintf((s), " ___ __ \n"); \
|
||||
fprintf((s), " (_ ( . ) )__ -.- '. \\ : / .' \n"); \
|
||||
fprintf((s), " '(___(_____) -.- '. \\ : / .' \n"); \
|
||||
fprintf((s), " '. \\ : / .' \n"); \
|
||||
fprintf((s), " __ -----____ _ _____----- \n"); \
|
||||
fprintf((s), "_________________/. _\\________________________________(_)______________________\n"); \
|
||||
fprintf((s), " .--.|/_/__ \n"); \
|
||||
fprintf((s), " ''.--o/___ \\ ~ ~ ,-----------------------, \n"); \
|
||||
fprintf((s), " ~ /.'o|_o '.| ~ | | \n"); \
|
||||
fprintf((s), " |/ |_| ~ | Waitui | \n"); \
|
||||
fprintf((s), " ~ ' |_| ~ | by Rick | \n"); \
|
||||
fprintf((s), " __|_|-;.___.;--.,___ | | \n"); \
|
||||
fprintf((s), " ~ _,,-\"\" |_| \"\"-,,_ `------------------------' \n"); \
|
||||
fprintf((s), " .-'´'´ |_| ``-. ~ \n"); \
|
||||
fprintf((s), " \", |_| ,\" ~ \n"); \
|
||||
fprintf((s), " \"-_ _-\" ~ \n"); \
|
||||
fprintf((s), " ~ ``----..,_ , __,,..---'´ ~ ~ \n"); \
|
||||
fprintf((s), " ```'''''' ~ ~ \n"); \
|
||||
} \
|
||||
while (0)
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* @brief Print version.
|
||||
* @param[in] stream Where the version should be printed
|
||||
* @param logo Whether to print the logo
|
||||
*/
|
||||
void waitui_printVersion(FILE *stream, int logo) {
|
||||
fprintf(stream, "%s version %s", WAITUI_VERSION_NAME,
|
||||
WAITUI_VERSION_STRING);
|
||||
|
||||
if (logo) { waitui_printLogo(stream); }
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print help.
|
||||
* @param[in] stream Where the help should be printed
|
||||
*/
|
||||
void waitui_printHelp(FILE *stream) {
|
||||
waitui_printVersion(stream, 0);
|
||||
|
||||
fprintf(stream, "\n\n");
|
||||
fprintf(stream, "Usage: %s[-hvq] [-d level]\n", WAITUI_VERSION_NAME);
|
||||
fprintf(stream, "\t--help, -h \t\tDisplays this help\n");
|
||||
fprintf(stream, "\t--version, -v \t\tDisplays the version\n");
|
||||
fprintf(stream, "\t--quiet, -q \t\tDisplays the version\n");
|
||||
fprintf(stream, "\t--debug=level, -d level\t\tDisplays the version\n");
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Main function
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int result = WAITUI_SUCCESS;
|
||||
|
||||
bool quite = false;
|
||||
long loglevel = WAITUI_LOG_DEBUG;
|
||||
|
||||
waitui_log_setQuiet(quite);
|
||||
waitui_log_setLevel(loglevel);
|
||||
|
||||
while (1) {
|
||||
int index = -1;
|
||||
struct option *opt = NULL;
|
||||
|
||||
int optRes = getopt_long(argc, argv, waitui_shortOptions,
|
||||
waitui_longOptions, &index);
|
||||
if (optRes == -1) break; /* end of list */
|
||||
switch (optRes) {
|
||||
case 'v':
|
||||
waitui_printVersion(stdout, 1);
|
||||
return WAITUI_SUCCESS;
|
||||
case 'h':
|
||||
waitui_printHelp(stdout);
|
||||
return WAITUI_SUCCESS;
|
||||
case 'q':
|
||||
quite = true;
|
||||
break;
|
||||
case 'd':
|
||||
if (optarg) {
|
||||
char *endPtr = NULL;
|
||||
errno = 0;
|
||||
loglevel = strtol(optarg, &endPtr, 10);
|
||||
if (errno != 0 || endPtr == optarg ||
|
||||
loglevel < WAITUI_LOG_TRACE ||
|
||||
loglevel >= WAITUI_LOG_MAX) {
|
||||
waitui_log_warn(
|
||||
"no valid log level given or out of range "
|
||||
"(%d - %d): %s",
|
||||
WAITUI_LOG_TRACE, WAITUI_LOG_MAX - 1, optarg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
/* all parameter that do not appear in the option string */
|
||||
opt = (struct option *) &(waitui_longOptions[index]);
|
||||
printf("'%s' was specified.", opt->name);
|
||||
if (opt->has_arg == required_argument)
|
||||
printf("Arg: <%s>", optarg);
|
||||
printf("\n");
|
||||
break;
|
||||
default: /* unknown */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* print all others parameters */
|
||||
while (optind < argc) { printf("other parameter: <%s>\n", argv[optind++]); }
|
||||
|
||||
waitui_log_setQuiet(quite);
|
||||
waitui_log_setLevel(loglevel);
|
||||
|
||||
waitui_log_debug("waitui start execution");
|
||||
|
||||
waitui_log_debug("waitui execution done");
|
||||
|
||||
return result;
|
||||
}
|
||||
35
cmake/FetchCMocka.cmake
Normal file
35
cmake/FetchCMocka.cmake
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright 2020 OLIVIER LE DOEUFF
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
# and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all copies or
|
||||
# substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
# THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
cmocka
|
||||
GIT_REPOSITORY https://git.cryptomilk.org/projects/cmocka.git
|
||||
GIT_TAG cmocka-1.1.5
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
|
||||
set(WITH_STATIC_LIB ON CACHE BOOL "CMocka: Build with a static library" FORCE)
|
||||
set(WITH_CMOCKERY_SUPPORT OFF CACHE BOOL "CMocka: Install a cmockery header" FORCE)
|
||||
set(WITH_EXAMPLES OFF CACHE BOOL "CMocka: Build examples" FORCE)
|
||||
set(UNIT_TESTING OFF CACHE BOOL "CMocka: Build with unit testing" FORCE)
|
||||
set(PICKY_DEVELOPER OFF CACHE BOOL "CMocka: Build with picky developer flags" FORCE)
|
||||
|
||||
FetchContent_MakeAvailable(cmocka)
|
||||
274
cmake/GetGitRevisionDescription.cmake
Normal file
274
cmake/GetGitRevisionDescription.cmake
Normal file
@ -0,0 +1,274 @@
|
||||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the working tree (--dirty option),
|
||||
# and adjusting the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# git_local_changes(<var>)
|
||||
#
|
||||
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||
# Does not regard untracked files.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
#
|
||||
# Copyright 2009-2013, Iowa State University.
|
||||
# Copyright 2013-2020, Ryan Pavlik
|
||||
# Copyright 2013-2020, Contributors
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
# Function _git_find_closest_git_dir finds the next closest .git directory
|
||||
# that is part of any directory in the path defined by _start_dir.
|
||||
# The result is returned in the parent scope variable whose name is passed
|
||||
# as variable _git_dir_var. If no .git directory can be found, the
|
||||
# function returns an empty string via _git_dir_var.
|
||||
#
|
||||
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
||||
# neither foo nor bar contain a file/directory .git. This wil return
|
||||
# C:/bla/.git
|
||||
#
|
||||
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||
set(cur_dir "${_start_dir}")
|
||||
set(git_dir "${_start_dir}/.git")
|
||||
while(NOT EXISTS "${git_dir}")
|
||||
# .git dir not found, search parent directories
|
||||
set(git_previous_parent "${cur_dir}")
|
||||
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
|
||||
if(cur_dir STREQUAL git_previous_parent)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_git_dir_var}
|
||||
""
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(git_dir "${cur_dir}/.git")
|
||||
endwhile()
|
||||
set(${_git_dir_var}
|
||||
"${git_dir}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
|
||||
|
||||
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
|
||||
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
|
||||
else()
|
||||
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
|
||||
endif()
|
||||
if(NOT "${GIT_DIR}" STREQUAL "")
|
||||
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
|
||||
"${GIT_DIR}")
|
||||
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
|
||||
# We've gone above the CMake root dir.
|
||||
set(GIT_DIR "")
|
||||
endif()
|
||||
endif()
|
||||
if("${GIT_DIR}" STREQUAL "")
|
||||
set(${_refspecvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
set(${_hashvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Check if the current source dir is a git submodule or a worktree.
|
||||
# In both cases .git is a file instead of a directory.
|
||||
#
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
# The following git command will return a non empty string that
|
||||
# points to the super project working tree if the current
|
||||
# source dir is inside a git submodule.
|
||||
# Otherwise the command will return an empty string.
|
||||
#
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" rev-parse
|
||||
--show-superproject-working-tree
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT "${out}" STREQUAL "")
|
||||
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
|
||||
${submodule})
|
||||
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
|
||||
ABSOLUTE)
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
else()
|
||||
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
|
||||
file(READ ${GIT_DIR} worktree_ref)
|
||||
# The .git directory contains a path to the worktree information directory
|
||||
# inside the parent git repo of the worktree.
|
||||
#
|
||||
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
|
||||
${worktree_ref})
|
||||
string(STRIP ${git_worktree_dir} git_worktree_dir)
|
||||
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
|
||||
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
|
||||
endif()
|
||||
else()
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake" @ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar}
|
||||
"${HEAD_REF}"
|
||||
PARENT_SCOPE)
|
||||
set(${_hashvar}
|
||||
"${HEAD_HASH}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe_working_tree _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_local_changes _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(res EQUAL 0)
|
||||
set(${_var}
|
||||
"CLEAN"
|
||||
PARENT_SCOPE)
|
||||
else()
|
||||
set(${_var}
|
||||
"DIRTY"
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
43
cmake/GetGitRevisionDescription.cmake.in
Normal file
43
cmake/GetGitRevisionDescription.cmake.in
Normal file
@ -0,0 +1,43 @@
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright 2009-2012, Iowa State University
|
||||
# Copyright 2011-2015, Contributors
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
22
library/log/CMakeLists.txt
Normal file
22
library/log/CMakeLists.txt
Normal file
@ -0,0 +1,22 @@
|
||||
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
|
||||
|
||||
include("project-meta-info.in")
|
||||
|
||||
project(waitui-log
|
||||
VERSION ${project_version}
|
||||
DESCRIPTION ${project_description}
|
||||
HOMEPAGE_URL ${project_homepage}
|
||||
LANGUAGES C)
|
||||
|
||||
add_library(log OBJECT)
|
||||
|
||||
target_sources(log
|
||||
PRIVATE
|
||||
"src/log.c"
|
||||
PUBLIC
|
||||
"include/waitui/log.h"
|
||||
)
|
||||
|
||||
target_include_directories(log PUBLIC "include")
|
||||
|
||||
target_compile_definitions(log PUBLIC "LOG_USE_COLOR")
|
||||
130
library/log/include/waitui/log.h
Normal file
130
library/log/include/waitui/log.h
Normal file
@ -0,0 +1,130 @@
|
||||
/**
|
||||
* @file log.h
|
||||
* @author rick
|
||||
* @date 28.08.20
|
||||
* @brief File for the Log implementation
|
||||
*/
|
||||
|
||||
#ifndef WAITUI_LOG_H
|
||||
#define WAITUI_LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief The type for log events.
|
||||
*/
|
||||
typedef struct waitui_log_event {
|
||||
va_list ap;
|
||||
const char *format;
|
||||
const char *file;
|
||||
int line;
|
||||
struct tm *time;
|
||||
int level;
|
||||
void *userData;
|
||||
} waitui_log_event;
|
||||
|
||||
/**
|
||||
* @brief The logging callback function type.
|
||||
*/
|
||||
typedef void (*waitui_log_logging_fn)(waitui_log_event *event);
|
||||
|
||||
/**
|
||||
* @brief The locking callback function type.
|
||||
*/
|
||||
typedef void (*waitui_log_lock_fn)(bool lock, void *userData);
|
||||
|
||||
/**
|
||||
* @brief The different log levels.
|
||||
*/
|
||||
typedef enum {
|
||||
WAITUI_LOG_TRACE,
|
||||
WAITUI_LOG_DEBUG,
|
||||
WAITUI_LOG_INFO,
|
||||
WAITUI_LOG_WARN,
|
||||
WAITUI_LOG_ERROR,
|
||||
WAITUI_LOG_FATAL,
|
||||
WAITUI_LOG_MAX,
|
||||
} waitui_log_level;
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Public defines
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define waitui_log_trace(...) \
|
||||
waitui_log_writeLog(WAITUI_LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define waitui_log_debug(...) \
|
||||
waitui_log_writeLog(WAITUI_LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define waitui_log_info(...) \
|
||||
waitui_log_writeLog(WAITUI_LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define waitui_log_warn(...) \
|
||||
waitui_log_writeLog(WAITUI_LOG_WARN, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define waitui_log_error(...) \
|
||||
waitui_log_writeLog(WAITUI_LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define waitui_log_fatal(...) \
|
||||
waitui_log_writeLog(WAITUI_LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Set locking function for log.
|
||||
* @param lockFn The function to be called for lock and unlock when writing logs
|
||||
* @param[in] userData Extra user data to pass to the locking function
|
||||
*/
|
||||
extern void waitui_log_set_lock(waitui_log_lock_fn lockFn, void *userData);
|
||||
|
||||
/**
|
||||
* @brief Set minimum log level to log on stderr.
|
||||
* @param level The minimum log level from which on log appear on stderr
|
||||
*/
|
||||
extern void waitui_log_setLevel(waitui_log_level level);
|
||||
|
||||
/**
|
||||
* @brief Disable or enable logging to stderr.
|
||||
* @param enable True to disable logging to stderr, false to enable
|
||||
*/
|
||||
extern void waitui_log_setQuiet(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Add the logFn as a log callback to write logs starting at the level.
|
||||
* @param logFn The function to add as a log callback
|
||||
* @param[in] userData Extra user data to pass to the logFn
|
||||
* @param level The level from which on this log callback is executed
|
||||
* @retval 1 Successful added the callback
|
||||
* @retval 0 No more space to add the callback
|
||||
*/
|
||||
extern int waitui_log_addCallback(waitui_log_logging_fn logFn, void *userData,
|
||||
waitui_log_level level);
|
||||
|
||||
/**
|
||||
* @brief Add a log callback to write logs starting at the level into the file.
|
||||
* @param[in] file The file into which to write the log
|
||||
* @param level The level from which on this log callback is executed
|
||||
* @retval 1 Successful added the file callback
|
||||
* @retval 0 No more space to add the callback
|
||||
*/
|
||||
extern int waitui_log_addFile(FILE *file, waitui_log_level level);
|
||||
|
||||
/**
|
||||
* @brief Write the log message to log with the given parameters.
|
||||
* @param level The log level for this message
|
||||
* @param[in] file The filename where this log is written
|
||||
* @param line The line number where this log is written
|
||||
* @param[in] format The message to write to the log
|
||||
* @param ... Extra values to be used inside the message
|
||||
*/
|
||||
extern void waitui_log_writeLog(waitui_log_level level, const char *file,
|
||||
int line, const char *format, ...);
|
||||
|
||||
#endif//WAITUI_LOG_H
|
||||
3
library/log/project-meta-info.in
Normal file
3
library/log/project-meta-info.in
Normal file
@ -0,0 +1,3 @@
|
||||
set(project_version 0.0.1)
|
||||
set(project_description "waitui waitui_log library")
|
||||
set(project_homepage "http://example.com")
|
||||
224
library/log/src/log.c
Normal file
224
library/log/src/log.c
Normal file
@ -0,0 +1,224 @@
|
||||
/**
|
||||
* @file log.c
|
||||
* @author rick
|
||||
* @date 28.08.20
|
||||
* @brief File for the Log implementation
|
||||
*/
|
||||
|
||||
#include "waitui/log.h"
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Local defines
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief The maximum number of possible callbacks to register.
|
||||
*/
|
||||
#define MAX_CALLBACKS 32
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Local types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Internal type to store the log callback function with all its info.
|
||||
*/
|
||||
typedef struct waitui_log_callback {
|
||||
waitui_log_logging_fn logFn;
|
||||
waitui_log_level level;
|
||||
void *userData;
|
||||
} waitui_log_callback;
|
||||
|
||||
/**
|
||||
* @brief Internal type to store the log with all its info.
|
||||
*/
|
||||
typedef struct waitui_log {
|
||||
waitui_log_lock_fn lockFn;
|
||||
waitui_log_level level;
|
||||
bool quiet;
|
||||
waitui_log_callback callbacks[MAX_CALLBACKS];
|
||||
void *userData;
|
||||
} log;
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Local variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief The internal state of the log lib.
|
||||
*/
|
||||
static struct waitui_log L;
|
||||
|
||||
/**
|
||||
* @brief String representations of the log levels.
|
||||
*/
|
||||
static const char *waitui_log_level_strings[] = {
|
||||
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL",
|
||||
};
|
||||
|
||||
#ifdef LOG_USE_COLOR
|
||||
/**
|
||||
* @brief Color representations of the log levels.
|
||||
*/
|
||||
static const char *waitui_log_level_colors[] = {
|
||||
"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m",
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Return the string representations of the log level.
|
||||
* @param level The level to return as a string.
|
||||
* @return The string representations of the log level or empty when out of bounds.
|
||||
*/
|
||||
static inline const char *waitui_log_levelAsString(waitui_log_level level) {
|
||||
if (level < WAITUI_LOG_TRACE || level >= WAITUI_LOG_MAX) { return ""; }
|
||||
return waitui_log_level_strings[level];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the color representations of the log level.
|
||||
* @param level The level to return as a color.
|
||||
* @return The color representations of the log level or empty when out of bounds.
|
||||
*/
|
||||
static inline const char *waitui_log_levelAsColor(waitui_log_level level) {
|
||||
if (level < WAITUI_LOG_TRACE || level >= WAITUI_LOG_MAX) { return ""; }
|
||||
return waitui_log_level_colors[level];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calls the locking callback function to get the lock.
|
||||
*/
|
||||
static inline void waitui_log_lock(void) {
|
||||
if (L.lockFn) { L.lockFn(true, L.userData); }
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calls the locking callback function to release the lock.
|
||||
*/
|
||||
static inline void waitui_log_unlock(void) {
|
||||
if (L.lockFn) { L.lockFn(false, L.userData); }
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback that write the log event to the console.
|
||||
* @param[in] event log event to write to the console
|
||||
*/
|
||||
static void waitui_log_console_callback(waitui_log_event *event) {
|
||||
char buffer[16];
|
||||
buffer[strftime(buffer, sizeof(buffer), "%H:%M:%S", event->time)] = '\0';
|
||||
|
||||
#ifdef LOG_USE_COLOR
|
||||
fprintf(event->userData, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", buffer,
|
||||
waitui_log_levelAsColor(event->level),
|
||||
waitui_log_levelAsString(event->level), event->file, event->line);
|
||||
#else
|
||||
fprintf(event->userData, "%s %-5s %s:%d: ", buffer,
|
||||
waitui_log_levelAsString(event->level), event->file, event->line);
|
||||
#endif
|
||||
|
||||
vfprintf(event->userData, event->format, event->ap);
|
||||
fprintf(event->userData, "\n");
|
||||
fflush(event->userData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback that write the log event to a file.
|
||||
* @param[in] event log event to write to a file
|
||||
*/
|
||||
static void waitui_log_file_callback(waitui_log_event *event) {
|
||||
char buffer[64];
|
||||
buffer[strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", event->time)] =
|
||||
'\0';
|
||||
|
||||
fprintf(event->userData, "%s %-5s %s:%d: ", buffer,
|
||||
waitui_log_levelAsString(event->level), event->file, event->line);
|
||||
|
||||
vfprintf(event->userData, event->format, event->ap);
|
||||
fprintf(event->userData, "\n");
|
||||
fflush(event->userData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the log event with time and userdata.
|
||||
* @param[in,out] event log event to write to initialize
|
||||
* @param[in] user_data user data to set for the log event
|
||||
*/
|
||||
static inline void waitui_log_init_event(waitui_log_event *event,
|
||||
void *userData) {
|
||||
if (!event->time) {
|
||||
time_t t = time(NULL);
|
||||
event->time = localtime(&t);
|
||||
}
|
||||
|
||||
event->userData = userData;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void waitui_log_set_lock(waitui_log_lock_fn lockFn, void *userData) {
|
||||
L.lockFn = lockFn;
|
||||
L.userData = userData;
|
||||
}
|
||||
|
||||
void waitui_log_setLevel(waitui_log_level level) { L.level = level; }
|
||||
|
||||
void waitui_log_setQuiet(bool enable) { L.quiet = enable; }
|
||||
|
||||
int waitui_log_addCallback(waitui_log_logging_fn logFn, void *userData,
|
||||
waitui_log_level level) {
|
||||
for (int i = 0; i < MAX_CALLBACKS; ++i) {
|
||||
if (!L.callbacks[i].logFn) {
|
||||
L.callbacks[i] = (waitui_log_callback){.logFn = logFn,
|
||||
.userData = userData,
|
||||
.level = level};
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int waitui_log_addFile(FILE *file, waitui_log_level level) {
|
||||
return waitui_log_addCallback(waitui_log_file_callback, file, level);
|
||||
}
|
||||
|
||||
void waitui_log_writeLog(waitui_log_level level, const char *file, int line,
|
||||
const char *format, ...) {
|
||||
waitui_log_event event = {
|
||||
.format = format,
|
||||
.file = file,
|
||||
.line = line,
|
||||
.level = level,
|
||||
};
|
||||
|
||||
waitui_log_lock();
|
||||
|
||||
if (!L.quiet && level >= L.level) {
|
||||
waitui_log_init_event(&event, stderr);
|
||||
va_start(event.ap, format);
|
||||
waitui_log_console_callback(&event);
|
||||
va_end(event.ap);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].logFn; ++i) {
|
||||
waitui_log_callback *cb = &L.callbacks[i];
|
||||
if (level >= cb->level) {
|
||||
waitui_log_init_event(&event, cb->userData);
|
||||
va_start(event.ap, format);
|
||||
cb->logFn(&event);
|
||||
va_end(event.ap);
|
||||
}
|
||||
}
|
||||
|
||||
waitui_log_unlock();
|
||||
}
|
||||
3
project-meta-info.in
Normal file
3
project-meta-info.in
Normal file
@ -0,0 +1,3 @@
|
||||
set(project_version 0.0.1)
|
||||
set(project_description "waitui language system")
|
||||
set(project_homepage "http://example.com")
|
||||
3
tests/CMakeLists.txt
Normal file
3
tests/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
include(../cmake/FetchCMocka.cmake)
|
||||
|
||||
#add_subdirectory()
|
||||
Loading…
Reference in New Issue
Block a user