Fix printf hack in the bindings (#152)

This commit is contained in:
Alex Kotov 2022-12-18 09:18:55 +04:00 committed by GitHub
parent f46438fa85
commit a1262ac64d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 64 additions and 43 deletions

View File

@ -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

View File

@ -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 .

View File

@ -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 .

View File

@ -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).

View File

@ -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

View File

@ -1,8 +1,5 @@
#include "main.h"
#include <stddef.h>
#include <string.h>
#include <mruby/presym.h>
#include <mruby/string.h>
#include <mruby/variable.h>

View File

@ -1,9 +1,5 @@
#include "main.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <mruby/array.h>
#include <mruby/presym.h>
#include <mruby/string.h>

View File

@ -4,6 +4,12 @@
#include <kernaux.h>
#include <mruby.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
void current_mrb_start(mrb_state *mrb);
void current_mrb_finish(mrb_state *mrb);
mrb_state *current_mrb_get();

View File

@ -1,7 +1,5 @@
#include "main.h"
#include <stdint.h>
#include <mruby/numeric.h>
#include <mruby/presym.h>
#include <mruby/string.h>

View File

@ -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);
}

View File

@ -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

View File

@ -4,6 +4,12 @@
#include <kernaux.h>
#include <ruby.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
extern ID rb_intern_call;
extern ID rb_intern_freeze;
extern ID rb_intern_LESS;

View File

@ -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);
}