#include #include #include #include #include #if defined(__PORT_mos6502) typedef void (*emitter_t)(char, char **) REENTRANT; #else typedef void (*emitter_t)(char, char **) OLDCALL; #endif static const char _hex[] = "0123456789ABCDEF"; inline void _printhex(uint16_t u, emitter_t emitter, char ** pData) { (*emitter)(_hex[(uint8_t)(u >> 8) >> 4], pData); (*emitter)(_hex[(uint8_t)(u >> 8) & 0x0fu], pData); (*emitter)(_hex[((uint8_t)u >> 4) & 0x0fu], pData); (*emitter)(_hex[(uint8_t)u & 0x0fu], pData); } inline void _printhexbyte(uint8_t u, emitter_t emitter, char ** pData) { (*emitter)(_hex[u >> 4], pData); (*emitter)(_hex[u & 0x0fu], pData); } static void _printbuf(char * buf, emitter_t emitter, char ** pData) { for (char *s = buf; *s; s++) (*emitter)(*s, pData); } void __printf(const char *format, emitter_t emitter, char **pData, va_list va) { char buf[16]; while ((uint8_t)(*format)) { if ((uint8_t)(*format) == '%') { format++; // 0 Padding is not supported, ignore if ((uint8_t)(*format) == '0') format++; // Width Specifier is not supported, ignore 1 digit worth if ((uint8_t)((uint8_t)(*format) - '1') < 9u) format++; switch ((uint8_t)(*format)) { case 'h': switch ((uint8_t)(*++format)) { case 'X' : case 'x' : _printhexbyte(va_arg(va, char), emitter, pData); break; case 'u': uitoa((unsigned char)va_arg(va, char), buf, 10); _printbuf(buf, emitter, pData); break; case 'd': itoa((signed char)va_arg(va, char), buf, 10); _printbuf(buf, emitter, pData); break; } break; case 'u': uitoa(va_arg(va, int), buf, 10); _printbuf(buf, emitter, pData); break; case 'd': itoa(va_arg(va, int), buf, 10); _printbuf(buf, emitter, pData); break; case 's': _printbuf(va_arg(va, char *), emitter, pData); break; case 'c': char c = va_arg(va, char); (*emitter)(c, pData); break; case 'X': case 'x': _printhex(va_arg(va, int), emitter, pData); break; default: (*emitter)(*format, pData); break; } } else { (*emitter)(*format, pData); } format++; } } #if defined(__PORT_mos6502) static void _sprintf_emitter(char c, char ** pData) REENTRANT #else static void _sprintf_emitter(char c, char ** pData) OLDCALL #endif { **pData = c; (*pData)++; } void sprintf(char *into, const char *format, ...) { va_list va; va_start(va, format); __printf(format, _sprintf_emitter, &into, va); _sprintf_emitter('\0', &into); }