xref: /openbmc/linux/drivers/acpi/acpica/utprint.c (revision 3958168f)
180a648c1SLv Zheng /******************************************************************************
280a648c1SLv Zheng  *
380a648c1SLv Zheng  * Module Name: utprint - Formatted printing routines
480a648c1SLv Zheng  *
580a648c1SLv Zheng  *****************************************************************************/
680a648c1SLv Zheng 
780a648c1SLv Zheng /*
87735ca0eSBob Moore  * Copyright (C) 2000 - 2017, Intel Corp.
980a648c1SLv Zheng  * All rights reserved.
1080a648c1SLv Zheng  *
1180a648c1SLv Zheng  * Redistribution and use in source and binary forms, with or without
1280a648c1SLv Zheng  * modification, are permitted provided that the following conditions
1380a648c1SLv Zheng  * are met:
1480a648c1SLv Zheng  * 1. Redistributions of source code must retain the above copyright
1580a648c1SLv Zheng  *    notice, this list of conditions, and the following disclaimer,
1680a648c1SLv Zheng  *    without modification.
1780a648c1SLv Zheng  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1880a648c1SLv Zheng  *    substantially similar to the "NO WARRANTY" disclaimer below
1980a648c1SLv Zheng  *    ("Disclaimer") and any redistribution must be conditioned upon
2080a648c1SLv Zheng  *    including a substantially similar Disclaimer requirement for further
2180a648c1SLv Zheng  *    binary redistribution.
2280a648c1SLv Zheng  * 3. Neither the names of the above-listed copyright holders nor the names
2380a648c1SLv Zheng  *    of any contributors may be used to endorse or promote products derived
2480a648c1SLv Zheng  *    from this software without specific prior written permission.
2580a648c1SLv Zheng  *
2680a648c1SLv Zheng  * Alternatively, this software may be distributed under the terms of the
2780a648c1SLv Zheng  * GNU General Public License ("GPL") version 2 as published by the Free
2880a648c1SLv Zheng  * Software Foundation.
2980a648c1SLv Zheng  *
3080a648c1SLv Zheng  * NO WARRANTY
3180a648c1SLv Zheng  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3280a648c1SLv Zheng  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3380a648c1SLv Zheng  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3480a648c1SLv Zheng  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3580a648c1SLv Zheng  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3680a648c1SLv Zheng  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3780a648c1SLv Zheng  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3880a648c1SLv Zheng  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3980a648c1SLv Zheng  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4080a648c1SLv Zheng  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4180a648c1SLv Zheng  * POSSIBILITY OF SUCH DAMAGES.
4280a648c1SLv Zheng  */
4380a648c1SLv Zheng 
4480a648c1SLv Zheng #include <acpi/acpi.h>
4580a648c1SLv Zheng #include "accommon.h"
4680a648c1SLv Zheng 
4780a648c1SLv Zheng #define _COMPONENT          ACPI_UTILITIES
4880a648c1SLv Zheng ACPI_MODULE_NAME("utprint")
4980a648c1SLv Zheng 
5080a648c1SLv Zheng #define ACPI_FORMAT_SIGN            0x01
5180a648c1SLv Zheng #define ACPI_FORMAT_SIGN_PLUS       0x02
5280a648c1SLv Zheng #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
5380a648c1SLv Zheng #define ACPI_FORMAT_ZERO            0x08
5480a648c1SLv Zheng #define ACPI_FORMAT_LEFT            0x10
5580a648c1SLv Zheng #define ACPI_FORMAT_UPPER           0x20
5680a648c1SLv Zheng #define ACPI_FORMAT_PREFIX          0x40
5780a648c1SLv Zheng /* Local prototypes */
5880a648c1SLv Zheng static acpi_size
5980a648c1SLv Zheng acpi_ut_bound_string_length(const char *string, acpi_size count);
6080a648c1SLv Zheng 
6180a648c1SLv Zheng static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
6280a648c1SLv Zheng 
6380a648c1SLv Zheng static char *acpi_ut_format_number(char *string,
6480a648c1SLv Zheng 				   char *end,
6580a648c1SLv Zheng 				   u64 number,
6680a648c1SLv Zheng 				   u8 base, s32 width, s32 precision, u8 type);
6780a648c1SLv Zheng 
6880a648c1SLv Zheng static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
6980a648c1SLv Zheng 
7080a648c1SLv Zheng /*******************************************************************************
7180a648c1SLv Zheng  *
7280a648c1SLv Zheng  * FUNCTION:    acpi_ut_bound_string_length
7380a648c1SLv Zheng  *
7480a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
7580a648c1SLv Zheng  *              count               - Boundary of the string
7680a648c1SLv Zheng  *
77ff2389feSBob Moore  * RETURN:      Length of the string. Less than or equal to Count.
7880a648c1SLv Zheng  *
7980a648c1SLv Zheng  * DESCRIPTION: Calculate the length of a string with boundary.
8080a648c1SLv Zheng  *
8180a648c1SLv Zheng  ******************************************************************************/
8280a648c1SLv Zheng 
8380a648c1SLv Zheng static acpi_size
8480a648c1SLv Zheng acpi_ut_bound_string_length(const char *string, acpi_size count)
8580a648c1SLv Zheng {
8680a648c1SLv Zheng 	u32 length = 0;
8780a648c1SLv Zheng 
8880a648c1SLv Zheng 	while (*string && count) {
8980a648c1SLv Zheng 		length++;
9080a648c1SLv Zheng 		string++;
9180a648c1SLv Zheng 		count--;
9280a648c1SLv Zheng 	}
9380a648c1SLv Zheng 
9480a648c1SLv Zheng 	return (length);
9580a648c1SLv Zheng }
9680a648c1SLv Zheng 
9780a648c1SLv Zheng /*******************************************************************************
9880a648c1SLv Zheng  *
9980a648c1SLv Zheng  * FUNCTION:    acpi_ut_bound_string_output
10080a648c1SLv Zheng  *
10180a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
10280a648c1SLv Zheng  *              end                 - Boundary of the string
10380a648c1SLv Zheng  *              c                   - Character to be output to the string
10480a648c1SLv Zheng  *
10580a648c1SLv Zheng  * RETURN:      Updated position for next valid character
10680a648c1SLv Zheng  *
10780a648c1SLv Zheng  * DESCRIPTION: Output a character into a string with boundary check.
10880a648c1SLv Zheng  *
10980a648c1SLv Zheng  ******************************************************************************/
11080a648c1SLv Zheng 
11180a648c1SLv Zheng static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
11280a648c1SLv Zheng {
11380a648c1SLv Zheng 
11480a648c1SLv Zheng 	if (string < end) {
11580a648c1SLv Zheng 		*string = c;
11680a648c1SLv Zheng 	}
11780a648c1SLv Zheng 
118ff2389feSBob Moore 	++string;
11980a648c1SLv Zheng 	return (string);
12080a648c1SLv Zheng }
12180a648c1SLv Zheng 
12280a648c1SLv Zheng /*******************************************************************************
12380a648c1SLv Zheng  *
12480a648c1SLv Zheng  * FUNCTION:    acpi_ut_put_number
12580a648c1SLv Zheng  *
12680a648c1SLv Zheng  * PARAMETERS:  string              - Buffer to hold reverse-ordered string
12780a648c1SLv Zheng  *              number              - Integer to be converted
12880a648c1SLv Zheng  *              base                - Base of the integer
12980a648c1SLv Zheng  *              upper               - Whether or not using upper cased digits
13080a648c1SLv Zheng  *
13180a648c1SLv Zheng  * RETURN:      Updated position for next valid character
13280a648c1SLv Zheng  *
13380a648c1SLv Zheng  * DESCRIPTION: Convert an integer into a string, note that, the string holds a
13480a648c1SLv Zheng  *              reversed ordered number without the trailing zero.
13580a648c1SLv Zheng  *
13680a648c1SLv Zheng  ******************************************************************************/
13780a648c1SLv Zheng 
13880a648c1SLv Zheng static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
13980a648c1SLv Zheng {
14080a648c1SLv Zheng 	const char *digits;
14180a648c1SLv Zheng 	u64 digit_index;
14280a648c1SLv Zheng 	char *pos;
14380a648c1SLv Zheng 
14480a648c1SLv Zheng 	pos = string;
145ff2389feSBob Moore 	digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
14680a648c1SLv Zheng 
14780a648c1SLv Zheng 	if (number == 0) {
14880a648c1SLv Zheng 		*(pos++) = '0';
14980a648c1SLv Zheng 	} else {
15080a648c1SLv Zheng 		while (number) {
15180a648c1SLv Zheng 			(void)acpi_ut_divide(number, base, &number,
15280a648c1SLv Zheng 					     &digit_index);
15380a648c1SLv Zheng 			*(pos++) = digits[digit_index];
15480a648c1SLv Zheng 		}
15580a648c1SLv Zheng 	}
15680a648c1SLv Zheng 
157ff2389feSBob Moore 	/* *(Pos++) = '0'; */
15880a648c1SLv Zheng 	return (pos);
15980a648c1SLv Zheng }
16080a648c1SLv Zheng 
16180a648c1SLv Zheng /*******************************************************************************
16280a648c1SLv Zheng  *
16380a648c1SLv Zheng  * FUNCTION:    acpi_ut_scan_number
16480a648c1SLv Zheng  *
16580a648c1SLv Zheng  * PARAMETERS:  string              - String buffer
16680a648c1SLv Zheng  *              number_ptr          - Where the number is returned
16780a648c1SLv Zheng  *
16880a648c1SLv Zheng  * RETURN:      Updated position for next valid character
16980a648c1SLv Zheng  *
17080a648c1SLv Zheng  * DESCRIPTION: Scan a string for a decimal integer.
17180a648c1SLv Zheng  *
17280a648c1SLv Zheng  ******************************************************************************/
17380a648c1SLv Zheng 
17480a648c1SLv Zheng const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
17580a648c1SLv Zheng {
17680a648c1SLv Zheng 	u64 number = 0;
17780a648c1SLv Zheng 
1784fa4616eSBob Moore 	while (isdigit((int)*string)) {
17965082bfcSLv Zheng 		acpi_ut_short_multiply(number, 10, &number);
18080a648c1SLv Zheng 		number += *(string++) - '0';
18180a648c1SLv Zheng 	}
18280a648c1SLv Zheng 
183ff2389feSBob Moore 	*number_ptr = number;
18480a648c1SLv Zheng 	return (string);
18580a648c1SLv Zheng }
18680a648c1SLv Zheng 
18780a648c1SLv Zheng /*******************************************************************************
18880a648c1SLv Zheng  *
18980a648c1SLv Zheng  * FUNCTION:    acpi_ut_print_number
19080a648c1SLv Zheng  *
19180a648c1SLv Zheng  * PARAMETERS:  string              - String buffer
19280a648c1SLv Zheng  *              number              - The number to be converted
19380a648c1SLv Zheng  *
19480a648c1SLv Zheng  * RETURN:      Updated position for next valid character
19580a648c1SLv Zheng  *
19680a648c1SLv Zheng  * DESCRIPTION: Print a decimal integer into a string.
19780a648c1SLv Zheng  *
19880a648c1SLv Zheng  ******************************************************************************/
19980a648c1SLv Zheng 
20080a648c1SLv Zheng const char *acpi_ut_print_number(char *string, u64 number)
20180a648c1SLv Zheng {
20280a648c1SLv Zheng 	char ascii_string[20];
20380a648c1SLv Zheng 	const char *pos1;
20480a648c1SLv Zheng 	char *pos2;
20580a648c1SLv Zheng 
20680a648c1SLv Zheng 	pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
20780a648c1SLv Zheng 	pos2 = string;
20880a648c1SLv Zheng 
20980a648c1SLv Zheng 	while (pos1 != ascii_string) {
21080a648c1SLv Zheng 		*(pos2++) = *(--pos1);
21180a648c1SLv Zheng 	}
21280a648c1SLv Zheng 
213ff2389feSBob Moore 	*pos2 = 0;
21480a648c1SLv Zheng 	return (string);
21580a648c1SLv Zheng }
21680a648c1SLv Zheng 
21780a648c1SLv Zheng /*******************************************************************************
21880a648c1SLv Zheng  *
21980a648c1SLv Zheng  * FUNCTION:    acpi_ut_format_number
22080a648c1SLv Zheng  *
22180a648c1SLv Zheng  * PARAMETERS:  string              - String buffer with boundary
22280a648c1SLv Zheng  *              end                 - Boundary of the string
22380a648c1SLv Zheng  *              number              - The number to be converted
22480a648c1SLv Zheng  *              base                - Base of the integer
22580a648c1SLv Zheng  *              width               - Field width
22680a648c1SLv Zheng  *              precision           - Precision of the integer
22780a648c1SLv Zheng  *              type                - Special printing flags
22880a648c1SLv Zheng  *
22980a648c1SLv Zheng  * RETURN:      Updated position for next valid character
23080a648c1SLv Zheng  *
23180a648c1SLv Zheng  * DESCRIPTION: Print an integer into a string with any base and any precision.
23280a648c1SLv Zheng  *
23380a648c1SLv Zheng  ******************************************************************************/
23480a648c1SLv Zheng 
23580a648c1SLv Zheng static char *acpi_ut_format_number(char *string,
23680a648c1SLv Zheng 				   char *end,
23780a648c1SLv Zheng 				   u64 number,
23880a648c1SLv Zheng 				   u8 base, s32 width, s32 precision, u8 type)
23980a648c1SLv Zheng {
2408884de6aSBob Moore 	char *pos;
24180a648c1SLv Zheng 	char sign;
24280a648c1SLv Zheng 	char zero;
24380a648c1SLv Zheng 	u8 need_prefix;
24480a648c1SLv Zheng 	u8 upper;
24580a648c1SLv Zheng 	s32 i;
24680a648c1SLv Zheng 	char reversed_string[66];
24780a648c1SLv Zheng 
248ff2389feSBob Moore 	/* Parameter validation */
24980a648c1SLv Zheng 
25080a648c1SLv Zheng 	if (base < 2 || base > 16) {
251ff2389feSBob Moore 		return (NULL);
25280a648c1SLv Zheng 	}
253ff2389feSBob Moore 
25480a648c1SLv Zheng 	if (type & ACPI_FORMAT_LEFT) {
25580a648c1SLv Zheng 		type &= ~ACPI_FORMAT_ZERO;
25680a648c1SLv Zheng 	}
25780a648c1SLv Zheng 
25880a648c1SLv Zheng 	need_prefix = ((type & ACPI_FORMAT_PREFIX)
25980a648c1SLv Zheng 		       && base != 10) ? TRUE : FALSE;
26080a648c1SLv Zheng 	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
26180a648c1SLv Zheng 	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
26280a648c1SLv Zheng 
26380a648c1SLv Zheng 	/* Calculate size according to sign and prefix */
26480a648c1SLv Zheng 
26580a648c1SLv Zheng 	sign = '\0';
26680a648c1SLv Zheng 	if (type & ACPI_FORMAT_SIGN) {
26780a648c1SLv Zheng 		if ((s64)number < 0) {
26880a648c1SLv Zheng 			sign = '-';
26980a648c1SLv Zheng 			number = -(s64)number;
27080a648c1SLv Zheng 			width--;
27180a648c1SLv Zheng 		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
27280a648c1SLv Zheng 			sign = '+';
27380a648c1SLv Zheng 			width--;
27480a648c1SLv Zheng 		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
27580a648c1SLv Zheng 			sign = ' ';
27680a648c1SLv Zheng 			width--;
27780a648c1SLv Zheng 		}
27880a648c1SLv Zheng 	}
27980a648c1SLv Zheng 	if (need_prefix) {
28080a648c1SLv Zheng 		width--;
28180a648c1SLv Zheng 		if (base == 16) {
28280a648c1SLv Zheng 			width--;
28380a648c1SLv Zheng 		}
28480a648c1SLv Zheng 	}
28580a648c1SLv Zheng 
28680a648c1SLv Zheng 	/* Generate full string in reverse order */
28780a648c1SLv Zheng 
2888884de6aSBob Moore 	pos = acpi_ut_put_number(reversed_string, number, base, upper);
2893958168fSLv Zheng 	i = (s32)ACPI_PTR_DIFF(pos, reversed_string);
29080a648c1SLv Zheng 
29180a648c1SLv Zheng 	/* Printing 100 using %2d gives "100", not "00" */
29280a648c1SLv Zheng 
29380a648c1SLv Zheng 	if (i > precision) {
29480a648c1SLv Zheng 		precision = i;
29580a648c1SLv Zheng 	}
296ff2389feSBob Moore 
29780a648c1SLv Zheng 	width -= precision;
29880a648c1SLv Zheng 
29980a648c1SLv Zheng 	/* Output the string */
30080a648c1SLv Zheng 
30180a648c1SLv Zheng 	if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
30280a648c1SLv Zheng 		while (--width >= 0) {
30380a648c1SLv Zheng 			string = acpi_ut_bound_string_output(string, end, ' ');
30480a648c1SLv Zheng 		}
30580a648c1SLv Zheng 	}
30680a648c1SLv Zheng 	if (sign) {
30780a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, sign);
30880a648c1SLv Zheng 	}
30980a648c1SLv Zheng 	if (need_prefix) {
31080a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, '0');
31180a648c1SLv Zheng 		if (base == 16) {
3121fad8738SBob Moore 			string =
3131fad8738SBob Moore 			    acpi_ut_bound_string_output(string, end,
31480a648c1SLv Zheng 							upper ? 'X' : 'x');
31580a648c1SLv Zheng 		}
31680a648c1SLv Zheng 	}
31780a648c1SLv Zheng 	if (!(type & ACPI_FORMAT_LEFT)) {
31880a648c1SLv Zheng 		while (--width >= 0) {
31980a648c1SLv Zheng 			string = acpi_ut_bound_string_output(string, end, zero);
32080a648c1SLv Zheng 		}
32180a648c1SLv Zheng 	}
322ff2389feSBob Moore 
32380a648c1SLv Zheng 	while (i <= --precision) {
32480a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, '0');
32580a648c1SLv Zheng 	}
32680a648c1SLv Zheng 	while (--i >= 0) {
32780a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end,
32880a648c1SLv Zheng 						     reversed_string[i]);
32980a648c1SLv Zheng 	}
33080a648c1SLv Zheng 	while (--width >= 0) {
33180a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, ' ');
33280a648c1SLv Zheng 	}
33380a648c1SLv Zheng 
33480a648c1SLv Zheng 	return (string);
33580a648c1SLv Zheng }
33680a648c1SLv Zheng 
33780a648c1SLv Zheng /*******************************************************************************
33880a648c1SLv Zheng  *
339f173a775SLv Zheng  * FUNCTION:    vsnprintf
34080a648c1SLv Zheng  *
34180a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
34280a648c1SLv Zheng  *              size                - Boundary of the string
34380a648c1SLv Zheng  *              format              - Standard printf format
34480a648c1SLv Zheng  *              args                - Argument list
34580a648c1SLv Zheng  *
346ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
34780a648c1SLv Zheng  *
34880a648c1SLv Zheng  * DESCRIPTION: Formatted output to a string using argument list pointer.
34980a648c1SLv Zheng  *
35080a648c1SLv Zheng  ******************************************************************************/
35180a648c1SLv Zheng 
352f173a775SLv Zheng int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
35380a648c1SLv Zheng {
354cef9aaa7SLv Zheng 	u8 base;
355cef9aaa7SLv Zheng 	u8 type;
356cef9aaa7SLv Zheng 	s32 width;
357cef9aaa7SLv Zheng 	s32 precision;
358cef9aaa7SLv Zheng 	char qualifier;
35980a648c1SLv Zheng 	u64 number;
36080a648c1SLv Zheng 	char *pos;
36180a648c1SLv Zheng 	char *end;
36280a648c1SLv Zheng 	char c;
36380a648c1SLv Zheng 	const char *s;
36480a648c1SLv Zheng 	const void *p;
36580a648c1SLv Zheng 	s32 length;
36680a648c1SLv Zheng 	int i;
36780a648c1SLv Zheng 
36880a648c1SLv Zheng 	pos = string;
36980a648c1SLv Zheng 	end = string + size;
37080a648c1SLv Zheng 
37180a648c1SLv Zheng 	for (; *format; ++format) {
37280a648c1SLv Zheng 		if (*format != '%') {
37380a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, *format);
37480a648c1SLv Zheng 			continue;
37580a648c1SLv Zheng 		}
37680a648c1SLv Zheng 
377cef9aaa7SLv Zheng 		type = 0;
378cef9aaa7SLv Zheng 		base = 10;
379cef9aaa7SLv Zheng 
38080a648c1SLv Zheng 		/* Process sign */
38180a648c1SLv Zheng 
38280a648c1SLv Zheng 		do {
38380a648c1SLv Zheng 			++format;
38480a648c1SLv Zheng 			if (*format == '#') {
38580a648c1SLv Zheng 				type |= ACPI_FORMAT_PREFIX;
38680a648c1SLv Zheng 			} else if (*format == '0') {
38780a648c1SLv Zheng 				type |= ACPI_FORMAT_ZERO;
38880a648c1SLv Zheng 			} else if (*format == '+') {
38980a648c1SLv Zheng 				type |= ACPI_FORMAT_SIGN_PLUS;
39080a648c1SLv Zheng 			} else if (*format == ' ') {
39180a648c1SLv Zheng 				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
39280a648c1SLv Zheng 			} else if (*format == '-') {
39380a648c1SLv Zheng 				type |= ACPI_FORMAT_LEFT;
39480a648c1SLv Zheng 			} else {
39580a648c1SLv Zheng 				break;
39680a648c1SLv Zheng 			}
3971fad8738SBob Moore 
39880a648c1SLv Zheng 		} while (1);
39980a648c1SLv Zheng 
40080a648c1SLv Zheng 		/* Process width */
40180a648c1SLv Zheng 
4023589b8b8SLv Zheng 		width = -1;
4034fa4616eSBob Moore 		if (isdigit((int)*format)) {
40480a648c1SLv Zheng 			format = acpi_ut_scan_number(format, &number);
40580a648c1SLv Zheng 			width = (s32)number;
40680a648c1SLv Zheng 		} else if (*format == '*') {
40780a648c1SLv Zheng 			++format;
40880a648c1SLv Zheng 			width = va_arg(args, int);
40980a648c1SLv Zheng 			if (width < 0) {
41080a648c1SLv Zheng 				width = -width;
41180a648c1SLv Zheng 				type |= ACPI_FORMAT_LEFT;
41280a648c1SLv Zheng 			}
41380a648c1SLv Zheng 		}
41480a648c1SLv Zheng 
41580a648c1SLv Zheng 		/* Process precision */
41680a648c1SLv Zheng 
4173589b8b8SLv Zheng 		precision = -1;
41880a648c1SLv Zheng 		if (*format == '.') {
41980a648c1SLv Zheng 			++format;
4204fa4616eSBob Moore 			if (isdigit((int)*format)) {
42180a648c1SLv Zheng 				format = acpi_ut_scan_number(format, &number);
42280a648c1SLv Zheng 				precision = (s32)number;
42380a648c1SLv Zheng 			} else if (*format == '*') {
42480a648c1SLv Zheng 				++format;
42580a648c1SLv Zheng 				precision = va_arg(args, int);
42680a648c1SLv Zheng 			}
4271fad8738SBob Moore 
42880a648c1SLv Zheng 			if (precision < 0) {
42980a648c1SLv Zheng 				precision = 0;
43080a648c1SLv Zheng 			}
43180a648c1SLv Zheng 		}
43280a648c1SLv Zheng 
43380a648c1SLv Zheng 		/* Process qualifier */
43480a648c1SLv Zheng 
4353589b8b8SLv Zheng 		qualifier = -1;
43680a648c1SLv Zheng 		if (*format == 'h' || *format == 'l' || *format == 'L') {
43780a648c1SLv Zheng 			qualifier = *format;
43880a648c1SLv Zheng 			++format;
439ff2389feSBob Moore 
44080a648c1SLv Zheng 			if (qualifier == 'l' && *format == 'l') {
44180a648c1SLv Zheng 				qualifier = 'L';
44280a648c1SLv Zheng 				++format;
44380a648c1SLv Zheng 			}
44480a648c1SLv Zheng 		}
44580a648c1SLv Zheng 
44680a648c1SLv Zheng 		switch (*format) {
44780a648c1SLv Zheng 		case '%':
44880a648c1SLv Zheng 
44980a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, '%');
45080a648c1SLv Zheng 			continue;
45180a648c1SLv Zheng 
45280a648c1SLv Zheng 		case 'c':
45380a648c1SLv Zheng 
45480a648c1SLv Zheng 			if (!(type & ACPI_FORMAT_LEFT)) {
45580a648c1SLv Zheng 				while (--width > 0) {
45680a648c1SLv Zheng 					pos =
45780a648c1SLv Zheng 					    acpi_ut_bound_string_output(pos,
45880a648c1SLv Zheng 									end,
45980a648c1SLv Zheng 									' ');
46080a648c1SLv Zheng 				}
46180a648c1SLv Zheng 			}
462ff2389feSBob Moore 
46380a648c1SLv Zheng 			c = (char)va_arg(args, int);
46480a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, c);
465ff2389feSBob Moore 
46680a648c1SLv Zheng 			while (--width > 0) {
46780a648c1SLv Zheng 				pos =
46880a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end, ' ');
46980a648c1SLv Zheng 			}
47080a648c1SLv Zheng 			continue;
47180a648c1SLv Zheng 
47280a648c1SLv Zheng 		case 's':
47380a648c1SLv Zheng 
47480a648c1SLv Zheng 			s = va_arg(args, char *);
47580a648c1SLv Zheng 			if (!s) {
47680a648c1SLv Zheng 				s = "<NULL>";
47780a648c1SLv Zheng 			}
4783958168fSLv Zheng 			length = (s32)acpi_ut_bound_string_length(s, precision);
47980a648c1SLv Zheng 			if (!(type & ACPI_FORMAT_LEFT)) {
48080a648c1SLv Zheng 				while (length < width--) {
48180a648c1SLv Zheng 					pos =
48280a648c1SLv Zheng 					    acpi_ut_bound_string_output(pos,
48380a648c1SLv Zheng 									end,
48480a648c1SLv Zheng 									' ');
48580a648c1SLv Zheng 				}
48680a648c1SLv Zheng 			}
4871fad8738SBob Moore 
48880a648c1SLv Zheng 			for (i = 0; i < length; ++i) {
48980a648c1SLv Zheng 				pos = acpi_ut_bound_string_output(pos, end, *s);
49080a648c1SLv Zheng 				++s;
49180a648c1SLv Zheng 			}
4921fad8738SBob Moore 
49380a648c1SLv Zheng 			while (length < width--) {
49480a648c1SLv Zheng 				pos =
49580a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end, ' ');
49680a648c1SLv Zheng 			}
49780a648c1SLv Zheng 			continue;
49880a648c1SLv Zheng 
49980a648c1SLv Zheng 		case 'o':
50080a648c1SLv Zheng 
50180a648c1SLv Zheng 			base = 8;
50280a648c1SLv Zheng 			break;
50380a648c1SLv Zheng 
50480a648c1SLv Zheng 		case 'X':
50580a648c1SLv Zheng 
50680a648c1SLv Zheng 			type |= ACPI_FORMAT_UPPER;
50780a648c1SLv Zheng 
50880a648c1SLv Zheng 		case 'x':
50980a648c1SLv Zheng 
51080a648c1SLv Zheng 			base = 16;
51180a648c1SLv Zheng 			break;
51280a648c1SLv Zheng 
51380a648c1SLv Zheng 		case 'd':
51480a648c1SLv Zheng 		case 'i':
51580a648c1SLv Zheng 
51680a648c1SLv Zheng 			type |= ACPI_FORMAT_SIGN;
51780a648c1SLv Zheng 
51880a648c1SLv Zheng 		case 'u':
51980a648c1SLv Zheng 
52080a648c1SLv Zheng 			break;
52180a648c1SLv Zheng 
52280a648c1SLv Zheng 		case 'p':
52380a648c1SLv Zheng 
52480a648c1SLv Zheng 			if (width == -1) {
52580a648c1SLv Zheng 				width = 2 * sizeof(void *);
52680a648c1SLv Zheng 				type |= ACPI_FORMAT_ZERO;
52780a648c1SLv Zheng 			}
528ff2389feSBob Moore 
52980a648c1SLv Zheng 			p = va_arg(args, void *);
5301fad8738SBob Moore 			pos =
5311fad8738SBob Moore 			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
5321fad8738SBob Moore 						  16, width, precision, type);
53380a648c1SLv Zheng 			continue;
53480a648c1SLv Zheng 
53580a648c1SLv Zheng 		default:
53680a648c1SLv Zheng 
53780a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, '%');
53880a648c1SLv Zheng 			if (*format) {
53980a648c1SLv Zheng 				pos =
54080a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end,
54180a648c1SLv Zheng 								*format);
54280a648c1SLv Zheng 			} else {
54380a648c1SLv Zheng 				--format;
54480a648c1SLv Zheng 			}
54580a648c1SLv Zheng 			continue;
54680a648c1SLv Zheng 		}
54780a648c1SLv Zheng 
54880a648c1SLv Zheng 		if (qualifier == 'L') {
54980a648c1SLv Zheng 			number = va_arg(args, u64);
55080a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
55180a648c1SLv Zheng 				number = (s64)number;
55280a648c1SLv Zheng 			}
55380a648c1SLv Zheng 		} else if (qualifier == 'l') {
55480a648c1SLv Zheng 			number = va_arg(args, unsigned long);
55580a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
55680a648c1SLv Zheng 				number = (s32)number;
55780a648c1SLv Zheng 			}
55880a648c1SLv Zheng 		} else if (qualifier == 'h') {
55980a648c1SLv Zheng 			number = (u16)va_arg(args, int);
56080a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
56180a648c1SLv Zheng 				number = (s16)number;
56280a648c1SLv Zheng 			}
56380a648c1SLv Zheng 		} else {
56480a648c1SLv Zheng 			number = va_arg(args, unsigned int);
56580a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
56680a648c1SLv Zheng 				number = (signed int)number;
56780a648c1SLv Zheng 			}
56880a648c1SLv Zheng 		}
569ff2389feSBob Moore 
57080a648c1SLv Zheng 		pos = acpi_ut_format_number(pos, end, number, base,
57180a648c1SLv Zheng 					    width, precision, type);
57280a648c1SLv Zheng 	}
57380a648c1SLv Zheng 
57480a648c1SLv Zheng 	if (size > 0) {
57580a648c1SLv Zheng 		if (pos < end) {
57680a648c1SLv Zheng 			*pos = '\0';
57780a648c1SLv Zheng 		} else {
57880a648c1SLv Zheng 			end[-1] = '\0';
57980a648c1SLv Zheng 		}
58080a648c1SLv Zheng 	}
58180a648c1SLv Zheng 
5823958168fSLv Zheng 	return ((int)ACPI_PTR_DIFF(pos, string));
58380a648c1SLv Zheng }
58480a648c1SLv Zheng 
58580a648c1SLv Zheng /*******************************************************************************
58680a648c1SLv Zheng  *
587f173a775SLv Zheng  * FUNCTION:    snprintf
58880a648c1SLv Zheng  *
58980a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
59080a648c1SLv Zheng  *              size                - Boundary of the string
59180a648c1SLv Zheng  *              Format, ...         - Standard printf format
59280a648c1SLv Zheng  *
593ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
59480a648c1SLv Zheng  *
59580a648c1SLv Zheng  * DESCRIPTION: Formatted output to a string.
59680a648c1SLv Zheng  *
59780a648c1SLv Zheng  ******************************************************************************/
59880a648c1SLv Zheng 
599f173a775SLv Zheng int snprintf(char *string, acpi_size size, const char *format, ...)
60080a648c1SLv Zheng {
60180a648c1SLv Zheng 	va_list args;
60280a648c1SLv Zheng 	int length;
60380a648c1SLv Zheng 
60480a648c1SLv Zheng 	va_start(args, format);
605f173a775SLv Zheng 	length = vsnprintf(string, size, format, args);
606f173a775SLv Zheng 	va_end(args);
607f173a775SLv Zheng 
608f173a775SLv Zheng 	return (length);
609f173a775SLv Zheng }
610f173a775SLv Zheng 
611f173a775SLv Zheng /*******************************************************************************
612f173a775SLv Zheng  *
613f173a775SLv Zheng  * FUNCTION:    sprintf
614f173a775SLv Zheng  *
615f173a775SLv Zheng  * PARAMETERS:  string              - String with boundary
616f173a775SLv Zheng  *              Format, ...         - Standard printf format
617f173a775SLv Zheng  *
618f173a775SLv Zheng  * RETURN:      Number of bytes actually written.
619f173a775SLv Zheng  *
620f173a775SLv Zheng  * DESCRIPTION: Formatted output to a string.
621f173a775SLv Zheng  *
622f173a775SLv Zheng  ******************************************************************************/
623f173a775SLv Zheng 
624f173a775SLv Zheng int sprintf(char *string, const char *format, ...)
625f173a775SLv Zheng {
626f173a775SLv Zheng 	va_list args;
627f173a775SLv Zheng 	int length;
628f173a775SLv Zheng 
629f173a775SLv Zheng 	va_start(args, format);
630f173a775SLv Zheng 	length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
63180a648c1SLv Zheng 	va_end(args);
63280a648c1SLv Zheng 
63380a648c1SLv Zheng 	return (length);
63480a648c1SLv Zheng }
63580a648c1SLv Zheng 
63680a648c1SLv Zheng #ifdef ACPI_APPLICATION
63780a648c1SLv Zheng /*******************************************************************************
63880a648c1SLv Zheng  *
639f173a775SLv Zheng  * FUNCTION:    vprintf
640f173a775SLv Zheng  *
641f173a775SLv Zheng  * PARAMETERS:  format              - Standard printf format
642f173a775SLv Zheng  *              args                - Argument list
643f173a775SLv Zheng  *
644f173a775SLv Zheng  * RETURN:      Number of bytes actually written.
645f173a775SLv Zheng  *
646f173a775SLv Zheng  * DESCRIPTION: Formatted output to stdout using argument list pointer.
647f173a775SLv Zheng  *
648f173a775SLv Zheng  ******************************************************************************/
649f173a775SLv Zheng 
650f173a775SLv Zheng int vprintf(const char *format, va_list args)
651f173a775SLv Zheng {
652f173a775SLv Zheng 	acpi_cpu_flags flags;
653f173a775SLv Zheng 	int length;
654f173a775SLv Zheng 
655f173a775SLv Zheng 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
656f173a775SLv Zheng 	length = vsnprintf(acpi_gbl_print_buffer,
657f173a775SLv Zheng 			   sizeof(acpi_gbl_print_buffer), format, args);
658f173a775SLv Zheng 
659dd99cbccSLv Zheng 	(void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
660f173a775SLv Zheng 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
661f173a775SLv Zheng 
662f173a775SLv Zheng 	return (length);
663f173a775SLv Zheng }
664f173a775SLv Zheng 
665f173a775SLv Zheng /*******************************************************************************
666f173a775SLv Zheng  *
667f173a775SLv Zheng  * FUNCTION:    printf
668f173a775SLv Zheng  *
669f173a775SLv Zheng  * PARAMETERS:  Format, ...         - Standard printf format
670f173a775SLv Zheng  *
671f173a775SLv Zheng  * RETURN:      Number of bytes actually written.
672f173a775SLv Zheng  *
673f173a775SLv Zheng  * DESCRIPTION: Formatted output to stdout.
674f173a775SLv Zheng  *
675f173a775SLv Zheng  ******************************************************************************/
676f173a775SLv Zheng 
677f173a775SLv Zheng int printf(const char *format, ...)
678f173a775SLv Zheng {
679f173a775SLv Zheng 	va_list args;
680f173a775SLv Zheng 	int length;
681f173a775SLv Zheng 
682f173a775SLv Zheng 	va_start(args, format);
683f173a775SLv Zheng 	length = vprintf(format, args);
684f173a775SLv Zheng 	va_end(args);
685f173a775SLv Zheng 
686f173a775SLv Zheng 	return (length);
687f173a775SLv Zheng }
688f173a775SLv Zheng 
689f173a775SLv Zheng /*******************************************************************************
690f173a775SLv Zheng  *
691f173a775SLv Zheng  * FUNCTION:    vfprintf
69280a648c1SLv Zheng  *
69380a648c1SLv Zheng  * PARAMETERS:  file                - File descriptor
69480a648c1SLv Zheng  *              format              - Standard printf format
69580a648c1SLv Zheng  *              args                - Argument list
69680a648c1SLv Zheng  *
697ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
69880a648c1SLv Zheng  *
69980a648c1SLv Zheng  * DESCRIPTION: Formatted output to a file using argument list pointer.
70080a648c1SLv Zheng  *
70180a648c1SLv Zheng  ******************************************************************************/
70280a648c1SLv Zheng 
703f173a775SLv Zheng int vfprintf(FILE * file, const char *format, va_list args)
70480a648c1SLv Zheng {
70580a648c1SLv Zheng 	acpi_cpu_flags flags;
70680a648c1SLv Zheng 	int length;
70780a648c1SLv Zheng 
70880a648c1SLv Zheng 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
709f173a775SLv Zheng 	length = vsnprintf(acpi_gbl_print_buffer,
71080a648c1SLv Zheng 			   sizeof(acpi_gbl_print_buffer), format, args);
711ff2389feSBob Moore 
712dd99cbccSLv Zheng 	(void)fwrite(acpi_gbl_print_buffer, length, 1, file);
71380a648c1SLv Zheng 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
71480a648c1SLv Zheng 
71580a648c1SLv Zheng 	return (length);
71680a648c1SLv Zheng }
71780a648c1SLv Zheng 
71880a648c1SLv Zheng /*******************************************************************************
71980a648c1SLv Zheng  *
720f173a775SLv Zheng  * FUNCTION:    fprintf
72180a648c1SLv Zheng  *
72280a648c1SLv Zheng  * PARAMETERS:  file                - File descriptor
72380a648c1SLv Zheng  *              Format, ...         - Standard printf format
72480a648c1SLv Zheng  *
725ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
72680a648c1SLv Zheng  *
72780a648c1SLv Zheng  * DESCRIPTION: Formatted output to a file.
72880a648c1SLv Zheng  *
72980a648c1SLv Zheng  ******************************************************************************/
73080a648c1SLv Zheng 
731f173a775SLv Zheng int fprintf(FILE * file, const char *format, ...)
73280a648c1SLv Zheng {
73380a648c1SLv Zheng 	va_list args;
73480a648c1SLv Zheng 	int length;
73580a648c1SLv Zheng 
73680a648c1SLv Zheng 	va_start(args, format);
737f173a775SLv Zheng 	length = vfprintf(file, format, args);
73880a648c1SLv Zheng 	va_end(args);
73980a648c1SLv Zheng 
74080a648c1SLv Zheng 	return (length);
74180a648c1SLv Zheng }
74280a648c1SLv Zheng #endif
743