Compare commits

...

2 Commits

Author SHA1 Message Date
Lephe 86cd9b98d4
small improvements
* Update TOTO list
* Change the type of gint_vbr to comply with a new warning in GCC 9
* Add strcmp()
2019-09-19 15:59:38 +02:00
Lephe a05d3416f0
std: support integer size formats (hh, h, l, ll) 2019-09-19 15:58:35 +02:00
6 changed files with 77 additions and 34 deletions

5
TODO
View File

@ -13,13 +13,12 @@ Complementary elements on existing code.
* topti: support unicode fonts
* gray: find good values for more models than the Graph 35+E II
* render: get rid of GINT_NEED_VRAM and #define vram gint_vram if you need
* dma: dma_memcpy() and dma_memset(), possibly requiring alignment
* dma: maybe relax the 4-byte size constraint for dma_memset()
* core: try to leave add-in without reset in case of fatal exception
* core: try to leave add-in without reset in case of panic
* topti: support Unicode fonts
* hardware: fill in the HWMEM_FITTLB flag
* keyboard: think of extended functions
* keyboard: add an intermediate-level API with some sort of IsKeyDown()
* keyboard: implement keydown() in an event-compliant way
* cpg: spread spectrum on fxcg50
* bopti: blending modes for monochrome bitmaps (use topti assembler)
* display: use more of topti's assembler in drect()

View File

