ep7
[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                     buffer[ptr] = '0';
68                     buffer[ptr+1] = 'x';
69                     __itoa_internal((int)dptr, buffer + ptr + 2, 16, &adv);
70                     adv+=2;
71                     break;
72                 }
73                 case '%': {
74                     buffer[ptr] = c;
75                     adv = 1;
76                     break;
77                 }
78                 default:
79                     // unknown
80                     break;
81             }
82         }
83         fmt++;
84         ptr += adv;
85     }
86     buffer[ptr] = '\0';
87 }
88
89 void
90 sprintf(char* buffer, char* fmt, ...)
91 {
92     va_list args;
93     va_start(args, fmt);
94     __sprintf_internal(buffer, fmt, args);
95     va_end(args);
96 }