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
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:
@@ -41,6 +41,10 @@ foreach(TARGET ${PROJECT_NAME}_shared ${PROJECT_NAME}_static)
|
|||||||
else()
|
else()
|
||||||
target_compile_options(${TARGET} PRIVATE -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token)
|
target_compile_options(${TARGET} PRIVATE -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
target_link_libraries(${TARGET} PRIVATE m)
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Install libraries
|
# Install libraries
|
||||||
|
2
build.sh
2
build.sh
@@ -4,7 +4,7 @@ set -e
|
|||||||
|
|
||||||
BUILD_DIR="BUILD"
|
BUILD_DIR="BUILD"
|
||||||
INSTALL_DIR="$(pwd)/install"
|
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
|
BUILD_SHARED=1
|
||||||
PTHREAD_SUPPORT=1
|
PTHREAD_SUPPORT=1
|
||||||
POSIX_SUPPORT=1
|
POSIX_SUPPORT=1
|
||||||
|
193
src/dcfg.c
193
src/dcfg.c
@@ -44,6 +44,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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)
|
int64_t dcfg_strtoll(const char *s, char **end, int base)
|
||||||
{
|
{
|
||||||
size_t n = strlen(s);
|
char const *p = s;
|
||||||
char *clean = malloc(n + 1);
|
while (isspace((unsigned char)*p))
|
||||||
if (!clean) {
|
p++;
|
||||||
errno = ENOMEM;
|
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)
|
if (end)
|
||||||
*end = (char *)s;
|
*end = (char *)s;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (end)
|
||||||
size_t w = 0;
|
*end = (char *)last;
|
||||||
for (size_t r = 0; r < n && s[r]; ++r)
|
return neg ? -val : val;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double dcfg_strtod(char const *s, char **end)
|
double dcfg_strtod(char const *s, char **end)
|
||||||
{
|
{
|
||||||
size_t n = strlen(s);
|
char const *p = s;
|
||||||
char *clean = malloc(n + 1);
|
while (isspace((unsigned char)*p))
|
||||||
if (!clean) {
|
p++;
|
||||||
errno = ENOMEM;
|
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)
|
if (end)
|
||||||
*end = (char *)s;
|
*end = (char *)s;
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t w = 0;
|
double result = (double)ip + frac / div;
|
||||||
for (size_t r = 0; r < n && s[r]; ++r)
|
if (in_exp && exp_any)
|
||||||
if (s[r] != '_' && s[r] != '\'')
|
result *= pow(10.0, exp_sign * exp_val);
|
||||||
clean[w++] = s[r];
|
if (neg)
|
||||||
clean[w] = '\0';
|
result = -result;
|
||||||
|
if (end)
|
||||||
char *tmp_end;
|
*end = (char *)last;
|
||||||
double v = strtod(clean, &tmp_end);
|
return result;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef dcfg_Value Value;
|
typedef dcfg_Value Value;
|
||||||
@@ -526,7 +611,7 @@ static void skip_ws_and_comments(Lexer *lx)
|
|||||||
while (lx->ch != -1) {
|
while (lx->ch != -1) {
|
||||||
if (lx->ch == '*' && lx->next == '/') {
|
if (lx->ch == '*' && lx->next == '/') {
|
||||||
lex_advance(lx);
|
lex_advance(lx);
|
||||||
lex_advance(lx); /* / */
|
lex_advance(lx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lex_advance(lx);
|
lex_advance(lx);
|
||||||
@@ -575,7 +660,7 @@ static Token lex_number(Lexer *lx)
|
|||||||
|
|
||||||
while (isdigit_cp(lx->ch) || lx->ch == '_' || lx->ch == '\'')
|
while (isdigit_cp(lx->ch) || lx->ch == '_' || lx->ch == '\'')
|
||||||
lex_advance(lx);
|
lex_advance(lx);
|
||||||
if (lx->ch == '.') {
|
if (lx->ch == '.' || lx->ch == ',') {
|
||||||
real = true;
|
real = true;
|
||||||
lex_advance(lx);
|
lex_advance(lx);
|
||||||
while (isdigit_cp(lx->ch) || lx->ch == '_' || lx->ch == '\'')
|
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)
|
if (!value)
|
||||||
return dcfg_ValueType_Nil;
|
return dcfg_ValueType_Nil;
|
||||||
(void)evaluate; /* eval ignored for now */
|
(void)evaluate;
|
||||||
return value->type;
|
return value->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user