unset ld env before running command
[ginge.git] / loader / llibc.c
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
15 static 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
121 int 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
141 void 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' || *s == 'z')
169       s++; // ignore for now
170     if (*s == 's') {
171       const char *ns = va_arg(ap, const char *);
172       if (ns == NULL)
173         ns = "(null)";
174       int len = strlen(ns);
175       while (justify > len && left > 1) {
176         *d++ = ' ';
177         justify--;
178         left--;
179       }
180       if (len > left - 1) {
181         memcpy(d, ns, left - 1);
182         break;
183       }
184       memcpy(d, ns, len);
185       d += len;
186       left -= len;
187       while (justify < -len && left > 1) {
188         *d++ = ' ';
189         justify++;
190         left--;
191       }
192       s++;
193       continue;
194     }
195
196     format_number(&d, left, va_arg(ap, int), *s++, justify, zeropad);
197   }
198   *d = 0;
199   va_end(ap);
200
201   g_write_raw(fd, buf, d - buf);
202 }
203
204 // vim:shiftwidth=2:expandtab