Maintenance (#114)

This commit is contained in:
Alex Kotov 2022-12-01 23:42:43 +04:00 committed by GitHub
parent cb834226a7
commit 84319ac0b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 138 additions and 64 deletions

View File

@ -137,10 +137,5 @@ jobs:
- uses: actions/checkout@v2
- name: dependencies
run: sudo apt-get --yes install cppcheck
- name: cppcheck source code
# TODO: don't suppress "src/printf.c"
run: cppcheck --quiet --error-exitcode=1 --std=c99 --enable=warning,style,performance,portability --suppress='*:src/printf.c' include/ src/ libc/
- name: cppcheck examples
run: cppcheck --quiet --error-exitcode=1 --std=c99 --enable=warning,style,performance,portability --suppress=duplicateExpression --suppress=staticStringCompare examples/
- name: cppcheck tests
run: cppcheck --quiet --error-exitcode=1 --std=c99 --enable=warning,style,performance,portability --suppress=unusedStructMember tests/
- name: cppcheck
run: cppcheck --quiet --error-exitcode=1 --std=c99 --enable=warning,style,performance,portability --inline-suppr examples/ include/ libc/ src/ tests/

View File

@ -62,6 +62,13 @@ Avoid stupid errors with:
* Default case in switch statements
* Braces (curly brackets) around code blocks
### Things to review periodically
* `git grep -i fixme`
* `git grep -i todo`
* `git grep -i cppcheck-suppress`
* `git grep -i rubocop:disable`
C language

View File

@ -1,3 +1,7 @@
2022-12-01 Alex Kotov <kotovalexarian@gmail.com>
* src/printf.c: Fix a bug with too big float precision
2022-11-30 Alex Kotov <kotovalexarian@gmail.com>
* configure.ac: Fix CFLAGS setting
@ -10,6 +14,10 @@
"KERNAUX_RETURNS_TWICE", "KERNAUX_ASM"
* include/kernaux/printf_fmt.h: Make stable
2022-11-27 Alex Kotov <kotovalexarian@gmail.com>
* src/free_list.c: Bug fixed
2022-11-26 Alex Kotov <kotovalexarian@gmail.com>
libkernaux 0.5.0 released

View File

@ -30,7 +30,6 @@ lib_LTLIBRARIES = libkernaux.la
libkernaux_la_LIBADD =
libkernaux_la_SOURCES = \
src/assert.c \
src/libc.h \
src/generic/malloc.c \
src/generic/mutex.c

View File

@ -35,7 +35,7 @@ API
### Headers
We use [semantic versioning](https://semver.org) for stable APIs. Stable APIs
can only change when major version number is increased (or minor while major is
may only change when major version number is increased (or minor while major is
zero). Work-in-progress APIs can change at any time.
* Basic features

View File

@ -37,7 +37,7 @@ void mrb_mruby_kernaux_gem_init(mrb_state *const mrb)
#endif // KERNAUX_VERSION_WITH_PRINTF
}
void current_mrb_start(mrb_state *mrb)
void current_mrb_start(mrb_state *const mrb)
{
mrb_assert(mrb_stack_count < MRB_STACK_SIZE - 1);
mrb_assert(mrb_stack[mrb_stack_count] == NULL);
@ -46,7 +46,7 @@ void current_mrb_start(mrb_state *mrb)
mrb_stack[mrb_stack_count++] = mrb;
}
void current_mrb_finish(mrb_state *mrb)
void current_mrb_finish(mrb_state *const mrb)
{
mrb_assert(mrb_stack_count > 0);
mrb_assert(mrb_stack[mrb_stack_count - 1] != NULL);

View File

@ -89,7 +89,43 @@
- result: '1.200000'
args: [['%f', 1.2]]
float: true
- result: '123.456789'
args: [['%f', 123.456789]]
float: true
- result: '0.01234568'
args: [['%.8f', 0.0123456789012345678901234567890123456789]]
float: true
- result: '0.012345679'
args: [['%.9f', 0.0123456789012345678901234567890123456789]]
float: true
# Actual precision is no more than 9
- result: '0.0123456790'
args: [['%.10f', 0.0123456789012345678901234567890123456789]]
float: true
- result: '0.01234567900'
args: [['%.11f', 0.0123456789012345678901234567890123456789]]
float: true
- result: '0.012345679000'
args: [['%.12f', 0.0123456789012345678901234567890123456789]]
float: true
- result: '0.012345679000000000000000000000'
args: [['%.30f', 0.0123456789012345678901234567890123456789]]
float: true
# Actual length is no more than 32
- result: '0.012345679000000000000000000000'
args: [['%.31f', 0.0123456789012345678901234567890123456789]]
float: true
- result: '0.012345679000000000000000000000'
args: [['%.32f', 0.0123456789012345678901234567890123456789]]
float: true
# Actual length is no more than 32
- result: '10.01234567900000000000000000000'
args: [['%.32f', 10.0123456789012345678901234567890123456789]]
float: true
- result: '100.0123456790000000000000000000'
args: [['%.32f', 100.0123456789012345678901234567890123456789]]
float: true
- result: '1000.012345679000000000000000000'
args: [['%.32f', 1000.0123456789012345678901234567890123456789]]
float: true

View File

@ -25,6 +25,7 @@ int main()
{
kernaux_assert_cb = assert_cb;
// cppcheck-suppress duplicateExpression
KERNAUX_ASSERT(1 == 1);
assert(count == 0);
@ -32,6 +33,7 @@ int main()
assert(last_line == 0);
assert(last_str == NULL);
// cppcheck-suppress duplicateExpression
KERNAUX_ASSERT(1 != 1);
assert(count == 1);
@ -39,6 +41,7 @@ int main()
assert(last_line == __LINE__ - 4);
assert(strcmp(last_str, "1 != 1") == 0);
// cppcheck-suppress staticStringCompare
KERNAUX_ASSERT(strcmp("qwe", "rty") == 0);
assert(count == 2);

View File

@ -35,12 +35,14 @@ static void *MyMalloc_realloc(void *malloc, void *ptr, size_t size);
struct MyMalloc MyMalloc_create()
{
struct MyMalloc my_malloc;
my_malloc.malloc.calloc = MyMalloc_calloc;
my_malloc.malloc.free = MyMalloc_free;
my_malloc.malloc.malloc = MyMalloc_malloc;
my_malloc.malloc.realloc = MyMalloc_realloc;
return my_malloc;
return (struct MyMalloc){
.malloc = {
.calloc = MyMalloc_calloc,
.free = MyMalloc_free,
.malloc = MyMalloc_malloc,
.realloc = MyMalloc_realloc,
},
};
}
void *MyMalloc_calloc(void *const malloc, const size_t nmemb, const size_t size)

View File

@ -35,9 +35,12 @@ static void MyMutex_unlock(void *mutex);
struct MyMutex MyMutex_create()
{
struct MyMutex my_mutex;
my_mutex.mutex.lock = MyMutex_lock;
my_mutex.mutex.unlock = MyMutex_unlock;
struct MyMutex my_mutex = {
.mutex = {
.lock = MyMutex_lock,
.unlock = MyMutex_unlock,
},
};
if (pthread_mutex_init(&my_mutex.pthread_mutex, NULL) != 0) abort();
return my_mutex;
}

View File

@ -1,6 +1,7 @@
#include <kernaux/macro.h>
#include <assert.h>
#include <string.h>
struct Foo {
const char *hello;
@ -29,5 +30,6 @@ void example_main()
assert(bar_ptr->a == 143);
assert(bar_ptr->b == 820794098);
assert(strcmp(bar_ptr->foo.hello, "Hello, World!") == 0);
assert(bar_ptr->c == 10981);
}

View File

@ -11,6 +11,8 @@ static const struct {
// of type "KernAux_Multiboot2_HTag_InfoReq"
// when the number of requested information
// tag types is even (n % 2 == 0).
//
// cppcheck-suppress unknownMacro
KERNAUX_MULTIBOOT2_HFIELDS_INFO_REQ_EVEN(
// This is the name of the structure field.
tag_info_req_even,
@ -22,6 +24,8 @@ static const struct {
// of type "KernAux_Multiboot2_HTag_InfoReq"
// when the number of requested information
// tag types is odd (n % 2 == 1).
//
// cppcheck-suppress unknownMacro
KERNAUX_MULTIBOOT2_HFIELDS_INFO_REQ_ODD(
// This is the name of the structure field.
tag_info_req_odd,
@ -34,6 +38,8 @@ static const struct {
_align1
)
// This macro may be used for all other header tag types.
//
// cppcheck-suppress unknownMacro
KERNAUX_MULTIBOOT2_HFIELDS_COMMON(
// This is the name of the structure field.
tag_none,

View File

@ -12,7 +12,7 @@ static const char *const data = "foobar";
static char buffer[BUFFER_SIZE];
static size_t buffer_index = 0;
static void my_putchar(const char chr, void *arg)
static void my_putchar(const char chr, void *const arg)
{
assert(arg == data);
if (buffer_index >= BUFFER_SIZE) abort();

View File

@ -12,7 +12,7 @@ static const char *const data = "foobar";
static char buffer[BUFFER_SIZE];
static size_t buffer_index = 0;
static void my_putchar(const char chr, void *arg)
static void my_putchar(const char chr, void *const arg)
{
assert(arg == data);
if (buffer_index >= BUFFER_SIZE) abort();

View File

@ -7,9 +7,8 @@ extern "C" {
#include <kernaux/macro.h>
KERNAUX_NORETURN
void kernaux_drivers_shutdown_halt();
void kernaux_drivers_shutdown_poweroff();
KERNAUX_NORETURN void kernaux_drivers_shutdown_halt();
KERNAUX_NORETURN void kernaux_drivers_shutdown_poweroff();
#ifdef __cplusplus
}

View File

@ -15,7 +15,13 @@ extern "C" {
#define KERNAUX_MULTIBOOT2_HEADER_MAGIC 0xe85250d6
#define KERNAUX_MULTIBOOT2_INFO_MAGIC 0x36d76289
#define KERNAUX_MULTIBOOT2_HEADER_ALIGN 4
// @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#OS-image-format
#define KERNAUX_MULTIBOOT2_HEADER_ALIGN 8
// @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-tags-structure
#define KERNAUX_MULTIBOOT2_INFO_ALIGN 8
// @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-tags
// @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-tags-structure
#define KERNAUX_MULTIBOOT2_TAG_ALIGN 8
#define KERNAUX_MULTIBOOT2_HEADER_CHECKSUM(arch, total_size) \
((uint32_t)(-( \
@ -26,8 +32,6 @@ extern "C" {
#define KERNAUX_MULTIBOOT2_DATA(ptr) (((uint8_t*)(ptr)) + sizeof(*(ptr)))
#define KERNAUX_MULTIBOOT2_TAG_ALIGN 8
#define KERNAUX_MULTIBOOT2_HTAG_NEXT(tag_base) \
((struct KernAux_Multiboot2_HTagBase*)KERNAUX_MULTIBOOT2_TAG_NEXT(tag_base))
#define KERNAUX_MULTIBOOT2_ITAG_NEXT(tag_base) \

View File

@ -1,18 +0,0 @@
// TODO: remove this file, require needed headers separately
#ifndef KERNAUX_INCLUDED_SRC_LIBC
#define KERNAUX_INCLUDED_SRC_LIBC
#ifdef __cplusplus
extern "C" {
#endif
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
}
#endif
#endif

View File

@ -47,9 +47,11 @@ char *kernaux_utoa(uint64_t value, char *buffer, int base, const char *prefix)
char *pos = buffer;
if (value == 0) *(pos++) = '0';
while (value > 0) {
// cppcheck-suppress zerodivcond
const char mod = value % base;
*(pos++) = mod < 10 ? mod + '0' : mod - 10 + alpha;
value /= base;
// cppcheck-suppress zerodivcond
value /= base;
}
char *const result = pos;
*(pos--) = '\0';

View File

@ -6,7 +6,7 @@
#include <kernaux/macro.h>
#include <kernaux/pfa.h>
#include "libc.h"
#include <string.h>
#define PAGE_INDEX(page_addr) ((page_addr) / KERNAUX_PFA_PAGE_SIZE)

View File

@ -17,10 +17,9 @@
#include <kernaux/printf.h>
#include <kernaux/printf_fmt.h>
#include "libc.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
// import float.h for DBL_MAX
#ifdef ENABLE_FLOAT
@ -245,6 +244,7 @@ int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char*
case KERNAUX_PRINTF_FMT_TYPE_PTR:
{
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
// cppcheck-suppress knownConditionTrueFalse
if (is_ll) {
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16u, spec.precision, spec.width, spec.flags);
} else {
@ -425,10 +425,6 @@ size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen
// internal ftoa for fixed decimal floating point
size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0u;
double diff = 0.0;
// powers of 10
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
@ -457,16 +453,18 @@ size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double v
if (!(flags & KERNAUX_PRINTF_FMT_FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0u;
const unsigned int orig_prec = prec;
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9u)) {
buf[len++] = '0';
prec--;
}
if (prec > 9u) prec = 9u;
int whole = (int)value;
double tmp = (value - whole) * pow10[prec];
unsigned long frac = (unsigned long)tmp;
diff = tmp - frac;
double diff = tmp - frac;
if (diff > 0.5) {
++frac;
@ -484,6 +482,7 @@ size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double v
if (prec == 0u) {
diff = value - (double)whole;
// cppcheck-suppress redundantCondition
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
@ -537,6 +536,24 @@ size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double v
}
}
// This slows down the algorighm, but
// only if the precision was more than 9.
if (orig_prec > prec) {
const size_t space_left = PRINTF_FTOA_BUFFER_SIZE - len;
const size_t zeroes_wanted = orig_prec - prec;
const size_t delta =
space_left < zeroes_wanted ? space_left : zeroes_wanted;
for (size_t rev_index = 0; rev_index < len; ++rev_index) {
const size_t index = len - 1 - rev_index;
buf[index + delta] = buf[index];
}
len += delta;
for (size_t index = 0; index < delta; ++index) buf[index] = '0';
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}

View File

@ -12,11 +12,11 @@
#include <kernaux/assert.h>
#include <kernaux/printf_fmt.h>
#include "libc.h"
#include <ctype.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct KernAux_PrintfFmt_Spec *Spec;

View File

@ -6,7 +6,7 @@
#include <kernaux/ntoa.h>
#include <kernaux/units.h>
#include "libc.h"
#include <string.h>
#define TMP_BUFFER_SIZE (64)

View File

@ -40,6 +40,10 @@ static void test(const char *const expected, const char *const format, ...)
va_start(va, format);
result = kernaux_vfprintf(test_putc, (void*)data, format, va);
va_end(va);
printf("Exp: %s\n", expected);
printf("Got: %s\n\n", buffer);
assert((size_t)result == strlen(expected));
assert(strcmp(expected, buffer) == 0);
@ -48,6 +52,7 @@ static void test(const char *const expected, const char *const format, ...)
va_start(va, format);
result = kernaux_vsnprintf(buffer, sizeof(buffer), format, va);
va_end(va);
assert((size_t)result == strlen(expected));
assert(strcmp(expected, buffer) == 0);
}
@ -63,7 +68,6 @@ void test_main()
{% if case.float %}
#ifdef ENABLE_FLOAT
{% endif %}
printf("%s\n", {{ escape_str(case.result) }});
test({{ escape_str(case.result) }}, {{ escape_str(fmt(case.args)) }}{{ values(case.args) }});
{% if case.float %}
#endif

View File

@ -37,6 +37,7 @@ static void before_assert()
static void expect_assert()
{
#ifdef ENABLE_DEBUG
// cppcheck-suppress assignmentInAssert
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/memmap.c") != NULL);
assert_last_file = NULL;

View File

@ -42,6 +42,7 @@ static void test_utoa_assert(char *const buffer, const int base)
if (setjmp(jmpbuf) == 0) {
kernaux_utoa(0, buffer, base, NULL);
} else {
// cppcheck-suppress assignmentInAssert
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/ntoa.c") != NULL);
assert(assert_last_line != 0);
@ -58,6 +59,7 @@ static void test_itoa_assert(char *const buffer, const int base)
if (setjmp(jmpbuf) == 0) {
kernaux_itoa(0, buffer, base, NULL);
} else {
// cppcheck-suppress assignmentInAssert
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/ntoa.c") != NULL);
assert(assert_last_line != 0);
@ -96,6 +98,7 @@ void test_main()
kernaux_utoa(123, buffer, 'd', TOO_LONG_PREFIX);
} else {
assert(strcmp(buffer, VALID_LONG_PREFIX) == 0);
// cppcheck-suppress assignmentInAssert
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/ntoa.c") != NULL);
assert(assert_last_line != 0);
@ -131,6 +134,7 @@ void test_main()
kernaux_itoa(123, buffer, 'd', TOO_LONG_PREFIX);
} else {
assert(strcmp(buffer, VALID_LONG_PREFIX) == 0);
// cppcheck-suppress assignmentInAssert
assert(assert_count_ctr == ++assert_count_exp);
assert(strstr(assert_last_file, "src/ntoa.c") != NULL);
assert(assert_last_line != 0);