xref: /openbmc/linux/drivers/acpi/acpica/utprint.c (revision ff2389fe)
180a648c1SLv Zheng /******************************************************************************
280a648c1SLv Zheng  *
380a648c1SLv Zheng  * Module Name: utprint - Formatted printing routines
480a648c1SLv Zheng  *
580a648c1SLv Zheng  *****************************************************************************/
680a648c1SLv Zheng 
780a648c1SLv Zheng /*
880a648c1SLv Zheng  * Copyright (C) 2000 - 2014, 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 
70ff2389feSBob Moore /* Module globals */
71ff2389feSBob Moore 
72ff2389feSBob Moore static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
73ff2389feSBob Moore static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
74ff2389feSBob Moore 
7580a648c1SLv Zheng /*******************************************************************************
7680a648c1SLv Zheng  *
7780a648c1SLv Zheng  * FUNCTION:    acpi_ut_bound_string_length
7880a648c1SLv Zheng  *
7980a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
8080a648c1SLv Zheng  *              count               - Boundary of the string
8180a648c1SLv Zheng  *
82ff2389feSBob Moore  * RETURN:      Length of the string. Less than or equal to Count.
8380a648c1SLv Zheng  *
8480a648c1SLv Zheng  * DESCRIPTION: Calculate the length of a string with boundary.
8580a648c1SLv Zheng  *
8680a648c1SLv Zheng  ******************************************************************************/
8780a648c1SLv Zheng 
8880a648c1SLv Zheng static acpi_size
8980a648c1SLv Zheng acpi_ut_bound_string_length(const char *string, acpi_size count)
9080a648c1SLv Zheng {
9180a648c1SLv Zheng 	u32 length = 0;
9280a648c1SLv Zheng 
9380a648c1SLv Zheng 	while (*string && count) {
9480a648c1SLv Zheng 		length++;
9580a648c1SLv Zheng 		string++;
9680a648c1SLv Zheng 		count--;
9780a648c1SLv Zheng 	}
9880a648c1SLv Zheng 
9980a648c1SLv Zheng 	return (length);
10080a648c1SLv Zheng }
10180a648c1SLv Zheng 
10280a648c1SLv Zheng /*******************************************************************************
10380a648c1SLv Zheng  *
10480a648c1SLv Zheng  * FUNCTION:    acpi_ut_bound_string_output
10580a648c1SLv Zheng  *
10680a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
10780a648c1SLv Zheng  *              end                 - Boundary of the string
10880a648c1SLv Zheng  *              c                   - Character to be output to the string
10980a648c1SLv Zheng  *
11080a648c1SLv Zheng  * RETURN:      Updated position for next valid character
11180a648c1SLv Zheng  *
11280a648c1SLv Zheng  * DESCRIPTION: Output a character into a string with boundary check.
11380a648c1SLv Zheng  *
11480a648c1SLv Zheng  ******************************************************************************/
11580a648c1SLv Zheng 
11680a648c1SLv Zheng static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
11780a648c1SLv Zheng {
11880a648c1SLv Zheng 
11980a648c1SLv Zheng 	if (string < end) {
12080a648c1SLv Zheng 		*string = c;
12180a648c1SLv Zheng 	}
12280a648c1SLv Zheng 
123ff2389feSBob Moore 	++string;
12480a648c1SLv Zheng 	return (string);
12580a648c1SLv Zheng }
12680a648c1SLv Zheng 
12780a648c1SLv Zheng /*******************************************************************************
12880a648c1SLv Zheng  *
12980a648c1SLv Zheng  * FUNCTION:    acpi_ut_put_number
13080a648c1SLv Zheng  *
13180a648c1SLv Zheng  * PARAMETERS:  string              - Buffer to hold reverse-ordered string
13280a648c1SLv Zheng  *              number              - Integer to be converted
13380a648c1SLv Zheng  *              base                - Base of the integer
13480a648c1SLv Zheng  *              upper               - Whether or not using upper cased digits
13580a648c1SLv Zheng  *
13680a648c1SLv Zheng  * RETURN:      Updated position for next valid character
13780a648c1SLv Zheng  *
13880a648c1SLv Zheng  * DESCRIPTION: Convert an integer into a string, note that, the string holds a
13980a648c1SLv Zheng  *              reversed ordered number without the trailing zero.
14080a648c1SLv Zheng  *
14180a648c1SLv Zheng  ******************************************************************************/
14280a648c1SLv Zheng 
14380a648c1SLv Zheng static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
14480a648c1SLv Zheng {
14580a648c1SLv Zheng 	const char *digits;
14680a648c1SLv Zheng 	u64 digit_index;
14780a648c1SLv Zheng 	char *pos;
14880a648c1SLv Zheng 
14980a648c1SLv Zheng 	pos = string;
150ff2389feSBob Moore 	digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
15180a648c1SLv Zheng 
15280a648c1SLv Zheng 	if (number == 0) {
15380a648c1SLv Zheng 		*(pos++) = '0';
15480a648c1SLv Zheng 	} else {
15580a648c1SLv Zheng 		while (number) {
15680a648c1SLv Zheng 			(void)acpi_ut_divide(number, base, &number,
15780a648c1SLv Zheng 					     &digit_index);
15880a648c1SLv Zheng 			*(pos++) = digits[digit_index];
15980a648c1SLv Zheng 		}
16080a648c1SLv Zheng 	}
16180a648c1SLv Zheng 
162ff2389feSBob Moore 	/* *(Pos++) = '0'; */
16380a648c1SLv Zheng 	return (pos);
16480a648c1SLv Zheng }
16580a648c1SLv Zheng 
16680a648c1SLv Zheng /*******************************************************************************
16780a648c1SLv Zheng  *
16880a648c1SLv Zheng  * FUNCTION:    acpi_ut_scan_number
16980a648c1SLv Zheng  *
17080a648c1SLv Zheng  * PARAMETERS:  string              - String buffer
17180a648c1SLv Zheng  *              number_ptr          - Where the number is returned
17280a648c1SLv Zheng  *
17380a648c1SLv Zheng  * RETURN:      Updated position for next valid character
17480a648c1SLv Zheng  *
17580a648c1SLv Zheng  * DESCRIPTION: Scan a string for a decimal integer.
17680a648c1SLv Zheng  *
17780a648c1SLv Zheng  ******************************************************************************/
17880a648c1SLv Zheng 
17980a648c1SLv Zheng const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
18080a648c1SLv Zheng {
18180a648c1SLv Zheng 	u64 number = 0;
18280a648c1SLv Zheng 
18380a648c1SLv Zheng 	while (ACPI_IS_DIGIT(*string)) {
18480a648c1SLv Zheng 		number *= 10;
18580a648c1SLv Zheng 		number += *(string++) - '0';
18680a648c1SLv Zheng 	}
18780a648c1SLv Zheng 
188ff2389feSBob Moore 	*number_ptr = number;
18980a648c1SLv Zheng 	return (string);
19080a648c1SLv Zheng }
19180a648c1SLv Zheng 
19280a648c1SLv Zheng /*******************************************************************************
19380a648c1SLv Zheng  *
19480a648c1SLv Zheng  * FUNCTION:    acpi_ut_print_number
19580a648c1SLv Zheng  *
19680a648c1SLv Zheng  * PARAMETERS:  string              - String buffer
19780a648c1SLv Zheng  *              number              - The number to be converted
19880a648c1SLv Zheng  *
19980a648c1SLv Zheng  * RETURN:      Updated position for next valid character
20080a648c1SLv Zheng  *
20180a648c1SLv Zheng  * DESCRIPTION: Print a decimal integer into a string.
20280a648c1SLv Zheng  *
20380a648c1SLv Zheng  ******************************************************************************/
20480a648c1SLv Zheng 
20580a648c1SLv Zheng const char *acpi_ut_print_number(char *string, u64 number)
20680a648c1SLv Zheng {
20780a648c1SLv Zheng 	char ascii_string[20];
20880a648c1SLv Zheng 	const char *pos1;
20980a648c1SLv Zheng 	char *pos2;
21080a648c1SLv Zheng 
21180a648c1SLv Zheng 	pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
21280a648c1SLv Zheng 	pos2 = string;
21380a648c1SLv Zheng 
21480a648c1SLv Zheng 	while (pos1 != ascii_string) {
21580a648c1SLv Zheng 		*(pos2++) = *(--pos1);
21680a648c1SLv Zheng 	}
21780a648c1SLv Zheng 
218ff2389feSBob Moore 	*pos2 = 0;
21980a648c1SLv Zheng 	return (string);
22080a648c1SLv Zheng }
22180a648c1SLv Zheng 
22280a648c1SLv Zheng /*******************************************************************************
22380a648c1SLv Zheng  *
22480a648c1SLv Zheng  * FUNCTION:    acpi_ut_format_number
22580a648c1SLv Zheng  *
22680a648c1SLv Zheng  * PARAMETERS:  string              - String buffer with boundary
22780a648c1SLv Zheng  *              end                 - Boundary of the string
22880a648c1SLv Zheng  *              number              - The number to be converted
22980a648c1SLv Zheng  *              base                - Base of the integer
23080a648c1SLv Zheng  *              width               - Field width
23180a648c1SLv Zheng  *              precision           - Precision of the integer
23280a648c1SLv Zheng  *              type                - Special printing flags
23380a648c1SLv Zheng  *
23480a648c1SLv Zheng  * RETURN:      Updated position for next valid character
23580a648c1SLv Zheng  *
23680a648c1SLv Zheng  * DESCRIPTION: Print an integer into a string with any base and any precision.
23780a648c1SLv Zheng  *
23880a648c1SLv Zheng  ******************************************************************************/
23980a648c1SLv Zheng 
24080a648c1SLv Zheng static char *acpi_ut_format_number(char *string,
24180a648c1SLv Zheng 				   char *end,
24280a648c1SLv Zheng 				   u64 number,
24380a648c1SLv Zheng 				   u8 base, s32 width, s32 precision, u8 type)
24480a648c1SLv Zheng {
24580a648c1SLv Zheng 	char sign;
24680a648c1SLv Zheng 	char zero;
24780a648c1SLv Zheng 	u8 need_prefix;
24880a648c1SLv Zheng 	u8 upper;
24980a648c1SLv Zheng 	s32 i;
25080a648c1SLv Zheng 	char reversed_string[66];
25180a648c1SLv Zheng 
252ff2389feSBob Moore 	/* Parameter validation */
25380a648c1SLv Zheng 
25480a648c1SLv Zheng 	if (base < 2 || base > 16) {
255ff2389feSBob Moore 		return (NULL);
25680a648c1SLv Zheng 	}
257ff2389feSBob Moore 
25880a648c1SLv Zheng 	if (type & ACPI_FORMAT_LEFT) {
25980a648c1SLv Zheng 		type &= ~ACPI_FORMAT_ZERO;
26080a648c1SLv Zheng 	}
26180a648c1SLv Zheng 
26280a648c1SLv Zheng 	need_prefix = ((type & ACPI_FORMAT_PREFIX)
26380a648c1SLv Zheng 		       && base != 10) ? TRUE : FALSE;
26480a648c1SLv Zheng 	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
26580a648c1SLv Zheng 	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
26680a648c1SLv Zheng 
26780a648c1SLv Zheng 	/* Calculate size according to sign and prefix */
26880a648c1SLv Zheng 
26980a648c1SLv Zheng 	sign = '\0';
27080a648c1SLv Zheng 	if (type & ACPI_FORMAT_SIGN) {
27180a648c1SLv Zheng 		if ((s64) number < 0) {
27280a648c1SLv Zheng 			sign = '-';
27380a648c1SLv Zheng 			number = -(s64) number;
27480a648c1SLv Zheng 			width--;
27580a648c1SLv Zheng 		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
27680a648c1SLv Zheng 			sign = '+';
27780a648c1SLv Zheng 			width--;
27880a648c1SLv Zheng 		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
27980a648c1SLv Zheng 			sign = ' ';
28080a648c1SLv Zheng 			width--;
28180a648c1SLv Zheng 		}
28280a648c1SLv Zheng 	}
28380a648c1SLv Zheng 	if (need_prefix) {
28480a648c1SLv Zheng 		width--;
28580a648c1SLv Zheng 		if (base == 16) {
28680a648c1SLv Zheng 			width--;
28780a648c1SLv Zheng 		}
28880a648c1SLv Zheng 	}
28980a648c1SLv Zheng 
29080a648c1SLv Zheng 	/* Generate full string in reverse order */
29180a648c1SLv Zheng 
29280a648c1SLv Zheng 	i = ACPI_PTR_DIFF(acpi_ut_put_number
29380a648c1SLv Zheng 			  (reversed_string, number, base, upper),
29480a648c1SLv Zheng 			  reversed_string);
29580a648c1SLv Zheng 
29680a648c1SLv Zheng 	/* Printing 100 using %2d gives "100", not "00" */
29780a648c1SLv Zheng 
29880a648c1SLv Zheng 	if (i > precision) {
29980a648c1SLv Zheng 		precision = i;
30080a648c1SLv Zheng 	}
301ff2389feSBob Moore 
30280a648c1SLv Zheng 	width -= precision;
30380a648c1SLv Zheng 
30480a648c1SLv Zheng 	/* Output the string */
30580a648c1SLv Zheng 
30680a648c1SLv Zheng 	if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
30780a648c1SLv Zheng 		while (--width >= 0) {
30880a648c1SLv Zheng 			string = acpi_ut_bound_string_output(string, end, ' ');
30980a648c1SLv Zheng 		}
31080a648c1SLv Zheng 	}
31180a648c1SLv Zheng 	if (sign) {
31280a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, sign);
31380a648c1SLv Zheng 	}
31480a648c1SLv Zheng 	if (need_prefix) {
31580a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, '0');
31680a648c1SLv Zheng 		if (base == 16) {
31780a648c1SLv Zheng 			string = acpi_ut_bound_string_output(string, end,
31880a648c1SLv Zheng 							     upper ? 'X' : 'x');
31980a648c1SLv Zheng 		}
32080a648c1SLv Zheng 	}
32180a648c1SLv Zheng 	if (!(type & ACPI_FORMAT_LEFT)) {
32280a648c1SLv Zheng 		while (--width >= 0) {
32380a648c1SLv Zheng 			string = acpi_ut_bound_string_output(string, end, zero);
32480a648c1SLv Zheng 		}
32580a648c1SLv Zheng 	}
326ff2389feSBob Moore 
32780a648c1SLv Zheng 	while (i <= --precision) {
32880a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, '0');
32980a648c1SLv Zheng 	}
33080a648c1SLv Zheng 	while (--i >= 0) {
33180a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end,
33280a648c1SLv Zheng 						     reversed_string[i]);
33380a648c1SLv Zheng 	}
33480a648c1SLv Zheng 	while (--width >= 0) {
33580a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, ' ');
33680a648c1SLv Zheng 	}
33780a648c1SLv Zheng 
33880a648c1SLv Zheng 	return (string);
33980a648c1SLv Zheng }
34080a648c1SLv Zheng 
34180a648c1SLv Zheng /*******************************************************************************
34280a648c1SLv Zheng  *
34380a648c1SLv Zheng  * FUNCTION:    acpi_ut_vsnprintf
34480a648c1SLv Zheng  *
34580a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
34680a648c1SLv Zheng  *              size                - Boundary of the string
34780a648c1SLv Zheng  *              format              - Standard printf format
34880a648c1SLv Zheng  *              args                - Argument list
34980a648c1SLv Zheng  *
350ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
35180a648c1SLv Zheng  *
35280a648c1SLv Zheng  * DESCRIPTION: Formatted output to a string using argument list pointer.
35380a648c1SLv Zheng  *
35480a648c1SLv Zheng  ******************************************************************************/
35580a648c1SLv Zheng 
35680a648c1SLv Zheng int
35780a648c1SLv Zheng acpi_ut_vsnprintf(char *string,
35880a648c1SLv Zheng 		  acpi_size size, const char *format, va_list args)
35980a648c1SLv Zheng {
36080a648c1SLv Zheng 	u8 base = 10;
36180a648c1SLv Zheng 	u8 type = 0;
36280a648c1SLv Zheng 	s32 width = -1;
36380a648c1SLv Zheng 	s32 precision = -1;
36480a648c1SLv Zheng 	char qualifier = 0;
36580a648c1SLv Zheng 	u64 number;
36680a648c1SLv Zheng 	char *pos;
36780a648c1SLv Zheng 	char *end;
36880a648c1SLv Zheng 	char c;
36980a648c1SLv Zheng 	const char *s;
37080a648c1SLv Zheng 	const void *p;
37180a648c1SLv Zheng 	s32 length;
37280a648c1SLv Zheng 	int i;
37380a648c1SLv Zheng 
37480a648c1SLv Zheng 	pos = string;
37580a648c1SLv Zheng 	end = string + size;
37680a648c1SLv Zheng 
37780a648c1SLv Zheng 	for (; *format; ++format) {
37880a648c1SLv Zheng 		if (*format != '%') {
37980a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, *format);
38080a648c1SLv Zheng 			continue;
38180a648c1SLv Zheng 		}
38280a648c1SLv Zheng 
38380a648c1SLv Zheng 		/* Process sign */
38480a648c1SLv Zheng 
38580a648c1SLv Zheng 		do {
38680a648c1SLv Zheng 			++format;
38780a648c1SLv Zheng 			if (*format == '#') {
38880a648c1SLv Zheng 				type |= ACPI_FORMAT_PREFIX;
38980a648c1SLv Zheng 			} else if (*format == '0') {
39080a648c1SLv Zheng 				type |= ACPI_FORMAT_ZERO;
39180a648c1SLv Zheng 			} else if (*format == '+') {
39280a648c1SLv Zheng 				type |= ACPI_FORMAT_SIGN_PLUS;
39380a648c1SLv Zheng 			} else if (*format == ' ') {
39480a648c1SLv Zheng 				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
39580a648c1SLv Zheng 			} else if (*format == '-') {
39680a648c1SLv Zheng 				type |= ACPI_FORMAT_LEFT;
39780a648c1SLv Zheng 			} else {
39880a648c1SLv Zheng 				break;
39980a648c1SLv Zheng 			}
40080a648c1SLv Zheng 		} while (1);
40180a648c1SLv Zheng 
40280a648c1SLv Zheng 		/* Process width */
40380a648c1SLv Zheng 
40480a648c1SLv Zheng 		if (ACPI_IS_DIGIT(*format)) {
40580a648c1SLv Zheng 			format = acpi_ut_scan_number(format, &number);
40680a648c1SLv Zheng 			width = (s32) number;
40780a648c1SLv Zheng 		} else if (*format == '*') {
40880a648c1SLv Zheng 			++format;
40980a648c1SLv Zheng 			width = va_arg(args, int);
41080a648c1SLv Zheng 			if (width < 0) {
41180a648c1SLv Zheng 				width = -width;
41280a648c1SLv Zheng 				type |= ACPI_FORMAT_LEFT;
41380a648c1SLv Zheng 			}
41480a648c1SLv Zheng 		}
41580a648c1SLv Zheng 
41680a648c1SLv Zheng 		/* Process precision */
41780a648c1SLv Zheng 
41880a648c1SLv Zheng 		if (*format == '.') {
41980a648c1SLv Zheng 			++format;
42080a648c1SLv Zheng 			if (ACPI_IS_DIGIT(*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 			}
42780a648c1SLv Zheng 			if (precision < 0) {
42880a648c1SLv Zheng 				precision = 0;
42980a648c1SLv Zheng 			}
43080a648c1SLv Zheng 		}
43180a648c1SLv Zheng 
43280a648c1SLv Zheng 		/* Process qualifier */
43380a648c1SLv Zheng 
43480a648c1SLv Zheng 		if (*format == 'h' || *format == 'l' || *format == 'L') {
43580a648c1SLv Zheng 			qualifier = *format;
43680a648c1SLv Zheng 			++format;
437ff2389feSBob Moore 
43880a648c1SLv Zheng 			if (qualifier == 'l' && *format == 'l') {
43980a648c1SLv Zheng 				qualifier = 'L';
44080a648c1SLv Zheng 				++format;
44180a648c1SLv Zheng 			}
44280a648c1SLv Zheng 		}
44380a648c1SLv Zheng 
44480a648c1SLv Zheng 		switch (*format) {
44580a648c1SLv Zheng 		case '%':
44680a648c1SLv Zheng 
44780a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, '%');
44880a648c1SLv Zheng 			continue;
44980a648c1SLv Zheng 
45080a648c1SLv Zheng 		case 'c':
45180a648c1SLv Zheng 
45280a648c1SLv Zheng 			if (!(type & ACPI_FORMAT_LEFT)) {
45380a648c1SLv Zheng 				while (--width > 0) {
45480a648c1SLv Zheng 					pos =
45580a648c1SLv Zheng 					    acpi_ut_bound_string_output(pos,
45680a648c1SLv Zheng 									end,
45780a648c1SLv Zheng 									' ');
45880a648c1SLv Zheng 				}
45980a648c1SLv Zheng 			}
460ff2389feSBob Moore 
46180a648c1SLv Zheng 			c = (char)va_arg(args, int);
46280a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, c);
463ff2389feSBob Moore 
46480a648c1SLv Zheng 			while (--width > 0) {
46580a648c1SLv Zheng 				pos =
46680a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end, ' ');
46780a648c1SLv Zheng 			}
46880a648c1SLv Zheng 			continue;
46980a648c1SLv Zheng 
47080a648c1SLv Zheng 		case 's':
47180a648c1SLv Zheng 
47280a648c1SLv Zheng 			s = va_arg(args, char *);
47380a648c1SLv Zheng 			if (!s) {
47480a648c1SLv Zheng 				s = "<NULL>";
47580a648c1SLv Zheng 			}
47680a648c1SLv Zheng 			length = acpi_ut_bound_string_length(s, precision);
47780a648c1SLv Zheng 			if (!(type & ACPI_FORMAT_LEFT)) {
47880a648c1SLv Zheng 				while (length < width--) {
47980a648c1SLv Zheng 					pos =
48080a648c1SLv Zheng 					    acpi_ut_bound_string_output(pos,
48180a648c1SLv Zheng 									end,
48280a648c1SLv Zheng 									' ');
48380a648c1SLv Zheng 				}
48480a648c1SLv Zheng 			}
48580a648c1SLv Zheng 			for (i = 0; i < length; ++i) {
48680a648c1SLv Zheng 				pos = acpi_ut_bound_string_output(pos, end, *s);
48780a648c1SLv Zheng 				++s;
48880a648c1SLv Zheng 			}
48980a648c1SLv Zheng 			while (length < width--) {
49080a648c1SLv Zheng 				pos =
49180a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end, ' ');
49280a648c1SLv Zheng 			}
49380a648c1SLv Zheng 			continue;
49480a648c1SLv Zheng 
49580a648c1SLv Zheng 		case 'o':
49680a648c1SLv Zheng 
49780a648c1SLv Zheng 			base = 8;
49880a648c1SLv Zheng 			break;
49980a648c1SLv Zheng 
50080a648c1SLv Zheng 		case 'X':
50180a648c1SLv Zheng 
50280a648c1SLv Zheng 			type |= ACPI_FORMAT_UPPER;
50380a648c1SLv Zheng 
50480a648c1SLv Zheng 		case 'x':
50580a648c1SLv Zheng 
50680a648c1SLv Zheng 			base = 16;
50780a648c1SLv Zheng 			break;
50880a648c1SLv Zheng 
50980a648c1SLv Zheng 		case 'd':
51080a648c1SLv Zheng 		case 'i':
51180a648c1SLv Zheng 
51280a648c1SLv Zheng 			type |= ACPI_FORMAT_SIGN;
51380a648c1SLv Zheng 
51480a648c1SLv Zheng 		case 'u':
51580a648c1SLv Zheng 
51680a648c1SLv Zheng 			break;
51780a648c1SLv Zheng 
51880a648c1SLv Zheng 		case 'p':
51980a648c1SLv Zheng 
52080a648c1SLv Zheng 			if (width == -1) {
52180a648c1SLv Zheng 				width = 2 * sizeof(void *);
52280a648c1SLv Zheng 				type |= ACPI_FORMAT_ZERO;
52380a648c1SLv Zheng 			}
524ff2389feSBob Moore 
52580a648c1SLv Zheng 			p = va_arg(args, void *);
52680a648c1SLv Zheng 			pos = acpi_ut_format_number(pos, end,
527ff2389feSBob Moore 						    ACPI_TO_INTEGER(p), 16,
528ff2389feSBob Moore 						    width, precision, type);
52980a648c1SLv Zheng 			continue;
53080a648c1SLv Zheng 
53180a648c1SLv Zheng 		default:
53280a648c1SLv Zheng 
53380a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, '%');
53480a648c1SLv Zheng 			if (*format) {
53580a648c1SLv Zheng 				pos =
53680a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end,
53780a648c1SLv Zheng 								*format);
53880a648c1SLv Zheng 			} else {
53980a648c1SLv Zheng 				--format;
54080a648c1SLv Zheng 			}
54180a648c1SLv Zheng 			continue;
54280a648c1SLv Zheng 		}
54380a648c1SLv Zheng 
54480a648c1SLv Zheng 		if (qualifier == 'L') {
54580a648c1SLv Zheng 			number = va_arg(args, u64);
54680a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
54780a648c1SLv Zheng 				number = (s64) number;
54880a648c1SLv Zheng 			}
54980a648c1SLv Zheng 		} else if (qualifier == 'l') {
55080a648c1SLv Zheng 			number = va_arg(args, unsigned long);
55180a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
55280a648c1SLv Zheng 				number = (s32) number;
55380a648c1SLv Zheng 			}
55480a648c1SLv Zheng 		} else if (qualifier == 'h') {
55580a648c1SLv Zheng 			number = (u16)va_arg(args, int);
55680a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
55780a648c1SLv Zheng 				number = (s16) number;
55880a648c1SLv Zheng 			}
55980a648c1SLv Zheng 		} else {
56080a648c1SLv Zheng 			number = va_arg(args, unsigned int);
56180a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
56280a648c1SLv Zheng 				number = (signed int)number;
56380a648c1SLv Zheng 			}
56480a648c1SLv Zheng 		}
565ff2389feSBob Moore 
56680a648c1SLv Zheng 		pos = acpi_ut_format_number(pos, end, number, base,
56780a648c1SLv Zheng 					    width, precision, type);
56880a648c1SLv Zheng 	}
56980a648c1SLv Zheng 
57080a648c1SLv Zheng 	if (size > 0) {
57180a648c1SLv Zheng 		if (pos < end) {
57280a648c1SLv Zheng 			*pos = '\0';
57380a648c1SLv Zheng 		} else {
57480a648c1SLv Zheng 			end[-1] = '\0';
57580a648c1SLv Zheng 		}
57680a648c1SLv Zheng 	}
57780a648c1SLv Zheng 
57880a648c1SLv Zheng 	return (ACPI_PTR_DIFF(pos, string));
57980a648c1SLv Zheng }
58080a648c1SLv Zheng 
58180a648c1SLv Zheng /*******************************************************************************
58280a648c1SLv Zheng  *
58380a648c1SLv Zheng  * FUNCTION:    acpi_ut_snprintf
58480a648c1SLv Zheng  *
58580a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
58680a648c1SLv Zheng  *              size                - Boundary of the string
58780a648c1SLv Zheng  *              Format, ...         - Standard printf format
58880a648c1SLv Zheng  *
589ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
59080a648c1SLv Zheng  *
59180a648c1SLv Zheng  * DESCRIPTION: Formatted output to a string.
59280a648c1SLv Zheng  *
59380a648c1SLv Zheng  ******************************************************************************/
59480a648c1SLv Zheng 
59580a648c1SLv Zheng int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
59680a648c1SLv Zheng {
59780a648c1SLv Zheng 	va_list args;
59880a648c1SLv Zheng 	int length;
59980a648c1SLv Zheng 
60080a648c1SLv Zheng 	va_start(args, format);
60180a648c1SLv Zheng 	length = acpi_ut_vsnprintf(string, size, format, args);
60280a648c1SLv Zheng 	va_end(args);
60380a648c1SLv Zheng 
60480a648c1SLv Zheng 	return (length);
60580a648c1SLv Zheng }
60680a648c1SLv Zheng 
60780a648c1SLv Zheng #ifdef ACPI_APPLICATION
60880a648c1SLv Zheng /*******************************************************************************
60980a648c1SLv Zheng  *
61080a648c1SLv Zheng  * FUNCTION:    acpi_ut_file_vprintf
61180a648c1SLv Zheng  *
61280a648c1SLv Zheng  * PARAMETERS:  file                - File descriptor
61380a648c1SLv Zheng  *              format              - Standard printf format
61480a648c1SLv Zheng  *              args                - Argument list
61580a648c1SLv Zheng  *
616ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
61780a648c1SLv Zheng  *
61880a648c1SLv Zheng  * DESCRIPTION: Formatted output to a file using argument list pointer.
61980a648c1SLv Zheng  *
62080a648c1SLv Zheng  ******************************************************************************/
62180a648c1SLv Zheng 
62280a648c1SLv Zheng int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
62380a648c1SLv Zheng {
62480a648c1SLv Zheng 	acpi_cpu_flags flags;
62580a648c1SLv Zheng 	int length;
62680a648c1SLv Zheng 
62780a648c1SLv Zheng 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
62880a648c1SLv Zheng 	length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
62980a648c1SLv Zheng 				   sizeof(acpi_gbl_print_buffer), format, args);
630ff2389feSBob Moore 
63180a648c1SLv Zheng 	(void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
63280a648c1SLv Zheng 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
63380a648c1SLv Zheng 
63480a648c1SLv Zheng 	return (length);
63580a648c1SLv Zheng }
63680a648c1SLv Zheng 
63780a648c1SLv Zheng /*******************************************************************************
63880a648c1SLv Zheng  *
63980a648c1SLv Zheng  * FUNCTION:    acpi_ut_file_printf
64080a648c1SLv Zheng  *
64180a648c1SLv Zheng  * PARAMETERS:  file                - File descriptor
64280a648c1SLv Zheng  *              Format, ...         - Standard printf format
64380a648c1SLv Zheng  *
644ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
64580a648c1SLv Zheng  *
64680a648c1SLv Zheng  * DESCRIPTION: Formatted output to a file.
64780a648c1SLv Zheng  *
64880a648c1SLv Zheng  ******************************************************************************/
64980a648c1SLv Zheng 
65080a648c1SLv Zheng int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
65180a648c1SLv Zheng {
65280a648c1SLv Zheng 	va_list args;
65380a648c1SLv Zheng 	int length;
65480a648c1SLv Zheng 
65580a648c1SLv Zheng 	va_start(args, format);
65680a648c1SLv Zheng 	length = acpi_ut_file_vprintf(file, format, args);
65780a648c1SLv Zheng 	va_end(args);
65880a648c1SLv Zheng 
65980a648c1SLv Zheng 	return (length);
66080a648c1SLv Zheng }
66180a648c1SLv Zheng #endif
662