Repository: tailix/libkernaux (language: python)

Issue:
Test on all architectures
Use binfmt

* [x] `aarch64` #87
* [x] `i386` #86
* [x] `riscv64` #87
* [x] `x86_64` (default)

Bindings:

* [ ] `aarch64`
* [ ] `i386`
* [ ] `riscv64`
* [x] `x86_64` (default)


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 126e8abb..5e1c9075 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -29,6 +29,29 @@ jobs:
       - name: install
         run: sudo make install
 
+  cross:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        cross:
+          - host: 'i386-unknown-elf'
+            apt: 'crossbuild-essential-i386'
+            cprefix: 'i686-linux-gnu-'
+    steps:
+      - uses: actions/checkout@v2
+      - name: dependencies
+        run: sudo apt-get --yes install ${{matrix.cross.apt}}
+      - name: autogen
+        run: ./autogen.sh
+      - name: configure
+        run: ./configure --host='${{matrix.cross.host}}' --enable-tests --enable-tests-python AR='${{matrix.cross.cprefix}}ar' CC='${{matrix.cross.cprefix}}gcc' LD='${{matrix.cross.cprefix}}ld' RANLIB='${{matrix.cross.cprefix}}ranlib'
+      - name: make
+        run: make
+      - name: check
+        run: make check || (./test-suite-log && false)
+      - name: install
+        run: sudo make install
+
   cond:
     runs-on: ubuntu-latest
     strategy:
diff --git a/.gitignore b/.gitignore
index fa56d74d..8f453765 100644
--- a/.gitignore
+++ b/.gitignore
@@ -147,4 +147,5 @@
 /tests/test_printf_fmt_gen.c
 /tests/test_printf_gen
 /tests/test_printf_gen.c
+/tests/test_printf_reg
 /tests/test_units_human
diff --git a/bindings/mruby/.rubocop.yml b/bindings/mruby/.rubocop.yml
index 1b268e56..084bd23b 100644
--- a/bindings/mruby/.rubocop.yml
+++ b/bindings/mruby/.rubocop.yml
@@ -25,6 +25,10 @@ Metrics/BlockLength:
     - 'Rakefile'
     - 'test/**/*.rb'
 
+Metrics/BlockNesting:
+  Exclude:
+    - 'test/printf.rb'
+
 Security/Eval:
   Exclude:
     - 'test/**/*.rb'
diff --git a/bindings/ruby/spec/lib/kernaux/printf/sprintf_spec.rb b/bindings/ruby/spec/lib/kernaux/printf/sprintf_spec.rb
index 7010b390..ba11072a 100644
--- a/bindings/ruby/spec/lib/kernaux/printf/sprintf_spec.rb
+++ b/bindings/ruby/spec/lib/kernaux/printf/sprintf_spec.rb
@@ -36,7 +36,13 @@
           else
             arg.map do |item|
               if item.is_a? Array
-                item[0]
+                if item.length == 1
+                  item[0]
+                elsif item[0] == 'long long'
+                  item[1]
+                else
+                  raise "Unknown format: #{args.inspect}"
+                end
               else
                 item
               end
diff --git a/common/printf_orig.yml b/common/printf_orig.yml
index 31513d65..5a4d8282 100644
--- a/common/printf_orig.yml
+++ b/common/printf_orig.yml
@@ -196,7 +196,7 @@
 - result: '0'
   args: [['%#.1x', 0]]
 - result: ''
-  args: [['%#.0llx', 0]]
+  args: [['%#.0llx', ['long long', 0]]]
 - result: '0x0000614e'
   args: [['%#.8x', 0x614e]]
 - result: '0b110'
diff --git a/configure.ac b/configure.ac
index 6e082a25..09070073 100644
--- a/configure.ac
+++ b/configure.ac
@@ -151,8 +151,6 @@ AS_IF([test "$with_libc"           = yes], [with_libc=yes],           [with_libc
 # Test args #
 #############
 
-AS_IF([test "$enable_tests"        = yes -a "$host_cpu" != "$build_cpu" ], AC_MSG_ERROR([can not build cross-platform tests]))
-AS_IF([test "$enable_tests_python" = yes -a "$host_cpu" != "$build_cpu" ], AC_MSG_ERROR([can not build cross-platform tests]))
 AS_IF([test "$enable_tests"        = yes -a "$enable_freestanding" = yes], AC_MSG_ERROR([can not build freestanding tests]))
 AS_IF([test "$enable_tests_python" = yes -a "$enable_freestanding" = yes], AC_MSG_ERROR([can not build freestanding tests]))
 AS_IF([test "$enable_tests"        = yes -a "$with_libc"           = yes], AC_MSG_ERROR([can not use package `libc' with tests]))


Test patch:
diff --git a/bindings/mruby/test/printf.rb b/bindings/mruby/test/printf.rb
index 5cffaab4..922567ea 100644
--- a/bindings/mruby/test/printf.rb
+++ b/bindings/mruby/test/printf.rb
@@ -56,7 +56,13 @@
             else
               arg.map do |item|
                 if item.is_a? Array
-                  item[0]
+                  if item.length == 1
+                    item[0]
+                  elsif item[0] == 'long long'
+                    item[1]
+                  else
+                    raise "Unknown format: #{args.inspect}"
+                  end
                 else
                   item
                 end
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6031286f..b678d571 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -335,6 +335,18 @@ CLEANFILES += test_printf_gen.c
 test_printf_gen.c: printf_gen.py printf_gen.jinja $(top_srcdir)/common/printf.yml $(top_srcdir)/common/printf_orig.yml
 	python3 printf_gen.py
 
+###################
+# test_printf_reg #
+###################
+
+if WITH_PRINTF
+TESTS += test_printf_reg
+test_printf_reg_LDADD = $(top_builddir)/libkernaux.la
+test_printf_reg_SOURCES = \
+	main.c \
+	test_printf_reg.c
+endif
+
 ####################
 # test_units_human #
 ####################
diff --git a/tests/printf_gen.py b/tests/printf_gen.py
index 343e7924..bc322a1f 100644
--- a/tests/printf_gen.py
+++ b/tests/printf_gen.py
@@ -65,7 +65,12 @@ def values(args):
             if type(arg[1]) is str:
                 values += ', ' + escape_str(arg[1])
             elif type(arg[1]) is list:
-                values += ', ' + escape_char(arg[1][0])
+                if len(arg[1]) == 1:
+                    values += ', ' + escape_char(arg[1][0])
+                elif arg[1][0] == 'long long':
+                    values += ', (long long)' + str(arg[1][1])
+                else:
+                    raise RuntimeError('unknown format: ' + str(args))
             else:
                 values += ', ' + str(arg[1])
 
diff --git a/tests/test_printf_reg.c b/tests/test_printf_reg.c
new file mode 100644
index 00000000..75f8ec5a
--- /dev/null
+++ b/tests/test_printf_reg.c
@@ -0,0 +1,34 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <kernaux/printf.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+void test_main()
+{
+    char buffer[1000];
+
+    // Sanity check
+    {
+        memset(buffer, 0xff, sizeof(buffer));
+        const int result =
+            kernaux_snprintf(buffer, sizeof(buffer), "%s", "Hello, World!");
+        fprintf(stderr, "%d:%s\n", result, buffer);
+        assert(result == 13);
+        assert(strcmp(buffer, "Hello, World!") == 0);
+    }
+
+    // i386 requires "(long long)0" instead of just "0"
+    {
+        memset(buffer, 0xff, sizeof(buffer));
+        const int result =
+            kernaux_snprintf(buffer, sizeof(buffer), "%#.0llx", (long long)0);
+        fprintf(stderr, "%d:%s\n", result, buffer);
+        assert(result == 0);
+        assert(strcmp(buffer, "") == 0);
+    }
+}