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 - 2018, 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
474		case 'x':
475
476			base = 16;
477			break;
478
479		case 'd':
480		case 'i':
481
482			type |= ACPI_FORMAT_SIGN;
483
484		case 'u':
485
486			break;
487
488		case 'p':
489
490			if (width == -1) {
491				width = 2 * sizeof(void *);
492				type |= ACPI_FORMAT_ZERO;
493			}
494
495			p = va_arg(args, void *);
496			pos =
497			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
498						  16, width, precision, type);
499			continue;
500
501		default:
502
503			pos = acpi_ut_bound_string_output(pos, end, '%');
504			if (*format) {
505				pos =
506				    acpi_ut_bound_string_output(pos, end,
507								*format);
508			} else {
509				--format;
510			}
511			continue;
512		}
513
514		if (qualifier == 'L') {
515			number = va_arg(args, u64);
516			if (type & ACPI_FORMAT_SIGN) {
517				number = (s64)number;
518			}
519		} else if (qualifier == 'l') {
520			number = va_arg(args, unsigned long);
521			if (type & ACPI_FORMAT_SIGN) {
522				number = (s32)number;
523			}
524		} else if (qualifier == 'h') {
525			number = (u16)va_arg(args, int);
526			if (type & ACPI_FORMAT_SIGN) {
527				number = (s16)number;
528			}
529		} else {
530			number = va_arg(args, unsigned int);
531			if (type & ACPI_FORMAT_SIGN) {
532				number = (signed int)number;
533			}
534		}
535
536		pos = acpi_ut_format_number(pos, end, number, base,
537					    width, precision, type);
538	}
539
540	if (size > 0) {
541		if (pos < end) {
542			*pos = '\0';
543		} else {
544			end[-1] = '\0';
545		}
546	}
547
548	return ((int)ACPI_PTR_DIFF(pos, string));
549}
550
551/*******************************************************************************
552 *
553 * FUNCTION:    snprintf
554 *
555 * PARAMETERS:  string              - String with boundary
556 *              size                - Boundary of the string
557 *              Format, ...         - Standard printf format
558 *
559 * RETURN:      Number of bytes actually written.
560 *
561 * DESCRIPTION: Formatted output to a string.
562 *
563 ******************************************************************************/
564
565int snprintf(char *string, acpi_size size, const char *format, ...)
566{
567	va_list args;
568	int length;
569
570	va_start(args, format);
571	length = vsnprintf(string, size, format, args);
572	va_end(args);
573
574	return (length);
575}
576
577/*******************************************************************************
578 *
579 * FUNCTION:    sprintf
580 *
581 * PARAMETERS:  string              - String with boundary
582 *              Format, ...         - Standard printf format
583 *
584 * RETURN:      Number of bytes actually written.
585 *
586 * DESCRIPTION: Formatted output to a string.
587 *
588 ******************************************************************************/
589
590int sprintf(char *string, const char *format, ...)
591{
592	va_list args;
593	int length;
594
595	va_start(args, format);
596	length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
597	va_end(args);
598
599	return (length);
600}
601
602#ifdef ACPI_APPLICATION
603/*******************************************************************************
604 *
605 * FUNCTION:    vprintf
606 *
607 * PARAMETERS:  format              - Standard printf format
608 *              args                - Argument list
609 *
610 * RETURN:      Number of bytes actually written.
611 *
612 * DESCRIPTION: Formatted output to stdout using argument list pointer.
613 *
614 ******************************************************************************/
615
616int vprintf(const char *format, va_list args)
617{
618	acpi_cpu_flags flags;
619	int length;
620
621	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
622	length = vsnprintf(acpi_gbl_print_buffer,
623			   sizeof(acpi_gbl_print_buffer), format, args);
624
625	(void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
626	acpi_os_release_lock(acpi_gbl_print_lock, flags);
627
628	return (length);
629}
630
631/*******************************************************************************
632 *
633 * FUNCTION:    printf
634 *
635 * PARAMETERS:  Format, ...         - Standard printf format
636 *
637 * RETURN:      Number of bytes actually written.
638 *
639 * DESCRIPTION: Formatted output to stdout.
640 *
641 ******************************************************************************/
642
643int printf(const char *format, ...)
644{
645	va_list args;
646	int length;
647
648	va_start(args, format);
649	length = vprintf(format, args);
650	va_end(args);
651
652	return (length);
653}
654
655/*******************************************************************************
656 *
657 * FUNCTION:    vfprintf
658 *
659 * PARAMETERS:  file                - File descriptor
660 *              format              - Standard printf format
661 *              args                - Argument list
662 *
663 * RETURN:      Number of bytes actually written.
664 *
665 * DESCRIPTION: Formatted output to a file using argument list pointer.
666 *
667 ******************************************************************************/
668
669int vfprintf(FILE * file, const char *format, va_list args)
670{
671	acpi_cpu_flags flags;
672	int length;
673
674	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
675	length = vsnprintf(acpi_gbl_print_buffer,
676			   sizeof(acpi_gbl_print_buffer), format, args);
677
678	(void)fwrite(acpi_gbl_print_buffer, length, 1, file);
679	acpi_os_release_lock(acpi_gbl_print_lock, flags);
680
681	return (length);
682}
683
684/*******************************************************************************
685 *
686 * FUNCTION:    fprintf
687 *
688 * PARAMETERS:  file                - File descriptor
689 *              Format, ...         - Standard printf format
690 *
691 * RETURN:      Number of bytes actually written.
692 *
693 * DESCRIPTION: Formatted output to a file.
694 *
695 ******************************************************************************/
696
697int fprintf(FILE * file, const char *format, ...)
698{
699	va_list args;
700	int length;
701
702	va_start(args, format);
703	length = vfprintf(file, format, args);
704	va_end(args);
705
706	return (length);
707}
708#endif