]> gitweb.michael.orlitzky.com - iconv-quirks.git/commitdiff
Initial commit
authorMichael Orlitzky <michael@orlitzky.com>
Sat, 4 Jul 2026 16:30:04 +0000 (12:30 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Sat, 4 Jul 2026 16:30:04 +0000 (12:30 -0400)
Makefile [new file with mode: 0644]
main.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..787fdff
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,6 @@
+# main.c -> main.o -> main uses implicit rules
+all: main
+
+.PHONY: clean
+clean:
+       rm -f main main.o
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..fb4f9bd
--- /dev/null
+++ b/main.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <errno.h>
+#include <iconv.h>
+
+/* The various invalid sequences can be inferred from the table of
+ * valid ones,
+ *
+ * https://www.unicode.org/versions/Unicode17.0.0/core-spec/chapter-3/#G27506
+ *
+ * Code Points           Byte1     Byte2     Byte3     Byte4
+ * ----------------------------------------------------------
+ * U+0000..U+007F        00..7F
+ * U+0080..U+07FF        C2..DF    80..BF
+ * U+0800..U+0FFF        E0        A0..BF    80..BF
+ * U+1000..U+CFFF        E1..EC    80..BF    80..BF
+ * U+D000..U+D7FF        ED        80..9F    80..BF
+ * U+E000..U+FFFF        EE..EF    80..BF    80..BF
+ * U+10000..U+3FFFF      F0        90..BF    80..BF    80..BF
+ * U+40000..U+FFFFF      F1..F3    80..BF    80..BF    80..BF
+ * U+100000..U+10FFFF    F4        80..8F    80..BF    80..BF
+ *
+ * In particular:
+ *
+ * (a) 0x00-0x7F are the only valid standalone bytes
+ * (b) 0xC2-0xF4 initiate a multi-byte sequence
+ * (c) 0x80-0xBF only valid as byte >= 2 of a multi-byte sequence
+ * (d) 0xC0, 0xC1, 0xF5-0xFF are never valid
+ */
+
+#define ICONV_OPEN_FAILED 1
+#define ICONV_CLOSE_FAILED 2
+
+int main(int argc, char** argv) {
+  const char* tocode = "UTF-8";
+  const char* fromcode = "UTF-8";
+
+  iconv_t cd = iconv_open(tocode, fromcode);
+  if (cd == (iconv_t)(-1)) {
+    /* The errno values are standard, but we have no way of knowing
+     * if the implementation follows the standard! */
+    fprintf(stderr,
+           "ERROR: iconv_open(\"%s\", \"%s\") returned ",
+           tocode,
+           fromcode);
+    switch (errno) {
+      case EMFILE:
+       fprintf(stderr, "EMFILE");
+       break;
+      case ENFILE:
+       fprintf(stderr, "ENFILE");
+       break;
+      case ENOMEM:
+       fprintf(stderr, "ENOMEM");
+       break;
+      case EINVAL:
+       fprintf(stderr, "EINVAL");
+       break;
+      default:
+       fprintf(stderr, "UNKNOWN");
+    }
+    fprintf(stderr, "\n");
+    return ICONV_OPEN_FAILED;
+  }
+
+  /* actual conversion takes place here */
+
+  if (iconv_close(cd) == -1) {
+    /* The underlying type of iconv_t is unspecified, so we can't
+     * easily print the argument here. */
+    fprintf(stderr, "ERROR: iconv_close() returned ");
+    switch (errno) {
+      case EBADF:
+       fprintf(stderr, "EBADF");
+       break;
+      default:
+       fprintf(stderr, "UNKNOWN");
+    }
+    fprintf(stderr, "\n");
+    return ICONV_CLOSE_FAILED;
+  }
+
+  return 0;
+}