libyang REFACTOR simplify logging and extend location information
Simplify logger interface by using location information maintained in
the background. logger now prints all the available information: schema
path, data path and line numbers. However, the line number are quite
inaccurate (e.g. points to XML closing parent element) and some future
tuning would be great.
diff --git a/src/log.c b/src/log.c
index 640c8ff..7498c74 100644
--- a/src/log.c
+++ b/src/log.c
@@ -499,57 +499,73 @@
}
static LY_ERR
-ly_vlog_build_path(const struct ly_ctx *ctx, enum LY_VLOG_ELEM elem_type, const void *elem, char **path)
+ly_vlog_build_path(const struct ly_ctx *ctx, struct ly_log_location_s *location, char **path)
{
int rc;
+ char *str = NULL, *prev = NULL;
+ *path = NULL;
- switch (elem_type) {
- case LY_VLOG_STR:
- *path = strdup(elem);
+ if (location->paths.count && ((const char *)(location->paths.objs[location->paths.count - 1]))[0]) {
+ /* simply get what is in the provided path string */
+ *path = strdup((const char *)location->paths.objs[location->paths.count - 1]);
LY_CHECK_ERR_RET(!(*path), LOGMEM(ctx), LY_EMEM);
- break;
- case LY_VLOG_LINE:
- rc = asprintf(path, "Line number %" PRIu64 ".", *((uint64_t *)elem));
- LY_CHECK_ERR_RET(rc == -1, LOGMEM(ctx), LY_EMEM);
- break;
- case LY_VLOG_LYSC:
- *path = lysc_path(elem, LYSC_PATH_LOG, NULL, 0);
- LY_CHECK_ERR_RET(!(*path), LOGMEM(ctx), LY_EMEM);
- break;
- case LY_VLOG_LYD:
- *path = lyd_path(elem, LYD_PATH_STD, NULL, 0);
- LY_CHECK_ERR_RET(!(*path), LOGMEM(ctx), LY_EMEM);
- break;
- default:
- /* shouldn't be here */
- LOGINT_RET(ctx);
+ } else {
+ /* generate location string */
+ if (location->scnodes.count) {
+ str = lysc_path(location->scnodes.objs[location->scnodes.count - 1], LYSC_PATH_LOG, NULL, 0);
+ LY_CHECK_ERR_RET(!str, LOGMEM(ctx), LY_EMEM);
+
+ rc = asprintf(path, "Schema location %s", str);
+ free(str);
+ LY_CHECK_ERR_RET(rc == -1, LOGMEM(ctx), LY_EMEM);
+ }
+ if (location->dnodes.count) {
+ prev = *path;
+ str = lyd_path(location->dnodes.objs[location->dnodes.count - 1], LYD_PATH_STD, NULL, 0);
+ LY_CHECK_ERR_RET(!str, LOGMEM(ctx), LY_EMEM);
+
+ rc = asprintf(path, "%s%sata location %s", prev ? prev : "", prev ? ", d" : "D", str);
+ free(str);
+ free(prev);
+ LY_CHECK_ERR_RET(rc == -1, LOGMEM(ctx), LY_EMEM);
+ }
+ if (location->line) {
+ prev = *path;
+ rc = asprintf(path, "%s%sine number %" PRIu64, prev ? prev : "", prev ? ", l" : "L", location->line);
+ free(prev);
+ LY_CHECK_ERR_RET(rc == -1, LOGMEM(ctx), LY_EMEM);
+
+ location->line = 0;
+ } else if (location->inputs.count) {
+ prev = *path;
+ rc = asprintf(path, "%s%sine number %" PRIu64, prev ? prev : "", prev ? ", l" : "L",
+ ((struct ly_in *)location->inputs.objs[location->inputs.count - 1])->line);
+ free(prev);
+ LY_CHECK_ERR_RET(rc == -1, LOGMEM(ctx), LY_EMEM);
+ }
+
+ if (*path) {
+ prev = *path;
+ rc = asprintf(path, "%s.", prev);
+ free(prev);
+ LY_CHECK_ERR_RET(rc == -1, LOGMEM(ctx), LY_EMEM);
+ }
}
return LY_SUCCESS;
}
void
-ly_vlog(const struct ly_ctx *ctx, enum LY_VLOG_ELEM elem_type, const void *elem, LY_VECODE code, const char *format, ...)
+ly_vlog(const struct ly_ctx *ctx, LY_VECODE code, const char *format, ...)
{
va_list ap;
char *path = NULL;
- const struct ly_err_item *first;
- if (path_flag && (elem_type != LY_VLOG_NONE)) {
- if (elem_type == LY_VLOG_PREV) {
- /* use previous path */
- first = ly_err_first(ctx);
- if (first && first->prev->path) {
- path = strdup(first->prev->path);
- }
- } else {
- /* print path */
- if (!elem) {
- /* top-level */
- path = strdup("/");
- } else {
- ly_vlog_build_path(ctx, elem_type, elem, &path);
- }
+ if (path_flag && ctx) {
+ /* get the location information */
+ struct ly_log_location_s *location = pthread_getspecific(ctx->log_location_key);
+ if (location) {
+ ly_vlog_build_path(ctx, location, &path);
}
}