Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/******************************************************************************
  2 *
  3 * Module Name: utprint - Formatted printing routines
  4 *
  5 *****************************************************************************/
  6
  7/*
  8 * Copyright (C) 2000 - 2016, Intel Corp.
  9 * All rights reserved.
 10 *
 11 * Redistribution and use in source and binary forms, with or without
 12 * modification, are permitted provided that the following conditions
 13 * are met:
 14 * 1. Redistributions of source code must retain the above copyright
 15 *    notice, this list of conditions, and the following disclaimer,
 16 *    without modification.
 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 18 *    substantially similar to the "NO WARRANTY" disclaimer below
 19 *    ("Disclaimer") and any redistribution must be conditioned upon
 20 *    including a substantially similar Disclaimer requirement for further
 21 *    binary redistribution.
 22 * 3. Neither the names of the above-listed copyright holders nor the names
 23 *    of any contributors may be used to endorse or promote products derived
 24 *    from this software without specific prior written permission.
 25 *
 26 * Alternatively, this software may be distributed under the terms of the
 27 * GNU General Public License ("GPL") version 2 as published by the Free
 28 * Software Foundation.
 29 *
 30 * NO WARRANTY
 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 41 * POSSIBILITY OF SUCH DAMAGES.
 42 */
 43
 44#include <acpi/acpi.h>
 45#include "accommon.h"
 46
 47#define _COMPONENT          ACPI_UTILITIES
 48ACPI_MODULE_NAME("utprint")
 49
 50#define ACPI_FORMAT_SIGN            0x01
 51#define ACPI_FORMAT_SIGN_PLUS       0x02
 52#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
 53#define ACPI_FORMAT_ZERO            0x08
 54#define ACPI_FORMAT_LEFT            0x10
 55#define ACPI_FORMAT_UPPER           0x20
 56#define ACPI_FORMAT_PREFIX          0x40
 57/* Local prototypes */
 58static acpi_size
 59acpi_ut_bound_string_length(const char *string, acpi_size count);
 60
 61static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
 62
 63static char *acpi_ut_format_number(char *string,
 64				   char *end,
 65				   u64 number,
 66				   u8 base, s32 width, s32 precision, u8 type);
 67
 68static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
 69
 70/* Module globals */
 71
 72static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
 73static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
 74
 75/*******************************************************************************
 76 *
 77 * FUNCTION:    acpi_ut_bound_string_length
 78 *
 79 * PARAMETERS:  string              - String with boundary
 80 *              count               - Boundary of the string
 81 *
 82 * RETURN:      Length of the string. Less than or equal to Count.
 83 *
 84 * DESCRIPTION: Calculate the length of a string with boundary.
 85 *
 86 ******************************************************************************/
 87
 88static acpi_size
 89acpi_ut_bound_string_length(const char *string, acpi_size count)
 90{
 91	u32 length = 0;
 92
 93	while (*string && count) {
 94		length++;
 95		string++;
 96		count--;
 97	}
 98
 99	return (length);
100}
101
102/*******************************************************************************
103 *
104 * FUNCTION:    acpi_ut_bound_string_output
105 *
106 * PARAMETERS:  string              - String with boundary
107 *              end                 - Boundary of the string
108 *              c                   - Character to be output to the string
109 *
110 * RETURN:      Updated position for next valid character
111 *
112 * DESCRIPTION: Output a character into a string with boundary check.
113 *
114 ******************************************************************************/
115
116static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
117{
118
119	if (string < end) {
120		*string = c;
121	}
122
123	++string;
124	return (string);
125}
126
127/*******************************************************************************
128 *
129 * FUNCTION:    acpi_ut_put_number
130 *
131 * PARAMETERS:  string              - Buffer to hold reverse-ordered string
132 *              number              - Integer to be converted
133 *              base                - Base of the integer
134 *              upper               - Whether or not using upper cased digits
135 *
136 * RETURN:      Updated position for next valid character
137 *
138 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
139 *              reversed ordered number without the trailing zero.
140 *
141 ******************************************************************************/
142
143static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
144{
145	const char *digits;
146	u64 digit_index;
147	char *pos;
148
149	pos = string;
150	digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
151
152	if (number == 0) {
153		*(pos++) = '0';
154	} else {
155		while (number) {
156			(void)acpi_ut_divide(number, base, &number,
157					     &digit_index);
158			*(pos++) = digits[digit_index];
159		}
160	}
161
162	/* *(Pos++) = '0'; */
163	return (pos);
164}
165
166/*******************************************************************************
167 *
168 * FUNCTION:    acpi_ut_scan_number
169 *
170 * PARAMETERS:  string              - String buffer
171 *              number_ptr          - Where the number is returned
172 *
173 * RETURN:      Updated position for next valid character
174 *
175 * DESCRIPTION: Scan a string for a decimal integer.
176 *
177 ******************************************************************************/
178
179const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
180{
181	u64 number = 0;
182
183	while (isdigit((int)*string)) {
184		number *= 10;
185		number += *(string++) - '0';
186	}
187
188	*number_ptr = number;
189	return (string);
190}
191
192/*******************************************************************************
193 *
194 * FUNCTION:    acpi_ut_print_number
195 *
196 * PARAMETERS:  string              - String buffer
197 *              number              - The number to be converted
198 *
199 * RETURN:      Updated position for next valid character
200 *
201 * DESCRIPTION: Print a decimal integer into a string.
202 *
203 ******************************************************************************/
204
205const char *acpi_ut_print_number(char *string, u64 number)
206{
207	char ascii_string[20];
208	const char *pos1;
209	char *pos2;
210
211	pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
212	pos2 = string;
213
214	while (pos1 != ascii_string) {
215		*(pos2++) = *(--pos1);
216	}
217
218	*pos2 = 0;
219	return (string);
220}
221
222/*******************************************************************************
223 *
224 * FUNCTION:    acpi_ut_format_number
225 *
226 * PARAMETERS:  string              - String buffer with boundary
227 *              end                 - Boundary of the string
228 *              number              - The number to be converted
229 *              base                - Base of the integer
230 *              width               - Field width
231 *              precision           - Precision of the integer
232 *              type                - Special printing flags
233 *
234 * RETURN:      Updated position for next valid character
235 *
236 * DESCRIPTION: Print an integer into a string with any base and any precision.
237 *
238 ******************************************************************************/
239
240static char *acpi_ut_format_number(char *string,
241				   char *end,
242				   u64 number,
243				   u8 base, s32 width, s32 precision, u8 type)
244{
245	char *pos;
246	char sign;
247	char zero;
248	u8 need_prefix;
249	u8 upper;
250	s32 i;
251	char reversed_string[66];
252
253	/* Parameter validation */
254
255	if (base < 2 || base > 16) {
256		return (NULL);
257	}
258
259	if (type & ACPI_FORMAT_LEFT) {
260		type &= ~ACPI_FORMAT_ZERO;
261	}
262
263	need_prefix = ((type & ACPI_FORMAT_PREFIX)
264		       && base != 10) ? TRUE : FALSE;
265	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
266	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
267
268	/* Calculate size according to sign and prefix */
269
270	sign = '\0';
271	if (type & ACPI_FORMAT_SIGN) {
272		if ((s64) number < 0) {
273			sign = '-';
274			number = -(s64) number;
275			width--;
276		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
277			sign = '+';
278			width--;
279		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
280			sign = ' ';
281			width--;
282		}
283	}
284	if (need_prefix) {
285		width--;
286		if (base == 16) {
287			width--;
288		}
289	}
290
291	/* Generate full string in reverse order */
292
293	pos = acpi_ut_put_number(reversed_string, number, base, upper);
294	i = ACPI_PTR_DIFF(pos, reversed_string);
295
296	/* Printing 100 using %2d gives "100", not "00" */
297
298	if (i > precision) {
299		precision = i;
300	}
301
302	width -= precision;
303
304	/* Output the string */
305
306	if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
307		while (--width >= 0) {
308			string = acpi_ut_bound_string_output(string, end, ' ');
309		}
310	}
311	if (sign) {
312		string = acpi_ut_bound_string_output(string, end, sign);
313	}
314	if (need_prefix) {
315		string = acpi_ut_bound_string_output(string, end, '0');
316		if (base == 16) {
317			string =
318			    acpi_ut_bound_string_output(string, end,
319							upper ? 'X' : 'x');
320		}
321	}
322	if (!(type & ACPI_FORMAT_LEFT)) {
323		while (--width >= 0) {
324			string = acpi_ut_bound_string_output(string, end, zero);
325		}
326	}
327
328	while (i <= --precision) {
329		string = acpi_ut_bound_string_output(string, end, '0');
330	}
331	while (--i >= 0) {
332		string = acpi_ut_bound_string_output(string, end,
333						     reversed_string[i]);
334	}
335	while (--width >= 0) {
336		string = acpi_ut_bound_string_output(string, end, ' ');
337	}
338
339	return (string);
340}
341
342/*******************************************************************************
343 *
344 * FUNCTION:    acpi_ut_vsnprintf
345 *
346 * PARAMETERS:  string              - String with boundary
347 *              size                - Boundary of the string
348 *              format              - Standard printf format
349 *              args                - Argument list
350 *
351 * RETURN:      Number of bytes actually written.
352 *
353 * DESCRIPTION: Formatted output to a string using argument list pointer.
354 *
355 ******************************************************************************/
356
357int
358acpi_ut_vsnprintf(char *string,
359		  acpi_size size, const char *format, va_list args)
360{
361	u8 base;
362	u8 type;
363	s32 width;
364	s32 precision;
365	char qualifier;
366	u64 number;
367	char *pos;
368	char *end;
369	char c;
370	const char *s;
371	const void *p;
372	s32 length;
373	int i;
374
375	pos = string;
376	end = string + size;
377
378	for (; *format; ++format) {
379		if (*format != '%') {
380			pos = acpi_ut_bound_string_output(pos, end, *format);
381			continue;
382		}
383
384		type = 0;
385		base = 10;
386
387		/* Process sign */
388
389		do {
390			++format;
391			if (*format == '#') {
392				type |= ACPI_FORMAT_PREFIX;
393			} else if (*format == '0') {
394				type |= ACPI_FORMAT_ZERO;
395			} else if (*format == '+') {
396				type |= ACPI_FORMAT_SIGN_PLUS;
397			} else if (*format == ' ') {
398				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
399			} else if (*format == '-') {
400				type |= ACPI_FORMAT_LEFT;
401			} else {
402				break;
403			}
404
405		} while (1);
406
407		/* Process width */
408
409		width = -1;
410		if (isdigit((int)*format)) {
411			format = acpi_ut_scan_number(format, &number);
412			width = (s32) number;
413		} else if (*format == '*') {
414			++format;
415			width = va_arg(args, int);
416			if (width < 0) {
417				width = -width;
418				type |= ACPI_FORMAT_LEFT;
419			}
420		}
421
422		/* Process precision */
423
424		precision = -1;
425		if (*format == '.') {
426			++format;
427			if (isdigit((int)*format)) {
428				format = acpi_ut_scan_number(format, &number);
429				precision = (s32) number;
430			} else if (*format == '*') {
431				++format;
432				precision = va_arg(args, int);
433			}
434
435			if (precision < 0) {
436				precision = 0;
437			}
438		}
439
440		/* Process qualifier */
441
442		qualifier = -1;
443		if (*format == 'h' || *format == 'l' || *format == 'L') {
444			qualifier = *format;
445			++format;
446
447			if (qualifier == 'l' && *format == 'l') {
448				qualifier = 'L';
449				++format;
450			}
451		}
452
453		switch (*format) {
454		case '%':
455
456			pos = acpi_ut_bound_string_output(pos, end, '%');
457			continue;
458
459		case 'c':
460
461			if (!(type & ACPI_FORMAT_LEFT)) {
462				while (--width > 0) {
463					pos =
464					    acpi_ut_bound_string_output(pos,
465									end,
466									' ');
467				}
468			}
469
470			c = (char)va_arg(args, int);
471			pos = acpi_ut_bound_string_output(pos, end, c);
472
473			while (--width > 0) {
474				pos =
475				    acpi_ut_bound_string_output(pos, end, ' ');
476			}
477			continue;
478
479		case 's':
480
481			s = va_arg(args, char *);
482			if (!s) {
483				s = "<NULL>";
484			}
485			length = acpi_ut_bound_string_length(s, precision);
486			if (!(type & ACPI_FORMAT_LEFT)) {
487				while (length < width--) {
488					pos =
489					    acpi_ut_bound_string_output(pos,
490									end,
491									' ');
492				}
493			}
494
495			for (i = 0; i < length; ++i) {
496				pos = acpi_ut_bound_string_output(pos, end, *s);
497				++s;
498			}
499
500			while (length < width--) {
501				pos =
502				    acpi_ut_bound_string_output(pos, end, ' ');
503			}
504			continue;
505
506		case 'o':
507
508			base = 8;
509			break;
510
511		case 'X':
512
513			type |= ACPI_FORMAT_UPPER;
514
515		case 'x':
516
517			base = 16;
518			break;
519
520		case 'd':
521		case 'i':
522
523			type |= ACPI_FORMAT_SIGN;
524
525		case 'u':
526
527			break;
528
529		case 'p':
530
531			if (width == -1) {
532				width = 2 * sizeof(void *);
533				type |= ACPI_FORMAT_ZERO;
534			}
535
536			p = va_arg(args, void *);
537			pos =
538			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
539						  16, width, precision, type);
540			continue;
541
542		default:
543
544			pos = acpi_ut_bound_string_output(pos, end, '%');
545			if (*format) {
546				pos =
547				    acpi_ut_bound_string_output(pos, end,
548								*format);
549			} else {
550				--format;
551			}
552			continue;
553		}
554
555		if (qualifier == 'L') {
556			number = va_arg(args, u64);
557			if (type & ACPI_FORMAT_SIGN) {
558				number = (s64) number;
559			}
560		} else if (qualifier == 'l') {
561			number = va_arg(args, unsigned long);
562			if (type & ACPI_FORMAT_SIGN) {
563				number = (s32) number;
564			}
565		} else if (qualifier == 'h') {
566			number = (u16)va_arg(args, int);
567			if (type & ACPI_FORMAT_SIGN) {
568				number = (s16) number;
569			}
570		} else {
571			number = va_arg(args, unsigned int);
572			if (type & ACPI_FORMAT_SIGN) {
573				number = (signed int)number;
574			}
575		}
576
577		pos = acpi_ut_format_number(pos, end, number, base,
578					    width, precision, type);
579	}
580
581	if (size > 0) {
582		if (pos < end) {
583			*pos = '\0';
584		} else {
585			end[-1] = '\0';
586		}
587	}
588
589	return (ACPI_PTR_DIFF(pos, string));
590}
591
592/*******************************************************************************
593 *
594 * FUNCTION:    acpi_ut_snprintf
595 *
596 * PARAMETERS:  string              - String with boundary
597 *              size                - Boundary of the string
598 *              Format, ...         - Standard printf format
599 *
600 * RETURN:      Number of bytes actually written.
601 *
602 * DESCRIPTION: Formatted output to a string.
603 *
604 ******************************************************************************/
605
606int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
607{
608	va_list args;
609	int length;
610
611	va_start(args, format);
612	length = acpi_ut_vsnprintf(string, size, format, args);
613	va_end(args);
614
615	return (length);
616}
617
618#ifdef ACPI_APPLICATION
619/*******************************************************************************
620 *
621 * FUNCTION:    acpi_ut_file_vprintf
622 *
623 * PARAMETERS:  file                - File descriptor
624 *              format              - Standard printf format
625 *              args                - Argument list
626 *
627 * RETURN:      Number of bytes actually written.
628 *
629 * DESCRIPTION: Formatted output to a file using argument list pointer.
630 *
631 ******************************************************************************/
632
633int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
634{
635	acpi_cpu_flags flags;
636	int length;
637
638	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
639	length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
640				   sizeof(acpi_gbl_print_buffer), format, args);
641
642	(void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
643	acpi_os_release_lock(acpi_gbl_print_lock, flags);
644
645	return (length);
646}
647
648/*******************************************************************************
649 *
650 * FUNCTION:    acpi_ut_file_printf
651 *
652 * PARAMETERS:  file                - File descriptor
653 *              Format, ...         - Standard printf format
654 *
655 * RETURN:      Number of bytes actually written.
656 *
657 * DESCRIPTION: Formatted output to a file.
658 *
659 ******************************************************************************/
660
661int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
662{
663	va_list args;
664	int length;
665
666	va_start(args, format);
667	length = acpi_ut_file_vprintf(file, format, args);
668	va_end(args);
669
670	return (length);
671}
672#endif