xref: /linux/drivers/acpi/acpica/utprint.c (revision 2ba9268dd603d23e17643437b2246acb6844953b)
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
48 ACPI_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 */
58 static acpi_size
59 acpi_ut_bound_string_length(const char *string, acpi_size count);
60 
61 static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
62 
63 static char *acpi_ut_format_number(char *string,
64 				   char *end,
65 				   u64 number,
66 				   u8 base, s32 width, s32 precision, u8 type);
67 
68 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
69 
70 /* Module globals */
71 
72 static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
73 static 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 
88 static acpi_size
89 acpi_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 
116 static 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 
143 static 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 
179 const 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 
205 const 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 
240 static 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 
356 int
357 acpi_ut_vsnprintf(char *string,
358 		  acpi_size size, const char *format, va_list args)
359 {
360 	u8 base = 10;
361 	u8 type = 0;
362 	s32 width = -1;
363 	s32 precision = -1;
364 	char qualifier = 0;
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 		/* Process sign */
384 
385 		do {
386 			++format;
387 			if (*format == '#') {
388 				type |= ACPI_FORMAT_PREFIX;
389 			} else if (*format == '0') {
390 				type |= ACPI_FORMAT_ZERO;
391 			} else if (*format == '+') {
392 				type |= ACPI_FORMAT_SIGN_PLUS;
393 			} else if (*format == ' ') {
394 				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
395 			} else if (*format == '-') {
396 				type |= ACPI_FORMAT_LEFT;
397 			} else {
398 				break;
399 			}
400 		} while (1);
401 
402 		/* Process width */
403 
404 		width = -1;
405 		if (ACPI_IS_DIGIT(*format)) {
406 			format = acpi_ut_scan_number(format, &number);
407 			width = (s32) number;
408 		} else if (*format == '*') {
409 			++format;
410 			width = va_arg(args, int);
411 			if (width < 0) {
412 				width = -width;
413 				type |= ACPI_FORMAT_LEFT;
414 			}
415 		}
416 
417 		/* Process precision */
418 
419 		precision = -1;
420 		if (*format == '.') {
421 			++format;
422 			if (ACPI_IS_DIGIT(*format)) {
423 				format = acpi_ut_scan_number(format, &number);
424 				precision = (s32) number;
425 			} else if (*format == '*') {
426 				++format;
427 				precision = va_arg(args, int);
428 			}
429 			if (precision < 0) {
430 				precision = 0;
431 			}
432 		}
433 
434 		/* Process qualifier */
435 
436 		qualifier = -1;
437 		if (*format == 'h' || *format == 'l' || *format == 'L') {
438 			qualifier = *format;
439 			++format;
440 
441 			if (qualifier == 'l' && *format == 'l') {
442 				qualifier = 'L';
443 				++format;
444 			}
445 		}
446 
447 		switch (*format) {
448 		case '%':
449 
450 			pos = acpi_ut_bound_string_output(pos, end, '%');
451 			continue;
452 
453 		case 'c':
454 
455 			if (!(type & ACPI_FORMAT_LEFT)) {
456 				while (--width > 0) {
457 					pos =
458 					    acpi_ut_bound_string_output(pos,
459 									end,
460 									' ');
461 				}
462 			}
463 
464 			c = (char)va_arg(args, int);
465 			pos = acpi_ut_bound_string_output(pos, end, c);
466 
467 			while (--width > 0) {
468 				pos =
469 				    acpi_ut_bound_string_output(pos, end, ' ');
470 			}
471 			continue;
472 
473 		case 's':
474 
475 			s = va_arg(args, char *);
476 			if (!s) {
477 				s = "<NULL>";
478 			}
479 			length = acpi_ut_bound_string_length(s, precision);
480 			if (!(type & ACPI_FORMAT_LEFT)) {
481 				while (length < width--) {
482 					pos =
483 					    acpi_ut_bound_string_output(pos,
484 									end,
485 									' ');
486 				}
487 			}
488 			for (i = 0; i < length; ++i) {
489 				pos = acpi_ut_bound_string_output(pos, end, *s);
490 				++s;
491 			}
492 			while (length < width--) {
493 				pos =
494 				    acpi_ut_bound_string_output(pos, end, ' ');
495 			}
496 			continue;
497 
498 		case 'o':
499 
500 			base = 8;
501 			break;
502 
503 		case 'X':
504 
505 			type |= ACPI_FORMAT_UPPER;
506 
507 		case 'x':
508 
509 			base = 16;
510 			break;
511 
512 		case 'd':
513 		case 'i':
514 
515 			type |= ACPI_FORMAT_SIGN;
516 
517 		case 'u':
518 
519 			break;
520 
521 		case 'p':
522 
523 			if (width == -1) {
524 				width = 2 * sizeof(void *);
525 				type |= ACPI_FORMAT_ZERO;
526 			}
527 
528 			p = va_arg(args, void *);
529 			pos = acpi_ut_format_number(pos, end,
530 						    ACPI_TO_INTEGER(p), 16,
531 						    width, precision, type);
532 			continue;
533 
534 		default:
535 
536 			pos = acpi_ut_bound_string_output(pos, end, '%');
537 			if (*format) {
538 				pos =
539 				    acpi_ut_bound_string_output(pos, end,
540 								*format);
541 			} else {
542 				--format;
543 			}
544 			continue;
545 		}
546 
547 		if (qualifier == 'L') {
548 			number = va_arg(args, u64);
549 			if (type & ACPI_FORMAT_SIGN) {
550 				number = (s64) number;
551 			}
552 		} else if (qualifier == 'l') {
553 			number = va_arg(args, unsigned long);
554 			if (type & ACPI_FORMAT_SIGN) {
555 				number = (s32) number;
556 			}
557 		} else if (qualifier == 'h') {
558 			number = (u16)va_arg(args, int);
559 			if (type & ACPI_FORMAT_SIGN) {
560 				number = (s16) number;
561 			}
562 		} else {
563 			number = va_arg(args, unsigned int);
564 			if (type & ACPI_FORMAT_SIGN) {
565 				number = (signed int)number;
566 			}
567 		}
568 
569 		pos = acpi_ut_format_number(pos, end, number, base,
570 					    width, precision, type);
571 	}
572 
573 	if (size > 0) {
574 		if (pos < end) {
575 			*pos = '\0';
576 		} else {
577 			end[-1] = '\0';
578 		}
579 	}
580 
581 	return (ACPI_PTR_DIFF(pos, string));
582 }
583 
584 /*******************************************************************************
585  *
586  * FUNCTION:    acpi_ut_snprintf
587  *
588  * PARAMETERS:  string              - String with boundary
589  *              size                - Boundary of the string
590  *              Format, ...         - Standard printf format
591  *
592  * RETURN:      Number of bytes actually written.
593  *
594  * DESCRIPTION: Formatted output to a string.
595  *
596  ******************************************************************************/
597 
598 int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
599 {
600 	va_list args;
601 	int length;
602 
603 	va_start(args, format);
604 	length = acpi_ut_vsnprintf(string, size, format, args);
605 	va_end(args);
606 
607 	return (length);
608 }
609 
610 #ifdef ACPI_APPLICATION
611 /*******************************************************************************
612  *
613  * FUNCTION:    acpi_ut_file_vprintf
614  *
615  * PARAMETERS:  file                - File descriptor
616  *              format              - Standard printf format
617  *              args                - Argument list
618  *
619  * RETURN:      Number of bytes actually written.
620  *
621  * DESCRIPTION: Formatted output to a file using argument list pointer.
622  *
623  ******************************************************************************/
624 
625 int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
626 {
627 	acpi_cpu_flags flags;
628 	int length;
629 
630 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
631 	length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
632 				   sizeof(acpi_gbl_print_buffer), format, args);
633 
634 	(void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
635 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
636 
637 	return (length);
638 }
639 
640 /*******************************************************************************
641  *
642  * FUNCTION:    acpi_ut_file_printf
643  *
644  * PARAMETERS:  file                - File descriptor
645  *              Format, ...         - Standard printf format
646  *
647  * RETURN:      Number of bytes actually written.
648  *
649  * DESCRIPTION: Formatted output to a file.
650  *
651  ******************************************************************************/
652 
653 int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
654 {
655 	va_list args;
656 	int length;
657 
658 	va_start(args, format);
659 	length = acpi_ut_file_vprintf(file, format, args);
660 	va_end(args);
661 
662 	return (length);
663 }
664 #endif
665