brintos

brintos / linux-shallow public Read only

0
0
Text · 16.4 KiB · 42b30b9 Raw
715 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: utprint - Formatted printing routines5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12 13#define _COMPONENT          ACPI_UTILITIES14ACPI_MODULE_NAME("utprint")15 16#define ACPI_FORMAT_SIGN            0x0117#define ACPI_FORMAT_SIGN_PLUS       0x0218#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x0419#define ACPI_FORMAT_ZERO            0x0820#define ACPI_FORMAT_LEFT            0x1021#define ACPI_FORMAT_UPPER           0x2022#define ACPI_FORMAT_PREFIX          0x4023/* Local prototypes */24static acpi_size25acpi_ut_bound_string_length(const char *string, acpi_size count);26 27static char *acpi_ut_bound_string_output(char *string, const char *end, char c);28 29static char *acpi_ut_format_number(char *string,30				   char *end,31				   u64 number,32				   u8 base, s32 width, s32 precision, u8 type);33 34static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);35 36/*******************************************************************************37 *38 * FUNCTION:    acpi_ut_bound_string_length39 *40 * PARAMETERS:  string              - String with boundary41 *              count               - Boundary of the string42 *43 * RETURN:      Length of the string. Less than or equal to Count.44 *45 * DESCRIPTION: Calculate the length of a string with boundary.46 *47 ******************************************************************************/48 49static acpi_size50acpi_ut_bound_string_length(const char *string, acpi_size count)51{52	u32 length = 0;53 54	while (*string && count) {55		length++;56		string++;57		count--;58	}59 60	return (length);61}62 63/*******************************************************************************64 *65 * FUNCTION:    acpi_ut_bound_string_output66 *67 * PARAMETERS:  string              - String with boundary68 *              end                 - Boundary of the string69 *              c                   - Character to be output to the string70 *71 * RETURN:      Updated position for next valid character72 *73 * DESCRIPTION: Output a character into a string with boundary check.74 *75 ******************************************************************************/76 77static char *acpi_ut_bound_string_output(char *string, const char *end, char c)78{79 80	if (string < end) {81		*string = c;82	}83 84	++string;85	return (string);86}87 88/*******************************************************************************89 *90 * FUNCTION:    acpi_ut_put_number91 *92 * PARAMETERS:  string              - Buffer to hold reverse-ordered string93 *              number              - Integer to be converted94 *              base                - Base of the integer95 *              upper               - Whether or not using upper cased digits96 *97 * RETURN:      Updated position for next valid character98 *99 * DESCRIPTION: Convert an integer into a string, note that, the string holds a100 *              reversed ordered number without the trailing zero.101 *102 ******************************************************************************/103 104static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)105{106	const char *digits;107	u64 digit_index;108	char *pos;109 110	pos = string;111	digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;112 113	if (number == 0) {114		*(pos++) = '0';115	} else {116		while (number) {117			(void)acpi_ut_divide(number, base, &number,118					     &digit_index);119			*(pos++) = digits[digit_index];120		}121	}122 123	/* *(Pos++) = '0'; */124	return (pos);125}126 127/*******************************************************************************128 *129 * FUNCTION:    acpi_ut_scan_number130 *131 * PARAMETERS:  string              - String buffer132 *              number_ptr          - Where the number is returned133 *134 * RETURN:      Updated position for next valid character135 *136 * DESCRIPTION: Scan a string for a decimal integer.137 *138 ******************************************************************************/139 140const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)141{142	u64 number = 0;143 144	while (isdigit((int)*string)) {145		acpi_ut_short_multiply(number, 10, &number);146		number += *(string++) - '0';147	}148 149	*number_ptr = number;150	return (string);151}152 153/*******************************************************************************154 *155 * FUNCTION:    acpi_ut_print_number156 *157 * PARAMETERS:  string              - String buffer158 *              number              - The number to be converted159 *160 * RETURN:      Updated position for next valid character161 *162 * DESCRIPTION: Print a decimal integer into a string.163 *164 ******************************************************************************/165 166const char *acpi_ut_print_number(char *string, u64 number)167{168	char ascii_string[20];169	const char *pos1;170	char *pos2;171 172	pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);173	pos2 = string;174 175	while (pos1 != ascii_string) {176		*(pos2++) = *(--pos1);177	}178 179	*pos2 = 0;180	return (string);181}182 183/*******************************************************************************184 *185 * FUNCTION:    acpi_ut_format_number186 *187 * PARAMETERS:  string              - String buffer with boundary188 *              end                 - Boundary of the string189 *              number              - The number to be converted190 *              base                - Base of the integer191 *              width               - Field width192 *              precision           - Precision of the integer193 *              type                - Special printing flags194 *195 * RETURN:      Updated position for next valid character196 *197 * DESCRIPTION: Print an integer into a string with any base and any precision.198 *199 ******************************************************************************/200 201static char *acpi_ut_format_number(char *string,202				   char *end,203				   u64 number,204				   u8 base, s32 width, s32 precision, u8 type)205{206	char *pos;207	char sign;208	char zero;209	u8 need_prefix;210	u8 upper;211	s32 i;212	char reversed_string[66];213 214	/* Parameter validation */215 216	if (base < 2 || base > 16) {217		return (NULL);218	}219 220	if (type & ACPI_FORMAT_LEFT) {221		type &= ~ACPI_FORMAT_ZERO;222	}223 224	need_prefix = ((type & ACPI_FORMAT_PREFIX)225		       && base != 10) ? TRUE : FALSE;226	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;227	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';228 229	/* Calculate size according to sign and prefix */230 231	sign = '\0';232	if (type & ACPI_FORMAT_SIGN) {233		if ((s64)number < 0) {234			sign = '-';235			number = -(s64)number;236			width--;237		} else if (type & ACPI_FORMAT_SIGN_PLUS) {238			sign = '+';239			width--;240		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {241			sign = ' ';242			width--;243		}244	}245	if (need_prefix) {246		width--;247		if (base == 16) {248			width--;249		}250	}251 252	/* Generate full string in reverse order */253 254	pos = acpi_ut_put_number(reversed_string, number, base, upper);255	i = (s32)ACPI_PTR_DIFF(pos, reversed_string);256 257	/* Printing 100 using %2d gives "100", not "00" */258 259	if (i > precision) {260		precision = i;261	}262 263	width -= precision;264 265	/* Output the string */266 267	if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {268		while (--width >= 0) {269			string = acpi_ut_bound_string_output(string, end, ' ');270		}271	}272	if (sign) {273		string = acpi_ut_bound_string_output(string, end, sign);274	}275	if (need_prefix) {276		string = acpi_ut_bound_string_output(string, end, '0');277		if (base == 16) {278			string =279			    acpi_ut_bound_string_output(string, end,280							upper ? 'X' : 'x');281		}282	}283	if (!(type & ACPI_FORMAT_LEFT)) {284		while (--width >= 0) {285			string = acpi_ut_bound_string_output(string, end, zero);286		}287	}288 289	while (i <= --precision) {290		string = acpi_ut_bound_string_output(string, end, '0');291	}292	while (--i >= 0) {293		string = acpi_ut_bound_string_output(string, end,294						     reversed_string[i]);295	}296	while (--width >= 0) {297		string = acpi_ut_bound_string_output(string, end, ' ');298	}299 300	return (string);301}302 303/*******************************************************************************304 *305 * FUNCTION:    vsnprintf306 *307 * PARAMETERS:  string              - String with boundary308 *              size                - Boundary of the string309 *              format              - Standard printf format310 *              args                - Argument list311 *312 * RETURN:      Number of bytes actually written.313 *314 * DESCRIPTION: Formatted output to a string using argument list pointer.315 *316 ******************************************************************************/317 318int vsnprintf(char *string, acpi_size size, const char *format, va_list args)319{320	u8 base;321	u8 type;322	s32 width;323	s32 precision;324	char qualifier;325	u64 number;326	char *pos;327	char *end;328	char c;329	const char *s;330	const void *p;331	s32 length;332	int i;333 334	pos = string;335 336	if (size != ACPI_UINT32_MAX) {337		end = string + size;338	} else {339		end = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);340	}341 342	for (; *format; ++format) {343		if (*format != '%') {344			pos = acpi_ut_bound_string_output(pos, end, *format);345			continue;346		}347 348		type = 0;349		base = 10;350 351		/* Process sign */352 353		do {354			++format;355			if (*format == '#') {356				type |= ACPI_FORMAT_PREFIX;357			} else if (*format == '0') {358				type |= ACPI_FORMAT_ZERO;359			} else if (*format == '+') {360				type |= ACPI_FORMAT_SIGN_PLUS;361			} else if (*format == ' ') {362				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;363			} else if (*format == '-') {364				type |= ACPI_FORMAT_LEFT;365			} else {366				break;367			}368 369		} while (1);370 371		/* Process width */372 373		width = -1;374		if (isdigit((int)*format)) {375			format = acpi_ut_scan_number(format, &number);376			width = (s32)number;377		} else if (*format == '*') {378			++format;379			width = va_arg(args, int);380			if (width < 0) {381				width = -width;382				type |= ACPI_FORMAT_LEFT;383			}384		}385 386		/* Process precision */387 388		precision = -1;389		if (*format == '.') {390			++format;391			if (isdigit((int)*format)) {392				format = acpi_ut_scan_number(format, &number);393				precision = (s32)number;394			} else if (*format == '*') {395				++format;396				precision = va_arg(args, int);397			}398 399			if (precision < 0) {400				precision = 0;401			}402		}403 404		/* Process qualifier */405 406		qualifier = -1;407		if (*format == 'h' || *format == 'l' || *format == 'L') {408			qualifier = *format;409			++format;410 411			if (qualifier == 'l' && *format == 'l') {412				qualifier = 'L';413				++format;414			}415		}416 417		switch (*format) {418		case '%':419 420			pos = acpi_ut_bound_string_output(pos, end, '%');421			continue;422 423		case 'c':424 425			if (!(type & ACPI_FORMAT_LEFT)) {426				while (--width > 0) {427					pos =428					    acpi_ut_bound_string_output(pos,429									end,430									' ');431				}432			}433 434			c = (char)va_arg(args, int);435			pos = acpi_ut_bound_string_output(pos, end, c);436 437			while (--width > 0) {438				pos =439				    acpi_ut_bound_string_output(pos, end, ' ');440			}441			continue;442 443		case 's':444 445			s = va_arg(args, char *);446			if (!s) {447				s = "<NULL>";448			}449			length = (s32)acpi_ut_bound_string_length(s, precision);450			if (!(type & ACPI_FORMAT_LEFT)) {451				while (length < width--) {452					pos =453					    acpi_ut_bound_string_output(pos,454									end,455									' ');456				}457			}458 459			for (i = 0; i < length; ++i) {460				pos = acpi_ut_bound_string_output(pos, end, *s);461				++s;462			}463 464			while (length < width--) {465				pos =466				    acpi_ut_bound_string_output(pos, end, ' ');467			}468			continue;469 470		case 'o':471 472			base = 8;473			break;474 475		case 'X':476 477			type |= ACPI_FORMAT_UPPER;478			ACPI_FALLTHROUGH;479 480		case 'x':481 482			base = 16;483			break;484 485		case 'd':486		case 'i':487 488			type |= ACPI_FORMAT_SIGN;489 490		case 'u':491 492			break;493 494		case 'p':495 496			if (width == -1) {497				width = 2 * sizeof(void *);498				type |= ACPI_FORMAT_ZERO;499			}500 501			p = va_arg(args, void *);502			pos =503			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),504						  16, width, precision, type);505			continue;506 507		default:508 509			pos = acpi_ut_bound_string_output(pos, end, '%');510			if (*format) {511				pos =512				    acpi_ut_bound_string_output(pos, end,513								*format);514			} else {515				--format;516			}517			continue;518		}519 520		if (qualifier == 'L') {521			number = va_arg(args, u64);522			if (type & ACPI_FORMAT_SIGN) {523				number = (s64)number;524			}525		} else if (qualifier == 'l') {526			number = va_arg(args, unsigned long);527			if (type & ACPI_FORMAT_SIGN) {528				number = (s32)number;529			}530		} else if (qualifier == 'h') {531			number = (u16)va_arg(args, int);532			if (type & ACPI_FORMAT_SIGN) {533				number = (s16)number;534			}535		} else {536			number = va_arg(args, unsigned int);537			if (type & ACPI_FORMAT_SIGN) {538				number = (signed int)number;539			}540		}541 542		pos = acpi_ut_format_number(pos, end, number, base,543					    width, precision, type);544	}545 546	if (size > 0) {547		if (pos < end) {548			*pos = '\0';549		} else {550			end[-1] = '\0';551		}552	}553 554	return ((int)ACPI_PTR_DIFF(pos, string));555}556 557/*******************************************************************************558 *559 * FUNCTION:    snprintf560 *561 * PARAMETERS:  string              - String with boundary562 *              size                - Boundary of the string563 *              Format, ...         - Standard printf format564 *565 * RETURN:      Number of bytes actually written.566 *567 * DESCRIPTION: Formatted output to a string.568 *569 ******************************************************************************/570 571int snprintf(char *string, acpi_size size, const char *format, ...)572{573	va_list args;574	int length;575 576	va_start(args, format);577	length = vsnprintf(string, size, format, args);578	va_end(args);579 580	return (length);581}582 583/*******************************************************************************584 *585 * FUNCTION:    sprintf586 *587 * PARAMETERS:  string              - String with boundary588 *              Format, ...         - Standard printf format589 *590 * RETURN:      Number of bytes actually written.591 *592 * DESCRIPTION: Formatted output to a string.593 *594 ******************************************************************************/595 596int sprintf(char *string, const char *format, ...)597{598	va_list args;599	int length;600 601	va_start(args, format);602	length = vsnprintf(string, ACPI_UINT32_MAX, format, args);603	va_end(args);604 605	return (length);606}607 608#ifdef ACPI_APPLICATION609/*******************************************************************************610 *611 * FUNCTION:    vprintf612 *613 * PARAMETERS:  format              - Standard printf format614 *              args                - Argument list615 *616 * RETURN:      Number of bytes actually written.617 *618 * DESCRIPTION: Formatted output to stdout using argument list pointer.619 *620 ******************************************************************************/621 622int vprintf(const char *format, va_list args)623{624	acpi_cpu_flags flags;625	int length;626 627	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);628	length = vsnprintf(acpi_gbl_print_buffer,629			   sizeof(acpi_gbl_print_buffer), format, args);630 631	(void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);632	acpi_os_release_lock(acpi_gbl_print_lock, flags);633 634	return (length);635}636 637/*******************************************************************************638 *639 * FUNCTION:    printf640 *641 * PARAMETERS:  Format, ...         - Standard printf format642 *643 * RETURN:      Number of bytes actually written.644 *645 * DESCRIPTION: Formatted output to stdout.646 *647 ******************************************************************************/648 649int printf(const char *format, ...)650{651	va_list args;652	int length;653 654	va_start(args, format);655	length = vprintf(format, args);656	va_end(args);657 658	return (length);659}660 661/*******************************************************************************662 *663 * FUNCTION:    vfprintf664 *665 * PARAMETERS:  file                - File descriptor666 *              format              - Standard printf format667 *              args                - Argument list668 *669 * RETURN:      Number of bytes actually written.670 *671 * DESCRIPTION: Formatted output to a file using argument list pointer.672 *673 ******************************************************************************/674 675int vfprintf(FILE * file, const char *format, va_list args)676{677	acpi_cpu_flags flags;678	int length;679 680	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);681	length = vsnprintf(acpi_gbl_print_buffer,682			   sizeof(acpi_gbl_print_buffer), format, args);683 684	(void)fwrite(acpi_gbl_print_buffer, length, 1, file);685	acpi_os_release_lock(acpi_gbl_print_lock, flags);686 687	return (length);688}689 690/*******************************************************************************691 *692 * FUNCTION:    fprintf693 *694 * PARAMETERS:  file                - File descriptor695 *              Format, ...         - Standard printf format696 *697 * RETURN:      Number of bytes actually written.698 *699 * DESCRIPTION: Formatted output to a file.700 *701 ******************************************************************************/702 703int fprintf(FILE * file, const char *format, ...)704{705	va_list args;706	int length;707 708	va_start(args, format);709	length = vfprintf(file, format, args);710	va_end(args);711 712	return (length);713}714#endif715