123 lines
3.2 KiB
C
123 lines
3.2 KiB
C
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
static void utoa(unsigned int value, char *buf, int base) {
|
|
char temp[32];
|
|
int i = 0;
|
|
|
|
// Handle zero explicitly
|
|
if (value == 0) {
|
|
buf[0] = '0';
|
|
buf[1] = '\0';
|
|
return;
|
|
}
|
|
|
|
// Convert digits in reverse order
|
|
while (value > 0) {
|
|
int remainder = value % base;
|
|
if (remainder < 10) {
|
|
temp[i++] = '0' + remainder;
|
|
} else {
|
|
temp[i++] = 'a' + (remainder - 10);
|
|
}
|
|
value /= base;
|
|
}
|
|
|
|
// Reverse the string into the output destination buffer
|
|
int j = 0;
|
|
while (i > 0) {
|
|
buf[j++] = temp[--i];
|
|
}
|
|
buf[j] = '\0';
|
|
}
|
|
|
|
/* Helper function to convert a signed integer to a string */
|
|
static void itoa(int value, char *buf, int base) {
|
|
if (value < 0 && base == 10) {
|
|
*buf++ = '-';
|
|
value = -value;
|
|
}
|
|
utoa((unsigned int)value, buf, base);
|
|
}
|
|
|
|
int printf(const char *format, ...) {
|
|
va_list args;
|
|
va_start(args, format);
|
|
|
|
int written_total = 0;
|
|
char num_buf[32]; // Stack-allocated scratchpad for string conversions
|
|
|
|
while (*format != '\0') {
|
|
if (*format == '%') {
|
|
format++; // Move past '%'
|
|
|
|
switch (*format) {
|
|
case 'c': {
|
|
char c = (char)va_arg(args, int);
|
|
write(1, &c, 1);
|
|
written_total++;
|
|
break;
|
|
}
|
|
case 's': {
|
|
char *s = va_arg(args, char *);
|
|
if (!s) s = "(null)";
|
|
// Find length manually without dragging headers
|
|
int len = 0;
|
|
while (s[len] != '\0') len++;
|
|
write(1, s, len);
|
|
written_total += len;
|
|
break;
|
|
}
|
|
case 'd':
|
|
case 'i': {
|
|
int n = va_arg(args, int);
|
|
itoa(n, num_buf, 10);
|
|
int len = 0;
|
|
while (num_buf[len] != '\0') len++;
|
|
write(1, num_buf, len);
|
|
written_total += len;
|
|
break;
|
|
}
|
|
case 'x': {
|
|
unsigned int x = va_arg(args, unsigned int);
|
|
utoa(x, num_buf, 16);
|
|
int len = 0;
|
|
while (num_buf[len] != '\0') len++;
|
|
write(1, num_buf, len);
|
|
written_total += len;
|
|
break;
|
|
}
|
|
case '%': {
|
|
write(1, "%", 1);
|
|
written_total++;
|
|
break;
|
|
}
|
|
default:
|
|
// Unknown conversion, print verbatim
|
|
write(1, format - 1, 2);
|
|
written_total += 2;
|
|
break;
|
|
}
|
|
} else {
|
|
// Standard text character
|
|
write(1, format, 1);
|
|
written_total++;
|
|
}
|
|
format++;
|
|
}
|
|
|
|
va_end(args);
|
|
return written_total;
|
|
}
|
|
|
|
char getchar(void) {
|
|
char c;
|
|
int res = read(0, &c, 1);
|
|
|
|
if (res <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
return (char)c;
|
|
}
|