@ -9,9 +9,21 @@
#include <stdarg.h>
/* Formatted printing functions
These functions implement most of printf()'s features, except:
* Large parameters (ll)
* Floating-point (%e, %E, %f, %F, %g, %G, %a, %A) */
These functions implement most of printf()'s features, including:
* Signed and unsigned integer formats (%d, %i, %o, %u, %x, %X)
* Character, string and pointer formats (%c, %s, %p)
* Format options (0, #, -, (space), length, precision)
* Parameter size (hh, h, l, ll)
* Limiting the size of the output and still returning the whole length
They do not support:
* Floating-point (%e, %E, %f, %F, %g, %G, %a, %A)
* Exotic integer types (intmax_t) or features (thousands separators)
A new fixed-point format %j has been added; it behaves like %d but includes
a decimal point. The number of decimal places is specified by the precision
field. */
/* Print to string from var args */
int sprintf(char *str, char const *format, ...);

View File

@ -16,10 +16,13 @@ void *memset(void *dest, int byte, size_t n);
/* strlen(): Length of a NUL-terminated string */
size_t strlen(char const *str);
/* strncpy(): Copy a string with a size limit*/
/* strncpy(): Copy a string with a size limit */
char *strncpy(char *dst, char const *src, size_t n);
/* strcat(): Concatenation of src in dest*/
/* strcat(): Concatenation a string to a pre-allocated space */
char *strcat(char *dest, const char *src);
/* strcmp(): Compare NUL-terminated strings */
int strcmp(char const *s1, char const *s2);
#endif /* GINT_STD_STRING */

View File

@ -10,7 +10,7 @@
#include <gint/mpu/intc.h>
/* VBR address, from the linker script */
extern char gint_vbr;
extern char gint_vbr[];
/* System's VBR address */
GBSS static uint32_t system_vbr;
/* Size of exception and TLB handler */

View File

@ -54,12 +54,12 @@ struct kprint_options
/* How much significant characters of data, meaning varies */
uint16_t precision;
/* Size specifier, may be one of:
(b) 8-bit data (%o, %x)
(w) 16-bit data (%o, %x)
(l) 32-bit data (%o, %x) or long int type (%i, %d, %u)
(q) 64-bit data (%o, %x) or long long int type (%i, %d, %u)
(h) short int type (%i, %d, %u) */
/* Size specifier for integers (%o, %x, %i, %d, %u), may be one of:
(0) char (8-bit)
(1) short (16-bit)
(2) int (32-bit)
(3) long (32-bit)
(4) long long (64-bit) */
uint8_t size;
/* (#) Alternative form: base prefixes, decimal point */
@ -146,8 +146,9 @@ GINLINE static void kprint_outn(int byte, size_t n)
/* kprint_opt(): Parse option strings */
struct kprint_options kprint_opt(char const **options_ptr)
{
/* No options enabled by default */
struct kprint_options opt = { 0 };
/* No options enabled by default, set the size to int */
struct kprint_options opt = { .size = 2 };
/* This function acts as a deterministic finite automaton */
enum {
basic, /* Reading option characters */
@ -159,8 +160,8 @@ struct kprint_options kprint_opt(char const **options_ptr)
for(int c; (c = *options); options++)
{
int c_lower = c | 0x20;
if(!c || (c_lower >= 'a' && c_lower < 'z')) break;
int c_low = c | 0x20;
if(c_low >= 'a' && c_low <= 'z' && c != 'h' && c != 'l') break;
if(c == '.')
{
@ -192,8 +193,8 @@ struct kprint_options kprint_opt(char const **options_ptr)
}
/* Data size */
if(c == 'l') opt.size++;
if(c == 'h') opt.size--;
if(c == 'l') opt.size++;
if(c >= '1' && c <= '9') state = length, options--;
}
@ -336,7 +337,7 @@ static void kformat_geometry(int spec, struct kprint_options *opt,
Fills up the provided digit string from least significant to most
significant digit, not adding zeros except if argument is zero. Returns the
number of digits. No NUL terminator is added. */
static int digits_10(char *str, uint n)
static int digits_10(char *str, uint64_t n)
{
int digits = 0;
@ -350,7 +351,7 @@ static int digits_10(char *str, uint n)
}
/* digits_16(): Generate digits in base 16 */
static int digits_16(char *str, int uppercase, uint32_t n)
static int digits_16(char *str, int uppercase, uint64_t n)
{
char *hex = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
int digits = 0;
@ -364,7 +365,7 @@ static int digits_16(char *str, int uppercase, uint32_t n)
}
/* digits_8(): Generate digits in base 8 */
static int digits_8(char *str, uint32_t n)
static int digits_8(char *str, uint64_t n)
{
int digits = 0;
@ -376,6 +377,28 @@ static int digits_8(char *str, uint32_t n)
return digits;
}
//---
// Loading helpers
//---
static int64_t load_i(int size, va_list *args)
{
/* All smaller types are promoeted to int so we can't read the
explicitly. They have been converted and sign-extended we don't need
to care what their size is, the result will remain the same */
if(size == 3) return va_arg(*args, long);
if(size == 4) return va_arg(*args, long long);
return va_arg(*args, int);
}
static uint64_t load_u(int size, va_list *args)
{
/* Again, no need to care about small types */
if(size == 3) return va_arg(*args, unsigned long);
if(size == 4) return va_arg(*args, unsigned long long);
return va_arg(*args, unsigned int);
}
//---
// Individual formatters
//---
@ -430,7 +453,7 @@ static void kformat_str(KFORMAT_ARGS)
{pre} Forces a minimal number of digits, creating 0s (overrides '0') */
static void kformat_int(KFORMAT_ARGS)
{
int n = va_arg(*args, int);
int64_t n = load_i(opt->size, args);
/* Compute the sign and the absolute value */
struct geometry g = {
@ -468,9 +491,9 @@ static void kformat_int(KFORMAT_ARGS)
{pre} Forces a minimal number of digits, creating 0s (overrides '0') */
static void kformat_uint(KFORMAT_ARGS)
{
uint n = va_arg(*args, uint);
uint64_t n = load_u(opt->size, args);
char digits[32];
char digits[48];
int pure = 0, total;
int specl = spec | 0x20;
@ -525,7 +548,7 @@ static void kformat_ptr(KFORMAT_ARGS)
{pre} Number of digits after the decimal dot */
static void kformat_fixed(KFORMAT_ARGS)
{
int n = va_arg(*args, int);
int64_t n = load_i(opt->size, args);
/* Compute the sign and the absolute value */
struct geometry g = {

View File

@ -6,24 +6,30 @@
#include <gint/defs/attributes.h>
#include <stdarg.h>
GWEAK size_t strlen(const char *str)
GWEAK size_t strlen(char const *str)
{
int len = 0;
while(str[len]) len++;
return len;
}
GWEAK char *strncpy(char *dst, const char *src, size_t n)
GWEAK char *strncpy(char *dst, char const *src, size_t n)
{
size_t i = 0;
while(i < n && (dst[i] = src[i])) i++;
return dst;
}
GWEAK char *strcat(char *dest, const char *src)
GWEAK char *strcat(char *dest, char const *src)
{
unsigned long fin_dest = strlen(dest);
unsigned int i;
for (i = 0 ; i <= strlen(src) ; i++) dest[fin_dest + i] = src[i];
return dest;
unsigned long fin_dest = strlen(dest);
unsigned int i;
for (i = 0 ; i <= strlen(src) ; i++) dest[fin_dest + i] = src[i];
return dest;
}
GWEAK int strcmp(char const *s1, char const *s2)
{
while(*s1 && *s1 == *s2) s1++, s2++;
return *s1 - *s2;
}