Replaced string to convert

This commit is contained in:
Alex 2022-10-20 01:06:20 +03:00
parent a6d5e08e3b
commit 7750dd777e
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
10 changed files with 316 additions and 149 deletions

View File

@ -2,7 +2,7 @@
#include <boot/binfo.h>
#include <types.h>
#include <debug.h>
#include <string.h>
#include <convert.h>
#include "../../kernel.h"

View File

@ -1,7 +1,7 @@
#include <cpu.hpp>
#include <memory.hpp>
#include <string.h>
#include <convert.h>
#include <debug.h>
#include "../kernel.h"

View File

@ -1,6 +1,6 @@
#include <memory.hpp>
#include <string.h>
#include <convert.h>
#include <debug.h>
#include "HeapAllocators/Xalloc.hpp"
@ -11,14 +11,6 @@ using namespace Memory;
Physical KernelAllocator;
PageTable *KernelPageTable = nullptr;
enum MemoryAllocatorType
{
None,
Pages,
XallocV1,
liballoc11
};
static MemoryAllocatorType AllocatorType = MemoryAllocatorType::None;
Xalloc::AllocatorV1 *XallocV1Allocator = nullptr;

View File

@ -1,6 +1,6 @@
#include <memory.hpp>
#include <string.h>
#include <convert.h>
#include <debug.h>
namespace Memory

View File

@ -1,6 +1,6 @@
#include <symbols.hpp>
#include <memory.hpp>
#include <string.h>
#include <convert.h>
#include <debug.h>
// #pragma GCC diagnostic ignored "-Wignored-qualifiers"

View File

