1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: utprint - Formatted printing routines
6 * Copyright (C) 2000 - 2020, Intel Corp.
8 *****************************************************************************/
10 #include <acpi/acpi.h>
13 #define _COMPONENT ACPI_UTILITIES
14 ACPI_MODULE_NAME("utprint")
16 #define ACPI_FORMAT_SIGN 0x01
17 #define ACPI_FORMAT_SIGN_PLUS 0x02
18 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
19 #define ACPI_FORMAT_ZERO 0x08
20 #define ACPI_FORMAT_LEFT 0x10
21 #define ACPI_FORMAT_UPPER 0x20
22 #define ACPI_FORMAT_PREFIX 0x40
23 /* Local prototypes */
25 acpi_ut_bound_string_length(const char *string
, acpi_size count
);
27 static char *acpi_ut_bound_string_output(char *string
, const char *end
, char c
);
29 static char *acpi_ut_format_number(char *string
,
32 u8 base
, s32 width
, s32 precision
, u8 type
);
34 static char *acpi_ut_put_number(char *string
, u64 number
, u8 base
, u8 upper
);
36 /*******************************************************************************
38 * FUNCTION: acpi_ut_bound_string_length
40 * PARAMETERS: string - String with boundary
41 * count - Boundary of the string
43 * RETURN: Length of the string. Less than or equal to Count.
45 * DESCRIPTION: Calculate the length of a string with boundary.
47 ******************************************************************************/
50 acpi_ut_bound_string_length(const char *string
, acpi_size count
)
54 while (*string
&& count
) {
63 /*******************************************************************************
65 * FUNCTION: acpi_ut_bound_string_output
67 * PARAMETERS: string - String with boundary
68 * end - Boundary of the string
69 * c - Character to be output to the string
71 * RETURN: Updated position for next valid character
73 * DESCRIPTION: Output a character into a string with boundary check.
75 ******************************************************************************/
77 static char *acpi_ut_bound_string_output(char *string
, const char *end
, char c
)
88 /*******************************************************************************
90 * FUNCTION: acpi_ut_put_number
92 * PARAMETERS: string - Buffer to hold reverse-ordered string
93 * number - Integer to be converted
94 * base - Base of the integer
95 * upper - Whether or not using upper cased digits
97 * RETURN: Updated position for next valid character
99 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
100 * reversed ordered number without the trailing zero.
102 ******************************************************************************/
104 static char *acpi_ut_put_number(char *string
, u64 number
, u8 base
, u8 upper
)
111 digits
= upper
? acpi_gbl_upper_hex_digits
: acpi_gbl_lower_hex_digits
;
117 (void)acpi_ut_divide(number
, base
, &number
,
119 *(pos
++) = digits
[digit_index
];
123 /* *(Pos++) = '0'; */
127 /*******************************************************************************
129 * FUNCTION: acpi_ut_scan_number
131 * PARAMETERS: string - String buffer
132 * number_ptr - Where the number is returned
134 * RETURN: Updated position for next valid character
136 * DESCRIPTION: Scan a string for a decimal integer.
138 ******************************************************************************/
140 const char *acpi_ut_scan_number(const char *string
, u64
*number_ptr
)
144 while (isdigit((int)*string
)) {
145 acpi_ut_short_multiply(number
, 10, &number
);
146 number
+= *(string
++) - '0';
149 *number_ptr
= number
;
153 /*******************************************************************************
155 * FUNCTION: acpi_ut_print_number
157 * PARAMETERS: string - String buffer
158 * number - The number to be converted
160 * RETURN: Updated position for next valid character
162 * DESCRIPTION: Print a decimal integer into a string.
164 ******************************************************************************/
166 const char *acpi_ut_print_number(char *string
, u64 number
)
168 char ascii_string
[20];
172 pos1
= acpi_ut_put_number(ascii_string
, number
, 10, FALSE
);
175 while (pos1
!= ascii_string
) {
176 *(pos2
++) = *(--pos1
);
183 /*******************************************************************************
185 * FUNCTION: acpi_ut_format_number
187 * PARAMETERS: string - String buffer with boundary
188 * end - Boundary of the string
189 * number - The number to be converted
190 * base - Base of the integer
191 * width - Field width
192 * precision - Precision of the integer
193 * type - Special printing flags
195 * RETURN: Updated position for next valid character
197 * DESCRIPTION: Print an integer into a string with any base and any precision.
199 ******************************************************************************/
201 static char *acpi_ut_format_number(char *string
,
204 u8 base
, s32 width
, s32 precision
, u8 type
)
212 char reversed_string
[66];
214 /* Parameter validation */
216 if (base
< 2 || base
> 16) {
220 if (type
& ACPI_FORMAT_LEFT
) {
221 type
&= ~ACPI_FORMAT_ZERO
;
224 need_prefix
= ((type
& ACPI_FORMAT_PREFIX
)
225 && base
!= 10) ? TRUE
: FALSE
;
226 upper
= (type
& ACPI_FORMAT_UPPER
) ? TRUE
: FALSE
;
227 zero
= (type
& ACPI_FORMAT_ZERO
) ? '0' : ' ';
229 /* Calculate size according to sign and prefix */
232 if (type
& ACPI_FORMAT_SIGN
) {
233 if ((s64
)number
< 0) {
235 number
= -(s64
)number
;
237 } else if (type
& ACPI_FORMAT_SIGN_PLUS
) {
240 } else if (type
& ACPI_FORMAT_SIGN_PLUS_SPACE
) {
252 /* Generate full string in reverse order */
254 pos
= acpi_ut_put_number(reversed_string
, number
, base
, upper
);
255 i
= (s32
)ACPI_PTR_DIFF(pos
, reversed_string
);
257 /* Printing 100 using %2d gives "100", not "00" */
265 /* Output the string */
267 if (!(type
& (ACPI_FORMAT_ZERO
| ACPI_FORMAT_LEFT
))) {
268 while (--width
>= 0) {
269 string
= acpi_ut_bound_string_output(string
, end
, ' ');
273 string
= acpi_ut_bound_string_output(string
, end
, sign
);
276 string
= acpi_ut_bound_string_output(string
, end
, '0');
279 acpi_ut_bound_string_output(string
, end
,
283 if (!(type
& ACPI_FORMAT_LEFT
)) {
284 while (--width
>= 0) {
285 string
= acpi_ut_bound_string_output(string
, end
, zero
);
289 while (i
<= --precision
) {
290 string
= acpi_ut_bound_string_output(string
, end
, '0');
293 string
= acpi_ut_bound_string_output(string
, end
,
296 while (--width
>= 0) {
297 string
= acpi_ut_bound_string_output(string
, end
, ' ');
303 /*******************************************************************************
305 * FUNCTION: vsnprintf
307 * PARAMETERS: string - String with boundary
308 * size - Boundary of the string
309 * format - Standard printf format
310 * args - Argument list
312 * RETURN: Number of bytes actually written.
314 * DESCRIPTION: Formatted output to a string using argument list pointer.
316 ******************************************************************************/
318 int vsnprintf(char *string
, acpi_size size
, const char *format
, va_list args
)
336 if (size
!= ACPI_UINT32_MAX
) {
339 end
= ACPI_CAST_PTR(char, ACPI_UINT32_MAX
);
342 for (; *format
; ++format
) {
343 if (*format
!= '%') {
344 pos
= acpi_ut_bound_string_output(pos
, end
, *format
);
355 if (*format
== '#') {
356 type
|= ACPI_FORMAT_PREFIX
;
357 } else if (*format
== '0') {
358 type
|= ACPI_FORMAT_ZERO
;
359 } else if (*format
== '+') {
360 type
|= ACPI_FORMAT_SIGN_PLUS
;
361 } else if (*format
== ' ') {
362 type
|= ACPI_FORMAT_SIGN_PLUS_SPACE
;
363 } else if (*format
== '-') {
364 type
|= ACPI_FORMAT_LEFT
;
374 if (isdigit((int)*format
)) {
375 format
= acpi_ut_scan_number(format
, &number
);
377 } else if (*format
== '*') {
379 width
= va_arg(args
, int);
382 type
|= ACPI_FORMAT_LEFT
;
386 /* Process precision */
389 if (*format
== '.') {
391 if (isdigit((int)*format
)) {
392 format
= acpi_ut_scan_number(format
, &number
);
393 precision
= (s32
)number
;
394 } else if (*format
== '*') {
396 precision
= va_arg(args
, int);
404 /* Process qualifier */
407 if (*format
== 'h' || *format
== 'l' || *format
== 'L') {
411 if (qualifier
== 'l' && *format
== 'l') {
420 pos
= acpi_ut_bound_string_output(pos
, end
, '%');
425 if (!(type
& ACPI_FORMAT_LEFT
)) {
426 while (--width
> 0) {
428 acpi_ut_bound_string_output(pos
,
434 c
= (char)va_arg(args
, int);
435 pos
= acpi_ut_bound_string_output(pos
, end
, c
);
437 while (--width
> 0) {
439 acpi_ut_bound_string_output(pos
, end
, ' ');
445 s
= va_arg(args
, char *);
449 length
= (s32
)acpi_ut_bound_string_length(s
, precision
);
450 if (!(type
& ACPI_FORMAT_LEFT
)) {
451 while (length
< width
--) {
453 acpi_ut_bound_string_output(pos
,
459 for (i
= 0; i
< length
; ++i
) {
460 pos
= acpi_ut_bound_string_output(pos
, end
, *s
);
464 while (length
< width
--) {
466 acpi_ut_bound_string_output(pos
, end
, ' ');
477 type
|= ACPI_FORMAT_UPPER
;
488 type
|= ACPI_FORMAT_SIGN
;
497 width
= 2 * sizeof(void *);
498 type
|= ACPI_FORMAT_ZERO
;
501 p
= va_arg(args
, void *);
503 acpi_ut_format_number(pos
, end
, ACPI_TO_INTEGER(p
),
504 16, width
, precision
, type
);
509 pos
= acpi_ut_bound_string_output(pos
, end
, '%');
512 acpi_ut_bound_string_output(pos
, end
,
520 if (qualifier
== 'L') {
521 number
= va_arg(args
, u64
);
522 if (type
& ACPI_FORMAT_SIGN
) {
523 number
= (s64
)number
;
525 } else if (qualifier
== 'l') {
526 number
= va_arg(args
, unsigned long);
527 if (type
& ACPI_FORMAT_SIGN
) {
528 number
= (s32
)number
;
530 } else if (qualifier
== 'h') {
531 number
= (u16
)va_arg(args
, int);
532 if (type
& ACPI_FORMAT_SIGN
) {
533 number
= (s16
)number
;
536 number
= va_arg(args
, unsigned int);
537 if (type
& ACPI_FORMAT_SIGN
) {
538 number
= (signed int)number
;
542 pos
= acpi_ut_format_number(pos
, end
, number
, base
,
543 width
, precision
, type
);
554 return ((int)ACPI_PTR_DIFF(pos
, string
));
557 /*******************************************************************************
561 * PARAMETERS: string - String with boundary
562 * size - Boundary of the string
563 * Format, ... - Standard printf format
565 * RETURN: Number of bytes actually written.
567 * DESCRIPTION: Formatted output to a string.
569 ******************************************************************************/
571 int snprintf(char *string
, acpi_size size
, const char *format
, ...)
576 va_start(args
, format
);
577 length
= vsnprintf(string
, size
, format
, args
);
583 /*******************************************************************************
587 * PARAMETERS: string - String with boundary
588 * Format, ... - Standard printf format
590 * RETURN: Number of bytes actually written.
592 * DESCRIPTION: Formatted output to a string.
594 ******************************************************************************/
596 int sprintf(char *string
, const char *format
, ...)
601 va_start(args
, format
);
602 length
= vsnprintf(string
, ACPI_UINT32_MAX
, format
, args
);
608 #ifdef ACPI_APPLICATION
609 /*******************************************************************************
613 * PARAMETERS: format - Standard printf format
614 * args - Argument list
616 * RETURN: Number of bytes actually written.
618 * DESCRIPTION: Formatted output to stdout using argument list pointer.
620 ******************************************************************************/
622 int vprintf(const char *format
, va_list args
)
624 acpi_cpu_flags flags
;
627 flags
= acpi_os_acquire_lock(acpi_gbl_print_lock
);
628 length
= vsnprintf(acpi_gbl_print_buffer
,
629 sizeof(acpi_gbl_print_buffer
), format
, args
);
631 (void)fwrite(acpi_gbl_print_buffer
, length
, 1, ACPI_FILE_OUT
);
632 acpi_os_release_lock(acpi_gbl_print_lock
, flags
);
637 /*******************************************************************************
641 * PARAMETERS: Format, ... - Standard printf format
643 * RETURN: Number of bytes actually written.
645 * DESCRIPTION: Formatted output to stdout.
647 ******************************************************************************/
649 int printf(const char *format
, ...)
654 va_start(args
, format
);
655 length
= vprintf(format
, args
);
661 /*******************************************************************************
665 * PARAMETERS: file - File descriptor
666 * format - Standard printf format
667 * args - Argument list
669 * RETURN: Number of bytes actually written.
671 * DESCRIPTION: Formatted output to a file using argument list pointer.
673 ******************************************************************************/
675 int vfprintf(FILE * file
, const char *format
, va_list args
)
677 acpi_cpu_flags flags
;
680 flags
= acpi_os_acquire_lock(acpi_gbl_print_lock
);
681 length
= vsnprintf(acpi_gbl_print_buffer
,
682 sizeof(acpi_gbl_print_buffer
), format
, args
);
684 (void)fwrite(acpi_gbl_print_buffer
, length
, 1, file
);
685 acpi_os_release_lock(acpi_gbl_print_lock
, flags
);
690 /*******************************************************************************
694 * PARAMETERS: file - File descriptor
695 * Format, ... - Standard printf format
697 * RETURN: Number of bytes actually written.
699 * DESCRIPTION: Formatted output to a file.
701 ******************************************************************************/
703 int fprintf(FILE * file
, const char *format
, ...)
708 va_start(args
, format
);
709 length
= vfprintf(file
, format
, args
);