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) { 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 { 360cef9aaa7SLv Zheng u8 base; 361cef9aaa7SLv Zheng u8 type; 362cef9aaa7SLv Zheng s32 width; 363cef9aaa7SLv Zheng s32 precision; 364cef9aaa7SLv Zheng char qualifier; 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 383cef9aaa7SLv Zheng type = 0; 384cef9aaa7SLv Zheng base = 10; 385cef9aaa7SLv Zheng 38680a648c1SLv Zheng /* Process sign */ 38780a648c1SLv Zheng 38880a648c1SLv Zheng do { 38980a648c1SLv Zheng ++format; 39080a648c1SLv Zheng if (*format == '#') { 39180a648c1SLv Zheng type |= ACPI_FORMAT_PREFIX; 39280a648c1SLv Zheng } else if (*format == '0') { 39380a648c1SLv Zheng type |= ACPI_FORMAT_ZERO; 39480a648c1SLv Zheng } else if (*format == '+') { 39580a648c1SLv Zheng type |= ACPI_FORMAT_SIGN_PLUS; 39680a648c1SLv Zheng } else if (*format == ' ') { 39780a648c1SLv Zheng type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 39880a648c1SLv Zheng } else if (*format == '-') { 39980a648c1SLv Zheng type |= ACPI_FORMAT_LEFT; 40080a648c1SLv Zheng } else { 40180a648c1SLv Zheng break; 40280a648c1SLv Zheng } 40380a648c1SLv Zheng } while (1); 40480a648c1SLv Zheng 40580a648c1SLv Zheng /* Process width */ 40680a648c1SLv Zheng 4073589b8b8SLv Zheng width = -1; 4084fa4616eSBob Moore if (isdigit((int)*format)) { 40980a648c1SLv Zheng format = acpi_ut_scan_number(format, &number); 41080a648c1SLv Zheng width = (s32) number; 41180a648c1SLv Zheng } else if (*format == '*') { 41280a648c1SLv Zheng ++format; 41380a648c1SLv Zheng width = va_arg(args, int); 41480a648c1SLv Zheng if (width < 0) { 41580a648c1SLv Zheng width = -width; 41680a648c1SLv Zheng type |= ACPI_FORMAT_LEFT; 41780a648c1SLv Zheng } 41880a648c1SLv Zheng } 41980a648c1SLv Zheng 42080a648c1SLv Zheng /* Process precision */ 42180a648c1SLv Zheng 4223589b8b8SLv Zheng precision = -1; 42380a648c1SLv Zheng if (*format == '.') { 42480a648c1SLv Zheng ++format; 4254fa4616eSBob Moore if (isdigit((int)*format)) { 42680a648c1SLv Zheng format = acpi_ut_scan_number(format, &number); 42780a648c1SLv Zheng precision = (s32) number; 42880a648c1SLv Zheng } else if (*format == '*') { 42980a648c1SLv Zheng ++format; 43080a648c1SLv Zheng precision = va_arg(args, int); 43180a648c1SLv Zheng } 43280a648c1SLv Zheng if (precision < 0) { 43380a648c1SLv Zheng precision = 0; 43480a648c1SLv Zheng } 43580a648c1SLv Zheng } 43680a648c1SLv Zheng 43780a648c1SLv Zheng /* Process qualifier */ 43880a648c1SLv Zheng 4393589b8b8SLv Zheng qualifier = -1; 44080a648c1SLv Zheng if (*format == 'h' || *format == 'l' || *format == 'L') { 44180a648c1SLv Zheng qualifier = *format; 44280a648c1SLv Zheng ++format; 443ff2389feSBob Moore 44480a648c1SLv Zheng if (qualifier == 'l' && *format == 'l') { 44580a648c1SLv Zheng qualifier = 'L'; 44680a648c1SLv Zheng ++format; 44780a648c1SLv Zheng } 44880a648c1SLv Zheng } 44980a648c1SLv Zheng 45080a648c1SLv Zheng switch (*format) { 45180a648c1SLv Zheng case '%': 45280a648c1SLv Zheng 45380a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, '%'); 45480a648c1SLv Zheng continue; 45580a648c1SLv Zheng 45680a648c1SLv Zheng case 'c': 45780a648c1SLv Zheng 45880a648c1SLv Zheng if (!(type & ACPI_FORMAT_LEFT)) { 45980a648c1SLv Zheng while (--width > 0) { 46080a648c1SLv Zheng pos = 46180a648c1SLv Zheng acpi_ut_bound_string_output(pos, 46280a648c1SLv Zheng end, 46380a648c1SLv Zheng ' '); 46480a648c1SLv Zheng } 46580a648c1SLv Zheng } 466ff2389feSBob Moore 46780a648c1SLv Zheng c = (char)va_arg(args, int); 46880a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, c); 469ff2389feSBob Moore 47080a648c1SLv Zheng while (--width > 0) { 47180a648c1SLv Zheng pos = 47280a648c1SLv Zheng acpi_ut_bound_string_output(pos, end, ' '); 47380a648c1SLv Zheng } 47480a648c1SLv Zheng continue; 47580a648c1SLv Zheng 47680a648c1SLv Zheng case 's': 47780a648c1SLv Zheng 47880a648c1SLv Zheng s = va_arg(args, char *); 47980a648c1SLv Zheng if (!s) { 48080a648c1SLv Zheng s = "<NULL>"; 48180a648c1SLv Zheng } 48280a648c1SLv Zheng length = acpi_ut_bound_string_length(s, precision); 48380a648c1SLv Zheng if (!(type & ACPI_FORMAT_LEFT)) { 48480a648c1SLv Zheng while (length < width--) { 48580a648c1SLv Zheng pos = 48680a648c1SLv Zheng acpi_ut_bound_string_output(pos, 48780a648c1SLv Zheng end, 48880a648c1SLv Zheng ' '); 48980a648c1SLv Zheng } 49080a648c1SLv Zheng } 49180a648c1SLv Zheng for (i = 0; i < length; ++i) { 49280a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, *s); 49380a648c1SLv Zheng ++s; 49480a648c1SLv Zheng } 49580a648c1SLv Zheng while (length < width--) { 49680a648c1SLv Zheng pos = 49780a648c1SLv Zheng acpi_ut_bound_string_output(pos, end, ' '); 49880a648c1SLv Zheng } 49980a648c1SLv Zheng continue; 50080a648c1SLv Zheng 50180a648c1SLv Zheng case 'o': 50280a648c1SLv Zheng 50380a648c1SLv Zheng base = 8; 50480a648c1SLv Zheng break; 50580a648c1SLv Zheng 50680a648c1SLv Zheng case 'X': 50780a648c1SLv Zheng 50880a648c1SLv Zheng type |= ACPI_FORMAT_UPPER; 50980a648c1SLv Zheng 51080a648c1SLv Zheng case 'x': 51180a648c1SLv Zheng 51280a648c1SLv Zheng base = 16; 51380a648c1SLv Zheng break; 51480a648c1SLv Zheng 51580a648c1SLv Zheng case 'd': 51680a648c1SLv Zheng case 'i': 51780a648c1SLv Zheng 51880a648c1SLv Zheng type |= ACPI_FORMAT_SIGN; 51980a648c1SLv Zheng 52080a648c1SLv Zheng case 'u': 52180a648c1SLv Zheng 52280a648c1SLv Zheng break; 52380a648c1SLv Zheng 52480a648c1SLv Zheng case 'p': 52580a648c1SLv Zheng 52680a648c1SLv Zheng if (width == -1) { 52780a648c1SLv Zheng width = 2 * sizeof(void *); 52880a648c1SLv Zheng type |= ACPI_FORMAT_ZERO; 52980a648c1SLv Zheng } 530ff2389feSBob Moore 53180a648c1SLv Zheng p = va_arg(args, void *); 53280a648c1SLv Zheng pos = acpi_ut_format_number(pos, end, 533ff2389feSBob Moore ACPI_TO_INTEGER(p), 16, 534ff2389feSBob Moore width, precision, type); 53580a648c1SLv Zheng continue; 53680a648c1SLv Zheng 53780a648c1SLv Zheng default: 53880a648c1SLv Zheng 53980a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, '%'); 54080a648c1SLv Zheng if (*format) { 54180a648c1SLv Zheng pos = 54280a648c1SLv Zheng acpi_ut_bound_string_output(pos, end, 54380a648c1SLv Zheng *format); 54480a648c1SLv Zheng } else { 54580a648c1SLv Zheng --format; 54680a648c1SLv Zheng } 54780a648c1SLv Zheng continue; 54880a648c1SLv Zheng } 54980a648c1SLv Zheng 55080a648c1SLv Zheng if (qualifier == 'L') { 55180a648c1SLv Zheng number = va_arg(args, u64); 55280a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 55380a648c1SLv Zheng number = (s64) number; 55480a648c1SLv Zheng } 55580a648c1SLv Zheng } else if (qualifier == 'l') { 55680a648c1SLv Zheng number = va_arg(args, unsigned long); 55780a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 55880a648c1SLv Zheng number = (s32) number; 55980a648c1SLv Zheng } 56080a648c1SLv Zheng } else if (qualifier == 'h') { 56180a648c1SLv Zheng number = (u16)va_arg(args, int); 56280a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 56380a648c1SLv Zheng number = (s16) number; 56480a648c1SLv Zheng } 56580a648c1SLv Zheng } else { 56680a648c1SLv Zheng number = va_arg(args, unsigned int); 56780a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 56880a648c1SLv Zheng number = (signed int)number; 56980a648c1SLv Zheng } 57080a648c1SLv Zheng } 571ff2389feSBob Moore 57280a648c1SLv Zheng pos = acpi_ut_format_number(pos, end, number, base, 57380a648c1SLv Zheng width, precision, type); 57480a648c1SLv Zheng } 57580a648c1SLv Zheng 57680a648c1SLv Zheng if (size > 0) { 57780a648c1SLv Zheng if (pos < end) { 57880a648c1SLv Zheng *pos = '\0'; 57980a648c1SLv Zheng } else { 58080a648c1SLv Zheng end[-1] = '\0'; 58180a648c1SLv Zheng } 58280a648c1SLv Zheng } 58380a648c1SLv Zheng 58480a648c1SLv Zheng return (ACPI_PTR_DIFF(pos, string)); 58580a648c1SLv Zheng } 58680a648c1SLv Zheng 58780a648c1SLv Zheng /******************************************************************************* 58880a648c1SLv Zheng * 58980a648c1SLv Zheng * FUNCTION: acpi_ut_snprintf 59080a648c1SLv Zheng * 59180a648c1SLv Zheng * PARAMETERS: string - String with boundary 59280a648c1SLv Zheng * size - Boundary of the string 59380a648c1SLv Zheng * Format, ... - Standard printf format 59480a648c1SLv Zheng * 595ff2389feSBob Moore * RETURN: Number of bytes actually written. 59680a648c1SLv Zheng * 59780a648c1SLv Zheng * DESCRIPTION: Formatted output to a string. 59880a648c1SLv Zheng * 59980a648c1SLv Zheng ******************************************************************************/ 60080a648c1SLv Zheng 60180a648c1SLv Zheng int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...) 60280a648c1SLv Zheng { 60380a648c1SLv Zheng va_list args; 60480a648c1SLv Zheng int length; 60580a648c1SLv Zheng 60680a648c1SLv Zheng va_start(args, format); 60780a648c1SLv Zheng length = acpi_ut_vsnprintf(string, size, format, args); 60880a648c1SLv Zheng va_end(args); 60980a648c1SLv Zheng 61080a648c1SLv Zheng return (length); 61180a648c1SLv Zheng } 61280a648c1SLv Zheng 61380a648c1SLv Zheng #ifdef ACPI_APPLICATION 61480a648c1SLv Zheng /******************************************************************************* 61580a648c1SLv Zheng * 61680a648c1SLv Zheng * FUNCTION: acpi_ut_file_vprintf 61780a648c1SLv Zheng * 61880a648c1SLv Zheng * PARAMETERS: file - File descriptor 61980a648c1SLv Zheng * format - Standard printf format 62080a648c1SLv Zheng * args - Argument list 62180a648c1SLv Zheng * 622ff2389feSBob Moore * RETURN: Number of bytes actually written. 62380a648c1SLv Zheng * 62480a648c1SLv Zheng * DESCRIPTION: Formatted output to a file using argument list pointer. 62580a648c1SLv Zheng * 62680a648c1SLv Zheng ******************************************************************************/ 62780a648c1SLv Zheng 62880a648c1SLv Zheng int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args) 62980a648c1SLv Zheng { 63080a648c1SLv Zheng acpi_cpu_flags flags; 63180a648c1SLv Zheng int length; 63280a648c1SLv Zheng 63380a648c1SLv Zheng flags = acpi_os_acquire_lock(acpi_gbl_print_lock); 63480a648c1SLv Zheng length = acpi_ut_vsnprintf(acpi_gbl_print_buffer, 63580a648c1SLv Zheng sizeof(acpi_gbl_print_buffer), format, args); 636ff2389feSBob Moore 63780a648c1SLv Zheng (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1); 63880a648c1SLv Zheng acpi_os_release_lock(acpi_gbl_print_lock, flags); 63980a648c1SLv Zheng 64080a648c1SLv Zheng return (length); 64180a648c1SLv Zheng } 64280a648c1SLv Zheng 64380a648c1SLv Zheng /******************************************************************************* 64480a648c1SLv Zheng * 64580a648c1SLv Zheng * FUNCTION: acpi_ut_file_printf 64680a648c1SLv Zheng * 64780a648c1SLv Zheng * PARAMETERS: file - File descriptor 64880a648c1SLv Zheng * Format, ... - Standard printf format 64980a648c1SLv Zheng * 650ff2389feSBob Moore * RETURN: Number of bytes actually written. 65180a648c1SLv Zheng * 65280a648c1SLv Zheng * DESCRIPTION: Formatted output to a file. 65380a648c1SLv Zheng * 65480a648c1SLv Zheng ******************************************************************************/ 65580a648c1SLv Zheng 65680a648c1SLv Zheng int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...) 65780a648c1SLv Zheng { 65880a648c1SLv Zheng va_list args; 65980a648c1SLv Zheng int length; 66080a648c1SLv Zheng 66180a648c1SLv Zheng va_start(args, format); 66280a648c1SLv Zheng length = acpi_ut_file_vprintf(file, format, args); 66380a648c1SLv Zheng va_end(args); 66480a648c1SLv Zheng 66580a648c1SLv Zheng return (length); 66680a648c1SLv Zheng } 66780a648c1SLv Zheng #endif 668