The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.9.3] - 2026-01-14
+
+### Added
+
+- fy-tool: `-winf` option for infinite width output
+- fy-tool: `--no-output-newline` option (useful with oneline mode)
+- Emitter: `FYEXCF_OUTPUT_FILENAME` extended option for direct file output
+
+### Changed
+
+- JSON emit mode now works like YAML flow mode (less special-casing)
+- Compact emit mode now produces truly compact output (no indentation)
+- Emitter only changes plain scalar style when space or linebreak is present (preserves numeric scalars better)
+
+### Fixed
+
+- **#170**: Wrong length return when buffer ends mid UTF-8 sequence
+- **#167**: Oneline styles now correctly use infinite width
+- **#139**: Walk path parser now always creates diagnostics (fixes token reference leak)
+- **#137**: Walk memory leak on parse error path
+- **#136**: Walk memory leak when no output is generated
+- **#131**: Walk memory leak when expression error occurs
+- Composer: Memory leak when back-to-back complex keys exist
+- Emitter: Broken flow mode output
+- Emitter: Unnecessary plain scalar style changes
+
+### Platform Support
+
+**Supported platforms**: Linux, macOS, FreeBSD, OpenBSD, and NetBSD.
+
+- **NetBSD**: Disabled mremap (different semantics than Linux)
+- **NetBSD**: CMake shared libraries now correctly built with -fPIC
+- **NetBSD**: Only include alloca.h if it exists
+- **NetBSD**: Fixed ctype(3) argument casting (unsigned char)
+- **GNU/Hurd**: Use `<endian.h>` for endianness detection
+- Use `getopt_long` instead of `getopt_long_only` for portability
+- Fix test(1) operator in test suite (use POSIX `=` not bash `==`)
+- Fix `-Wformat` warning (use PRIx64 for uint64_t)
+
+### Statistics
+
+- 25 commits since v0.9.2
+- 6 bug fix issues closed
+
## [0.9.2] - 2025-12-29
### Fixed
+- **#156**: automake: Respect --disable-static and don't build internals
- **#157**: dist tarball now includes the missing CMake files
## [0.9.1] - 2025-12-28
Initial public release with comprehensive YAML 1.2 support.
+[0.9.3]: https://github.com/pantoniou/libfyaml/compare/v0.9.2...v0.9.3
+[0.9.2]: https://github.com/pantoniou/libfyaml/compare/v0.9.1...v0.9.2
[0.9.1]: https://github.com/pantoniou/libfyaml/compare/v0.9...v0.9.1
[0.9]: https://github.com/pantoniou/libfyaml/releases/tag/v0.9
endif()
# Check for headers and functions
+check_include_file("alloca.h" HAVE_ALLOCA_H)
check_include_file("byteswap.h" HAVE_BYTESWAP_H)
check_function_exists(__builtin_bswap16 HAVE___BUILTIN_BSWAP16)
check_function_exists(__builtin_bswap32 HAVE___BUILTIN_BSWAP32)
endif()
+# the options for the libs
+set(LIB_OPTS "")
+if(BUILD_SHARED_LIBS)
+ list(APPEND LIB_OPTS "-fPIC")
+endif()
+
# Network tests
if(ENABLE_NETWORK)
set(HAVE_NETWORK 1)
HASHER_SUFFIX=portable
SIMD_DEGREE=1
)
-target_compile_options(b3portable PRIVATE ${COMMON_C_FLAGS})
+target_compile_options(b3portable PRIVATE ${COMMON_C_FLAGS} ${LIB_OPTS})
# BLAKE3 SIMD libraries
set(BLAKE3_TARGETS b3portable)
HASHER_SUFFIX=sse2
SIMD_DEGREE=4
)
- target_compile_options(b3sse2 PRIVATE ${COMMON_C_FLAGS} -msse2)
+ target_compile_options(b3sse2 PRIVATE ${COMMON_C_FLAGS} -msse2 ${LIB_OPTS})
list(APPEND BLAKE3_TARGETS b3sse2)
endif()
HASHER_SUFFIX=sse41
SIMD_DEGREE=4
)
- target_compile_options(b3sse41 PRIVATE ${COMMON_C_FLAGS} -msse4.1)
+ target_compile_options(b3sse41 PRIVATE ${COMMON_C_FLAGS} -msse4.1 ${LIB_OPTS})
list(APPEND BLAKE3_TARGETS b3sse41)
endif()
HASHER_SUFFIX=avx2
SIMD_DEGREE=8
)
- target_compile_options(b3avx2 PRIVATE ${COMMON_C_FLAGS} -mavx2)
+ target_compile_options(b3avx2 PRIVATE ${COMMON_C_FLAGS} -mavx2 ${LIB_OPTS})
list(APPEND BLAKE3_TARGETS b3avx2)
endif()
HASHER_SUFFIX=avx512
SIMD_DEGREE=16
)
- target_compile_options(b3avx512 PRIVATE ${COMMON_C_FLAGS} -mavx512f -mavx512vl)
+ target_compile_options(b3avx512 PRIVATE ${COMMON_C_FLAGS} -mavx512f -mavx512vl ${LIB_OPTS})
list(APPEND BLAKE3_TARGETS b3avx512)
endif()
HASHER_SUFFIX=neon
SIMD_DEGREE=4
)
- target_compile_options(b3neon PRIVATE ${COMMON_C_FLAGS})
+ target_compile_options(b3neon PRIVATE ${COMMON_C_FLAGS} ${LIB_OPTS})
if(TARGET_CPU_ARM)
target_compile_options(b3neon PRIVATE -mfpu=neon)
endif()
# Shared options between GCC and CLANG
if(NOT MSVC)
+ target_compile_options(fyaml PRIVATE ${LIB_OPTS})
target_compile_options(fyaml PRIVATE -fvisibility=hidden)
- if(BUILD_SHARED_LIBS)
- target_compile_options(fyaml PRIVATE -fPIC)
- endif()
-
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(fyaml PRIVATE -O2)
endif()
#ifndef CONFIG_H
#define CONFIG_H
+/* Define to 1 if you have alloca.h */
+#cmakedefine HAVE_ALLOCA_H
+
/* Define to 1 if you have byteswap.h */
#cmakedefine HAVE_BYTESWAP_H
AC_TYPE_UID_T
AC_CHECK_DECLS(environ)
-AC_CHECK_HEADERS([byteswap.h])
+AC_CHECK_HEADERS([alloca.h byteswap.h])
AC_CHECK_FUNCS([__builtin_bswap16 __builtin_bswap32 __builtin_bswap64])
dnl for old autoconf version AX_APPEND_COMPILE_FLAGS does not work
AS_HELP_STRING([--enable-portable-target],
[Enable portable mode (disable per-target optimizations)]))
HAVE_PORTABLE_TARGET=0
-if test "x$enable_portable_target" == "xyes"; then
+if test "x$enable_portable_target" = "xyes"; then
HAVE_PORTABLE_TARGET=1
fi
AC_SUBST(HAVE_PORTABLE_TARGET)
AC_DEFINE_UNQUOTED([HAVE_PORTABLE_TARGET], [$HAVE_PORTABLE_TARGET], [Define to 1 if PORTABLE_TARGET is enabled])
-AM_CONDITIONAL([HAVE_PORTABLE_TARGET], [ test x$HAVE_PORTABLE_TARGET == x1 ])
+AM_CONDITIONAL([HAVE_PORTABLE_TARGET], [ test x$HAVE_PORTABLE_TARGET = x1 ])
dnl Detect cross-compilation
if test "x$build" != "x$host" ; then
HAVE_ASAN=0
ASAN_CFLAGS=""
ASAN_LIBS=""
-if test "x$enable_asan" == "xyes" ; then
+if test "x$enable_asan" = "xyes" ; then
AC_MSG_CHECKING([location of ASAN library])
ASANLIB1=`${CC} -print-file-name=libasan.so`
ASANLIB=`readlink -f "${ASANLIB1}"`
fi
fi
if test "x$with_libclang" != "xno"; then
- if test "x$with_libclang" == "xauto"; then
+ if test "x$with_libclang" = "xauto"; then
# try to auto detect (llvm 20 down to 10)
check="llvm-config llvm-config-20 llvm-config-19 llvm-config-18 llvm-config-17 llvm-config-16 \
llvm-config-15 llvm-config-14 llvm-config-13 llvm-config-12 llvm-config-11 llvm-config-10"
else
- if test "x$with_libclang" == "xlatest"; then
+ if test "x$with_libclang" = "xlatest"; then
check="llvm-config"
else
check="llvm-config-$with_libclang"
+set(CMAKE_PREFIX_PATH "/home/panto/work/libfyaml/build")
cmake_minimum_required(VERSION 3.12)
project(libfyaml-examples C)
* @FYEXCF_OUTPUT_FILE: Output to the fp FILE pointer
* @FYEXCF_OUTPUT_FD: Output to the fd file descriptor
* @FYEXCF_NULL_OUTPUT: No output
+ * @FYEXCF_OUTPUT_FILENAME: Output to the given filename
*/
enum fy_emitter_xcfg_flags {
FYEXCF_COLOR_AUTO = FYEXCF_COLOR(0),
FYEXCF_OUTPUT_FILE = FYEXCF_OUTPUT(2),
FYEXCF_OUTPUT_FD = FYEXCF_OUTPUT(2),
FYEXCF_NULL_OUTPUT = FYEXCF_OUTPUT(3),
+ FYEXCF_OUTPUT_FILENAME = FYEXCF_OUTPUT(4),
FYEXCF_VISIBLE_WS = FY_BIT(5),
FYEXCF_EXTENDED_INDICATORS = FY_BIT(6),
};
* @colors: ANSI color overrides for the default output method
* @output_fp: The output FILE \*, FYEXCF\_FILE\_OUTPUT must be set
* @output_fd: The output file descriptor, FYEXCF\_FD\_OUTPUT must be set
+ * @output_filename: The output filename, FYEXCF\_FILENAME\_OUTPUT must be set
*/
struct fy_emitter_xcfg {
struct fy_emitter_cfg cfg;
union {
FILE *output_fp;
int output_fd;
+ const char *output_filename;
};
};
if (a->flags & FYAF_TRACE) {
int i;
size_t j;
- printf("%s: %p: dup-store %p 0x%016lx %zx:", __func__, a, de->mem, hash, total_size);
+ printf("%s: %p: dup-store %p 0x%016"PRIx64" %zx:", __func__,
+ a, de->mem, hash, total_size);
for (i = 0; i < iovcnt; i++) {
for (j = 0; j < iov[i].iov_len; j++) {
printf("%02x", (int)(((uint8_t *)iov[i].iov_base)[j]) & 0xff);
if (a->flags & FYAF_TRACE) {
int i;
size_t j;
- printf("%s: %p: new-store %p 0x%016lx %zx:", __func__, a, de->mem, hash, total_size);
+ printf("%s: %p: new-store %p 0x%016"PRIx64" %zx:", __func__,
+ a, de->mem, hash, total_size);
for (i = 0; i < iovcnt; i++) {
for (j = 0; j < iov[i].iov_len; j++) {
printf("%02x", (int)(((uint8_t *)iov[i].iov_base)[j]) & 0xff);
#include <time.h>
#include <inttypes.h>
#include <math.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <stdio.h>
#include <inttypes.h>
#include <math.h>
#include <sys/mman.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <stdio.h>
// #define DEBUG_ARENA
-// #define DISABLE_MREMAP
+#if defined(__NetBSD__)
+#define DISABLE_MREMAP
+#endif
#if HAVE_MREMAP && !defined(DISABLE_MREMAP)
#define USE_MREMAP 1
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <pthread.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <stdbool.h>
#include <getopt.h>
#include <ctype.h>
const char *parent_allocator = "linear";
size_t size = 0;
- while ((opt = getopt_long_only(argc, argv, "a:p:s:h", lopts, &lidx)) != -1) {
+ while ((opt = getopt_long(argc, argv, "a:p:s:h", lopts, &lidx)) != -1) {
switch (opt) {
case 'a':
case 'p':
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <stdbool.h>
#include <getopt.h>
#include <ctype.h>
length = 0;
s = linebuf;
- while (isxdigit(*s))
+ while (isxdigit((unsigned char)*s))
s++;
length = s - linebuf;
- if (length == 0 || length > (BLAKE3_OUT_LEN * 2) || (length % 1) || !isspace(*s)) {
+ if (length == 0 || length > (BLAKE3_OUT_LEN * 2) || (length % 1) || !isspace((unsigned char)*s)) {
fprintf(stderr, "Bad line found at file \"%s\" line #%d\n", check_filename, line);
fprintf(stderr, "%s\n", linebuf);
goto err_out;
*s++ = '\0';
- while (isspace(*s))
+ while (isspace((unsigned char)*s))
s++;
length >>= 1; /* to bytes */
uint8_t key[BLAKE3_OUT_LEN];
ssize_t rdn;
- while ((opt = getopt_long_only(argc, argv, "cl:b:dh", lopts, &lidx)) != -1) {
+ while ((opt = getopt_long(argc, argv, "cl:b:dh", lopts, &lidx)) != -1) {
switch (opt) {
case OPT_DERIVE_KEY:
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <stdbool.h>
#include <getopt.h>
#include <ctype.h>
unsigned int num_threads = 0;
int exitcode = EXIT_FAILURE, opti;
- while ((opt = getopt_long_only(argc, argv, "h", lopts, &lidx)) != -1) {
+ while ((opt = getopt_long(argc, argv, "h", lopts, &lidx)) != -1) {
switch (opt) {
case OPT_NUM_THREADS:
opti = atoi(optarg);
fy_valgrind_check(&argc, &argv);
- while ((opt = getopt_long_only(argc, argv, "I:m:i:w:d:rsc:C:D:M:W:S:qh", lopts, &lidx)) != -1) {
+ while ((opt = getopt_long(argc, argv, "I:m:i:w:d:rsc:C:D:M:W:S:qh", lopts, &lidx)) != -1) {
switch (opt) {
case 'I':
tmp = alloca(strlen(cfg.search_path) + 1 + strlen(optarg) + 1);
nread = fy_atom_iter_read(iter, buf + 1, w - 1);
if (nread != (w - 1)) {
if (nread != -1 && nread < (w - 1))
- *lenp += nread;
+ *lenp = nread;
return 0;
}
}
fyc_error_check(fyc, fyd, err_out,
"fy_document_builder_take_document() failed\n");
+ fy_document_builder_destroy(fypp->fydb);
+ fypp->fydb = NULL;
+
fypc_last->map.is_complex_key = true;
fypc_last->map.accumulating_complex_key = false;
fypc_last->map.complex_key = fyd;
if (!str)
return FYET_MAX;
- if (isdigit(*str)) {
+ if (isdigit((unsigned char)*str)) {
level = atoi(str);
if (level >= 0 && level < FYET_MAX)
return (enum fy_error_type)level;
switch (ptr_flags) {
default:
case FYNWF_PTR_YAML:
- while (s < e && isspace(*s))
+ while (s < e && isspace((unsigned char)*s))
s++;
c = *s;
s = end_idx;
- while (s < e && isspace(*s))
+ while (s < e && isspace((unsigned char)*s))
s++;
if (c == '[' && *s++ != ']')
return NULL;
- while (s < e && isspace(*s))
+ while (s < e && isspace((unsigned char)*s))
s++;
break;
/* first path component may be an alias */
if ((flags & FYNWF_FOLLOW) && fyn && path) {
- while (s < e && isspace(*s))
+ while (s < e && isspace((unsigned char)*s))
s++;
if (s >= e || *s != '*')
}
/* trim spaces from key */
- while (isspace(*s))
+ while (isspace((unsigned char)*s))
s++;
te = t;
- while (te > s && isspace(te[-1]))
+ while (te > s && isspace((unsigned char)te[-1]))
*--te = '\0';
key = s;
/* we have to scan until the next space that's not in char set */
fmtspec = t;
while (t < e) {
- if (isspace(*t))
+ if (isspace((unsigned char)*t))
break;
/* character set (may include space) */
if (*t == '[') {
{
int width;
+ if (fy_emit_is_oneline(emit))
+ return INT_MAX;
+
width = (emit->xcfg.cfg.flags & FYECF_WIDTH(FYECF_WIDTH_MASK)) >> FYECF_WIDTH_SHIFT;
if (width == 0)
return 80;
if (emit->column)
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- /* stripping doc indicators, do not emit */
- if (emit->xcfg.cfg.flags & FYECF_STRIP_DOC)
- goto no_doc_emit;
-
/* ok, emit document start indicator */
fy_emit_puts_simple(emit, fyewt_document_indicator, "---");
emit->flags &= ~FYEF_WHITESPACE;
if ((flags & DDNF_ROOT) && emit->column != 0 &&
!(emit->flags & FYEF_HAD_DOCUMENT_START)) {
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
}
}
if (type != FYNT_SCALAR && (flags & DDNF_ROOT) && emit->column != 0) {
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
}
switch (type) {
if (flow && (style == FYNS_ANY || style == FYNS_LITERAL || style == FYNS_FOLDED)) {
- /* if there's a linebreak, use double quoted style */
- if (ta->flags & FYTTAF_HAS_ANY_LB) {
+ /* if there's a linebreak, or ends in a colon, use double quoted style */
+ if (ta->flags & (FYTTAF_HAS_ANY_LB | FYTTAF_ENDS_WITH_COLON)) {
style = FYNS_DOUBLE_QUOTED;
goto out;
}
((ta->flags & FYTTAF_QUOTE_AT_0) && indent == 0))
style = FYNS_DOUBLE_QUOTED;
- /* make it double quoted, but only if not already over the width */
- if (style == FYNS_PLAIN && emit->column < fy_emit_width(emit) && (emit->column + ta->maxspan) > fy_emit_width(emit))
+ /* make it double quoted, but only if not already over the width (and contains a space/lb) */
+ if (style == FYNS_PLAIN && (ta->flags & (FYTTAF_HAS_LB | FYTTAF_HAS_WS)) &&
+ emit->column < fy_emit_width(emit) && (emit->column + ta->maxspan) > fy_emit_width(emit))
style = FYNS_DOUBLE_QUOTED;
}
sc->flow = sc->empty;
else
sc->flow = fy_emit_is_flow_mode(emit) || emit->flow_level || sc->flow_token || sc->empty;
+ } else
+ sc->flow = true;
- if (sc->flow) {
- if (!emit->flow_level) {
- sc->indent = fy_emit_increase_indent(emit, sc->flags, sc->indent);
- sc->old_indent = sc->indent;
- }
-
- sc->flags = (sc->flags | DDNF_FLOW) | (sc->flags & ~DDNF_INDENTLESS);
- fy_emit_write_indicator(emit, di_left_bracket, sc->flags, sc->indent, fyewt_indicator);
- } else {
- sc->flags = (sc->flags & ~DDNF_FLOW);
+ if (sc->flow) {
+ if (!emit->flow_level) {
+ sc->indent = fy_emit_increase_indent(emit, sc->flags, sc->indent);
+ sc->old_indent = sc->indent;
}
- } else {
+
sc->flags = (sc->flags | DDNF_FLOW) | (sc->flags & ~DDNF_INDENTLESS);
fy_emit_write_indicator(emit, di_left_bracket, sc->flags, sc->indent, fyewt_indicator);
+
+ /* we need an indent afterward if not compact */
+ if (!fy_emit_is_oneline_or_compact(emit))
+ sc->flags |= DDNF_HANGING_INDENT;
+ } else {
+ sc->flags = (sc->flags & ~DDNF_FLOW);
}
- if (!fy_emit_is_oneline(emit)) {
+ if (!fy_emit_is_oneline_or_compact(emit)) {
if (was_flow || (sc->flags & (DDNF_ROOT | DDNF_SEQ)))
sc->indent = fy_emit_increase_indent(emit, sc->flags, sc->indent);
}
sc->flags |= DDNF_SEQ;
if (fy_emit_token_has_comment(emit, fyt_value, fycp_top) ||
- (!fy_emit_is_oneline_or_compact(emit) && !sc->flow) ||
+ !fy_emit_is_oneline_or_compact(emit) ||
((fy_emit_is_compact(emit) || sc->flow) && emit->column >= fy_emit_width(emit)))
fy_emit_write_indent(emit, sc->indent);
static void fy_emit_sequence_item_epilog(struct fy_emitter *emit, struct fy_emit_save_ctx *sc,
bool last, struct fy_token *fyt_value)
{
+ bool needs_hanging_indent;
+
if ((sc->flow || fy_emit_is_json_mode(emit)) && !last)
fy_emit_write_indicator(emit, di_comma, sc->flags, sc->indent, fyewt_indicator);
fy_emit_token_comment(emit, fyt_value, sc->flags, sc->indent, fycp_right);
- if (last && sc->flow && (sc->flags & DDNF_HANGING_INDENT) && !fy_emit_is_oneline_or_compact(emit) && !sc->empty)
+ needs_hanging_indent = sc->flow && !fy_emit_is_oneline_or_compact(emit) && !sc->empty;
+
+ if (last && needs_hanging_indent && (sc->flags & DDNF_HANGING_INDENT))
fy_emit_write_indent(emit, sc->old_indent);
+ else if (needs_hanging_indent)
+ sc->flags |= DDNF_HANGING_INDENT;
sc->flags &= ~DDNF_SEQ;
}
sc->flow = sc->empty;
else
sc->flow = fy_emit_is_flow_mode(emit) || emit->flow_level || sc->flow_token || sc->empty;
+ } else
+ sc->flow = true;
- if (sc->flow) {
- if (!emit->flow_level) {
- sc->indent = fy_emit_increase_indent(emit, sc->flags, sc->indent);
- sc->old_indent = sc->indent;
- }
-
- sc->flags = (sc->flags | DDNF_FLOW) | (sc->flags & ~DDNF_INDENTLESS);
- fy_emit_write_indicator(emit, di_left_brace, sc->flags, sc->indent, fyewt_indicator);
- } else {
- sc->flags &= ~(DDNF_FLOW | DDNF_INDENTLESS);
+ if (sc->flow) {
+ if (!emit->flow_level) {
+ sc->indent = fy_emit_increase_indent(emit, sc->flags, sc->indent);
+ sc->old_indent = sc->indent;
}
- } else {
+
sc->flags = (sc->flags | DDNF_FLOW) | (sc->flags & ~DDNF_INDENTLESS);
fy_emit_write_indicator(emit, di_left_brace, sc->flags, sc->indent, fyewt_indicator);
+
+ /* we need an indent afterward if not compact */
+ if (!fy_emit_is_oneline_or_compact(emit))
+ sc->flags |= DDNF_HANGING_INDENT;
+ } else {
+ sc->flags &= ~(DDNF_FLOW | DDNF_INDENTLESS);
}
- if (!fy_emit_is_oneline(emit) && !sc->empty)
+ if (!fy_emit_is_oneline_or_compact(emit) && !sc->empty)
sc->indent = fy_emit_increase_indent(emit, sc->flags, sc->indent);
sc->flags &= ~DDNF_ROOT;
sc->flags = DDNF_MAP | (sc->flags & DDNF_FLOW);
+ if (!fy_emit_is_oneline_or_compact(emit) ||
+ ((fy_emit_is_compact(emit) || sc->flow) && emit->column >= fy_emit_width(emit)))
+ fy_emit_write_indent(emit, sc->indent);
+
if (simple_key) {
sc->flags |= DDNF_SIMPLE;
if (fyt_key && fyt_key->type == FYTT_SCALAR)
}
do_indent = false;
- if (!fy_emit_is_oneline(emit)) {
+ if (!fy_emit_is_oneline_or_compact(emit)) {
if (fyt_key && fyt_key->type != FYTT_SCALAR)
/* always indent on non scalar keys */
- key_over = false;
+ key_over = true;
else {
/* for scalar keys, check if key + 2 + quotes go over */
ta = fy_token_text_analyze(fyt_key);
bool value_over;
/* don't do anything for those cases */
- if (!sc->flow || fy_emit_is_oneline(emit) || !fyt_value || fyt_value->type != FYTT_SCALAR)
+ if (!sc->flow || fy_emit_is_oneline_or_compact(emit) || !fyt_value || fyt_value->type != FYTT_SCALAR)
return;
ta = fy_token_text_analyze(fyt_value);
static void fy_emit_mapping_value_epilog(struct fy_emitter *emit, struct fy_emit_save_ctx *sc,
bool last, struct fy_token *fyt_value)
{
+ bool needs_hanging_indent;
+
if ((sc->flow || fy_emit_is_json_mode(emit)) && !last)
fy_emit_write_indicator(emit, di_comma, sc->flags, sc->indent, fyewt_indicator);
fy_emit_token_comment(emit, fyt_value, sc->flags, sc->indent, fycp_right);
- if (last && sc->flow && (sc->flags & DDNF_HANGING_INDENT) && !fy_emit_is_oneline_or_compact(emit) && !sc->empty)
+ needs_hanging_indent = sc->flow && !fy_emit_is_oneline_or_compact(emit) && !sc->empty;
+
+ if (last && needs_hanging_indent && (sc->flags & DDNF_HANGING_INDENT))
fy_emit_write_indent(emit, sc->old_indent);
+ else if (needs_hanging_indent)
+ sc->flags |= DDNF_HANGING_INDENT;
sc->flags &= ~DDNF_MAP;
}
enum fy_emitter_cfg_flags dsm_flags = flags & FYECF_DOC_START_MARK(FYECF_DOC_START_MARK_MASK);
bool vd, td, dsm;
bool had_non_default_tag = false;
+ bool strip_doc = false;
if (!emit || !fyds || emit->fyds)
return -1;
+ strip_doc = !!(emit->xcfg.cfg.flags & FYECF_STRIP_DOC);
+
emit->fyds = fy_document_state_ref(fyds);
vd = ((vd_flags == FYECF_VERSION_DIR_AUTO && fyds->version_explicit) ||
vd_flags == FYECF_VERSION_DIR_ON) &&
- !(emit->xcfg.cfg.flags & FYECF_STRIP_DOC);
+ !strip_doc;
td = ((td_flags == FYECF_TAG_DIR_AUTO && fyds->tags_explicit) ||
td_flags == FYECF_TAG_DIR_ON) &&
- !(emit->xcfg.cfg.flags & FYECF_STRIP_DOC);
+ !strip_doc;
/* if either a version or directive tags exist, and no previous
* explicit document end existed, output one now
if (!fy_emit_is_json_mode(emit) && (vd || td) && !(emit->flags & FYEF_HAD_DOCUMENT_END)) {
if (emit->column)
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- if (!(emit->xcfg.cfg.flags & FYECF_STRIP_DOC)) {
+ if (!strip_doc) {
fy_emit_puts_simple(emit, fyewt_document_indicator, "...");
emit->flags &= ~FYEF_WHITESPACE;
emit->flags |= FYEF_HAD_DOCUMENT_END;
fy_emit_printf(emit, fyewt_version_directive, "%%YAML %d.%d",
fyds->version.major, fyds->version.minor);
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
}
if (!fy_emit_is_json_mode(emit) && td) {
(int)td_handle_size, td_handle,
(int)td_prefix_size, td_prefix);
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
}
}
*/
dsm = (dsm_flags == FYECF_DOC_START_MARK_AUTO &&
(!fyds->start_implicit ||
- fyds->tags_explicit || fyds->version_explicit ||
- had_non_default_tag)) ||
+ (fyds->tags_explicit && had_non_default_tag) ||
+ fyds->version_explicit )) ||
dsm_flags == FYECF_DOC_START_MARK_ON;
/* if there was previous output without document end */
!(emit->flags & FYEF_HAD_DOCUMENT_END))
dsm = true;
+ /* there was *any* document end output (and no document end) */
+ if (!dsm && (emit->flags & FYEF_HAD_DOCUMENT_END_OUTPUT) &&
+ !(emit->flags & FYEF_HAD_DOCUMENT_END))
+ dsm = true;
+
/* output document start indicator if we should */
- if (dsm)
+ if (dsm && !fy_emit_is_json_mode(emit))
fy_emit_document_start_indicator(emit);
/* clear that in any case */
if (!(emit->xcfg.cfg.flags & FYECF_NO_ENDING_NEWLINE)) {
if (emit->column != 0) {
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
}
if (!fy_emit_is_json_mode(emit) && dem) {
fy_emit_puts_simple(emit, fyewt_document_indicator, "...");
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
emit->flags |= FYEF_HAD_DOCUMENT_END;
} else
emit->flags &= ~FYEF_HAD_DOCUMENT_END;
if (!fy_emit_is_json_mode(emit) && dem) {
if (emit->column != 0) {
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
}
fy_emit_puts_simple(emit, fyewt_document_indicator, "...");
emit->flags &= ~(FYEF_WHITESPACE | FYEF_INDENTATION);
if (emit->column != 0) {
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
}
if (!fy_emit_is_json_mode(emit)) {
fy_emit_puts_simple(emit, fyewt_document_indicator, "...");
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
emit->flags |= FYEF_HAD_DOCUMENT_END;
} else
emit->flags &= ~FYEF_HAD_DOCUMENT_END;
emit->column = 0;
emit->flow_level = 0;
emit->output_error = 0;
- /* start as if there was a previous document with an explicit end */
- /* this allows implicit documents start without an indicator */
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION | FYEF_HAD_DOCUMENT_END;
+ /* clear/set flags for a fresh start */
+ emit->flags &= ~(FYEF_OPEN_ENDED | FYEF_HAD_DOCUMENT_START | FYEF_HAD_DOCUMENT_OUTPUT);
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
emit->state = FYES_NONE;
free(emit->sc_stack);
fy_diag_unref(emit->diag);
+
+ if (emit->owned_output_fp)
+ fclose(emit->owned_output_fp);
}
int fy_emit_node_no_check(struct fy_emitter *emit, struct fy_node *fyn)
if (fye->type != FYET_ALIAS && fye->type != FYET_SCALAR &&
(emit->s_flags & DDNF_ROOT) && emit->column != 0) {
fy_emit_putc_simple(emit, fyewt_linebreak, '\n');
- emit->flags = FYEF_WHITESPACE | FYEF_INDENTATION;
+ emit->flags |= FYEF_WHITESPACE | FYEF_INDENTATION;
}
emit->s_flags = flags;
fy_emit_reset(emit, false);
fy_emit_goto_state(emit, FYES_DOCUMENT_START);
+ emit->flags |= FYEF_HAD_DOCUMENT_END_OUTPUT;
return 0;
}
return stderr;
case FYEXCF_OUTPUT_FILE:
return fye->xcfg.output_fp;
+ case FYEXCF_OUTPUT_FILENAME:
+ if (!fye->owned_output_fp && fye->xcfg.output_filename)
+ fye->owned_output_fp = fopen(fye->xcfg.output_filename, "wb");
+ return fye->owned_output_fp;
default:
break;
}
#define FYEF_HAD_DOCUMENT_START 0x0008
#define FYEF_HAD_DOCUMENT_END 0x0010
#define FYEF_HAD_DOCUMENT_OUTPUT 0x0020
+#define FYEF_HAD_DOCUMENT_END_OUTPUT 0x0040
struct fy_document;
struct fy_emitter;
FILE *output_fp;
int output_fd;
bool output_colorize;
+ FILE *owned_output_fp;
struct fy_document *fyd;
struct fy_document_state *fyds; /* fyd->fyds when fyd != NULL */
handle->end_mark.line = 0;
handle->end_mark.column = fy_utf8_count(data, size);
/* if it's plain, all is good */
- if ((simple || (aflags & FYACF_FLOW_PLAIN)) && !(aflags & FYACF_LB)) {
+ if ((simple || (aflags & FYACF_FLOW_PLAIN)) &&
+ !(aflags & (FYACF_LB | FYACF_ENDS_WITH_COLON))) {
handle->storage_hint = size; /* maximum */
handle->storage_hint_valid = false;
handle->direct_output = !!(aflags & FYACF_JSON_ESCAPE);
/* last character */
if (cn < 0) {
- /* if ends with whitespace or linebreak, can't be plain */
- if (fy_is_ws(c) || fy_token_is_lb(fyt, c))
+ /* if ends with whitespace or linebreak, or : can't be plain */
+ if (fy_is_ws(c) || fy_token_is_lb(fyt, c) || c == ':') {
flags &= ~(FYTTAF_CAN_BE_PLAIN |
FYTTAF_CAN_BE_PLAIN_FLOW);
+ if (c == ':')
+ flags |= FYTTAF_ENDS_WITH_COLON;
+ }
}
}
s = data;
e = data + size;
+ /* if it ends in : can't be a plain */
+ if (e > s && e[-1] == ':') {
+ flags &= ~(FYACF_BLOCK_PLAIN | FYACF_FLOW_PLAIN);
+ flags |= FYACF_ENDS_WITH_COLON;
+ }
+
col = 0;
first = true;
lastc = -1;
#define FYACF_SIZE0 0x020000 /* contains absolutely nothing */
#define FYACF_VALID_ANCHOR 0x040000 /* contains valid anchor (without & prefix) */
#define FYACF_JSON_ESCAPE 0x080000 /* contains a character that JSON escapes */
+#define FYACF_ENDS_WITH_COLON 0x100000 /* ends with : */
/* analysis flags */
#define FYTTAF_HAS_LB FY_BIT(0)
#define FYTTAF_HAS_START_IND FY_BIT(19) /* has --- at col 0 */
#define FYTTAF_HAS_END_IND FY_BIT(20) /* has ... at col 0 */
#define FYTTAF_HAS_NON_PRINT FY_BIT(21) /* has any non printable utf8 */
+#define FYTTAF_ENDS_WITH_COLON FY_BIT(22) /* ends with a colon */
#define FYTTAF_ANALYZED FY_BIT(31) /* analyzed mark */
void fy_path_parser_setup(struct fy_path_parser *fypp, const struct fy_path_parse_cfg *pcfg)
{
+ struct fy_diag_cfg dcfg;
+
if (!fypp)
return;
memset(fypp, 0, sizeof(*fypp));
if (pcfg)
fypp->cfg = *pcfg;
+ if (!fypp->cfg.diag) {
+ fy_diag_cfg_default(&dcfg);
+ fypp->cfg.diag = fy_diag_create(&dcfg);
+ fypp->owns_diag = true;
+ }
fy_reader_setup(&fypp->reader, &fy_path_parser_reader_ops);
fy_token_list_init(&fypp->queued_tokens);
fypp->last_queued_token_type = FYTT_NONE;
fypp->paren_nest_level = 0;
}
-void fy_path_parser_cleanup(struct fy_path_parser *fypp)
+int fy_path_parser_reset(struct fy_path_parser *fypp)
{
struct fy_path_expr *expr;
if (!fypp)
- return;
+ return -1;
fy_expr_stack_cleanup(&fypp->operands);
fy_expr_stack_cleanup(&fypp->operators);
fypp->stream_error = false;
fypp->token_activity_counter = 0;
fypp->paren_nest_level = 0;
+
+ return 0;
+}
+
+void fy_path_parser_cleanup(struct fy_path_parser *fypp)
+{
+ if (!fypp)
+ return;
+
+ fy_path_parser_reset(fypp);
+ if (fypp->owns_diag && fypp->cfg.diag)
+ fy_diag_unref(fypp->cfg.diag);
+ memset(fypp, 0, sizeof(*fypp));
}
int fy_path_parser_open(struct fy_path_parser *fypp,
int fy_path_fetch_tokens(struct fy_path_parser *fypp)
{
enum fy_token_type type;
- struct fy_token *fyt;
+ struct fy_token *fyt = NULL;
struct fy_reader *fyr;
int c, cn, rc, simple_token_count;
fyt = fy_path_token_queue(fypp, FYTT_STREAM_START, fy_reader_fill_atom_a(fyr, 0));
fyr_error_check(fyr, fyt, err_out, "fy_path_token_queue() failed\n");
+ fyt = NULL;
fypp->stream_start_produced = true;
return 0;
/* produce stream end continuously */
fyt = fy_path_token_queue(fypp, FYTT_STREAM_END, fy_reader_fill_atom_a(fyr, 0));
fyr_error_check(fyr, fyt, err_out, "fy_path_token_queue() failed\n");
+ fyt = NULL;
return 0;
}
if (simple_token_count > 0) {
fyt = fy_path_token_queue(fypp, type, fy_reader_fill_atom_a(fyr, simple_token_count));
fyr_error_check(fyr, fyt, err_out, "fy_path_token_queue() failed\n");
+ fyt = NULL;
return 0;
}
struct fy_reader *fyr;
struct fy_token *fyt = NULL;
enum fy_token_type fytt;
- struct fy_path_expr *expr, *expr_top, *exprt;
+ struct fy_path_expr *expr = NULL, *expr_top, *exprt;
enum fy_expr_mode old_scan_mode, prev_scan_mode;
int ret, rc;
return expr;
err_out:
+ if (expr)
+ fy_path_expr_free(expr);
#ifdef DEBUG_EXPR
fy_notice(fypp->cfg.diag, "operator stack (error)\n");
fy_expr_stack_dump(fypp->cfg.diag, &fypp->operators);
free(fypp);
}
-int fy_path_parser_reset(struct fy_path_parser *fypp)
-{
- if (!fypp)
- return -1;
- fy_path_parser_cleanup(fypp);
- return 0;
-}
-
struct fy_path_expr *
fy_path_parse_expr_from_string(struct fy_path_parser *fypp,
const char *str, size_t len)
if (!set) {
/* on unselect, return input, on select return NULL */
- return op == FYWRSO_UNSELECT ? input : NULL;
+ if (op == FYWRSO_UNSELECT)
+ return input;
+
+ fy_walk_result_free(input);
+ return NULL;
}
assert(input->type == fwrt_node_ref || input->type == fwrt_refs);
if (!output) {
/* nothing? nothing was removed or nothing was selected */
- return op == FYWRSO_UNSELECT ? input : NULL;
+ if (op == FYWRSO_UNSELECT)
+ return input;
+
+ fy_walk_result_free(input);
+ return NULL;
}
/* simplify (might remove everything if empty) */
bool stream_start_produced;
bool stream_end_produced;
bool stream_error;
+ bool owns_diag;
int token_activity_counter;
struct fy_input *fyi;
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#define ALLOW_DUPLICATE_KEYS_DEFAULT false
#define STRIP_EMPTY_KV_DEFAULT false
#define TSV_FORMAT_DEFAULT false
+#define NO_ENDING_NEWLINE_DEFAULT false
#define OPT_DUMP 1000
#define OPT_TESTSUITE 1001
#define OPT_DISABLE_DOC_MARKERS 2022
#define OPT_DISABLE_SCALAR_STYLES 2023
#define OPT_NO_STREAMING 2024
+#define OPT_NO_ENDING_NEWLINE 2025
#define OPT_DISABLE_DIAG 3000
#define OPT_ENABLE_DIAG 3001
{"disable-depth-limit", no_argument, 0, OPT_DISABLE_DEPTH_LIMIT },
{"disable-mmap", no_argument, 0, OPT_DISABLE_MMAP },
{"disable-diag", required_argument, 0, OPT_DISABLE_DIAG },
- {"enable-diag", required_argument, 0, OPT_ENABLE_DIAG },
+ {"enable-diag", required_argument, 0, OPT_ENABLE_DIAG },
{"show-diag", required_argument, 0, OPT_SHOW_DIAG },
- {"hide-diag", required_argument, 0, OPT_HIDE_DIAG },
+ {"hide-diag", required_argument, 0, OPT_HIDE_DIAG },
{"yaml-1.1", no_argument, 0, OPT_YAML_1_1 },
{"yaml-1.2", no_argument, 0, OPT_YAML_1_2 },
{"yaml-1.3", no_argument, 0, OPT_YAML_1_3 },
{"document-event-stream",no_argument, 0, OPT_DOCUMENT_EVENT_STREAM },
{"noexec", no_argument, 0, OPT_NOEXEC },
{"null-output", no_argument, 0, OPT_NULL_OUTPUT },
+ {"no-ending-newline", no_argument, 0, OPT_NO_ENDING_NEWLINE },
{"collect-errors", no_argument, 0, OPT_COLLECT_ERRORS },
{"allow-duplicate-keys",no_argument, 0, OPT_ALLOW_DUPLICATE_KEYS },
{"strip-empty-kv", no_argument, 0, OPT_STRIP_EMPTY_KV },
{"help", no_argument, 0, 'h' },
{"version", no_argument, 0, 'v' },
- {0, 0, 0, 0 },
+ {0, 0, 0, 0 },
};
static void display_usage(FILE *fp, char *progname, int tool_mode)
fprintf(fp, "\t--indent, -i <indent> : Set dump indent to <indent>"
" (default indent %d)\n",
INDENT_DEFAULT);
- fprintf(fp, "\t--width, -w <width> : Set dump width to <width>"
+ fprintf(fp, "\t--width, -w <width> : Set dump width to <width> - inf for infinite"
" (default width %d)\n",
WIDTH_DEFAULT);
fprintf(fp, "\t--resolve, -r : Perform anchor and merge key resolution"
fprintf(fp, "\t--ypath-aliases : Use YPATH aliases (default %s)\n",
YPATH_ALIASES_DEFAULT ? "true" : "false");
fprintf(fp, "\t--null-output : Do not generate output (for scanner profiling)\n");
+ fprintf(fp, "\t--no-ending-newline : Do not generate a final newline\n");
fprintf(fp, "\t--collect-errors : Collect errors instead of outputting directly"
" (default %s)\n",
COLLECT_ERRORS_DEFAULT ? "true" : "false");
length = 0;
s = linebuf;
- while (isxdigit(*s))
+ while (isxdigit((unsigned char)*s))
s++;
length = s - linebuf;
- if (length == 0 || length > (FY_BLAKE3_OUT_LEN * 2) || (length % 1) || !isspace(*s)) {
+ if (length == 0 || length > (FY_BLAKE3_OUT_LEN * 2) || (length % 1) || !isspace((unsigned char)*s)) {
fprintf(stderr, "Bad line found at file \"%s\" line #%d\n", check_filename, line);
fprintf(stderr, "%s\n", linebuf);
goto err_out;
*s++ = '\0';
- while (isspace(*s))
+ while (isspace((unsigned char)*s))
s++;
length >>= 1; /* to bytes */
FYEXCF_COLOR_NONE) |
FYEXCF_OUTPUT_STDOUT;
- while ((opt = getopt_long_only(argc, argv,
+ while ((opt = getopt_long(argc, argv,
"I:" "d:" "i:" "w:" "rsc" "C:" "m:" "V" "f:" "t:" "T:F:" "j:" "qhvl",
lopts, &lidx)) != -1) {
switch (opt) {
break;
case 'i':
indent = atoi(optarg);
- if (indent < 0 || indent > FYECF_INDENT_MASK) {
+ if (indent <= 0 || indent > FYECF_INDENT_MASK) {
fprintf(stderr, "bad indent option %s\n", optarg);
goto err_out_usage;
}
break;
case 'w':
- width = atoi(optarg);
- if (width < 0 || width > FYECF_WIDTH_MASK) {
- fprintf(stderr, "bad width option %s\n", optarg);
- goto err_out_usage;
+ if (!strcmp(optarg, "inf")) {
+ width = 0; /* infinite */
+ } else {
+ width = atoi(optarg);
+ if (width <= 8 || width > FYECF_WIDTH_MASK) { /* it should fit %YAML 1.3 at least */
+ fprintf(stderr, "bad width option %s\n", optarg);
+ goto err_out_usage;
+ }
}
manual_width = true;
break;
break;
case OPT_NULL_OUTPUT:
null_output = true;
+ emit_xflags |= FYEXCF_NULL_OUTPUT;
+ break;
+ case OPT_NO_ENDING_NEWLINE:
+ emit_flags |= FYECF_NO_ENDING_NEWLINE;
break;
case OPT_YAML_1_1:
cfg.flags &= ~(FYPCF_DEFAULT_VERSION_MASK << FYPCF_DEFAULT_VERSION_SHIFT);
/* if we're dumping to a non tty stdout width is infinite */
if (tool_mode == OPT_DUMP && !isatty(fileno(stdout)) && !manual_width)
emit_width_flags = FYECF_WIDTH_INF;
- else
+ else if (width > 0)
emit_width_flags = FYECF_WIDTH(width);
+ else
+ emit_width_flags = FYECF_WIDTH_INF;
memset(&emit_xcfg, 0, sizeof(emit_xcfg));
emit_xcfg.cfg.flags = emit_flags | emit_width_flags |
#ifndef FY_ENDIAN_H
#define FY_ENDIAN_H
-#if defined(__linux__) || defined(__CYGWIN__) || defined(__OpenBSD__)
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__OpenBSD__) || defined(__GNU__)
# include <endian.h>
#elif defined(__APPLE__)
# include <libkern/OSByteOrder.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include "fy-utils.h"
e = iter->end;
/* skip whitespace */
- while (s < e && isblank(*s))
+ while (s < e && isblank((unsigned char)*s))
s++;
if (s >= e)
le -= 2;
/* backtrack while there's space at the end of line */
- while (le > s && isblank(le[-1]))
+ while (le > s && isblank((unsigned char)le[-1]))
le--;
/* check if the whole line is punctuation so it's formatting */
t = s;
- while (t < le && ispunct(*t))
+ while (t < le && ispunct((unsigned char)*t))
t++;
/* everything is punctuation? */
}
/* something is there, skip over '// ' or '* ' */
- if ((le - s) > 3 && s[0] == '/' && s[1] == '/' && isblank(s[2]))
+ if ((le - s) > 3 && s[0] == '/' && s[1] == '/' && isblank((unsigned char)s[2]))
s += 3;
- else if ((le - s) > 2 && s[0] == '*' && isblank(s[1]))
+ else if ((le - s) > 2 && s[0] == '*' && isblank((unsigned char)s[1]))
s += 2;
- else if (iter->line == 0 && (le - s) > 3 && s[0] == '/' && s[1] == '*' && isblank(s[2]))
+ else if (iter->line == 0 && (le - s) > 3 && s[0] == '/' && s[1] == '*' && isblank((unsigned char)s[2]))
s += 3;
iter->line++;
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#ifdef __linux__
#include <linux/limits.h>
#endif
#include <getopt.h>
#include <unistd.h>
#include <limits.h>
+
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
+#endif
+
#include <check.h>
fy_valgrind_check(&argc, &argv);
- while ((opt = getopt_long_only(argc, argv, "qh", lopts, &lidx)) != -1) {
+ while ((opt = getopt_long(argc, argv, "qh", lopts, &lidx)) != -1) {
switch (opt) {
case 'q':
quiet = true;
#!/usr/bin/env bash
-if [ "x$builddir" == "x" ]; then
+if [ "x$builddir" = "x" ]; then
T=`realpath ./libfyaml-test`
else
T=`realpath ${builddir}/libfyaml-test`
EXTRA_DUMP_ARGS=""
-if [ "x$1" == "x--streaming" ]; then
+if [ "x$1" = "x--streaming" ]; then
EXTRA_DUMP_ARGS="$EXTRA_DUMP_ARGS --streaming"
-elif [ "x$1" == "x--restreaming" ]; then
+elif [ "x$1" = "x--restreaming" ]; then
EXTRA_DUMP_ARGS="$EXTRA_DUMP_ARGS --streaming --recreating"
fi
fi
# all errors test are expected to fail
- if [ "$pass_parse" == "1" ]; then
+ if [ "$pass_parse" = "1" ]; then
diff -u "$t1" "$t2"
if [ $? -eq 0 ]; then
res="ok"
echo "$errmsg" >"$t"
# all errors test are expected to fail
- if [ "$pass_yaml" == "0" ]; then
+ if [ "$pass_yaml" = "0" ]; then
res="ok"
# diff is pointless under valgrind
- if [ "x$USE_VALGRIND" == "x" ]; then
+ if [ "x$USE_VALGRIND" = "x" ]; then
diff_err=0
diff -u "$dir/test.error" "$t"
if [ $? -eq 0 ]; then
fi
res="ok"
- if [ "x$skip_reason" == "x" ]; then
+ if [ "x$skip_reason" = "x" ]; then
res="not ok"
t=`mktemp`
fi
res="ok"
- if [ "x$skip_reason" == "x" ]; then
+ if [ "x$skip_reason" = "x" ]; then
t1=`mktemp`
t2=`mktemp`
fi
res="ok"
- if [ "x$skip_reason" == "x" ]; then
+ if [ "x$skip_reason" = "x" ]; then
res="not ok"
${TOP_BUILDDIR}/src/fy-tool --dump --resolve "$tst/in.yaml" | ${TOP_BUILDDIR}/src/fy-tool --testsuite --disable-flow-markers - >"$t1"
directive=""
for skip in $skiplist; do
- if [ "$test_subtest_id" == "$skip" ]; then
+ if [ "$test_subtest_id" = "$skip" ]; then
directive=" # SKIP"
break
fi
done
res="ok"
- if [ "x$directive" == "x" ]; then
+ if [ "x$directive" = "x" ]; then
res="not ok"
pass_yaml=0
if [ -e "$tst/error" ]; then
# test is expected to fail
- if [ $pass_yaml == "0" ]; then
+ if [ $pass_yaml = "0" ]; then
res="ok"
else
res="not ok"
fi
else
# test is expected to pass
- if [ $pass_yaml == "1" ]; then
+ if [ $pass_yaml = "1" ]; then
diff_yaml=0
# diff -u "$tst/test.event" "$t" | sed -e 's/^/# /'
diff -u "$tst/test.event" "$t"
rm -f "$t"
for xfail in $xfaillist; do
- if [ "$test_subtest_id" == "$xfail" ]; then
+ if [ "$test_subtest_id" = "$xfail" ]; then
directive=" # TODO: known failure."
break
fi