[glibutil] Initial commit
This commit is contained in:
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
*~
|
||||
debian/files
|
||||
debian/libglibutil-dev.debhelper.log
|
||||
debian/libglibutil-dev.substvars
|
||||
debian/libglibutil-dev
|
||||
debian/libglibutil.debhelper.log
|
||||
debian/libglibutil.postinst.debhelper
|
||||
debian/libglibutil.postrm.debhelper
|
||||
debian/libglibutil.substvars
|
||||
debian/libglibutil
|
||||
debian/tmp
|
||||
documentation.list
|
||||
installroot
|
||||
build
|
||||
RPMS
|
||||
190
Makefile
Normal file
190
Makefile
Normal file
@@ -0,0 +1,190 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: clean all debug release
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release pkgconfig
|
||||
|
||||
#
|
||||
# Library version
|
||||
#
|
||||
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 0
|
||||
VERSION_RELEASE = 0
|
||||
|
||||
NAME = glibutil
|
||||
LIB_NAME = lib$(NAME)
|
||||
LIB_DEV_SYMLINK = $(LIB_NAME).so
|
||||
LIB_SYMLINK1 = $(LIB_DEV_SYMLINK).$(VERSION_MAJOR)
|
||||
LIB_SYMLINK2 = $(LIB_SYMLINK1).$(VERSION_MINOR)
|
||||
LIB_SONAME = $(LIB_SYMLINK1)
|
||||
LIB = $(LIB_SONAME).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = gutil_log.c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = src
|
||||
INCLUDE_DIR = include
|
||||
BUILD_DIR = build
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(INCLUDE_DIR)
|
||||
BASE_FLAGS = -fPIC
|
||||
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
|
||||
-MMD -MP $(shell pkg-config --cflags $(PKGS))
|
||||
FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \
|
||||
$(shell pkg-config --libs $(PKGS))
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
PKGCONFIG = $(BUILD_DIR)/$(LIB_NAME).pc
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS) $(DEBUG_LIB): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS) $(RELEASE_LIB): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB)
|
||||
RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB)
|
||||
DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1)
|
||||
RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1)
|
||||
|
||||
debug: $(DEBUG_LIB) $(DEBUG_LINK)
|
||||
|
||||
release: $(RELEASE_LIB) $(RELEASE_LINK)
|
||||
|
||||
pkgconfig: $(PKGCONFIG)
|
||||
|
||||
clean:
|
||||
rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~
|
||||
rm -fr $(BUILD_DIR) RPMS installroot
|
||||
rm -fr debian/tmp debian/libglibutil debian/libglibutil-dev
|
||||
rm -f documentation.list debian/files debian/*.substvars
|
||||
rm -f debian/*.debhelper.log debian/*.debhelper debian/*~
|
||||
|
||||
$(GEN_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_LIB): $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) -o $@
|
||||
|
||||
$(RELEASE_LIB): $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
$(DEBUG_LINK):
|
||||
ln -sf $(LIB) $@
|
||||
|
||||
$(RELEASE_LINK):
|
||||
ln -sf $(LIB) $@
|
||||
|
||||
$(PKGCONFIG): $(LIB_NAME).pc.in
|
||||
sed -e 's/\[version\]/'$(VERSION_MAJOR).$(VERSION_MINOR)/g $< > $@
|
||||
|
||||
#
|
||||
# Install
|
||||
#
|
||||
|
||||
INSTALL_PERM = 644
|
||||
INSTALL_OWNER = $(shell id -u)
|
||||
INSTALL_GROUP = $(shell id -g)
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_DIRS = $(INSTALL) -d
|
||||
INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM)
|
||||
|
||||
INSTALL_LIB_DIR = $(DESTDIR)/usr/lib
|
||||
INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/$(NAME)
|
||||
INSTALL_PKGCONFIG_DIR = $(DESTDIR)/usr/lib/pkgconfig
|
||||
|
||||
INSTALL_ALIAS = $(INSTALL_LIB_DIR)/$(LIB_SHORTCUT)
|
||||
|
||||
install: $(INSTALL_LIB_DIR)
|
||||
$(INSTALL_FILES) $(RELEASE_LIB) $(INSTALL_LIB_DIR)
|
||||
ln -sf $(LIB) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2)
|
||||
ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1)
|
||||
|
||||
install-dev: install $(INSTALL_INCLUDE_DIR) $(INSTALL_PKGCONFIG_DIR)
|
||||
$(INSTALL_FILES) $(INCLUDE_DIR)/*.h $(INSTALL_INCLUDE_DIR)
|
||||
$(INSTALL_FILES) $(PKGCONFIG) $(INSTALL_PKGCONFIG_DIR)
|
||||
ln -sf $(LIB_SYMLINK1) $(INSTALL_LIB_DIR)/$(LIB_DEV_SYMLINK)
|
||||
|
||||
$(INSTALL_LIB_DIR):
|
||||
$(INSTALL_DIRS) $@
|
||||
|
||||
$(INSTALL_INCLUDE_DIR):
|
||||
$(INSTALL_DIRS) $@
|
||||
|
||||
$(INSTALL_PKGCONFIG_DIR):
|
||||
$(INSTALL_DIRS) $@
|
||||
5
debian/changelog
vendored
Normal file
5
debian/changelog
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
libglibutil (1.0.0) unstable; urgency=low
|
||||
|
||||
* Initial release
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Sat, 27 Dec 2014 22:36:32 +0200
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
5
|
||||
18
debian/control
vendored
Normal file
18
debian/control
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Source: libglibutil
|
||||
Section: libs
|
||||
Priority: optional
|
||||
Maintainer: Slava Monich <slava.monich@jolla.com>
|
||||
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0)
|
||||
Standards-Version: 3.8.4
|
||||
|
||||
Package: libglibutil
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Library of glib utilities
|
||||
|
||||
Package: libglibutil-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: libglibutil (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Development files for libglibutil
|
||||
29
debian/copyright
vendored
Normal file
29
debian/copyright
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
Copyright (C) 2014-2015 Jolla Ltd.
|
||||
Contact: Slava Monich <slava.monich@jolla.com>
|
||||
|
||||
You may use this file under the terms of BSD license as follows:
|
||||
|
||||
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.
|
||||
3. Neither the name of the Jolla Ltd nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
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 HOLDERS 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.
|
||||
3
debian/libglibutil-dev.install
vendored
Normal file
3
debian/libglibutil-dev.install
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
debian/tmp/usr/lib/libglibutil.so usr/lib
|
||||
include/*.h usr/include/glibutil
|
||||
build/libglibutil.pc usr/lib/pkgconfig
|
||||
1
debian/libglibutil.install
vendored
Normal file
1
debian/libglibutil.install
vendored
Normal file
@@ -0,0 +1 @@
|
||||
debian/tmp/usr/lib/libglibutil.so.* usr/lib
|
||||
11
debian/rules
vendored
Executable file
11
debian/rules
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install -- install-dev
|
||||
|
||||
%:
|
||||
dh $@
|
||||
343
include/gutil_log.h
Normal file
343
include/gutil_log.h
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the Jolla Ltd nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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 GUTIL_LOG_H
|
||||
#define GUTIL_LOG_H
|
||||
|
||||
#include "gutil_types.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Log levels */
|
||||
#define GLOG_LEVEL_ALWAYS (-2)
|
||||
#define GLOG_LEVEL_INHERIT (-1)
|
||||
#define GLOG_LEVEL_NONE (0)
|
||||
#define GLOG_LEVEL_ERR (1)
|
||||
#define GLOG_LEVEL_WARN (2)
|
||||
#define GLOG_LEVEL_INFO (3)
|
||||
#define GLOG_LEVEL_DEBUG (4)
|
||||
#define GLOG_LEVEL_VERBOSE (5)
|
||||
|
||||
/* Allow these to be redefined */
|
||||
#ifndef GLOG_LEVEL_MAX
|
||||
# ifdef DEBUG
|
||||
# define GLOG_LEVEL_MAX GLOG_LEVEL_VERBOSE
|
||||
# else
|
||||
# define GLOG_LEVEL_MAX GLOG_LEVEL_DEBUG
|
||||
# endif
|
||||
#endif /* GLOG_LEVEL_MAX */
|
||||
|
||||
#ifndef GLOG_LEVEL_DEFAULT
|
||||
# ifdef DEBUG
|
||||
# define GLOG_LEVEL_DEFAULT GLOG_LEVEL_DEBUG
|
||||
# else
|
||||
# define GLOG_LEVEL_DEFAULT GLOG_LEVEL_INFO
|
||||
# endif
|
||||
#endif /* GLOG_LEVEL_DEFAULT */
|
||||
|
||||
/* Do we need a separate log level for ASSERTs? */
|
||||
#ifndef GLOG_LEVEL_ASSERT
|
||||
# ifdef DEBUG
|
||||
# define GLOG_LEVEL_ASSERT GLOG_LEVEL_ERR
|
||||
# else
|
||||
/* No asserts in release build */
|
||||
# define GLOG_LEVEL_ASSERT (GLOG_LEVEL_MAX+1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Log module */
|
||||
struct glog_module {
|
||||
const char* name; /* Name (used as prefix) */
|
||||
const GLogModule* parent; /* Parent log module (optional) */
|
||||
void* reserved; /* Reserved for future expansion */
|
||||
const int max_level; /* Maximum level defined at compile time */
|
||||
int level; /* Current log level */
|
||||
int flags; /* Flags (should be zero) */
|
||||
int reserved2; /* Reserved for future expansion */
|
||||
};
|
||||
|
||||
/* Command line parsing helper. Option format is [module]:level
|
||||
* where level can be either a number or log level name ("none", err etc.) */
|
||||
gboolean
|
||||
gutil_log_parse_option(
|
||||
const char* opt, /* String to parse */
|
||||
GLogModule** modules, /* Known modules */
|
||||
int count, /* Number of known modules */
|
||||
GError** error); /* Optional error message */
|
||||
|
||||
/* Set log type by name ("syslog", "stdout" or "glib"). This is also
|
||||
* primarily for parsing command line options */
|
||||
gboolean
|
||||
gutil_log_set_type(
|
||||
const char* type,
|
||||
const char* default_name);
|
||||
|
||||
const char*
|
||||
gutil_log_get_type(
|
||||
void);
|
||||
|
||||
/* Generates the string containg description of log levels and list of
|
||||
* log modules. The caller must deallocate the string with g_free */
|
||||
char*
|
||||
gutil_log_description(
|
||||
GLogModule** modules, /* Known modules */
|
||||
int count); /* Number of known modules */
|
||||
|
||||
/* Logging function */
|
||||
void
|
||||
gutil_log(
|
||||
const GLogModule* module, /* Calling module (NULL for default) */
|
||||
int level, /* Message log level */
|
||||
const char* format, /* Message format */
|
||||
...) G_GNUC_PRINTF(3,4); /* Followed by arguments */
|
||||
|
||||
void
|
||||
gutil_logv(
|
||||
const GLogModule* module,
|
||||
int level,
|
||||
const char* format,
|
||||
va_list va);
|
||||
|
||||
/* Check if logging is enabled for the specified log level */
|
||||
gboolean
|
||||
gutil_log_enabled(
|
||||
const GLogModule* module,
|
||||
int level);
|
||||
|
||||
/* Known log types */
|
||||
extern const char GLOG_TYPE_STDOUT[];
|
||||
extern const char GLOG_TYPE_STDERR[];
|
||||
extern const char GLOG_TYPE_GLIB[];
|
||||
extern const char GLOG_TYPE_CUSTOM[];
|
||||
extern const char GLOG_TYPE_SYSLOG[];
|
||||
|
||||
/* Available log handlers */
|
||||
#define GUTIL_DEFINE_LOG_FN(fn) void fn(const char* name, int level, \
|
||||
const char* format, va_list va)
|
||||
GUTIL_DEFINE_LOG_FN(gutil_log_stdout);
|
||||
GUTIL_DEFINE_LOG_FN(gutil_log_stderr);
|
||||
GUTIL_DEFINE_LOG_FN(gutil_log_glib);
|
||||
GUTIL_DEFINE_LOG_FN(gutil_log_syslog);
|
||||
|
||||
/* Log configuration */
|
||||
#define GLOG_MODULE_DECL(m) extern GLogModule m;
|
||||
GLOG_MODULE_DECL(gutil_log_default)
|
||||
typedef GUTIL_DEFINE_LOG_FN((*GLogProc));
|
||||
extern GLogProc gutil_log_func;
|
||||
extern gboolean gutil_log_timestamp; /* Only affects stdout and stderr */
|
||||
|
||||
/* Log module (optional) */
|
||||
#define GLOG_MODULE_DEFINE_(var,name) \
|
||||
GLogModule var = {name, NULL, NULL, \
|
||||
GLOG_LEVEL_MAX, GLOG_LEVEL_INHERIT, 0, 0}
|
||||
#define GLOG_MODULE_DEFINE2_(var,name,parent) \
|
||||
GLogModule var = {name, &(parent), NULL, \
|
||||
GLOG_LEVEL_MAX, GLOG_LEVEL_INHERIT, 0, 0}
|
||||
#ifdef GLOG_MODULE_NAME
|
||||
extern GLogModule GLOG_MODULE_NAME;
|
||||
# define GLOG_MODULE_CURRENT (&GLOG_MODULE_NAME)
|
||||
# define GLOG_MODULE_DEFINE(name) \
|
||||
GLOG_MODULE_DEFINE_(GLOG_MODULE_NAME,name)
|
||||
# define GLOG_MODULE_DEFINE2(name,parent) \
|
||||
GLOG_MODULE_DEFINE2_(GLOG_MODULE_NAME,name,parent)
|
||||
#else
|
||||
# define GLOG_MODULE_CURRENT NULL
|
||||
#endif
|
||||
|
||||
/* Logging macros */
|
||||
|
||||
#define GLOG_NOTHING ((void)0)
|
||||
#define GLOG_ENABLED(level) gutil_log_enabled(GLOG_MODULE_CURRENT,level)
|
||||
#define GERRMSG(err) (((err) && (err)->message) ? (err)->message : \
|
||||
"Unknown error")
|
||||
|
||||
#if !defined(GLOG_VARARGS) && defined(__GNUC__)
|
||||
# define GLOG_VARARGS
|
||||
#endif
|
||||
|
||||
#ifndef GLOG_VARARGS
|
||||
# define GLOG_VA_NONE(x) static inline void GUTIL_##x(const char* f, ...) {}
|
||||
# define GLOG_VA(x) static inline void GUTIL_##x(const char* f, ...) { \
|
||||
if (f && f[0]) { \
|
||||
va_list va; va_start(va,f); \
|
||||
gutil_logv(GLOG_MODULE_CURRENT, GLOG_LEVEL_##x, f, va); \
|
||||
va_end(va); \
|
||||
} \
|
||||
}
|
||||
#endif /* GLOG_VARARGS */
|
||||
|
||||
#define GUTIL_LOG_ANY (GLOG_LEVEL_MAX >= GLOG_LEVEL_NONE)
|
||||
#define GUTIL_LOG_ERR (GLOG_LEVEL_MAX >= GLOG_LEVEL_ERR)
|
||||
#define GUTIL_LOG_WARN (GLOG_LEVEL_MAX >= GLOG_LEVEL_WARN)
|
||||
#define GUTIL_LOG_INFO (GLOG_LEVEL_MAX >= GLOG_LEVEL_INFO)
|
||||
#define GUTIL_LOG_DEBUG (GLOG_LEVEL_MAX >= GLOG_LEVEL_DEBUG)
|
||||
#define GUTIL_LOG_VERBOSE (GLOG_LEVEL_MAX >= GLOG_LEVEL_VERBOSE)
|
||||
#define GUTIL_LOG_ASSERT (GLOG_LEVEL_MAX >= GLOG_LEVEL_ASSERT)
|
||||
|
||||
#if GUTIL_LOG_ASSERT
|
||||
void
|
||||
gutil_log_assert(
|
||||
const GLogModule* module, /* Calling module (NULL for default) */
|
||||
int level, /* Assert log level */
|
||||
const char* expr, /* Assert expression */
|
||||
const char* file, /* File name */
|
||||
int line); /* Line number */
|
||||
# define GASSERT(expr) ((expr) ? GLOG_NOTHING : \
|
||||
gutil_log_assert(GLOG_MODULE_CURRENT, GLOG_LEVEL_ASSERT, \
|
||||
#expr, __FILE__, __LINE__))
|
||||
# define GVERIFY(expr) GASSERT(expr)
|
||||
# define GVERIFY_FALSE(expr) GASSERT(!(expr))
|
||||
# define GVERIFY_EQ(expr,val) GASSERT((expr) == (val))
|
||||
# define GVERIFY_NE(expr,val) GASSERT((expr) != (val))
|
||||
# define GVERIFY_GE(expr,val) GASSERT((expr) >= (val))
|
||||
# define GVERIFY_GT(expr,val) GASSERT((expr) > (val))
|
||||
# define GVERIFY_LE(expr,val) GASSERT((expr) <= (val))
|
||||
# define GVERIFY_LT(expr,val) GASSERT((expr) < (val))
|
||||
#else
|
||||
# define GASSERT(expr)
|
||||
# define GVERIFY(expr) (expr)
|
||||
# define GVERIFY_FALSE(expr) (expr)
|
||||
# define GVERIFY_EQ(expr,val) (expr)
|
||||
# define GVERIFY_NE(expr,val) (expr)
|
||||
# define GVERIFY_GE(expr,val) (expr)
|
||||
# define GVERIFY_GT(expr,val) (expr)
|
||||
# define GVERIFY_LE(expr,val) (expr)
|
||||
# define GVERIFY_LT(expr,val) (expr)
|
||||
#endif
|
||||
|
||||
#ifdef GLOG_VARARGS
|
||||
# if GUTIL_LOG_ERR
|
||||
# define GERR(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_ERR, f, ##args)
|
||||
# define GERR_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_ERR, "%s() " f, __FUNCTION__, ##args)
|
||||
# else
|
||||
# define GERR(f,args...) GLOG_NOTHING
|
||||
# define GERR_(f,args...) GLOG_NOTHING
|
||||
# endif /* GUTIL_LOG_ERR */
|
||||
#else
|
||||
# define GERR_ GERR
|
||||
# if GUTIL_LOG_ERR
|
||||
GLOG_VA(ERR)
|
||||
# else
|
||||
GLOG_VA_NONE(ERR)
|
||||
# endif /* GUTIL_LOG_ERR */
|
||||
#endif /* GLOG_VARARGS */
|
||||
|
||||
#ifdef GLOG_VARARGS
|
||||
# if GUTIL_LOG_WARN
|
||||
# define GWARN(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_WARN, f, ##args)
|
||||
# define GWARN_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_WARN, "%s() " f, __FUNCTION__, ##args)
|
||||
# else
|
||||
# define GWARN(f,args...) GLOG_NOTHING
|
||||
# define GWARN_(f,args...) GLOG_NOTHING
|
||||
# endif /* GUTIL_LOGL_WARN */
|
||||
#else
|
||||
# define GWARN_ GWARN
|
||||
# if GUTIL_LOG_WARN
|
||||
GLOG_VA(WARN)
|
||||
# else
|
||||
GLOG_VA_NONE(WARN)
|
||||
# endif /* GUTIL_LOGL_WARN */
|
||||
# endif /* GLOG_VARARGS */
|
||||
|
||||
#ifdef GLOG_VARARGS
|
||||
# if GUTIL_LOG_INFO
|
||||
# define GINFO(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_INFO, f, ##args)
|
||||
# define GINFO_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_INFO, "%s() " f, __FUNCTION__, ##args)
|
||||
# else
|
||||
# define GINFO(f,args...) GLOG_NOTHING
|
||||
# define GINFO_(f,args...) GLOG_NOTHING
|
||||
# endif /* GUTIL_LOG_INFO */
|
||||
#else
|
||||
# define GINFO_ GINFO
|
||||
# if GUTIL_LOG_INFO
|
||||
GLOG_VA(INFO)
|
||||
# else
|
||||
GLOG_VA_NONE(INFO)
|
||||
# endif /* GUTIL_LOG_INFO */
|
||||
#endif /* GLOG_VARARGS */
|
||||
|
||||
#ifdef GLOG_VARARGS
|
||||
# if GUTIL_LOG_DEBUG
|
||||
# define GDEBUG(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_DEBUG, f, ##args)
|
||||
# define GDEBUG_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_DEBUG, "%s() " f, __FUNCTION__, ##args)
|
||||
# else
|
||||
# define GDEBUG(f,args...) GLOG_NOTHING
|
||||
# define GDEBUG_(f,args...) GLOG_NOTHING
|
||||
# endif /* GUTIL_LOG_DEBUG */
|
||||
#else
|
||||
# define GDEBUG_ GDEBUG
|
||||
# if GUTIL_LOG_DEBUG
|
||||
GLOG_VA(DEBUG)
|
||||
# else
|
||||
GLOG_VA_NONE(DEBUG)
|
||||
# endif /* GUTIL_LOG_DEBUG */
|
||||
#endif /* GLOG_VARARGS */
|
||||
|
||||
#ifdef GLOG_VARARGS
|
||||
# if GUTIL_LOG_VERBOSE
|
||||
# define GVERBOSE(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_VERBOSE, f, ##args)
|
||||
# define GVERBOSE_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \
|
||||
GLOG_LEVEL_VERBOSE, "%s() " f, __FUNCTION__, ##args)
|
||||
# else
|
||||
# define GVERBOSE(f,args...) GLOG_NOTHING
|
||||
# define GVERBOSE_(f,args...) GLOG_NOTHING
|
||||
# endif /* GUTIL_LOG_VERBOSE */
|
||||
#else
|
||||
# define GVERBOSE_ GVERBOSE
|
||||
# if GUTIL_LOG_VERBOSE
|
||||
GLOG_VA(VERBOSE)
|
||||
# else
|
||||
GLOG_VA_NONE(VERBOSE)
|
||||
# endif /* GUTIL_LOG_VERBOSE */
|
||||
#endif /* GLOG_VARARGS */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GUTIL_LOG_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
59
include/gutil_macros.h
Normal file
59
include/gutil_macros.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the Jolla Ltd nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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 GUTIL_MACROS_H
|
||||
#define GUTIL_MACROS_H
|
||||
|
||||
#include <gutil_types.h>
|
||||
|
||||
#define G_CAST(address,type,field) \
|
||||
((type *)((guint8*)(address) - G_STRUCT_OFFSET(type,field)))
|
||||
|
||||
#define G_ALIGN2(value) (((value)+1) & ~1)
|
||||
#define G_ALIGN4(value) (((value)+3) & ~3)
|
||||
#define G_ALIGN8(value) (((value)+7) & ~7)
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define G_PACKED __attribute__((packed))
|
||||
#else
|
||||
# define G_PACKED
|
||||
#endif
|
||||
|
||||
#endif /* GUTIL_MACROS_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
51
include/gutil_types.h
Normal file
51
include/gutil_types.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the Jolla Ltd nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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 GUTIL_TYPES_H
|
||||
#define GUTIL_TYPES_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct glog_module GLogModule;
|
||||
|
||||
#endif /* GUTIL_TYPES_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
10
libglibutil.pc.in
Normal file
10
libglibutil.pc.in
Normal file
@@ -0,0 +1,10 @@
|
||||
name=glibutil
|
||||
libdir=/usr/lib
|
||||
includedir=/usr/include
|
||||
|
||||
Name: libglibutil
|
||||
Description: Library of glib utilities
|
||||
Version: [version]
|
||||
Requires: glib-2.0
|
||||
Libs: -L${libdir} -l${name}
|
||||
Cflags: -I${includedir} -I${includedir}/${name}
|
||||
46
rpm/libglibutil.spec
Normal file
46
rpm/libglibutil.spec
Normal file
@@ -0,0 +1,46 @@
|
||||
Name: libglibutil
|
||||
Version: 1.0
|
||||
Release: 0
|
||||
Summary: Library of glib utilities
|
||||
Group: Development/Libraries
|
||||
License: BSD
|
||||
URL: https://github.com/nemomobile/libglibutil
|
||||
Source: %{name}-%{version}.tar.bz2
|
||||
BuildRequires: glib2-devel >= 2.0
|
||||
Requires(post): /sbin/ldconfig
|
||||
Requires(postun): /sbin/ldconfig
|
||||
|
||||
%description
|
||||
Provides glib utility functions and macros
|
||||
|
||||
%package devel
|
||||
Summary: Development library for %{name}
|
||||
Requires: %{name} = %{version}
|
||||
Requires: pkgconfig
|
||||
|
||||
%description devel
|
||||
This package contains the development library for %{name}.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
make KEEP_SYMBOLS=1 release pkgconfig
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
make install-dev DESTDIR=%{buildroot}
|
||||
|
||||
%post -p /sbin/ldconfig
|
||||
|
||||
%postun -p /sbin/ldconfig
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/%{name}.so.*
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pkgconfig/*.pc
|
||||
%{_libdir}/%{name}.so
|
||||
%{_includedir}/glibutil/*.h
|
||||
527
src/gutil_log.c
Normal file
527
src/gutil_log.c
Normal file
@@ -0,0 +1,527 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the Jolla Ltd nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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 "gutil_log.h"
|
||||
|
||||
#if defined(DEBUG) && defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef GLOG_SYSLOG
|
||||
# ifdef unix
|
||||
# define GLOG_SYSLOG 1
|
||||
# else
|
||||
# define GLOG_SYSLOG 0
|
||||
# endif
|
||||
#endif /* GLOG_SYSLOG */
|
||||
|
||||
#ifndef GLOG_GLIB
|
||||
# define GLOG_GLIB 1
|
||||
#endif /* GLOG_GLIB */
|
||||
|
||||
/* Allows timestamps in stdout log */
|
||||
gboolean gutil_log_timestamp = TRUE;
|
||||
|
||||
/* Log configuration */
|
||||
GLogProc gutil_log_func = gutil_log_stdout;
|
||||
GLogModule gutil_log_default = {
|
||||
NULL, /* name */
|
||||
NULL, /* parent */
|
||||
NULL, /* reserved */
|
||||
GLOG_LEVEL_MAX, /* max_level */
|
||||
GLOG_LEVEL_DEFAULT, /* level */
|
||||
0 /* flags */
|
||||
};
|
||||
|
||||
/* Log level descriptions */
|
||||
static const struct _gutil_log_level {
|
||||
const char* name;
|
||||
const char* description;
|
||||
} gutil_log_levels [] = {
|
||||
{ "none", "Disable log output" },
|
||||
{ "error", "Errors only"},
|
||||
{ "warning", "From warning level to errors" },
|
||||
{ "info", "From information level to errors" },
|
||||
{ "debug", "From debug messages to errors" },
|
||||
{ "verbose", "From verbose trace messages to errors" }
|
||||
};
|
||||
|
||||
const char GLOG_TYPE_STDOUT[] = "stdout";
|
||||
const char GLOG_TYPE_STDERR[] = "stderr";
|
||||
const char GLOG_TYPE_CUSTOM[] = "custom";
|
||||
#if GLOG_GLIB
|
||||
const char GLOG_TYPE_GLIB[] = "glib";
|
||||
#endif
|
||||
#if GLOG_SYSLOG
|
||||
const char GLOG_TYPE_SYSLOG[] = "syslog";
|
||||
#endif
|
||||
|
||||
G_STATIC_ASSERT(G_N_ELEMENTS(gutil_log_levels) > GLOG_LEVEL_MAX);
|
||||
G_STATIC_ASSERT(G_N_ELEMENTS(gutil_log_levels) > GLOG_LEVEL_DEFAULT);
|
||||
|
||||
/**
|
||||
* Formats the string into the given buffer (most commonly allocated
|
||||
* on caller's stack). If formatted string fits into the provided buffer,
|
||||
* returns pointer to the given buffer. If formatted string is too long
|
||||
* to fit into the provided buffer, allocates a new one and returns pointer
|
||||
* to it.
|
||||
*/
|
||||
static
|
||||
char*
|
||||
gutil_log_format(
|
||||
char* buf,
|
||||
int bufsize,
|
||||
const char* format,
|
||||
va_list va)
|
||||
{
|
||||
int size, nchars = -1;
|
||||
char* buffer;
|
||||
if (buf) {
|
||||
size = bufsize;
|
||||
buffer = buf;
|
||||
} else {
|
||||
size = MAX(100,bufsize);
|
||||
buffer = g_malloc(size);
|
||||
}
|
||||
while (buffer) {
|
||||
|
||||
/* Try to print in the allocated space. */
|
||||
va_list va2;
|
||||
G_VA_COPY(va2, va);
|
||||
nchars = g_vsnprintf(buffer, size, format, va2);
|
||||
va_end(va2);
|
||||
|
||||
/* Return the string or try again with more space. */
|
||||
if (nchars >= 0) {
|
||||
if (nchars < size) break;
|
||||
size = nchars+1; /* Precisely what is needed */
|
||||
} else {
|
||||
size *= 2; /* Twice the old size */
|
||||
}
|
||||
|
||||
if (buffer != buf) g_free(buffer);
|
||||
buffer = g_malloc(size);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Forward output to stdout or stderr */
|
||||
void
|
||||
gutil_log_stdio(
|
||||
FILE* out,
|
||||
const char* name,
|
||||
int level,
|
||||
const char* format,
|
||||
va_list va)
|
||||
{
|
||||
char t[32];
|
||||
char buf[512];
|
||||
const char* prefix = "";
|
||||
char* msg;
|
||||
if (gutil_log_timestamp) {
|
||||
time_t now;
|
||||
time(&now);
|
||||
strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S ", localtime(&now));
|
||||
} else {
|
||||
t[0] = 0;
|
||||
}
|
||||
switch (level) {
|
||||
case GLOG_LEVEL_WARN: prefix = "WARNING: "; break;
|
||||
case GLOG_LEVEL_ERR: prefix = "ERROR: "; break;
|
||||
default: break;
|
||||
}
|
||||
msg = gutil_log_format(buf, sizeof(buf), format, va);
|
||||
#if defined(DEBUG) && defined(_WIN32)
|
||||
{
|
||||
char s[1023];
|
||||
if (name) {
|
||||
g_snprintf(s, sizeof(s), "%s[%s] %s%s\n", t, name, prefix, msg);
|
||||
} else {
|
||||
g_snprintf(s, sizeof(s), "%s%s%s\n", t, prefix, msg);
|
||||
}
|
||||
OutputDebugStringA(s);
|
||||
}
|
||||
#endif
|
||||
if (name) {
|
||||
fprintf(out, "%s[%s] %s%s\n", t, name, prefix, msg);
|
||||
} else {
|
||||
fprintf(out, "%s%s%s\n", t, prefix, msg);
|
||||
}
|
||||
if (msg != buf) g_free(msg);
|
||||
}
|
||||
|
||||
void
|
||||
gutil_log_stdout(
|
||||
const char* name,
|
||||
int level,
|
||||
const char* format,
|
||||
va_list va)
|
||||
{
|
||||
gutil_log_stdio(stdout, name, level, format, va);
|
||||
}
|
||||
|
||||
void
|
||||
gutil_log_stderr(
|
||||
const char* name,
|
||||
int level,
|
||||
const char* format,
|
||||
va_list va)
|
||||
{
|
||||
gutil_log_stdio(stderr, name, level, format, va);
|
||||
}
|
||||
|
||||
/* Formards output to syslog */
|
||||
#if GLOG_SYSLOG
|
||||
#include <syslog.h>
|
||||
void
|
||||
gutil_log_syslog(
|
||||
const char* name,
|
||||
int level,
|
||||
const char* format,
|
||||
va_list va)
|
||||
{
|
||||
int priority;
|
||||
const char* prefix = NULL;
|
||||
switch (level) {
|
||||
default:
|
||||
case GLOG_LEVEL_INFO:
|
||||
priority = LOG_NOTICE;
|
||||
break;
|
||||
case GLOG_LEVEL_VERBOSE:
|
||||
priority = LOG_DEBUG;
|
||||
break;
|
||||
case GLOG_LEVEL_DEBUG:
|
||||
priority = LOG_INFO;
|
||||
break;
|
||||
case GLOG_LEVEL_WARN:
|
||||
priority = LOG_WARNING;
|
||||
prefix = "WARNING! ";
|
||||
break;
|
||||
case GLOG_LEVEL_ERR:
|
||||
priority = LOG_ERR;
|
||||
prefix = "ERROR! ";
|
||||
break;
|
||||
}
|
||||
if (name || prefix) {
|
||||
char buf[512];
|
||||
g_vsnprintf(buf, sizeof(buf), format, va);
|
||||
if (!prefix) prefix = "";
|
||||
if (name) {
|
||||
syslog(priority, "[%s] %s%s", name, prefix, buf);
|
||||
} else {
|
||||
syslog(priority, "%s%s", prefix, buf);
|
||||
}
|
||||
} else {
|
||||
vsyslog(priority, format, va);
|
||||
}
|
||||
}
|
||||
#endif /* GLOG_SYSLOG */
|
||||
|
||||
/* Forwards output to g_logv */
|
||||
#if GLOG_GLIB
|
||||
void
|
||||
gutil_log_glib(
|
||||
const char* name,
|
||||
int level,
|
||||
const char* format,
|
||||
va_list va)
|
||||
{
|
||||
GLogLevelFlags flags;
|
||||
switch (level) {
|
||||
default:
|
||||
case GLOG_LEVEL_INFO: flags = G_LOG_LEVEL_MESSAGE; break;
|
||||
case GLOG_LEVEL_VERBOSE: flags = G_LOG_LEVEL_DEBUG; break;
|
||||
case GLOG_LEVEL_DEBUG: flags = G_LOG_LEVEL_INFO; break;
|
||||
case GLOG_LEVEL_WARN: flags = G_LOG_LEVEL_WARNING; break;
|
||||
case GLOG_LEVEL_ERR: flags = G_LOG_LEVEL_CRITICAL; break;
|
||||
}
|
||||
g_logv(name, flags, format, va);
|
||||
}
|
||||
#endif /* GLOG_GLIB */
|
||||
|
||||
/* Logging function */
|
||||
void
|
||||
gutil_logv_r(
|
||||
const GLogModule* module,
|
||||
int level,
|
||||
const char* prefix,
|
||||
const char* format,
|
||||
va_list va)
|
||||
{
|
||||
if (module->parent && module->level == GLOG_LEVEL_INHERIT) {
|
||||
gutil_logv_r(module->parent, level, prefix, format, va);
|
||||
} else {
|
||||
const int max_level = (module->level == GLOG_LEVEL_INHERIT) ?
|
||||
gutil_log_default.level : module->level;
|
||||
if (level > GLOG_LEVEL_NONE && level <= max_level) {
|
||||
GLogProc log = gutil_log_func;
|
||||
if (G_LIKELY(log)) {
|
||||
log(prefix, level, format, va);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gutil_logv(
|
||||
const GLogModule* module,
|
||||
int level,
|
||||
const char* format,
|
||||
va_list va)
|
||||
{
|
||||
if (level != GLOG_LEVEL_NONE && gutil_log_func) {
|
||||
if (!module) module = &gutil_log_default;
|
||||
if (G_UNLIKELY(level == GLOG_LEVEL_ALWAYS)) {
|
||||
GLogProc log = gutil_log_func;
|
||||
if (G_LIKELY(log)) {
|
||||
if (level == GLOG_LEVEL_ALWAYS) {
|
||||
log(module->name, level, format, va);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gutil_logv_r(module, level, module->name, format, va);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gutil_log(
|
||||
const GLogModule* module,
|
||||
int level,
|
||||
const char* format,
|
||||
...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
gutil_logv(module, level, format, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void
|
||||
gutil_log_assert(
|
||||
const GLogModule* module,
|
||||
int level,
|
||||
const char* expr,
|
||||
const char* file,
|
||||
int line)
|
||||
{
|
||||
gutil_log(module, level, "Assert %s failed at %s:%d\r", expr, file, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if logging is enabled for the specified log level
|
||||
*/
|
||||
static
|
||||
gboolean
|
||||
gutil_log_enabled_r(
|
||||
const GLogModule* module,
|
||||
int level)
|
||||
{
|
||||
if (module->parent && module->level == GLOG_LEVEL_INHERIT) {
|
||||
return gutil_log_enabled_r(module->parent, level);
|
||||
} else {
|
||||
const int max_level = (module->level == GLOG_LEVEL_INHERIT) ?
|
||||
gutil_log_default.level : module->level;
|
||||
return (level > GLOG_LEVEL_NONE && level <= max_level);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gutil_log_enabled(
|
||||
const GLogModule* module,
|
||||
int level)
|
||||
{
|
||||
if (gutil_log_func) {
|
||||
if (level == GLOG_LEVEL_ALWAYS) {
|
||||
return TRUE;
|
||||
} else if (level > GLOG_LEVEL_NONE) {
|
||||
if (!module) module = &gutil_log_default;
|
||||
return gutil_log_enabled_r(module, level);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* gutil_log_parse_option helper */
|
||||
static
|
||||
int
|
||||
gutil_log_parse_level(
|
||||
const char* str,
|
||||
GError** error)
|
||||
{
|
||||
if (str && str[0]) {
|
||||
guint i;
|
||||
const size_t len = strlen(str);
|
||||
if (len == 1) {
|
||||
const char* valid_numbers = "012345";
|
||||
const char* number = strchr(valid_numbers, str[0]);
|
||||
if (number) {
|
||||
return number - valid_numbers;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<G_N_ELEMENTS(gutil_log_levels); i++) {
|
||||
if (!strncmp(gutil_log_levels[i].name, str, len)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
*error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Invalid log level '%s'", str);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command line parsing helper. Option format is [module:]level where level
|
||||
* can be either a number or log level name ("none", "error", etc.)
|
||||
*/
|
||||
gboolean
|
||||
gutil_log_parse_option(
|
||||
const char* opt,
|
||||
GLogModule** modules,
|
||||
int count,
|
||||
GError** error)
|
||||
{
|
||||
const char* sep = strchr(opt, ':');
|
||||
if (sep) {
|
||||
const int modlevel = gutil_log_parse_level(sep+1, error);
|
||||
if (modlevel >= 0) {
|
||||
int i;
|
||||
const size_t namelen = sep - opt;
|
||||
for (i=0; i<count; i++) {
|
||||
if (!g_ascii_strncasecmp(modules[i]->name, opt, namelen) &&
|
||||
strlen(modules[i]->name) == namelen) {
|
||||
modules[i]->level = modlevel;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
*error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Unknown log module '%.*s'", (int)namelen, opt);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const int deflevel = gutil_log_parse_level(opt, error);
|
||||
if (deflevel >= 0) {
|
||||
gutil_log_default.level = deflevel;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the string containg description of log levels and list of
|
||||
* log modules. The caller must deallocate the string with g_free
|
||||
*/
|
||||
char*
|
||||
gutil_log_description(
|
||||
GLogModule** modules, /* Known modules */
|
||||
int count) /* Number of known modules */
|
||||
{
|
||||
int i;
|
||||
GString* desc = g_string_sized_new(128);
|
||||
g_string_append(desc, "Log Levels:\n");
|
||||
for (i=0; i<=GLOG_LEVEL_VERBOSE; i++) {
|
||||
g_string_append_printf(desc, " %d, ", i);
|
||||
g_string_append_printf(desc, "%-8s ", gutil_log_levels[i].name);
|
||||
g_string_append(desc, gutil_log_levels[i].description);
|
||||
if (i == GLOG_LEVEL_DEFAULT) g_string_append(desc, " (default)");
|
||||
g_string_append(desc, "\n");
|
||||
}
|
||||
if (modules) {
|
||||
g_string_append(desc, "\nLog Modules:\n");
|
||||
for (i=0; i<count; i++) {
|
||||
g_string_append_printf(desc, " %s\n", modules[i]->name);
|
||||
}
|
||||
}
|
||||
return g_string_free(desc, FALSE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gutil_log_set_type(
|
||||
const char* type,
|
||||
const char* default_name)
|
||||
{
|
||||
#if GLOG_SYSLOG
|
||||
if (!g_ascii_strcasecmp(type, GLOG_TYPE_SYSLOG)) {
|
||||
if (gutil_log_func != gutil_log_syslog) {
|
||||
openlog(NULL, LOG_PID | LOG_CONS, LOG_USER);
|
||||
}
|
||||
gutil_log_default.name = NULL;
|
||||
gutil_log_func = gutil_log_syslog;
|
||||
return TRUE;
|
||||
}
|
||||
if (gutil_log_func == gutil_log_syslog) {
|
||||
closelog();
|
||||
}
|
||||
#endif /* GLOG_SYSLOG */
|
||||
gutil_log_default.name = default_name;
|
||||
if (!g_ascii_strcasecmp(type, GLOG_TYPE_STDOUT)) {
|
||||
gutil_log_func = gutil_log_stdout;
|
||||
return TRUE;
|
||||
} if (!g_ascii_strcasecmp(type, GLOG_TYPE_STDERR)) {
|
||||
gutil_log_func = gutil_log_stderr;
|
||||
return TRUE;
|
||||
#if GLOG_GLIB
|
||||
} else if (!g_ascii_strcasecmp(type, GLOG_TYPE_GLIB)) {
|
||||
gutil_log_func = gutil_log_glib;
|
||||
return TRUE;
|
||||
#endif /* GLOG_GLIB */
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const char*
|
||||
gutil_log_get_type()
|
||||
{
|
||||
return (gutil_log_func == gutil_log_stdout) ? GLOG_TYPE_STDOUT :
|
||||
(gutil_log_func == gutil_log_stderr) ? GLOG_TYPE_STDERR :
|
||||
#if GLOG_SYSLOG
|
||||
(gutil_log_func == gutil_log_syslog) ? GLOG_TYPE_SYSLOG :
|
||||
#endif /* GLOG_SYSLOG */
|
||||
#if GLOG_GLIB
|
||||
(gutil_log_func == gutil_log_glib) ? GLOG_TYPE_GLIB :
|
||||
#endif /* GLOG_GLIB */
|
||||
GLOG_TYPE_CUSTOM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
Reference in New Issue
Block a user