libpayload: avoid excessive casts in printf.c
[coreboot.git] / payloads / libpayload / libc / printf.c
index 2f1ca8bda6b31bc24c1b4f9c7a3b4487f9e1a198..ccb64fd67833a2f48d2d452c1c51941281f46d82 100644 (file)
  */
 
 #include <libpayload.h>
+#include <ctype.h>
+
+static struct _FILE {
+} _stdout, _stdin, _stderr;
+
+FILE *stdout = &_stdout;
+FILE *stdin = &_stdin;
+FILE *stderr = &_stderr;
 
 /** Structure for specifying output methods for different printf clones. */
 struct printf_spec {
        /* Output function, returns count of printed characters or EOF. */
-       int (*write) (void *, size_t, void *);
+       int (*write) (const char *, size_t, void *);
        /* Support data - output stream specification, its state, locks, ... */
        void *data;
 };
@@ -77,8 +85,8 @@ typedef enum {
        PrintfQualifierPointer,
 } qualifier_t;
 
-static char digits_small[] = "0123456789abcdef";
-static char digits_big[] = "0123456789ABCDEF";
+static const char digits_small[] = "0123456789abcdef";
+static const char digits_big[] = "0123456789ABCDEF";
 
 /**
  * Print one or more characters without adding newline.
@@ -91,7 +99,7 @@ static char digits_big[] = "0123456789ABCDEF";
 static int printf_putnchars(const char *buf, size_t count,
                            struct printf_spec *ps)
 {
-       return ps->write((void *)buf, count, ps->data);
+       return ps->write(buf, count, ps->data);
 }
 
 /**
@@ -101,18 +109,9 @@ static int printf_putnchars(const char *buf, size_t count,
  * @param ps   Write function specification and support data.
  * @return     Number of characters printed.
  */
-static int printf_putstr(const char *str, struct printf_spec *ps)
+static inline int printf_putstr(const char *str, struct printf_spec *ps)
 {
-       size_t count;
-
-       if (str == NULL) {
-               char *nullstr = "(NULL)";
-               return printf_putnchars(nullstr, strlen(nullstr), ps);
-       }
-
-       count = strlen(str);
-
-       return ps->write((void *)str, count, ps->data);
+       return printf_putnchars(str, strlen(str), ps);
 }
 
 /**
@@ -124,9 +123,9 @@ static int printf_putstr(const char *str, struct printf_spec *ps)
  */
 static int printf_putchar(int c, struct printf_spec *ps)
 {
-       unsigned char ch = c;
+       char ch = c;
 
-       return ps->write((void *)&ch, 1, ps->data);
+       return ps->write(&ch, 1, ps->data);
 }
 
 /**
@@ -135,6 +134,7 @@ static int printf_putchar(int c, struct printf_spec *ps)
  * @param c    Character to print.
  * @param width        Width modifier.
  * @param flags        Flags that change the way the character is printed.
+ * @param ps   Output methods spec for different printf clones.
  * @return     Number of characters printed, negative value on failure.
  */
 static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps)
@@ -156,7 +156,7 @@ static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps)
                        ++counter;
        }
 
-       return ++counter;
+       return counter;
 }
 
 /**
@@ -166,8 +166,10 @@ static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps)
  * @param width                Width modifier.
  * @param precision    Precision modifier.
  * @param flags                Flags that modify the way the string is printed.
+ * @param ps           Output methods spec for different printf clones.
  * @return             Number of characters printed, negative value on failure.
  */
