167 lines
2.5 KiB
C
167 lines
2.5 KiB
C
#include <vx_print.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
static const char* skip_flags(const char* format) {
|
|
for (;;) {
|
|
int c = *format++;
|
|
switch (c) {
|
|
case '-':
|
|
case '+':
|
|
case ' ':
|
|
case '#': break;
|
|
default : {
|
|
return --format;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static const char* skip_width(const char* format) {
|
|
if (*format == '*') {
|
|
++format;
|
|
} else {
|
|
char *endptr;
|
|
strtol(format, &endptr, 10);
|
|
format = endptr;
|
|
}
|
|
return format;
|
|
}
|
|
|
|
static const char* skip_precision(const char* format) {
|
|
if (*format == '.') {
|
|
++format;
|
|
if (*format == '*') {
|
|
++format;
|
|
} else {
|
|
char *endptr;
|
|
strtol(format, &endptr, 10);
|
|
format = endptr;
|
|
}
|
|
}
|
|
return format;
|
|
}
|
|
|
|
static const char* skip_modifier(const char* format) {
|
|
switch (*format) {
|
|
case 'h':
|
|
format++;
|
|
if (*format == 'h') {
|
|
format++;
|
|
}
|
|
break;
|
|
case 'l':
|
|
++format;
|
|
if (*format == 'l') {
|
|
++format;
|
|
}
|
|
break;
|
|
case 'j':
|
|
case 'z':
|
|
case 't':
|
|
case 'L':
|
|
++format;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return format;
|
|
}
|
|
|
|
static const char* parse_format(const char* format, va_list va) {
|
|
char buffer[64];
|
|
char fmt[64];
|
|
|
|
const char* p = format;
|
|
p = skip_flags(p);
|
|
p = skip_width(p);
|
|
p = skip_precision(p);
|
|
p = skip_modifier(p);
|
|
++p;
|
|
|
|
int i;
|
|
|
|
fmt[0] = '%';
|
|
for (i = 0; i < (p - format); ++i) {
|
|
fmt[i+1] = format[i];
|
|
}
|
|
fmt[i+1] = 0;
|
|
|
|
int len = vsnprintf(buffer, 256, fmt, va);
|
|
|
|
for (i = 0; i < len; ++i) {
|
|
vx_putchar(buffer[i]);
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
int vx_vprintf(const char* format, va_list va) {
|
|
if (format == NULL)
|
|
return -1;
|
|
|
|
const char* p = format;
|
|
int c = *p++;
|
|
while (c) {
|
|
if (c == '%') {
|
|
p = parse_format(p, va);
|
|
c = *p++;
|
|
} else {
|
|
vx_putchar(c);
|
|
c = *p++;
|
|
}
|
|
}
|
|
|
|
return (int)(p - format);
|
|
}
|
|
|
|
int vx_printf(const char * format, ...) {
|
|
va_list va;
|
|
va_start(va, format);
|
|
int ret = vx_vprintf(format, va);
|
|
va_end(va);
|
|
return ret;
|
|
}
|
|
|
|
static const char hextoa[] = "0123456789abcdef";
|
|
|
|
void vx_prints(const char * str) {
|
|
int c = *str++;
|
|
while (c) {
|
|
vx_putchar(c);
|
|
c = *str++;
|
|
}
|
|
}
|
|
|
|
void vx_printx(unsigned value) {
|
|
if (value < 16) {
|
|
vx_putchar(hextoa[value]);
|
|
} else {
|
|
int i = 32;
|
|
bool start = false;
|
|
do {
|
|
int temp = (value >> (i - 4)) & 0xf;
|
|
if (temp != 0)
|
|
start = true;
|
|
if (start)
|
|
vx_putchar(hextoa[temp]);
|
|
i-= 4;
|
|
} while (i != 0);
|
|
}
|
|
vx_putchar('\n');
|
|
}
|
|
|
|
void vx_printv(const char * str, unsigned value) {
|
|
vx_prints(str);
|
|
vx_printx(value);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif |