#include "common.h" void putchar(char c); size_t align_up(size_t value, size_t align) { /* To align means to compute the smallest value which is greater than a * given number and that is an exact multiple of another specified * number */ size_t remainder = value % align; if (remainder == 0) return value; return value + (align - remainder); } size_t is_aligned(size_t value, size_t align) { return value % align == 0; } void *memcpy(void *dst, const void *src, size_t n) { uint8_t *d = (uint8_t*)dst; const uint8_t *s = (uint8_t*)src; while (n--) { *d++ = *s++; } return dst; } void *memset(void *buf, char c, size_t n) { uint8_t *p = (uint8_t*)buf; while (n--) { *p++ = c; } return buf; } char *strcpy(char *dst, const char *src) { char *d = dst; while (*src != '\0') { *d++ = *src++; } *d = '\0'; return dst; } int strcmp(const char *s1, const char *s2) { while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; } return *((unsigned char *)s1) - *((unsigned char *)s2); } void printf(const char *fmt, ...) { va_list args; va_start(args, fmt); while (*fmt != '\0') { if (*fmt != '%') { putchar(*fmt); fmt++; } else { fmt++; // consume % switch (*fmt) { case '\0': putchar('%'); goto end; case '%': putchar('%'); break; case 's': const char *s = va_arg(args, const char*); while (*s != '\0') { putchar(*s); s++; } break; case 'd': int num = va_arg(args, int); unsigned int magnitude = num; unsigned int power = 1; if (num < 0) { putchar('-'); magnitude = -magnitude; } while ((magnitude / power) > 9) { power *= 10; } while (power > 0) { putchar('0' + (magnitude / power)); magnitude %= power; power /= 10; } break; case 'x': unsigned int hex = va_arg(args, unsigned int); putchar('0'); putchar('x'); for (int i = 7; i >= 0; i--) { unsigned int nibble = (hex >> (4 * i)) & 0xf; putchar("0123456789abcdef"[nibble]); } break; } fmt++; // consume modifier } } end: va_end(args); return; }