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