diff --git a/.cirrus.yml b/.cirrus.yml index 41d3ee4..ba5f266 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -46,7 +46,7 @@ ruby_freebsd_task: CPATH: '/usr/local/include' LIBRARY_PATH: '/usr/local/lib' dependencies_script: - - pkg install --yes autoconf automake git libtool wget + - pkg install --yes autoconf automake cppcheck git libtool wget dependencies_ruby_script: - wget https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.3.tar.gz - tar -xzf ruby-3.0.3.tar.gz diff --git a/.github/workflows/mruby.yml b/.github/workflows/mruby.yml index 4e08365..afd12f7 100644 --- a/.github/workflows/mruby.yml +++ b/.github/workflows/mruby.yml @@ -46,6 +46,3 @@ jobs: - working-directory: bindings/mruby name: lint run: rake - - working-directory: bindings/mruby - name: cppcheck - run: cppcheck --quiet --error-exitcode=1 --std=c99 --enable=warning,style,performance,portability . diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 2ea62d7..d5a2ca6 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -44,6 +44,3 @@ jobs: - working-directory: bindings/ruby name: test & lint run: SKIP_COVERAGE='${{matrix.packages.skip_coverage}}' rake - - working-directory: bindings/ruby - name: cppcheck - run: cppcheck --quiet --error-exitcode=1 --std=c99 --enable=warning,style,performance,portability . diff --git a/README.md b/README.md index 96754bb..833b761 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,12 @@ make You can test with `make check`. +#### See also + +* [GitHub Actions](/.github/) for **GNU/Linux** build environment +* [Cirrus CI](/.cirrus.yml) for **FreeBSD** build environment +* [sourcehut CI](/.openbsd.yml) for **OpenBSD** build environment + ### Cross Create configuration script with `./autogen.sh` (if present). diff --git a/bindings/mruby/Rakefile b/bindings/mruby/Rakefile index 567628a..d71d39f 100644 --- a/bindings/mruby/Rakefile +++ b/bindings/mruby/Rakefile @@ -4,7 +4,7 @@ desc 'Run default checks' task default: :lint desc 'Run code analysis tools' -task lint: :rubocop +task lint: %i[rubocop cppcheck] desc 'Fix code style (rubocop --auto-correct)' task fix: 'rubocop:auto_correct' @@ -15,3 +15,15 @@ begin rescue LoadError nil end + +desc 'Run cppcheck' +task :cppcheck do + sh( + 'cppcheck', + '--quiet', + '--error-exitcode=1', + '--std=c99', + '--enable=warning,style,performance,portability', + __dir__, + ) +end diff --git a/bindings/mruby/src/assert.c b/bindings/mruby/src/assert.c index b9f5d66..0942a99 100644 --- a/bindings/mruby/src/assert.c +++ b/bindings/mruby/src/assert.c @@ -1,8 +1,5 @@ #include "main.h" -#include -#include - #include #include #include diff --git a/bindings/mruby/src/cmdline.c b/bindings/mruby/src/cmdline.c index 7826675..9dd1aa7 100644 --- a/bindings/mruby/src/cmdline.c +++ b/bindings/mruby/src/cmdline.c @@ -1,9 +1,5 @@ #include "main.h" -#include -#include -#include - #include #include #include diff --git a/bindings/mruby/src/main.h b/bindings/mruby/src/main.h index 5270041..a38d805 100644 --- a/bindings/mruby/src/main.h +++ b/bindings/mruby/src/main.h @@ -4,6 +4,12 @@ #include #include +#include +#include +#include +#include +#include + void current_mrb_start(mrb_state *mrb); void current_mrb_finish(mrb_state *mrb); mrb_state *current_mrb_get(); diff --git a/bindings/mruby/src/ntoa.c b/bindings/mruby/src/ntoa.c index d1dd384..f8f9c03 100644 --- a/bindings/mruby/src/ntoa.c +++ b/bindings/mruby/src/ntoa.c @@ -1,7 +1,5 @@ #include "main.h" -#include - #include #include #include diff --git a/bindings/mruby/src/printf.c b/bindings/mruby/src/printf.c index 02b05f0..71bc1ef 100644 --- a/bindings/mruby/src/printf.c +++ b/bindings/mruby/src/printf.c @@ -29,8 +29,7 @@ void init_printf(mrb_state *const mrb) mrb_value rb_KernAux_sprintf(mrb_state *const mrb, mrb_value self) { - // FIXME: const - char *format; + const char *format; mrb_value *args; mrb_int argc; mrb_get_args(mrb, "z*", &format, &args, &argc); @@ -45,12 +44,9 @@ mrb_value rb_KernAux_sprintf(mrb_state *const mrb, mrb_value self) continue; } - // FIXME: unnecessary - const char *const old_format = format; ++format; struct KernAux_PrintfFmt_Spec spec = - // FIXME: no type cast - KernAux_PrintfFmt_Spec_create_out((const char**)&format); + KernAux_PrintfFmt_Spec_create_out(&format); if (spec.set_width) { TAKE_ARG; @@ -87,14 +83,16 @@ mrb_value rb_KernAux_sprintf(mrb_state *const mrb, mrb_value self) DynArg_use_str(&dynarg, RSTRING_CSTR(mrb, arg_rb)); } + // 1 additional byte for the '%' character. + // 1 additional byte for the terminating '\0' character. + char old_format[2 + spec.format_limit - spec.format_start]; + memset(old_format, '\0', sizeof(old_format)); + old_format[0] = '%'; + strncpy(&old_format[1], spec.format_start, sizeof(old_format) - 2); + char buffer[BUFFER_SIZE]; int slen; - // FIXME: it's a hack - // TODO: convert printf format spec to string - const char tmp = *format; - *format = '\0'; - if (spec.set_width) { if (spec.set_precision) { if (dynarg.use_dbl) { @@ -133,7 +131,6 @@ mrb_value rb_KernAux_sprintf(mrb_state *const mrb, mrb_value self) } } - *format = tmp; mrb_str_cat(mrb, result, buffer, slen); } diff --git a/bindings/ruby/Rakefile b/bindings/ruby/Rakefile index 2675fc7..5bf5204 100644 --- a/bindings/ruby/Rakefile +++ b/bindings/ruby/Rakefile @@ -20,13 +20,13 @@ CLEAN << 'doc' CLEAN << 'spec/examples.txt' desc 'Run default checks' -task default: %i[test lint yard:cov] +task default: %i[test lint] desc 'Run tests' task test: :spec desc 'Run code analysis tools' -task lint: :rubocop +task lint: %i[rubocop cppcheck yard:cov] desc 'Fix code style (rubocop --auto-correct)' task fix: 'rubocop:auto_correct' @@ -66,6 +66,18 @@ task :console do sh 'bundle', 'exec', File.expand_path(File.join('bin', 'console'), __dir__) end +desc 'Run cppcheck' +task :cppcheck do + sh( + 'cppcheck', + '--quiet', + '--error-exitcode=1', + '--std=c99', + '--enable=warning,style,performance,portability', + __dir__, + ) +end + namespace :yard do desc 'Measure documentation coverage' task :cov do diff --git a/bindings/ruby/ext/default/main.h b/bindings/ruby/ext/default/main.h index 74d2187..ddbb2ff 100644 --- a/bindings/ruby/ext/default/main.h +++ b/bindings/ruby/ext/default/main.h @@ -4,6 +4,12 @@ #include #include +#include +#include +#include +#include +#include + extern ID rb_intern_call; extern ID rb_intern_freeze; extern ID rb_intern_LESS; diff --git a/bindings/ruby/ext/default/printf.c b/bindings/ruby/ext/default/printf.c index b2785b6..e73ddf0 100644 --- a/bindings/ruby/ext/default/printf.c +++ b/bindings/ruby/ext/default/printf.c @@ -31,8 +31,7 @@ VALUE rb_KernAux_sprintf(const int argc, VALUE *const argv, VALUE self) { if (argc == 0) rb_raise(rb_eArgError, "too few arguments"); - // FIXME: const - char *format = StringValueCStr(argv[0]); + const char *format = StringValueCStr(argv[0]); int arg_index = 1; VALUE result = rb_str_new_literal(""); @@ -43,12 +42,9 @@ VALUE rb_KernAux_sprintf(const int argc, VALUE *const argv, VALUE self) continue; } - // FIXME: unnecessary - const char *const old_format = format; ++format; struct KernAux_PrintfFmt_Spec spec = - // FIXME: no type cast - KernAux_PrintfFmt_Spec_create_out((const char**)&format); + KernAux_PrintfFmt_Spec_create_out(&format); if (spec.set_width) { TAKE_ARG; @@ -82,14 +78,16 @@ VALUE rb_KernAux_sprintf(const int argc, VALUE *const argv, VALUE self) DynArg_use_str(&dynarg, StringValueCStr(arg_rb)); } + // 1 additional byte for the '%' character. + // 1 additional byte for the terminating '\0' character. + char old_format[2 + spec.format_limit - spec.format_start]; + memset(old_format, '\0', sizeof(old_format)); + old_format[0] = '%'; + strncpy(&old_format[1], spec.format_start, sizeof(old_format) - 2); + char buffer[BUFFER_SIZE]; int slen; - // FIXME: it's a hack - // TODO: convert printf format spec to string - const char tmp = *format; - *format = '\0'; - if (spec.set_width) { if (spec.set_precision) { if (dynarg.use_dbl) { @@ -128,7 +126,6 @@ VALUE rb_KernAux_sprintf(const int argc, VALUE *const argv, VALUE self) } } - *format = tmp; rb_str_cat(result, buffer, slen); }