/* * fy-diag.h - diagnostics * * Copyright (c) 2019 Pantelis Antoniou <pantelis.antoniou@konsulko.com> * * SPDX-License-Identifier: MIT */ #ifndef FY_DIAG_H #define FY_DIAG_H #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <stdint.h> #include <stdbool.h> #include <stdio.h> #include <stdarg.h> #include <libfyaml.h> #include "fy-list.h" #include "fy-token.h" #if !defined(NDEBUG) && defined(HAVE_DEVMODE) && HAVE_DEVMODE #define FY_DEVMODE #else #undef FY_DEVMODE #endif /* error flags (above 0x100 is library specific) */ #define FYEF_SOURCE 0x0001 #define FYEF_POSITION 0x0002 #define FYEF_TYPE 0x0004 #define FYEF_USERSTART 0x0100 #define FYDF_LEVEL_SHIFT 0 #define FYDF_LEVEL_MASK (0x0f << FYDF_LEVEL_SHIFT) #define FYDF_LEVEL(x) (((unsigned int)(x) << FYDF_LEVEL_SHIFT) & FYDF_LEVEL_MASK) #define FYDF_DEBUG FYDF_LEVEL(FYET_DEBUG) #define FYDF_INFO FYDF_LEVEL(FYET_INFO) #define FYDF_NOTICE FYDF_LEVEL(FYET_NOTICE) #define FYDF_WARNING FYDF_LEVEL(FYET_WARNING) #define FYDF_ERROR FYDF_LEVEL(FYET_ERROR) #define FYDF_MODULE_SHIFT 4 #define FYDF_MODULE_MASK (0x0f << FYDF_MODULE_SHIFT) #define FYDF_MODULE(x) (((unsigned int)(x) << FYDF_MODULE_SHIFT) & FYDF_MODULE_MASK) #define FYDF_ATOM FYDF_MODULE(FYEM_ATOM) #define FYDF_SCANNER FYDF_MODULE(FYEM_SCANNER) #define FYDF_PARSER FYDF_MODULE(FYEM_PARSER) #define FYDF_TREE FYDF_MODULE(FYEM_TREE) #define FYDF_BUILDER FYDF_MODULE(FYEM_BUILDER) #define FYDF_INTERNAL FYDF_MODULE(FYEM_INTERNAL) #define FYDF_SYSTEM FYDF_MODULE(FYEM_SYSTEM) #define FYDF_MODULE_USER_MASK 7 #define FYDF_MODULE_USER(x) FYDF_MODULE(8 + ((x) & FYDF_MODULE_USER_MASK)) struct fy_diag_term_info { int rows; int columns; }; struct fy_diag_report_ctx { enum fy_error_type type; enum fy_error_module module; struct fy_token *fyt; bool has_override; const char *override_file; int override_line; int override_column; }; FY_TYPE_FWD_DECL_LIST(diag_errorp); struct fy_diag_errorp { struct fy_list_head node; char *space; struct fy_diag_error e; }; FY_TYPE_DECL_LIST(diag_errorp); struct fy_diag { struct fy_diag_cfg cfg; int refs; bool on_error : 1; bool destroyed : 1; bool collect_errors : 1; bool terminal_probed : 1; struct fy_diag_term_info term_info; struct fy_diag_errorp_list errors; }; void fy_diag_free(struct fy_diag *diag); void fy_diag_vreport(struct fy_diag *diag, const struct fy_diag_report_ctx *fydrc, const char *fmt, va_list ap); void fy_diag_report(struct fy_diag *diag, const struct fy_diag_report_ctx *fydrc, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 3, 4)); #ifdef FY_DEVMODE #define __FY_DEBUG_UNUSED__ /* nothing */ #else #define __FY_DEBUG_UNUSED__ FY_ATTRIBUTE(__unused__) #endif /* parser diagnostics */ struct fy_parser; void fy_diag_cfg_from_parser_flags(struct fy_diag_cfg *cfg, enum fy_parse_cfg_flags pflags); int fy_parser_vdiag(struct fy_parser *fyp, unsigned int flags, const char *file, int line, const char *func, const char *fmt, va_list ap); int fy_parser_diag(struct fy_parser *fyp, unsigned int flags, const char *file, int line, const char *func, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 6, 7)); void fy_diag_error_atom_display(struct fy_diag *diag, enum fy_error_type type, struct fy_atom *atom); void fy_diag_error_token_display(struct fy_diag *diag, enum fy_error_type type, struct fy_token *fyt); void fy_parser_diag_vreport(struct fy_parser *fyp, const struct fy_diag_report_ctx *fydrc, const char *fmt, va_list ap); void fy_parser_diag_report(struct fy_parser *fyp, const struct fy_diag_report_ctx *fydrc, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 3, 4)); #ifdef FY_DEVMODE #define fyp_debug(_fyp, _module, _fmt, ...) \ fy_parser_diag((_fyp), FYET_DEBUG | FYDF_MODULE(_module), \ __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #else #define fyp_debug(_fyp, _module, _fmt, ...) \ do { } while(0) #endif #define fyp_info(_fyp, _fmt, ...) \ fy_parser_diag((_fyp), FYET_INFO, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyp_notice(_fyp, _fmt, ...) \ fy_parser_diag((_fyp), FYET_NOTICE, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyp_warning(_fyp, _fmt, ...) \ fy_parser_diag((_fyp), FYET_WARNING, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyp_error(_fyp, _fmt, ...) \ fy_parser_diag((_fyp), FYET_ERROR, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyp_scan_debug(_fyp, _fmt, ...) \ fyp_debug((_fyp), FYEM_SCAN, (_fmt) , ## __VA_ARGS__) #define fyp_parse_debug(_fyp, _fmt, ...) \ fyp_debug((_fyp), FYEM_PARSE, (_fmt) , ## __VA_ARGS__) #define fyp_doc_debug(_fyp, _fmt, ...) \ fyp_debug((_fyp), FYEM_DOC, (_fmt) , ## __VA_ARGS__) #define fyp_error_check(_fyp, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ fyp_error((_fyp), _fmt, ## __VA_ARGS__); \ goto _label ; \ } \ } while(0) #define _FYP_TOKEN_DIAG(_fyp, _fyt, _type, _module, _fmt, ...) \ do { \ struct fy_diag_report_ctx _drc; \ memset(&_drc, 0, sizeof(_drc)); \ _drc.type = (_type); \ _drc.module = (_module); \ _drc.fyt = (_fyt); \ fy_parser_diag_report((_fyp), &_drc, (_fmt) , ## __VA_ARGS__); \ } while(0) #define FYP_TOKEN_DIAG(_fyp, _fyt, _type, _module, _fmt, ...) \ _FYP_TOKEN_DIAG(_fyp, fy_token_ref(_fyt), _type, _module, _fmt, ## __VA_ARGS__) #define FYP_PARSE_DIAG(_fyp, _adv, _cnt, _type, _module, _fmt, ...) \ _FYP_TOKEN_DIAG(_fyp, \ fy_token_create(FYTT_INPUT_MARKER, \ fy_fill_atom_at((_fyp), (_adv), (_cnt), \ FY_ALLOCA(sizeof(struct fy_atom)))), \ _type, _module, _fmt, ## __VA_ARGS__) #define FYP_MARK_DIAG(_fyp, _sm, _em, _type, _module, _fmt, ...) \ _FYP_TOKEN_DIAG(_fyp, \ fy_token_create(FYTT_INPUT_MARKER, \ fy_fill_atom_mark(((_fyp)), (_sm), (_em), \ FY_ALLOCA(sizeof(struct fy_atom)))), \ _type, _module, _fmt, ## __VA_ARGS__) #define FYP_NODE_DIAG(_fyp, _fyn, _type, _module, _fmt, ...) \ _FYP_TOKEN_DIAG(_fyp, fy_node_token(_fyn), _type, _module, _fmt, ## __VA_ARGS__) #define FYP_TOKEN_ERROR(_fyp, _fyt, _module, _fmt, ...) \ FYP_TOKEN_DIAG(_fyp, _fyt, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYP_PARSE_ERROR(_fyp, _adv, _cnt, _module, _fmt, ...) \ FYP_PARSE_DIAG(_fyp, _adv, _cnt, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYP_MARK_ERROR(_fyp, _sm, _em, _module, _fmt, ...) \ FYP_MARK_DIAG(_fyp, _sm, _em, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYP_NODE_ERROR(_fyp, _fyn, _module, _fmt, ...) \ FYP_NODE_DIAG(_fyp, _fyn, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYP_TOKEN_ERROR_CHECK(_fyp, _fyt, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYP_TOKEN_ERROR(_fyp, _fyt, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYP_PARSE_ERROR_CHECK(_fyp, _adv, _cnt, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYP_PARSE_ERROR(_fyp, _adv, _cnt, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYP_MARK_ERROR_CHECK(_fyp, _sm, _em, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYP_MARK_ERROR(_fyp, _sm, _em, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYP_NODE_ERROR_CHECK(_fyp, _fyn, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYP_NODE_ERROR(_fyp, _fyn, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYP_TOKEN_WARNING(_fyp, _fyt, _module, _fmt, ...) \ FYP_TOKEN_DIAG(_fyp, _fyt, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) #define FYP_PARSE_WARNING(_fyp, _adv, _cnt, _module, _fmt, ...) \ FYP_PARSE_DIAG(_fyp, _adv, _cnt, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) #define FYP_MARK_WARNING(_fyp, _sm, _em, _module, _fmt, ...) \ FYP_MARK_DIAG(_fyp, _sm, _em, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) #define FYP_NODE_WARNING(_fyp, _fyn, _type, _module, _fmt, ...) \ FYP_NODE_DIAG(_fyp, _fyn, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) /* reader diagnostics */ struct fy_reader; int fy_reader_vdiag(struct fy_reader *fyr, unsigned int flags, const char *file, int line, const char *func, const char *fmt, va_list ap); int fy_reader_diag(struct fy_reader *fyr, unsigned int flags, const char *file, int line, const char *func, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 6, 7)); void fy_reader_diag_vreport(struct fy_reader *fyr, const struct fy_diag_report_ctx *fydrc, const char *fmt, va_list ap); void fy_reader_diag_report(struct fy_reader *fyr, const struct fy_diag_report_ctx *fydrc, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 3, 4)); #ifdef FY_DEVMODE #define fyr_debug(_fyr, _fmt, ...) \ fy_reader_diag((_fyr), FYET_DEBUG, \ __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #else #define fyr_debug(_fyr, _fmt, ...) \ do { } while(0) #endif #define fyr_info(_fyr, _fmt, ...) \ fy_reader_diag((_fyr), FYET_INFO, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyr_notice(_fyr, _fmt, ...) \ fy_reader_diag((_fyr), FYET_NOTICE, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyr_warning(_fyr, _fmt, ...) \ fy_reader_diag((_fyr), FYET_WARNING, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyr_error(_fyr, _fmt, ...) \ fy_reader_diag((_fyr), FYET_ERROR, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyr_error_check(_fyr, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ fyr_error((_fyr), _fmt, ## __VA_ARGS__); \ goto _label ; \ } \ } while(0) #define _FYR_TOKEN_DIAG(_fyr, _fyt, _type, _module, _fmt, ...) \ do { \ struct fy_diag_report_ctx _drc; \ memset(&_drc, 0, sizeof(_drc)); \ _drc.type = (_type); \ _drc.module = (_module); \ _drc.fyt = (_fyt); \ fy_reader_diag_report((_fyr), &_drc, (_fmt) , ## __VA_ARGS__); \ } while(0) #define FYR_TOKEN_DIAG(_fyr, _fyt, _type, _module, _fmt, ...) \ _FYR_TOKEN_DIAG(_fyr, fy_token_ref(_fyt), _type, _module, _fmt, ## __VA_ARGS__) #define FYR_PARSE_DIAG(_fyr, _adv, _cnt, _type, _module, _fmt, ...) \ _FYR_TOKEN_DIAG(_fyr, \ fy_token_create(FYTT_INPUT_MARKER, \ fy_reader_fill_atom_at((_fyr), (_adv), (_cnt), \ FY_ALLOCA(sizeof(struct fy_atom)))), \ _type, _module, _fmt, ## __VA_ARGS__) #define FYR_MARK_DIAG(_fyr, _sm, _em, _type, _module, _fmt, ...) \ _FYR_TOKEN_DIAG(_fyr, \ fy_token_create(FYTT_INPUT_MARKER, \ fy_reader_fill_atom_mark(((_fyr)), (_sm), (_em), \ FY_ALLOCA(sizeof(struct fy_atom)))), \ _type, _module, _fmt, ## __VA_ARGS__) #define FYR_NODE_DIAG(_fyr, _fyn, _type, _module, _fmt, ...) \ _FYR_TOKEN_DIAG(_fyr, fy_node_token(_fyn), _type, _module, _fmt, ## __VA_ARGS__) #define FYR_TOKEN_ERROR(_fyr, _fyt, _module, _fmt, ...) \ FYR_TOKEN_DIAG(_fyr, _fyt, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYR_PARSE_ERROR(_fyr, _adv, _cnt, _module, _fmt, ...) \ FYR_PARSE_DIAG(_fyr, _adv, _cnt, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYR_MARK_ERROR(_fyr, _sm, _em, _module, _fmt, ...) \ FYR_MARK_DIAG(_fyr, _sm, _em, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYR_NODE_ERROR(_fyr, _fyn, _module, _fmt, ...) \ FYR_NODE_DIAG(_fyr, _fyn, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYR_TOKEN_ERROR_CHECK(_fyr, _fyt, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYR_TOKEN_ERROR(_fyr, _fyt, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYR_PARSE_ERROR_CHECK(_fyr, _adv, _cnt, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYR_PARSE_ERROR(_fyr, _adv, _cnt, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYR_MARK_ERROR_CHECK(_fyr, _sm, _em, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYR_MARK_ERROR(_fyr, _sm, _em, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYR_NODE_ERROR_CHECK(_fyr, _fyn, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYR_NODE_ERROR(_fyr, _fyn, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYR_TOKEN_WARNING(_fyr, _fyt, _module, _fmt, ...) \ FYR_TOKEN_DIAG(_fyr, _fyt, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) #define FYR_PARSE_WARNING(_fyr, _adv, _cnt, _module, _fmt, ...) \ FYR_PARSE_DIAG(_fyr, _adv, _cnt, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) #define FYR_MARK_WARNING(_fyr, _sm, _em, _module, _fmt, ...) \ FYR_MARK_DIAG(_fyr, _sm, _em, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) #define FYR_NODE_WARNING(_fyr, _fyn, _type, _module, _fmt, ...) \ FYR_NODE_DIAG(_fyr, _fyn, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) /* doc */ struct fy_document; int fy_document_vdiag(struct fy_document *fyd, unsigned int flags, const char *file, int line, const char *func, const char *fmt, va_list ap); int fy_document_diag(struct fy_document *fyd, unsigned int flags, const char *file, int line, const char *func, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 6, 7)); void fy_document_diag_vreport(struct fy_document *fyd, const struct fy_diag_report_ctx *fydrc, const char *fmt, va_list ap); void fy_document_diag_report(struct fy_document *fyd, const struct fy_diag_report_ctx *fydrc, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 3, 4)); #ifdef FY_DEVMODE #define fyd_debug(_fyd, _module, _fmt, ...) \ fy_document_diag((_fyd), FYET_DEBUG | FYDF_MODULE(_module), \ __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #else #define fyd_debug(_fyd, _module, _fmt, ...) \ do { } while(0) #endif #define fyd_info(_fyd, _fmt, ...) \ fy_document_diag((_fyd), FYET_INFO, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyd_notice(_fyd, _fmt, ...) \ fy_document_diag((_fyd), FYET_NOTICE, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyd_warning(_fyd, _fmt, ...) \ fy_document_diag((_fyd), FYET_WARNING, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyd_error(_fyd, _fmt, ...) \ fy_document_diag((_fyd), FYET_ERROR, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyd_doc_debug(_fyd, _fmt, ...) \ fyd_debug((_fyd), FYEM_DOC, (_fmt) , ## __VA_ARGS__) #define fyd_error_check(_fyd, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ fyd_error((_fyd), _fmt, ## __VA_ARGS__); \ goto _label ; \ } \ } while(0) #define _FYD_TOKEN_DIAG(_fyd, _fyt, _type, _module, _fmt, ...) \ do { \ struct fy_diag_report_ctx _drc; \ memset(&_drc, 0, sizeof(_drc)); \ _drc.type = (_type); \ _drc.module = (_module); \ _drc.fyt = (_fyt); \ fy_document_diag_report((_fyd), &_drc, (_fmt) , ## __VA_ARGS__); \ } while(0) #define FYD_TOKEN_DIAG(_fyd, _fyt, _type, _module, _fmt, ...) \ _FYD_TOKEN_DIAG(_fyd, fy_token_ref(_fyt), _type, _module, _fmt, ## __VA_ARGS__) #define FYD_NODE_DIAG(_fyd, _fyn, _type, _module, _fmt, ...) \ _FYD_TOKEN_DIAG(_fyd, fy_node_token(_fyn), _type, _module, _fmt, ## __VA_ARGS__) #define FYD_TOKEN_ERROR(_fyd, _fyt, _module, _fmt, ...) \ FYD_TOKEN_DIAG(_fyd, _fyt, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYD_NODE_ERROR(_fyd, _fyn, _module, _fmt, ...) \ FYD_NODE_DIAG(_fyd, _fyn, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYD_TOKEN_ERROR_CHECK(_fyd, _fyt, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYD_TOKEN_ERROR(_fyd, _fyt, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYD_NODE_ERROR_CHECK(_fyd, _fyn, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYD_NODE_ERROR(_fyd, _fyn, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYD_TOKEN_WARNING(_fyd, _fyt, _module, _fmt, ...) \ FYD_TOKEN_DIAG(_fyd, _fyt, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) #define FYD_NODE_WARNING(_fyd, _fyn, _type, _module, _fmt, ...) \ FYD_NODE_DIAG(_fyd, _fyn, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) /* composer */ struct fy_composer; int fy_composer_vdiag(struct fy_composer *fyc, unsigned int flags, const char *file, int line, const char *func, const char *fmt, va_list ap); int fy_composer_diag(struct fy_composer *fyc, unsigned int flags, const char *file, int line, const char *func, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 6, 7)); void fy_composer_diag_vreport(struct fy_composer *fyc, const struct fy_diag_report_ctx *fydrc, const char *fmt, va_list ap); void fy_composer_diag_report(struct fy_composer *fyc, const struct fy_diag_report_ctx *fydrc, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 3, 4)); #ifdef FY_DEVMODE #define fyc_debug(_fyc, _module, _fmt, ...) \ fy_composer_diag((_fyc), FYET_DEBUG | FYDF_MODULE(_module), \ __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #else #define fyc_debug(_fyc, _module, _fmt, ...) \ do { } while(0) #endif #define fyc_info(_fyc, _fmt, ...) \ fy_composer_diag((_fyc), FYET_INFO, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyc_notice(_fyc, _fmt, ...) \ fy_composer_diag((_fyc), FYET_NOTICE, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyc_warning(_fyc, _fmt, ...) \ fy_composer_diag((_fyc), FYET_WARNING, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyc_error(_fyc, _fmt, ...) \ fy_composer_diag((_fyc), FYET_ERROR, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fyc_error_check(_fyc, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ fyc_error((_fyc), _fmt, ## __VA_ARGS__); \ goto _label ; \ } \ } while(0) #define _FYC_TOKEN_DIAG(_fyc, _fyt, _type, _module, _fmt, ...) \ do { \ struct fy_diag_report_ctx _drc; \ memset(&_drc, 0, sizeof(_drc)); \ _drc.type = (_type); \ _drc.module = (_module); \ _drc.fyt = (_fyt); \ fy_composer_diag_report((_fyc), &_drc, (_fmt) , ## __VA_ARGS__); \ } while(0) #define FYC_TOKEN_DIAG(_fyc, _fyt, _type, _module, _fmt, ...) \ _FYC_TOKEN_DIAG(_fyc, fy_token_ref(_fyt), _type, _module, _fmt, ## __VA_ARGS__) #define FYC_NODE_DIAG(_fyc, _fyn, _type, _module, _fmt, ...) \ _FYC_TOKEN_DIAG(_fyc, fy_node_token(_fyn), _type, _module, _fmt, ## __VA_ARGS__) #define FYC_TOKEN_ERROR(_fyc, _fyt, _module, _fmt, ...) \ FYC_TOKEN_DIAG(_fyc, _fyt, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYC_TOKEN_ERROR_CHECK(_fyc, _fyt, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYC_TOKEN_ERROR(_fyc, _fyt, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYC_TOKEN_WARNING(_fyc, _fyt, _module, _fmt, ...) \ FYC_TOKEN_DIAG(_fyc, _fyt, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) /* document builder */ struct fy_document_builder; int fy_document_builder_vdiag(struct fy_document_builder *fydb, unsigned int flags, const char *file, int line, const char *func, const char *fmt, va_list ap); int fy_document_builder_diag(struct fy_document_builder *fydb, unsigned int flags, const char *file, int line, const char *func, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 6, 7)); void fy_document_builder_diag_vreport(struct fy_document_builder *fydb, const struct fy_diag_report_ctx *fydrc, const char *fmt, va_list ap); void fy_document_builder_diag_report(struct fy_document_builder *fydb, const struct fy_diag_report_ctx *fydrc, const char *fmt, ...) FY_ATTRIBUTE(format(printf, 3, 4)); #ifdef FY_DEVMODE #define fydb_debug(_fydb, _module, _fmt, ...) \ fy_document_builder_diag((_fydb), FYET_DEBUG | FYDF_MODULE(_module), \ __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #else #define fydb_debug(_fydb, _module, _fmt, ...) \ do { } while(0) #endif #define fydb_info(_fydb, _fmt, ...) \ fy_document_builder_diag((_fydb), FYET_INFO, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fydb_notice(_fydb, _fmt, ...) \ fy_document_builder_diag((_fydb), FYET_NOTICE, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fydb_warning(_fydb, _fmt, ...) \ fy_document_builder_diag((_fydb), FYET_WARNING, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fydb_error(_fydb, _fmt, ...) \ fy_document_builder_diag((_fydb), FYET_ERROR, __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__) #define fydb_error_check(_fydb, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ fydb_error((_fydb), _fmt, ## __VA_ARGS__); \ goto _label ; \ } \ } while(0) #define _FYDB_TOKEN_DIAG(_fydb, _fyt, _type, _module, _fmt, ...) \ do { \ struct fy_diag_report_ctx _drc; \ memset(&_drc, 0, sizeof(_drc)); \ _drc.type = (_type); \ _drc.module = (_module); \ _drc.fyt = (_fyt); \ fy_document_builder_diag_report((_fydb), &_drc, (_fmt) , ## __VA_ARGS__); \ } while(0) #define FYDB_TOKEN_DIAG(_fydb, _fyt, _type, _module, _fmt, ...) \ _FYDB_TOKEN_DIAG(_fydb, fy_token_ref(_fyt), _type, _module, _fmt, ## __VA_ARGS__) #define FYDB_NODE_DIAG(_fydb, _fyn, _type, _module, _fmt, ...) \ _FYDB_TOKEN_DIAG(_fydb, fy_node_token(_fyn), _type, _module, _fmt, ## __VA_ARGS__) #define FYDB_TOKEN_ERROR(_fydb, _fyt, _module, _fmt, ...) \ FYDB_TOKEN_DIAG(_fydb, _fyt, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYDB_NODE_ERROR(_fydb, _fyn, _module, _fmt, ...) \ FYDB_NODE_DIAG(_fydb, _fyn, FYET_ERROR, _module, _fmt, ## __VA_ARGS__) #define FYDB_TOKEN_ERROR_CHECK(_fydb, _fyt, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYDB_TOKEN_ERROR(_fydb, _fyt, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYDB_NODE_ERROR_CHECK(_fydb, _fyn, _module, _cond, _label, _fmt, ...) \ do { \ if (!(_cond)) { \ FYDB_NODE_ERROR(_fydb, _fyn, _module, _fmt, ## __VA_ARGS__); \ goto _label; \ } \ } while(0) #define FYDB_TOKEN_WARNING(_fydb, _fyt, _module, _fmt, ...) \ FYDB_TOKEN_DIAG(_fydb, _fyt, FYET_WARNING, _module, _fmt, ## __VA_ARGS__) /* alloca formatted print methods */ #define alloca_vsprintf(_res, _fmt, _ap) \ do { \ const char *__fmt = (_fmt); \ va_list _ap_orig; \ int _size; \ int _sizew __FY_DEBUG_UNUSED__; \ char *_buf = NULL, *_s; \ \ va_copy(_ap_orig, (_ap)); \ _size = vsnprintf(NULL, 0, __fmt, _ap_orig); \ va_end(_ap_orig); \ if (_size != -1) { \ _buf = FY_ALLOCA(_size + 1); \ _sizew = vsnprintf(_buf, _size + 1, __fmt, _ap); \ assert(_size == _sizew); \ _s = _buf + strlen(_buf); \ while (_s > _buf && _s[-1] == '\n') \ *--_s = '\0'; \ } \ *(_res) = _buf; \ } while(false) #define alloca_sprintf(_res, _fmt, ...) \ do { \ const char *__fmt = (_fmt); \ int _size; \ int _sizew __FY_DEBUG_UNUSED__; \ char *_buf = NULL, *_s; \ \ _size = snprintf(NULL, 0, __fmt, ## __VA_ARGS__); \ if (_size != -1) { \ _buf = FY_ALLOCA(_size + 1); \ _sizew = snprintf(_buf, _size + 1, __fmt, __VA_ARGS__); \ assert(_size == _sizew); \ _s = _buf + strlen(_buf); \ while (_s > _buf && _s[-1] == '\n') \ *--_s = '\0'; \ } \ *(_res) = _buf; \ } while(false) #endif