mirror of
https://github.com/ascii-boxes/boxes.git
synced 2025-03-03 16:51:46 +01:00
Add new module 'logging' to handle debug logging
This should be nicer than using the preprocessor.
This commit is contained in:
parent
716348befc
commit
d8e0e7421c
@ -23,11 +23,11 @@ GEN_HDR = parser.h boxes.h lex.yy.h
|
|||||||
GEN_SRC = parser.c lex.yy.c
|
GEN_SRC = parser.c lex.yy.c
|
||||||
GEN_FILES = $(GEN_SRC) $(GEN_HDR)
|
GEN_FILES = $(GEN_SRC) $(GEN_HDR)
|
||||||
ORIG_HDRCL = boxes.in.h config.h
|
ORIG_HDRCL = boxes.in.h config.h
|
||||||
ORIG_HDR = $(ORIG_HDRCL) bxstring.h cmdline.h detect.h discovery.h generate.h input.h list.h parsecode.h parsing.h \
|
ORIG_HDR = $(ORIG_HDRCL) bxstring.h cmdline.h detect.h discovery.h generate.h input.h list.h logging.h parsecode.h \
|
||||||
query.h regulex.h remove.h shape.h tools.h unicode.h
|
parsing.h query.h regulex.h remove.h shape.h tools.h unicode.h
|
||||||
ORIG_GEN = lexer.l parser.y
|
ORIG_GEN = lexer.l parser.y
|
||||||
ORIG_NORM = boxes.c bxstring.c cmdline.c detect.c discovery.c generate.c input.c list.c parsecode.c parsing.c query.c \
|
ORIG_NORM = boxes.c bxstring.c cmdline.c detect.c discovery.c generate.c input.c list.c logging.c parsecode.c \
|
||||||
regulex.c remove.c shape.c tools.c unicode.c
|
parsing.c query.c regulex.c remove.c shape.c tools.c unicode.c
|
||||||
ORIG_SRC = $(ORIG_GEN) $(ORIG_NORM)
|
ORIG_SRC = $(ORIG_GEN) $(ORIG_NORM)
|
||||||
ORIG_FILES = $(ORIG_SRC) $(ORIG_HDR)
|
ORIG_FILES = $(ORIG_SRC) $(ORIG_HDR)
|
||||||
|
|
||||||
@ -116,6 +116,7 @@ generate.o: generate.c generate.h boxes.h shape.h tools.h unicode.h config.h |
|
|||||||
input.o: input.c boxes.h input.h regulex.h tools.h unicode.h config.h | check_dir
|
input.o: input.c boxes.h input.h regulex.h tools.h unicode.h config.h | check_dir
|
||||||
lex.yy.o: lex.yy.c parser.h boxes.h parsing.h tools.h shape.h unicode.h config.h | check_dir
|
lex.yy.o: lex.yy.c parser.h boxes.h parsing.h tools.h shape.h unicode.h config.h | check_dir
|
||||||
list.o: list.c list.h boxes.h bxstring.h parsing.h query.h shape.h tools.h unicode.h config.h | check_dir
|
list.o: list.c list.h boxes.h bxstring.h parsing.h query.h shape.h tools.h unicode.h config.h | check_dir
|
||||||
|
logging.o: logging.c logging.h tools.h config.h | check_dir
|
||||||
parsecode.o: parsecode.c parsecode.h discovery.h lex.yy.h parsing.h parser.h query.h regulex.h shape.h tools.h unicode.h config.h | check_dir
|
parsecode.o: parsecode.c parsecode.h discovery.h lex.yy.h parsing.h parser.h query.h regulex.h shape.h tools.h unicode.h config.h | check_dir
|
||||||
parser.o: parser.c boxes.h bxstring.h lex.yy.h parsecode.h parser.h parsing.h shape.h tools.h unicode.h config.h | check_dir
|
parser.o: parser.c boxes.h bxstring.h lex.yy.h parsecode.h parser.h parsing.h shape.h tools.h unicode.h config.h | check_dir
|
||||||
parsing.o: parsing.c parsing.h bxstring.h parser.h lex.yy.h boxes.h tools.h config.h | check_dir
|
parsing.o: parsing.c parsing.h bxstring.h parser.h lex.yy.h boxes.h tools.h config.h | check_dir
|
||||||
|
@ -143,6 +143,7 @@ typedef struct { /* Command line options: */
|
|||||||
char *eol; /** `-e`: line break to use. Never NULL, default to "\n". */
|
char *eol; /** `-e`: line break to use. Never NULL, default to "\n". */
|
||||||
int eol_overridden; /** `-e`: 0: value in `eol` is the default; 1: value in `eol` specified via `-e` */
|
int eol_overridden; /** `-e`: 0: value in `eol` is the default; 1: value in `eol` specified via `-e` */
|
||||||
char *f; /** `-f`: config file path */
|
char *f; /** `-f`: config file path */
|
||||||
|
int *debug; /** `-g`: activate debug logging for given debug log areas */
|
||||||
int help; /** `-h`: flags if help argument was specified */
|
int help; /** `-h`: flags if help argument was specified */
|
||||||
char indentmode; /** `-i`: 'b', 't', 'n', or '\0' */
|
char indentmode; /** `-i`: 'b', 't', 'n', or '\0' */
|
||||||
int killblank; /** `-k`: kill blank lines, -1 if not set */
|
int killblank; /** `-k`: kill blank lines, -1 if not set */
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "boxes.h"
|
#include "boxes.h"
|
||||||
#include "discovery.h"
|
#include "discovery.h"
|
||||||
|
#include "logging.h"
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "cmdline.h"
|
#include "cmdline.h"
|
||||||
@ -91,6 +92,7 @@ void usage_long(FILE *st)
|
|||||||
strcmp(EOL_DEFAULT, "\r\n") == 0 ? "CRLF" : "LF");
|
strcmp(EOL_DEFAULT, "\r\n") == 0 ? "CRLF" : "LF");
|
||||||
fprintf(st, " -f, --config <file> Configuration file [default: %s]\n",
|
fprintf(st, " -f, --config <file> Configuration file [default: %s]\n",
|
||||||
config_file != NULL ? bxs_to_output(config_file) : "none");
|
config_file != NULL ? bxs_to_output(config_file) : "none");
|
||||||
|
/* fprintf(st, " -g, --debug <areas> Activate debug logging for specified log areas [default area: MAIN]"); // undocumented */
|
||||||
fprintf(st, " -h, --help Print usage information\n");
|
fprintf(st, " -h, --help Print usage information\n");
|
||||||
fprintf(st, " -i, --indent <mode> Indentation mode [default: box]\n");
|
fprintf(st, " -i, --indent <mode> Indentation mode [default: box]\n");
|
||||||
fprintf(st, " -k <bool> Leading/trailing blank line retention on removal\n");
|
fprintf(st, " -k <bool> Leading/trailing blank line retention on removal\n");
|
||||||
@ -121,6 +123,7 @@ static opt_t *create_new_opt()
|
|||||||
result->eol = "\n"; /* we must default to "\n" instead of EOL_DEFAULT as long as stdout is in text mode */
|
result->eol = "\n"; /* we must default to "\n" instead of EOL_DEFAULT as long as stdout is in text mode */
|
||||||
result->tabexp = 'e';
|
result->tabexp = 'e';
|
||||||
result->killblank = -1;
|
result->killblank = -1;
|
||||||
|
result->debug = (int *) calloc(NUM_LOG_AREAS, sizeof(int));
|
||||||
for (int i = 0; i < NUM_SIDES; ++i) {
|
for (int i = 0; i < NUM_SIDES; ++i) {
|
||||||
result->padding[i] = -1;
|
result->padding[i] = -1;
|
||||||
}
|
}
|
||||||
@ -458,6 +461,51 @@ static int size_of_box(opt_t *result, char *optarg)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int debug_areas(opt_t *result, char *optarg)
|
||||||
|
{
|
||||||
|
char *dup = NULL;
|
||||||
|
if (optarg != NULL) {
|
||||||
|
dup = strdup(optarg); /* required because strtok() modifies its input */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dup = strdup(log_area_names[MAIN]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (char *a = strtok(dup, ","); a != NULL; a = strtok(NULL, ","))
|
||||||
|
{
|
||||||
|
char *trimmed = trimdup(a, a + strlen(a) - 1);
|
||||||
|
if (strlen(trimmed) == 0) {
|
||||||
|
BFREE(trimmed);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int valid = 0;
|
||||||
|
for (size_t i = ALL; i < NUM_LOG_AREAS + 2; i++) {
|
||||||
|
if (strcasecmp(trimmed, log_area_names[i]) == 0) {
|
||||||
|
valid = 1;
|
||||||
|
if (i == ALL) {
|
||||||
|
for (size_t i = 0; i < NUM_LOG_AREAS; i++) {
|
||||||
|
result->debug[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result->debug[i - 2] = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!valid) {
|
||||||
|
bx_fprintf(stderr, "%s: invalid debug area -- %s\n", PROJECT, trimmed);
|
||||||
|
BFREE(trimmed);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
BFREE(trimmed);
|
||||||
|
}
|
||||||
|
BFREE(dup);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tab handling. Format is `n[eku]`.
|
* Tab handling. Format is `n[eku]`.
|
||||||
* @param result the options struct we are building
|
* @param result the options struct we are building
|
||||||
@ -644,6 +692,7 @@ opt_t *process_commandline(int argc, char *argv[])
|
|||||||
{ "create", required_argument, NULL, 'c' },
|
{ "create", required_argument, NULL, 'c' },
|
||||||
{ "color", no_argument, NULL, OPT_COLOR },
|
{ "color", no_argument, NULL, OPT_COLOR },
|
||||||
{ "no-color", no_argument, NULL, OPT_NO_COLOR },
|
{ "no-color", no_argument, NULL, OPT_NO_COLOR },
|
||||||
|
{ "debug", optional_argument, NULL, 'g' },
|
||||||
{ "design", required_argument, NULL, 'd' },
|
{ "design", required_argument, NULL, 'd' },
|
||||||
{ "eol", required_argument, NULL, 'e' },
|
{ "eol", required_argument, NULL, 'e' },
|
||||||
{ "config", required_argument, NULL, 'f' },
|
{ "config", required_argument, NULL, 'f' },
|
||||||
@ -662,7 +711,7 @@ opt_t *process_commandline(int argc, char *argv[])
|
|||||||
{ "version", no_argument, NULL, 'v' },
|
{ "version", no_argument, NULL, 'v' },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
const char *short_options = "a:c:d:e:f:hi:k:lmn:p:q:rs:t:v";
|
const char *short_options = "a:c:d:e:f:g::hi:k:lmn:p:q:rs:t:v";
|
||||||
|
|
||||||
int oc; /* option character */
|
int oc; /* option character */
|
||||||
do {
|
do {
|
||||||
@ -710,6 +759,14 @@ opt_t *process_commandline(int argc, char *argv[])
|
|||||||
result->f = strdup(optarg); /* input file */
|
result->f = strdup(optarg); /* input file */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
if (debug_areas(result, optarg) != 0) {
|
||||||
|
BFREE(result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
activate_debug_logging(result->debug);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
result->help = 1;
|
result->help = 1;
|
||||||
return result;
|
return result;
|
||||||
|
154
src/logging.c
Normal file
154
src/logging.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* boxes - Command line filter to draw/remove ASCII boxes around text
|
||||||
|
* Copyright (c) 1999-2023 Thomas Jensen and the boxes contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||||
|
* License, version 3, as published by the Free Software Foundation.
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program.
|
||||||
|
* If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple makeshift log facility for handling debug output.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "regulex.h"
|
||||||
|
#include "tools.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
|
||||||
|
char *log_area_names[] = { "RESERVED", "ALL", "MAIN", "REGEXP", "PARSER", "LEXER", "DISCOVERY" };
|
||||||
|
|
||||||
|
static int debug_logging_active = 0;
|
||||||
|
|
||||||
|
static int *areas_active = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char *shorten_module(const char *module)
|
||||||
|
{
|
||||||
|
if (module == NULL) {
|
||||||
|
return strdup("NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *s = strrchr(module, '/');
|
||||||
|
if (s == NULL) {
|
||||||
|
s = strrchr(module, '\\');
|
||||||
|
}
|
||||||
|
if (s != NULL) {
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s = module;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *e = strrchr(module, '.');
|
||||||
|
if (e != NULL && e > s && *s != '\0') {
|
||||||
|
char *result = strdup(s);
|
||||||
|
result[e-s] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return strdup(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void activate_debug_logging(int *log_areas)
|
||||||
|
{
|
||||||
|
debug_logging_active = 0;
|
||||||
|
|
||||||
|
if (areas_active != NULL) {
|
||||||
|
BFREE(areas_active);
|
||||||
|
}
|
||||||
|
areas_active = (int *) calloc(NUM_LOG_AREAS, sizeof(int));
|
||||||
|
if (log_areas != NULL) {
|
||||||
|
memcpy(areas_active, log_areas, NUM_LOG_AREAS * sizeof(int));
|
||||||
|
debug_logging_active = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int is_area_active(log_area_t log_area)
|
||||||
|
{
|
||||||
|
if (debug_logging_active && areas_active != NULL && log_area != RESERVED && log_area < NUM_LOG_AREAS + 2) {
|
||||||
|
if (log_area == ALL) {
|
||||||
|
for (size_t i = 0; i < NUM_LOG_AREAS; i++) {
|
||||||
|
if (!areas_active[i]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return areas_active[log_area - 2];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int is_debug_logging(log_area_t log_area)
|
||||||
|
{
|
||||||
|
return (debug_logging_active && is_area_active(log_area)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int is_debug_activated()
|
||||||
|
{
|
||||||
|
if (debug_logging_active) {
|
||||||
|
for (size_t i = 0; i < NUM_LOG_AREAS; i++) {
|
||||||
|
if (areas_active[i]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void log_debug(const char *module, log_area_t log_area, const char *format, ...)
|
||||||
|
{
|
||||||
|
if (is_debug_logging(log_area)) {
|
||||||
|
char *msg = (char *) malloc(1024);
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
vsprintf(msg, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
char *short_module = shorten_module(module);
|
||||||
|
bx_fprintf(stderr, "[%-9s] %s", short_module, msg);
|
||||||
|
BFREE(short_module);
|
||||||
|
BFREE(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void log_debug_cont(log_area_t log_area, const char *format, ...)
|
||||||
|
{
|
||||||
|
if (is_debug_logging(log_area)) {
|
||||||
|
char *msg = (char *) malloc(1024);
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
vsprintf(msg, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
bx_fprintf(stderr, "%s", msg);
|
||||||
|
BFREE(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* vim: set cindent sw=4: */
|
101
src/logging.h
Normal file
101
src/logging.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* boxes - Command line filter to draw/remove ASCII boxes around text
|
||||||
|
* Copyright (c) 1999-2023 Thomas Jensen and the boxes contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||||
|
* License, version 3, as published by the Free Software Foundation.
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program.
|
||||||
|
* If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple makeshift log facility for handling debug output.
|
||||||
|
*
|
||||||
|
* Debug output is printed on stderr. Each message is annotated with its module and "area".
|
||||||
|
* The "area" defines certain sections of code as a possible filter criterion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOGGING_H
|
||||||
|
#define LOGGING_H
|
||||||
|
|
||||||
|
|
||||||
|
/** Enum of the log areas supported. `ALL` means all of them, `RESERVED` cannot be used. */
|
||||||
|
typedef enum _log_area_t {
|
||||||
|
/** the 0 value is reserved and must not be used */
|
||||||
|
RESERVED,
|
||||||
|
|
||||||
|
/** all areas */
|
||||||
|
ALL,
|
||||||
|
|
||||||
|
/** the main areas of the code (activate this if unsure) */
|
||||||
|
MAIN,
|
||||||
|
|
||||||
|
/** regular expression handling */
|
||||||
|
REGEXP,
|
||||||
|
|
||||||
|
/** parser code */
|
||||||
|
PARSER,
|
||||||
|
|
||||||
|
/** lexer code */
|
||||||
|
LEXER,
|
||||||
|
|
||||||
|
/** config file discovery */
|
||||||
|
DISCOVERY
|
||||||
|
} log_area_t;
|
||||||
|
|
||||||
|
/** names of the values of `log_area_t` as strings for parsing */
|
||||||
|
extern char *log_area_names[];
|
||||||
|
|
||||||
|
/** number of log areas in `log_area_t`, excluding `ALL` and `RESERVED` */
|
||||||
|
#define NUM_LOG_AREAS 5
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activate debug logging.
|
||||||
|
* @param log_areas an array of log areas to activate, zero-terminated, should not be empty. The value will by copied
|
||||||
|
* and can be freed after returning from the function. Passing NULL will turn off debug logging.
|
||||||
|
*/
|
||||||
|
void activate_debug_logging(int *log_areas);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if debug logging was activated for any debug area.
|
||||||
|
* @return 1 if active, 0 if not
|
||||||
|
*/
|
||||||
|
int is_debug_activated();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if debug logging is active and the given area is active, too.
|
||||||
|
* @param log_area the log area to check
|
||||||
|
* @return 1 if active, 0 if not
|
||||||
|
*/
|
||||||
|
int is_debug_logging(log_area_t log_area);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print a debug log message if the log area is active. Debug log messages will be printed on `stderr`.
|
||||||
|
* @param module the module name as per `__FILE__`
|
||||||
|
* @param log_area_t log_area
|
||||||
|
* @param format format string for the message, followed by the placeholder arguments
|
||||||
|
*/
|
||||||
|
void log_debug(const char *module, log_area_t log_area, const char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print a debug log message if the log area is active. Debug log messages will be printed on `stderr`.
|
||||||
|
* The difference to `log_debug()` is that no module is printed.
|
||||||
|
* @param log_area_t log_area
|
||||||
|
* @param format format string for the message, followed by the placeholder arguments
|
||||||
|
*/
|
||||||
|
void log_debug_cont(log_area_t log_area, const char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vim: set cindent sw=4: */
|
Loading…
Reference in New Issue
Block a user