/******************************************************************************* * * MODULE: cterror.c * ******************************************************************************** * * DESCRIPTION: Error reporting for the ctlib * ******************************************************************************** * * Copyright (c) 2002-2024 Marcus Holland-Moritz. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the same terms as Perl itself. * *******************************************************************************/ /*===== GLOBAL INCLUDES ======================================================*/ #include #include #include #include /*===== LOCAL INCLUDES =======================================================*/ #include "cterror.h" #include "util/memalloc.h" #include "ucpp/cpp.h" #include "ucpp/mem.h" #include "cppreent.h" /*===== DEFINES ==============================================================*/ #define INIT_CHECK \ do { \ if (!initialized) \ { \ fprintf(stderr, "FATAL: print functions have not been set!\n"); \ abort(); \ } \ } while(0) /*===== TYPEDEFS =============================================================*/ /*===== STATIC FUNCTION PROTOTYPES ===========================================*/ static CTLibError *error_new(enum CTErrorSeverity severity, void *str); static void error_delete(CTLibError *error); static void push_str(CParseInfo *pCPI, enum CTErrorSeverity severity, void *str); static void push_verror(CParseInfo *pCPI, enum CTErrorSeverity severity, const char *fmt, va_list *pap); /*===== EXTERNAL VARIABLES ===================================================*/ /*===== GLOBAL VARIABLES =====================================================*/ /*===== STATIC VARIABLES =====================================================*/ static int initialized = 0; static PrintFunctions F; /*===== STATIC FUNCTIONS =====================================================*/ /******************************************************************************* * * ROUTINE: error_new * * WRITTEN BY: Marcus Holland-Moritz ON: Nov 2003 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ static CTLibError *error_new(enum CTErrorSeverity severity, void *str) { CTLibError *perr; const char *string; size_t len; string = F.cstring(str, &len); AllocF(CTLibError *, perr, sizeof(CTLibError)); AllocF(char *, perr->string, len + 1); perr->severity = severity; strncpy(perr->string, string, len); perr->string[len] = '\0'; return perr; } /******************************************************************************* * * ROUTINE: error_delete * * WRITTEN BY: Marcus Holland-Moritz ON: Nov 2003 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ static void error_delete(CTLibError *error) { if (error) { if (error->string) Free(error->string); Free(error); } } /******************************************************************************* * * ROUTINE: push_str * * WRITTEN BY: Marcus Holland-Moritz ON: Nov 2003 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ static void push_str(CParseInfo *pCPI, enum CTErrorSeverity severity, void *str) { if (pCPI == NULL || pCPI->errorStack == NULL) F.fatalerr(str); LL_push(pCPI->errorStack, error_new(severity, str)); } /******************************************************************************* * * ROUTINE: push_verror * * WRITTEN BY: Marcus Holland-Moritz ON: Nov 2003 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ static void push_verror(CParseInfo *pCPI, enum CTErrorSeverity severity, const char *fmt, va_list *pap) { void *str = F.newstr(); F.vscatf(str, fmt, pap); push_str(pCPI, severity, str); F.destroy(str); } /*===== FUNCTIONS ============================================================*/ /******************************************************************************* * * ROUTINE: set_print_functions * * WRITTEN BY: Marcus Holland-Moritz ON: Mar 2002 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ void set_print_functions(PrintFunctions *pPF) { if (pPF->newstr == NULL || pPF->destroy == NULL || pPF->scatf == NULL || pPF->vscatf == NULL || pPF->cstring == NULL || pPF->fatalerr == NULL) { fprintf(stderr, "FATAL: all print functions must be set!\n"); abort(); } F = *pPF; initialized = 1; } /******************************************************************************* * * ROUTINE: pop_all_errors * * WRITTEN BY: Marcus Holland-Moritz ON: Nov 2003 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ void pop_all_errors(CParseInfo *pCPI) { LL_flush(pCPI->errorStack, (LLDestroyFunc) error_delete); } /******************************************************************************* * * ROUTINE: push_error * * WRITTEN BY: Marcus Holland-Moritz ON: Nov 2003 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ void push_error(CParseInfo *pCPI, const char *fmt, ...) { va_list ap; INIT_CHECK; va_start(ap, fmt); push_verror(pCPI, CTES_ERROR, fmt, &ap); va_end(ap); } /******************************************************************************* * * ROUTINE: push_warning * * WRITTEN BY: Marcus Holland-Moritz ON: Nov 2003 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ void push_warning(CParseInfo *pCPI, const char *fmt, ...) { va_list ap; INIT_CHECK; va_start(ap, fmt); push_verror(pCPI, CTES_WARNING, fmt, &ap); va_end(ap); } /******************************************************************************* * * ROUTINE: fatal_error * * WRITTEN BY: Marcus Holland-Moritz ON: Nov 2003 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ void fatal_error(const char *fmt, ...) { va_list ap; void *str; INIT_CHECK; va_start(ap, fmt); str = F.newstr(); F.vscatf(str, fmt, &ap); va_end(ap); F.fatalerr(str); } /******************************************************************************* * * ROUTINE: my_ucpp_ouch * * WRITTEN BY: Marcus Holland-Moritz ON: Mar 2002 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ void my_ucpp_ouch(pUCPP_ char *fmt, ...) { va_list ap; void *str; INIT_CHECK; va_start(ap, fmt); str = F.newstr(); F.scatf(str, "%s: (FATAL) ", r_current_filename); F.vscatf(str, fmt, &ap); va_end(ap); F.fatalerr(str); } /******************************************************************************* * * ROUTINE: my_ucpp_error * * WRITTEN BY: Marcus Holland-Moritz ON: Mar 2002 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ void my_ucpp_error(pUCPP_ long line, char *fmt, ...) { va_list ap; void *str; INIT_CHECK; va_start(ap, fmt); str = F.newstr(); if (line > 0) F.scatf(str, "%s, line %ld: ", r_current_filename, line); else if (line == 0) F.scatf(str, "%s: ", r_current_filename); F.vscatf(str, fmt, &ap); if (line >= 0) { struct stack_context *sc = report_context(aUCPP); size_t i; for (i = 0; sc[i].line >= 0; i++) F.scatf(str, "\n\tincluded from %s:%ld", sc[i].long_name ? sc[i].long_name : sc[i].name, sc[i].line); freemem(sc); } va_end(ap); push_str(r_callback_arg, CTES_ERROR, str); F.destroy(str); } /******************************************************************************* * * ROUTINE: my_ucpp_warning * * WRITTEN BY: Marcus Holland-Moritz ON: Mar 2002 * CHANGED BY: ON: * ******************************************************************************** * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * *******************************************************************************/ void my_ucpp_warning(pUCPP_ long line, char *fmt, ...) { va_list ap; void *str; INIT_CHECK; va_start(ap, fmt); str = F.newstr(); if (line > 0) F.scatf(str, "%s, line %ld: (warning) ", r_current_filename, line); else if (line == 0) F.scatf(str, "%s: (warning) ", r_current_filename); else F.scatf(str, "(warning) "); F.vscatf(str, fmt, &ap); if (line >= 0) { struct stack_context *sc = report_context(aUCPP); size_t i; for (i = 0; sc[i].line >= 0; i++) F.scatf(str, "\n\tincluded from %s:%ld", sc[i].long_name ? sc[i].long_name : sc[i].name, sc[i].line); freemem(sc); } va_end(ap); push_str(r_callback_arg, CTES_WARNING, str); F.destroy(str); }