/* * fy-input.h - YAML input methods * * Copyright (c) 2019 Pantelis Antoniou * * SPDX-License-Identifier: MIT */ #ifndef FY_INPUT_H #define FY_INPUT_H #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "fy-utils.h" #include "fy-typelist.h" #include "fy-ctype.h" #include "fy-atom.h" #include "fy-diag.h" struct fy_atom; struct fy_parser; struct fy_generic_iterator; enum fy_input_type { fyit_file, fyit_stream, fyit_memory, fyit_alloc, fyit_callback, fyit_fd, fyit_dociter, fyit_geniter, }; struct fy_input_cfg { enum fy_input_type type; void *userdata; size_t chunk; bool ignore_stdio : 1; bool no_fclose_fp : 1; bool no_close_fd : 1; union { struct { const char *filename; } file; struct { const char *name; FILE *fp; } stream; struct { const void *data; size_t size; } memory; struct { void *data; size_t size; } alloc; struct { /* negative return is error, 0 is EOF */ ssize_t (*input)(void *user, void *buf, size_t count); } callback; struct { int fd; } fd; struct { enum fy_parser_event_generator_flags flags; struct fy_document_iterator *fydi; bool owns_iterator; } dociter; struct { enum fy_parser_event_generator_flags flags; struct fy_generic_iterator *fygi; bool owns_iterator; } geniter; }; }; enum fy_input_state { FYIS_NONE, FYIS_QUEUED, FYIS_PARSE_IN_PROGRESS, FYIS_PARSED, FYIS_ERROR, }; FY_TYPE_FWD_DECL_LIST(input); struct fy_input { struct list_head node; enum fy_input_state state; struct fy_input_cfg cfg; int refs; /* number of referers */ char *name; void *buffer; /* when the file can't be mmaped */ uint64_t generation; size_t allocated; size_t read; size_t chunk; size_t chop; FILE *fp; /* FILE* for the input if it exists */ int fd; /* fd for file and stream */ size_t length; /* length of file */ void *addr; /* mmaped for files, allocated for streams */ bool eof : 1; /* got EOF */ bool err : 1; /* got an error */ /* propagated */ bool json_mode; enum fy_lb_mode lb_mode; enum fy_flow_ws_mode fws_mode; bool directive0_mode; }; FY_TYPE_DECL_LIST(input); static inline const void * fy_input_start_size(const struct fy_input *fyi, size_t *sizep) { const void *start; size_t size; /* tokens cannot cross boundaries */ switch (fyi->cfg.type) { case fyit_file: case fyit_fd: if (fyi->addr) { start = fyi->addr; size = fyi->length; break; } /* fall-through */ case fyit_stream: case fyit_callback: start = fyi->buffer; size = fyi->read; break; case fyit_memory: start = fyi->cfg.memory.data; size = fyi->cfg.memory.size; break; case fyit_alloc: start = fyi->cfg.alloc.data; size = fyi->cfg.alloc.size; break; default: start = NULL; size = 0; break; } /* if we've parsed need to clamp */ if (fyi->state == FYIS_PARSED || fyi->state == FYIS_ERROR) { switch (fyi->cfg.type) { case fyit_file: case fyit_fd: case fyit_stream: case fyit_callback: if (fyi->allocated < size) size = fyi->allocated; break; default: break; } } *sizep = size; return start; } static inline const void *fy_input_start(const struct fy_input *fyi) { size_t size; return fy_input_start_size(fyi, &size); } static inline size_t fy_input_size(const struct fy_input *fyi) { size_t size; (void)fy_input_start_size(fyi, &size); return size; } struct fy_input *fy_input_alloc(void); void fy_input_free(struct fy_input *fyi); static inline enum fy_input_state fy_input_get_state(struct fy_input *fyi) { return fyi->state; } struct fy_input *fy_input_create(const struct fy_input_cfg *fyic); const char *fy_input_get_filename(struct fy_input *fyi); struct fy_input *fy_input_from_data(const char *data, size_t size, struct fy_atom *handle, bool simple); struct fy_input *fy_input_from_malloc_data(char *data, size_t size, struct fy_atom *handle, bool simple); struct fy_input *fy_input_from_data_styled(const char *data, size_t size, struct fy_atom *handle, enum fy_scalar_style sstyle); struct fy_input *fy_input_from_malloc_data_styled(char *data, size_t size, struct fy_atom *handle, enum fy_scalar_style sstyle); void fy_input_close(struct fy_input *fyi); static inline struct fy_input * fy_input_ref(struct fy_input *fyi) { if (!fyi) return NULL; assert(fyi->refs + 1 > 0); fyi->refs++; return fyi; } static inline void fy_input_unref(struct fy_input *fyi) { if (!fyi) return; assert(fyi->refs > 0); if (fyi->refs == 1) fy_input_free(fyi); else fyi->refs--; } ssize_t fy_input_estimate_queued_size(const struct fy_input *fyi); struct fy_reader; enum fy_reader_mode { fyrm_yaml, fyrm_json, fyrm_yaml_1_1, /* yaml 1.1 mode */ }; struct fy_reader_ops { struct fy_diag *(*get_diag)(struct fy_reader *fyr); int (*file_open)(struct fy_reader *fyr, const char *filename); }; struct fy_reader_input_cfg { bool disable_mmap_opt; }; struct fy_reader { const struct fy_reader_ops *ops; enum fy_reader_mode mode; struct fy_reader_input_cfg current_input_cfg; struct fy_input *current_input; size_t this_input_start; /* this input start */ const void *current_ptr; /* current pointer into the buffer */ const void *current_ptr_start; /* the start of this input */ const void *current_ptr_end; /* the end of this input */ int line; /* always on input */ int column; int tabsize; /* very experimental tab size for indent purposes */ struct fy_diag *diag; /* decoded mode variables; update when changing modes */ bool json_mode; enum fy_lb_mode lb_mode; enum fy_flow_ws_mode fws_mode; bool directive0_mode; }; void fy_reader_reset(struct fy_reader *fyr); void fy_reader_setup(struct fy_reader *fyr, const struct fy_reader_ops *ops); void fy_reader_cleanup(struct fy_reader *fyr); int fy_reader_input_open(struct fy_reader *fyr, struct fy_input *fyi, const struct fy_reader_input_cfg *icfg); int fy_reader_input_done(struct fy_reader *fyr); int fy_reader_input_scan_token_mark_slow_path(struct fy_reader *fyr); static FY_ALWAYS_INLINE inline size_t fy_reader_current_input_pos(const struct fy_reader *fyr) { return (size_t)((const char *)fyr->current_ptr - (const char *)fyr->current_ptr_start); } static FY_ALWAYS_INLINE inline size_t fy_reader_current_left(const struct fy_reader *fyr) { return (size_t)((const char *)fyr->current_ptr_end - (const char *)fyr->current_ptr); } static inline bool fy_reader_input_chop_active(struct fy_reader *fyr) { struct fy_input *fyi; assert(fyr); fyi = fyr->current_input; assert(fyi); if (!fyi->chop) return false; switch (fyi->cfg.type) { case fyit_file: return !fyi->addr && fyi->fp; /* non-mmap mode */ case fyit_stream: case fyit_callback: return true; default: /* all the others do not support chop */ break; } return false; } static inline int fy_reader_input_scan_token_mark(struct fy_reader *fyr) { /* don't chop until ready */ if (!fy_reader_input_chop_active(fyr) || fyr->current_input->chop > fy_reader_current_input_pos(fyr)) return 0; return fy_reader_input_scan_token_mark_slow_path(fyr); } const void *fy_reader_ptr_slow_path(struct fy_reader *fyr, size_t *leftp); const void *fy_reader_ensure_lookahead_slow_path(struct fy_reader *fyr, size_t size, size_t *leftp); void fy_reader_apply_mode(struct fy_reader *fyr); static FY_ALWAYS_INLINE inline enum fy_reader_mode fy_reader_get_mode(const struct fy_reader *fyr) { assert(fyr); return fyr->mode; } static FY_ALWAYS_INLINE inline void fy_reader_set_mode(struct fy_reader *fyr, enum fy_reader_mode mode) { assert(fyr); fyr->mode = mode; fy_reader_apply_mode(fyr); } static FY_ALWAYS_INLINE inline enum fy_reader_mode fy_reader_calculate_mode(const struct fy_version *vers, bool json_mode) { enum fy_reader_mode mode; if (!json_mode) mode = fy_version_compare(vers, fy_version_make(1, 1)) <= 0 ? fyrm_yaml_1_1 : fyrm_yaml; else mode = fyrm_json; return mode; } static FY_ALWAYS_INLINE inline struct fy_input * fy_reader_current_input(const struct fy_reader *fyr) { assert(fyr); return fyr->current_input; } static FY_ALWAYS_INLINE inline uint64_t fy_reader_current_input_generation(const struct fy_reader *fyr) { assert(fyr); assert(fyr->current_input); return fyr->current_input->generation; } static FY_ALWAYS_INLINE inline int fy_reader_column(const struct fy_reader *fyr) { assert(fyr); return fyr->column; } static FY_ALWAYS_INLINE inline int fy_reader_tabsize(const struct fy_reader *fyr) { assert(fyr); return fyr->tabsize; } static FY_ALWAYS_INLINE inline int fy_reader_line(const struct fy_reader *fyr) { assert(fyr); return fyr->line; } static FY_ALWAYS_INLINE inline bool fy_reader_generates_events(const struct fy_reader *fyr) { struct fy_input *fyi; fyi = fy_reader_current_input(fyr); if (!fyi) return false; return fyi->cfg.type == fyit_dociter || fyi->cfg.type == fyit_geniter; } struct fy_event *fy_reader_generate_next_event(struct fy_reader *fyr); void fy_reader_event_free(struct fy_reader *fyr, struct fy_event *fye); /* force new line at the end of stream */ static inline void fy_reader_stream_end(struct fy_reader *fyr) { assert(fyr); /* force new line */ if (fyr->column) { fyr->column = 0; fyr->line++; } } static FY_ALWAYS_INLINE inline void fy_reader_get_mark(struct fy_reader *fyr, struct fy_mark *fym) { assert(fyr); fym->input_pos = fy_reader_current_input_pos(fyr); fym->line = fyr->line; fym->column = fyr->column; } static FY_ALWAYS_INLINE inline const void * fy_reader_ptr(struct fy_reader *fyr, size_t *leftp) { if (fyr->current_ptr) { if (leftp) *leftp = fy_reader_current_left(fyr); return fyr->current_ptr; } return fy_reader_ptr_slow_path(fyr, leftp); } static FY_ALWAYS_INLINE inline bool fy_reader_json_mode(const struct fy_reader *fyr) { assert(fyr); return fyr->json_mode; } static FY_ALWAYS_INLINE inline enum fy_lb_mode fy_reader_lb_mode(const struct fy_reader *fyr) { assert(fyr); return fyr->lb_mode; } static FY_ALWAYS_INLINE inline enum fy_flow_ws_mode fy_reader_flow_ws_mode(const struct fy_reader *fyr) { assert(fyr); return fyr->fws_mode; } static FY_ALWAYS_INLINE inline enum fy_flow_ws_mode fy_reader_directive0_mode(const struct fy_reader *fyr) { assert(fyr); return fyr->directive0_mode; } static FY_ALWAYS_INLINE inline bool fy_reader_is_lb(const struct fy_reader *fyr, int c) { return fy_is_lb_m(c, fy_reader_lb_mode(fyr)); } static FY_ALWAYS_INLINE inline bool fy_reader_is_lbz(const struct fy_reader *fyr, int c) { return fy_is_lbz_m(c, fy_reader_lb_mode(fyr)); } static FY_ALWAYS_INLINE inline bool fy_reader_is_blankz(const struct fy_reader *fyr, int c) { return fy_is_blankz_m(c, fy_reader_lb_mode(fyr)); } static FY_ALWAYS_INLINE inline bool fy_reader_is_generic_lb(const struct fy_reader *fyr, int c) { return fy_is_generic_lb_m(c, fy_reader_lb_mode(fyr)); } static FY_ALWAYS_INLINE inline bool fy_reader_is_generic_lbz(const struct fy_reader *fyr, int c) { return fy_is_generic_lbz_m(c, fy_reader_lb_mode(fyr)); } static FY_ALWAYS_INLINE inline bool fy_reader_is_generic_blankz(const struct fy_reader *fyr, int c) { return fy_is_generic_blankz_m(c, fy_reader_lb_mode(fyr)); } static FY_ALWAYS_INLINE inline bool fy_reader_is_flow_ws(const struct fy_reader *fyr, int c) { return fy_is_flow_ws_m(c, fy_reader_flow_ws_mode(fyr)); } static FY_ALWAYS_INLINE inline bool fy_reader_is_flow_blank(const struct fy_reader *fyr, int c) { return fy_reader_is_flow_ws(fyr, c); /* same */ } static FY_ALWAYS_INLINE inline bool fy_reader_is_flow_blankz(const struct fy_reader *fyr, int c) { return fy_is_flow_blankz(c, fy_reader_flow_ws_mode(fyr), fy_reader_lb_mode(fyr)); } static FY_ALWAYS_INLINE inline const void * fy_reader_ensure_lookahead(struct fy_reader *fyr, size_t size, size_t *leftp) { size_t current_left = fy_reader_current_left(fyr); if (current_left >= size) { *leftp = current_left; return fyr->current_ptr; } return fy_reader_ensure_lookahead_slow_path(fyr, size, leftp); } /* compare string at the current point (n max) */ static inline int fy_reader_strncmp(struct fy_reader *fyr, const char *str, size_t n) { const char *p; size_t len; int ret; assert(fyr); p = fy_reader_ensure_lookahead(fyr, n, &len); if (!p) return -1; /* not enough? */ if (n > len) return 1; ret = strncmp(p, str, n); return ret ? 1 : 0; } int fy_reader_peek_at_offset_width_slow_path(struct fy_reader *fyr, size_t offset, int *wp); static FY_ALWAYS_INLINE inline int fy_reader_peek_at_offset_width(struct fy_reader *fyr, size_t offset, int *wp) { assert(fyr); if ((ssize_t)(fy_reader_current_left(fyr) - offset) >= 4) return fy_utf8_get((const char *)fyr->current_ptr + offset, 4, wp); return fy_reader_peek_at_offset_width_slow_path(fyr, offset, wp); } int64_t fy_reader_peek_at_offset_width_slow_path_64(struct fy_reader *fyr, size_t offset); static FY_ALWAYS_INLINE inline int64_t fy_reader_peek_at_offset_width_64(struct fy_reader *fyr, size_t offset) { assert(fyr); if ((ssize_t)(fy_reader_current_left(fyr) - offset) >= 4) return fy_utf8_get_64((const char *)fyr->current_ptr + offset, 4); return fy_reader_peek_at_offset_width_slow_path_64(fyr, offset); } static FY_ALWAYS_INLINE inline int fy_reader_peek_at_offset(struct fy_reader *fyr, size_t offset) { int w; return fy_reader_peek_at_offset_width(fyr, offset, &w); } static FY_ALWAYS_INLINE inline int fy_reader_peek_at_width_internal(struct fy_reader *fyr, int pos, ssize_t *offsetp, int *wp) { int i, c, w; size_t offset; offset = (size_t)*offsetp; if ((ssize_t)offset < 0) { for (i = 0, offset = 0; i < pos; i++, offset += w) { c = fy_reader_peek_at_offset_width(fyr, offset, &w); if (c < 0) return c; } } c = fy_reader_peek_at_offset_width(fyr, offset, wp); *offsetp = offset + *wp; return c; } static FY_ALWAYS_INLINE inline int fy_reader_peek_at_internal(struct fy_reader *fyr, int pos, ssize_t *offsetp) { int w; return fy_reader_peek_at_width_internal(fyr, pos, offsetp, &w); } static FY_ALWAYS_INLINE inline bool fy_reader_is_blank_at_offset(struct fy_reader *fyr, size_t offset) { return fy_is_blank(fy_reader_peek_at_offset(fyr, offset)); } static FY_ALWAYS_INLINE inline bool fy_reader_is_blankz_at_offset(struct fy_reader *fyr, size_t offset) { return fy_reader_is_blankz(fyr, fy_reader_peek_at_offset(fyr, offset)); } static FY_ALWAYS_INLINE inline int fy_reader_peek_at_width(struct fy_reader *fyr, int pos, int *wp) { int i, c, w; size_t offset; assert(fyr); for (i = 0, offset = 0; i < pos; i++, offset += w) { c = fy_reader_peek_at_offset_width(fyr, offset, &w); if (c < 0) return c; } return fy_reader_peek_at_offset_width(fyr, offset, wp); } static FY_ALWAYS_INLINE inline int fy_reader_peek_at(struct fy_reader *fyr, int pos) { int i, c, w; size_t offset; assert(fyr); for (i = 0, offset = 0; i < pos; i++, offset += w) { c = fy_reader_peek_at_offset_width(fyr, offset, &w); if (c < 0) return c; } return fy_reader_peek_at_offset(fyr, offset); } static FY_ALWAYS_INLINE inline int fy_reader_peek_width(struct fy_reader *fyr, int *wp) { return fy_reader_peek_at_offset_width(fyr, 0, wp); } static FY_ALWAYS_INLINE inline int fy_reader_peek(struct fy_reader *fyr) { int w; return fy_reader_peek_width(fyr, &w); } static FY_ALWAYS_INLINE inline const void * fy_reader_peek_block(struct fy_reader *fyr, size_t *lenp) { const void *p; /* try to pull at least one utf8 character usually */ p = fy_reader_ensure_lookahead(fyr, 4, lenp); /* not a utf8 character available? try a single byte */ if (!p) p = fy_reader_ensure_lookahead(fyr, 1, lenp); if (!*lenp) p = NULL; return p; } static FY_ALWAYS_INLINE inline void fy_reader_advance_octets(struct fy_reader *fyr, size_t advance) { fyr->current_ptr = (const char *)fyr->current_ptr + advance; } void fy_reader_advance_slow_path(struct fy_reader *fyr, int c); static FY_ALWAYS_INLINE inline void fy_reader_advance_printable_ascii(struct fy_reader *fyr, int c FY_UNUSED) { assert(fyr); fy_reader_advance_octets(fyr, 1); fyr->column++; } static FY_ALWAYS_INLINE inline void fy_reader_update_state_lb_mode(struct fy_reader *fyr, const int c, const enum fy_lb_mode lb_mode) { if (fy_is_lb_m(c, lb_mode)) { fyr->column = 0; fyr->line++; } else if (fy_is_tab(c) && fyr->tabsize) fyr->column += (fyr->tabsize - (fyr->column % fyr->tabsize)); else fyr->column++; } static FY_ALWAYS_INLINE inline void fy_reader_advance_lb_mode(struct fy_reader *fyr, const int c, const enum fy_lb_mode lb_mode) { assert(fy_utf8_is_valid(c)); fy_reader_advance_octets(fyr, fy_utf8_width(c)); /* Handle CRLF as single line break */ if (c == '\r' && fy_reader_peek(fyr) == '\n') { fy_reader_advance_octets(fyr, 1); fyr->column = 0; fyr->line++; } else { fy_reader_update_state_lb_mode(fyr, c, lb_mode); } } static FY_ALWAYS_INLINE inline void fy_reader_advance(struct fy_reader *fyr, const int c) { fy_reader_advance_lb_mode(fyr, c, fy_reader_lb_mode(fyr)); } static FY_ALWAYS_INLINE inline void fy_reader_advance_ws(struct fy_reader *fyr, int c) { /* skip this character */ fy_reader_advance_octets(fyr, fy_utf8_width(c)); if (fy_is_tab(c) && fyr->tabsize) fyr->column += (fyr->tabsize - (fyr->column % fyr->tabsize)); else fyr->column++; } static FY_ALWAYS_INLINE inline void fy_reader_advance_space(struct fy_reader *fyr) { fy_reader_advance_octets(fyr, 1); fyr->column++; } static FY_ALWAYS_INLINE inline int fy_reader_get(struct fy_reader *fyr) { int value; value = fy_reader_peek(fyr); if (value < 0) return value; fy_reader_advance(fyr, value); return value; } static FY_ALWAYS_INLINE inline int fy_reader_advance_by(struct fy_reader *fyr, int count) { int i, c; for (i = 0; i < count; i++) { c = fy_reader_get(fyr); if (c < 0) break; } return i ? i : -1; } /* compare string at the current point */ static inline bool fy_reader_strcmp(struct fy_reader *fyr, const char *str) { return fy_reader_strncmp(fyr, str, strlen(str)); } /* atom */ static inline void fy_reader_fill_atom_start(struct fy_reader *fyr, struct fy_atom *handle) { /* start mark */ fy_reader_get_mark(fyr, &handle->start_mark); handle->fyi = fy_reader_current_input(fyr); handle->fyi_generation = fy_reader_current_input_generation(fyr); handle->increment = 0; handle->tozero = 0; memset(&handle->analysis, 0, sizeof(handle->analysis)); /* note that handle->data may be zero for empty input */ } static inline void fy_reader_fill_atom_end_at(struct fy_reader *fyr, struct fy_atom *handle, struct fy_mark *end_mark) { if (end_mark) handle->end_mark = *end_mark; else fy_reader_get_mark(fyr, &handle->end_mark); /* default is plain, modify at return */ handle->style = FYAS_PLAIN; handle->chomp = FYAC_CLIP; /* by default we don't do storage hints, it's the job of the caller */ handle->storage_hint = 0; handle->storage_hint_valid = false; handle->tabsize = fy_reader_tabsize(fyr); handle->json_mode = fy_reader_json_mode(fyr); handle->lb_mode = fy_reader_lb_mode(fyr); handle->fws_mode = fy_reader_flow_ws_mode(fyr); handle->directive0_mode = fy_reader_directive0_mode(fyr); } static inline void fy_reader_fill_atom_end(struct fy_reader *fyr, struct fy_atom *handle) { fy_reader_fill_atom_end_at(fyr, handle, NULL); } /* diag */ static inline bool fyr_debug_log_level_is_enabled(struct fy_reader *fyr) { return fyr && fy_diag_log_level_is_enabled(fyr->diag, FYET_DEBUG, FYEM_SCAN); } 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_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_FORMAT(printf, 3, 4); #ifdef FY_DEVMODE #define fyr_debug(_fyr, _fmt, ...) \ do { \ struct fy_reader *__fyr = (_fyr); \ \ if (fyr_debug_log_level_is_enabled(__fyr)) \ fy_reader_diag(__fyr, FYET_DEBUG, \ __FILE__, __LINE__, __func__, \ (_fmt) , ## __VA_ARGS__); \ } while(0) #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), \ 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), \ 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__) struct fy_input *fy_input_from_data(const char *data, size_t size, struct fy_atom *handle, bool simple); struct fy_input *fy_input_from_malloc_data(char *data, size_t size, struct fy_atom *handle, bool simple); #endif