mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
improve structure of sources and formatted printer
* Create an `src/3rdparty` folder for third-party code (to add the Grisu2B alfogithm soon). * Split the formatted printer into gint's kprint (src/kprint), its extension and interface (include/gint/kprint.h), and its use in the standard stdio functions (src/std/print.c). * Slightly improve the interface of kformat_geometry() to avoid relying on knowing format specifiers. * Add a function to register more formatters, to allow floating-point formatters without requiring them.
This commit is contained in:
parent
ee7b4f27b8
commit
023675d449
10 changed files with 229 additions and 130 deletions
|
@ -30,6 +30,7 @@ set(SOURCES_COMMON
|
||||||
src/keysc/iokbd.c
|
src/keysc/iokbd.c
|
||||||
src/keysc/keycodes.c
|
src/keysc/keycodes.c
|
||||||
src/keysc/keysc.c
|
src/keysc/keysc.c
|
||||||
|
src/kprint/kprint.c
|
||||||
src/mmu/mmu.c
|
src/mmu/mmu.c
|
||||||
src/render/dhline.c
|
src/render/dhline.c
|
||||||
src/render/dimage.c
|
src/render/dimage.c
|
||||||
|
@ -43,18 +44,18 @@ set(SOURCES_COMMON
|
||||||
src/rtc/rtc.c
|
src/rtc/rtc.c
|
||||||
src/rtc/rtc_ticks.c
|
src/rtc/rtc_ticks.c
|
||||||
src/spu/spu.c
|
src/spu/spu.c
|
||||||
src/std/tinymt32/rand.c
|
|
||||||
src/std/tinymt32/tinymt32.c
|
|
||||||
src/std/memcmp.s
|
src/std/memcmp.s
|
||||||
src/std/memcpy.s
|
src/std/memcpy.s
|
||||||
src/std/memmove.s
|
src/std/memmove.s
|
||||||
src/std/memset.s
|
src/std/memset.s
|
||||||
src/std/stdio.c
|
src/std/print.c
|
||||||
src/std/string.c
|
src/std/string.c
|
||||||
src/tmu/inth-etmu.s
|
src/tmu/inth-etmu.s
|
||||||
src/tmu/inth-tmu.s
|
src/tmu/inth-tmu.s
|
||||||
src/tmu/sleep.c
|
src/tmu/sleep.c
|
||||||
src/tmu/tmu.c
|
src/tmu/tmu.c
|
||||||
|
src/3rdparty/tinymt32/rand.c
|
||||||
|
src/3rdparty/tinymt32/tinymt32.c
|
||||||
)
|
)
|
||||||
set(SOURCES_FX
|
set(SOURCES_FX
|
||||||
src/gray/engine.c
|
src/gray/engine.c
|
||||||
|
|
|
@ -17,7 +17,7 @@ Currently, this only includes:
|
||||||
|
|
||||||
* A stripped-down version of the [TinyMT random number generator](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index.html)
|
* A stripped-down version of the [TinyMT random number generator](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index.html)
|
||||||
([GitHub repository](https://github.com/MersenneTwister-Lab/TinyMT)) by
|
([GitHub repository](https://github.com/MersenneTwister-Lab/TinyMT)) by
|
||||||
Mutsuo Saito and Makoto Matsumoto. See `src/std/tinymt32/LICENSE.txt`.
|
Mutsuo Saito and Makoto Matsumoto. See `src/3rdparty/tinymt32/LICENSE.txt`.
|
||||||
|
|
||||||
## Programming interface
|
## Programming interface
|
||||||
|
|
||||||
|
|
1
TODO
1
TODO
|
@ -1,4 +1,5 @@
|
||||||
Extensions on existing code:
|
Extensions on existing code:
|
||||||
|
* kernel: check if cpu_setVBR() really needs to be perma-mapped
|
||||||
* stdio: support %f in printf
|
* stdio: support %f in printf
|
||||||
* project: add license file
|
* project: add license file
|
||||||
* kernel: group linker script symbols in a single header file
|
* kernel: group linker script symbols in a single header file
|
||||||
|
|
138
include/gint/kprint.h
Normal file
138
include/gint/kprint.h
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
//---
|
||||||
|
// gint:kprint - gint's printf(3)-like formatted printer
|
||||||
|
//---
|
||||||
|
|
||||||
|
#ifndef GINT_KPRINT
|
||||||
|
#define GINT_KPRINT
|
||||||
|
|
||||||
|
#include <gint/defs/types.h>
|
||||||
|
#include <gint/defs/attributes.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Formatted printing
|
||||||
|
//---
|
||||||
|
|
||||||
|
/* kvsprint(): Formatted print to string
|
||||||
|
This function is similar to vsnprintf(3), except that variadic arguments are
|
||||||
|
passed as a pointer to va_list. For standard functions like vsnprintf(3),
|
||||||
|
see <stdio.h>. */
|
||||||
|
size_t kvsprint(char *output, size_t len, char const *format, va_list *args);
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Printer extensions
|
||||||
|
//---
|
||||||
|
|
||||||
|
/* Arguments passed to formatters */
|
||||||
|
#define KFORMAT_ARGS \
|
||||||
|
GUNUSED int spec, /* Specifier letter */ \
|
||||||
|
GUNUSED kprint_options_t *opt, /* Other options in format */ \
|
||||||
|
va_list *args /* Vararg list to read from */
|
||||||
|
|
||||||
|
/* kprint_options_t: Standard format options */
|
||||||
|
typedef struct {
|
||||||
|
/* Minimal length of formatted string (padding can be added) */
|
||||||
|
uint16_t length;
|
||||||
|
/* How much significant characters of data, meaning varies */
|
||||||
|
uint16_t precision;
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
uint alternative :1;
|
||||||
|
/* ( ) Add a blank sign before nonnegative numbers */
|
||||||
|
uint blank_sign :1;
|
||||||
|
/* (+) Always add a sign before a number (overrides ' ') */
|
||||||
|
uint force_sign :1;
|
||||||
|
|
||||||
|
/* Alignment options: each option overrides all others before itself
|
||||||
|
NUL By default, align right
|
||||||
|
(0) Left-pad numerical values with zeros
|
||||||
|
(-) Align left by adding space on the right, dropping zeros */
|
||||||
|
uint8_t alignment;
|
||||||
|
|
||||||
|
} GPACKED(2) kprint_options_t;
|
||||||
|
|
||||||
|
/* kprint_formatter_t: Type of format function */
|
||||||
|
typedef void (*kprint_formatter_t)(KFORMAT_ARGS);
|
||||||
|
|
||||||
|
/* kprint_register(): Register a formatter
|
||||||
|
|
||||||
|
The formatter designated by the specified lowercase letter (eg 'q') is
|
||||||
|
registered. It will handle formats for both the lowercase and uppercase
|
||||||
|
formats (eg "%q" and "%Q").
|
||||||
|
|
||||||
|
Default formatters can be overridden (although not advised), but formatters
|
||||||
|
for "h" and "l" and "z" cannot be set because these letters are used as size
|
||||||
|
specifiers (eg in "%hd" or "%zu").
|
||||||
|
|
||||||
|
A formatter can be removed or disabled by registering NULL.
|
||||||
|
|
||||||
|
@spec Specifier to use, should be a lowercase letter
|
||||||
|
@kformat Format function */
|
||||||
|
void kprint_register(int spec, kprint_formatter_t kformat);
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Helper functions for formatters
|
||||||
|
//---
|
||||||
|
|
||||||
|
/* kprint_geometry_t: General geometry for a format
|
||||||
|
This helper defines the structure of a format as follows:
|
||||||
|
|
||||||
|
sign v |< zeros >| |< content >|
|
||||||
|
_ _ _ _ _ _ _ _ _ + 0 x 0 0 0 0 0 0 8 a c 7 . 3 c _ _ _ _ _ _ _ _ _ _
|
||||||
|
|< left_spaces >| ^^^ prefix |< right_spaces >|
|
||||||
|
|
||||||
|
The sign character is absent if sign=0, the prefix is specified by length
|
||||||
|
and is also absent if prefix=0. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t left_spaces; /* Spaces before content */
|
||||||
|
uint8_t sign; /* Sign character (NUL, ' ', '+' or '-') */
|
||||||
|
uint8_t prefix; /* Base prefix ('0', '0x', etc) length */
|
||||||
|
uint16_t zeros; /* For integer displays, number of zeros */
|
||||||
|
uint16_t content; /* Content length in bytes */
|
||||||
|
uint16_t right_spaces; /* Spaces after content */
|
||||||
|
|
||||||
|
/* Style of display:
|
||||||
|
KPRINT_GENERIC Sign ignored, 0-padding ignored
|
||||||
|
KPRINT_INTEGER .precision causes 0-padding
|
||||||
|
KPRINT_NUMERICAL No effect */
|
||||||
|
enum { KPRINT_GENERIC = 0, KPRINT_INTEGER, KPRINT_NUMERICAL } style;
|
||||||
|
|
||||||
|
} GPACKED(2) kprint_geometry_t;
|
||||||
|
|
||||||
|
/* kformat_geometry(): Calculate the geometry of a format
|
||||||
|
|
||||||
|
The caller provides as input:
|
||||||
|
* opt, as passed by the main kprint() routine
|
||||||
|
* g->prefix, the length of the desired prefix (if unused, 0)
|
||||||
|
* g->content, the natural content length for the provided data
|
||||||
|
* g->sign, the sign of the input ("+" or "-"); for KPRINT_GENERIC, 0
|
||||||
|
|
||||||
|
This function outputs:
|
||||||
|
* g->sign, which can be changed to " " or NUL depending on opt
|
||||||
|
* All other fields of g that are not part of the input
|
||||||
|
|
||||||
|
The algorithm for laying out the format is as follows.
|
||||||
|
1. For numerical and integer formats, turn a "+" sign into " " if
|
||||||
|
opt->blank_sign is set, "+" if opt->force_sign is set, NUL otherwise.
|
||||||
|
2. Compute the total amount of padding needed to reach opt->length.
|
||||||
|
3. In integer style, if a precision is specified and more than content
|
||||||
|
length plus sign and prefix, turn some padding into zeros.
|
||||||
|
4. If numerical and integer styles, if opt->alignment == '0' turn all the
|
||||||
|
padding into zeros.
|
||||||
|
5. Turn remaining padding into spaces at the left (if opt->alignment == NUL)
|
||||||
|
or right (if opt->alignment == '-').
|
||||||
|
|
||||||
|
@opt Options provided by the main kprint() routine
|
||||||
|
@g Format geometry (input/output) */
|
||||||
|
void kformat_geometry(kprint_options_t *opt, kprint_geometry_t *g);
|
||||||
|
|
||||||
|
#endif /* GINT_KPRINT */
|
|
@ -1,5 +1,5 @@
|
||||||
//---
|
//---
|
||||||
// The stdio formatted printer.
|
// gint:kprint - gint's printf(3)-like formatted printer
|
||||||
//
|
//
|
||||||
// Things to change when creating new formats:
|
// Things to change when creating new formats:
|
||||||
// -> List of prototypes at the end of the definition section
|
// -> List of prototypes at the end of the definition section
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <gint/std/stdio.h>
|
#include <gint/std/stdio.h>
|
||||||
#include <gint/std/string.h>
|
#include <gint/std/string.h>
|
||||||
|
#include <gint/kprint.h>
|
||||||
|
|
||||||
#include <gint/defs/attributes.h>
|
#include <gint/defs/attributes.h>
|
||||||
#include <gint/defs/types.h>
|
#include <gint/defs/types.h>
|
||||||
|
@ -21,8 +22,6 @@
|
||||||
//---
|
//---
|
||||||
|
|
||||||
#define KPRINT_BUFSIZE 64
|
#define KPRINT_BUFSIZE 64
|
||||||
#define KFORMAT_ARGS \
|
|
||||||
GUNUSED int spec, GUNUSED struct kprint_options *opt, va_list *args
|
|
||||||
|
|
||||||
/* Current position in the output buffer */
|
/* Current position in the output buffer */
|
||||||
static char *kprint_ptr = NULL;
|
static char *kprint_ptr = NULL;
|
||||||
|
@ -44,41 +43,6 @@ static enum {
|
||||||
// KprintOutputDevice = 1,
|
// KprintOutputDevice = 1,
|
||||||
} kprint_type;
|
} kprint_type;
|
||||||
|
|
||||||
/*
|
|
||||||
struct kprint_options -- standard format options
|
|
||||||
*/
|
|
||||||
struct kprint_options
|
|
||||||
{
|
|
||||||
/* Minimal length of formatted string (padding can be added) */
|
|
||||||
uint16_t length;
|
|
||||||
/* How much significant characters of data, meaning varies */
|
|
||||||
uint16_t precision;
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
uint alternative :1;
|
|
||||||
/* ( ) Add a blank sign before nonnegative numbers */
|
|
||||||
uint blank_sign :1;
|
|
||||||
/* (+) Always add a sign before a number (overrides ' ') */
|
|
||||||
uint force_sign :1;
|
|
||||||
|
|
||||||
/* Alignment options: each option overrides all others before itself
|
|
||||||
NUL By default, align right
|
|
||||||
(0) Left-pad numerical values with zeros
|
|
||||||
(-) Align left by adding space on the right, dropping zeros */
|
|
||||||
uint8_t alignment;
|
|
||||||
|
|
||||||
} GPACKED(2);
|
|
||||||
|
|
||||||
typedef void (*kprint_formatter_t)(KFORMAT_ARGS);
|
|
||||||
|
|
||||||
/* Default formatters */
|
/* Default formatters */
|
||||||
static void kformat_char (KFORMAT_ARGS);
|
static void kformat_char (KFORMAT_ARGS);
|
||||||
static void kformat_int (KFORMAT_ARGS);
|
static void kformat_int (KFORMAT_ARGS);
|
||||||
|
@ -99,6 +63,20 @@ kprint_formatter_t kprint_formatters[26] = {
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* kprint_register(): Register a formatter */
|
||||||
|
void kprint_register(int spec, kprint_formatter_t kformat)
|
||||||
|
{
|
||||||
|
spec |= 0x20;
|
||||||
|
int i = (spec | 0x20) - 'a';
|
||||||
|
|
||||||
|
/* Non-letters */
|
||||||
|
if(i < 0 || i >= 26) return;
|
||||||
|
/* Size-specifying letters */
|
||||||
|
if(spec == 'h' || spec == 'l' || spec == 'z') return;
|
||||||
|
|
||||||
|
kprint_formatters[i] = kformat;
|
||||||
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Output functions
|
// Output functions
|
||||||
//---
|
//---
|
||||||
|
@ -144,10 +122,10 @@ GINLINE static void kprint_outn(int byte, size_t n)
|
||||||
//---
|
//---
|
||||||
|
|
||||||
/* kprint_opt(): Parse option strings */
|
/* kprint_opt(): Parse option strings */
|
||||||
struct kprint_options kprint_opt(char const **options_ptr)
|
kprint_options_t kprint_opt(char const **options_ptr)
|
||||||
{
|
{
|
||||||
/* No options enabled by default, set the size to int */
|
/* No options enabled by default, set the size to int */
|
||||||
struct kprint_options opt = { .size = 2 };
|
kprint_options_t opt = { .size = 2 };
|
||||||
|
|
||||||
/* This function acts as a deterministic finite automaton */
|
/* This function acts as a deterministic finite automaton */
|
||||||
enum {
|
enum {
|
||||||
|
@ -195,6 +173,7 @@ struct kprint_options kprint_opt(char const **options_ptr)
|
||||||
/* Data size */
|
/* Data size */
|
||||||
if(c == 'h') opt.size--;
|
if(c == 'h') opt.size--;
|
||||||
if(c == 'l') opt.size++;
|
if(c == 'l') opt.size++;
|
||||||
|
if(c == 'z') opt.size = 3;
|
||||||
|
|
||||||
if(c >= '1' && c <= '9') state = length, options--;
|
if(c >= '1' && c <= '9') state = length, options--;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +190,7 @@ struct kprint_options kprint_opt(char const **options_ptr)
|
||||||
void kprint(char const *format, va_list *args)
|
void kprint(char const *format, va_list *args)
|
||||||
{
|
{
|
||||||
int c, spec;
|
int c, spec;
|
||||||
struct kprint_options opt;
|
kprint_options_t opt;
|
||||||
|
|
||||||
while((c = *format++))
|
while((c = *format++))
|
||||||
{
|
{
|
||||||
|
@ -262,37 +241,11 @@ size_t kvsprint(char *output, size_t length, char const *format, va_list *args)
|
||||||
// Formatter helpers
|
// Formatter helpers
|
||||||
//---
|
//---
|
||||||
|
|
||||||
/* struct geometry: General geometry for a format */
|
/* kformat_geometry(): Calculate the geometry of a format */
|
||||||
struct geometry
|
void kformat_geometry(kprint_options_t *opt, kprint_geometry_t *g)
|
||||||
{
|
{
|
||||||
uint16_t left_spaces; /* Spaces before content */
|
int integral = (g->style == KPRINT_INTEGER);
|
||||||
uint8_t sign; /* Sign character (NUL, ' ', '+' or '-') */
|
int numerical = (g->style == KPRINT_NUMERICAL) || integral;
|
||||||
uint8_t prefix; /* Base prefix ('0', '0x', etc) length */
|
|
||||||
uint16_t zeros; /* For numerical displays, number of zeros */
|
|
||||||
uint16_t content; /* Content length in bytes */
|
|
||||||
uint16_t right_spaces; /* Spaces after content */
|
|
||||||
|
|
||||||
} GPACKED(2);
|
|
||||||
|
|
||||||
/* kformat_geometry(): Calculate the geometry of a format
|
|
||||||
|
|
||||||
The caller must provide the [prefix] and [content] lengths in the geometry
|
|
||||||
structure. Additionally, a sign must be indicated: either '+' if the
|
|
||||||
formatted value is nonnegative, or '-' otherwise. The sign might be updated
|
|
||||||
by this function, but not the other two fields.
|
|
||||||
|
|
||||||
This function is not *really* isolated from the standard kformat functions
|
|
||||||
(as would a precise API be), because the meaning of each options and the
|
|
||||||
process of resolving them varies so much. */
|
|
||||||
static void kformat_geometry(int spec, struct kprint_options *opt,
|
|
||||||
struct geometry *g)
|
|
||||||
{
|
|
||||||
/* Determining whether we are in numerical. The blacklist approach
|
|
||||||
allows custom specifiers which call this function to enable zeros if
|
|
||||||
they like (they can disable them by un-setting opt->alignment if
|
|
||||||
it's '0' in any case) */
|
|
||||||
int numerical = (spec != 'c' && spec != 'p' && spec != 's');
|
|
||||||
|
|
||||||
ssize_t padding;
|
ssize_t padding;
|
||||||
|
|
||||||
/* Sign character (no discussion required for negative values) */
|
/* Sign character (no discussion required for negative values) */
|
||||||
|
@ -305,12 +258,12 @@ static void kformat_geometry(int spec, struct kprint_options *opt,
|
||||||
|
|
||||||
g->zeros = 0;
|
g->zeros = 0;
|
||||||
|
|
||||||
padding = opt->length - !!g->sign - g->prefix
|
padding = opt->length - (g->sign != 0) - g->prefix
|
||||||
- max(g->content, opt->precision);
|
- max(g->content, opt->precision);
|
||||||
if(padding < 0) padding = 0;
|
if(padding < 0) padding = 0;
|
||||||
|
|
||||||
/* In numerical modes, precision forces zeros */
|
/* In integral modes, precision forces zeros */
|
||||||
if(numerical && opt->precision)
|
if(integral && opt->precision)
|
||||||
{
|
{
|
||||||
if(opt->alignment == '0') opt->alignment = 0;
|
if(opt->alignment == '0') opt->alignment = 0;
|
||||||
|
|
||||||
|
@ -384,7 +337,7 @@ static int digits_8(char *str, uint64_t n)
|
||||||
|
|
||||||
static int64_t load_i(int size, va_list *args)
|
static int64_t load_i(int size, va_list *args)
|
||||||
{
|
{
|
||||||
/* All smaller types are promoted to int wth sign extension, so we
|
/* All smaller types are promoted to int with sign extension, so we
|
||||||
don't need to care about them. */
|
don't need to care about them. */
|
||||||
if(size == 3) return va_arg(*args, long);
|
if(size == 3) return va_arg(*args, long);
|
||||||
if(size == 4) return va_arg(*args, long long);
|
if(size == 4) return va_arg(*args, long long);
|
||||||
|
@ -410,10 +363,10 @@ static void kformat_char(KFORMAT_ARGS)
|
||||||
{
|
{
|
||||||
int c = va_arg(*args, int);
|
int c = va_arg(*args, int);
|
||||||
|
|
||||||
struct geometry g = {
|
kprint_geometry_t g = {
|
||||||
.prefix = 0, .sign = 0, .content = 1,
|
.prefix = 0, .sign = 0, .content = 1,
|
||||||
};
|
};
|
||||||
kformat_geometry(spec, opt, &g);
|
kformat_geometry(opt, &g);
|
||||||
|
|
||||||
kprint_outn(' ', g.left_spaces);
|
kprint_outn(' ', g.left_spaces);
|
||||||
kprint_out(c);
|
kprint_out(c);
|
||||||
|
@ -434,10 +387,10 @@ static void kformat_str(KFORMAT_ARGS)
|
||||||
uint32_t precision = opt->precision ? opt->precision : (-1);
|
uint32_t precision = opt->precision ? opt->precision : (-1);
|
||||||
while(s[len] && len < precision) len++;
|
while(s[len] && len < precision) len++;
|
||||||
|
|
||||||
struct geometry g = {
|
kprint_geometry_t g = {
|
||||||
.prefix = 0, .sign = 0, .content = len,
|
.prefix = 0, .sign = 0, .content = len,
|
||||||
};
|
};
|
||||||
kformat_geometry(spec, opt, &g);
|
kformat_geometry(opt, &g);
|
||||||
|
|
||||||
kprint_outn(' ', g.left_spaces);
|
kprint_outn(' ', g.left_spaces);
|
||||||
for(size_t i = 0; i < len; i++) kprint_out(s[i]);
|
for(size_t i = 0; i < len; i++) kprint_out(s[i]);
|
||||||
|
@ -456,9 +409,10 @@ static void kformat_int(KFORMAT_ARGS)
|
||||||
int64_t n = load_i(opt->size, args);
|
int64_t n = load_i(opt->size, args);
|
||||||
|
|
||||||
/* Compute the sign and the absolute value */
|
/* Compute the sign and the absolute value */
|
||||||
struct geometry g = {
|
kprint_geometry_t g = {
|
||||||
.sign = (n < 0) ? '-' : '+',
|
.sign = (n < 0) ? '-' : '+',
|
||||||
.prefix = 0,
|
.prefix = 0,
|
||||||
|
.style = KPRINT_INTEGER,
|
||||||
};
|
};
|
||||||
if(n < 0) n = -n;
|
if(n < 0) n = -n;
|
||||||
|
|
||||||
|
@ -470,7 +424,7 @@ static void kformat_int(KFORMAT_ARGS)
|
||||||
total = max(pure, opt->precision);
|
total = max(pure, opt->precision);
|
||||||
g.content = total;
|
g.content = total;
|
||||||
|
|
||||||
kformat_geometry(spec, opt, &g);
|
kformat_geometry(opt, &g);
|
||||||
|
|
||||||
/* Print the result */
|
/* Print the result */
|
||||||
kprint_outn(' ', g.left_spaces);
|
kprint_outn(' ', g.left_spaces);
|
||||||
|
@ -507,10 +461,11 @@ static void kformat_uint(KFORMAT_ARGS)
|
||||||
size_t prefix = 0;
|
size_t prefix = 0;
|
||||||
if(opt->alternative) prefix = (specl != 'u') + (specl == 'x');
|
if(opt->alternative) prefix = (specl != 'u') + (specl == 'x');
|
||||||
|
|
||||||
struct geometry g = {
|
kprint_geometry_t g = {
|
||||||
.sign = 0, .prefix = prefix, .content = total
|
.sign = 0, .prefix = prefix, .content = total,
|
||||||
|
.style = KPRINT_INTEGER,
|
||||||
};
|
};
|
||||||
kformat_geometry(spec, opt, &g);
|
kformat_geometry(opt, &g);
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
kprint_outn(' ', g.left_spaces);
|
kprint_outn(' ', g.left_spaces);
|
||||||
|
@ -551,9 +506,10 @@ static void kformat_fixed(KFORMAT_ARGS)
|
||||||
int64_t n = load_i(opt->size, args);
|
int64_t n = load_i(opt->size, args);
|
||||||
|
|
||||||
/* Compute the sign and the absolute value */
|
/* Compute the sign and the absolute value */
|
||||||
struct geometry g = {
|
kprint_geometry_t g = {
|
||||||
.sign = (n < 0) ? '-' : '+',
|
.sign = (n < 0) ? '-' : '+',
|
||||||
.prefix = 0,
|
.prefix = 0,
|
||||||
|
.style = KPRINT_NUMERICAL,
|
||||||
};
|
};
|
||||||
if(n < 0) n = -n;
|
if(n < 0) n = -n;
|
||||||
|
|
||||||
|
@ -561,7 +517,7 @@ static void kformat_fixed(KFORMAT_ARGS)
|
||||||
char digits[32];
|
char digits[32];
|
||||||
|
|
||||||
g.content = digits_10(digits, n) + 1;
|
g.content = digits_10(digits, n) + 1;
|
||||||
kformat_geometry(spec, opt, &g);
|
kformat_geometry(opt, &g);
|
||||||
|
|
||||||
/* Print the result */
|
/* Print the result */
|
||||||
kprint_outn(' ', g.left_spaces);
|
kprint_outn(' ', g.left_spaces);
|
||||||
|
@ -576,43 +532,3 @@ static void kformat_fixed(KFORMAT_ARGS)
|
||||||
|
|
||||||
kprint_outn(' ', g.right_spaces);
|
kprint_outn(' ', g.right_spaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
|
||||||
// Standard formatted printing functions
|
|
||||||
//---
|
|
||||||
|
|
||||||
/* sprintf() */
|
|
||||||
GWEAK int sprintf(char *str, char const *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
|
|
||||||
int count = kvsprint(str, 65536, format, &args);
|
|
||||||
|
|
||||||
va_end(args);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vsprintf() */
|
|
||||||
GWEAK int vsprintf(char *str, char const *format, va_list args)
|
|
||||||
{
|
|
||||||
return kvsprint(str, 65536, format, &args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* snprintf() */
|
|
||||||
GWEAK int snprintf(char *str, size_t n, char const *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
|
|
||||||
int count = kvsprint(str, n, format, &args);
|
|
||||||
|
|
||||||
va_end(args);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vsprintf() */
|
|
||||||
GWEAK int vsnprintf(char *str, size_t n, char const *format, va_list args)
|
|
||||||
{
|
|
||||||
return kvsprint(str, n, format, &args);
|
|
||||||
}
|
|
43
src/std/print.c
Normal file
43
src/std/print.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
//---
|
||||||
|
// gint:src:print - Standard formatted printing functions
|
||||||
|
//---
|
||||||
|
|
||||||
|
#include <gint/std/stdio.h>
|
||||||
|
#include <gint/kprint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/* sprintf() */
|
||||||
|
GWEAK int sprintf(char *str, char const *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
int count = kvsprint(str, 65536, format, &args);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vsprintf() */
|
||||||
|
GWEAK int vsprintf(char *str, char const *format, va_list args)
|
||||||
|
{
|
||||||
|
return kvsprint(str, 65536, format, &args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* snprintf() */
|
||||||
|
GWEAK int snprintf(char *str, size_t n, char const *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
int count = kvsprint(str, n, format, &args);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vsprintf() */
|
||||||
|
GWEAK int vsnprintf(char *str, size_t n, char const *format, va_list args)
|
||||||
|
{
|
||||||
|
return kvsprint(str, n, format, &args);
|
||||||
|
}
|
Loading…
Reference in a new issue