xref: /openbmc/linux/drivers/acpi/acpica/utprint.c (revision 1fad8738)
180a648c1SLv Zheng /******************************************************************************
280a648c1SLv Zheng  *
380a648c1SLv Zheng  * Module Name: utprint - Formatted printing routines
480a648c1SLv Zheng  *
580a648c1SLv Zheng  *****************************************************************************/
680a648c1SLv Zheng 
780a648c1SLv Zheng /*
882a80941SDavid E. Box  * Copyright (C) 2000 - 2015, 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 
1834fa4616eSBob Moore 	while (isdigit((int)*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 {
2458884de6aSBob Moore 	char *pos;
24680a648c1SLv Zheng 	char sign;
24780a648c1SLv Zheng 	char zero;
24880a648c1SLv Zheng 	u8 need_prefix;
24980a648c1SLv Zheng 	u8 upper;
25080a648c1SLv Zheng 	s32 i;
25180a648c1SLv Zheng 	char reversed_string[66];
25280a648c1SLv Zheng 
253ff2389feSBob Moore 	/* Parameter validation */
25480a648c1SLv Zheng 
25580a648c1SLv Zheng 	if (base < 2 || base > 16) {
256ff2389feSBob Moore 		return (NULL);
25780a648c1SLv Zheng 	}
258ff2389feSBob Moore 
25980a648c1SLv Zheng 	if (type & ACPI_FORMAT_LEFT) {
26080a648c1SLv Zheng 		type &= ~ACPI_FORMAT_ZERO;
26180a648c1SLv Zheng 	}
26280a648c1SLv Zheng 
26380a648c1SLv Zheng 	need_prefix = ((type & ACPI_FORMAT_PREFIX)
26480a648c1SLv Zheng 		       && base != 10) ? TRUE : FALSE;
26580a648c1SLv Zheng 	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
26680a648c1SLv Zheng 	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
26780a648c1SLv Zheng 
26880a648c1SLv Zheng 	/* Calculate size according to sign and prefix */
26980a648c1SLv Zheng 
27080a648c1SLv Zheng 	sign = '\0';
27180a648c1SLv Zheng 	if (type & ACPI_FORMAT_SIGN) {
27280a648c1SLv Zheng 		if ((s64) number < 0) {
27380a648c1SLv Zheng 			sign = '-';
27480a648c1SLv Zheng 			number = -(s64) number;
27580a648c1SLv Zheng 			width--;
27680a648c1SLv Zheng 		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
27780a648c1SLv Zheng 			sign = '+';
27880a648c1SLv Zheng 			width--;
27980a648c1SLv Zheng 		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
28080a648c1SLv Zheng 			sign = ' ';
28180a648c1SLv Zheng 			width--;
28280a648c1SLv Zheng 		}
28380a648c1SLv Zheng 	}
28480a648c1SLv Zheng 	if (need_prefix) {
28580a648c1SLv Zheng 		width--;
28680a648c1SLv Zheng 		if (base == 16) {
28780a648c1SLv Zheng 			width--;
28880a648c1SLv Zheng 		}
28980a648c1SLv Zheng 	}
29080a648c1SLv Zheng 
29180a648c1SLv Zheng 	/* Generate full string in reverse order */
29280a648c1SLv Zheng 
2938884de6aSBob Moore 	pos = acpi_ut_put_number(reversed_string, number, base, upper);
2948884de6aSBob Moore 	i = ACPI_PTR_DIFF(pos, 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) {
3171fad8738SBob Moore 			string =
3181fad8738SBob Moore 			    acpi_ut_bound_string_output(string, end,
31980a648c1SLv Zheng 							upper ? 'X' : 'x');
32080a648c1SLv Zheng 		}
32180a648c1SLv Zheng 	}
32280a648c1SLv Zheng 	if (!(type & ACPI_FORMAT_LEFT)) {
32380a648c1SLv Zheng 		while (--width >= 0) {
32480a648c1SLv Zheng 			string = acpi_ut_bound_string_output(string, end, zero);
32580a648c1SLv Zheng 		}
32680a648c1SLv Zheng 	}
327ff2389feSBob Moore 
32880a648c1SLv Zheng 	while (i <= --precision) {
32980a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, '0');
33080a648c1SLv Zheng 	}
33180a648c1SLv Zheng 	while (--i >= 0) {
33280a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end,
33380a648c1SLv Zheng 						     reversed_string[i]);
33480a648c1SLv Zheng 	}
33580a648c1SLv Zheng 	while (--width >= 0) {
33680a648c1SLv Zheng 		string = acpi_ut_bound_string_output(string, end, ' ');
33780a648c1SLv Zheng 	}
33880a648c1SLv Zheng 
33980a648c1SLv Zheng 	return (string);
34080a648c1SLv Zheng }
34180a648c1SLv Zheng 
34280a648c1SLv Zheng /*******************************************************************************
34380a648c1SLv Zheng  *
34480a648c1SLv Zheng  * FUNCTION:    acpi_ut_vsnprintf
34580a648c1SLv Zheng  *
34680a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
34780a648c1SLv Zheng  *              size                - Boundary of the string
34880a648c1SLv Zheng  *              format              - Standard printf format
34980a648c1SLv Zheng  *              args                - Argument list
35080a648c1SLv Zheng  *
351ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
35280a648c1SLv Zheng  *
35380a648c1SLv Zheng  * DESCRIPTION: Formatted output to a string using argument list pointer.
35480a648c1SLv Zheng  *
35580a648c1SLv Zheng  ******************************************************************************/
35680a648c1SLv Zheng 
35780a648c1SLv Zheng int
35880a648c1SLv Zheng acpi_ut_vsnprintf(char *string,
35980a648c1SLv Zheng 		  acpi_size size, const char *format, va_list args)
36080a648c1SLv Zheng {
361cef9aaa7SLv Zheng 	u8 base;
362cef9aaa7SLv Zheng 	u8 type;
363cef9aaa7SLv Zheng 	s32 width;
364cef9aaa7SLv Zheng 	s32 precision;
365cef9aaa7SLv Zheng 	char qualifier;
36680a648c1SLv Zheng 	u64 number;
36780a648c1SLv Zheng 	char *pos;
36880a648c1SLv Zheng 	char *end;
36980a648c1SLv Zheng 	char c;
37080a648c1SLv Zheng 	const char *s;
37180a648c1SLv Zheng 	const void *p;
37280a648c1SLv Zheng 	s32 length;
37380a648c1SLv Zheng 	int i;
37480a648c1SLv Zheng 
37580a648c1SLv Zheng 	pos = string;
37680a648c1SLv Zheng 	end = string + size;
37780a648c1SLv Zheng 
37880a648c1SLv Zheng 	for (; *format; ++format) {
37980a648c1SLv Zheng 		if (*format != '%') {
38080a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, *format);
38180a648c1SLv Zheng 			continue;
38280a648c1SLv Zheng 		}
38380a648c1SLv Zheng 
384cef9aaa7SLv Zheng 		type = 0;
385cef9aaa7SLv Zheng 		base = 10;
386cef9aaa7SLv Zheng 
38780a648c1SLv Zheng 		/* Process sign */
38880a648c1SLv Zheng 
38980a648c1SLv Zheng 		do {
39080a648c1SLv Zheng 			++format;
39180a648c1SLv Zheng 			if (*format == '#') {
39280a648c1SLv Zheng 				type |= ACPI_FORMAT_PREFIX;
39380a648c1SLv Zheng 			} else if (*format == '0') {
39480a648c1SLv Zheng 				type |= ACPI_FORMAT_ZERO;
39580a648c1SLv Zheng 			} else if (*format == '+') {
39680a648c1SLv Zheng 				type |= ACPI_FORMAT_SIGN_PLUS;
39780a648c1SLv Zheng 			} else if (*format == ' ') {
39880a648c1SLv Zheng 				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
39980a648c1SLv Zheng 			} else if (*format == '-') {
40080a648c1SLv Zheng 				type |= ACPI_FORMAT_LEFT;
40180a648c1SLv Zheng 			} else {
40280a648c1SLv Zheng 				break;
40380a648c1SLv Zheng 			}
4041fad8738SBob Moore 
40580a648c1SLv Zheng 		} while (1);
40680a648c1SLv Zheng 
40780a648c1SLv Zheng 		/* Process width */
40880a648c1SLv Zheng 
4093589b8b8SLv Zheng 		width = -1;
4104fa4616eSBob Moore 		if (isdigit((int)*format)) {
41180a648c1SLv Zheng 			format = acpi_ut_scan_number(format, &number);
41280a648c1SLv Zheng 			width = (s32) number;
41380a648c1SLv Zheng 		} else if (*format == '*') {
41480a648c1SLv Zheng 			++format;
41580a648c1SLv Zheng 			width = va_arg(args, int);
41680a648c1SLv Zheng 			if (width < 0) {
41780a648c1SLv Zheng 				width = -width;
41880a648c1SLv Zheng 				type |= ACPI_FORMAT_LEFT;
41980a648c1SLv Zheng 			}
42080a648c1SLv Zheng 		}
42180a648c1SLv Zheng 
42280a648c1SLv Zheng 		/* Process precision */
42380a648c1SLv Zheng 
4243589b8b8SLv Zheng 		precision = -1;
42580a648c1SLv Zheng 		if (*format == '.') {
42680a648c1SLv Zheng 			++format;
4274fa4616eSBob Moore 			if (isdigit((int)*format)) {
42880a648c1SLv Zheng 				format = acpi_ut_scan_number(format, &number);
42980a648c1SLv Zheng 				precision = (s32) number;
43080a648c1SLv Zheng 			} else if (*format == '*') {
43180a648c1SLv Zheng 				++format;
43280a648c1SLv Zheng 				precision = va_arg(args, int);
43380a648c1SLv Zheng 			}
4341fad8738SBob Moore 
43580a648c1SLv Zheng 			if (precision < 0) {
43680a648c1SLv Zheng 				precision = 0;
43780a648c1SLv Zheng 			}
43880a648c1SLv Zheng 		}
43980a648c1SLv Zheng 
44080a648c1SLv Zheng 		/* Process qualifier */
44180a648c1SLv Zheng 
4423589b8b8SLv Zheng 		qualifier = -1;
44380a648c1SLv Zheng 		if (*format == 'h' || *format == 'l' || *format == 'L') {
44480a648c1SLv Zheng 			qualifier = *format;
44580a648c1SLv Zheng 			++format;
446ff2389feSBob Moore 
44780a648c1SLv Zheng 			if (qualifier == 'l' && *format == 'l') {
44880a648c1SLv Zheng 				qualifier = 'L';
44980a648c1SLv Zheng 				++format;
45080a648c1SLv Zheng 			}
45180a648c1SLv Zheng 		}
45280a648c1SLv Zheng 
45380a648c1SLv Zheng 		switch (*format) {
45480a648c1SLv Zheng 		case '%':
45580a648c1SLv Zheng 
45680a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, '%');
45780a648c1SLv Zheng 			continue;
45880a648c1SLv Zheng 
45980a648c1SLv Zheng 		case 'c':
46080a648c1SLv Zheng 
46180a648c1SLv Zheng 			if (!(type & ACPI_FORMAT_LEFT)) {
46280a648c1SLv Zheng 				while (--width > 0) {
46380a648c1SLv Zheng 					pos =
46480a648c1SLv Zheng 					    acpi_ut_bound_string_output(pos,
46580a648c1SLv Zheng 									end,
46680a648c1SLv Zheng 									' ');
46780a648c1SLv Zheng 				}
46880a648c1SLv Zheng 			}
469ff2389feSBob Moore 
47080a648c1SLv Zheng 			c = (char)va_arg(args, int);
47180a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, c);
472ff2389feSBob Moore 
47380a648c1SLv Zheng 			while (--width > 0) {
47480a648c1SLv Zheng 				pos =
47580a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end, ' ');
47680a648c1SLv Zheng 			}
47780a648c1SLv Zheng 			continue;
47880a648c1SLv Zheng 
47980a648c1SLv Zheng 		case 's':
48080a648c1SLv Zheng 
48180a648c1SLv Zheng 			s = va_arg(args, char *);
48280a648c1SLv Zheng 			if (!s) {
48380a648c1SLv Zheng 				s = "<NULL>";
48480a648c1SLv Zheng 			}
48580a648c1SLv Zheng 			length = acpi_ut_bound_string_length(s, precision);
48680a648c1SLv Zheng 			if (!(type & ACPI_FORMAT_LEFT)) {
48780a648c1SLv Zheng 				while (length < width--) {
48880a648c1SLv Zheng 					pos =
48980a648c1SLv Zheng 					    acpi_ut_bound_string_output(pos,
49080a648c1SLv Zheng 									end,
49180a648c1SLv Zheng 									' ');
49280a648c1SLv Zheng 				}
49380a648c1SLv Zheng 			}
4941fad8738SBob Moore 
49580a648c1SLv Zheng 			for (i = 0; i < length; ++i) {
49680a648c1SLv Zheng 				pos = acpi_ut_bound_string_output(pos, end, *s);
49780a648c1SLv Zheng 				++s;
49880a648c1SLv Zheng 			}
4991fad8738SBob Moore 
50080a648c1SLv Zheng 			while (length < width--) {
50180a648c1SLv Zheng 				pos =
50280a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end, ' ');
50380a648c1SLv Zheng 			}
50480a648c1SLv Zheng 			continue;
50580a648c1SLv Zheng 
50680a648c1SLv Zheng 		case 'o':
50780a648c1SLv Zheng 
50880a648c1SLv Zheng 			base = 8;
50980a648c1SLv Zheng 			break;
51080a648c1SLv Zheng 
51180a648c1SLv Zheng 		case 'X':
51280a648c1SLv Zheng 
51380a648c1SLv Zheng 			type |= ACPI_FORMAT_UPPER;
51480a648c1SLv Zheng 
51580a648c1SLv Zheng 		case 'x':
51680a648c1SLv Zheng 
51780a648c1SLv Zheng 			base = 16;
51880a648c1SLv Zheng 			break;
51980a648c1SLv Zheng 
52080a648c1SLv Zheng 		case 'd':
52180a648c1SLv Zheng 		case 'i':
52280a648c1SLv Zheng 
52380a648c1SLv Zheng 			type |= ACPI_FORMAT_SIGN;
52480a648c1SLv Zheng 
52580a648c1SLv Zheng 		case 'u':
52680a648c1SLv Zheng 
52780a648c1SLv Zheng 			break;
52880a648c1SLv Zheng 
52980a648c1SLv Zheng 		case 'p':
53080a648c1SLv Zheng 
53180a648c1SLv Zheng 			if (width == -1) {
53280a648c1SLv Zheng 				width = 2 * sizeof(void *);
53380a648c1SLv Zheng 				type |= ACPI_FORMAT_ZERO;
53480a648c1SLv Zheng 			}
535ff2389feSBob Moore 
53680a648c1SLv Zheng 			p = va_arg(args, void *);
5371fad8738SBob Moore 			pos =
5381fad8738SBob Moore 			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
5391fad8738SBob Moore 						  16, width, precision, type);
54080a648c1SLv Zheng 			continue;
54180a648c1SLv Zheng 
54280a648c1SLv Zheng 		default:
54380a648c1SLv Zheng 
54480a648c1SLv Zheng 			pos = acpi_ut_bound_string_output(pos, end, '%');
54580a648c1SLv Zheng 			if (*format) {
54680a648c1SLv Zheng 				pos =
54780a648c1SLv Zheng 				    acpi_ut_bound_string_output(pos, end,
54880a648c1SLv Zheng 								*format);
54980a648c1SLv Zheng 			} else {
55080a648c1SLv Zheng 				--format;
55180a648c1SLv Zheng 			}
55280a648c1SLv Zheng 			continue;
55380a648c1SLv Zheng 		}
55480a648c1SLv Zheng 
55580a648c1SLv Zheng 		if (qualifier == 'L') {
55680a648c1SLv Zheng 			number = va_arg(args, u64);
55780a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
55880a648c1SLv Zheng 				number = (s64) number;
55980a648c1SLv Zheng 			}
56080a648c1SLv Zheng 		} else if (qualifier == 'l') {
56180a648c1SLv Zheng 			number = va_arg(args, unsigned long);
56280a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
56380a648c1SLv Zheng 				number = (s32) number;
56480a648c1SLv Zheng 			}
56580a648c1SLv Zheng 		} else if (qualifier == 'h') {
56680a648c1SLv Zheng 			number = (u16)va_arg(args, int);
56780a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
56880a648c1SLv Zheng 				number = (s16) number;
56980a648c1SLv Zheng 			}
57080a648c1SLv Zheng 		} else {
57180a648c1SLv Zheng 			number = va_arg(args, unsigned int);
57280a648c1SLv Zheng 			if (type & ACPI_FORMAT_SIGN) {
57380a648c1SLv Zheng 				number = (signed int)number;
57480a648c1SLv Zheng 			}
57580a648c1SLv Zheng 		}
576ff2389feSBob Moore 
57780a648c1SLv Zheng 		pos = acpi_ut_format_number(pos, end, number, base,
57880a648c1SLv Zheng 					    width, precision, type);
57980a648c1SLv Zheng 	}
58080a648c1SLv Zheng 
58180a648c1SLv Zheng 	if (size > 0) {
58280a648c1SLv Zheng 		if (pos < end) {
58380a648c1SLv Zheng 			*pos = '\0';
58480a648c1SLv Zheng 		} else {
58580a648c1SLv Zheng 			end[-1] = '\0';
58680a648c1SLv Zheng 		}
58780a648c1SLv Zheng 	}
58880a648c1SLv Zheng 
58980a648c1SLv Zheng 	return (ACPI_PTR_DIFF(pos, string));
59080a648c1SLv Zheng }
59180a648c1SLv Zheng 
59280a648c1SLv Zheng /*******************************************************************************
59380a648c1SLv Zheng  *
59480a648c1SLv Zheng  * FUNCTION:    acpi_ut_snprintf
59580a648c1SLv Zheng  *
59680a648c1SLv Zheng  * PARAMETERS:  string              - String with boundary
59780a648c1SLv Zheng  *              size                - Boundary of the string
59880a648c1SLv Zheng  *              Format, ...         - Standard printf format
59980a648c1SLv Zheng  *
600ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
60180a648c1SLv Zheng  *
60280a648c1SLv Zheng  * DESCRIPTION: Formatted output to a string.
60380a648c1SLv Zheng  *
60480a648c1SLv Zheng  ******************************************************************************/
60580a648c1SLv Zheng 
60680a648c1SLv Zheng int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
60780a648c1SLv Zheng {
60880a648c1SLv Zheng 	va_list args;
60980a648c1SLv Zheng 	int length;
61080a648c1SLv Zheng 
61180a648c1SLv Zheng 	va_start(args, format);
61280a648c1SLv Zheng 	length = acpi_ut_vsnprintf(string, size, format, args);
61380a648c1SLv Zheng 	va_end(args);
61480a648c1SLv Zheng 
61580a648c1SLv Zheng 	return (length);
61680a648c1SLv Zheng }
61780a648c1SLv Zheng 
61880a648c1SLv Zheng #ifdef ACPI_APPLICATION
61980a648c1SLv Zheng /*******************************************************************************
62080a648c1SLv Zheng  *
62180a648c1SLv Zheng  * FUNCTION:    acpi_ut_file_vprintf
62280a648c1SLv Zheng  *
62380a648c1SLv Zheng  * PARAMETERS:  file                - File descriptor
62480a648c1SLv Zheng  *              format              - Standard printf format
62580a648c1SLv Zheng  *              args                - Argument list
62680a648c1SLv Zheng  *
627ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
62880a648c1SLv Zheng  *
62980a648c1SLv Zheng  * DESCRIPTION: Formatted output to a file using argument list pointer.
63080a648c1SLv Zheng  *
63180a648c1SLv Zheng  ******************************************************************************/
63280a648c1SLv Zheng 
63380a648c1SLv Zheng int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
63480a648c1SLv Zheng {
63580a648c1SLv Zheng 	acpi_cpu_flags flags;
63680a648c1SLv Zheng 	int length;
63780a648c1SLv Zheng 
63880a648c1SLv Zheng 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
63980a648c1SLv Zheng 	length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
64080a648c1SLv Zheng 				   sizeof(acpi_gbl_print_buffer), format, args);
641ff2389feSBob Moore 
64280a648c1SLv Zheng 	(void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
64380a648c1SLv Zheng 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
64480a648c1SLv Zheng 
64580a648c1SLv Zheng 	return (length);
64680a648c1SLv Zheng }
64780a648c1SLv Zheng 
64880a648c1SLv Zheng /*******************************************************************************
64980a648c1SLv Zheng  *
65080a648c1SLv Zheng  * FUNCTION:    acpi_ut_file_printf
65180a648c1SLv Zheng  *
65280a648c1SLv Zheng  * PARAMETERS:  file                - File descriptor
65380a648c1SLv Zheng  *              Format, ...         - Standard printf format
65480a648c1SLv Zheng  *
655ff2389feSBob Moore  * RETURN:      Number of bytes actually written.
65680a648c1SLv Zheng  *
65780a648c1SLv Zheng  * DESCRIPTION: Formatted output to a file.
65880a648c1SLv Zheng  *
65980a648c1SLv Zheng  ******************************************************************************/
66080a648c1SLv Zheng 
66180a648c1SLv Zheng int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
66280a648c1SLv Zheng {
66380a648c1SLv Zheng 	va_list args;
66480a648c1SLv Zheng 	int length;
66580a648c1SLv Zheng 
66680a648c1SLv Zheng 	va_start(args, format);
66780a648c1SLv Zheng 	length = acpi_ut_file_vprintf(file, format, args);
66880a648c1SLv Zheng 	va_end(args);
66980a648c1SLv Zheng 
67080a648c1SLv Zheng 	return (length);
67180a648c1SLv Zheng }
67280a648c1SLv Zheng #endif
673