@ -1,5 +1,6 @@
#include <string.h>
#include <convert.h>
#include <types.h>
#include <memory.hpp>
// TODO: Replace mem* with assembly code
@ -418,6 +419,23 @@ char *strstr(const char *haystack, const char *needle)
}
}
char *strchr(const char *String, int Char)
{
while (*String != (char)Char)
{
if (!*String++)
return 0;
}
return (char *)String;
}
char *strdup(const char *String)
{
char *OutBuffer = kmalloc(strlen((char *)String) + 1);
strcpy(OutBuffer, String);
return OutBuffer;
}
int isdigit(int c)
{
return c >= '0' && c <= '9';
@ -440,3 +458,142 @@ int isempty(char *str)
}
return 1;
}
int abs(int i) { return i < 0 ? -i : i; }
void swap(char *x, char *y)
{
char t = *x;
*x = *y;
*y = t;
}
char *reverse(char *Buffer, int i, int j)
{
while (i < j)
swap(&Buffer[i++], &Buffer[j--]);
return Buffer;
}
int atoi(const char *String)
{
uint64_t Length = strlen((char *)String);
uint64_t OutBuffer = 0;
uint64_t Power = 1;
for (uint64_t i = Length; i > 0; --i)
{
OutBuffer += (String[i - 1] - 48) * Power;
Power *= 10;
}
return OutBuffer;
}
double atof(const char *String)
{
// Originally from https://github.com/GaloisInc/minlibc/blob/master/atof.c
/*
Copyright (c) 2014 Galois Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Galois, Inc. nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
double a = 0.0;
int e = 0;
int c;
while ((c = *String++) != '\0' && isdigit(c))
{
a = a * 10.0 + (c - '0');
}
if (c == '.')
{
while ((c = *String++) != '\0' && isdigit(c))
{
a = a * 10.0 + (c - '0');
e = e - 1;
}
}
if (c == 'e' || c == 'E')
{
int sign = 1;
int i = 0;
c = *String++;
if (c == '+')
c = *String++;
else if (c == '-')
{
c = *String++;
sign = -1;
}
while (isdigit(c))
{
i = i * 10 + (c - '0');
c = *String++;
}
e += i * sign;
}
while (e > 0)
{
a *= 10.0;
e--;
}
while (e < 0)
{
a *= 0.1;
e++;
}
return a;
}
char *itoa(int Value, char *Buffer, int Base)
{
if (Base < 2 || Base > 32)
return Buffer;
int n = abs(Value);
int i = 0;
while (n)
{
int r = n % Base;
if (r >= 10)
Buffer[i++] = 65 + (r - 10);
else
Buffer[i++] = 48 + r;
n = n / Base;
}
if (i == 0)
Buffer[i++] = '0';
if (Value < 0 && Base == 10)
Buffer[i++] = '-';
Buffer[i] = '\0';
return reverse(Buffer, 0, i - 1);
}

View File

@ -37,21 +37,21 @@
* THE SOFTWARE.
*/
#pragma GCC diagnostic ignored "-Wtype-limits"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wtautological-compare"
#pragma GCC diagnostic ignored "-Wsign-compare"
// Define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
// Define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H=1 ...) to include the
// printf_config.h header file
#if PRINTF_INCLUDE_CONFIG_H
#include "printf_config.h"
#endif
#include <printf.h>
#ifdef __cplusplus
#include <cstdint>
#include <climits>
#else
#include <types.h>
#include <limits.h>
#include <debug.h>
#include <printf.h>
#endif // __cplusplus
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#define printf_ printf
@ -104,7 +104,7 @@
#endif
// Support for the long long integral types (with the ll, z and t length modifiers for specifiers
// %d,%i,%o,%x,%X,%u, and with the %p specifier). Note: 'L' (long / *doubl e*/unsigned long) is not supported.
// %d,%i,%o,%x,%X,%u, and with the %p specifier). Note: 'L' (long double) is not supported.
#ifndef PRINTF_SUPPORT_LONG_LONG
#define PRINTF_SUPPORT_LONG_LONG 1
#endif
@ -120,6 +120,12 @@
#error "At least one non-constant Taylor expansion is necessary for the log10() calculation"
#endif
// Be extra-safe, and don't assume format specifiers are completed correctly
// before the format string end.
#ifndef PRINTF_CHECK_FOR_NUL_IN_FORMAT_SPECIFIER
#define PRINTF_CHECK_FOR_NUL_IN_FORMAT_SPECIFIER 1
#endif
#define PRINTF_PREFER_DECIMAL false
#define PRINTF_PREFER_EXPONENTIAL true
@ -245,14 +251,14 @@ typedef uint64_t double_uint_t;
#define DOUBLE_MAX_SUBNORMAL_POWER_OF_10 1e-308
#else
#error "Unsupported / *doubl e*/unsigned long type configuration"
#error "Unsupported double type configuration"
#endif
#define DOUBLE_STORED_MANTISSA_BITS (DBL_MANT_DIG - 1)
typedef union
{
double_uint_t U;
/* double */ unsigned long F;
double F;
} double_with_bit_access;
// This is unnecessary in C99, since compound initializers can be used,
@ -260,14 +266,14 @@ typedef union
// 1. Some compilers are finicky about this;
// 2. Some people may want to convert this to C89;
// 3. If you try to use it as C++, only C++20 supports compound literals
static inline double_with_bit_access get_bit_access(/* double */ unsigned long x)
static inline double_with_bit_access get_bit_access(double x)
{
double_with_bit_access dwba;
dwba.F = x;
return dwba;
}
static inline int get_sign_bit(/* double */ unsigned long x)
static inline int get_sign_bit(double x)
{
// The sign is stored in the highest bit
return (int)(get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1));
@ -356,7 +362,7 @@ static inline void putchar_wrapper(char c, void *unused)
putchar(c);
}
static inline output_gadget_t discarding_gadget()
static inline output_gadget_t discarding_gadget(void)
{
output_gadget_t gadget;
gadget.function = NULL;
@ -388,7 +394,7 @@ static inline output_gadget_t function_gadget(void (*function)(char, void *), vo
return result;
}
static inline output_gadget_t extern_putchar_gadget()
static inline output_gadget_t extern_putchar_gadget(void)
{
return function_gadget(putchar_wrapper, NULL);
}
@ -576,53 +582,50 @@ static void print_integer(output_gadget_t *output, printf_unsigned_value_t value
#if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
// Stores a fixed-precision representation of a / *doubl e*/unsigned long relative
// Stores a fixed-precision representation of a double relative
// to a fixed precision (which cannot be determined by examining this structure)
struct double_components
{
int_fast64_t integral;
int_fast64_t fractional;
// ... truncation of the actual fractional part of the / *doubl e*/unsigned long value, scaled
// ... truncation of the actual fractional part of the double value, scaled
// by the precision value
bool is_negative;
};
#define NUM_DECIMAL_DIGITS_IN_INT64_T 18
#define PRINTF_MAX_PRECOMPUTED_POWER_OF_10 NUM_DECIMAL_DIGITS_IN_INT64_T
static const /* double */ unsigned long powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = {
static const double powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = {
1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08,
1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17};
#define PRINTF_MAX_SUPPORTED_PRECISION NUM_DECIMAL_DIGITS_IN_INT64_T - 1
// Break up a / *doubl e*/unsigned long number - which is known to be a finite non-negative number -
// Break up a double number - which is known to be a finite non-negative number -
// into its base-10 parts: integral - before the decimal point, and fractional - after it.
// Taken the precision into account, but does not change it even internally.
static struct double_components get_components(/* double */ unsigned long number, printf_size_t precision)
static struct double_components get_components(double number, printf_size_t precision)
{
struct double_components number_;
number_.is_negative = get_sign_bit(number);
/* double */ unsigned long abs_number = (number_.is_negative) ? -number : number;
double abs_number = (number_.is_negative) ? -number : number;
number_.integral = (int_fast64_t)abs_number;
/* double */ unsigned long remainder = (abs_number - (/* double */ unsigned long)number_.integral) * powers_of_10[precision];
double remainder = (abs_number - (double)number_.integral) * powers_of_10[precision];
number_.fractional = (int_fast64_t)remainder;
remainder -= (/* double */ unsigned long)number_.fractional;
remainder -= (double)number_.fractional;
// if (remainder > 0.5)
warn("SSE not supported.");
if (remainder > 1)
if (remainder > 0.5)
{
++number_.fractional;
// handle rollover, e.g. case 0.99 with precision 1 is 1.0
if ((/* double */ unsigned long)number_.fractional >= powers_of_10[precision])
if ((double)number_.fractional >= powers_of_10[precision])
{
number_.fractional = 0;
++number_.integral;
}
}
// else if ((remainder == 0.5) && ((number_.fractional == 0U) || (number_.fractional & 1U)))
else if ((remainder == 1) && ((number_.fractional == 0U) || (number_.fractional & 1U)))
else if ((remainder == 0.5) && ((number_.fractional == 0U) || (number_.fractional & 1U)))
{
// if halfway, round up if odd OR if last digit is 0
++number_.fractional;
@ -630,9 +633,8 @@ static struct double_components get_components(/* double */ unsigned long number
if (precision == 0U)
{
remainder = abs_number - (/* double */ unsigned long)number_.integral;
// if ((!(remainder < 0.5) || (remainder > 0.5)) && (number_.integral & 1))
if ((!(remainder < 1) || (remainder > 1)) && (number_.integral & 1))
remainder = abs_number - (double)number_.integral;
if ((!(remainder < 0.5) || (remainder > 0.5)) && (number_.integral & 1))
{
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
@ -645,21 +647,29 @@ static struct double_components get_components(/* double */ unsigned long number
#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
struct scaling_factor
{
/* double */ unsigned long raw_factor;
double raw_factor;
bool multiply; // if true, need to multiply by raw_factor; otherwise need to divide by it
};
static /* double */ unsigned long apply_scaling(/* double */ unsigned long num, struct scaling_factor normalization)
static double apply_scaling(double num, struct scaling_factor normalization)
{
return normalization.multiply ? num * normalization.raw_factor : num / normalization.raw_factor;
}
static /* double */ unsigned long unapply_scaling(/* double */ unsigned long normalized, struct scaling_factor normalization)
static double unapply_scaling(double normalized, struct scaling_factor normalization)
{
#ifdef __GNUC__
// accounting for a static analysis bug in GCC 6.x and earlier
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
return normalization.multiply ? normalized / normalization.raw_factor : normalized * normalization.raw_factor;
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
static struct scaling_factor update_normalization(struct scaling_factor sf, /* double */ unsigned long extra_multiplicative_factor)
static struct scaling_factor update_normalization(struct scaling_factor sf, double extra_multiplicative_factor)
{
struct scaling_factor result;
if (sf.multiply)
@ -687,11 +697,11 @@ static struct scaling_factor update_normalization(struct scaling_factor sf, /* d
return result;
}
static struct double_components get_normalized_components(bool negative, printf_size_t precision, /* double */ unsigned long non_normalized, struct scaling_factor normalization, int floored_exp10)
static struct double_components get_normalized_components(bool negative, printf_size_t precision, double non_normalized, struct scaling_factor normalization, int floored_exp10)
{
struct double_components components;
components.is_negative = negative;
/* double */ unsigned long scaled = apply_scaling(non_normalized, normalization);
double scaled = apply_scaling(non_normalized, normalization);
bool close_to_representation_extremum = ((-floored_exp10 + (int)precision) >= DBL_MAX_10_EXP - 1);
if (close_to_representation_extremum)
@ -702,14 +712,14 @@ static struct double_components get_normalized_components(bool negative, printf_
return get_components(negative ? -scaled : scaled, precision);
}
components.integral = (int_fast64_t)scaled;
/* double */ unsigned long remainder = non_normalized - unapply_scaling((/* double */ unsigned long)components.integral, normalization);
/* double */ unsigned long prec_power_of_10 = powers_of_10[precision];
double remainder = non_normalized - unapply_scaling((double)components.integral, normalization);
double prec_power_of_10 = powers_of_10[precision];
struct scaling_factor account_for_precision = update_normalization(normalization, prec_power_of_10);
/* double */ unsigned long scaled_remainder = apply_scaling(remainder, account_for_precision);
/* double */ unsigned long rounding_threshold = 1; // 0.5;
double scaled_remainder = apply_scaling(remainder, account_for_precision);
double rounding_threshold = 0.5;
components.fractional = (int_fast64_t)scaled_remainder; // when precision == 0, the assigned value should be 0
scaled_remainder -= (/* double */ unsigned long)components.fractional; // when precision == 0, this will not change scaled_remainder
components.fractional = (int_fast64_t)scaled_remainder; // when precision == 0, the assigned value should be 0
scaled_remainder -= (double)components.fractional; // when precision == 0, this will not change scaled_remainder
components.fractional += (scaled_remainder >= rounding_threshold);
if (scaled_remainder == rounding_threshold)
@ -722,7 +732,7 @@ static struct double_components get_normalized_components(bool negative, printf_
// Note: for precision = 0, this will "translate" the rounding effect from
// the fractional part to the integral part where it should actually be
// felt (as prec_power_of_10 is 1)
if ((/* double */ unsigned long)components.fractional >= prec_power_of_10)
if ((double)components.fractional >= prec_power_of_10)
{
components.fractional = 0;
++components.integral;
@ -833,7 +843,7 @@ static void print_broken_up_decimal(
}
// internal ftoa for fixed decimal floating point
static void print_decimal_number(output_gadget_t *output, /* double */ unsigned long number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
static void print_decimal_number(output_gadget_t *output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
{
struct double_components value_ = get_components(number, precision);
print_broken_up_decimal(value_, output, precision, width, flags, buf, len);
@ -843,19 +853,19 @@ static void print_decimal_number(output_gadget_t *output, /* double */ unsigned
// A floor function - but one which only works for numbers whose
// floor value is representable by an int.
static int bastardized_floor(/* double */ unsigned long x)
static int bastardized_floor(double x)
{
if (x >= 0)
{
return (int)x;
}
int n = (int)x;
return (((/* double */ unsigned long)n) == x) ? n : n - 1;
return (((double)n) == x) ? n : n - 1;
}
// Computes the base-10 logarithm of the input number - which must be an actual
// positive number (not infinity or NaN, nor a sub-normal)
static /* double */ unsigned long log10_of_positive(/* double */ unsigned long positive_number)
static double log10_of_positive(double positive_number)
{
// The implementation follows David Gay (https://www.ampl.com/netlib/fp/dtoa.c).
//
@ -871,36 +881,23 @@ static /* double */ unsigned long log10_of_positive(/* double */ unsigned long p
// drop the exponent, so dwba.F comes into the range [1,2)
dwba.U = (dwba.U & (((double_uint_t)(1) << DOUBLE_STORED_MANTISSA_BITS) - 1U)) |
((double_uint_t)DOUBLE_BASE_EXPONENT << DOUBLE_STORED_MANTISSA_BITS);
/* double */ unsigned long z = (dwba.F - 1 /* 1.5 */);
// return (
// // Taylor expansion around 1.5:
// 0.1760912590556812420 // Expansion term 0: ln(1.5) / ln(10)
// + z * 0.2895296546021678851 // Expansion term 1: (M - 1.5) * 2/3 / ln(10)
// #if PRINTF_LOG10_TAYLOR_TERMS > 2
// - z * z * 0.0965098848673892950 // Expansion term 2: (M - 1.5)^2 * 2/9 / ln(10)
// #if PRINTF_LOG10_TAYLOR_TERMS > 3
// + z * z * z * 0.0428932821632841311 // Expansion term 2: (M - 1.5)^3 * 8/81 / ln(10)
// #endif
// #endif
// // exact log_2 of the exponent x, with logarithm base change
// + exp2 * 0.30102999566398119521 // = exp2 * log_10(2) = exp2 * ln(2)/ln(10)
// );
double z = (dwba.F - 1.5);
return (
// Taylor expansion around 1.5:
0 // Expansion term 0: ln(1.5) / ln(10)
+ z * 0 // Expansion term 1: (M - 1.5) * 2/3 / ln(10)
0.1760912590556812420 // Expansion term 0: ln(1.5) / ln(10)
+ z * 0.2895296546021678851 // Expansion term 1: (M - 1.5) * 2/3 / ln(10)
#if PRINTF_LOG10_TAYLOR_TERMS > 2
- z * z * 0 // Expansion term 2: (M - 1.5)^2 * 2/9 / ln(10)
- z * z * 0.0965098848673892950 // Expansion term 2: (M - 1.5)^2 * 2/9 / ln(10)
#if PRINTF_LOG10_TAYLOR_TERMS > 3
+ z * z * z * 0 // Expansion term 2: (M - 1.5)^3 * 8/81 / ln(10)
+ z * z * z * 0.0428932821632841311 // Expansion term 2: (M - 1.5)^3 * 8/81 / ln(10)
#endif
#endif
// exact log_2 of the exponent x, with logarithm base change
+ exp2 * 0 // = exp2 * log_10(2) = exp2 * ln(2)/ln(10)
+ exp2 * 0.30102999566398119521 // = exp2 * log_10(2) = exp2 * ln(2)/ln(10)
);
}
static /* double */ unsigned long pow10_of_int(int floored_exp10)
static double pow10_of_int(int floored_exp10)
{
// A crude hack for avoiding undesired behavior with barely-normal or slightly-subnormal values.
if (floored_exp10 == DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10)
@ -909,11 +906,9 @@ static /* double */ unsigned long pow10_of_int(int floored_exp10)
}
// Compute 10^(floored_exp10) but (try to) make sure that doesn't overflow
double_with_bit_access dwba;
// int exp2 = bastardized_floor(floored_exp10 * 3.321928094887362 + 0.5);
// const /* double */ unsigned long z = floored_exp10 * 2.302585092994046 - exp2 * 0.6931471805599453;
int exp2 = bastardized_floor(floored_exp10 * 3 + 1 /* 0.5 */);
const /* double */ unsigned long z = floored_exp10 * 2 - exp2 * 0;
const /* double */ unsigned long z2 = z * z;
int exp2 = bastardized_floor(floored_exp10 * 3.321928094887362 + 0.5);
const double z = floored_exp10 * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z;
dwba.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS;
// compute exp(z) using continued fractions,
// see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
@ -921,28 +916,27 @@ static /* double */ unsigned long pow10_of_int(int floored_exp10)
return dwba.F;
}
static void print_exponential_number(output_gadget_t *output, /* double */ unsigned long number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
static void print_exponential_number(output_gadget_t *output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
{
const bool negative = get_sign_bit(number);
// This number will decrease gradually (by factors of 10) as we "extract" the exponent out of it
/* double */ unsigned long abs_number = negative ? -number : number;
double abs_number = negative ? -number : number;
int floored_exp10;
bool abs_exp10_covered_by_powers_table;
struct scaling_factor normalization;
// Determine the decimal exponent
// if (abs_number == 0.0)
if (abs_number == 0)
if (abs_number == 0.0)
{
// TODO: This is a special-case for 0.0 (and -0.0); but proper handling is required for denormals more generally.
floored_exp10 = 0; // ... and no need to set a normalization factor or check the powers table
}
else
{
/* double */ unsigned long exp10 = log10_of_positive(abs_number);
double exp10 = log10_of_positive(abs_number);
floored_exp10 = bastardized_floor(exp10);
/* double */ unsigned long p10 = pow10_of_int(floored_exp10);
double p10 = pow10_of_int(floored_exp10);
// correct for rounding errors
if (abs_number < p10)
{
@ -1001,7 +995,7 @@ static void print_exponential_number(output_gadget_t *output, /* double */ unsig
}
}
// the floored_exp10 format is "E%+03d" and largest possible floored_exp10 value for a 64-bit / *doubl e*/unsigned long
// the floored_exp10 format is "E%+03d" and largest possible floored_exp10 value for a 64-bit double
// is "307" (for 2^1023), so we set aside 4-5 characters overall
printf_size_t exp10_part_width = fall_back_to_decimal_only_mode ? 0U : (PRINTF_ABS(floored_exp10) < 100) ? 4U
: 5U;
@ -1045,7 +1039,7 @@ static void print_exponential_number(output_gadget_t *output, /* double */ unsig
}
#endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
static void print_floating_point(output_gadget_t *output, /* double */ unsigned long value, printf_size_t precision, printf_size_t width, printf_flags_t flags, bool prefer_exponential)
static void print_floating_point(output_gadget_t *output, double value, printf_size_t precision, printf_size_t width, printf_flags_t flags, bool prefer_exponential)
{
char buf[PRINTF_DECIMAL_BUFFER_SIZE];
printf_size_t len = 0U;
@ -1056,22 +1050,19 @@ static void print_floating_point(output_gadget_t *output, /* double */ unsigned
out_rev_(output, "nan", 3, width, flags);
return;
}
// if (value < -DBL_MAX)
if (value < -1)
if (value < -DBL_MAX)
{
out_rev_(output, "fni-", 4, width, flags);
return;
}
// if (value > DBL_MAX)
if (value > 1)
if (value > DBL_MAX)
{
out_rev_(output, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
return;
}
if (!prefer_exponential &&
// ((value > PRINTF_FLOAT_NOTATION_THRESHOLD) || (value < -PRINTF_FLOAT_NOTATION_THRESHOLD)))
((value > 1) || (value < -1)))
((value > PRINTF_FLOAT_NOTATION_THRESHOLD) || (value < -PRINTF_FLOAT_NOTATION_THRESHOLD)))
{
// The required behavior of standard printf is to print _every_ integral-part digit -- which could mean
// printing hundreds of characters, overflowing any fixed internal buffer and necessitating a more complicated
@ -1140,29 +1131,31 @@ static printf_flags_t parse_flags(const char **format)
} while (true);
}
// internal vsnprintf - used for implementing _all library functions
// Note: We don't like the C standard's parameter names, so using more informative parameter names
// here instead.
static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
static inline void format_string_loop(output_gadget_t *output, const char *format, va_list args)
{
// Note: The library only calls _vsnprintf() with output->pos being 0. However, it is
// possible to call this function with a non-zero pos value for some "remedial printing".
#if PRINTF_CHECK_FOR_NUL_IN_FORMAT_SPECIFIER
#define ADVANCE_IN_FORMAT_STRING(cptr_) \
do \
{ \
(cptr_)++; \
if (!*(cptr_)) \
return; \
} while (0)
#else
#define ADVANCE_IN_FORMAT_STRING(cptr_) (cptr_)++
#endif
while (*format)
{
// format specifier? %[flags][width][.precision][length]
if (*format != '%')
{
// no
// A regular content character
putchar_via_gadget(output, *format);
format++;
continue;
}
else
{
// yes, evaluate it
format++;
}
// We're parsing a format specifier: %[flags][width][.precision][length]
ADVANCE_IN_FORMAT_STRING(format);
printf_flags_t flags = parse_flags(&format);
@ -1184,7 +1177,7 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
{
width = (printf_size_t)w;
}
format++;
ADVANCE_IN_FORMAT_STRING(format);
}
// evaluate precision field
@ -1192,7 +1185,7 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
if (*format == '.')
{
flags |= FLAGS_PRECISION;
format++;
ADVANCE_IN_FORMAT_STRING(format);
if (is_digit_(*format))
{
precision = (printf_size_t)atou_(&format);
@ -1201,7 +1194,7 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
{
const int precision_ = va_arg(args, int);
precision = precision_ > 0 ? (printf_size_t)precision_ : 0U;
format++;
ADVANCE_IN_FORMAT_STRING(format);
}
}
@ -1211,16 +1204,16 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
#ifdef PRINTF_SUPPORT_MSVC_STYLE_INTEGER_SPECIFIERS
case 'I':
{
format++;
ADVANCE_IN_FORMAT_STRING(format);
// Greedily parse for size in bits: 8, 16, 32 or 64
switch (*format)
{
case '8':
flags |= FLAGS_INT8;
format++;
ADVANCE_IN_FORMAT_STRING(format);
break;
case '1':
format++;
ADVANCE_IN_FORMAT_STRING(format);
if (*format == '6')
{
format++;
@ -1228,18 +1221,18 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
}
break;
case '3':
format++;
ADVANCE_IN_FORMAT_STRING(format);
if (*format == '2')
{
format++;
ADVANCE_IN_FORMAT_STRING(format);
flags |= FLAGS_INT32;
}
break;
case '6':
format++;
ADVANCE_IN_FORMAT_STRING(format);
if (*format == '4')
{
format++;
ADVANCE_IN_FORMAT_STRING(format);
flags |= FLAGS_INT64;
}
break;
@ -1251,33 +1244,33 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
#endif
case 'l':
flags |= FLAGS_LONG;
format++;
ADVANCE_IN_FORMAT_STRING(format);
if (*format == 'l')
{
flags |= FLAGS_LONG_LONG;
format++;
ADVANCE_IN_FORMAT_STRING(format);
}
break;
case 'h':
flags |= FLAGS_SHORT;
format++;
ADVANCE_IN_FORMAT_STRING(format);
if (*format == 'h')
{
flags |= FLAGS_CHAR;
format++;
ADVANCE_IN_FORMAT_STRING(format);
}
break;
case 't':
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
ADVANCE_IN_FORMAT_STRING(format);
break;
case 'j':
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
ADVANCE_IN_FORMAT_STRING(format);
break;
case 'z':
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
ADVANCE_IN_FORMAT_STRING(format);
break;
default:
break;
@ -1390,7 +1383,7 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
case 'F':
if (*format == 'F')
flags |= FLAGS_UPPERCASE;
print_floating_point(output, va_arg(args, /* double */ unsigned long), precision, width, flags, PRINTF_PREFER_DECIMAL);
print_floating_point(output, va_arg(args, double), precision, width, flags, PRINTF_PREFER_DECIMAL);
format++;
break;
#endif
@ -1403,7 +1396,7 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
flags |= FLAGS_ADAPT_EXP;
if ((*format == 'E') || (*format == 'G'))
flags |= FLAGS_UPPERCASE;
print_floating_point(output, va_arg(args, /* double */ unsigned long), precision, width, flags, PRINTF_PREFER_EXPONENTIAL);
print_floating_point(output, va_arg(args, double), precision, width, flags, PRINTF_PREFER_EXPONENTIAL);
format++;
break;
#endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
@ -1517,6 +1510,14 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
break;
}
}
}
// internal vsnprintf - used for implementing _all library functions
static int vsnprintf_impl(output_gadget_t *output, const char *format, va_list args)
{
// Note: The library only calls vsnprintf_impl() with output->pos being 0. However, it is
// possible to call this function with a non-zero pos value for some "remedial printing".
format_string_loop(output, format, args);
// termination
append_termination_with_gadget(output);
@ -1530,13 +1531,13 @@ static int _vsnprintf(output_gadget_t *output, const char *format, va_list args)
int vprintf_(const char *format, va_list arg)
{
output_gadget_t gadget = extern_putchar_gadget();
return _vsnprintf(&gadget, format, arg);
return vsnprintf_impl(&gadget, format, arg);
}
int vsnprintf_(char *s, size_t n, const char *format, va_list arg)
{
output_gadget_t gadget = buffer_gadget(s, n);
return _vsnprintf(&gadget, format, arg);
return vsnprintf_impl(&gadget, format, arg);
}
int vsprintf_(char *s, const char *format, va_list arg)
@ -1547,7 +1548,7 @@ int vsprintf_(char *s, const char *format, va_list arg)
int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg)
{
output_gadget_t gadget = function_gadget(out, extra_arg);
return _vsnprintf(&gadget, format, arg);
return vsnprintf_impl(&gadget, format, arg);
}
int printf_(const char *format, ...)
@ -1585,7 +1586,3 @@ int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char
va_end(args);
return ret;
}
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -9,6 +9,13 @@ extern "C"
int isspace(int c);
int isempty(char *str);
unsigned int isdelim(char c, char *delim);
int abs(int i);
void swap(char *x, char *y);
char *reverse(char *Buffer, int i, int j);
int atoi(const char *String);
double atof(const char *String);
char *itoa(int Value, char *Buffer, int Base);
void *memcpy(void *dest, const void *src, size_t n);
void *memset(void *dest, int c, size_t n);

View File

@ -1,2 +1,2 @@
#pragma once
#include <string.h>
#include <convert.h>

View File

@ -1,11 +1,15 @@
#ifndef __FENNIX_KERNEL_INTERNAL_MEMORY_H__
#define __FENNIX_KERNEL_INTERNAL_MEMORY_H__
#ifdef __cplusplus
#include <boot/binfo.h>
#include <bitmap.hpp>
#include <lock.hpp>
#endif // __cplusplus
#include <types.h>
#ifdef __cplusplus
extern uint64_t _kernel_start, _kernel_end;
extern uint64_t _kernel_text_end, _kernel_data_end, _kernel_rodata_end;
@ -51,6 +55,14 @@ extern uint64_t _kernel_text_end, _kernel_data_end, _kernel_rodata_end;
namespace Memory
{
enum MemoryAllocatorType
{
None,
Pages,
XallocV1,
liballoc11
};
/**
* @brief https://wiki.osdev.org/images/4/41/64-bit_page_tables1.png
* @brief https://wiki.osdev.org/images/6/6b/64-bit_page_tables2.png
@ -429,17 +441,19 @@ void operator delete[](void *Pointer);
void operator delete(void *Pointer, long unsigned int Size);
void operator delete[](void *Pointer, long unsigned int Size);
void *HeapMalloc(uint64_t Size);
void *HeapCalloc(uint64_t n, uint64_t Size);
void *HeapRealloc(void *Address, uint64_t Size);
void HeapFree(void *Address);
extern Memory::Physical KernelAllocator;
extern Memory::PageTable *KernelPageTable;
#endif // __cplusplus
EXTERNC void *HeapMalloc(uint64_t Size);
EXTERNC void *HeapCalloc(uint64_t n, uint64_t Size);
EXTERNC void *HeapRealloc(void *Address, uint64_t Size);
EXTERNC void HeapFree(void *Address);
#define kmalloc(Size) HeapMalloc(Size)
#define kcalloc(n, Size) HeapCalloc(n, Size)
#define krealloc(Address, Size) HeapRealloc(Address, Size)
#define kfree(Address) HeapFree(Address)
extern Memory::Physical KernelAllocator;
extern Memory::PageTable *KernelPageTable;
#endif // !__FENNIX_KERNEL_INTERNAL_MEMORY_H__