Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/******************************************************************************
  3 *
  4 * Module Name: utprint - Formatted printing routines
  5 *
  6 * Copyright (C) 2000 - 2023, Intel Corp.
  7 *
  8 *****************************************************************************/
  9
 10#include <acpi/acpi.h>
 11#include "accommon.h"
 12
 13#define _COMPONENT          ACPI_UTILITIES
 14ACPI_MODULE_NAME("utprint")
 15
 16#define ACPI_FORMAT_SIGN            0x01
 17#define ACPI_FORMAT_SIGN_PLUS       0x02
 18#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
 19#define ACPI_FORMAT_ZERO            0x08
 20#define ACPI_FORMAT_LEFT            0x10
 21#define ACPI_FORMAT_UPPER           0x20
 22#define ACPI_FORMAT_PREFIX          0x40
 23/* Local prototypes */
 24static acpi_size
 25acpi_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_length
 39 *
 40 * PARAMETERS:  string              - String with boundary
 41 *              count               - Boundary of the string
 42 *
 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_size
 50acpi_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_output
 66 *
 67 * PARAMETERS:  string              - String with boundary
 68 *              end                 - Boundary of the string
 69 *              c                   - Character to be output to the string
 70 *
 71 * RETURN:      Updated position for next valid character
 72 *
 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_number
 91 *
 92 * PARAMETERS:  string              - Buffer to hold reverse-ordered string
 93 *              number              - Integer to be converted
 94 *              base                - Base of the integer
 95 *              upper               - Whether or not using upper cased digits
 96 *
 97 * RETURN:      Updated position for next valid character
 98 *
 99 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
100 *              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_number
130 *
131 * PARAMETERS:  string              - String buffer
132 *              number_ptr          - Where the number is returned
133 *
134 * RETURN:      Updated position for next valid character
135 *
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_number
156 *
157 * PARAMETERS:  string              - String buffer
158 *              number              - The number to be converted
159 *
160 * RETURN:      Updated position for next valid character
161 *
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_number
186 *
187 * PARAMETERS:  string              - String buffer with boundary
188 *              end                 - Boundary of the string
189 *              number              - The number to be converted
190 *              base                - Base of the integer
191 *              width               - Field width
192 *              precision           - Precision of the integer
193 *              type                - Special printing flags
194 *
195 * RETURN:      Updated position for next valid character
196 *
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:    vsnprintf
306 *
307 * PARAMETERS:  string              - String with boundary
308 *              size                - Boundary of the string
309 *              format              - Standard printf format
310 *              args                - Argument list
311 *
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:    snprintf
560 *
561 * PARAMETERS:  string              - String with boundary
562 *              size                - Boundary of the string
563 *              Format, ...         - Standard printf format
564 *
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:    sprintf
586 *
587 * PARAMETERS:  string              - String with boundary
588 *              Format, ...         - Standard printf format
589 *
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_APPLICATION
609/*******************************************************************************
610 *
611 * FUNCTION:    vprintf
612 *
613 * PARAMETERS:  format              - Standard printf format
614 *              args                - Argument list
615 *
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:    printf
640 *
641 * PARAMETERS:  Format, ...         - Standard printf format
642 *
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:    vfprintf
664 *
665 * PARAMETERS:  file                - File descriptor
666 *              format              - Standard printf format
667 *              args                - Argument list
668 *
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:    fprintf
693 *
694 * PARAMETERS:  file                - File descriptor
695 *              Format, ...         - Standard printf format
696 *
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#endif