15a7fe2503fd840eeb00d245a912c98ba02f452a
[lunaix-os.git] / lunaix-os / libs / libc / stdio / sprintf.c
1 #define __LUNAIX_LIBC
2 #include <libc/stdio.h>
3 #include <libc/stdlib.h>
4 #include <libc/string.h>
5 #include <stdint.h>
6
7 void
8 __sprintf_internal(char* buffer, char* fmt, va_list args)
9 {
10     char c;
11     int num;
12     unsigned int ptr = 0;
13     unsigned int adv = 0;
14     while ((c = *fmt)) {
15         if (c != '%') {
16             buffer[ptr] = c;
17             adv = 1;
18         } else {
19             adv = 0;
20             fmt++;
21             switch (c = *fmt) {
22                 case 'c': {
23                     buffer[ptr] = (char)va_arg(args, int);
24                     adv = 1;
25                     break;
26                 }
27                 case 's': {
28                     char* str = va_arg(args, char*);
29                     strcpy(buffer + ptr, str);
30                     adv = strlen(str);
31                     break;
32                 }
33                 case 'i':
34                 // fall through
35                 case 'd': {
36                     num = va_arg(args, int);
37                     __itoa_internal(num, buffer + ptr, 10, &adv);
38                     break;
39                 }
40                 case 'u': {
41                     unsigned int unum = va_arg(args, unsigned int);
42                     __uitoa_internal(unum, buffer + ptr, 10, &adv);
43                     break;
44                 }
45                 case 'o': {
46                     num = va_arg(args, int);
47                     __itoa_internal(num, buffer + ptr, 8, &adv);
48                     break;
49                 }
50                 case 'x':
51                 // fall through
52                 case 'X': {
53                     num = va_arg(args, int);
54                     __itoa_internal(num, buffer + ptr, 16, &adv);
55                     if (c == 'X') {
56                         int p = ptr;
57                         char c_;
58                         while ((c_ = buffer[p])) {
59                             buffer[p] = c_ & ~((c_ & 0x40) >> 1);
60                             p++;
61                         }
62                     }
63                     break;
64                 }
65                 case 'p': {
66                     uintptr_t dptr = va_arg(args, uintptr_t);
67                     __itoa_internal((int)dptr, buffer + ptr, 16, &adv);
68                     break;
69                 }
70                 case '%': {
71                     buffer[ptr] = c;
72                     adv = 1;
73                     break;
74                 }
75                 default:
76                     // unknown
77                     break;
78             }
79         }
80         fmt++;
81         ptr += adv;
82     }
83     buffer[ptr] = '\0';
84 }
85
86 void
87 sprintf(char* buffer, char* fmt, ...)
88 {
89     va_list args;
90     va_start(args, fmt);
91     __sprintf_internal(buffer, fmt, args);
92     va_end(args);
93 }