1 /******************************************************************************
3 * Module Name: utprint - Formatted printing routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2015, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
44 #include <acpi/acpi.h>
47 #define _COMPONENT ACPI_UTILITIES
48 ACPI_MODULE_NAME("utprint")
50 #define ACPI_FORMAT_SIGN 0x01
51 #define ACPI_FORMAT_SIGN_PLUS 0x02
52 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
53 #define ACPI_FORMAT_ZERO 0x08
54 #define ACPI_FORMAT_LEFT 0x10
55 #define ACPI_FORMAT_UPPER 0x20
56 #define ACPI_FORMAT_PREFIX 0x40
57 /* Local prototypes */
59 acpi_ut_bound_string_length(const char *string
, acpi_size count
);
61 static char *acpi_ut_bound_string_output(char *string
, const char *end
, char c
);
63 static char *acpi_ut_format_number(char *string
,
66 u8 base
, s32 width
, s32 precision
, u8 type
);
68 static char *acpi_ut_put_number(char *string
, u64 number
, u8 base
, u8 upper
);
72 static const char acpi_gbl_lower_hex_digits
[] = "0123456789abcdef";
73 static const char acpi_gbl_upper_hex_digits
[] = "0123456789ABCDEF";
75 /*******************************************************************************
77 * FUNCTION: acpi_ut_bound_string_length
79 * PARAMETERS: string - String with boundary
80 * count - Boundary of the string
82 * RETURN: Length of the string. Less than or equal to Count.
84 * DESCRIPTION: Calculate the length of a string with boundary.
86 ******************************************************************************/
89 acpi_ut_bound_string_length(const char *string
, acpi_size count
)
93 while (*string
&& count
) {
102 /*******************************************************************************
104 * FUNCTION: acpi_ut_bound_string_output
106 * PARAMETERS: string - String with boundary
107 * end - Boundary of the string
108 * c - Character to be output to the string
110 * RETURN: Updated position for next valid character
112 * DESCRIPTION: Output a character into a string with boundary check.
114 ******************************************************************************/
116 static char *acpi_ut_bound_string_output(char *string
, const char *end
, char c
)
127 /*******************************************************************************
129 * FUNCTION: acpi_ut_put_number
131 * PARAMETERS: string - Buffer to hold reverse-ordered string
132 * number - Integer to be converted
133 * base - Base of the integer
134 * upper - Whether or not using upper cased digits
136 * RETURN: Updated position for next valid character
138 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
139 * reversed ordered number without the trailing zero.
141 ******************************************************************************/
143 static char *acpi_ut_put_number(char *string
, u64 number
, u8 base
, u8 upper
)
150 digits
= upper
? acpi_gbl_upper_hex_digits
: acpi_gbl_lower_hex_digits
;
156 (void)acpi_ut_divide(number
, base
, &number
,
158 *(pos
++) = digits
[digit_index
];
162 /* *(Pos++) = '0'; */
166 /*******************************************************************************
168 * FUNCTION: acpi_ut_scan_number
170 * PARAMETERS: string - String buffer
171 * number_ptr - Where the number is returned
173 * RETURN: Updated position for next valid character
175 * DESCRIPTION: Scan a string for a decimal integer.
177 ******************************************************************************/
179 const char *acpi_ut_scan_number(const char *string
, u64
*number_ptr
)
183 while (ACPI_IS_DIGIT(*string
)) {
185 number
+= *(string
++) - '0';
188 *number_ptr
= number
;
192 /*******************************************************************************
194 * FUNCTION: acpi_ut_print_number
196 * PARAMETERS: string - String buffer
197 * number - The number to be converted
199 * RETURN: Updated position for next valid character
201 * DESCRIPTION: Print a decimal integer into a string.
203 ******************************************************************************/
205 const char *acpi_ut_print_number(char *string
, u64 number
)
207 char ascii_string
[20];
211 pos1
= acpi_ut_put_number(ascii_string
, number
, 10, FALSE
);
214 while (pos1
!= ascii_string
) {
215 *(pos2
++) = *(--pos1
);
222 /*******************************************************************************
224 * FUNCTION: acpi_ut_format_number
226 * PARAMETERS: string - String buffer with boundary
227 * end - Boundary of the string
228 * number - The number to be converted
229 * base - Base of the integer
230 * width - Field width
231 * precision - Precision of the integer
232 * type - Special printing flags
234 * RETURN: Updated position for next valid character
236 * DESCRIPTION: Print an integer into a string with any base and any precision.
238 ******************************************************************************/
240 static char *acpi_ut_format_number(char *string
,
243 u8 base
, s32 width
, s32 precision
, u8 type
)
251 char reversed_string
[66];
253 /* Parameter validation */
255 if (base
< 2 || base
> 16) {
259 if (type
& ACPI_FORMAT_LEFT
) {
260 type
&= ~ACPI_FORMAT_ZERO
;
263 need_prefix
= ((type
& ACPI_FORMAT_PREFIX
)
264 && base
!= 10) ? TRUE
: FALSE
;
265 upper
= (type
& ACPI_FORMAT_UPPER
) ? TRUE
: FALSE
;
266 zero
= (type
& ACPI_FORMAT_ZERO
) ? '0' : ' ';
268 /* Calculate size according to sign and prefix */
271 if (type
& ACPI_FORMAT_SIGN
) {
272 if ((s64
) number
< 0) {
274 number
= -(s64
) number
;
276 } else if (type
& ACPI_FORMAT_SIGN_PLUS
) {
279 } else if (type
& ACPI_FORMAT_SIGN_PLUS_SPACE
) {
291 /* Generate full string in reverse order */
293 pos
= acpi_ut_put_number(reversed_string
, number
, base
, upper
);
294 i
= ACPI_PTR_DIFF(pos
, reversed_string
);
296 /* Printing 100 using %2d gives "100", not "00" */
304 /* Output the string */
306 if (!(type
& (ACPI_FORMAT_ZERO
| ACPI_FORMAT_LEFT
))) {
307 while (--width
>= 0) {
308 string
= acpi_ut_bound_string_output(string
, end
, ' ');
312 string
= acpi_ut_bound_string_output(string
, end
, sign
);
315 string
= acpi_ut_bound_string_output(string
, end
, '0');
317 string
= acpi_ut_bound_string_output(string
, end
,
321 if (!(type
& ACPI_FORMAT_LEFT
)) {
322 while (--width
>= 0) {
323 string
= acpi_ut_bound_string_output(string
, end
, zero
);
327 while (i
<= --precision
) {
328 string
= acpi_ut_bound_string_output(string
, end
, '0');
331 string
= acpi_ut_bound_string_output(string
, end
,
334 while (--width
>= 0) {
335 string
= acpi_ut_bound_string_output(string
, end
, ' ');
341 /*******************************************************************************
343 * FUNCTION: acpi_ut_vsnprintf
345 * PARAMETERS: string - String with boundary
346 * size - Boundary of the string
347 * format - Standard printf format
348 * args - Argument list
350 * RETURN: Number of bytes actually written.
352 * DESCRIPTION: Formatted output to a string using argument list pointer.
354 ******************************************************************************/
357 acpi_ut_vsnprintf(char *string
,
358 acpi_size size
, const char *format
, va_list args
)
377 for (; *format
; ++format
) {
378 if (*format
!= '%') {
379 pos
= acpi_ut_bound_string_output(pos
, end
, *format
);
390 if (*format
== '#') {
391 type
|= ACPI_FORMAT_PREFIX
;
392 } else if (*format
== '0') {
393 type
|= ACPI_FORMAT_ZERO
;
394 } else if (*format
== '+') {
395 type
|= ACPI_FORMAT_SIGN_PLUS
;
396 } else if (*format
== ' ') {
397 type
|= ACPI_FORMAT_SIGN_PLUS_SPACE
;
398 } else if (*format
== '-') {
399 type
|= ACPI_FORMAT_LEFT
;
408 if (ACPI_IS_DIGIT(*format
)) {
409 format
= acpi_ut_scan_number(format
, &number
);
410 width
= (s32
) number
;
411 } else if (*format
== '*') {
413 width
= va_arg(args
, int);
416 type
|= ACPI_FORMAT_LEFT
;
420 /* Process precision */
423 if (*format
== '.') {
425 if (ACPI_IS_DIGIT(*format
)) {
426 format
= acpi_ut_scan_number(format
, &number
);
427 precision
= (s32
) number
;
428 } else if (*format
== '*') {
430 precision
= va_arg(args
, int);
437 /* Process qualifier */
440 if (*format
== 'h' || *format
== 'l' || *format
== 'L') {
444 if (qualifier
== 'l' && *format
== 'l') {
453 pos
= acpi_ut_bound_string_output(pos
, end
, '%');
458 if (!(type
& ACPI_FORMAT_LEFT
)) {
459 while (--width
> 0) {
461 acpi_ut_bound_string_output(pos
,
467 c
= (char)va_arg(args
, int);
468 pos
= acpi_ut_bound_string_output(pos
, end
, c
);
470 while (--width
> 0) {
472 acpi_ut_bound_string_output(pos
, end
, ' ');
478 s
= va_arg(args
, char *);
482 length
= acpi_ut_bound_string_length(s
, precision
);
483 if (!(type
& ACPI_FORMAT_LEFT
)) {
484 while (length
< width
--) {
486 acpi_ut_bound_string_output(pos
,
491 for (i
= 0; i
< length
; ++i
) {
492 pos
= acpi_ut_bound_string_output(pos
, end
, *s
);
495 while (length
< width
--) {
497 acpi_ut_bound_string_output(pos
, end
, ' ');
508 type
|= ACPI_FORMAT_UPPER
;
518 type
|= ACPI_FORMAT_SIGN
;
527 width
= 2 * sizeof(void *);
528 type
|= ACPI_FORMAT_ZERO
;
531 p
= va_arg(args
, void *);
532 pos
= acpi_ut_format_number(pos
, end
,
533 ACPI_TO_INTEGER(p
), 16,
534 width
, precision
, type
);
539 pos
= acpi_ut_bound_string_output(pos
, end
, '%');
542 acpi_ut_bound_string_output(pos
, end
,
550 if (qualifier
== 'L') {
551 number
= va_arg(args
, u64
);
552 if (type
& ACPI_FORMAT_SIGN
) {
553 number
= (s64
) number
;
555 } else if (qualifier
== 'l') {
556 number
= va_arg(args
, unsigned long);
557 if (type
& ACPI_FORMAT_SIGN
) {
558 number
= (s32
) number
;
560 } else if (qualifier
== 'h') {
561 number
= (u16
)va_arg(args
, int);
562 if (type
& ACPI_FORMAT_SIGN
) {
563 number
= (s16
) number
;
566 number
= va_arg(args
, unsigned int);
567 if (type
& ACPI_FORMAT_SIGN
) {
568 number
= (signed int)number
;
572 pos
= acpi_ut_format_number(pos
, end
, number
, base
,
573 width
, precision
, type
);
584 return (ACPI_PTR_DIFF(pos
, string
));
587 /*******************************************************************************
589 * FUNCTION: acpi_ut_snprintf
591 * PARAMETERS: string - String with boundary
592 * size - Boundary of the string
593 * Format, ... - Standard printf format
595 * RETURN: Number of bytes actually written.
597 * DESCRIPTION: Formatted output to a string.
599 ******************************************************************************/
601 int acpi_ut_snprintf(char *string
, acpi_size size
, const char *format
, ...)
606 va_start(args
, format
);
607 length
= acpi_ut_vsnprintf(string
, size
, format
, args
);
613 #ifdef ACPI_APPLICATION
614 /*******************************************************************************
616 * FUNCTION: acpi_ut_file_vprintf
618 * PARAMETERS: file - File descriptor
619 * format - Standard printf format
620 * args - Argument list
622 * RETURN: Number of bytes actually written.
624 * DESCRIPTION: Formatted output to a file using argument list pointer.
626 ******************************************************************************/
628 int acpi_ut_file_vprintf(ACPI_FILE file
, const char *format
, va_list args
)
630 acpi_cpu_flags flags
;
633 flags
= acpi_os_acquire_lock(acpi_gbl_print_lock
);
634 length
= acpi_ut_vsnprintf(acpi_gbl_print_buffer
,
635 sizeof(acpi_gbl_print_buffer
), format
, args
);
637 (void)acpi_os_write_file(file
, acpi_gbl_print_buffer
, length
, 1);
638 acpi_os_release_lock(acpi_gbl_print_lock
, flags
);
643 /*******************************************************************************
645 * FUNCTION: acpi_ut_file_printf
647 * PARAMETERS: file - File descriptor
648 * Format, ... - Standard printf format
650 * RETURN: Number of bytes actually written.
652 * DESCRIPTION: Formatted output to a file.
654 ******************************************************************************/
656 int acpi_ut_file_printf(ACPI_FILE file
, const char *format
, ...)
661 va_start(args
, format
);
662 length
= acpi_ut_file_vprintf(file
, format
, args
);