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