X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/fcd529e692af2196e118bdd3cf7eef6685329e1c..b58b0ba2f6b92efa234677e19dd998346113504d:/src/xbt/log.cpp diff --git a/src/xbt/log.cpp b/src/xbt/log.cpp index b109018ca2..d21ea0e07b 100644 --- a/src/xbt/log.cpp +++ b/src/xbt/log.cpp @@ -1,31 +1,23 @@ /* log - a generic logging facility in the spirit of log4j */ -/* Copyright (c) 2004-2019. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2004-2023. The SimGrid Team. All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ -#include "src/xbt_modinter.h" #include "src/xbt/log_private.hpp" -#include "xbt/asserts.h" -#include "xbt/dynar.h" -#include "xbt/str.h" +#include "xbt/string.hpp" +#include "xbt/sysdep.h" #include +#include +#include +#include #include #include #include int xbt_log_no_loc = 0; /* if set to true (with --log=no_loc), file localization will be omitted (for tesh tests) */ -static std::recursive_mutex* log_cat_init_mutex = nullptr; - -/** @addtogroup XBT_log - * - * For more information, please refer to @ref outcomes_logs Section. - */ - -xbt_log_appender_t xbt_log_default_appender = nullptr; /* set in log_init */ -xbt_log_layout_t xbt_log_default_layout = nullptr; /* set in log_init */ struct xbt_log_setting_t { std::string catname; @@ -35,18 +27,15 @@ struct xbt_log_setting_t { xbt_log_appender_t appender = nullptr; }; -static std::vector xbt_log_settings; - -const char *xbt_log_priority_names[8] = { - "NONE", - "TRACE", - "DEBUG", - "VERBOSE", - "INFO", - "WARNING", - "ERROR", - "CRITICAL" -}; +// This function is here to avoid static initialization order fiasco +static auto& xbt_log_settings() +{ + static std::vector value; + return value; +} + +constexpr std::array xbt_log_priority_names{ + {"NONE", "TRACE", "DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR", "CRITICAL"}}; s_xbt_log_category_t _XBT_LOGV(XBT_LOG_ROOT_CAT) = { nullptr /*parent */, @@ -64,30 +53,19 @@ s_xbt_log_category_t _XBT_LOGV(XBT_LOG_ROOT_CAT) = { XBT_LOG_NEW_DEFAULT_SUBCATEGORY(log, xbt, "Loggings from the logging mechanism itself"); -/* create the default appender and install it in the root category, - which were already created (damnit. Too slow little beetle) */ -void xbt_log_preinit(void) -{ - xbt_log_default_appender = xbt_log_appender_file_new(nullptr); - xbt_log_default_layout = xbt_log_layout_simple_new(nullptr); - _XBT_LOGV(XBT_LOG_ROOT_CAT).appender = xbt_log_default_appender; - _XBT_LOGV(XBT_LOG_ROOT_CAT).layout = xbt_log_default_layout; - log_cat_init_mutex = new std::recursive_mutex(); -} +static void xbt_log_help(); +static void xbt_log_help_categories(); +static void xbt_log_postexit(); -static void xbt_log_help(void); -static void xbt_log_help_categories(void); - -/** @brief Get all logging settings from the command line - * - * xbt_log_control_set() is called on each string we got from cmd line - */ void xbt_log_init(int *argc, char **argv) { unsigned help_requested = 0; /* 1: logs; 2: categories */ int j = 1; int parse_args = 1; // Stop parsing the parameters once we found '--' + xbt_log_control_set("xbt_help.app:stdout xbt_help.threshold:VERBOSE xbt_help.fmt:%m%n"); + atexit(xbt_log_postexit); + /* Set logs and init log submodule */ for (int i = 1; i < *argc; i++) { if (strcmp("--", argv[i]) == 0) { @@ -122,27 +100,27 @@ void xbt_log_init(int *argc, char **argv) static void log_cat_exit(xbt_log_category_t cat) { - xbt_log_category_t child; - if (cat->appender) { if (cat->appender->free_) cat->appender->free_(cat->appender); xbt_free(cat->appender); + cat->appender = nullptr; } if (cat->layout) { if (cat->layout->free_) cat->layout->free_(cat->layout); xbt_free(cat->layout); + cat->layout = nullptr; } - for (child = cat->firstChild; child != nullptr; child = child->nextSibling) + for (auto* child = cat->firstChild; child != nullptr; child = child->nextSibling) log_cat_exit(child); + cat->firstChild = nullptr; } -void xbt_log_postexit(void) +static void xbt_log_postexit(void) { XBT_VERB("Exiting log"); - delete log_cat_init_mutex; log_cat_exit(&_XBT_LOGV(XBT_LOG_ROOT_CAT)); } @@ -154,34 +132,32 @@ static constexpr size_t XBT_LOG_DYNAMIC_BUFFER_SIZE = 4096; void _xbt_log_event_log(xbt_log_event_t ev, const char *fmt, ...) { - xbt_log_category_t cat = ev->cat; + const xbt_log_category_s* cat = ev->cat; xbt_assert(ev->priority >= 0, "Negative logging priority naturally forbidden"); - xbt_assert(static_cast(ev->priority) < sizeof(xbt_log_priority_names)/sizeof(xbt_log_priority_names[0]), + xbt_assert(static_cast(ev->priority) < xbt_log_priority_names.size(), "Priority %d is greater than the biggest allowed value", ev->priority); - while (1) { - xbt_log_appender_t appender = cat->appender; - - if (appender != nullptr) { + while (true) { + if (const s_xbt_log_appender_t* appender = cat->appender) { xbt_assert(cat->layout, "No valid layout for the appender of category %s", cat->name); /* First, try with a static buffer */ - int done = 0; - char buff[XBT_LOG_STATIC_BUFFER_SIZE]; - ev->buffer = buff; - ev->buffer_size = sizeof buff; + bool done = false; + std::array buff; + ev->buffer = buff.data(); + ev->buffer_size = buff.size(); va_start(ev->ap, fmt); done = cat->layout->do_layout(cat->layout, ev, fmt); va_end(ev->ap); + ev->buffer = nullptr; // Calm down, static analyzers, this pointer to local array won't leak out of the scope. if (done) { - appender->do_append(appender, buff); + appender->do_append(appender, buff.data()); } else { - /* The static buffer was too small, use a dynamically expanded one */ ev->buffer_size = XBT_LOG_DYNAMIC_BUFFER_SIZE; ev->buffer = static_cast(xbt_malloc(ev->buffer_size)); - while (1) { + while (true) { va_start(ev->ap, fmt); done = cat->layout->do_layout(cat->layout, ev, fmt); va_end(ev->ap); @@ -195,7 +171,7 @@ void _xbt_log_event_log(xbt_log_event_t ev, const char *fmt, ...) } } - if (!cat->additivity) + if (not cat->additivity) break; cat = cat->parent; } @@ -215,7 +191,7 @@ static int fake_xbt_log_cat_init(xbt_log_category_t, e_xbt_log_priority_t) return 0; } #define DISABLE_XBT_LOG_CAT_INIT() \ - int (*_xbt_log_cat_init)(xbt_log_category_t, e_xbt_log_priority_t) XBT_ATTRIB_UNUSED = fake_xbt_log_cat_init; + XBT_ATTRIB_UNUSED int (*_xbt_log_cat_init)(xbt_log_category_t, e_xbt_log_priority_t) = fake_xbt_log_cat_init static void _xbt_log_cat_apply_set(xbt_log_category_t category, const xbt_log_setting_t& setting) { @@ -241,7 +217,7 @@ static void _xbt_log_cat_apply_set(xbt_log_category_t category, const xbt_log_se } if (setting.appender) { xbt_log_appender_set(category, setting.appender); - if (!category->layout) + if (not category->layout) xbt_log_layout_set(category, xbt_log_layout_simple_new(nullptr)); category->additivity = 0; XBT_DEBUG("Set %p as appender of category '%s'", setting.appender, category->name); @@ -258,8 +234,8 @@ int _xbt_log_cat_init(xbt_log_category_t category, e_xbt_log_priority_t priority if (category->initialized) return priority >= category->threshold; - if (log_cat_init_mutex != nullptr) - log_cat_init_mutex->lock(); + static std::recursive_mutex log_cat_init_mutex; + const std::scoped_lock lock(log_cat_init_mutex); XBT_DEBUG("Initializing category '%s' (firstChild=%s, nextSibling=%s)", category->name, (category->firstChild ? category->firstChild->name : "none"), @@ -267,10 +243,10 @@ int _xbt_log_cat_init(xbt_log_category_t category, e_xbt_log_priority_t priority if (category == &_XBT_LOGV(XBT_LOG_ROOT_CAT)) { category->threshold = xbt_log_priority_info; - category->appender = xbt_log_default_appender; - category->layout = xbt_log_default_layout; + category->appender = xbt_log_appender_stream(stderr); + category->layout = xbt_log_layout_simple_new(nullptr); } else { - if (!category->parent) + if (not category->parent) category->parent = &_XBT_LOGV(XBT_LOG_ROOT_CAT); XBT_DEBUG("Set %s (%s) as father of %s ", category->parent->name, @@ -280,7 +256,7 @@ int _xbt_log_cat_init(xbt_log_category_t category, e_xbt_log_priority_t priority if (XBT_LOG_ISENABLED(log, xbt_log_priority_debug)) { std::string res; - xbt_log_category_t cpp = category->parent->firstChild; + const xbt_log_category_s* cpp = category->parent->firstChild; while (cpp) { res += std::string(" ") + cpp->name; cpp = cpp->nextSibling; @@ -292,19 +268,17 @@ int _xbt_log_cat_init(xbt_log_category_t category, e_xbt_log_priority_t priority } /* Apply the control */ - auto iset = std::find_if(begin(xbt_log_settings), end(xbt_log_settings), - [category](const xbt_log_setting_t& s) { return s.catname == category->name; }); - if (iset != xbt_log_settings.end()) { + if (auto iset = std::find_if(begin(xbt_log_settings()), end(xbt_log_settings()), + [category](const xbt_log_setting_t& s) { return s.catname == category->name; }); + iset != xbt_log_settings().end()) { _xbt_log_cat_apply_set(category, *iset); - xbt_log_settings.erase(iset); + xbt_log_settings().erase(iset); } else { XBT_DEBUG("Category '%s': inherited threshold = %s (=%d)", category->name, xbt_log_priority_names[category->threshold], category->threshold); } category->initialized = 1; - if (log_cat_init_mutex != nullptr) - log_cat_init_mutex->unlock(); return priority >= category->threshold; } @@ -330,15 +304,15 @@ void xbt_log_parent_set(xbt_log_category_t cat, xbt_log_category_t parent) parent->firstChild = cat; - if (!parent->initialized) - _xbt_log_cat_init(parent, xbt_log_priority_uninitialized /* ignored */ ); + if (not parent->initialized) + (void)_xbt_log_cat_init(parent, xbt_log_priority_uninitialized /* ignored */); cat->threshold = parent->threshold; cat->isThreshInherited = 1; } -static void _set_inherited_thresholds(xbt_log_category_t cat) +static void _set_inherited_thresholds(const s_xbt_log_category_t* cat) { xbt_log_category_t child = cat->firstChild; @@ -366,90 +340,68 @@ static xbt_log_setting_t _xbt_log_parse_setting(const char *control_string) const char *orig_control_string = control_string; xbt_log_setting_t set; - if (!*control_string) + if (not*control_string) return set; XBT_DEBUG("Parse log setting '%s'", control_string); control_string += strspn(control_string, " "); - const char *name = control_string; + const char* name = control_string; control_string += strcspn(control_string, ".:= "); - const char *dot = control_string; + const char* option = control_string; control_string += strcspn(control_string, ":= "); - const char *eq = control_string; + const char* value = control_string; - xbt_assert(*dot == '.' || (*eq != '=' && *eq != ':'), "Invalid control string '%s'", orig_control_string); + xbt_assert(*option == '.' && (*value == '=' || *value == ':'), "Invalid control string '%s'", orig_control_string); - if (!strncmp(dot + 1, "threshold", (size_t) (eq - dot - 1))) { - int i; - char *neweq = xbt_strdup(eq + 1); - char *p = neweq - 1; + size_t name_len = option - name; + ++option; + size_t option_len = value - option; + ++value; - while (*(++p) != '\0') { - if (*p >= 'a' && *p <= 'z') { - *p -= 'a' - 'A'; - } - } - - XBT_DEBUG("New priority name = %s", neweq); + if (strncmp(option, "threshold", option_len) == 0) { + XBT_DEBUG("New priority name = %s", value); + int i; for (i = 0; i < xbt_log_priority_infinite; i++) { - if (!strncmp(xbt_log_priority_names[i], neweq, p - eq)) { + if (strcasecmp(value, xbt_log_priority_names[i]) == 0) { XBT_DEBUG("This is priority %d", i); break; } } if(i= 'a' && *p <= 'z') { - *p -= 'a' - 'A'; - } + throw std::invalid_argument(simgrid::xbt::string_printf( + "Unknown priority name: %s (must be one of: trace,debug,verbose,info,warning,error,critical)", value)); } - if (!strcmp(neweq, "ON") || !strcmp(neweq, "YES") || !strcmp(neweq, "1")) { - set.additivity = 1; + } else if (strncmp(option, "additivity", option_len) == 0) { + set.additivity = (strcasecmp(value, "ON") == 0 || strcasecmp(value, "YES") == 0 || strcmp(value, "1") == 0); + } else if (strncmp(option, "appender", option_len) == 0) { + if (strncmp(value, "file:", 5) == 0) { + set.appender = xbt_log_appender_file_new(value + 5); + } else if (strncmp(value, "rollfile:", 9) == 0) { + set.appender = xbt_log_appender2_file_new(value + 9, 1); + } else if (strncmp(value, "splitfile:", 10) == 0) { + set.appender = xbt_log_appender2_file_new(value + 10, 0); + } else if (strcmp(value, "stderr") == 0) { + set.appender = xbt_log_appender_stream(stderr); + } else if (strcmp(value, "stdout") == 0) { + set.appender = xbt_log_appender_stream(stdout); } else { - set.additivity = 0; + throw std::invalid_argument(simgrid::xbt::string_printf("Unknown appender log type: '%s'", value)); } - xbt_free(neweq); - } else if (!strncmp(dot + 1, "app", (size_t) (eq - dot - 1)) || - !strncmp(dot + 1, "appender", (size_t) (eq - dot - 1))) { - char *neweq = xbt_strdup(eq + 1); - - if (!strncmp(neweq, "file:", 5)) { - set.appender = xbt_log_appender_file_new(neweq + 5); - }else if (!strncmp(neweq, "rollfile:", 9)) { - set.appender = xbt_log_appender2_file_new(neweq + 9, 1); - }else if (!strncmp(neweq, "splitfile:", 10)) { - set.appender = xbt_log_appender2_file_new(neweq + 10, 0); - } else { - THROWF(arg_error, 0, "Unknown appender log type: '%s'", neweq); - } - xbt_free(neweq); - } else if (!strncmp(dot + 1, "fmt", (size_t) (eq - dot - 1))) { - set.fmt = std::string(eq + 1); + } else if (strncmp(option, "fmt", option_len) == 0) { + set.fmt = value; } else { - char buff[512]; - snprintf(buff, std::min(512, eq - dot), "%s", dot + 1); - xbt_die("Unknown setting of the log category: '%s'", buff); + xbt_die("Unknown setting of the log category: '%.*s'", static_cast(option_len), option); } - set.catname = std::string(name, dot - name); + set.catname = std::string(name, name_len); XBT_DEBUG("This is for cat '%s'", set.catname.c_str()); @@ -458,18 +410,15 @@ static xbt_log_setting_t _xbt_log_parse_setting(const char *control_string) static xbt_log_category_t _xbt_log_cat_searchsub(xbt_log_category_t cat, const char* name) { - xbt_log_category_t child; - xbt_log_category_t res; - XBT_DEBUG("Search '%s' into '%s' (firstChild='%s'; nextSibling='%s')", name, cat->name, (cat->firstChild ? cat->firstChild->name : "none"), (cat->nextSibling ? cat->nextSibling->name : "none")); if (strcmp(cat->name, name) == 0) return cat; - for (child = cat->firstChild; child != nullptr; child = child->nextSibling) { + for (xbt_log_category_t child = cat->firstChild; child != nullptr; child = child->nextSibling) { XBT_DEBUG("Dig into %s", child->name); - res = _xbt_log_cat_searchsub(child, name); + xbt_log_category_t res = _xbt_log_cat_searchsub(child, name); if (res) return res; } @@ -477,33 +426,9 @@ static xbt_log_category_t _xbt_log_cat_searchsub(xbt_log_category_t cat, const c return nullptr; } -/** - * @ingroup XBT_log - * @param control_string What to parse - * - * Typically passed a command-line argument. The string has the syntax: - * - * ( [category] "." [keyword] ":" value (" ")... )... - * - * where [category] is one the category names (see @ref XBT_log_cats for a complete list of the ones defined in the - * SimGrid library) and keyword is one of the following: - * - * - thres: category's threshold priority. Possible values: - * TRACE,DEBUG,VERBOSE,INFO,WARNING,ERROR,CRITICAL - * - add or additivity: whether the logging actions must be passed to the parent category. - * Possible values: 0, 1, no, yes, on, off. - * Default value: yes. - * - fmt: the format to use. See @ref log_use_conf_fmt for more information. - * - app or appender: the appender to use. See @ref log_use_conf_app for more information. - */ void xbt_log_control_set(const char *control_string) { - /* To split the string in commands, and the cursors */ - xbt_dynar_t set_strings; - char *str; - unsigned int cpt; - - if (!control_string) + if (not control_string) return; XBT_DEBUG("Parse log settings '%s'", control_string); @@ -512,17 +437,16 @@ void xbt_log_control_set(const char *control_string) xbt_log_no_loc = 1; return; } - /* split the string, and remove empty entries */ - set_strings = xbt_str_split_quoted(control_string); - - if (xbt_dynar_is_empty(set_strings)) { /* vicious user! */ - xbt_dynar_free(&set_strings); - return; - } - - /* Parse each entry and either use it right now (if the category was already created), or store it for further use */ - xbt_dynar_foreach(set_strings, cpt, str) { - xbt_log_setting_t set = _xbt_log_parse_setting(str); + /* Split the string, and remove empty entries + Parse each entry and either use it right now (if the category was already created), or store it for further use */ + std::string parsed_control_string(control_string); + boost::escaped_list_separator sep("\\", " ", "\"'"); + boost::tokenizer> tok(parsed_control_string, sep); + for (const auto& str : tok) { + if (str.empty()) + continue; + + xbt_log_setting_t set = _xbt_log_parse_setting(str.c_str()); xbt_log_category_t cat = _xbt_log_cat_searchsub(&_XBT_LOGV(XBT_LOG_ROOT_CAT), set.catname.c_str()); if (cat) { @@ -531,10 +455,9 @@ void xbt_log_control_set(const char *control_string) } else { XBT_DEBUG("Store for further application"); XBT_DEBUG("push %p to the settings", &set); - xbt_log_settings.emplace_back(std::move(set)); + xbt_log_settings().emplace_back(std::move(set)); } } - xbt_dynar_free(&set_strings); } void xbt_log_appender_set(xbt_log_category_t cat, xbt_log_appender_t app) @@ -550,7 +473,7 @@ void xbt_log_appender_set(xbt_log_category_t cat, xbt_log_appender_t app) void xbt_log_layout_set(xbt_log_category_t cat, xbt_log_layout_t lay) { DISABLE_XBT_LOG_CAT_INIT(); - if (!cat->appender) { + if (not cat->appender) { XBT_VERB ("No appender to category %s. Setting the file appender as default", cat->name); xbt_log_appender_set(cat, xbt_log_appender_file_new(nullptr)); } @@ -569,64 +492,72 @@ void xbt_log_additivity_set(xbt_log_category_t cat, int additivity) cat->additivity = additivity; } -static void xbt_log_help(void) +static void xbt_log_help() { - printf("Description of the logging output:\n" - "\n" - " Threshold configuration: --log=CATEGORY_NAME.thres:PRIORITY_LEVEL\n" - " CATEGORY_NAME: defined in code with function 'XBT_LOG_NEW_CATEGORY'\n" - " PRIORITY_LEVEL: the level to print (trace,debug,verbose,info,warning,error,critical)\n" - " -> trace: enter and return of some functions\n" - " -> debug: crufty output\n" - " -> verbose: verbose output for the user wanting more\n" - " -> info: output about the regular functioning\n" - " -> warning: minor issue encountered\n" - " -> error: issue encountered\n" - " -> critical: major issue encountered\n" - " The default priority level is 'info'.\n" - "\n" - " Format configuration: --log=CATEGORY_NAME.fmt:FORMAT\n" - " FORMAT string may contain:\n" - " -> %%%%: the %% char\n" - " -> %%n: platform-dependent line separator (LOG4J compatible)\n" - " -> %%e: plain old space (SimGrid extension)\n" - "\n" - " -> %%m: user-provided message\n" - "\n" - " -> %%c: Category name (LOG4J compatible)\n" - " -> %%p: Priority name (LOG4J compatible)\n" - "\n" - " -> %%h: Hostname (SimGrid extension)\n" - " -> %%P: Process name (SimGrid extension)\n" - " -> %%t: Thread \"name\" (LOG4J compatible -- actually the address of the thread in memory)\n" - " -> %%i: Process PID (SimGrid extension -- this is a 'i' as in 'i'dea)\n" - "\n" - " -> %%F: file name where the log event was raised (LOG4J compatible)\n" - " -> %%l: location where the log event was raised (LOG4J compatible, like '%%F:%%L' -- this is a l as " - "in 'l'etter)\n" - " -> %%L: line number where the log event was raised (LOG4J compatible)\n" - " -> %%M: function name (LOG4J compatible -- called method name here of course).\n" - " Defined only when using gcc because there is no __func__ elsewhere.\n" - "\n" - " -> %%b: full backtrace (Called %%throwable in LOG4J). Defined only under windows or when using the " - "GNU libc because\n" - " backtrace() is not defined elsewhere, and we only have a fallback for windows boxes, not " - "mac ones for example.\n" - " -> %%B: short backtrace (only the first line of the %%b). Called %%throwable{short} in LOG4J; " - "defined where %%b is.\n" - "\n" - " -> %%d: date (UNIX-like epoch)\n" - " -> %%r: application age (time elapsed since the beginning of the application)\n" - "\n" - " Miscellaneous:\n" - " --help-log-categories Display the current hierarchy of log categories.\n" - " --log=no_loc Don't print file names in messages (for tesh tests).\n" - "\n"); + XBT_HELP( + "Description of the logging output:\n" + "\n" + " Threshold configuration: --log=CATEGORY_NAME.thres:PRIORITY_LEVEL\n" + " CATEGORY_NAME: defined in code with function 'XBT_LOG_NEW_CATEGORY'\n" + " PRIORITY_LEVEL: the level to print (trace,debug,verbose,info,warning,error,critical)\n" + " -> trace: enter and return of some functions\n" + " -> debug: crufty output\n" + " -> verbose: verbose output for the user wanting more\n" + " -> info: output about the regular functioning\n" + " -> warning: minor issue encountered\n" + " -> error: issue encountered\n" + " -> critical: major issue encountered\n" + " The default priority level is 'info'.\n" + "\n" + " Format configuration: --log=CATEGORY_NAME.fmt:FORMAT\n" + " FORMAT string may contain:\n" + " -> %%%%: the %% char\n" + " -> %%n: platform-dependent line separator (LOG4J compatible)\n" + " -> %%e: plain old space (SimGrid extension)\n" + "\n" + " -> %%m: user-provided message\n" + "\n" + " -> %%c: Category name (LOG4J compatible)\n" + " -> %%p: Priority name (LOG4J compatible)\n" + "\n" + " -> %%h: Hostname (SimGrid extension)\n" + " -> %%a: Actor name (SimGrid extension)\n" + " -> %%t: Thread \"name\" (LOG4J compatible -- actually the address of the thread in memory)\n" + " -> %%i: Process PID (SimGrid extension -- this is a 'i' as in 'i'dea)\n" + "\n" + " -> %%F: file name where the log event was raised (LOG4J compatible)\n" + " -> %%l: location where the log event was raised (LOG4J compatible, like '%%F:%%L' -- this is a l as " + "in 'l'etter)\n" + " -> %%L: line number where the log event was raised (LOG4J compatible)\n" + " -> %%M: function name (LOG4J compatible -- called method name here of course).\n" + "\n" + " -> %%b: full backtrace (Called %%throwable in LOG4J). Defined only when using the GNU libc because\n" + " backtrace() is not defined elsewhere.\n" + " -> %%B: short backtrace (only the first line of the %%b). Called %%throwable{short} in LOG4J; " + "defined where %%b is.\n" + "\n" + " -> %%d: date (UNIX-like epoch)\n" + " -> %%r: application age (time elapsed since the beginning of the application)\n" + "\n" + " Category appender: --log=CATEGORY_NAME.app:APPENDER\n" + " APPENDER may be:\n" + " -> stdout or stderr: standard output streams\n" + " -> file:NAME: append to file with given name\n" + " -> splitfile:SIZE:NAME: append to files with maximum size SIZE per file.\n" + " NAME may contain the %% wildcard as a placeholder for the file number.\n" + " -> rollfile:SIZE:NAME: append to file with maximum size SIZE.\n" + "\n" + " Category additivity: --log=CATEGORY_NAME.add:VALUE\n" + " VALUE: '0', '1', 'no', 'yes', 'on', or 'off'\n" + "\n" + " Miscellaneous:\n" + " --help-log-categories Display the current hierarchy of log categories.\n" + " --log=no_loc Don't print file names in messages (for tesh tests).\n"); } static void xbt_log_help_categories_rec(xbt_log_category_t category, const std::string& prefix) { - if (!category) + if (not category) return; std::string this_prefix(prefix); @@ -641,19 +572,19 @@ static void xbt_log_help_categories_rec(xbt_log_category_t category, const std:: cats.push_back(cat); std::sort(begin(cats), end(cats), - [](xbt_log_category_t a, xbt_log_category_t b) { return strcmp(a->name, b->name) < 0; }); + [](const s_xbt_log_category_t* a, const s_xbt_log_category_t* b) { return strcmp(a->name, b->name) < 0; }); for (auto const& cat : cats) { - printf("%s%s: %s\n", this_prefix.c_str(), cat->name, cat->description); + XBT_HELP("%s%s: %s", this_prefix.c_str(), cat->name, cat->description); if (cat == cats.back() && category->parent) child_prefix[child_prefix.rfind('|')] = ' '; xbt_log_help_categories_rec(cat->firstChild, child_prefix); } } -static void xbt_log_help_categories(void) +static void xbt_log_help_categories() { - printf("Current log category hierarchy:\n"); + XBT_HELP("Current log category hierarchy:"); xbt_log_help_categories_rec(&_XBT_LOGV(XBT_LOG_ROOT_CAT), " "); - printf("\n"); + XBT_HELP("%s", ""); }