+/*
+ File name : fprintf.c
+ Date of creation : 05/12/2022
+ Version : 1.0
+ Copyright : Soft'n'design
+ Author : Laurent Mazet <mazet@softndesign.org>
+
+ Description : This file contains embedded printf
+
+ History :
+ - initial version
+*/
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+
+inline unsigned int nextpow10 (unsigned int x) {
+ unsigned int n = 0;
+ while (x) {
+ n++;
+ x = x / 10;
+ }
+ return (n == 0) ? 1 : n;
+}
+
+/* simple fprintf function */
+
+size_t _fprintf (FILE *fid, const char *fmt, ...)
+{
+ char buffer[1024 + 1] = { 0 };
+ char *str = buffer;
+
+ va_list ap;
+ va_start (ap, fmt);
+ while (*fmt) {
+ char *s;
+ int d = 0;
+ unsigned int u;
+ void *p;
+ char c = *fmt++;
+
+ /* copy standard char */
+ if (c != '%') {
+ *str++ = c;
+ } else {
+ int t = 0;
+ size_t i;
+
+ /* process format char */
+ switch (*fmt++) {
+ case 'c': /* char */
+ c = (char) va_arg (ap, int);
+ *str++ = c;
+ break;
+ case 'd': /* int */
+ d = va_arg (ap, int);
+ if (d < 0) {
+ *str++ = '-';
+ d = -d;
+ }
+ t = 1;
+ /* fall through */
+ case 'u': /* unsigned int */
+ u = (t) ? (unsigned int)d : va_arg (ap, unsigned int);
+ for (i = nextpow10 (u), s = str; i > 0; i--, s++) {
+ str[i - 1] = '0' + (u % 10);
+ u /= 10;
+ }
+ str = s;
+ break;
+ case 'p': /* pointer */
+ p = va_arg (ap, void *);
+ *str++ = '0';
+ *str++ = 'x';
+ for (i = sizeof (void *) * 2; i > 0; i--) {
+ char x = (char)(((uintptr_t)p >> (i * 4 - 4)) & 0xf);
+ *str++ = (x > 9) ? 'a' + x - 10 : '0' + x;
+ }
+ break;
+ case 's': /* string */
+ s = va_arg (ap, char *);
+ while (s && *s)
+ *str++ = *s++;
+ break;
+ default:
+ *str++ = '?';
+ }
+ }
+ }
+ va_end (ap);
+
+ /* output string */
+ size_t n = str - buffer;
+ if (n < sizeof (buffer) - 1) {
+ fwrite (buffer, n, 1, fid);
+ return n;
+ }
+ return 0;
+}
+
+/* vim: set ts=4 sw=4 et */