180a648c1SLv Zheng /****************************************************************************** 280a648c1SLv Zheng * 380a648c1SLv Zheng * Module Name: utprint - Formatted printing routines 480a648c1SLv Zheng * 580a648c1SLv Zheng *****************************************************************************/ 680a648c1SLv Zheng 780a648c1SLv Zheng /* 8c8100dc4SBob Moore * Copyright (C) 2000 - 2016, 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 7080a648c1SLv Zheng /******************************************************************************* 7180a648c1SLv Zheng * 7280a648c1SLv Zheng * FUNCTION: acpi_ut_bound_string_length 7380a648c1SLv Zheng * 7480a648c1SLv Zheng * PARAMETERS: string - String with boundary 7580a648c1SLv Zheng * count - Boundary of the string 7680a648c1SLv Zheng * 77ff2389feSBob Moore * RETURN: Length of the string. Less than or equal to Count. 7880a648c1SLv Zheng * 7980a648c1SLv Zheng * DESCRIPTION: Calculate the length of a string with boundary. 8080a648c1SLv Zheng * 8180a648c1SLv Zheng ******************************************************************************/ 8280a648c1SLv Zheng 8380a648c1SLv Zheng static acpi_size 8480a648c1SLv Zheng acpi_ut_bound_string_length(const char *string, acpi_size count) 8580a648c1SLv Zheng { 8680a648c1SLv Zheng u32 length = 0; 8780a648c1SLv Zheng 8880a648c1SLv Zheng while (*string && count) { 8980a648c1SLv Zheng length++; 9080a648c1SLv Zheng string++; 9180a648c1SLv Zheng count--; 9280a648c1SLv Zheng } 9380a648c1SLv Zheng 9480a648c1SLv Zheng return (length); 9580a648c1SLv Zheng } 9680a648c1SLv Zheng 9780a648c1SLv Zheng /******************************************************************************* 9880a648c1SLv Zheng * 9980a648c1SLv Zheng * FUNCTION: acpi_ut_bound_string_output 10080a648c1SLv Zheng * 10180a648c1SLv Zheng * PARAMETERS: string - String with boundary 10280a648c1SLv Zheng * end - Boundary of the string 10380a648c1SLv Zheng * c - Character to be output to the string 10480a648c1SLv Zheng * 10580a648c1SLv Zheng * RETURN: Updated position for next valid character 10680a648c1SLv Zheng * 10780a648c1SLv Zheng * DESCRIPTION: Output a character into a string with boundary check. 10880a648c1SLv Zheng * 10980a648c1SLv Zheng ******************************************************************************/ 11080a648c1SLv Zheng 11180a648c1SLv Zheng static char *acpi_ut_bound_string_output(char *string, const char *end, char c) 11280a648c1SLv Zheng { 11380a648c1SLv Zheng 11480a648c1SLv Zheng if (string < end) { 11580a648c1SLv Zheng *string = c; 11680a648c1SLv Zheng } 11780a648c1SLv Zheng 118ff2389feSBob Moore ++string; 11980a648c1SLv Zheng return (string); 12080a648c1SLv Zheng } 12180a648c1SLv Zheng 12280a648c1SLv Zheng /******************************************************************************* 12380a648c1SLv Zheng * 12480a648c1SLv Zheng * FUNCTION: acpi_ut_put_number 12580a648c1SLv Zheng * 12680a648c1SLv Zheng * PARAMETERS: string - Buffer to hold reverse-ordered string 12780a648c1SLv Zheng * number - Integer to be converted 12880a648c1SLv Zheng * base - Base of the integer 12980a648c1SLv Zheng * upper - Whether or not using upper cased digits 13080a648c1SLv Zheng * 13180a648c1SLv Zheng * RETURN: Updated position for next valid character 13280a648c1SLv Zheng * 13380a648c1SLv Zheng * DESCRIPTION: Convert an integer into a string, note that, the string holds a 13480a648c1SLv Zheng * reversed ordered number without the trailing zero. 13580a648c1SLv Zheng * 13680a648c1SLv Zheng ******************************************************************************/ 13780a648c1SLv Zheng 13880a648c1SLv Zheng static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper) 13980a648c1SLv Zheng { 14080a648c1SLv Zheng const char *digits; 14180a648c1SLv Zheng u64 digit_index; 14280a648c1SLv Zheng char *pos; 14380a648c1SLv Zheng 14480a648c1SLv Zheng pos = string; 145ff2389feSBob Moore digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits; 14680a648c1SLv Zheng 14780a648c1SLv Zheng if (number == 0) { 14880a648c1SLv Zheng *(pos++) = '0'; 14980a648c1SLv Zheng } else { 15080a648c1SLv Zheng while (number) { 15180a648c1SLv Zheng (void)acpi_ut_divide(number, base, &number, 15280a648c1SLv Zheng &digit_index); 15380a648c1SLv Zheng *(pos++) = digits[digit_index]; 15480a648c1SLv Zheng } 15580a648c1SLv Zheng } 15680a648c1SLv Zheng 157ff2389feSBob Moore /* *(Pos++) = '0'; */ 15880a648c1SLv Zheng return (pos); 15980a648c1SLv Zheng } 16080a648c1SLv Zheng 16180a648c1SLv Zheng /******************************************************************************* 16280a648c1SLv Zheng * 16380a648c1SLv Zheng * FUNCTION: acpi_ut_scan_number 16480a648c1SLv Zheng * 16580a648c1SLv Zheng * PARAMETERS: string - String buffer 16680a648c1SLv Zheng * number_ptr - Where the number is returned 16780a648c1SLv Zheng * 16880a648c1SLv Zheng * RETURN: Updated position for next valid character 16980a648c1SLv Zheng * 17080a648c1SLv Zheng * DESCRIPTION: Scan a string for a decimal integer. 17180a648c1SLv Zheng * 17280a648c1SLv Zheng ******************************************************************************/ 17380a648c1SLv Zheng 17480a648c1SLv Zheng const char *acpi_ut_scan_number(const char *string, u64 *number_ptr) 17580a648c1SLv Zheng { 17680a648c1SLv Zheng u64 number = 0; 17780a648c1SLv Zheng 1784fa4616eSBob Moore while (isdigit((int)*string)) { 17980a648c1SLv Zheng number *= 10; 18080a648c1SLv Zheng number += *(string++) - '0'; 18180a648c1SLv Zheng } 18280a648c1SLv Zheng 183ff2389feSBob Moore *number_ptr = number; 18480a648c1SLv Zheng return (string); 18580a648c1SLv Zheng } 18680a648c1SLv Zheng 18780a648c1SLv Zheng /******************************************************************************* 18880a648c1SLv Zheng * 18980a648c1SLv Zheng * FUNCTION: acpi_ut_print_number 19080a648c1SLv Zheng * 19180a648c1SLv Zheng * PARAMETERS: string - String buffer 19280a648c1SLv Zheng * number - The number to be converted 19380a648c1SLv Zheng * 19480a648c1SLv Zheng * RETURN: Updated position for next valid character 19580a648c1SLv Zheng * 19680a648c1SLv Zheng * DESCRIPTION: Print a decimal integer into a string. 19780a648c1SLv Zheng * 19880a648c1SLv Zheng ******************************************************************************/ 19980a648c1SLv Zheng 20080a648c1SLv Zheng const char *acpi_ut_print_number(char *string, u64 number) 20180a648c1SLv Zheng { 20280a648c1SLv Zheng char ascii_string[20]; 20380a648c1SLv Zheng const char *pos1; 20480a648c1SLv Zheng char *pos2; 20580a648c1SLv Zheng 20680a648c1SLv Zheng pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE); 20780a648c1SLv Zheng pos2 = string; 20880a648c1SLv Zheng 20980a648c1SLv Zheng while (pos1 != ascii_string) { 21080a648c1SLv Zheng *(pos2++) = *(--pos1); 21180a648c1SLv Zheng } 21280a648c1SLv Zheng 213ff2389feSBob Moore *pos2 = 0; 21480a648c1SLv Zheng return (string); 21580a648c1SLv Zheng } 21680a648c1SLv Zheng 21780a648c1SLv Zheng /******************************************************************************* 21880a648c1SLv Zheng * 21980a648c1SLv Zheng * FUNCTION: acpi_ut_format_number 22080a648c1SLv Zheng * 22180a648c1SLv Zheng * PARAMETERS: string - String buffer with boundary 22280a648c1SLv Zheng * end - Boundary of the string 22380a648c1SLv Zheng * number - The number to be converted 22480a648c1SLv Zheng * base - Base of the integer 22580a648c1SLv Zheng * width - Field width 22680a648c1SLv Zheng * precision - Precision of the integer 22780a648c1SLv Zheng * type - Special printing flags 22880a648c1SLv Zheng * 22980a648c1SLv Zheng * RETURN: Updated position for next valid character 23080a648c1SLv Zheng * 23180a648c1SLv Zheng * DESCRIPTION: Print an integer into a string with any base and any precision. 23280a648c1SLv Zheng * 23380a648c1SLv Zheng ******************************************************************************/ 23480a648c1SLv Zheng 23580a648c1SLv Zheng static char *acpi_ut_format_number(char *string, 23680a648c1SLv Zheng char *end, 23780a648c1SLv Zheng u64 number, 23880a648c1SLv Zheng u8 base, s32 width, s32 precision, u8 type) 23980a648c1SLv Zheng { 2408884de6aSBob Moore char *pos; 24180a648c1SLv Zheng char sign; 24280a648c1SLv Zheng char zero; 24380a648c1SLv Zheng u8 need_prefix; 24480a648c1SLv Zheng u8 upper; 24580a648c1SLv Zheng s32 i; 24680a648c1SLv Zheng char reversed_string[66]; 24780a648c1SLv Zheng 248ff2389feSBob Moore /* Parameter validation */ 24980a648c1SLv Zheng 25080a648c1SLv Zheng if (base < 2 || base > 16) { 251ff2389feSBob Moore return (NULL); 25280a648c1SLv Zheng } 253ff2389feSBob Moore 25480a648c1SLv Zheng if (type & ACPI_FORMAT_LEFT) { 25580a648c1SLv Zheng type &= ~ACPI_FORMAT_ZERO; 25680a648c1SLv Zheng } 25780a648c1SLv Zheng 25880a648c1SLv Zheng need_prefix = ((type & ACPI_FORMAT_PREFIX) 25980a648c1SLv Zheng && base != 10) ? TRUE : FALSE; 26080a648c1SLv Zheng upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; 26180a648c1SLv Zheng zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' '; 26280a648c1SLv Zheng 26380a648c1SLv Zheng /* Calculate size according to sign and prefix */ 26480a648c1SLv Zheng 26580a648c1SLv Zheng sign = '\0'; 26680a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 26780a648c1SLv Zheng if ((s64)number < 0) { 26880a648c1SLv Zheng sign = '-'; 26980a648c1SLv Zheng number = -(s64)number; 27080a648c1SLv Zheng width--; 27180a648c1SLv Zheng } else if (type & ACPI_FORMAT_SIGN_PLUS) { 27280a648c1SLv Zheng sign = '+'; 27380a648c1SLv Zheng width--; 27480a648c1SLv Zheng } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) { 27580a648c1SLv Zheng sign = ' '; 27680a648c1SLv Zheng width--; 27780a648c1SLv Zheng } 27880a648c1SLv Zheng } 27980a648c1SLv Zheng if (need_prefix) { 28080a648c1SLv Zheng width--; 28180a648c1SLv Zheng if (base == 16) { 28280a648c1SLv Zheng width--; 28380a648c1SLv Zheng } 28480a648c1SLv Zheng } 28580a648c1SLv Zheng 28680a648c1SLv Zheng /* Generate full string in reverse order */ 28780a648c1SLv Zheng 2888884de6aSBob Moore pos = acpi_ut_put_number(reversed_string, number, base, upper); 2898884de6aSBob Moore i = ACPI_PTR_DIFF(pos, reversed_string); 29080a648c1SLv Zheng 29180a648c1SLv Zheng /* Printing 100 using %2d gives "100", not "00" */ 29280a648c1SLv Zheng 29380a648c1SLv Zheng if (i > precision) { 29480a648c1SLv Zheng precision = i; 29580a648c1SLv Zheng } 296ff2389feSBob Moore 29780a648c1SLv Zheng width -= precision; 29880a648c1SLv Zheng 29980a648c1SLv Zheng /* Output the string */ 30080a648c1SLv Zheng 30180a648c1SLv Zheng if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) { 30280a648c1SLv Zheng while (--width >= 0) { 30380a648c1SLv Zheng string = acpi_ut_bound_string_output(string, end, ' '); 30480a648c1SLv Zheng } 30580a648c1SLv Zheng } 30680a648c1SLv Zheng if (sign) { 30780a648c1SLv Zheng string = acpi_ut_bound_string_output(string, end, sign); 30880a648c1SLv Zheng } 30980a648c1SLv Zheng if (need_prefix) { 31080a648c1SLv Zheng string = acpi_ut_bound_string_output(string, end, '0'); 31180a648c1SLv Zheng if (base == 16) { 3121fad8738SBob Moore string = 3131fad8738SBob Moore acpi_ut_bound_string_output(string, end, 31480a648c1SLv Zheng upper ? 'X' : 'x'); 31580a648c1SLv Zheng } 31680a648c1SLv Zheng } 31780a648c1SLv Zheng if (!(type & ACPI_FORMAT_LEFT)) { 31880a648c1SLv Zheng while (--width >= 0) { 31980a648c1SLv Zheng string = acpi_ut_bound_string_output(string, end, zero); 32080a648c1SLv Zheng } 32180a648c1SLv Zheng } 322ff2389feSBob Moore 32380a648c1SLv Zheng while (i <= --precision) { 32480a648c1SLv Zheng string = acpi_ut_bound_string_output(string, end, '0'); 32580a648c1SLv Zheng } 32680a648c1SLv Zheng while (--i >= 0) { 32780a648c1SLv Zheng string = acpi_ut_bound_string_output(string, end, 32880a648c1SLv Zheng reversed_string[i]); 32980a648c1SLv Zheng } 33080a648c1SLv Zheng while (--width >= 0) { 33180a648c1SLv Zheng string = acpi_ut_bound_string_output(string, end, ' '); 33280a648c1SLv Zheng } 33380a648c1SLv Zheng 33480a648c1SLv Zheng return (string); 33580a648c1SLv Zheng } 33680a648c1SLv Zheng 33780a648c1SLv Zheng /******************************************************************************* 33880a648c1SLv Zheng * 339f173a775SLv Zheng * FUNCTION: vsnprintf 34080a648c1SLv Zheng * 34180a648c1SLv Zheng * PARAMETERS: string - String with boundary 34280a648c1SLv Zheng * size - Boundary of the string 34380a648c1SLv Zheng * format - Standard printf format 34480a648c1SLv Zheng * args - Argument list 34580a648c1SLv Zheng * 346ff2389feSBob Moore * RETURN: Number of bytes actually written. 34780a648c1SLv Zheng * 34880a648c1SLv Zheng * DESCRIPTION: Formatted output to a string using argument list pointer. 34980a648c1SLv Zheng * 35080a648c1SLv Zheng ******************************************************************************/ 35180a648c1SLv Zheng 352f173a775SLv Zheng int vsnprintf(char *string, acpi_size size, const char *format, va_list args) 35380a648c1SLv Zheng { 354cef9aaa7SLv Zheng u8 base; 355cef9aaa7SLv Zheng u8 type; 356cef9aaa7SLv Zheng s32 width; 357cef9aaa7SLv Zheng s32 precision; 358cef9aaa7SLv Zheng char qualifier; 35980a648c1SLv Zheng u64 number; 36080a648c1SLv Zheng char *pos; 36180a648c1SLv Zheng char *end; 36280a648c1SLv Zheng char c; 36380a648c1SLv Zheng const char *s; 36480a648c1SLv Zheng const void *p; 36580a648c1SLv Zheng s32 length; 36680a648c1SLv Zheng int i; 36780a648c1SLv Zheng 36880a648c1SLv Zheng pos = string; 36980a648c1SLv Zheng end = string + size; 37080a648c1SLv Zheng 37180a648c1SLv Zheng for (; *format; ++format) { 37280a648c1SLv Zheng if (*format != '%') { 37380a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, *format); 37480a648c1SLv Zheng continue; 37580a648c1SLv Zheng } 37680a648c1SLv Zheng 377cef9aaa7SLv Zheng type = 0; 378cef9aaa7SLv Zheng base = 10; 379cef9aaa7SLv Zheng 38080a648c1SLv Zheng /* Process sign */ 38180a648c1SLv Zheng 38280a648c1SLv Zheng do { 38380a648c1SLv Zheng ++format; 38480a648c1SLv Zheng if (*format == '#') { 38580a648c1SLv Zheng type |= ACPI_FORMAT_PREFIX; 38680a648c1SLv Zheng } else if (*format == '0') { 38780a648c1SLv Zheng type |= ACPI_FORMAT_ZERO; 38880a648c1SLv Zheng } else if (*format == '+') { 38980a648c1SLv Zheng type |= ACPI_FORMAT_SIGN_PLUS; 39080a648c1SLv Zheng } else if (*format == ' ') { 39180a648c1SLv Zheng type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 39280a648c1SLv Zheng } else if (*format == '-') { 39380a648c1SLv Zheng type |= ACPI_FORMAT_LEFT; 39480a648c1SLv Zheng } else { 39580a648c1SLv Zheng break; 39680a648c1SLv Zheng } 3971fad8738SBob Moore 39880a648c1SLv Zheng } while (1); 39980a648c1SLv Zheng 40080a648c1SLv Zheng /* Process width */ 40180a648c1SLv Zheng 4023589b8b8SLv Zheng width = -1; 4034fa4616eSBob Moore if (isdigit((int)*format)) { 40480a648c1SLv Zheng format = acpi_ut_scan_number(format, &number); 40580a648c1SLv Zheng width = (s32)number; 40680a648c1SLv Zheng } else if (*format == '*') { 40780a648c1SLv Zheng ++format; 40880a648c1SLv Zheng width = va_arg(args, int); 40980a648c1SLv Zheng if (width < 0) { 41080a648c1SLv Zheng width = -width; 41180a648c1SLv Zheng type |= ACPI_FORMAT_LEFT; 41280a648c1SLv Zheng } 41380a648c1SLv Zheng } 41480a648c1SLv Zheng 41580a648c1SLv Zheng /* Process precision */ 41680a648c1SLv Zheng 4173589b8b8SLv Zheng precision = -1; 41880a648c1SLv Zheng if (*format == '.') { 41980a648c1SLv Zheng ++format; 4204fa4616eSBob Moore if (isdigit((int)*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 } 4271fad8738SBob Moore 42880a648c1SLv Zheng if (precision < 0) { 42980a648c1SLv Zheng precision = 0; 43080a648c1SLv Zheng } 43180a648c1SLv Zheng } 43280a648c1SLv Zheng 43380a648c1SLv Zheng /* Process qualifier */ 43480a648c1SLv Zheng 4353589b8b8SLv Zheng qualifier = -1; 43680a648c1SLv Zheng if (*format == 'h' || *format == 'l' || *format == 'L') { 43780a648c1SLv Zheng qualifier = *format; 43880a648c1SLv Zheng ++format; 439ff2389feSBob Moore 44080a648c1SLv Zheng if (qualifier == 'l' && *format == 'l') { 44180a648c1SLv Zheng qualifier = 'L'; 44280a648c1SLv Zheng ++format; 44380a648c1SLv Zheng } 44480a648c1SLv Zheng } 44580a648c1SLv Zheng 44680a648c1SLv Zheng switch (*format) { 44780a648c1SLv Zheng case '%': 44880a648c1SLv Zheng 44980a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, '%'); 45080a648c1SLv Zheng continue; 45180a648c1SLv Zheng 45280a648c1SLv Zheng case 'c': 45380a648c1SLv Zheng 45480a648c1SLv Zheng if (!(type & ACPI_FORMAT_LEFT)) { 45580a648c1SLv Zheng while (--width > 0) { 45680a648c1SLv Zheng pos = 45780a648c1SLv Zheng acpi_ut_bound_string_output(pos, 45880a648c1SLv Zheng end, 45980a648c1SLv Zheng ' '); 46080a648c1SLv Zheng } 46180a648c1SLv Zheng } 462ff2389feSBob Moore 46380a648c1SLv Zheng c = (char)va_arg(args, int); 46480a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, c); 465ff2389feSBob Moore 46680a648c1SLv Zheng while (--width > 0) { 46780a648c1SLv Zheng pos = 46880a648c1SLv Zheng acpi_ut_bound_string_output(pos, end, ' '); 46980a648c1SLv Zheng } 47080a648c1SLv Zheng continue; 47180a648c1SLv Zheng 47280a648c1SLv Zheng case 's': 47380a648c1SLv Zheng 47480a648c1SLv Zheng s = va_arg(args, char *); 47580a648c1SLv Zheng if (!s) { 47680a648c1SLv Zheng s = "<NULL>"; 47780a648c1SLv Zheng } 47880a648c1SLv Zheng length = acpi_ut_bound_string_length(s, precision); 47980a648c1SLv Zheng if (!(type & ACPI_FORMAT_LEFT)) { 48080a648c1SLv Zheng while (length < width--) { 48180a648c1SLv Zheng pos = 48280a648c1SLv Zheng acpi_ut_bound_string_output(pos, 48380a648c1SLv Zheng end, 48480a648c1SLv Zheng ' '); 48580a648c1SLv Zheng } 48680a648c1SLv Zheng } 4871fad8738SBob Moore 48880a648c1SLv Zheng for (i = 0; i < length; ++i) { 48980a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, *s); 49080a648c1SLv Zheng ++s; 49180a648c1SLv Zheng } 4921fad8738SBob Moore 49380a648c1SLv Zheng while (length < width--) { 49480a648c1SLv Zheng pos = 49580a648c1SLv Zheng acpi_ut_bound_string_output(pos, end, ' '); 49680a648c1SLv Zheng } 49780a648c1SLv Zheng continue; 49880a648c1SLv Zheng 49980a648c1SLv Zheng case 'o': 50080a648c1SLv Zheng 50180a648c1SLv Zheng base = 8; 50280a648c1SLv Zheng break; 50380a648c1SLv Zheng 50480a648c1SLv Zheng case 'X': 50580a648c1SLv Zheng 50680a648c1SLv Zheng type |= ACPI_FORMAT_UPPER; 50780a648c1SLv Zheng 50880a648c1SLv Zheng case 'x': 50980a648c1SLv Zheng 51080a648c1SLv Zheng base = 16; 51180a648c1SLv Zheng break; 51280a648c1SLv Zheng 51380a648c1SLv Zheng case 'd': 51480a648c1SLv Zheng case 'i': 51580a648c1SLv Zheng 51680a648c1SLv Zheng type |= ACPI_FORMAT_SIGN; 51780a648c1SLv Zheng 51880a648c1SLv Zheng case 'u': 51980a648c1SLv Zheng 52080a648c1SLv Zheng break; 52180a648c1SLv Zheng 52280a648c1SLv Zheng case 'p': 52380a648c1SLv Zheng 52480a648c1SLv Zheng if (width == -1) { 52580a648c1SLv Zheng width = 2 * sizeof(void *); 52680a648c1SLv Zheng type |= ACPI_FORMAT_ZERO; 52780a648c1SLv Zheng } 528ff2389feSBob Moore 52980a648c1SLv Zheng p = va_arg(args, void *); 5301fad8738SBob Moore pos = 5311fad8738SBob Moore acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p), 5321fad8738SBob Moore 16, width, precision, type); 53380a648c1SLv Zheng continue; 53480a648c1SLv Zheng 53580a648c1SLv Zheng default: 53680a648c1SLv Zheng 53780a648c1SLv Zheng pos = acpi_ut_bound_string_output(pos, end, '%'); 53880a648c1SLv Zheng if (*format) { 53980a648c1SLv Zheng pos = 54080a648c1SLv Zheng acpi_ut_bound_string_output(pos, end, 54180a648c1SLv Zheng *format); 54280a648c1SLv Zheng } else { 54380a648c1SLv Zheng --format; 54480a648c1SLv Zheng } 54580a648c1SLv Zheng continue; 54680a648c1SLv Zheng } 54780a648c1SLv Zheng 54880a648c1SLv Zheng if (qualifier == 'L') { 54980a648c1SLv Zheng number = va_arg(args, u64); 55080a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 55180a648c1SLv Zheng number = (s64)number; 55280a648c1SLv Zheng } 55380a648c1SLv Zheng } else if (qualifier == 'l') { 55480a648c1SLv Zheng number = va_arg(args, unsigned long); 55580a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 55680a648c1SLv Zheng number = (s32)number; 55780a648c1SLv Zheng } 55880a648c1SLv Zheng } else if (qualifier == 'h') { 55980a648c1SLv Zheng number = (u16)va_arg(args, int); 56080a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 56180a648c1SLv Zheng number = (s16)number; 56280a648c1SLv Zheng } 56380a648c1SLv Zheng } else { 56480a648c1SLv Zheng number = va_arg(args, unsigned int); 56580a648c1SLv Zheng if (type & ACPI_FORMAT_SIGN) { 56680a648c1SLv Zheng number = (signed int)number; 56780a648c1SLv Zheng } 56880a648c1SLv Zheng } 569ff2389feSBob Moore 57080a648c1SLv Zheng pos = acpi_ut_format_number(pos, end, number, base, 57180a648c1SLv Zheng width, precision, type); 57280a648c1SLv Zheng } 57380a648c1SLv Zheng 57480a648c1SLv Zheng if (size > 0) { 57580a648c1SLv Zheng if (pos < end) { 57680a648c1SLv Zheng *pos = '\0'; 57780a648c1SLv Zheng } else { 57880a648c1SLv Zheng end[-1] = '\0'; 57980a648c1SLv Zheng } 58080a648c1SLv Zheng } 58180a648c1SLv Zheng 58280a648c1SLv Zheng return (ACPI_PTR_DIFF(pos, string)); 58380a648c1SLv Zheng } 58480a648c1SLv Zheng 58580a648c1SLv Zheng /******************************************************************************* 58680a648c1SLv Zheng * 587f173a775SLv Zheng * FUNCTION: snprintf 58880a648c1SLv Zheng * 58980a648c1SLv Zheng * PARAMETERS: string - String with boundary 59080a648c1SLv Zheng * size - Boundary of the string 59180a648c1SLv Zheng * Format, ... - Standard printf format 59280a648c1SLv Zheng * 593ff2389feSBob Moore * RETURN: Number of bytes actually written. 59480a648c1SLv Zheng * 59580a648c1SLv Zheng * DESCRIPTION: Formatted output to a string. 59680a648c1SLv Zheng * 59780a648c1SLv Zheng ******************************************************************************/ 59880a648c1SLv Zheng 599f173a775SLv Zheng int snprintf(char *string, acpi_size size, const char *format, ...) 60080a648c1SLv Zheng { 60180a648c1SLv Zheng va_list args; 60280a648c1SLv Zheng int length; 60380a648c1SLv Zheng 60480a648c1SLv Zheng va_start(args, format); 605f173a775SLv Zheng length = vsnprintf(string, size, format, args); 606f173a775SLv Zheng va_end(args); 607f173a775SLv Zheng 608f173a775SLv Zheng return (length); 609f173a775SLv Zheng } 610f173a775SLv Zheng 611f173a775SLv Zheng /******************************************************************************* 612f173a775SLv Zheng * 613f173a775SLv Zheng * FUNCTION: sprintf 614f173a775SLv Zheng * 615f173a775SLv Zheng * PARAMETERS: string - String with boundary 616f173a775SLv Zheng * Format, ... - Standard printf format 617f173a775SLv Zheng * 618f173a775SLv Zheng * RETURN: Number of bytes actually written. 619f173a775SLv Zheng * 620f173a775SLv Zheng * DESCRIPTION: Formatted output to a string. 621f173a775SLv Zheng * 622f173a775SLv Zheng ******************************************************************************/ 623f173a775SLv Zheng 624f173a775SLv Zheng int sprintf(char *string, const char *format, ...) 625f173a775SLv Zheng { 626f173a775SLv Zheng va_list args; 627f173a775SLv Zheng int length; 628f173a775SLv Zheng 629f173a775SLv Zheng va_start(args, format); 630f173a775SLv Zheng length = vsnprintf(string, ACPI_UINT32_MAX, format, args); 63180a648c1SLv Zheng va_end(args); 63280a648c1SLv Zheng 63380a648c1SLv Zheng return (length); 63480a648c1SLv Zheng } 63580a648c1SLv Zheng 63680a648c1SLv Zheng #ifdef ACPI_APPLICATION 63780a648c1SLv Zheng /******************************************************************************* 63880a648c1SLv Zheng * 639f173a775SLv Zheng * FUNCTION: vprintf 640f173a775SLv Zheng * 641f173a775SLv Zheng * PARAMETERS: format - Standard printf format 642f173a775SLv Zheng * args - Argument list 643f173a775SLv Zheng * 644f173a775SLv Zheng * RETURN: Number of bytes actually written. 645f173a775SLv Zheng * 646f173a775SLv Zheng * DESCRIPTION: Formatted output to stdout using argument list pointer. 647f173a775SLv Zheng * 648f173a775SLv Zheng ******************************************************************************/ 649f173a775SLv Zheng 650f173a775SLv Zheng int vprintf(const char *format, va_list args) 651f173a775SLv Zheng { 652f173a775SLv Zheng acpi_cpu_flags flags; 653f173a775SLv Zheng int length; 654f173a775SLv Zheng 655f173a775SLv Zheng flags = acpi_os_acquire_lock(acpi_gbl_print_lock); 656f173a775SLv Zheng length = vsnprintf(acpi_gbl_print_buffer, 657f173a775SLv Zheng sizeof(acpi_gbl_print_buffer), format, args); 658f173a775SLv Zheng 659f173a775SLv Zheng (void)acpi_os_write_file(ACPI_FILE_OUT, acpi_gbl_print_buffer, length, 660f173a775SLv Zheng 1); 661f173a775SLv Zheng acpi_os_release_lock(acpi_gbl_print_lock, flags); 662f173a775SLv Zheng 663f173a775SLv Zheng return (length); 664f173a775SLv Zheng } 665f173a775SLv Zheng 666f173a775SLv Zheng /******************************************************************************* 667f173a775SLv Zheng * 668f173a775SLv Zheng * FUNCTION: printf 669f173a775SLv Zheng * 670f173a775SLv Zheng * PARAMETERS: Format, ... - Standard printf format 671f173a775SLv Zheng * 672f173a775SLv Zheng * RETURN: Number of bytes actually written. 673f173a775SLv Zheng * 674f173a775SLv Zheng * DESCRIPTION: Formatted output to stdout. 675f173a775SLv Zheng * 676f173a775SLv Zheng ******************************************************************************/ 677f173a775SLv Zheng 678f173a775SLv Zheng int printf(const char *format, ...) 679f173a775SLv Zheng { 680f173a775SLv Zheng va_list args; 681f173a775SLv Zheng int length; 682f173a775SLv Zheng 683f173a775SLv Zheng va_start(args, format); 684f173a775SLv Zheng length = vprintf(format, args); 685f173a775SLv Zheng va_end(args); 686f173a775SLv Zheng 687f173a775SLv Zheng return (length); 688f173a775SLv Zheng } 689f173a775SLv Zheng 690f173a775SLv Zheng /******************************************************************************* 691f173a775SLv Zheng * 692f173a775SLv Zheng * FUNCTION: vfprintf 69380a648c1SLv Zheng * 69480a648c1SLv Zheng * PARAMETERS: file - File descriptor 69580a648c1SLv Zheng * format - Standard printf format 69680a648c1SLv Zheng * args - Argument list 69780a648c1SLv Zheng * 698ff2389feSBob Moore * RETURN: Number of bytes actually written. 69980a648c1SLv Zheng * 70080a648c1SLv Zheng * DESCRIPTION: Formatted output to a file using argument list pointer. 70180a648c1SLv Zheng * 70280a648c1SLv Zheng ******************************************************************************/ 70380a648c1SLv Zheng 704f173a775SLv Zheng int vfprintf(FILE * file, const char *format, va_list args) 70580a648c1SLv Zheng { 70680a648c1SLv Zheng acpi_cpu_flags flags; 70780a648c1SLv Zheng int length; 70880a648c1SLv Zheng 70980a648c1SLv Zheng flags = acpi_os_acquire_lock(acpi_gbl_print_lock); 710f173a775SLv Zheng length = vsnprintf(acpi_gbl_print_buffer, 71180a648c1SLv Zheng sizeof(acpi_gbl_print_buffer), format, args); 712ff2389feSBob Moore 71380a648c1SLv Zheng (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1); 71480a648c1SLv Zheng acpi_os_release_lock(acpi_gbl_print_lock, flags); 71580a648c1SLv Zheng 71680a648c1SLv Zheng return (length); 71780a648c1SLv Zheng } 71880a648c1SLv Zheng 71980a648c1SLv Zheng /******************************************************************************* 72080a648c1SLv Zheng * 721f173a775SLv Zheng * FUNCTION: fprintf 72280a648c1SLv Zheng * 72380a648c1SLv Zheng * PARAMETERS: file - File descriptor 72480a648c1SLv Zheng * Format, ... - Standard printf format 72580a648c1SLv Zheng * 726ff2389feSBob Moore * RETURN: Number of bytes actually written. 72780a648c1SLv Zheng * 72880a648c1SLv Zheng * DESCRIPTION: Formatted output to a file. 72980a648c1SLv Zheng * 73080a648c1SLv Zheng ******************************************************************************/ 73180a648c1SLv Zheng 732f173a775SLv Zheng int fprintf(FILE * file, const char *format, ...) 73380a648c1SLv Zheng { 73480a648c1SLv Zheng va_list args; 73580a648c1SLv Zheng int length; 73680a648c1SLv Zheng 73780a648c1SLv Zheng va_start(args, format); 738f173a775SLv Zheng length = vfprintf(file, format, args); 73980a648c1SLv Zheng va_end(args); 74080a648c1SLv Zheng 74180a648c1SLv Zheng return (length); 74280a648c1SLv Zheng } 74380a648c1SLv Zheng #endif 744