fixed merge conflicts

This commit is contained in:
NeGate 2022-06-05 20:26:32 -04:00
commit 67e15fbb4e
6 changed files with 280 additions and 72 deletions

4
code/errno.c Normal file
View File

@ -0,0 +1,4 @@
#include <errno.h>
int errno;

View File

@ -4,10 +4,18 @@
#include <stdbool.h> #include <stdbool.h>
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#include <math.h>
// TODO: strto*: locale-based parsing for integers // TODO: strto*: locale-based parsing
// TODO: i made a function that parses longs and i'm fucken // TODO: correctly rounded base 16 floats parsing
// tired. someone make float parsing :kekw:
// Call me weak if you want but I'm actually too lazy to type
// them out every time, also they take up a lot of horiz space.
typedef long long intll;
typedef long intl;
typedef unsigned long long intull;
typedef unsigned long intul;
typedef unsigned intu;
#define inrange(start, c, end) ((start) <= (c) && (c) <= (end)) #define inrange(start, c, end) ((start) <= (c) && (c) <= (end))
@ -28,8 +36,18 @@ static bool isbase(int c, int base) {
return val < base; return val < base;
} }
static bool strprefix_i(char const *restrict str, char const *restrict prefix) {
while(*prefix != 0) {
if(*str == 0) break;
if(toupper(*str) != toupper(*prefix)) return false;
++prefix;
++str;
}
return true;
}
// Called only when isbase(c, base) for some base in range // Called only when isbase(c, base) for some base in range
static long todigitl(int c) { static long todigit(int c) {
int val; int val;
if(isdigit(c)) { if(isdigit(c)) {
val = c-'0'; val = c-'0';
@ -43,92 +61,255 @@ static long todigitl(int c) {
return val; return val;
} }
long static intull strtoi_generic(const char *restrict nptr,
strtol(const char *restrict nptr, char **restrict endptr, int inbase) { char **restrict endptr,
if(!inrange(0, inbase, 36)) { int inbase,
*endptr = NULL; intl *coefptr,
return 0; intull int_max) {
const char *restrict str = nptr;
intull value = 0;
int digits_read = 0;
bool is_signed = (coefptr != NULL);
// Find max{abs(int)}. Signed integers have negative,
// whose absolute value is 1 bigger than int_max.
intull int_abs_max = int_max;
if(is_signed) {
++int_abs_max;
} }
if(!inrange(0, inbase, 36)) {
goto finish;
}
intull base = (intull)inbase;
// Skip space on the beginning // Skip space on the beginning
while(isspace(*nptr)) { while(isspace(*str)) {
++nptr; ++str;
} }
// Parse sign // Parse sign
long coef = 1; intl coef = 1;
if(*nptr == '-') { if(is_signed) {
coef = -1; if(*str == '-') {
++nptr; coef = -1;
++str;
}
} }
if(*nptr == '+') { if(*str == '+') {
++nptr; ++str;
} }
unsigned long base = (unsigned long)inbase;
unsigned long value = 0;
// See if we need to parse base in C-like format // See if we need to parse base in C-like format
if(*nptr == '0' && *(nptr+1) == 'x') { // then set the base accordingly
++nptr; if(strprefix_i(str, "0X")) {
++str;
if(base == 16 || base == 0) { if(base == 16 || base == 0) {
++nptr; ++str;
base = 16; base = 16;
} }
else { else {
value = 0; goto finish;
goto end;
} }
} }
else if(*nptr == '0') { else if(*str == '0') {
++nptr; ++str;
++digits_read;
if(base == 8 || base == 0) { if(base == 8 || base == 0) {
base = 8; base = 8;
} }
} }
while(isbase(*nptr, (int)base)) { // Parse the string of digits in the given base. If the value
unsigned long digit = (unsigned long)todigitl(*nptr); // exceeds abs(int_min) we exit with range error.
if(value > (ULONG_MAX - digit)/base) { while(isbase(*str, (int)base)) {
errno = ERANGE; intull digit = (intull)todigit(*str);
value = 0; if(value > (int_abs_max - digit)/base) {
goto end; goto error_out_of_range;
} }
value = base*value + digit; value = base*value + digit;
++nptr; ++str;
++digits_read;
} }
unsigned long max_modulo = (unsigned long)LONG_MAX+1; // We only allow the modulo of value equal to abs(int_min) if it is
if(value > max_modulo) { // preceeded by the minus sign.
errno = ERANGE; if(is_signed) {
if(value == int_abs_max && coef != -1) {
goto error_out_of_range;
}
}
goto finish;
error_out_of_range:
// Skip the remainder of the subject string
while(isbase(*str, (int)base)) {
++str;
}
errno = ERANGE;
value = int_max;
goto finish;
finish:
// If no conversion is performed we return the value of 0 and *endptr
// is set to the nptr.
bool conv_performed = (digits_read > 0);
if(!conv_performed) {
value = 0; value = 0;
goto end;
} }
if(value == max_modulo) { if(endptr != NULL) {
if(coef == 1) { if(!conv_performed) {
errno = ERANGE; *endptr = (char *)nptr;
value = 0;
goto end;
} }
else { else {
value = LONG_MIN; *endptr = (char *)str;
coef = 1;
} }
} }
end: *coefptr = coef;
if(endptr != NULL) { return value;
*endptr = (char *)nptr; }
static double strtod_generic(const char *restrict nptr, char **restrict endptr) {
const char *restrict str = nptr;
bool conv_performed = false;
double value = 0.0;
double coef = 1.0;
// Skip space on the beginning
while(isspace(*str)) {
++str;
} }
return coef*(long)value; // Check for inf and nan
if(strprefix_i(str, "INF")) {
str += sizeof "INF"-1;
value = HUGE_VAL;
conv_performed = true;
goto finish;
}
if(strprefix_i(str, "INFINITY")) {
str += sizeof "INFINITY"-1;
value = HUGE_VAL;
conv_performed = true;
goto finish;
}
if(strprefix_i(str, "NAN")) {
str += sizeof "NAN"-1;
value = NAN;
conv_performed = true;
if(*str == '(') {
while(*str != ')') {
++str;
}
++str;
}
goto finish;
}
// Parse C float
if(*str == '+') {
++str;
}
else if(*str == '-') {
coef = -1.;
++str;
}
int base = 10;
if(strprefix_i(str, "0X")) {
str += sizeof "0X"-1;
base = 16;
}
// Parse the whole part
while(isbase(*str, base)) {
long digit = todigit(*str);
value = 10.0*value + (double)digit;
++str;
}
if(*str != '.') {
value = 0.0;
goto finish;
}
++str;
// Parse the fractional part
long exp = 1;
while(isbase(*str, base)) {
long digit = todigit(*str);
double fract = (double)digit;
long cexp = exp;
while(cexp-- != 0) {
fract /= (double)base;
}
value += fract;
++exp;
++str;
}
// Parse the exponent
if((base == 10 && strprefix_i(str, "E"))
|| (base == 16 && strprefix_i(str, "P")))
{
++str;
long exp = 0;
long exp_coef = 1;
if(*str == '+') {
++str;
}
else if(*str == '-') {
exp_coef = -1;
++str;
}
while(isdigit(*str)) {
exp = 10*exp + (long)(*str-'0');
++str;
}
if(exp_coef == 1) {
while(exp--!=0) value = value * base;
}
else if(exp_coef == -1) {
while(exp--!=0) value = value / base;
}
}
if(!isfinite(value)) {
errno = ERANGE;
value = coef*HUGE_VAL;
}
conv_performed = true;
finish:
if(endptr != NULL) {
if(conv_performed) {
*endptr = (char *)str;
}
else {
*endptr = (char *)nptr;
}
}
return coef*value;
} }
long long intl strtol(const char *restrict nptr, char **restrict endptr, int base) {
strtoll(const char *restrict nptr, char **restrict endptr, int base) { intull int_max = (intull)LONG_MAX;
return 0; intl coef;
intull modulo = strtoi_generic(nptr, endptr, base, &coef, int_max);
intl value;
if(modulo == int_max) {
value = LONG_MIN;
}
else {
value = coef * (intl)modulo;
}
return value;
} }
unsigned long intll strtoll(const char *restrict nptr, char **restrict endptr, int base) {
strtoul(const char *restrict nptr, char **restrict endptr, int base) { intull int_max = (intull)LLONG_MAX;
return 0; intl coef;
intull modulo = strtoi_generic(nptr, endptr, base, &coef, int_max);
intll value;
if(modulo == int_max) {
value = LLONG_MIN;
}
else {
value = (intll)coef * (intll)modulo;
}
return value;
} }
unsigned long long intul strtoul(const char *restrict nptr, char **restrict endptr, int base) {
strtoull(const char *restrict nptr, char **restrict endptr, int base) { intull int_max = (intull)ULONG_MAX;
return 0; intull value = strtoi_generic(nptr, endptr, base, NULL, int_max);
return (intul)value;
}
intull strtoull(const char *restrict nptr, char **restrict endptr, int base) {
intull int_max = (intull)ULLONG_MAX;
return strtoi_generic(nptr, endptr, base, NULL, int_max);
} }
double atof(const char *nptr) { double atof(const char *nptr) {
@ -148,13 +329,13 @@ long long int atoll(const char *nptr) {
} }
double strtod(const char *restrict nptr, char **restrict endptr) { double strtod(const char *restrict nptr, char **restrict endptr) {
return 0; return strtod_generic(nptr, endptr);
} }
float strtof(const char *restrict nptr, char **restrict endptr) { float strtof(const char *restrict nptr, char **restrict endptr) {
return 0; return (float)strtod_generic(nptr, endptr);
} }
long double strtold(const char *restrict nptr, char **restrict endptr) { long double strtold(const char *restrict nptr, char **restrict endptr) {
return 0; return (long double)strtod_generic(nptr, endptr);
} }

View File

@ -5,4 +5,4 @@
#define ERANGE 3 #define ERANGE 3
// TODO: make it thread-local // TODO: make it thread-local
int errno; extern int errno;

View File

@ -21,11 +21,11 @@ typedef double double_t;
#define FP_INFINITE 1 #define FP_INFINITE 1
#define FP_NAN 2 #define FP_NAN 2
FP_INFINITE //FP_INFINITE
FP_NAN //FP_NAN
FP_NORMAL //FP_NORMAL
FP_SUBNORMAL //FP_SUBNORMAL
FP_ZERO //FP_ZERO
#define FP_FAST_FMA 1 #define FP_FAST_FMA 1
#define FP_FAST_FMAF 1 #define FP_FAST_FMAF 1
#define FP_FAST_FMAL 1 #define FP_FAST_FMAL 1
@ -39,8 +39,11 @@ FP_ZERO
// TODO: implement this // TODO: implement this
#define fpclassify(x) 0 #define fpclassify(x) 0
#define isfinite(x) 0
#define isinf(x) 0 // HACK: If its fine just remove the comment
#define isfinite(x) ((double)(x) != HUGE_VAL && (double)(x) != -HUGE_VAL)
#define isinf(x) (!(isinf(x)))
#define isnan(x) 0 #define isnan(x) 0
#define isnormal(x) 0 #define isnormal(x) 0
#define signbit(x) 0 #define signbit(x) 0

View File

@ -1,4 +1,3 @@
#pragma once #pragma once
#if !defined(NULL) #if !defined(NULL)

View File

@ -1,6 +1,8 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char** argv) { int main(int argc, char** argv) {
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
@ -13,5 +15,24 @@ int main(int argc, char** argv) {
for (char c = 'a'; c != 'z'; ++c) { for (char c = 'a'; c != 'z'; ++c) {
assert(isupper(toupper(c))); assert(isupper(toupper(c)));
} }
return 0;
double v0 = strtod("0X1.BC70A3D70A3D7P+6", NULL);
// parsing with error handling
const char *p = "111.11 -2.22 Nan nan(2) inF 0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz";
char *end;
for (double f = strtod(p, &end); p != end; f = strtod(p, &end)) {
printf("'%.*s' -> ", (int)(end - p), p);
p = end;
if (errno == ERANGE){
printf("range error, got ");
}
printf("%f\n", f);
}
// parsing without error handling
double v1 = strtod(" -0.0000000123junk", NULL);
double v2 = strtod("junk", NULL);
} }