remove skeleton file
[ascii.git] / fdprintf.c
1 /*
2 File name : fprintf.c
3 Date of creation : 05/12/2022
4 Version : 1.0
5 Copyright : Soft'n'design
6 Author : Laurent Mazet <mazet@softndesign.org>
7
8 Description : This file contains embedded printf
9
10 History :
11 - initial version
12 */
13
14 #include <stdarg.h>
15 #include <stdint.h>
16 #include <unistd.h>
17
18 #include "fdprintf.h"
19
20 int stdfdin = STDIN_FILENO;
21 int stdfdout = STDOUT_FILENO;
22 int stdfderr = STDERR_FILENO;
23
24 unsigned int nextpow (unsigned int x, int base) {
25 unsigned int n = 0;
26 while (x) {
27 n++;
28 x = x / base;
29 }
30 return (n == 0) ? 1 : n;
31 }
32
33 char *itoa (char *str, unsigned u, unsigned int sz)
34 {
35 unsigned int i = (sz == 0 ) ? nextpow (u, 10) : sz;
36 char *s = str;
37 while (i > 0) {
38 str[i - 1] = '0' + (u % 10);
39 u /= 10;
40 i--;
41 s++;
42 }
43 return s;
44 }
45
46 double tenpower(int n)
47 {
48 double t = 1.0;
49 int i;
50 for (i = 0; i < n; i++) {
51 t *= 10;
52 }
53 for (i = 0; i > n; i--) {
54 t /= 10;
55 }
56 return t;
57 }
58
59 int getexponant (double *f, int maxexp)
60 {
61 int exp = 0;
62 while (*f > 10) {
63 *f /= 10;
64 exp++;
65 }
66 while (*f < 1) {
67 *f *= 10;
68 exp--;
69 }
70 *f += tenpower (maxexp - 1);
71 if (*f >= 10) {
72 *f /= 10;
73 exp++;
74 }
75
76 return exp;
77 }
78 /* simple fprintf function */
79
80 int fdprintf (int fd, const char *fmt, ...)
81 {
82 char buffer[1024 + 1] = { 0 };
83 char *str = buffer;
84
85 va_list ap;
86 va_start (ap, fmt);
87 while (*fmt) {
88 char *s;
89 double f = 0.0;
90 int d = 0;
91 unsigned int u;
92 char c = *fmt++;
93
94 /* copy standard char */
95 if (c != '%') {
96 *str++ = c;
97 } else {
98 int t = 0;
99 char w = '0';
100 int i, sz = 0;
101 void *p = NULL;
102
103 /* stamp */
104 if ((*fmt == ' ') || (*fmt == '0')) {
105 w = *fmt++;
106 }
107
108 /* size */
109 if ((*fmt >= '1') && (*fmt <= '9')) {
110 sz = *fmt++ - '0';
111 }
112
113 /* process format char */
114 switch (*fmt++) {
115 case '%': /* percent */
116 *str++ = '%';
117 break;
118 case 'c': /* char */
119 c = (char) va_arg (ap, int);
120 *str++ = c;
121 break;
122 case 'd': /* int */
123 d = va_arg (ap, int);
124 if (d < 0) {
125 *str++ = '-';
126 d = -d;
127 }
128 t = 1;
129 /* fall through */
130 case 'u': /* unsigned int */
131 str = itoa (str, (t) ? (unsigned int)d : va_arg (ap, unsigned int), 0);
132 break;
133 case 'f': /* float */
134 f = va_arg (ap, double);
135 if (f == 0) {
136 *str++ = '0';
137 break;
138 }
139 if (f < 0) {
140 *str++ = '-';
141 f = -f;
142 }
143 if (sz == 0) sz = 6;
144 t = getexponant (&f, -sz);
145 u = (int)f;
146 str = itoa (str, u, 0);
147 d = (int)((f - u) * tenpower (sz));
148 if (d > 0) {
149 *str++ = '.';
150 str = itoa (str, d, sz);
151 }
152 while (*(str - 1) == '0') {
153 str--;
154 }
155 if (t != 0) {
156 *str++ = 'e';
157 if (t < 0) {
158 *str++ = '-';
159 t = -t;
160 }
161 str = itoa (str, t, 0);
162 }
163 break;
164 case 'p': /* pointer */
165 *str++ = '0';
166 *str++ = 'x';
167 w = '0';
168 sz = sizeof (void *) * 2;
169 p = va_arg (ap, void *);
170 /* fall through */
171 case 'x': /* integer hexa */
172 if (!p) {
173 u = va_arg (ap, unsigned int);
174 if (sz == 0) {
175 sz = nextpow (u, 16);
176 }
177 } else {
178 u = (uintptr_t)p;
179 }
180 for (i = sz, t = 1; i > 0; i--) {
181 char x = (char)((u >> (i * 4 - 4)) & 0xf);
182 if ((t == 1) && (x == 0)) {
183 *str++ = w;
184 } else {
185 *str++ = (x > 9) ? 'a' + x - 10 : '0' + x;
186 t = 0;
187 }
188 }
189 break;
190 case 's': /* string */
191 s = va_arg (ap, char *);
192 while (s && *s)
193 *str++ = *s++;
194 break;
195 default:
196 *str++ = '?';
197 }
198 }
199 }
200 va_end (ap);
201
202 /* output string */
203 int n = str - buffer;
204 if (n < (int)sizeof (buffer) - 1) {
205 return write (fd, buffer, n);
206 }
207 return 0;
208 }
209
210 /* vim: set ts=4 sw=4 et: */