Diary

Previous: 2026-10, 2026-09

2026-11-03

A good written history that's here to teach https://tomasp.net/longreads/closing/

Most software we use today is black-box and cannot be easily modified by its users. This article follows the history of information hiding from OS/360 to Free Software and the history of the Web and documents how software becomes opaque through well-intended engineering decisions

And what it teaches me, in particular?

Nothing, as usual.

But as a reading, it is good.

โ™กโ™กโ™ก

It's been a long time since I dealt with iconv. So long that I don't even remember how I handled errors. Okay, I open man page and see the following three cases (out of five) where conversion stops because of invalid or unconvertible input:

  1. An invalid multibyte sequence is encountered in the input. In this case it sets errno to EILSEQ and returns (size_t)(โˆ’1). *inbuf is left pointing to the beginning of the invalid multibyte sequence.

  2. A multibyte sequence is encountered that is valid but that cannot be translated to the character encoding of the output. This condition depends on the implementation and on the conversion descriptor. In the GNU C library and GNU libiconv, if cd was created without the suffix //TRANSLIT or //IGNORE or //NON_IDENTICAL_DISCARD, the conversion is strict: lossy conversions produce this condition. If the suffix //TRANSLIT was specified, transliteration can avoid this condition in some cases. In the musl C library, this condition cannot occur because a conversion to '*' is used as a fallback. In the FreeBSD, NetBSD, and Solaris implementations of iconv, this condition cannot occur either, because a conversion to '?' is used as a fallback. When this condition is met, the iconv function sets errno to EILSEQ and returns (size_t)(โˆ’1). *inbuf is left pointing to the beginning of the unconvertible multibyte sequence.

  3. An incomplete multibyte sequence is encountered in the input, and the input byte sequence terminates after it. In this case it sets errno to EINVAL and returns (size_t)(โˆ’1). *inbuf is left pointing to the beginning of the incomplete multibyte sequence.

The third case more or less clear: get more bytes and call again to continue. But the first twos... well, they both set errno to EILSEQ, they both return (size_t) -1, and they both leave *inbuf pointing to the beginning of multibute sequence, either invalid or unconvertible.

Someone tell me how the fuck I distinguish these two cases? Invalid from unconvertible? How do I handle unconvertible case by myself? How???

Okay, as I see in the most mentioned implementations this unconvertible condition cannot occur. But GNU.

This is a part of POSIX:2024. If they write such standards then I do not look this stupid to myself. This reconciles me with the world, a little, but I'm still feeling sad.

I need to waste some time to check the behavior on all those musl and FreeBSDs which I don't have at hand at the moment.

I am also curious whether and how iconv validates UTF-8 input. Do all those implementations use the same '?' and '*' fallback characters if I convert wrong UTF-8 to UTF-32? Not U+FFFD? How do they handle surrogate pairs?

Too many questions not covered on the man page and a lot of TODOs:

2026-11-01

It was a big temptation to use printf-style formatting, but there's a better one. I don't know where exactly it originates from, but it was (and probably still is) used in Python and allows referencing same argument multiple times.

I don't want any mini-language, so let it be simple: mandatory argument index (1-based) surrounded by curly brackets.

Any custom formatting must be done before calling pw_format function.

Wait, pw_format?

It just concatenates args. It must be something like... pw_argscat? No, it looks like scat.

Let it be pw_acat. It's more like in PetWay.