preliminary version
[calc.git] / fdprintf.c
CommitLineData
1968fc94
LM
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
01f02c41 20int stdfdin = STDIN_FILENO;
a8476deb
LM
21int stdfdout = STDOUT_FILENO;
22int stdfderr = STDERR_FILENO;
1968fc94
LM
23
24unsigned 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
95834c7b
LM
33char *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
1968fc94
LM
46/* simple fprintf function */
47
48int fdprintf (int fd, const char *fmt, ...)
49{
50 char buffer[1024 + 1] = { 0 };
51 char *str = buffer;
52
53 va_list ap;
54 va_start (ap, fmt);
55 while (*fmt) {
56 char *s;
95834c7b 57 double f = 0.0;
1968fc94
LM
58 int d = 0;
59 unsigned int u;
60 char c = *fmt++;
61
62 /* copy standard char */
63 if (c != '%') {
64 *str++ = c;
65 } else {
66 int t = 0;
95834c7b 67 char w = '0';
1968fc94
LM
68 int i, sz = 0;
69 void *p = NULL;
70
71 /* stamp */
72 if ((*fmt == ' ') || (*fmt == '0')) {
73 w = *fmt++;
74 }
75
76 /* size */
77 if ((*fmt >= '1') && (*fmt <= '9')) {
78 sz = *fmt++ - '0';
79 }
80
81 /* process format char */
82 switch (*fmt++) {
83 case 'c': /* char */
84 c = (char) va_arg (ap, int);
85 *str++ = c;
86 break;
87 case 'd': /* int */
88 d = va_arg (ap, int);
89 if (d < 0) {
90 *str++ = '-';
91 d = -d;
92 }
93 t = 1;
94 /* fall through */
95 case 'u': /* unsigned int */
95834c7b
LM
96 str = itoa (str, (t) ? (unsigned int)d : va_arg (ap, unsigned int), 0);
97 break;
98 case 'f': /* float */
99 f = va_arg (ap, double);
100 if (f < 0) {
101 *str++ = '-';
102 f = -f;
103 }
104 t = 0;
105 while (f > 10) {
106 f /= 10;
107 t++;
108 }
109 while (f < 1) {
110 f *= 10;
111 t--;
112 }
113 f += 1e-7;
114 if (f >= 10) {
115 f /= 10;
116 t++;
117 }
118 u = (int)f;
119 str = itoa (str, u, 0);
120 d = (int)((f - u) * 1e6);
121 if (d > 0) {
122 *str++ = '.';
123 str = itoa (str, d, 6);
124 }
125 if (t != 0) {
126 *str++ = 'e';
127 if (t < 0) {
128 *str++ = '-';
129 t = -t;
130 }
131 str = itoa (str, t, 0);
1968fc94 132 }
1968fc94
LM
133 break;
134 case 'p': /* pointer */
135 *str++ = '0';
136 *str++ = 'x';
137 w = '0';
138 sz = sizeof (void *) * 2;
139 p = va_arg (ap, void *);
140 /* fall through */
141 case 'x': /* integer hexa */
142 if (!p) {
143 u = va_arg (ap, unsigned int);
144 if (sz == 0) {
145 sz = nextpow (u, 16);
146 }
147 } else {
148 u = (uintptr_t)p;
149 }
150 for (i = sz, t = 1; i > 0; i--) {
151 char x = (char)((u >> (i * 4 - 4)) & 0xf);
152 if ((t == 1) && (x == 0)) {
153 *str++ = w;
154 } else {
155 *str++ = (x > 9) ? 'a' + x - 10 : '0' + x;
156 t = 0;
157 }
158 }
159 break;
160 case 's': /* string */
161 s = va_arg (ap, char *);
162 while (s && *s)
163 *str++ = *s++;
164 break;
165 default:
166 *str++ = '?';
167 }
168 }
169 }
170 va_end (ap);
171
172 /* output string */
173 int n = str - buffer;
174 if (n < (int)sizeof (buffer) - 1) {
175 return write (fd, buffer, n);
176 }
177 return 0;
178}
179
180/* vim: set ts=4 sw=4 et: */