Make strtoll and strtod malloc-free
Some checks failed
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=OFF (push) Successful in 19s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=OFF (push) Successful in 18s
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=ON (push) Failing after 22s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=ON (push) Failing after 20s
CMake / ubuntu-latest - shared=OFF, pthread=ON, posix=ON (push) Failing after 19s
CMake / ubuntu-latest - shared=ON, pthread=ON, posix=ON (push) Failing after 20s

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-08-01 04:08:00 +03:00
parent 2ec675a320
commit 3d8f2270ef
3 changed files with 144 additions and 55 deletions

View File

@@ -41,6 +41,10 @@ foreach(TARGET ${PROJECT_NAME}_shared ${PROJECT_NAME}_static)
else()
target_compile_options(${TARGET} PRIVATE -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token)
endif()
if(NOT MSVC)
target_link_libraries(${TARGET} PRIVATE m)
endif()
endforeach()
# Install libraries

View File

@@ -4,7 +4,7 @@ set -e
BUILD_DIR="BUILD"
INSTALL_DIR="$(pwd)/install"
CFLAGS="-std=c99 -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token"
CFLAGS="-std=c99 -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token -lm"
BUILD_SHARED=1
PTHREAD_SUPPORT=1
POSIX_SUPPORT=1

View File

@@ -44,6 +44,7 @@
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -65,70 +66,154 @@ void pthread_mutex_unlock(pthread_mutex_t *);
int64_t dcfg_strtoll(const char *s, char **end, int base)
{
size_t n = strlen(s);
char *clean = malloc(n + 1);
if (!clean) {
errno = ENOMEM;
char const *p = s;
while (isspace((unsigned char)*p))
p++;
bool neg = false;
if (*p == '+' || *p == '-') {
neg = (*p == '-');
p++;
}
if (base == 0) {
if (*p == '0') {
if (p[1] == 'x' || p[1] == 'X') {
base = 16;
p += 2;
} else {
base = 8;
p++;
}
} else {
base = 10;
}
} else if (base == 16 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
p += 2;
}
int64_t val = 0;
char const *q = p, *last = p;
while (*q) {
char c = *q;
if (c == '_' || c == '\'') {
q++;
continue;
}
int d;
if (c >= '0' && c <= '9')
d = c - '0';
else if (c >= 'a' && c <= 'z')
d = c - 'a' + 10;
else if (c >= 'A' && c <= 'Z')
d = c - 'A' + 10;
else
break;
if (d >= base)
break;
val = val * base + d;
last = q + 1;
q++;
}
if (last == p) {
if (end)
*end = (char *)s;
return 0;
}
size_t w = 0;
for (size_t r = 0; r < n && s[r]; ++r)
if (s[r] != '_' && s[r] != '\'')
clean[w++] = s[r];
clean[w] = '\0';
char *tmp_end;
int64_t v = strtoll(clean, &tmp_end, base);
if (end) {
size_t consumed = (size_t)(tmp_end - clean);
size_t i = 0, c = 0;
while (i < n && c < consumed) {
if (s[i] != '_' && s[i] != '\'')
++c;
++i;
}
*end = (char *)s + i;
}
free(clean);
return v;
if (end)
*end = (char *)last;
return neg ? -val : val;
}
double dcfg_strtod(char const *s, char **end)
{
size_t n = strlen(s);
char *clean = malloc(n + 1);
if (!clean) {
errno = ENOMEM;
char const *p = s;
while (isspace((unsigned char)*p))
p++;
bool neg = false;
if (*p == '+' || *p == '-') {
neg = (*p == '-');
p++;
}
char const *fd = strchr(p, '.');
char const *fc = strchr(p, ',');
char dec = '.';
if (!fd && fc)
dec = ',';
else if (fd && fc && fc < fd)
dec = ',';
int64_t ip = 0;
double frac = 0.0, div = 1.0;
bool any = false, in_frac = false;
bool in_exp = false, exp_any = false;
int exp_sign = 1, exp_val = 0;
char const *last = p;
size_t i = p - s;
for (;; ++i) {
char c = s[i];
if (!c)
break;
if (!in_exp) {
if (c == '_' || c == '\'')
continue;
if (!in_frac && c == dec) {
in_frac = true;
last = s + i + 1;
continue;
}
if (!in_frac && (c == '.' || c == ','))
continue;
if (c >= '0' && c <= '9') {
any = true;
int d = c - '0';
if (!in_frac)
ip = ip * 10 + d;
else {
frac = frac * 10 + d;
div *= 10.0;
}
last = s + i + 1;
continue;
}
if ((c == 'e' || c == 'E') && any) {
in_exp = true;
last = s + i + 1;
continue;
}
break;
} else {
if ((c == '+' || c == '-') && !exp_any) {
if (c == '-')
exp_sign = -1;
last = s + i + 1;
continue;
}
if (c >= '0' && c <= '9') {
exp_any = true;
exp_val = exp_val * 10 + (c - '0');
last = s + i + 1;
continue;
}
break;
}
}
if (!any) {
if (end)
*end = (char *)s;
return 0.0;
}
size_t w = 0;
for (size_t r = 0; r < n && s[r]; ++r)
if (s[r] != '_' && s[r] != '\'')
clean[w++] = s[r];
clean[w] = '\0';
char *tmp_end;
double v = strtod(clean, &tmp_end);
if (end) {
size_t consumed = (size_t)(tmp_end - clean);
size_t i = 0, c = 0;
while (i < n && c < consumed) {
if (s[i] != '_' && s[i] != '\'')
++c;
++i;
}
*end = (char *)s + i;
}
free(clean);
return v;
double result = (double)ip + frac / div;
if (in_exp && exp_any)
result *= pow(10.0, exp_sign * exp_val);
if (neg)
result = -result;
if (end)
*end = (char *)last;
return result;
}
typedef dcfg_Value Value;
@@ -526,7 +611,7 @@ static void skip_ws_and_comments(Lexer *lx)
while (lx->ch != -1) {
if (lx->ch == '*' && lx->next == '/') {
lex_advance(lx);
lex_advance(lx); /* / */
lex_advance(lx);
break;
}
lex_advance(lx);
@@ -575,7 +660,7 @@ static Token lex_number(Lexer *lx)
while (isdigit_cp(lx->ch) || lx->ch == '_' || lx->ch == '\'')
lex_advance(lx);
if (lx->ch == '.') {
if (lx->ch == '.' || lx->ch == ',') {
real = true;
lex_advance(lx);
while (isdigit_cp(lx->ch) || lx->ch == '_' || lx->ch == '\'')
@@ -1449,7 +1534,7 @@ dcfg_ValueType dcfg_Value_type_ex(dcfg_Value *value, bool evaluate)
{
if (!value)
return dcfg_ValueType_Nil;
(void)evaluate; /* eval ignored for now */
(void)evaluate;
return value->type;
}