// // Created by rick on 06-02-21. // #include #include #include #include #include #include #include const char *printf_null_str = "NULL"; /* * Integer to string */ void print_int(uint32_t value, uint32_t width, char *buf, uint32_t *ptr, uint8_t base) { // uint32_t in binary is 32 digits, so never longer than 33 digits char msg[33]; itoa(value, msg, base); uint32_t digits = strlen(msg); if (digits < width) { for (uint32_t i = 0; i < (width - digits); ++i) { buf[*ptr] = '0'; *ptr += 1; } } for (uint32_t i = 0; i < digits; ++i) { buf[*ptr] = msg[i]; *ptr += 1; } } void vasprintf_unsupported(char c) { char *msg = "FMT '%x' is not supported\n"; msg[6] = c; k_panics(msg); } uint32_t vasprintf(char *buf, const char *fmt, va_list args) { uint32_t ptr = 0; for (size_t i = 0; i < strlen(fmt); ++i) { if (fmt[i] != '%') { buf[ptr++] = fmt[i]; continue; } ++i; uint32_t field_width = 0; uint32_t precision = 0; // todo bool negative_field_width = false; // todo if (fmt[i] == '-') { // invert negative_field_width = true; ++i; } while (fmt[i] >= '0' && fmt[i] <= '9') { field_width *= 10; field_width += fmt[i] - '0'; ++i; } if (fmt[i] == '.') { ++i; while (fmt[i] >= '0' && fmt[i] <= '9') { precision *= 10; precision += fmt[i] - '0'; ++i; } } switch (fmt[i]) { case 's': { // string uint32_t j = 0; const char *s_fmt = (char *) va_arg(args, char*); if (s_fmt == NULL) { s_fmt = printf_null_str; } while (*s_fmt && (precision == 0 || j != precision)) { buf[ptr++] = *s_fmt++; j++; } break; } case 'c': buf[ptr++] = (char) va_arg(args, int); break; case 'x': case 'p': case 'X': // todo capitalize print_int((uint32_t) va_arg(args, uint32_t), field_width, buf, &ptr, 16); break; case 'i': case 'd': case 'u': print_int((uint32_t) va_arg(args, uint32_t), field_width, buf, &ptr, 10); break; case '%': buf[ptr++] = '%'; break; default: vasprintf_unsupported(fmt[i]); break; } } buf[ptr] = 0; return ptr; } int vprintf(const char *fmt, va_list args) { int result; char buf[1024] = {-1}; result = vasprintf(buf, fmt, args); kprint(buf); return result; } int printf(const char *fmt, ...) { int result; va_list args; va_start(args, fmt); result = vprintf(fmt, args); va_end(args); return result; } int sprintf(char *target, const char *fmt, ...) { int result; va_list args; va_start(args, fmt); result = vasprintf(target, fmt, args); va_end(args); return result; }