123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- /******************************************************************************
- *
- * Module Name: utprint - Formatted printing routines
- *
- *****************************************************************************/
- /*
- * Copyright (C) 2000 - 2015, Intel Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions, and the following disclaimer,
- * without modification.
- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
- * substantially similar to the "NO WARRANTY" disclaimer below
- * ("Disclaimer") and any redistribution must be conditioned upon
- * including a substantially similar Disclaimer requirement for further
- * binary redistribution.
- * 3. Neither the names of the above-listed copyright holders nor the names
- * of any contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGES.
- */
- #include <acpi/acpi.h>
- #include "accommon.h"
- #define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME("utprint")
- #define ACPI_FORMAT_SIGN 0x01
- #define ACPI_FORMAT_SIGN_PLUS 0x02
- #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
- #define ACPI_FORMAT_ZERO 0x08
- #define ACPI_FORMAT_LEFT 0x10
- #define ACPI_FORMAT_UPPER 0x20
- #define ACPI_FORMAT_PREFIX 0x40
- /* Local prototypes */
- static acpi_size
- acpi_ut_bound_string_length(const char *string, acpi_size count);
- static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
- static char *acpi_ut_format_number(char *string,
- char *end,
- u64 number,
- u8 base, s32 width, s32 precision, u8 type);
- static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
- /* Module globals */
- static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
- static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_bound_string_length
- *
- * PARAMETERS: string - String with boundary
- * count - Boundary of the string
- *
- * RETURN: Length of the string. Less than or equal to Count.
- *
- * DESCRIPTION: Calculate the length of a string with boundary.
- *
- ******************************************************************************/
- static acpi_size
- acpi_ut_bound_string_length(const char *string, acpi_size count)
- {
- u32 length = 0;
- while (*string && count) {
- length++;
- string++;
- count--;
- }
- return (length);
- }
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_bound_string_output
- *
- * PARAMETERS: string - String with boundary
- * end - Boundary of the string
- * c - Character to be output to the string
- *
- * RETURN: Updated position for next valid character
- *
- * DESCRIPTION: Output a character into a string with boundary check.
- *
- ******************************************************************************/
- static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
- {
- if (string < end) {
- *string = c;
- }
- ++string;
- return (string);
- }
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_put_number
- *
- * PARAMETERS: string - Buffer to hold reverse-ordered string
- * number - Integer to be converted
- * base - Base of the integer
- * upper - Whether or not using upper cased digits
- *
- * RETURN: Updated position for next valid character
- *
- * DESCRIPTION: Convert an integer into a string, note that, the string holds a
- * reversed ordered number without the trailing zero.
- *
- ******************************************************************************/
- static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
- {
- const char *digits;
- u64 digit_index;
- char *pos;
- pos = string;
- digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
- if (number == 0) {
- *(pos++) = '0';
- } else {
- while (number) {
- (void)acpi_ut_divide(number, base, &number,
- &digit_index);
- *(pos++) = digits[digit_index];
- }
- }
- /* *(Pos++) = '0'; */
- return (pos);
- }
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_scan_number
- *
- * PARAMETERS: string - String buffer
- * number_ptr - Where the number is returned
- *
- * RETURN: Updated position for next valid character
- *
- * DESCRIPTION: Scan a string for a decimal integer.
- *
- ******************************************************************************/
- const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
- {
- u64 number = 0;
- while (isdigit((int)*string)) {
- number *= 10;
- number += *(string++) - '0';
- }
- *number_ptr = number;
- return (string);
- }
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_print_number
- *
- * PARAMETERS: string - String buffer
- * number - The number to be converted
- *
- * RETURN: Updated position for next valid character
- *
- * DESCRIPTION: Print a decimal integer into a string.
- *
- ******************************************************************************/
- const char *acpi_ut_print_number(char *string, u64 number)
- {
- char ascii_string[20];
- const char *pos1;
- char *pos2;
- pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
- pos2 = string;
- while (pos1 != ascii_string) {
- *(pos2++) = *(--pos1);
- }
- *pos2 = 0;
- return (string);
- }
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_format_number
- *
- * PARAMETERS: string - String buffer with boundary
- * end - Boundary of the string
- * number - The number to be converted
- * base - Base of the integer
- * width - Field width
- * precision - Precision of the integer
- * type - Special printing flags
- *
- * RETURN: Updated position for next valid character
- *
- * DESCRIPTION: Print an integer into a string with any base and any precision.
- *
- ******************************************************************************/
- static char *acpi_ut_format_number(char *string,
- char *end,
- u64 number,
- u8 base, s32 width, s32 precision, u8 type)
- {
- char *pos;
- char sign;
- char zero;
- u8 need_prefix;
- u8 upper;
- s32 i;
- char reversed_string[66];
- /* Parameter validation */
- if (base < 2 || base > 16) {
- return (NULL);
- }
- if (type & ACPI_FORMAT_LEFT) {
- type &= ~ACPI_FORMAT_ZERO;
- }
- need_prefix = ((type & ACPI_FORMAT_PREFIX)
- && base != 10) ? TRUE : FALSE;
- upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
- zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
- /* Calculate size according to sign and prefix */
- sign = '\0';
- if (type & ACPI_FORMAT_SIGN) {
- if ((s64) number < 0) {
- sign = '-';
- number = -(s64) number;
- width--;
- } else if (type & ACPI_FORMAT_SIGN_PLUS) {
- sign = '+';
- width--;
- } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
- sign = ' ';
- width--;
- }
- }
- if (need_prefix) {
- width--;
- if (base == 16) {
- width--;
- }
- }
- /* Generate full string in reverse order */
- pos = acpi_ut_put_number(reversed_string, number, base, upper);
- i = ACPI_PTR_DIFF(pos, reversed_string);
- /* Printing 100 using %2d gives "100", not "00" */
- if (i > precision) {
- precision = i;
- }
- width -= precision;
- /* Output the string */
- if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
- while (--width >= 0) {
- string = acpi_ut_bound_string_output(string, end, ' ');
- }
- }
- if (sign) {
- string = acpi_ut_bound_string_output(string, end, sign);
- }
- if (need_prefix) {
- string = acpi_ut_bound_string_output(string, end, '0');
- if (base == 16) {
- string = acpi_ut_bound_string_output(string, end,
- upper ? 'X' : 'x');
- }
- }
- if (!(type & ACPI_FORMAT_LEFT)) {
- while (--width >= 0) {
- string = acpi_ut_bound_string_output(string, end, zero);
- }
- }
- while (i <= --precision) {
- string = acpi_ut_bound_string_output(string, end, '0');
- }
- while (--i >= 0) {
- string = acpi_ut_bound_string_output(string, end,
- reversed_string[i]);
- }
- while (--width >= 0) {
- string = acpi_ut_bound_string_output(string, end, ' ');
- }
- return (string);
- }
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_vsnprintf
- *
- * PARAMETERS: string - String with boundary
- * size - Boundary of the string
- * format - Standard printf format
- * args - Argument list
- *
- * RETURN: Number of bytes actually written.
- *
- * DESCRIPTION: Formatted output to a string using argument list pointer.
- *
- ******************************************************************************/
- int
- acpi_ut_vsnprintf(char *string,
- acpi_size size, const char *format, va_list args)
- {
- u8 base;
- u8 type;
- s32 width;
- s32 precision;
- char qualifier;
- u64 number;
- char *pos;
- char *end;
- char c;
- const char *s;
- const void *p;
- s32 length;
- int i;
- pos = string;
- end = string + size;
- for (; *format; ++format) {
- if (*format != '%') {
- pos = acpi_ut_bound_string_output(pos, end, *format);
- continue;
- }
- type = 0;
- base = 10;
- /* Process sign */
- do {
- ++format;
- if (*format == '#') {
- type |= ACPI_FORMAT_PREFIX;
- } else if (*format == '0') {
- type |= ACPI_FORMAT_ZERO;
- } else if (*format == '+') {
- type |= ACPI_FORMAT_SIGN_PLUS;
- } else if (*format == ' ') {
- type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
- } else if (*format == '-') {
- type |= ACPI_FORMAT_LEFT;
- } else {
- break;
- }
- } while (1);
- /* Process width */
- width = -1;
- if (isdigit((int)*format)) {
- format = acpi_ut_scan_number(format, &number);
- width = (s32) number;
- } else if (*format == '*') {
- ++format;
- width = va_arg(args, int);
- if (width < 0) {
- width = -width;
- type |= ACPI_FORMAT_LEFT;
- }
- }
- /* Process precision */
- precision = -1;
- if (*format == '.') {
- ++format;
- if (isdigit((int)*format)) {
- format = acpi_ut_scan_number(format, &number);
- precision = (s32) number;
- } else if (*format == '*') {
- ++format;
- precision = va_arg(args, int);
- }
- if (precision < 0) {
- precision = 0;
- }
- }
- /* Process qualifier */
- qualifier = -1;
- if (*format == 'h' || *format == 'l' || *format == 'L') {
- qualifier = *format;
- ++format;
- if (qualifier == 'l' && *format == 'l') {
- qualifier = 'L';
- ++format;
- }
- }
- switch (*format) {
- case '%':
- pos = acpi_ut_bound_string_output(pos, end, '%');
- continue;
- case 'c':
- if (!(type & ACPI_FORMAT_LEFT)) {
- while (--width > 0) {
- pos =
- acpi_ut_bound_string_output(pos,
- end,
- ' ');
- }
- }
- c = (char)va_arg(args, int);
- pos = acpi_ut_bound_string_output(pos, end, c);
- while (--width > 0) {
- pos =
- acpi_ut_bound_string_output(pos, end, ' ');
- }
- continue;
- case 's':
- s = va_arg(args, char *);
- if (!s) {
- s = "<NULL>";
- }
- length = acpi_ut_bound_string_length(s, precision);
- if (!(type & ACPI_FORMAT_LEFT)) {
- while (length < width--) {
- pos =
- acpi_ut_bound_string_output(pos,
- end,
- ' ');
- }
- }
- for (i = 0; i < length; ++i) {
- pos = acpi_ut_bound_string_output(pos, end, *s);
- ++s;
- }
- while (length < width--) {
- pos =
- acpi_ut_bound_string_output(pos, end, ' ');
- }
- continue;
- case 'o':
- base = 8;
- break;
- case 'X':
- type |= ACPI_FORMAT_UPPER;
- case 'x':
- base = 16;
- break;
- case 'd':
- case 'i':
- type |= ACPI_FORMAT_SIGN;
- case 'u':
- break;
- case 'p':
- if (width == -1) {
- width = 2 * sizeof(void *);
- type |= ACPI_FORMAT_ZERO;
- }
- p = va_arg(args, void *);
- pos = acpi_ut_format_number(pos, end,
- ACPI_TO_INTEGER(p), 16,
- width, precision, type);
- continue;
- default:
- pos = acpi_ut_bound_string_output(pos, end, '%');
- if (*format) {
- pos =
- acpi_ut_bound_string_output(pos, end,
- *format);
- } else {
- --format;
- }
- continue;
- }
- if (qualifier == 'L') {
- number = va_arg(args, u64);
- if (type & ACPI_FORMAT_SIGN) {
- number = (s64) number;
- }
- } else if (qualifier == 'l') {
- number = va_arg(args, unsigned long);
- if (type & ACPI_FORMAT_SIGN) {
- number = (s32) number;
- }
- } else if (qualifier == 'h') {
- number = (u16)va_arg(args, int);
- if (type & ACPI_FORMAT_SIGN) {
- number = (s16) number;
- }
- } else {
- number = va_arg(args, unsigned int);
- if (type & ACPI_FORMAT_SIGN) {
- number = (signed int)number;
- }
- }
- pos = acpi_ut_format_number(pos, end, number, base,
- width, precision, type);
- }
- if (size > 0) {
- if (pos < end) {
- *pos = '\0';
- } else {
- end[-1] = '\0';
- }
- }
- return (ACPI_PTR_DIFF(pos, string));
- }
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_snprintf
- *
- * PARAMETERS: string - String with boundary
- * size - Boundary of the string
- * Format, ... - Standard printf format
- *
- * RETURN: Number of bytes actually written.
- *
- * DESCRIPTION: Formatted output to a string.
- *
- ******************************************************************************/
- int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
- {
- va_list args;
- int length;
- va_start(args, format);
- length = acpi_ut_vsnprintf(string, size, format, args);
- va_end(args);
- return (length);
- }
- #ifdef ACPI_APPLICATION
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_file_vprintf
- *
- * PARAMETERS: file - File descriptor
- * format - Standard printf format
- * args - Argument list
- *
- * RETURN: Number of bytes actually written.
- *
- * DESCRIPTION: Formatted output to a file using argument list pointer.
- *
- ******************************************************************************/
- int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
- {
- acpi_cpu_flags flags;
- int length;
- flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
- length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
- sizeof(acpi_gbl_print_buffer), format, args);
- (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
- acpi_os_release_lock(acpi_gbl_print_lock, flags);
- return (length);
- }
- /*******************************************************************************
- *
- * FUNCTION: acpi_ut_file_printf
- *
- * PARAMETERS: file - File descriptor
- * Format, ... - Standard printf format
- *
- * RETURN: Number of bytes actually written.
- *
- * DESCRIPTION: Formatted output to a file.
- *
- ******************************************************************************/
- int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
- {
- va_list args;
- int length;
- va_start(args, format);
- length = acpi_ut_file_vprintf(file, format, args);
- va_end(args);
- return (length);
- }
- #endif
|