Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / tests / tcg / minilib / printf.c
blob10472b4f5852041d03d1567518ebde1b0591e50a
1 /*
2 * Copyright (C) 2015 Virtual Open Systems SAS
3 * Author: Alexander Spyridakis <a.spyridakis@virtualopensystems.com>
5 * printf based on implementation by Kevin Wolf <kwolf@redhat.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * SPDX-License-Identifier: GPL-2.0-only
14 #include "minilib.h"
16 typedef __builtin_va_list va_list;
17 #define va_start(ap, X) __builtin_va_start(ap, X)
18 #define va_arg(ap, type) __builtin_va_arg(ap, type)
19 #define va_end(ap) __builtin_va_end(ap)
21 static void print_str(char *s)
23 while (*s) {
24 __sys_outc(*s++);
28 static void print_num(unsigned long long value, int base)
30 char digits[] = "0123456789abcdef";
31 char buf[32];
32 int i = sizeof(buf) - 2, j;
34 /* Set the buffer to 0. See problem of before. */
35 for (j = 0; j < 32; j++) {
36 buf[j] = 0;
39 do {
40 buf[i--] = digits[value % base];
41 value /= base;
42 } while (value);
44 print_str(&buf[i + 1]);
47 void ml_printf(const char *fmt, ...)
49 va_list ap;
50 char *str;
51 int base;
52 int has_long;
53 int alt_form;
54 unsigned long long val;
56 va_start(ap, fmt);
58 for (; *fmt; fmt++) {
59 if (*fmt != '%') {
60 __sys_outc(*fmt);
61 continue;
63 fmt++;
65 if (*fmt == '#') {
66 fmt++;
67 alt_form = 1;
68 } else {
69 alt_form = 0;
72 if (*fmt == 'l') {
73 fmt++;
74 if (*fmt == 'l') {
75 fmt++;
76 has_long = 2;
77 } else {
78 has_long = 1;
80 } else {
81 has_long = 0;
84 switch (*fmt) {
85 case 'x':
86 case 'p':
87 base = 16;
88 goto convert_number;
89 case 'd':
90 case 'i':
91 case 'u':
92 base = 10;
93 goto convert_number;
94 case 'o':
95 base = 8;
96 goto convert_number;
98 convert_number:
99 switch (has_long) {
100 case 0:
101 val = va_arg(ap, unsigned int);
102 break;
103 case 1:
104 val = va_arg(ap, unsigned long);
105 break;
106 case 2:
107 val = va_arg(ap, unsigned long long);
108 break;
111 if (alt_form && base == 16) {
112 print_str("0x");
115 print_num(val, base);
116 break;
118 case 's':
119 str = va_arg(ap, char*);
120 print_str(str);
121 break;
122 case 'c':
123 __sys_outc(va_arg(ap, int));
124 break;
125 case '%':
126 __sys_outc(*fmt);
127 break;
128 default:
129 __sys_outc('%');
130 __sys_outc(*fmt);
131 break;
135 va_end(ap);