mirror of
https://git.stationery.faith/corn/corn.git
synced 2024-11-24 09:12:18 +00:00
rework kprintf
This commit is contained in:
parent
ac431b0050
commit
f785bce3cc
3 changed files with 439 additions and 285 deletions
|
@ -633,7 +633,6 @@ int kload_page(void *virt_addr) {
|
|||
if (page->loaded)
|
||||
return -1;
|
||||
void *phys = alloc_phys_page();
|
||||
kprintf("0x%p\n", phys);
|
||||
if (phys == NULL)
|
||||
return -2;
|
||||
page->loaded = 1;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <backtrace.h>
|
||||
#include <fpu.h>
|
||||
#include <acpi.h>
|
||||
#include <memory.h>
|
||||
|
@ -18,6 +19,8 @@ void kmain(struct boot_info *info) {
|
|||
char *test = kalloc(5);
|
||||
*test = 1;
|
||||
|
||||
//log_backtrace();
|
||||
|
||||
while (1) {
|
||||
screen_redraw();
|
||||
// loop so we dont halt
|
||||
|
|
720
src/print.c
720
src/print.c
|
@ -1,6 +1,7 @@
|
|||
#include <lib.h>
|
||||
#include <serial.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void kputc(char c) {
|
||||
serial_out(c);
|
||||
|
@ -31,54 +32,110 @@ struct format_precision {
|
|||
};
|
||||
|
||||
enum format_modifier {
|
||||
MOD_NONE,
|
||||
MOD_INVALID,
|
||||
MOD_HALF_HALF,
|
||||
MOD_HALF,
|
||||
MOD_LONG_LONG,
|
||||
MOD_LONG,
|
||||
MOD_NONE = 0,
|
||||
MOD_HALF = 1,
|
||||
MOD_HALF_HALF = 3,
|
||||
MOD_LONG = 3,
|
||||
MOD_LONG_LONG = 4,
|
||||
MOD_INVALID = 5,
|
||||
};
|
||||
|
||||
enum format_conversion {
|
||||
FMT_INT,
|
||||
FMT_UINT,
|
||||
// decimal numbers
|
||||
FMT_CHAR = 0,
|
||||
FMT_INT = 4,
|
||||
FMT_UINT = 5,
|
||||
// otehr numbers
|
||||
FMT_OCT,
|
||||
FMT_HEX,
|
||||
FMT_HEX_UPPER,
|
||||
FMT_CHAR,
|
||||
// text
|
||||
FMT_STR,
|
||||
FMT_PTR,
|
||||
FMT_PTR_UPPER,
|
||||
FMT_PERCENT,
|
||||
// misc
|
||||
FMT_INVALID
|
||||
};
|
||||
|
||||
static enum format_flag read_flag(const char *format, const char **end) {
|
||||
enum format_length {
|
||||
LEN_UCHAR,
|
||||
LEN_CHAR,
|
||||
LEN_USHORT,
|
||||
LEN_SHORT,
|
||||
LEN_UINT,
|
||||
LEN_INT,
|
||||
LEN_ULONG,
|
||||
LEN_LONG,
|
||||
LEN_ULONGLONG,
|
||||
LEN_LONGLONG,
|
||||
LEN_SIZET,
|
||||
LEN_INVALID
|
||||
};
|
||||
|
||||
enum format_flag flag = FLG_NONE;
|
||||
struct spacing {
|
||||
unsigned left;
|
||||
unsigned length;
|
||||
unsigned right;
|
||||
bool zero;
|
||||
};
|
||||
|
||||
enum charcase {
|
||||
UPPERCASE,
|
||||
LOWERCASE
|
||||
};
|
||||
|
||||
enum printtype {
|
||||
NONE,
|
||||
OCTAL,
|
||||
HEX
|
||||
};
|
||||
|
||||
static enum printtype conversion_to_printtype(enum format_conversion conversion) {
|
||||
switch (conversion) {
|
||||
case FMT_OCT:
|
||||
return OCTAL;
|
||||
case FMT_HEX:
|
||||
case FMT_HEX_UPPER:
|
||||
return HEX;
|
||||
default:
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static enum charcase conversion_to_charcase(enum format_conversion conversion) {
|
||||
switch (conversion) {
|
||||
case FMT_HEX_UPPER:
|
||||
return UPPERCASE;
|
||||
default:
|
||||
return LOWERCASE;
|
||||
}
|
||||
}
|
||||
|
||||
static enum format_flag read_flags(const char *format, const char **end) {
|
||||
|
||||
enum format_flag flags = FLG_NONE;
|
||||
|
||||
for (; *format != '\0'; format++) {
|
||||
switch (*format) {
|
||||
case '#':
|
||||
flag |= FLG_ALTERNATE;
|
||||
flags |= FLG_ALTERNATE;
|
||||
break;
|
||||
case '0':
|
||||
flag |= FLG_ZERO;
|
||||
flags |= FLG_ZERO;
|
||||
break;
|
||||
case '-':
|
||||
flag |= FLG_LEFT_ALIGN;
|
||||
flags |= FLG_LEFT_ALIGN;
|
||||
break;
|
||||
case '+':
|
||||
flag |= FLG_ADD_SIGN;
|
||||
flags |= FLG_ADD_SIGN;
|
||||
break;
|
||||
default:
|
||||
*end = format;
|
||||
return flag;
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
|
||||
*end = format;
|
||||
return flag;
|
||||
return flags;
|
||||
}
|
||||
|
||||
static struct format_width read_width(const char *format, const char **end) {
|
||||
|
@ -221,213 +278,344 @@ static enum format_conversion read_conversion(const char *format, const char **e
|
|||
return FMT_STR;
|
||||
case 'p':
|
||||
return FMT_PTR;
|
||||
case 'P':
|
||||
return FMT_PTR_UPPER;
|
||||
case '%':
|
||||
return FMT_PERCENT;
|
||||
default:
|
||||
return FMT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_string(
|
||||
const char *str,
|
||||
enum format_flag flag,
|
||||
struct format_width width,
|
||||
struct format_precision precision
|
||||
) {
|
||||
|
||||
size_t max_len = 0;
|
||||
size_t min_len = 0;
|
||||
size_t len = 0;
|
||||
|
||||
if (width.defined)
|
||||
min_len = width.value;
|
||||
|
||||
if (precision.defined) {
|
||||
max_len = precision.value;
|
||||
len = max_len;
|
||||
if (max_len < min_len)
|
||||
min_len = max_len;
|
||||
} else {
|
||||
len = strlen(str);
|
||||
}
|
||||
|
||||
if (!(flag & FLG_LEFT_ALIGN) && len < min_len) {
|
||||
for (size_t i = 0; i < (min_len - len); i++) {
|
||||
kputc(' ');
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
kputc(str[i]);
|
||||
}
|
||||
|
||||
if ((flag & FLG_LEFT_ALIGN) && len < min_len) {
|
||||
for (size_t i = 0; i < (min_len - len); i++) {
|
||||
kputc(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char get_letter(
|
||||
char c,
|
||||
char base
|
||||
static char ctoa_print(
|
||||
char c, // the single digit to convert to ascii
|
||||
enum charcase cc // if this digit should be uppercase or lowercase
|
||||
) {
|
||||
char ascii_base = cc == UPPERCASE ? 'A' : 'a';
|
||||
if (c >= 0 && c <= 9)
|
||||
return c + '0';
|
||||
c -= 10;
|
||||
return c + base;
|
||||
return c + ascii_base;
|
||||
}
|
||||
|
||||
static char *get_decimal(
|
||||
long long num,
|
||||
char *buf,
|
||||
char sign,
|
||||
int radix,
|
||||
char base
|
||||
static char *ulltoa_print(
|
||||
unsigned long long num, // the number to convert to ascii
|
||||
unsigned radix, // the divisor for the number (base 10, octal, hex)
|
||||
char *buf, // the buffer to write to
|
||||
enum charcase cc, // if any a-z ascii should be uppercase or lowercase
|
||||
bool addsign // add a sign even if its positive
|
||||
) {
|
||||
|
||||
// we are printing the string backwards, add null byte
|
||||
*buf = '\0';
|
||||
buf--;
|
||||
|
||||
// if the number is zero, the while loop will never run
|
||||
// so we have to add the zero digit ourselves
|
||||
if (num == 0) {
|
||||
*buf = '0';
|
||||
buf--;
|
||||
}
|
||||
|
||||
// for each digit, convert to ascii and add to buffer
|
||||
while (num != 0) {
|
||||
char i = num % radix;
|
||||
char c = get_letter(i, base);
|
||||
char c = ctoa_print(i, cc);
|
||||
*buf = c;
|
||||
buf--;
|
||||
num /= radix;
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
*buf = sign;
|
||||
// since this is the unsigned function, add a plus sign if
|
||||
// requested
|
||||
if (addsign) {
|
||||
*buf = '+';
|
||||
buf--;
|
||||
}
|
||||
|
||||
buf++;
|
||||
buf++; // move forward one to be at the start of the string
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void print_unum(
|
||||
unsigned long long num,
|
||||
enum format_flag flag,
|
||||
struct format_width width,
|
||||
struct format_precision precision,
|
||||
bool isneg,
|
||||
int radix,
|
||||
char base
|
||||
static char *lltoa_print(
|
||||
signed long long num, // the number to convert to ascii
|
||||
unsigned radix, // the divistor for the number (base 10, octal, hex)
|
||||
char *buf, // the buffer to write to
|
||||
enum charcase cc, // if any a-z ascii should be uppercase or lowercase
|
||||
bool addsign // add a sign even if its positive
|
||||
) {
|
||||
bool isneg = num < 0;
|
||||
|
||||
size_t max_len = 0;
|
||||
size_t min_len = 0;
|
||||
size_t len = 0;
|
||||
|
||||
char sign = 0;
|
||||
if (isneg)
|
||||
sign = '-';
|
||||
else if (flag & FLG_ADD_SIGN)
|
||||
sign = '+';
|
||||
num = -num;
|
||||
|
||||
char buf[1024];
|
||||
char *str = get_decimal(
|
||||
num,
|
||||
buf + 1023,
|
||||
sign,
|
||||
radix,
|
||||
base
|
||||
);
|
||||
buf = ulltoa_print(num, radix, buf, cc, !isneg && addsign);
|
||||
|
||||
bool space_pre = (flag & FLG_LEFT_ALIGN) || !(flag & FLG_ZERO);
|
||||
|
||||
if (!space_pre && radix == 16 && (flag & FLG_ALTERNATE)) {
|
||||
char x = base + ('x' - 'a');
|
||||
serial_out('0');
|
||||
serial_out(x);
|
||||
if (isneg && num < 0) {
|
||||
buf--;
|
||||
*buf = '-';
|
||||
}
|
||||
|
||||
if (width.defined)
|
||||
min_len = width.value;
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (precision.defined) {
|
||||
max_len = precision.value;
|
||||
len = max_len;
|
||||
if (max_len < min_len)
|
||||
min_len = max_len;
|
||||
} else {
|
||||
len = strlen(str);
|
||||
|
||||
static void print_string_buffer(
|
||||
const char *buf, // buffer containing the text we want to print
|
||||
struct spacing spacing // the spacing on the left right and middle
|
||||
) {
|
||||
for (unsigned i = 0; i < spacing.left; i++) {
|
||||
kputc(' ');
|
||||
}
|
||||
|
||||
bool zero_padded = false;
|
||||
|
||||
if (!(flag & FLG_LEFT_ALIGN) && len < min_len) {
|
||||
for (size_t i = 0; i < (min_len - len); i++) {
|
||||
(flag & FLG_ZERO) ? kputc('0') : kputc(' ');
|
||||
}
|
||||
if (flag & FLG_ZERO)
|
||||
zero_padded = true;
|
||||
for (unsigned i = 0; i < spacing.length; i++) {
|
||||
kputc(*buf++);
|
||||
}
|
||||
|
||||
if (space_pre && radix == 16 && (flag & FLG_ALTERNATE)) {
|
||||
char x = base + ('x' - 'a');
|
||||
serial_out('0');
|
||||
serial_out(x);
|
||||
}
|
||||
|
||||
if (space_pre && radix == 16 && flag & FLG_ALTERNATE) {
|
||||
char x = base + ('x' - 'a');
|
||||
serial_out('0');
|
||||
serial_out(x);
|
||||
}
|
||||
|
||||
kputs(str);
|
||||
|
||||
if (!zero_padded && (flag & FLG_ALTERNATE) && radix == 8)
|
||||
kputc('0');
|
||||
|
||||
if ((flag & FLG_LEFT_ALIGN) && len < min_len) {
|
||||
for (size_t i = 0; i < (min_len - len); i++) {
|
||||
(flag & FLG_ZERO) ? kputc('0') : kputc(' ');
|
||||
}
|
||||
for (unsigned i = 0; i < spacing.right; i++) {
|
||||
kputc(' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void print_num(
|
||||
long long num,
|
||||
enum format_flag flag,
|
||||
struct format_width width,
|
||||
struct format_precision precision,
|
||||
int radix,
|
||||
char base
|
||||
static void print_number_buffer(
|
||||
const char *buf, // buffer containing the text we want to print
|
||||
struct spacing spacing, // the spacing on the left right and middle
|
||||
enum printtype type,
|
||||
enum charcase cc
|
||||
) {
|
||||
bool isneg = false;
|
||||
|
||||
if (num < 0) {
|
||||
num = ~num;
|
||||
isneg = true;
|
||||
// put the 0x at the start of the string
|
||||
if (spacing.left && spacing.zero && type == HEX) {
|
||||
if (cc == UPPERCASE) {
|
||||
kputs("0X");
|
||||
} else {
|
||||
kputs("0x");
|
||||
}
|
||||
}
|
||||
|
||||
print_unum(
|
||||
num,
|
||||
flag,
|
||||
width,
|
||||
precision,
|
||||
isneg,
|
||||
radix,
|
||||
base
|
||||
);
|
||||
if ((!spacing.left || !spacing.zero) && type == OCTAL) {
|
||||
kputc('0');
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < spacing.left; i++) {
|
||||
spacing.zero ? kputc('0') : kputc(' ');
|
||||
}
|
||||
|
||||
if ((!spacing.left || !spacing.zero) && type == HEX) {
|
||||
if (cc == UPPERCASE) {
|
||||
kputs("0X");
|
||||
} else {
|
||||
kputs("0x");
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < spacing.length; i++) {
|
||||
kputc(*buf++);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < spacing.right; i++) {
|
||||
kputc(' ');
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned get_string_len(
|
||||
const char *str,
|
||||
struct format_precision precision
|
||||
) {
|
||||
if (!precision.defined)
|
||||
return strlen(str);
|
||||
unsigned max = precision.value;
|
||||
for (unsigned i = 0; i < max; i++) {
|
||||
if (str[i] == '\0') {
|
||||
// we broke early
|
||||
// precision is greater then strlen
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
static struct spacing get_spacing(
|
||||
struct format_width width,
|
||||
struct format_precision precision,
|
||||
enum format_flag flags,
|
||||
unsigned length
|
||||
) {
|
||||
struct spacing spacing;
|
||||
|
||||
unsigned min = 0,
|
||||
max = 0;
|
||||
|
||||
if (width.defined) {
|
||||
min = width.value;
|
||||
}
|
||||
|
||||
if (precision.defined) {
|
||||
max = precision.value;
|
||||
if (length > max) {
|
||||
length = max;
|
||||
}
|
||||
if (min > max) {
|
||||
min = max;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned gap = 0;
|
||||
if (max > length) {
|
||||
gap = max - length;
|
||||
}
|
||||
|
||||
spacing.length = length;
|
||||
|
||||
if (flags & FLG_LEFT_ALIGN) {
|
||||
spacing.left = gap;
|
||||
spacing.right = 0;
|
||||
} else {
|
||||
spacing.left = 0;
|
||||
spacing.right = gap;
|
||||
}
|
||||
|
||||
spacing.zero = (flags & FLG_ZERO);
|
||||
|
||||
return spacing;
|
||||
}
|
||||
|
||||
static struct spacing get_string_spacing(
|
||||
const char *str,
|
||||
struct format_width width,
|
||||
struct format_precision precision,
|
||||
enum format_flag flags
|
||||
) {
|
||||
unsigned length = get_string_len(str, precision);
|
||||
return get_spacing(width, precision, flags, length);
|
||||
}
|
||||
|
||||
static void print_string(
|
||||
const char *str,
|
||||
enum format_flag flags,
|
||||
struct format_width width,
|
||||
struct format_precision precision
|
||||
) {
|
||||
struct spacing spacing =
|
||||
get_string_spacing(str, width, precision, flags);
|
||||
print_string_buffer(str, spacing);
|
||||
}
|
||||
|
||||
static enum format_length apply_modifier(
|
||||
enum format_conversion conversion,
|
||||
enum format_modifier modifier
|
||||
) {
|
||||
switch (conversion) {
|
||||
case FMT_CHAR:
|
||||
if (modifier == MOD_NONE)
|
||||
return LEN_CHAR;
|
||||
else
|
||||
return LEN_INVALID;
|
||||
|
||||
case FMT_PTR:
|
||||
if (modifier == MOD_NONE)
|
||||
return LEN_SIZET;
|
||||
else
|
||||
return LEN_INVALID;
|
||||
|
||||
case FMT_INT:
|
||||
if (modifier == MOD_LONG)
|
||||
return LEN_LONG;
|
||||
else if (modifier == MOD_LONG_LONG)
|
||||
return LEN_LONGLONG;
|
||||
else if (modifier == MOD_HALF)
|
||||
return LEN_SHORT;
|
||||
else if (modifier == MOD_HALF_HALF)
|
||||
return LEN_CHAR;
|
||||
else
|
||||
return LEN_INT;
|
||||
|
||||
case FMT_UINT:
|
||||
case FMT_OCT:
|
||||
case FMT_HEX:
|
||||
case FMT_HEX_UPPER:
|
||||
if (modifier == MOD_LONG)
|
||||
return LEN_ULONG;
|
||||
else if (modifier == MOD_LONG_LONG)
|
||||
return LEN_ULONGLONG;
|
||||
else if (modifier == MOD_HALF)
|
||||
return LEN_USHORT;
|
||||
else if (modifier == MOD_HALF_HALF)
|
||||
return LEN_UCHAR;
|
||||
else
|
||||
return LEN_UINT;
|
||||
|
||||
default:
|
||||
return LEN_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned printtype_to_radix(
|
||||
enum printtype type
|
||||
) {
|
||||
switch (type) {
|
||||
case OCTAL:
|
||||
return 8;
|
||||
case HEX:
|
||||
return 16;
|
||||
case NONE:
|
||||
default:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_signed_number(
|
||||
signed long long num,
|
||||
enum format_flag flags,
|
||||
struct format_width width,
|
||||
struct format_precision precision,
|
||||
enum printtype type,
|
||||
enum charcase cc
|
||||
) {
|
||||
unsigned radix = printtype_to_radix(type);
|
||||
char buf[256];
|
||||
char *ptr = lltoa_print(num, radix, buf + 255, cc, flags & FLG_ADD_SIGN);
|
||||
unsigned length = strlen(ptr);
|
||||
struct spacing spacing =
|
||||
get_spacing(width, precision, flags, length);
|
||||
print_number_buffer(ptr, spacing, type, cc);
|
||||
}
|
||||
|
||||
static void print_unsigned_number(
|
||||
unsigned long long num,
|
||||
enum format_flag flags,
|
||||
struct format_width width,
|
||||
struct format_precision precision,
|
||||
enum printtype type,
|
||||
enum charcase cc
|
||||
) {
|
||||
unsigned radix = printtype_to_radix(type);
|
||||
char buf[256];
|
||||
char *ptr = ulltoa_print(num, radix, buf + 255, cc, flags & FLG_ADD_SIGN);
|
||||
unsigned length = strlen(ptr);
|
||||
struct spacing spacing =
|
||||
get_spacing(width, precision, flags, length);
|
||||
print_number_buffer(ptr, spacing, type, cc);
|
||||
}
|
||||
|
||||
static bool is_conversion_number(enum format_conversion conversion) {
|
||||
switch (conversion) {
|
||||
case FMT_INT:
|
||||
case FMT_UINT:
|
||||
case FMT_OCT:
|
||||
case FMT_HEX:
|
||||
case FMT_HEX_UPPER:
|
||||
case FMT_PTR:
|
||||
return true;
|
||||
case FMT_CHAR:
|
||||
case FMT_STR:
|
||||
case FMT_INVALID:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void kvprintf(const char *format, va_list args) {
|
||||
for (; *format != '\0'; format++) {
|
||||
char c = *format;
|
||||
if (c == '%') {
|
||||
enum format_flag flag;
|
||||
enum format_flag flags;
|
||||
struct format_width width;
|
||||
struct format_precision precision;
|
||||
enum format_modifier modifier;
|
||||
|
@ -435,34 +623,24 @@ void kvprintf(const char *format, va_list args) {
|
|||
|
||||
const char *ptr = format + 1;
|
||||
|
||||
flag = read_flag(ptr, &ptr);
|
||||
if (*(format + 1) == '%') {
|
||||
kputc('%');
|
||||
format++;
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = read_flags(ptr, &ptr);
|
||||
width = read_width(ptr, &ptr);
|
||||
precision = read_precision(ptr, &ptr);
|
||||
|
||||
modifier = read_modifier(ptr, &ptr);
|
||||
|
||||
if (modifier == MOD_INVALID) {
|
||||
kputc('%');
|
||||
continue;
|
||||
goto error;
|
||||
}
|
||||
|
||||
conversion = read_conversion(ptr, &ptr);
|
||||
|
||||
if (conversion == FMT_INVALID) {
|
||||
kputc('%');
|
||||
continue;
|
||||
}
|
||||
|
||||
union {
|
||||
unsigned long long u;
|
||||
long long l;
|
||||
char c;
|
||||
const char *str;
|
||||
void *ptr;
|
||||
} data = {0};
|
||||
|
||||
int radix = 0;
|
||||
char base = 0;
|
||||
|
||||
if (width.varys) {
|
||||
int len = va_arg(args, int);
|
||||
width.value = len;
|
||||
|
@ -473,106 +651,80 @@ void kvprintf(const char *format, va_list args) {
|
|||
precision.value = len;
|
||||
}
|
||||
|
||||
switch (conversion) {
|
||||
case FMT_INT:
|
||||
if (modifier == MOD_NONE)
|
||||
data.l = va_arg(args, int);
|
||||
else if (modifier == MOD_HALF)
|
||||
data.l = (short) va_arg(args, int);
|
||||
else if (modifier == MOD_HALF_HALF)
|
||||
data.l = (char) va_arg(args, int);
|
||||
else if (modifier == MOD_LONG)
|
||||
data.l = va_arg(args, long);
|
||||
else if (modifier == MOD_LONG_LONG)
|
||||
data.l = va_arg(args, long long);
|
||||
radix = 10;
|
||||
print_num(
|
||||
data.l,
|
||||
flag,
|
||||
width,
|
||||
precision,
|
||||
radix,
|
||||
base
|
||||
);
|
||||
break;
|
||||
case FMT_UINT:
|
||||
case FMT_OCT:
|
||||
case FMT_HEX_UPPER:
|
||||
case FMT_HEX:
|
||||
if (modifier == MOD_NONE)
|
||||
data.u = va_arg(args, unsigned int);
|
||||
else if (modifier == MOD_HALF)
|
||||
data.u = (unsigned short) va_arg(args, unsigned int);
|
||||
else if (modifier == MOD_HALF_HALF)
|
||||
data.u = (unsigned char) va_arg(args, unsigned int);
|
||||
else if (modifier == MOD_LONG)
|
||||
data.u = va_arg(args, unsigned long);
|
||||
else if (modifier == MOD_LONG_LONG)
|
||||
data.u = va_arg(args, unsigned long long);
|
||||
|
||||
if (conversion == FMT_UINT) {
|
||||
radix = 10;
|
||||
} else if (conversion == FMT_OCT) {
|
||||
radix = 8;
|
||||
} else if (conversion == FMT_HEX) {
|
||||
radix = 16;
|
||||
base = 'a';
|
||||
} else if (conversion == FMT_HEX_UPPER) {
|
||||
radix = 16;
|
||||
base = 'A';
|
||||
}
|
||||
goto printunum;
|
||||
break;
|
||||
case FMT_PTR:
|
||||
case FMT_PTR_UPPER:
|
||||
flag |= FLG_ZERO;
|
||||
data.u = va_arg(args, size_t);
|
||||
radix = 16;
|
||||
if (conversion == FMT_PTR)
|
||||
base = 'a';
|
||||
else
|
||||
base = 'A';
|
||||
goto printunum;
|
||||
break;
|
||||
printunum:
|
||||
print_unum(
|
||||
data.u,
|
||||
flag,
|
||||
width,
|
||||
precision,
|
||||
false,
|
||||
radix,
|
||||
base
|
||||
);
|
||||
break;
|
||||
case FMT_CHAR: {
|
||||
char buf[2];
|
||||
buf[0] = (char) va_arg(args, int);
|
||||
buf[1] = '\0';
|
||||
print_string(
|
||||
buf,
|
||||
flag,
|
||||
width,
|
||||
precision
|
||||
);
|
||||
break;
|
||||
}
|
||||
case FMT_STR:
|
||||
data.str = va_arg(args, const char*);
|
||||
print_string(
|
||||
data.str,
|
||||
flag,
|
||||
width,
|
||||
precision
|
||||
);
|
||||
break;
|
||||
case FMT_PERCENT:
|
||||
kputc('%');
|
||||
break;
|
||||
case FMT_INVALID:
|
||||
break;
|
||||
if (conversion == FMT_INVALID) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (conversion == FMT_INT) {
|
||||
enum format_length length =
|
||||
apply_modifier(conversion, modifier);
|
||||
enum printtype type = NONE;
|
||||
enum charcase cc = LOWERCASE;
|
||||
|
||||
signed long long num = 0;
|
||||
switch (length) {
|
||||
case LEN_CHAR:
|
||||
case LEN_SHORT:
|
||||
case LEN_INT:
|
||||
num = va_arg(args, signed int);
|
||||
break;
|
||||
case LEN_LONG:
|
||||
num = va_arg(args, signed long);
|
||||
break;
|
||||
case LEN_LONGLONG:
|
||||
num = va_arg(args, signed long long);
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
print_signed_number(num, flags, width, precision, type, cc);
|
||||
} else if (is_conversion_number(conversion)) {
|
||||
enum format_length length =
|
||||
apply_modifier(conversion, modifier);
|
||||
enum printtype type =
|
||||
conversion_to_printtype(conversion);
|
||||
enum charcase cc =
|
||||
conversion_to_charcase(conversion);
|
||||
|
||||
unsigned long long num = 0;
|
||||
switch (length) {
|
||||
case LEN_UCHAR:
|
||||
case LEN_USHORT:
|
||||
case LEN_UINT:
|
||||
num = va_arg(args, unsigned int);
|
||||
break;
|
||||
case LEN_ULONG:
|
||||
num = va_arg(args, unsigned long);
|
||||
break;
|
||||
case LEN_ULONGLONG:
|
||||
num = va_arg(args, unsigned long long);
|
||||
break;
|
||||
case LEN_SIZET:
|
||||
num = va_arg(args, size_t);
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
print_unsigned_number(num, flags, width, precision, type, cc);
|
||||
} else if (conversion == FMT_STR) {
|
||||
char *str = va_arg(args, char *);
|
||||
print_string(str, flags, width, precision);
|
||||
} else if (conversion == FMT_CHAR) {
|
||||
char temp[2];
|
||||
temp[0] = va_arg(args, int);
|
||||
temp[1] = '\0';
|
||||
print_string(temp, flags, width, precision);
|
||||
}
|
||||
|
||||
format = ptr - 1;
|
||||
continue;
|
||||
|
||||
error:
|
||||
kputc('%');
|
||||
format++;
|
||||
continue;
|
||||
} else {
|
||||
kputc(c);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue