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 - 2019, 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	end = string + size;
336
337	for (; *format; ++format) {
338		if (*format != '%') {
339			pos = acpi_ut_bound_string_output(pos, end, *format);
340			continue;
341		}
342
343		type = 0;
344		base = 10;
345
346		/* Process sign */
347
348		do {
349			++format;
350			if (*format == '#') {
351				type |= ACPI_FORMAT_PREFIX;
352			} else if (*format == '0') {
353				type |= ACPI_FORMAT_ZERO;
354			} else if (*format == '+') {
355				type |= ACPI_FORMAT_SIGN_PLUS;
356			} else if (*format == ' ') {
357				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
358			} else if (*format == '-') {
359				type |= ACPI_FORMAT_LEFT;
360			} else {
361				break;
362			}
363
364		} while (1);
365
366		/* Process width */
367
368		width = -1;
369		if (isdigit((int)*format)) {
370			format = acpi_ut_scan_number(format, &number);
371			width = (s32)number;
372		} else if (*format == '*') {
373			++format;
374			width = va_arg(args, int);
375			if (width < 0) {
376				width = -width;
377				type |= ACPI_FORMAT_LEFT;
378			}
379		}
380
381		/* Process precision */
382
383		precision = -1;
384		if (*format == '.') {
385			++format;
386			if (isdigit((int)*format)) {
387				format = acpi_ut_scan_number(format, &number);
388				precision = (s32)number;
389			} else if (*format == '*') {
390				++format;
391				precision = va_arg(args, int);
392			}
393
394			if (precision < 0) {
395				precision = 0;
396			}
397		}
398
399		/* Process qualifier */
400
401		qualifier = -1;
402		if (*format == 'h' || *format == 'l' || *format == 'L') {
403			qualifier = *format;
404			++format;
405
406			if (qualifier == 'l' && *format == 'l') {
407				qualifier = 'L';
408				++format;
409			}
410		}
411
412		switch (*format) {
413		case '%':
414
415			pos = acpi_ut_bound_string_output(pos, end, '%');
416			continue;
417
418		case 'c':
419
420			if (!(type & ACPI_FORMAT_LEFT)) {
421				while (--width > 0) {
422					pos =
423					    acpi_ut_bound_string_output(pos,
424									end,
425									' ');
426				}
427			}
428
429			c = (char)va_arg(args, int);
430			pos = acpi_ut_bound_string_output(pos, end, c);
431
432			while (--width > 0) {
433				pos =
434				    acpi_ut_bound_string_output(pos, end, ' ');
435			}
436			continue;
437
438		case 's':
439
440			s = va_arg(args, char *);
441			if (!s) {
442				s = "<NULL>";
443			}
444			length = (s32)acpi_ut_bound_string_length(s, precision);
445			if (!(type & ACPI_FORMAT_LEFT)) {
446				while (length < width--) {
447					pos =
448					    acpi_ut_bound_string_output(pos,
449									end,
450									' ');
451				}
452			}
453
454			for (i = 0; i < length; ++i) {
455				pos = acpi_ut_bound_string_output(pos, end, *s);
456				++s;
457			}
458
459			while (length < width--) {
460				pos =
461				    acpi_ut_bound_string_output(pos, end, ' ');
462			}
463			continue;
464
465		case 'o':
466
467			base = 8;
468			break;
469
470		case 'X':
471
472			type |= ACPI_FORMAT_UPPER;
473			/* FALLTHROUGH */
474
475		case 'x':
476
477			base = 16;
478			break;
479
480		case 'd':
481		case 'i':
482
483			type |= ACPI_FORMAT_SIGN;
484
485		case 'u':
486
487			break;
488
489		case 'p':
490
491			if (width == -1) {
492				width = 2 * sizeof(void *);
493				type |= ACPI_FORMAT_ZERO;
494			}
495
496			p = va_arg(args, void *);
497			pos =
498			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
499						  16, width, precision, type);
500			continue;
501
502		default:
503
504			pos = acpi_ut_bound_string_output(pos, end, '%');
505			if (*format) {
506				pos =
507				    acpi_ut_bound_string_output(pos, end,
508								*format);
509			} else {
510				--format;
511			}
512			continue;
513		}
514
515		if (qualifier == 'L') {
516			number = va_arg(args, u64);
517			if (type & ACPI_FORMAT_SIGN) {
518				number = (s64)number;
519			}
520		} else if (qualifier == 'l') {
521			number = va_arg(args, unsigned long);
522			if (type & ACPI_FORMAT_SIGN) {
523				number = (s32)number;
524			}
525		} else if (qualifier == 'h') {
526			number = (u16)va_arg(args, int);
527			if (type & ACPI_FORMAT_SIGN) {
528				number = (s16)number;
529			}
530		} else {
531			number = va_arg(args, unsigned int);
532			if (type & ACPI_FORMAT_SIGN) {
533				number = (signed int)number;
534			}
535		}
536
537		pos = acpi_ut_format_number(pos, end, number, base,
538					    width, precision, type);
539	}
540
541	if (size > 0) {
542		if (pos < end) {
543			*pos = '\0';
544		} else {
545			end[-1] = '\0';
546		}
547	}
548
549	return ((int)ACPI_PTR_DIFF(pos, string));
550}
551
552/*******************************************************************************
553 *
554 * FUNCTION:    snprintf
555 *
556 * PARAMETERS:  string              - String with boundary
557 *              size                - Boundary of the string
558 *              Format, ...         - Standard printf format
559 *
560 * RETURN:      Number of bytes actually written.
561 *
562 * DESCRIPTION: Formatted output to a string.
563 *
564 ******************************************************************************/
565
566int snprintf(char *string, acpi_size size, const char *format, ...)
567{
568	va_list args;
569	int length;
570
571	va_start(args, format);
572	length = vsnprintf(string, size, format, args);
573	va_end(args);
574
575	return (length);
576}
577
578/*******************************************************************************
579 *
580 * FUNCTION:    sprintf
581 *
582 * PARAMETERS:  string              - String with boundary
583 *              Format, ...         - Standard printf format
584 *
585 * RETURN:      Number of bytes actually written.
586 *
587 * DESCRIPTION: Formatted output to a string.
588 *
589 ******************************************************************************/
590
591int sprintf(char *string, const char *format, ...)
592{
593	va_list args;
594	int length;
595
596	va_start(args, format);
597	length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
598	va_end(args);
599
600	return (length);
601}
602
603#ifdef ACPI_APPLICATION
604/*******************************************************************************
605 *
606 * FUNCTION:    vprintf
607 *
608 * PARAMETERS:  format              - Standard printf format
609 *              args                - Argument list
610 *
611 * RETURN:      Number of bytes actually written.
612 *
613 * DESCRIPTION: Formatted output to stdout using argument list pointer.
614 *
615 ******************************************************************************/
616
617int vprintf(const char *format, va_list args)
618{
619	acpi_cpu_flags flags;
620	int length;
621
622	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
623	length = vsnprintf(acpi_gbl_print_buffer,
624			   sizeof(acpi_gbl_print_buffer), format, args);
625
626	(void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
627	acpi_os_release_lock(acpi_gbl_print_lock, flags);
628
629	return (length);
630}
631
632/*******************************************************************************
633 *
634 * FUNCTION:    printf
635 *
636 * PARAMETERS:  Format, ...         - Standard printf format
637 *
638 * RETURN:      Number of bytes actually written.
639 *
640 * DESCRIPTION: Formatted output to stdout.
641 *
642 ******************************************************************************/
643
644int printf(const char *format, ...)
645{
646	va_list args;
647	int length;
648
649	va_start(args, format);
650	length = vprintf(format, args);
651	va_end(args);
652
653	return (length);
654}
655
656/*******************************************************************************
657 *
658 * FUNCTION:    vfprintf
659 *
660 * PARAMETERS:  file                - File descriptor
661 *              format              - Standard printf format
662 *              args                - Argument list
663 *
664 * RETURN:      Number of bytes actually written.
665 *
666 * DESCRIPTION: Formatted output to a file using argument list pointer.
667 *
668 ******************************************************************************/
669
670int vfprintf(FILE * file, const char *format, va_list args)
671{
672	acpi_cpu_flags flags;
673	int length;
674
675	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
676	length = vsnprintf(acpi_gbl_print_buffer,
677			   sizeof(acpi_gbl_print_buffer), format, args);
678
679	(void)fwrite(acpi_gbl_print_buffer, length, 1, file);
680	acpi_os_release_lock(acpi_gbl_print_lock, flags);
681
682	return (length);
683}
684
685/*******************************************************************************
686 *
687 * FUNCTION:    fprintf
688 *
689 * PARAMETERS:  file                - File descriptor
690 *              Format, ...         - Standard printf format
691 *
692 * RETURN:      Number of bytes actually written.
693 *
694 * DESCRIPTION: Formatted output to a file.
695 *
696 ******************************************************************************/
697
698int fprintf(FILE * file, const char *format, ...)
699{
700	va_list args;
701	int length;
702
703	va_start(args, format);
704	length = vfprintf(file, format, args);
705	va_end(args);
706
707	return (length);
708}
709#endif