MushOS  0.1
A UNIX-like OS prototype, written from scratch
Loading...
Searching...
No Matches
format.c
1#include "string.h"
2
3#include "heap.h"
4#include "vararg.h"
5
6
7#define undefined '?'
8
9typedef enum {
10 DECIMAL = 10, HEXADECIMAL = 16, BINARY = 2
11} system;
12
13typedef enum {
14 INTEGER, FLOAT
15} type;
16
17
18static mod_string char_to_string(char c) {
19 mod_string str = ralloc(2);
20 str[0] = c;
21 str[1] = 0;
22 return str;
23}
24
25static mod_string const_to_string(string str) {
26 u_dword length = len(str);
27 mod_string mod = ralloc(length + 1);
28 for (u_dword i = 0; i < length; i++) mod[i] = str[i];
29 mod[length] = 0;
30 return mod;
31}
32
33
34static char atom_to_char(u_byte b, system sys) {
35 if ((sys >= 2) && (sys <= 10)) return b + 48;
36 else if ((sys > 10) && (sys <= 36)) {
37 if (b < 10) return b + 48;
38 else return b + 65 - 10;
39 } else return undefined;
40}
41
42static mod_string int_to_string(u_dword b, system sys) {
43 u_qword mult = sys;
44 u_dword power = 1;
45 while (mult <= b) {
46 mult *= sys;
47 power++;
48 }
49
50 mod_string result = ralloc(power + 1);
51 result[power] = 0;
52
53 u_dword integer = b;
54 while (integer) {
55 power--;
56 result[power] = atom_to_char(integer % sys, sys);
57 integer /= sys;
58 }
59 return result;
60}
61
62static mod_string boolean_to_string(boolean b) {
63 if (b) return const_to_string("true");
64 else return const_to_string("false");
65}
66
67static mod_string float_to_string(precise b, u_dword after_comma) {
68 if (after_comma) {
69 mod_string integer = int_to_string((u_dword) b, DECIMAL);
70 mod_string full = concatenate(integer, ".");
71 unalloc(integer);
72
73 precise floating = b - (u_dword) b;
74 for (u_dword i = 0; i < after_comma; i++) floating *= DECIMAL;
75 mod_string part = int_to_string(floating, DECIMAL);
76 mod_string result = concatenate(full, part);
77 unalloc(part);
78 unalloc(full);
79
80 if (b < 0) {
81 mod_string signum = concatenate("-", result);
82 unalloc(result);
83 result = signum;
84 }
85 return result;
86 } else return int_to_string((u_dword) b, DECIMAL);
87}
88
89static mod_string pointer_to_string(void* ptr) {
90 if (ptr == nullptr) return const_to_string(".null");
91 else {
92 mod_string integer = int_to_string((u_dword) ptr, HEXADECIMAL);
93 mod_string result = concatenate(".", integer);
94 unalloc(integer);
95 return result;
96 }
97}
98
99static mod_string number_to_string(dword num, system sys) {
100 mod_string number;
101 if (num == 0) number = char_to_string(atom_to_char(0, sys));
102 else if (num < 0) number = int_to_string(-num, sys);
103 else number = int_to_string(num, sys);
104
105 mod_string result;
106 switch (sys) {
107 case DECIMAL:
108 result = number;
109 break;
110 case HEXADECIMAL:
111 result = concatenate("0x", number);
112 unalloc(number);
113 break;
114 case BINARY:
115 result = concatenate("0b", number);
116 unalloc(number);
117 break;
118 default:
119 mod_string prefix = format("(base %d) ", sys);
120 result = concatenate(prefix, number);
121 unalloc(prefix);
122 unalloc(number);
123 break;
124 }
125
126 if (num < 0) {
127 mod_string signum = concatenate("-", result);
128 unalloc(result);
129 result = signum;
130 }
131
132 return result;
133}
134
135
136static mod_string free_concat(mod_string string1, mod_string string2) {
137 mod_string result = concatenate(string1, string2);
138 unalloc(string1);
139 unalloc(string2);
140 return result;
141};
142
143mod_string format(string template, ...) {
144 mod_string result = (mod_string) zalloc(1);
145 u_dword argumentor = init_vararg(sizeof(string)), printed = 0;
146 for (int j = 0; j < len(template); ++j) {
147 if (template[j] == '%') {
148 result = free_concat(result, substring_mid(template, printed, j));
149 printed = j + 2;
150 j++;
151
152 switch (template[j]) {
153 case 'l':
154 result = free_concat(result, boolean_to_string(get_vararg(argumentor, boolean)));
155 break;
156 case 'p':
157 result = free_concat(result, pointer_to_string(get_vararg(argumentor, void*)));
158 break;
159 case 'd':
160 result = free_concat(result, number_to_string(get_vararg(argumentor, dword), DECIMAL));
161 break;
162 case 'h':
163 result = free_concat(result, number_to_string(get_vararg(argumentor, dword), HEXADECIMAL));
164 break;
165 case 'b':
166 result = free_concat(result, number_to_string(get_vararg(argumentor, dword), BINARY));
167 break;
168 case 'f':
169 result = free_concat(result, float_to_string(get_vararg(argumentor, precise), 4));
170 break;
171 case 'c':
172 result = free_concat(result, char_to_string(get_vararg(argumentor, char)));
173 break;
174 case 's':
175 result = free_concat(result, const_to_string(get_vararg(argumentor, string)));
176 break;
177 default:
178 j--;
179 printed -= 2;
180 break;
181 }
182 }
183 }
184
185 return free_concat(result, substring_beg(template, printed));
186}
This is a standard MushLib heap header. See standard implementation in lib/base/heap....
void * ralloc(u_dword size)
void unalloc(void *structure)
void * zalloc(u_dword size)