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