va_list fixed; printing 0 value fixed
This commit is contained in:
parent
877b6fc017
commit
a4ff669e7b
83
embformat.c
83
embformat.c
@ -14,34 +14,21 @@
|
|||||||
|
|
||||||
// format length ((nothing),l)
|
// format length ((nothing),l)
|
||||||
typedef enum {
|
typedef enum {
|
||||||
LEN_NORMAL,
|
LEN_NORMAL, LEN_LONG
|
||||||
LEN_LONG
|
|
||||||
} FmtLength;
|
} FmtLength;
|
||||||
|
|
||||||
// format flags ((nothing),0)
|
// format flags ((nothing),0)
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FLAG_NO = 0,
|
FLAG_NO = 0, FLAG_LEADING_ZEROS = 1, FLAG_LEADING_SPACES = 2, FLAG_PREPEND_PLUS_SIGN = 4
|
||||||
FLAG_LEADING_ZEROS = 1,
|
|
||||||
FLAG_LEADING_SPACES = 2,
|
|
||||||
FLAG_PREPEND_PLUS_SIGN = 4
|
|
||||||
} FmtFlags;
|
} FmtFlags;
|
||||||
|
|
||||||
// format type
|
// format type
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UNKNOWN = -1,
|
UNKNOWN = -1, LITERAL_PERCENT, SIGNED_INTEGER, UNSIGNED_INTEGER, DOUBLE, DOUBLE_EXPONENTIAL, UNSIGNED_HEXADECIMAL_INT, UNSIGNED_HEXADECIMAL_INT_UPPERCASE, STRING, CHARACTER
|
||||||
LITERAL_PERCENT,
|
|
||||||
SIGNED_INTEGER,
|
|
||||||
UNSIGNED_INTEGER,
|
|
||||||
DOUBLE,
|
|
||||||
DOUBLE_EXPONENTIAL,
|
|
||||||
UNSIGNED_HEXADECIMAL_INT,
|
|
||||||
UNSIGNED_HEXADECIMAL_INT_UPPERCASE,
|
|
||||||
STRING,
|
|
||||||
CHARACTER
|
|
||||||
} FmtType;
|
} FmtType;
|
||||||
|
|
||||||
struct _FmtWord;
|
struct _FmtWord;
|
||||||
typedef int (*printfn)(va_list va, struct _FmtWord *fmt, char *outbuf, size_t free_space);
|
typedef int (*printfn)(va_list *va, struct _FmtWord *fmt, char *outbuf, size_t free_space);
|
||||||
|
|
||||||
// pair of type and designator character
|
// pair of type and designator character
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -140,10 +127,10 @@ static int scientific_form_exponent(uint64_t l, unsigned int base, uint64_t *gnt
|
|||||||
if (*gntpd > 1) {
|
if (*gntpd > 1) {
|
||||||
(*gntpd) /= base;
|
(*gntpd) /= base;
|
||||||
}
|
}
|
||||||
return e;
|
return MAX(e, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pfn_literal_percent(va_list va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
static int pfn_literal_percent(va_list *va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
||||||
if (free_space >= 1) {
|
if (free_space >= 1) {
|
||||||
outbuf[0] = '%';
|
outbuf[0] = '%';
|
||||||
outbuf[1] = '\0';
|
outbuf[1] = '\0';
|
||||||
@ -219,15 +206,15 @@ static int print_number(uint64_t u, bool negative, FmtWord *fmt, char *outbuf, s
|
|||||||
return copy_len;
|
return copy_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pfn_integer(va_list va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
static int pfn_integer(va_list *va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
||||||
uint64_t u = 0;
|
uint64_t u = 0;
|
||||||
bool negative = false;
|
bool negative = false;
|
||||||
if (fmt->type == SIGNED_INTEGER) { // for signed integers
|
if (fmt->type == SIGNED_INTEGER) { // for signed integers
|
||||||
int64_t si;
|
int64_t si;
|
||||||
if (fmt->length == LEN_NORMAL) { // ...without length specifiers
|
if (fmt->length == LEN_NORMAL) { // ...without length specifiers
|
||||||
si = va_arg(va, int);
|
si = va_arg((*va), int);
|
||||||
} else { // ...with length specifiers
|
} else { // ...with length specifiers
|
||||||
si = va_arg(va, int64_t);
|
si = va_arg((*va), int64_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// absolute value
|
// absolute value
|
||||||
@ -239,10 +226,10 @@ static int pfn_integer(va_list va, FmtWord *fmt, char *outbuf, size_t free_space
|
|||||||
}
|
}
|
||||||
} else if (fmt->type == UNSIGNED_INTEGER || fmt->type == UNSIGNED_HEXADECIMAL_INT || fmt->type == UNSIGNED_HEXADECIMAL_INT_UPPERCASE) { // for UNsigned integers
|
} else if (fmt->type == UNSIGNED_INTEGER || fmt->type == UNSIGNED_HEXADECIMAL_INT || fmt->type == UNSIGNED_HEXADECIMAL_INT_UPPERCASE) { // for UNsigned integers
|
||||||
if (fmt->length == LEN_NORMAL) { // ...without length specifiers
|
if (fmt->length == LEN_NORMAL) { // ...without length specifiers
|
||||||
unsigned int d = va_arg(va, unsigned int);
|
unsigned int d = va_arg((*va), unsigned int);
|
||||||
u = d;
|
u = d;
|
||||||
} else { // ...with length specifiers
|
} else { // ...with length specifiers
|
||||||
u = va_arg(va, uint64_t);
|
u = va_arg((*va), uint64_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,9 +240,9 @@ static int pfn_integer(va_list va, FmtWord *fmt, char *outbuf, size_t free_space
|
|||||||
|
|
||||||
#define DECIMAL_POINT ('.')
|
#define DECIMAL_POINT ('.')
|
||||||
|
|
||||||
static int pfn_double(va_list va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
static int pfn_double(va_list *va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
||||||
// get passed double variable
|
// get passed double variable
|
||||||
double d = va_arg(va, double);
|
double d = va_arg((*va), double);
|
||||||
bool negative = d < 0;
|
bool negative = d < 0;
|
||||||
if (negative) {
|
if (negative) {
|
||||||
d *= -1;
|
d *= -1;
|
||||||
@ -272,13 +259,8 @@ static int pfn_double(va_list va, FmtWord *fmt, char *outbuf, size_t free_space)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// formatting of the integer part
|
// formatting of the integer part
|
||||||
FmtWord int_fmt = {
|
FmtWord int_fmt = { .flags = fmt->flags, .type = UNSIGNED_INTEGER, .width = fmt->width };
|
||||||
.flags = fmt->flags,
|
|
||||||
.type = UNSIGNED_INTEGER,
|
|
||||||
.width = fmt->width
|
|
||||||
};
|
|
||||||
|
|
||||||
// separate into integer and fractional part
|
// separate into integer and fractional part
|
||||||
uint64_t int_part = (uint64_t) d; // integer part
|
uint64_t int_part = (uint64_t) d; // integer part
|
||||||
@ -299,11 +281,7 @@ static int pfn_double(va_list va, FmtWord *fmt, char *outbuf, size_t free_space)
|
|||||||
*outbuf = '\0';
|
*outbuf = '\0';
|
||||||
|
|
||||||
// prepare format for
|
// prepare format for
|
||||||
FmtWord frac_fmt = {
|
FmtWord frac_fmt = { .flags = FLAG_NO, .width = -1, .type = UNSIGNED_INTEGER };
|
||||||
.flags = FLAG_NO,
|
|
||||||
.width = -1,
|
|
||||||
.type = UNSIGNED_INTEGER
|
|
||||||
};
|
|
||||||
|
|
||||||
// extract fractional part as integer
|
// extract fractional part as integer
|
||||||
double d_frac = d - (double) int_part;
|
double d_frac = d - (double) int_part;
|
||||||
@ -328,11 +306,7 @@ static int pfn_double(va_list va, FmtWord *fmt, char *outbuf, size_t free_space)
|
|||||||
sum_copy_len++;
|
sum_copy_len++;
|
||||||
|
|
||||||
// print value of exponent
|
// print value of exponent
|
||||||
FmtWord exponent_fmt = {
|
FmtWord exponent_fmt = { .flags = FLAG_PREPEND_PLUS_SIGN | FLAG_LEADING_ZEROS, .width = 2, .type = UNSIGNED_INTEGER };
|
||||||
.flags = FLAG_PREPEND_PLUS_SIGN | FLAG_LEADING_ZEROS,
|
|
||||||
.width = 2,
|
|
||||||
.type = UNSIGNED_INTEGER
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned int exponent_abs = exponent > 0 ? exponent : -exponent;
|
unsigned int exponent_abs = exponent > 0 ? exponent : -exponent;
|
||||||
|
|
||||||
@ -346,8 +320,8 @@ static int pfn_double(va_list va, FmtWord *fmt, char *outbuf, size_t free_space)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print character
|
// print character
|
||||||
static int pfn_char(va_list va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
static int pfn_char(va_list *va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
||||||
int c = va_arg(va, int);
|
int c = va_arg((*va), int);
|
||||||
if (free_space >= 1) {
|
if (free_space >= 1) {
|
||||||
outbuf[0] = (char) c;
|
outbuf[0] = (char) c;
|
||||||
outbuf[1] = '\0';
|
outbuf[1] = '\0';
|
||||||
@ -356,24 +330,15 @@ static int pfn_char(va_list va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print string
|
// print string
|
||||||
static int pfn_string(va_list va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
static int pfn_string(va_list *va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
||||||
char *str = va_arg(va, char *);
|
char *str = va_arg((*va), char*);
|
||||||
return string_copy(outbuf, str, free_space);
|
return string_copy(outbuf, str, free_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
// format swting assignment table
|
// format swting assignment table
|
||||||
static FmtTypeDesignatorPair sTypeDesAssignment[] = {
|
static FmtTypeDesignatorPair sTypeDesAssignment[] = { { '%', LITERAL_PERCENT, pfn_literal_percent }, { 'd', SIGNED_INTEGER, pfn_integer }, { 'i', SIGNED_INTEGER, pfn_integer }, { 'u',
|
||||||
{'%', LITERAL_PERCENT, pfn_literal_percent},
|
UNSIGNED_INTEGER, pfn_integer }, { 'f', DOUBLE, pfn_double }, { 'e', DOUBLE_EXPONENTIAL, pfn_double }, { 'x', UNSIGNED_HEXADECIMAL_INT, pfn_integer }, { 'X',
|
||||||
{'d', SIGNED_INTEGER, pfn_integer},
|
UNSIGNED_HEXADECIMAL_INT_UPPERCASE, pfn_integer }, { 's', STRING, pfn_string }, { 'c', CHARACTER, pfn_char }, { '\0', UNKNOWN } // termination
|
||||||
{'i', SIGNED_INTEGER, pfn_integer},
|
|
||||||
{'u', UNSIGNED_INTEGER, pfn_integer},
|
|
||||||
{'f', DOUBLE, pfn_double},
|
|
||||||
{'e', DOUBLE_EXPONENTIAL, pfn_double},
|
|
||||||
{'x', UNSIGNED_HEXADECIMAL_INT, pfn_integer},
|
|
||||||
{'X', UNSIGNED_HEXADECIMAL_INT_UPPERCASE, pfn_integer},
|
|
||||||
{'s', STRING, pfn_string},
|
|
||||||
{'c', CHARACTER, pfn_char},
|
|
||||||
{'\0', UNKNOWN} // termination
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
@ -580,7 +545,7 @@ unsigned long int vembfmt(char *str, unsigned long int len, char *format, va_lis
|
|||||||
int rewind;
|
int rewind;
|
||||||
process_format_word(word_str, &word, &rewind);
|
process_format_word(word_str, &word, &rewind);
|
||||||
if (word.type != UNKNOWN) {
|
if (word.type != UNKNOWN) {
|
||||||
int copy_len = word.pTypeDes->fn(args, &word, str, free_space); // variable with the same name!
|
int copy_len = word.pTypeDes->fn(&args, &word, str, free_space); // variable with the same name!
|
||||||
free_space -= copy_len;
|
free_space -= copy_len;
|
||||||
str += copy_len;
|
str += copy_len;
|
||||||
sum_copy_len += copy_len;
|
sum_copy_len += copy_len;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user