|
@@ -5,6 +5,23 @@
|
|
|
#include <string.h>
|
|
|
#include <unistd.h>
|
|
|
|
|
|
+#define BUFSIZ (4096)
|
|
|
+static char __stdout_buf[BUFSIZ];
|
|
|
+static size_t __stdout_buf_cnt;
|
|
|
+
|
|
|
+static inline void __buf_flush(void)
|
|
|
+{
|
|
|
+ write(STDOUT_FILENO, __stdout_buf, __stdout_buf_cnt);
|
|
|
+ __stdout_buf_cnt = 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline void __buf_put(int c)
|
|
|
+{
|
|
|
+ __stdout_buf[__stdout_buf_cnt++] = c;
|
|
|
+ if (__stdout_buf_cnt == BUFSIZ || c == '\n')
|
|
|
+ __buf_flush();
|
|
|
+}
|
|
|
+
|
|
|
// where n is in the range of [0, 9]
|
|
|
static inline char d_to_c(int32_t n)
|
|
|
{
|
|
@@ -368,18 +385,14 @@ int sprintf(char* buf, const char* fmt, ...)
|
|
|
|
|
|
int puts(const char* str)
|
|
|
{
|
|
|
- int len = 0;
|
|
|
-
|
|
|
- int ret = write(STDOUT_FILENO, str, strlen(str));
|
|
|
- if (ret < 0)
|
|
|
- return EOF;
|
|
|
- len += ret;
|
|
|
-
|
|
|
- ret = write(STDOUT_FILENO, "\n", 1);
|
|
|
- if (ret < 0)
|
|
|
- return EOF;
|
|
|
- len += ret;
|
|
|
-
|
|
|
+ // 1 is for \n at the end
|
|
|
+ int len = 1;
|
|
|
+
|
|
|
+ // TODO: FILE*
|
|
|
+ for (const char* p = str; *p; ++p, ++len)
|
|
|
+ __buf_put(*p);
|
|
|
+
|
|
|
+ __buf_put('\n');
|
|
|
return len;
|
|
|
}
|
|
|
|
|
@@ -395,3 +408,188 @@ char* gets(char* buf)
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|
|
|
+
|
|
|
+int vprintf_u32(uint32_t num)
|
|
|
+{
|
|
|
+ if (num <= 9) {
|
|
|
+ __buf_put(d_to_c(num));
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ int ret = vprintf_u32(num / 10);
|
|
|
+ __buf_put(d_to_c(num % 10));
|
|
|
+ return ret + 1;
|
|
|
+}
|
|
|
+
|
|
|
+int vprintf_d32(int32_t num)
|
|
|
+{
|
|
|
+ if (num < 0) {
|
|
|
+ __buf_put('-');
|
|
|
+ return vprintf_u32(-num) + 1;
|
|
|
+ }
|
|
|
+ return vprintf_u32(num);
|
|
|
+}
|
|
|
+
|
|
|
+int vprintf_u64(uint64_t num)
|
|
|
+{
|
|
|
+ if (num <= 9) {
|
|
|
+ __buf_put(d_to_c(num));
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ int ret = vprintf_u64(num / 10);
|
|
|
+ __buf_put(d_to_c(num % 10));
|
|
|
+ return ret + 1;
|
|
|
+}
|
|
|
+
|
|
|
+int vprintf_d64(int64_t num)
|
|
|
+{
|
|
|
+ if (num < 0) {
|
|
|
+ __buf_put('-');
|
|
|
+ return vprintf_u64(-num) + 1;
|
|
|
+ }
|
|
|
+ return vprintf_u64(num);
|
|
|
+}
|
|
|
+
|
|
|
+int vprintf_x32(uint32_t num, int off)
|
|
|
+{
|
|
|
+ // print leading 0x
|
|
|
+ if (off & 1) {
|
|
|
+ --off;
|
|
|
+ __buf_put('0');
|
|
|
+ __buf_put('X' + off);
|
|
|
+ return vprintf_x32(num, off) + 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (num <= 15) {
|
|
|
+ __buf_put(X_to_c(num) + off);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ int ret = vprintf_x32(num >> 4, off);
|
|
|
+ __buf_put(X_to_c(num & 0xf) + off);
|
|
|
+ return ret + 1;
|
|
|
+}
|
|
|
+
|
|
|
+int vprintf_x64(uint64_t num, int off)
|
|
|
+{
|
|
|
+ // print leading 0x
|
|
|
+ if (off & 1) {
|
|
|
+ --off;
|
|
|
+ __buf_put('0');
|
|
|
+ __buf_put('X' + off);
|
|
|
+ return vprintf_x64(num, off) + 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (num <= 15) {
|
|
|
+ __buf_put(X_to_c(num) + off);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ int ret = vprintf_x64(num >> 4, off);
|
|
|
+ __buf_put(X_to_c(num & 0xf) + off);
|
|
|
+ return ret + 1;
|
|
|
+}
|
|
|
+
|
|
|
+int vprintf(const char* fmt, va_list args)
|
|
|
+{
|
|
|
+ int n = 0;
|
|
|
+
|
|
|
+ for (char c = 0; (c = *fmt) != 0x00; ++fmt) {
|
|
|
+ if (c == '%') {
|
|
|
+ switch (*(++fmt)) {
|
|
|
+
|
|
|
+ // int
|
|
|
+ case 'd':
|
|
|
+ n += vprintf_d32(va_arg(args, int));
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'x':
|
|
|
+ n += vprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'X':
|
|
|
+ n += vprintf_x32(va_arg(args, unsigned int), 1);
|
|
|
+ break;
|
|
|
+
|
|
|
+ // long decimal
|
|
|
+ case 'l':
|
|
|
+ switch (*(++fmt)) {
|
|
|
+ // long long aka int64
|
|
|
+ case 'l':
|
|
|
+ switch (*(++fmt)) {
|
|
|
+ case 'd':
|
|
|
+ n += vprintf_d64(va_arg(args, long long));
|
|
|
+ break;
|
|
|
+ case 'x':
|
|
|
+ n += vprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1);
|
|
|
+ break;
|
|
|
+ case 'X':
|
|
|
+ n += vprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ // long int aka int32
|
|
|
+ case 'd':
|
|
|
+ n += vprintf_d32(va_arg(args, int));
|
|
|
+ break;
|
|
|
+ case 'x':
|
|
|
+ n += vprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'X':
|
|
|
+ n += vprintf_x32(va_arg(args, unsigned int), 1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ // c string
|
|
|
+ case 's':
|
|
|
+ n += printf(va_arg(args, const char*));
|
|
|
+ break;
|
|
|
+
|
|
|
+ // int8 char
|
|
|
+ case 'c':
|
|
|
+ ++n;
|
|
|
+ __buf_put(va_arg(args, int));
|
|
|
+ break;
|
|
|
+
|
|
|
+ // pointer
|
|
|
+ case 'p':
|
|
|
+#ifdef __32bit_system
|
|
|
+ n += vprintf_x32(va_arg(args, size_t), 'a' - 'A' + 1);
|
|
|
+#else
|
|
|
+ n += vprintf_x64(va_arg(args, size_t), 'a' - 'A' + 1);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ ++n;
|
|
|
+ __buf_put(*(fmt - 1));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ ++n;
|
|
|
+ __buf_put(c);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return n;
|
|
|
+}
|
|
|
+
|
|
|
+int printf(const char* fmt, ...)
|
|
|
+{
|
|
|
+ va_list args;
|
|
|
+ va_start(args, fmt);
|
|
|
+
|
|
|
+ int ret = vprintf(fmt, args);
|
|
|
+
|
|
|
+ va_end(args);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+int putchar(int c)
|
|
|
+{
|
|
|
+ __buf_put(c);
|
|
|
+ return c;
|
|
|
+}
|