override self/exe
[ginge.git] / loader / llibc.c
CommitLineData
d0b9b0df 1/*
2 * GINGE - GINGE Is Not Gp2x Emulator
3 * (C) notaz, 2016
4 *
5 * This work is licensed under the MAME license, see COPYING file for details.
6 */
7#include <stdio.h>
8#include <string.h>
9#include <stdarg.h>
10
11#include "syscalls.h"
12#include "llibc.h"
13
14// lame, broken and slow, but enough for ginge's needs
15static void format_number(char **dst_, int dst_len, unsigned int n,
16 char fmt, int justify, int zeropad)
17{
18 char buf[32], *p = buf, *dst;
19 int printing = 0;
20 unsigned int div;
21 unsigned int t;
22 unsigned int w;
23 int spaces;
24 int neg = 0;
25 int left;
26
27 w = justify < 0 ? -justify : justify;
28 if (w >= 32)
29 w = 31;
30
31 switch (fmt) {
32 case 'i':
33 case 'd':
34 if ((signed int)n < 0) {
35 n = -n;
36 neg = 1;
37 }
38 case 'u':
39 div = 1000000000;
40 left = 10;
41 while (w > left) {
42 *p++ = ' ';
43 w--;
44 continue;
45 }
46 while (left > 0) {
47 t = n / div;
48 n -= t * div;
49 div /= 10;
50 if (t || left == 1) {
51 if (neg && t && !printing) {
52 *p++ = '-';
53 if (w > 0) w--;
54 }
55 printing = 1;
56 }
57 if (printing)
58 *p++ = t + '0';
59 else if (w >= left) {
60 *p++ = ' ';
61 w--;
62 }
63 left--;
64 }
65 break;
66
67 case 'p':
68 w = 8;
69 zeropad = 1;
70 case 'x':
71 left = 8;
72 while (w > left) {
73 *p++ = zeropad ? '0' : ' ';
74 w--;
75 continue;
76 }
77 while (left > 0) {
78 t = n >> (left * 4 - 4);
79 t &= 0x0f;
80 if (t || left == 1)
81 printing = 1;
82 if (printing)
83 *p++ = t < 10 ? t + '0' : t + 'a' - 10;
84 else if (w >= left) {
85 *p++ = zeropad ? '0' : ' ';
86 w--;
87 }
88 left--;
89 }
90 break;
91
92 default:
93 memcpy(buf, "<FMTODO>", 9);
94 break;
95 }
96 *p = 0;
97
98 spaces = 0;
99 p = buf;
100 if (justify < 0) {
101 while (*p == ' ') {
102 spaces++;
103 p++;
104 }
105 }
106
107 dst = *dst_;
108 while (*p != 0 && dst_len > 1) {
109 *dst++ = *p++;
110 dst_len--;
111 }
112 while (spaces > 0 && dst_len > 1) {
113 *dst++ = ' ';
114 spaces--;
115 dst_len--;
116 }
117 *dst = 0;
118 *dst_ = dst;
119}
120
121int parse_dec(const char **p_)
122{
123 const char *p = *p_;
124 int neg = 0;
125 int r = 0;
126
127 if (*p == '-') {
128 neg = 1;
129 p++;
130 }
131
132 while ('0' <= *p && *p <= '9') {
133 r = r * 10 + *p - '0';
134 p++;
135 }
136
137 *p_ = p;
138 return neg ? -r : r;
139}
140
141void g_fprintf(int fd, const char *fmt, ...)
142{
143 char buf[256], *d = buf;
144 const char *s = fmt;
145 int left = sizeof(buf);;
146 int justify;
147 int zeropad;
148 va_list ap;
149
150 va_start(ap, fmt);
151 while (*s != 0 && left > 1) {
152 if (*s != '%') {
153 *d++ = *s++;
154 left--;
155 continue;
156 }
157 s++;
158 if (*s == 0)
159 break;
160 if (*s == '%') {
161 *d++ = *s++;
162 left--;
163 continue;
164 }
165
166 zeropad = *s == '0';
167 justify = parse_dec(&s);
168 if (*s == 'l')
169 s++; // ignore for now
170 if (*s == 's') {
171 char *ns = va_arg(ap, char *);
172 int len = strlen(ns);
173 while (justify > len && left > 1) {
174 *d++ = ' ';
175 justify--;
176 left--;
177 }
178 if (len > left - 1) {
179 memcpy(d, ns, left - 1);
180 break;
181 }
182 memcpy(d, ns, len);
183 d += len;
184 left -= len;
185 while (justify < -len && left > 1) {
186 *d++ = ' ';
187 justify++;
188 left--;
189 }
190 s++;
191 continue;
192 }
193
194 format_number(&d, left, va_arg(ap, int), *s++, justify, zeropad);
195 }
196 *d = 0;
197 va_end(ap);
198
199 g_write_raw(fd, buf, d - buf);
200}
201
d0b9b0df 202// vim:shiftwidth=2:expandtab