/* * The Rin Library – diagnostics module * * Copyright (C) 2015 Gediminas Jakutis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include "rin/diagnostic.h" #include "rin/definitions.h" #include "diagnostic_private.h" static struct iostate { FILE *err; FILE *warn; FILE *fixme; FILE *info; unsigned int flags; char pidconv[8]; } state = {NULL, NULL, NULL, NULL, RIN_DIAG_PREFIX, "%08x:"}; int rin_diag_flags(int flag, int action) { /* checking for non-existent flags */ if (flag & ~(RIN_DIAG_ALLFLAGS)) { return EINVAL; } state.flags = action ? (state.flags | flag) : (state.flags & ~(flag)); return 0; } int rin_diag_set_outstream(enum rin_diag_outstream channel, FILE *stream) { if (!stream) { return EINVAL; } switch (channel) { case rin_diag_err: state.err = stream; break; case rin_diag_warn: state.warn = stream; break; case rin_diag_fixme: state.fixme = stream; break; case rin_diag_info: state.info = stream; break; default: return EINVAL; } return 0; } void rin_err(const char *format, ...) { va_list args; va_start(args, format); __rin_msg(state.err ? state.err : stderr, "error", format, args); } void rin_warn(const char *format, ...) { va_list args; va_start(args, format); __rin_msg(state.warn ? state.warn : stderr, "warning", format, args); } void rin_fixme(const char *format, ...) { va_list args; va_start(args, format); __rin_msg(state.fixme ? state.fixme : stderr, "fixme", format, args); } void rin_info(const char *format, ...) { va_list args; va_start(args, format); __rin_msg(state.info ? state.info : stdout, "info", format, args); } static void __rin_msg(FILE *stream, const char *prefix, const char *format, va_list args) { rin_once(__rin_pidconvadjust()); if (state.flags & RIN_DIAG_PREFIX) { fprintf(stream, "%s:", prefix); } if (state.flags & RIN_DIAG_THREADNUM) { fprintf(stream, state.pidconv, gettid()); } if (state.flags & RIN_DIAG_TIME) { struct timespec t; clock_gettime(CLOCK_REALTIME, &t); fprintf(stream, "%lu.%lu:", t.tv_sec, t.tv_nsec); } vfprintf(stream, format, args); } static void __rin_pidconvadjust(void) { if (sizeof(pid_t) == 4) { const char convstr[8] = "%04hx:"; memcpy(state.pidconv, convstr, sizeof(convstr)); } }