+/** Structure for specifying output methods for different printf clones. */
 static int print_string(char *s, int width, unsigned int precision,
                        uint64_t flags, struct printf_spec *ps)
 {
@@ -207,16 +209,17 @@ static int print_string(char *s, int width, unsigned int precision,
  * Print significant digits of a number in given base.
  *
  * @param num          Number to print.
- * @param widt         Width modifier.h
+ * @param width                Width modifier.h
  * @param precision    Precision modifier.
  * @param base         Base to print the number in (must be between 2 and 16).
  * @param flags                Flags that modify the way the number is printed.
+ * @param ps           Output methods spec for different printf clones.
  * @return             Number of characters printed.
  */
 static int print_number(uint64_t num, int width, int precision, int base,
                        uint64_t flags, struct printf_spec *ps)
 {
-       char *digits = digits_small;
+       const char *digits = digits_small;
        char d[PRINT_NUMBER_BUFFER_SIZE];
        char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
        int size = 0;           /* Size of number with all prefixes and signs. */
@@ -359,11 +362,12 @@ static int print_number(uint64_t num, int width, int precision, int base,
        return counter;
 }
 
-/** Print formatted string.
+/**
+ * Print formatted string.
  *
  * Print string formatted according to the fmt parameter and variadic arguments.
  * Each formatting directive must have the following form:
- * 
+ *
  *     \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
  *
  * FLAGS:@n
@@ -381,7 +385,7 @@ static int print_number(uint64_t num, int width, int precision, int base,
  *     - "0"   Print 0 as padding instead of spaces. Zeroes are placed between
  *             sign and the rest of the number. This flag is ignored if "-"
  *             flag is specified.
- * 
+ *
  * WIDTH:@n
  *     - Specify the minimal width of a printed argument. If it is bigger,
  *     width is ignored. If width is specified with a "*" character instead of
@@ -398,15 +402,15 @@ static int print_number(uint64_t num, int width, int precision, int base,
  *     value is then expected in parameters. When both width and precision are
  *     specified using "*", the first parameter is used for width and the
  *     second one for precision.
- * 
+ *
  * TYPE:@n
  *     - "hh"  Signed or unsigned char.@n
  *     - "h"   Signed or unsigned short.@n
  *     - ""    Signed or unsigned int (default value).@n
  *     - "l"   Signed or unsigned long int.@n
  *     - "ll"  Signed or unsigned long long int.@n
- * 
- * 
+ *
+ *
  * CONVERSION:@n
  *     - %     Print percentile character itself.
  *
@@ -414,16 +418,16 @@ static int print_number(uint64_t num, int width, int precision, int base,
  *
  *     - s     Print zero terminated string. If a NULL value is passed as
  *             value, "(NULL)" is printed instead.
- * 
+ *
  *     - P, p  Print value of a pointer. Void * value is expected and it is
  *             printed in hexadecimal notation with prefix (as with \%#X / \%#x
  *             for 32-bit or \%#X / \%#x for 64-bit long pointers).
  *
  *     - b     Print value as unsigned binary number. Prefix is not printed by
  *             default. (Nonstandard extension.)
- * 
+ *
  *     - o     Print value as unsigned octal number. Prefix is not printed by
- *             default. 
+ *             default.
  *
  *     - d, i  Print signed decimal number. There is no difference between d
  *             and i conversion.
@@ -432,7 +436,7 @@ static int print_number(uint64_t num, int width, int precision, int base,
  *
  *     - X, x  Print hexadecimal number with upper- or lower-case. Prefix is
  *             not printed by default.
- * 
+ *
  * All other characters from fmt except the formatting directives are printed in
  * verbatim.
  *
@@ -717,6 +721,20 @@ int sprintf(char *str, const char *fmt, ...)
        return ret;
 }
 
+int fprintf(FILE *file, const char *fmt, ...)
+{
+       int ret;
+       if ((file == stdout) || (file == stderr)) {
+               va_list args;
+               va_start(args, fmt);
+               ret = vprintf(fmt, args);
+               va_end(args);
+
+               return ret;
+       }
+       return -1;
+}
+
 struct vsnprintf_data {
        size_t size;            /* Total space for string */
        size_t len;             /* Count of currently used characters */
@@ -734,13 +752,13 @@ struct vsnprintf_data {
  *
  * @param str  Source string to print.
  * @param count        Size of source string.
- * @param data Structure with destination string, counter of used space
+ * @param _data        Structure with destination string, counter of used space
  *              and total string size.
  * @return Number of characters to print (not characters really printed!).
  */
-static int vsnprintf_write(const char *str, size_t count,
-                          struct vsnprintf_data *data)
+static int vsnprintf_write(const char *str, size_t count, void *_data)
 {
+       struct vsnprintf_data *data = _data;
        size_t i;
 
        i = data->size - data->len;
@@ -780,8 +798,7 @@ static int vsnprintf_write(const char *str, size_t count,
 int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
 {
        struct vsnprintf_data data = { size, 0, str };
-       struct printf_spec ps =
-           { (int (*)(void *, size_t, void *))vsnprintf_write, &data };
+       struct printf_spec ps = { vsnprintf_write, &data };
 
        /* Print 0 at end of string - fix case that nothing will be printed. */
        if (size > 0)
@@ -820,8 +837,7 @@ static int vprintf_write(const char *str, size_t count, void *unused)
 
 int vprintf(const char *fmt, va_list ap)
 {
-       struct printf_spec ps =
-           { (int (*)(void *, size_t, void *))vprintf_write, NULL };
+       struct printf_spec ps = { vprintf_write, NULL };
 
        return printf_core(fmt, &ps, ap);
 }