clean calc
[calc.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 /* simple fprintf function */
34
35 int fdprintf (int fd, const char *fmt, ...)
36 {
37 char buffer[1024 + 1] = { 0 };
38 char *str = buffer;
39
40 va_list ap;
41 va_start (ap, fmt);
42 while (*fmt) {
43 char *s;
44 int d = 0;
45 unsigned int u;
46 char c = *fmt++;
47
48 /* copy standard char */
49 if (c != '%') {
50 *str++ = c;
51 } else {
52 int t = 0;
53 char w = '0';
54 int i, sz = 0;
55 void *p = NULL;
56
57 /* stamp */
58 if ((*fmt == ' ') || (*fmt == '0')) {
59 w = *fmt++;
60 }
61
62 /* size */
63 if ((*fmt >= '1') && (*fmt <= '9')) {
64 sz = *fmt++ - '0';
65 }
66
67 /* process format char */
68 switch (*fmt++) {
69 case 'c': /* char */
70 c = (char) va_arg (ap, int);
71 *str++ = c;
72 break;
73 case 'd': /* int */
74 d = va_arg (ap, int);
75 if (d < 0) {
76 *str++ = '-';
77 d = -d;
78 }
79 t = 1;
80 /* fall through */
81 case 'u': /* unsigned int */
82 u = (t) ? (unsigned int)d : va_arg (ap, unsigned int);
83 for (i = nextpow (u, 10), s = str; i > 0; i--, s++) {
84 str[i - 1] = '0' + (u % 10);
85 u /= 10;
86 }
87 str = s;
88 break;
89 case 'p': /* pointer */
90 *str++ = '0';
91 *str++ = 'x';
92 w = '0';
93 sz = sizeof (void *) * 2;
94 p = va_arg (ap, void *);
95 /* fall through */
96 case 'x': /* integer hexa */
97 if (!p) {
98 u = va_arg (ap, unsigned int);
99 if (sz == 0) {
100 sz = nextpow (u, 16);
101 }
102 } else {
103 u = (uintptr_t)p;
104 }
105 for (i = sz, t = 1; i > 0; i--) {
106 char x = (char)((u >> (i * 4 - 4)) & 0xf);
107 if ((t == 1) && (x == 0)) {
108 *str++ = w;
109 } else {
110 *str++ = (x > 9) ? 'a' + x - 10 : '0' + x;
111 t = 0;
112 }
113 }
114 break;
115 case 's': /* string */
116 s = va_arg (ap, char *);
117 while (s && *s)
118 *str++ = *s++;
119 break;
120 default:
121 *str++ = '?';
122 }
123 }
124 }
125 va_end (ap);
126
127 /* output string */
128 int n = str - buffer;
129 if (n < (int)sizeof (buffer) - 1) {
130 return write (fd, buffer, n);
131 }
132 return 0;
133 }
134
135 /* vim: set ts=4 sw=4 et: */