diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,7 @@
+## 5.8.0.1
+
+* Fix linking issues due to including `tuklib_mbstr_nonprint.c` and `tuklib_mbstr_wrap.c`
+
 ## 5.8.0
 
 * Update to 5.8.0 upstream sources
diff --git a/cbits/common/tuklib_mbstr.h b/cbits/common/tuklib_mbstr.h
deleted file mode 100644
--- a/cbits/common/tuklib_mbstr.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: 0BSD
-
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file       tuklib_mbstr.h
-/// \brief      Utility functions for handling multibyte strings
-///
-/// If not enough multibyte string support is available in the C library,
-/// these functions keep working with the assumption that all strings
-/// are in a single-byte character set without combining characters, e.g.
-/// US-ASCII or ISO-8859-*.
-//
-//  Author:     Lasse Collin
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef TUKLIB_MBSTR_H
-#define TUKLIB_MBSTR_H
-
-#include "tuklib_common.h"
-TUKLIB_DECLS_BEGIN
-
-#define tuklib_mbstr_width TUKLIB_SYMBOL(tuklib_mbstr_width)
-extern size_t tuklib_mbstr_width(const char *str, size_t *bytes);
-///<
-/// \brief      Get the number of columns needed for the multibyte string
-///
-/// This is somewhat similar to wcswidth() but works on multibyte strings.
-///
-/// \param      str         String whose width is to be calculated.
-/// \param      bytes       If this is not NULL, *bytes is set to the
-///                         value returned by strlen(str) (even if an
-///                         error occurs when calculating the width).
-///
-/// \return     On success, the number of columns needed to display the
-///             string e.g. in a terminal emulator is returned. On error,
-///             (size_t)-1 is returned. Possible errors include invalid,
-///             partial, or non-printable multibyte character in str.
-
-#define tuklib_mbstr_width_mem TUKLIB_SYMBOL(tuklib_mbstr_width_mem)
-extern size_t tuklib_mbstr_width_mem(const char *str, size_t len);
-///<
-/// \brief      Get the number of columns needed for the multibyte buffer
-///
-/// This is like tuklib_mbstr_width() except that this takes the buffer
-/// length in bytes as the second argument. This allows using the function
-/// for buffers that aren't terminated with '\0'.
-///
-/// \param      str         String whose width is to be calculated.
-/// \param      len         Number of bytes to read from str.
-///
-/// \return     On success, the number of columns needed to display the
-///             string e.g. in a terminal emulator is returned. On error,
-///             (size_t)-1 is returned. Possible errors include invalid,
-///             partial, or non-printable multibyte character in str.
-
-#define tuklib_mbstr_fw TUKLIB_SYMBOL(tuklib_mbstr_fw)
-extern int tuklib_mbstr_fw(const char *str, int columns_min);
-///<
-/// \brief      Get the field width for printf() e.g. to align table columns
-///
-/// Printing simple tables to a terminal can be done using the field field
-/// feature in the printf() format string, but it works only with single-byte
-/// character sets. To do the same with multibyte strings, tuklib_mbstr_fw()
-/// can be used to calculate appropriate field width.
-///
-/// The behavior of this function is undefined, if
-///   - str is NULL or not terminated with '\0';
-///   - columns_min <= 0; or
-///   - the calculated field width exceeds INT_MAX.
-///
-/// \return     If tuklib_mbstr_width(str, NULL) fails, -1 is returned.
-///             If str needs more columns than columns_min, zero is returned.
-///             Otherwise a positive integer is returned, which can be
-///             used as the field width, e.g. printf("%*s", fw, str).
-
-TUKLIB_DECLS_END
-#endif
diff --git a/cbits/common/tuklib_mbstr_fw.c b/cbits/common/tuklib_mbstr_fw.c
deleted file mode 100644
--- a/cbits/common/tuklib_mbstr_fw.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: 0BSD
-
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file       tuklib_mbstr_fw.c
-/// \brief      Get the field width for printf() e.g. to align table columns
-//
-//  Author:     Lasse Collin
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "tuklib_mbstr.h"
-
-
-extern int
-tuklib_mbstr_fw(const char *str, int columns_min)
-{
-	size_t len;
-	const size_t width = tuklib_mbstr_width(str, &len);
-	if (width == (size_t)-1)
-		return -1;
-
-	if (width > (size_t)columns_min)
-		return 0;
-
-	if (width < (size_t)columns_min)
-		len += (size_t)columns_min - width;
-
-	return (int)len;
-}
diff --git a/cbits/common/tuklib_mbstr_nonprint.c b/cbits/common/tuklib_mbstr_nonprint.c
deleted file mode 100644
--- a/cbits/common/tuklib_mbstr_nonprint.c
+++ /dev/null
@@ -1,162 +0,0 @@
-// SPDX-License-Identifier: 0BSD
-
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file       tuklib_mbstr_nonprint.c
-/// \brief      Find and replace non-printable characters with question marks
-//
-//  Author:     Lasse Collin
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "tuklib_mbstr_nonprint.h"
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#ifdef HAVE_MBRTOWC
-#	include <wchar.h>
-#	include <wctype.h>
-#else
-#	include <ctype.h>
-#endif
-
-
-static bool
-is_next_printable(const char *str, size_t len, size_t *next_len)
-{
-#ifdef HAVE_MBRTOWC
-	// This assumes that character sets with locking shift states aren't
-	// used, and thus mbsinit() is never needed.
-	mbstate_t ps;
-	memset(&ps, 0, sizeof(ps));
-
-	wchar_t wc;
-	*next_len = mbrtowc(&wc, str, len, &ps);
-
-	if (*next_len == (size_t)-2) {
-		// Incomplete multibyte sequence: Treat the whole sequence
-		// as a single non-printable multibyte character that ends
-		// the string.
-		*next_len = len;
-		return false;
-	}
-
-	// Check more broadly than just ret == (size_t)-1 to be safe
-	// in case mbrtowc() returns something weird. This check
-	// covers (size_t)-1 (that is, SIZE_MAX) too because len is from
-	// strlen() and the terminating '\0' isn't part of the length.
-	if (*next_len < 1 || *next_len > len) {
-		// Invalid multibyte sequence: Treat the first byte as
-		// a non-printable single-byte character. Decoding will
-		// be restarted from the next byte on the next call to
-		// this function.
-		*next_len = 1;
-		return false;
-	}
-
-#	if defined(_WIN32) && !defined(__CYGWIN__)
-	// On Windows, wchar_t stores UTF-16 code units, thus characters
-	// outside the Basic Multilingual Plane (BMP) don't fit into
-	// a single wchar_t. In an UTF-8 locale, UCRT's mbrtowc() returns
-	// successfully when the input is a non-BMP character but the
-	// output is the replacement character U+FFFD.
-	//
-	// iswprint() returns 0 for U+FFFD on Windows for some reason. Treat
-	// U+FFFD as printable and thus also all non-BMP chars as printable.
-	if (wc == 0xFFFD)
-		return true;
-#	endif
-
-	return iswprint((wint_t)wc) != 0;
-#else
-	(void)len;
-	*next_len = 1;
-	return isprint((unsigned char)str[0]) != 0;
-#endif
-}
-
-
-static bool
-has_nonprint(const char *str, size_t len)
-{
-	for (size_t i = 0; i < len; ) {
-		size_t next_len;
-		if (!is_next_printable(str + i, len - i, &next_len))
-			return true;
-
-		i += next_len;
-	}
-
-	return false;
-}
-
-
-extern bool
-tuklib_has_nonprint(const char *str)
-{
-	const int saved_errno = errno;
-	const bool ret = has_nonprint(str, strlen(str));
-	errno = saved_errno;
-	return ret;
-}
-
-
-extern const char *
-tuklib_mask_nonprint_r(const char *str, char **mem)
-{
-	const int saved_errno = errno;
-
-	// Free the old string, if any.
-	free(*mem);
-	*mem = NULL;
-
-	// If the whole input string contains only printable characters,
-	// return the input string.
-	const size_t len = strlen(str);
-	if (!has_nonprint(str, len)) {
-		errno = saved_errno;
-		return str;
-	}
-
-	// Allocate memory for the masked string. Since we use the single-byte
-	// character '?' to mask non-printable characters, it's possible that
-	// a few bytes less memory would be needed in reality if multibyte
-	// characters are masked.
-	//
-	// If allocation fails, return "???" because it should be safer than
-	// returning the unmasked string.
-	*mem = malloc(len + 1);
-	if (*mem == NULL) {
-		errno = saved_errno;
-		return "???";
-	}
-
-	// Replace all non-printable characters with '?'.
-	char *dest = *mem;
-
-	for (size_t i = 0; i < len; ) {
-		size_t next_len;
-		if (is_next_printable(str + i, len - i, &next_len)) {
-			memcpy(dest, str + i, next_len);
-			dest += next_len;
-		} else {
-			*dest++ = '?';
-		}
-
-		i += next_len;
-	}
-
-	*dest = '\0';
-
-	errno = saved_errno;
-	return *mem;
-}
-
-
-extern const char *
-tuklib_mask_nonprint(const char *str)
-{
-	static char *mem = NULL;
-	return tuklib_mask_nonprint_r(str, &mem);
-}
diff --git a/cbits/common/tuklib_mbstr_nonprint.h b/cbits/common/tuklib_mbstr_nonprint.h
deleted file mode 100644
--- a/cbits/common/tuklib_mbstr_nonprint.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// SPDX-License-Identifier: 0BSD
-
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file       tuklib_mbstr_nonprint.h
-/// \brief      Find and replace non-printable characters with question marks
-///
-/// If mbrtowc(3) is available, it and iswprint(3) is used to check if all
-/// characters are printable. Otherwise single-byte character set is assumed
-/// and isprint(3) is used.
-//
-//  Author:     Lasse Collin
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef TUKLIB_MBSTR_NONPRINT_H
-#define TUKLIB_MBSTR_NONPRINT_H
-
-#include "tuklib_common.h"
-TUKLIB_DECLS_BEGIN
-
-#define tuklib_has_nonprint TUKLIB_SYMBOL(tuklib_has_nonprint)
-extern bool tuklib_has_nonprint(const char *str);
-///<
-/// \brief      Check if a string contains any non-printable characters
-///
-/// \return     false if str contains only valid multibyte characters and
-///             iswprint(3) returns non-zero for all of them; true otherwise.
-///             The value of errno is preserved.
-///
-/// \note       In case mbrtowc(3) isn't available, single-byte character set
-///             is assumed and isprint(3) is used instead of iswprint(3).
-
-#define tuklib_mask_nonprint_r TUKLIB_SYMBOL(tuklib_mask_nonprint_r)
-extern const char *tuklib_mask_nonprint_r(const char *str, char **mem);
-///<
-/// \brief      Replace non-printable characters with question marks
-///
-/// \param      str     Untrusted string, for example, a filename
-/// \param      mem     This function always calls free(*mem) to free the old
-///                     allocation and then sets *mem = NULL. Before the first
-///                     call, *mem should be initialized to NULL. If this
-///                     function needs to allocate memory for a modified
-///                     string, a pointer to the allocated memory will be
-///                     stored to *mem. Otherwise *mem will remain NULL.
-///
-/// \return     If tuklib_has_nonprint(str) returns false, this function
-///             returns str. Otherwise memory is allocated to hold a modified
-///             string and a pointer to that is returned. The pointer to the
-///             allocated memory is also stored to *mem. A modified string
-///             has the problematic characters replaced by '?'. If memory
-///             allocation fails, "???" is returned and *mem is NULL.
-///             The value of errno is preserved.
-
-#define tuklib_mask_nonprint TUKLIB_SYMBOL(tuklib_mask_nonprint)
-extern const char *tuklib_mask_nonprint(const char *str);
-///<
-/// \brief      Replace non-printable characters with question marks
-///
-/// This is a convenience function for single-threaded use. This calls
-/// tuklib_mask_nonprint_r() using an internal static variable to hold
-/// the possible allocation.
-///
-/// \param      str     Untrusted string, for example, a filename
-///
-/// \return     See tuklib_mask_nonprint_r().
-///
-/// \note       This function is not thread safe!
-
-TUKLIB_DECLS_END
-#endif
diff --git a/cbits/common/tuklib_mbstr_width.c b/cbits/common/tuklib_mbstr_width.c
deleted file mode 100644
--- a/cbits/common/tuklib_mbstr_width.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: 0BSD
-
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file       tuklib_mbstr_width.c
-/// \brief      Calculate width of a multibyte string
-//
-//  Author:     Lasse Collin
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "tuklib_mbstr.h"
-#include <string.h>
-
-#ifdef HAVE_MBRTOWC
-#	include <wchar.h>
-#endif
-
-
-extern size_t
-tuklib_mbstr_width(const char *str, size_t *bytes)
-{
-	const size_t len = strlen(str);
-	if (bytes != NULL)
-		*bytes = len;
-
-	return tuklib_mbstr_width_mem(str, len);
-}
-
-
-extern size_t
-tuklib_mbstr_width_mem(const char *str, size_t len)
-{
-#ifndef HAVE_MBRTOWC
-	// In single-byte mode, the width of the string is the same
-	// as its length.
-	(void)str;
-	return len;
-
-#else
-	mbstate_t state;
-	memset(&state, 0, sizeof(state));
-
-	size_t width = 0;
-	size_t i = 0;
-
-	// Convert one multibyte character at a time to wchar_t
-	// and get its width using wcwidth().
-	while (i < len) {
-		wchar_t wc;
-		const size_t ret = mbrtowc(&wc, str + i, len - i, &state);
-		if (ret < 1 || ret > len - i)
-			return (size_t)-1;
-
-		i += ret;
-
-#ifdef HAVE_WCWIDTH
-		const int wc_width = wcwidth(wc);
-		if (wc_width < 0)
-			return (size_t)-1;
-
-		width += (size_t)wc_width;
-#else
-		// Without wcwidth() (like in a native Windows build),
-		// assume that one multibyte char == one column. With
-		// UTF-8, this is less bad than one byte == one column.
-		// This way quite a few languages will be handled correctly
-		// in practice; CJK chars will be very wrong though.
-		++width;
-#endif
-	}
-
-	// It's good to check that the string ended in the initial state.
-	// However, in practice this is redundant:
-	//
-	//   - No one will use this code with character sets that have
-	//     locking shift states.
-	//
-	//   - We already checked that mbrtowc() didn't return (size_t)-2
-	//     which would indicate a partial multibyte character.
-	if (!mbsinit(&state))
-		return (size_t)-1;
-
-	return width;
-#endif
-}
diff --git a/cbits/common/tuklib_mbstr_wrap.c b/cbits/common/tuklib_mbstr_wrap.c
deleted file mode 100644
--- a/cbits/common/tuklib_mbstr_wrap.c
+++ /dev/null
@@ -1,294 +0,0 @@
-// SPDX-License-Identifier: 0BSD
-
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file       tuklib_mbstr_wrap.c
-/// \brief      Word wraps a string and prints it to a FILE stream
-///
-/// This depends on tuklib_mbstr_width.c.
-//
-//  Author:     Lasse Collin
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "tuklib_mbstr.h"
-#include "tuklib_mbstr_wrap.h"
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-
-extern int
-tuklib_wraps(FILE *outfile, const struct tuklib_wrap_opt *opt, const char *str)
-{
-	// left_cont may be less than left_margin. In that case, if the first
-	// word is extremely long, it will stay on the first line even if
-	// the line then gets overlong.
-	//
-	// On the other hand, left2_cont < left2_margin isn't allowed because
-	// it could result in inconsistent behavior when a very long word
-	// comes right after a \v.
-	//
-	// It is fine to have left2_margin < left_margin although it would be
-	// an odd use case.
-	if (!(opt->left_margin < opt->right_margin
-			&& opt->left_cont < opt->right_margin
-			&& opt->left2_margin <= opt->left2_cont
-			&& opt->left2_cont < opt->right_margin))
-		return TUKLIB_WRAP_ERR_OPT;
-
-	// This is set to TUKLIB_WRAP_WARN_OVERLONG if one or more
-	// output lines extend past opt->right_margin columns.
-	int warn_overlong = 0;
-
-	// Indentation of the first output line after \n or \r.
-	// \v sets this to opt->left2_margin.
-	// \r resets this back to the original value.
-	size_t first_indent = opt->left_margin;
-
-	// Indentation of the output lines that occur due to word wrapping.
-	// \v sets this to opt->left2_cont and \r back to the original value.
-	size_t cont_indent = opt->left_cont;
-
-	// If word wrapping occurs, the newline isn't printed unless more
-	// text would be put on the continuation line. This is also used
-	// when \v needs to start on a new line.
-	bool pending_newline = false;
-
-	// Spaces are printed only when there is something else to put
-	// after the spaces on the line. This avoids unwanted empty lines
-	// in the output and makes it possible to ignore possible spaces
-	// before a \v character.
-	size_t pending_spaces = first_indent;
-
-	// Current output column. When cur_col == pending_spaces, nothing
-	// has been actually printed to the current output line.
-	size_t cur_col = pending_spaces;
-
-	while (true) {
-		// Number of bytes until the *next* line-break opportunity.
-		size_t len = 0;
-
-		// Number of columns until the *next* line-break opportunity.
-		size_t width = 0;
-
-		// Text between a pair of \b characters is treated as
-		// an unbreakable block even if it contains spaces.
-		// It must not contain any control characters before
-		// the closing \b.
-		bool unbreakable = false;
-
-		while (true) {
-			// Find the next character that we handle specially.
-			// In an unbreakable block, search only for the
-			// closing \b; if missing, the unbreakable block
-			// extends to the end of the string.
-			const size_t n = strcspn(str + len,
-					unbreakable ? "\b" : " \t\n\r\v\b");
-
-			// Calculate how many columns the characters need.
-			const size_t w = tuklib_mbstr_width_mem(str + len, n);
-			if (w == (size_t)-1)
-				return TUKLIB_WRAP_ERR_STR;
-
-			width += w;
-			len += n;
-
-			// \b isn't a line-break opportunity so it has to
-			// be handled here. For simplicity, empty blocks
-			// are treated as zero-width characters.
-			if (str[len] == '\b') {
-				++len;
-				unbreakable = !unbreakable;
-				continue;
-			}
-
-			break;
-		}
-
-		// Determine if adding this chunk of text would make the
-		// current output line exceed opt->right_margin columns.
-		const bool too_long = cur_col + width > opt->right_margin;
-
-		// Wrap the line if needed. However:
-		//
-		//   - Don't wrap if the current column is less than where
-		//     the continuation line would begin. In that case
-		//     the chunk wouldn't fit on the next line either so
-		//     we just have to produce an overlong line.
-		//
-		//   - Don't wrap if so far the line only contains spaces.
-		//     Wrapping in that case would leave a weird empty line.
-		//     NOTE: This "only contains spaces" condition is the
-		//     reason why left2_margin > left2_cont isn't allowed.
-		if (too_long && cur_col > cont_indent
-				&& cur_col > pending_spaces) {
-			// There might be trailing spaces or zero-width spaces
-			// which need to be ignored to keep the output pretty.
-			//
-			// Spaces need to be ignored because in some
-			// writing styles there are two spaces after
-			// a full stop. Example string:
-			//
-			//     "Foo bar.  Abc def."
-			//              ^
-			// If the first space after the first full stop
-			// triggers word wrapping, both spaces must be
-			// ignored. Otherwise the next line would be
-			// indented too much.
-			//
-			// Zero-width spaces are ignored the same way
-			// because they are meaningless if an adjacent
-			// character is a space.
-			while (*str == ' ' || *str == '\t')
-				++str;
-
-			// Don't print the newline here; only mark it as
-			// pending. This avoids an unwanted empty line if
-			// there is a \n or \r or \0 after the spaces have
-			// been ignored.
-			pending_newline = true;
-			pending_spaces = cont_indent;
-			cur_col = pending_spaces;
-
-			// Since str may have been incremented due to the
-			// ignored spaces, the loop needs to be restarted.
-			continue;
-		}
-
-		// Print the current chunk of text before the next
-		// line-break opportunity. If the chunk was empty,
-		// don't print anything so that the pending newline
-		// and pending spaces aren't printed on their own.
-		if (len > 0) {
-			if (pending_newline) {
-				pending_newline = false;
-				if (putc('\n', outfile) == EOF)
-					return TUKLIB_WRAP_ERR_IO;
-			}
-
-			while (pending_spaces > 0) {
-				if (putc(' ', outfile) == EOF)
-					return TUKLIB_WRAP_ERR_IO;
-
-				--pending_spaces;
-			}
-
-			for (size_t i = 0; i < len; ++i) {
-				// Ignore unbreakable block characters (\b).
-				const int c = (unsigned char)str[i];
-				if (c != '\b' && putc(c, outfile) == EOF)
-					return TUKLIB_WRAP_ERR_IO;
-			}
-
-			str += len;
-			cur_col += width;
-
-			// Remember if the line got overlong. If no other
-			// errors occur, we return warn_overlong. It might
-			// help in catching problematic strings.
-			if (too_long)
-				warn_overlong = TUKLIB_WRAP_WARN_OVERLONG;
-		}
-
-		// Handle the special character after the chunk of text.
-		switch (*str) {
-		case ' ':
-			// Regular space.
-			++cur_col;
-			++pending_spaces;
-			break;
-
-		case '\v':
-			// Set the alternative indentation settings.
-			first_indent = opt->left2_margin;
-			cont_indent = opt->left2_cont;
-
-			if (first_indent > cur_col) {
-				// Add one or more spaces to reach
-				// the column specified in first_indent.
-				pending_spaces += first_indent - cur_col;
-			} else {
-				// There is no room to add even one space
-				// before reaching the column first_indent.
-				pending_newline = true;
-				pending_spaces = first_indent;
-			}
-
-			cur_col = first_indent;
-			break;
-
-		case '\0': // Implicit newline at the end of the string.
-		case '\r': // Newline that also resets the effect of \v.
-		case '\n': // Newline without resetting the indentation mode.
-			if (putc('\n', outfile) == EOF)
-				return TUKLIB_WRAP_ERR_IO;
-
-			if (*str == '\0')
-				return warn_overlong;
-
-			if (*str == '\r') {
-				first_indent = opt->left_margin;
-				cont_indent = opt->left_cont;
-			}
-
-			pending_newline = false;
-			pending_spaces = first_indent;
-			cur_col = first_indent;
-			break;
-		}
-
-		// Skip the specially-handled character.
-		++str;
-	}
-}
-
-
-extern int
-tuklib_wrapf(FILE *stream, const struct tuklib_wrap_opt *opt,
-		const char *fmt, ...)
-{
-	va_list ap;
-	char *buf;
-
-#ifdef HAVE_VASPRINTF
-	va_start(ap, fmt);
-
-#ifdef __clang__
-#	pragma GCC diagnostic push
-#	pragma GCC diagnostic ignored "-Wformat-nonliteral"
-#endif
-	const int n = vasprintf(&buf, fmt, ap);
-#ifdef __clang__
-#	pragma GCC diagnostic pop
-#endif
-
-	va_end(ap);
-	if (n == -1)
-		return TUKLIB_WRAP_ERR_FORMAT;
-#else
-	// Fixed buffer size is dumb but in practice one shouldn't need
-	// huge strings for *formatted* output. This simple method is safe
-	// with pre-C99 vsnprintf() implementations too which don't return
-	// the required buffer size (they return -1 or buf_size - 1) or
-	// which might not null-terminate the buffer in case it's too small.
-	const size_t buf_size = 128 * 1024;
-	buf = malloc(buf_size);
-	if (buf == NULL)
-		return TUKLIB_WRAP_ERR_FORMAT;
-
-	va_start(ap, fmt);
-	const int n = vsnprintf(buf, buf_size, fmt, ap);
-	va_end(ap);
-
-	if (n <= 0 || n >= (int)(buf_size - 1)) {
-		free(buf);
-		return TUKLIB_WRAP_ERR_FORMAT;
-	}
-#endif
-
-	const int ret = tuklib_wraps(stream, opt, buf);
-	free(buf);
-	return ret;
-}
diff --git a/cbits/common/tuklib_mbstr_wrap.h b/cbits/common/tuklib_mbstr_wrap.h
deleted file mode 100644
--- a/cbits/common/tuklib_mbstr_wrap.h
+++ /dev/null
@@ -1,204 +0,0 @@
-// SPDX-License-Identifier: 0BSD
-
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file       tuklib_mbstr_wrap.h
-/// \brief      Word wrapping for multibyte strings
-///
-/// The word wrapping functions are intended to be usable, for example,
-/// for printing --help text in command line tools. While manually-wrapped
-/// --help text allows precise formatting, such freedom requires translators
-/// to count spaces and determine where line breaks should occur. It's
-/// tedious and error prone, and experience has shown that only some
-/// translators do it well. Automatic word wrapping is less flexible but
-/// results in polished-enough look with less effort from everyone.
-/// Right-to-left languages and languages that don't use spaces between
-/// words will still need extra effort though.
-//
-//  Author:     Lasse Collin
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef TUKLIB_MBSTR_WRAP_H
-#define TUKLIB_MBSTR_WRAP_H
-
-#include "tuklib_common.h"
-#include <stdio.h>
-
-TUKLIB_DECLS_BEGIN
-
-/// One or more output lines exceeded right_margin.
-/// This only a warning; everything was still printed successfully.
-#define TUKLIB_WRAP_WARN_OVERLONG   0x01
-
-/// Error writing to to the output FILE. The error flag in the FILE
-/// should have been set as well.
-#define TUKLIB_WRAP_ERR_IO          0x02
-
-/// Invalid options in struct tuklib_wrap_opt.
-/// Nothing was printed.
-#define TUKLIB_WRAP_ERR_OPT         0x04
-
-/// Invalid or unsupported multibyte character in the input string:
-/// either mbrtowc() failed or wcwidth() returned a negative value.
-#define TUKLIB_WRAP_ERR_STR         0x08
-
-/// Only tuklib_wrapf(): Error in converting the format string.
-/// It's either a memory allocation failure or something bad with the
-/// format string or arguments.
-#define TUKLIB_WRAP_ERR_FORMAT      0x10
-
-/// Options for tuklib_wraps() and tuklib_wrapf()
-struct tuklib_wrap_opt {
-	/// Indentation of the first output line after `\n` or `\r`.
-	/// This can be anything less than right_margin.
-	unsigned short left_margin;
-
-	/// Column where word-wrapped continuation lines start.
-	/// This can be anything less than right_margin.
-	unsigned short left_cont;
-
-	/// Column where the text after `\v` will start, either on the current
-	/// line (when there is room to add at least one space) or on a new
-	/// empty line.
-	unsigned short left2_margin;
-
-	/// Like left_cont but for text after a `\v`. However, this must
-	/// be greater than or equal to left2_margin in addition to being
-	/// less than right_margin.
-	unsigned short left2_cont;
-
-	/// For 80-column terminals, it is recommended to use 79 here for
-	/// maximum portability. 80 will work most of the time but it will
-	/// result in unwanted empty lines in the rare case where a terminal
-	/// moves the cursor to the beginning of the next line immediately
-	/// when the last column has been used.
-	unsigned short right_margin;
-};
-
-#define tuklib_wraps TUKLIB_SYMBOL(tuklib_wraps)
-extern int tuklib_wraps(FILE *stream, const struct tuklib_wrap_opt *opt,
-		const char *str);
-///<
-/// \brief      Word wrap a multibyte string and write it to a FILE
-///
-/// Word wrapping is done only at spaces and at the special control characters
-/// described below. Multiple consecutive spaces are handled properly: strings
-/// that have two (or more) spaces after a full sentence will look good even
-/// when the spaces occur at a word wrapping boundary. Trailing spaces are
-/// ignored at the end of a line or at the end of a string.
-///
-/// The following control characters have been repurposed:
-///
-///   - `\t` = Zero-width space allows a line break without producing any
-///            output by itself. This can be useful after hard hyphens as
-///            hyphens aren't otherwise used for line breaking. This can also
-///            be useful in languages that don't use spaces between words.
-///            (The Unicode character U+200B isn't supported.)
-///   - `\b` = Text between a pair of `\b` characters is treated as an
-///            unbreakable block (not wrapped even if there are spaces).
-///            For example, a non-breaking space can be done like
-///            in `"123\b \bMiB"`. Control characters (like `\n` or `\t`)
-///            aren't allowed before the closing `\b`. If closing `\b` is
-///            missing, the block extends to the end of the string. Empty
-///            blocks are treated as zero-width characters. If line breaks
-///            are possible around an empty block (like in `"foo \b\b bar"`
-///            or `"foo \b"`), it can result in weird output.
-///   - `\v` = Change to alternative indentation (left2_margin).
-///   - `\r` = Reset back to the initial indentation and add a newline.
-///            The next line will be indented by left_margin.
-///   - `\n` = Add a newline without resetting the effect of `\v`. The
-///            next line will be indented by left_margin or left2_margin
-///            (not left_cont or left2_cont).
-///
-/// Only `\n` should appear in translatable strings. `\t` works too but
-/// even that might confuse some translators even if there is a TRANSLATORS
-/// comment explaining its meaning.
-///
-/// To use the other control characters in messages, one should use
-/// tuklib_wrapf() with appropriate printf format string to combine
-/// translatable strings with non-translatable portions. For example:
-///
-/// \code{.c}
-/// static const struct tuklib_wrap_opt wrap2 = { 2,  2, 22, 22, 79 };
-/// int e = 0;
-/// ...
-/// e |= tuklib_wrapf(stdout, &wrap2,
-///                   "-h, --help\v%s\r"
-///                   "    --version\v%s",
-///                   W_("display this help and exit"),
-///                   W_("display version information and exit"));
-/// ...
-/// if (e != 0) {
-///     // Handle warning or error.
-///     ...
-/// }
-/// \endcode
-///
-/// Control characters other than `\n` and `\t` are unusable in
-/// translatable strings:
-///
-///   - Gettext tools show annoying warnings if C escape sequences other
-///     than `\n` or `\t` are seen. (Otherwise they still work perfectly
-///     fine though.)
-///
-///   - While at least Poedit and Lokalize support all escapes, some
-///     editors only support `\n` and `\t`.
-///
-///   - They could confuse some translators, resulting in broken
-///     translations.
-///
-/// Using non-control characters would solve some issues but it wouldn't
-/// help with the unfortunate real-world issue that some translators would
-/// likely have trouble understanding a new syntax. The Gettext manual
-/// specifically warns about this, see the subheading "No unusual markup"
-/// in `info (gettext)Preparing Strings`. (While using `\t` for zero-width
-/// space is such custom markup, most translators will never need it.)
-///
-/// Translators can use the Unicode character U+00A0 (or U+202F) if they
-/// need a non-breaking space. For example, in French a non-breaking space
-/// may be needed before colons and question marks (U+00A0 is common in
-/// real-world French PO files).
-///
-/// Using a non-ASCII char in a string in the C code (like `"123\u00A0MiB"`)
-/// can work if one tells xgettext that input encoding is UTF-8, one
-/// ensures that the C compiler uses UTF-8 as the input charset, and one
-/// is certain that the program is *always* run under an UTF-8 locale.
-/// Unfortunately a portable program cannot make this kind of assumptions,
-/// which means that there is no pretty way to have a non-breaking space in
-/// a translatable string.
-///
-/// Optional: To tell translators which strings are automatically word
-/// wrapped, see the macro `W_` in tuklib_gettext.h.
-///
-/// \param      stream      Output FILE stream. For decent performance, it
-///                         should be in buffered mode because this function
-///                         writes the output one byte at a time with fputc().
-/// \param      opt         Word wrapping options.
-/// \param      str         Null-terminated multibyte string that is in
-///                         the encoding used by the current locale.
-///
-/// \return     Returns 0 on success. If an error or warning occurs, one of
-///             TUKLIB_WRAP_* codes is returned. Those codes are powers
-///             of two. When warning/error detection can be delayed, the
-///             return values can be accumulated from multiple calls using
-///             bitwise-or into a single variable which can be checked after
-///             all strings have (hopefully) been printed.
-
-#define tuklib_wrapf TUKLIB_SYMBOL(tuklib_wrapf)
-tuklib_attr_format_printf(3, 4)
-extern int tuklib_wrapf(FILE *stream, const struct tuklib_wrap_opt *opt,
-		const char *fmt, ...);
-///<
-/// \brief      Format and word-wrap a multibyte string and write it to a FILE
-///
-/// This is like tuklib_wraps() except that this takes a printf
-/// format string.
-///
-/// \note       On platforms that lack vasprintf(), the intermediate
-///             result from vsnprintf() must fit into a 128 KiB buffer.
-///             TUKLIB_WRAP_ERR_FORMAT is returned if it doesn't but
-///             only on platforms that lack vasprintf().
-
-TUKLIB_DECLS_END
-#endif
diff --git a/xz-clib.cabal b/xz-clib.cabal
--- a/xz-clib.cabal
+++ b/xz-clib.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.2
 name:                xz-clib
-version:             5.8.0
+version:             5.8.0.1
 
 synopsis:            LZMA/XZ clibs
 description:         C source code for the LZMA/XZ compression and decompression library
@@ -54,8 +54,6 @@
   default-language:    Haskell2010
   c-sources:
     cbits/common/tuklib_cpucores.c
-    cbits/common/tuklib_mbstr_nonprint.c
-    cbits/common/tuklib_mbstr_wrap.c
     cbits/common/tuklib_physmem.c
     cbits/liblzma/check/check.c
     cbits/liblzma/check/crc32_fast.c
