/* * Copyright (c) 2019 shchmue * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "sprintf.h" #include <stdarg.h> static void _putc(char *buffer, const char c) { *buffer = c; } static u32 _puts(char *buffer, const char *s) { u32 count = 0; for (; *s; s++, count++) _putc(buffer + count, *s); return count; } static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) { char buf[0x121]; static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; char *p; int c = fcnt; if (base > 36) return 0; p = buf + 0x120; *p = 0; do { c--; *--p = digits[v % base]; v /= base; } while (v); if (fill != 0) { while (c > 0) { *--p = fill; c--; } } return _puts(buffer, p); } u32 sprintf(char *buffer, const char *fmt, ...) { va_list ap; int fill, fcnt; u32 count = 0; va_start(ap, fmt); while(*fmt) { if (*fmt == '%') { fmt++; fill = 0; fcnt = 0; if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') { fcnt = *fmt; fmt++; if (*fmt >= '0' && *fmt <= '9') { fill = fcnt; fcnt = *fmt - '0'; fmt++; } else { fill = ' '; fcnt -= '0'; } } switch (*fmt) { case 'c': _putc(buffer + count, va_arg(ap, u32)); count++; break; case 's': count += _puts(buffer + count, va_arg(ap, char *)); break; case 'd': count += _putn(buffer + count, va_arg(ap, u32), 10, fill, fcnt); break; case 'p': case 'P': case 'x': case 'X': count += _putn(buffer + count, va_arg(ap, u32), 16, fill, fcnt); break; case '%': _putc(buffer + count, '%'); count++; break; case '\0': goto out; default: _putc(buffer + count, '%'); count++; _putc(buffer + count, *fmt); count++; break; } } else { _putc(buffer + count, *fmt); count++; } fmt++; } out: buffer[count] = 0; va_end(ap); return count; }