• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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 /*******************************************************************************
71  *
72  * FUNCTION:    acpi_ut_bound_string_length
73  *
74  * PARAMETERS:  string              - String with boundary
75  *              count               - Boundary of the string
76  *
77  * RETURN:      Length of the string. Less than or equal to Count.
78  *
79  * DESCRIPTION: Calculate the length of a string with boundary.
80  *
81  ******************************************************************************/
82 
83 static acpi_size
acpi_ut_bound_string_length(const char * string,acpi_size count)84 acpi_ut_bound_string_length(const char *string, acpi_size count)
85 {
86 	u32 length = 0;
87 
88 	while (*string && count) {
89 		length++;
90 		string++;
91 		count--;
92 	}
93 
94 	return (length);
95 }
96 
97 /*******************************************************************************
98  *
99  * FUNCTION:    acpi_ut_bound_string_output
100  *
101  * PARAMETERS:  string              - String with boundary
102  *              end                 - Boundary of the string
103  *              c                   - Character to be output to the string
104  *
105  * RETURN:      Updated position for next valid character
106  *
107  * DESCRIPTION: Output a character into a string with boundary check.
108  *
109  ******************************************************************************/
110 
acpi_ut_bound_string_output(char * string,const char * end,char c)111 static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
112 {
113 
114 	if (string < end) {
115 		*string = c;
116 	}
117 
118 	++string;
119 	return (string);
120 }
121 
122 /*******************************************************************************
123  *
124  * FUNCTION:    acpi_ut_put_number
125  *
126  * PARAMETERS:  string              - Buffer to hold reverse-ordered string
127  *              number              - Integer to be converted
128  *              base                - Base of the integer
129  *              upper               - Whether or not using upper cased digits
130  *
131  * RETURN:      Updated position for next valid character
132  *
133  * DESCRIPTION: Convert an integer into a string, note that, the string holds a
134  *              reversed ordered number without the trailing zero.
135  *
136  ******************************************************************************/
137 
acpi_ut_put_number(char * string,u64 number,u8 base,u8 upper)138 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
139 {
140 	const char *digits;
141 	u64 digit_index;
142 	char *pos;
143 
144 	pos = string;
145 	digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
146 
147 	if (number == 0) {
148 		*(pos++) = '0';
149 	} else {
150 		while (number) {
151 			(void)acpi_ut_divide(number, base, &number,
152 					     &digit_index);
153 			*(pos++) = digits[digit_index];
154 		}
155 	}
156 
157 	/* *(Pos++) = '0'; */
158 	return (pos);
159 }
160 
161 /*******************************************************************************
162  *
163  * FUNCTION:    acpi_ut_scan_number
164  *
165  * PARAMETERS:  string              - String buffer
166  *              number_ptr          - Where the number is returned
167  *
168  * RETURN:      Updated position for next valid character
169  *
170  * DESCRIPTION: Scan a string for a decimal integer.
171  *
172  ******************************************************************************/
173 
acpi_ut_scan_number(const char * string,u64 * number_ptr)174 const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
175 {
176 	u64 number = 0;
177 
178 	while (isdigit((int)*string)) {
179 		number *= 10;
180 		number += *(string++) - '0';
181 	}
182 
183 	*number_ptr = number;
184 	return (string);
185 }
186 
187 /*******************************************************************************
188  *
189  * FUNCTION:    acpi_ut_print_number
190  *
191  * PARAMETERS:  string              - String buffer
192  *              number              - The number to be converted
193  *
194  * RETURN:      Updated position for next valid character
195  *
196  * DESCRIPTION: Print a decimal integer into a string.
197  *
198  ******************************************************************************/
199 
acpi_ut_print_number(char * string,u64 number)200 const char *acpi_ut_print_number(char *string, u64 number)
201 {
202 	char ascii_string[20];
203 	const char *pos1;
204 	char *pos2;
205 
206 	pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
207 	pos2 = string;
208 
209 	while (pos1 != ascii_string) {
210 		*(pos2++) = *(--pos1);
211 	}
212 
213 	*pos2 = 0;
214 	return (string);
215 }
216 
217 /*******************************************************************************
218  *
219  * FUNCTION:    acpi_ut_format_number
220  *
221  * PARAMETERS:  string              - String buffer with boundary
222  *              end                 - Boundary of the string
223  *              number              - The number to be converted
224  *              base                - Base of the integer
225  *              width               - Field width
226  *              precision           - Precision of the integer
227  *              type                - Special printing flags
228  *
229  * RETURN:      Updated position for next valid character
230  *
231  * DESCRIPTION: Print an integer into a string with any base and any precision.
232  *
233  ******************************************************************************/
234 
acpi_ut_format_number(char * string,char * end,u64 number,u8 base,s32 width,s32 precision,u8 type)235 static char *acpi_ut_format_number(char *string,
236 				   char *end,
237 				   u64 number,
238 				   u8 base, s32 width, s32 precision, u8 type)
239 {
240 	char *pos;
241 	char sign;
242 	char zero;
243 	u8 need_prefix;
244 	u8 upper;
245 	s32 i;
246 	char reversed_string[66];
247 
248 	/* Parameter validation */
249 
250 	if (base < 2 || base > 16) {
251 		return (NULL);
252 	}
253 
254 	if (type & ACPI_FORMAT_LEFT) {
255 		type &= ~ACPI_FORMAT_ZERO;
256 	}
257 
258 	need_prefix = ((type & ACPI_FORMAT_PREFIX)
259 		       && base != 10) ? TRUE : FALSE;
260 	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
261 	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
262 
263 	/* Calculate size according to sign and prefix */
264 
265 	sign = '\0';
266 	if (type & ACPI_FORMAT_SIGN) {
267 		if ((s64)number < 0) {
268 			sign = '-';
269 			number = -(s64)number;
270 			width--;
271 		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
272 			sign = '+';
273 			width--;
274 		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
275 			sign = ' ';
276 			width--;
277 		}
278 	}
279 	if (need_prefix) {
280 		width--;
281 		if (base == 16) {
282 			width--;
283 		}
284 	}
285 
286 	/* Generate full string in reverse order */
287 
288 	pos = acpi_ut_put_number(reversed_string, number, base, upper);
289 	i = ACPI_PTR_DIFF(pos, reversed_string);
290 
291 	/* Printing 100 using %2d gives "100", not "00" */
292 
293 	if (i > precision) {
294 		precision = i;
295 	}
296 
297 	width -= precision;
298 
299 	/* Output the string */
300 
301 	if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
302 		while (--width >= 0) {
303 			string = acpi_ut_bound_string_output(string, end, ' ');
304 		}
305 	}
306 	if (sign) {
307 		string = acpi_ut_bound_string_output(string, end, sign);
308 	}
309 	if (need_prefix) {
310 		string = acpi_ut_bound_string_output(string, end, '0');
311 		if (base == 16) {
312 			string =
313 			    acpi_ut_bound_string_output(string, end,
314 							upper ? 'X' : 'x');
315 		}
316 	}
317 	if (!(type & ACPI_FORMAT_LEFT)) {
318 		while (--width >= 0) {
319 			string = acpi_ut_bound_string_output(string, end, zero);
320 		}
321 	}
322 
323 	while (i <= --precision) {
324 		string = acpi_ut_bound_string_output(string, end, '0');
325 	}
326 	while (--i >= 0) {
327 		string = acpi_ut_bound_string_output(string, end,
328 						     reversed_string[i]);
329 	}
330 	while (--width >= 0) {
331 		string = acpi_ut_bound_string_output(string, end, ' ');
332 	}
333 
334 	return (string);
335 }
336 
337 /*******************************************************************************
338  *
339  * FUNCTION:    vsnprintf
340  *
341  * PARAMETERS:  string              - String with boundary
342  *              size                - Boundary of the string
343  *              format              - Standard printf format
344  *              args                - Argument list
345  *
346  * RETURN:      Number of bytes actually written.
347  *
348  * DESCRIPTION: Formatted output to a string using argument list pointer.
349  *
350  ******************************************************************************/
351 
vsnprintf(char * string,acpi_size size,const char * format,va_list args)352 int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
353 {
354 	u8 base;
355 	u8 type;
356 	s32 width;
357 	s32 precision;
358 	char qualifier;
359 	u64 number;
360 	char *pos;
361 	char *end;
362 	char c;
363 	const char *s;
364 	const void *p;
365 	s32 length;
366 	int i;
367 
368 	pos = string;
369 	end = string + size;
370 
371 	for (; *format; ++format) {
372 		if (*format != '%') {
373 			pos = acpi_ut_bound_string_output(pos, end, *format);
374 			continue;
375 		}
376 
377 		type = 0;
378 		base = 10;
379 
380 		/* Process sign */
381 
382 		do {
383 			++format;
384 			if (*format == '#') {
385 				type |= ACPI_FORMAT_PREFIX;
386 			} else if (*format == '0') {
387 				type |= ACPI_FORMAT_ZERO;
388 			} else if (*format == '+') {
389 				type |= ACPI_FORMAT_SIGN_PLUS;
390 			} else if (*format == ' ') {
391 				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
392 			} else if (*format == '-') {
393 				type |= ACPI_FORMAT_LEFT;
394 			} else {
395 				break;
396 			}
397 
398 		} while (1);
399 
400 		/* Process width */
401 
402 		width = -1;
403 		if (isdigit((int)*format)) {
404 			format = acpi_ut_scan_number(format, &number);
405 			width = (s32)number;
406 		} else if (*format == '*') {
407 			++format;
408 			width = va_arg(args, int);
409 			if (width < 0) {
410 				width = -width;
411 				type |= ACPI_FORMAT_LEFT;
412 			}
413 		}
414 
415 		/* Process precision */
416 
417 		precision = -1;
418 		if (*format == '.') {
419 			++format;
420 			if (isdigit((int)*format)) {
421 				format = acpi_ut_scan_number(format, &number);
422 				precision = (s32)number;
423 			} else if (*format == '*') {
424 				++format;
425 				precision = va_arg(args, int);
426 			}
427 
428 			if (precision < 0) {
429 				precision = 0;
430 			}
431 		}
432 
433 		/* Process qualifier */
434 
435 		qualifier = -1;
436 		if (*format == 'h' || *format == 'l' || *format == 'L') {
437 			qualifier = *format;
438 			++format;
439 
440 			if (qualifier == 'l' && *format == 'l') {
441 				qualifier = 'L';
442 				++format;
443 			}
444 		}
445 
446 		switch (*format) {
447 		case '%':
448 
449 			pos = acpi_ut_bound_string_output(pos, end, '%');
450 			continue;
451 
452 		case 'c':
453 
454 			if (!(type & ACPI_FORMAT_LEFT)) {
455 				while (--width > 0) {
456 					pos =
457 					    acpi_ut_bound_string_output(pos,
458 									end,
459 									' ');
460 				}
461 			}
462 
463 			c = (char)va_arg(args, int);
464 			pos = acpi_ut_bound_string_output(pos, end, c);
465 
466 			while (--width > 0) {
467 				pos =
468 				    acpi_ut_bound_string_output(pos, end, ' ');
469 			}
470 			continue;
471 
472 		case 's':
473 
474 			s = va_arg(args, char *);
475 			if (!s) {
476 				s = "<NULL>";
477 			}
478 			length = acpi_ut_bound_string_length(s, precision);
479 			if (!(type & ACPI_FORMAT_LEFT)) {
480 				while (length < width--) {
481 					pos =
482 					    acpi_ut_bound_string_output(pos,
483 									end,
484 									' ');
485 				}
486 			}
487 
488 			for (i = 0; i < length; ++i) {
489 				pos = acpi_ut_bound_string_output(pos, end, *s);
490 				++s;
491 			}
492 
493 			while (length < width--) {
494 				pos =
495 				    acpi_ut_bound_string_output(pos, end, ' ');
496 			}
497 			continue;
498 
499 		case 'o':
500 
501 			base = 8;
502 			break;
503 
504 		case 'X':
505 
506 			type |= ACPI_FORMAT_UPPER;
507 
508 		case 'x':
509 
510 			base = 16;
511 			break;
512 
513 		case 'd':
514 		case 'i':
515 
516 			type |= ACPI_FORMAT_SIGN;
517 
518 		case 'u':
519 
520 			break;
521 
522 		case 'p':
523 
524 			if (width == -1) {
525 				width = 2 * sizeof(void *);
526 				type |= ACPI_FORMAT_ZERO;
527 			}
528 
529 			p = va_arg(args, void *);
530 			pos =
531 			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
532 						  16, width, precision, type);
533 			continue;
534 
535 		default:
536 
537 			pos = acpi_ut_bound_string_output(pos, end, '%');
538 			if (*format) {
539 				pos =
540 				    acpi_ut_bound_string_output(pos, end,
541 								*format);
542 			} else {
543 				--format;
544 			}
545 			continue;
546 		}
547 
548 		if (qualifier == 'L') {
549 			number = va_arg(args, u64);
550 			if (type & ACPI_FORMAT_SIGN) {
551 				number = (s64)number;
552 			}
553 		} else if (qualifier == 'l') {
554 			number = va_arg(args, unsigned long);
555 			if (type & ACPI_FORMAT_SIGN) {
556 				number = (s32)number;
557 			}
558 		} else if (qualifier == 'h') {
559 			number = (u16)va_arg(args, int);
560 			if (type & ACPI_FORMAT_SIGN) {
561 				number = (s16)number;
562 			}
563 		} else {
564 			number = va_arg(args, unsigned int);
565 			if (type & ACPI_FORMAT_SIGN) {
566 				number = (signed int)number;
567 			}
568 		}
569 
570 		pos = acpi_ut_format_number(pos, end, number, base,
571 					    width, precision, type);
572 	}
573 
574 	if (size > 0) {
575 		if (pos < end) {
576 			*pos = '\0';
577 		} else {
578 			end[-1] = '\0';
579 		}
580 	}
581 
582 	return (ACPI_PTR_DIFF(pos, string));
583 }
584 
585 /*******************************************************************************
586  *
587  * FUNCTION:    snprintf
588  *
589  * PARAMETERS:  string              - String with boundary
590  *              size                - Boundary of the string
591  *              Format, ...         - Standard printf format
592  *
593  * RETURN:      Number of bytes actually written.
594  *
595  * DESCRIPTION: Formatted output to a string.
596  *
597  ******************************************************************************/
598 
snprintf(char * string,acpi_size size,const char * format,...)599 int snprintf(char *string, acpi_size size, const char *format, ...)
600 {
601 	va_list args;
602 	int length;
603 
604 	va_start(args, format);
605 	length = vsnprintf(string, size, format, args);
606 	va_end(args);
607 
608 	return (length);
609 }
610 
611 /*******************************************************************************
612  *
613  * FUNCTION:    sprintf
614  *
615  * PARAMETERS:  string              - String with boundary
616  *              Format, ...         - Standard printf format
617  *
618  * RETURN:      Number of bytes actually written.
619  *
620  * DESCRIPTION: Formatted output to a string.
621  *
622  ******************************************************************************/
623 
sprintf(char * string,const char * format,...)624 int sprintf(char *string, const char *format, ...)
625 {
626 	va_list args;
627 	int length;
628 
629 	va_start(args, format);
630 	length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
631 	va_end(args);
632 
633 	return (length);
634 }
635 
636 #ifdef ACPI_APPLICATION
637 /*******************************************************************************
638  *
639  * FUNCTION:    vprintf
640  *
641  * PARAMETERS:  format              - Standard printf format
642  *              args                - Argument list
643  *
644  * RETURN:      Number of bytes actually written.
645  *
646  * DESCRIPTION: Formatted output to stdout using argument list pointer.
647  *
648  ******************************************************************************/
649 
vprintf(const char * format,va_list args)650 int vprintf(const char *format, va_list args)
651 {
652 	acpi_cpu_flags flags;
653 	int length;
654 
655 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
656 	length = vsnprintf(acpi_gbl_print_buffer,
657 			   sizeof(acpi_gbl_print_buffer), format, args);
658 
659 	(void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
660 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
661 
662 	return (length);
663 }
664 
665 /*******************************************************************************
666  *
667  * FUNCTION:    printf
668  *
669  * PARAMETERS:  Format, ...         - Standard printf format
670  *
671  * RETURN:      Number of bytes actually written.
672  *
673  * DESCRIPTION: Formatted output to stdout.
674  *
675  ******************************************************************************/
676 
printf(const char * format,...)677 int printf(const char *format, ...)
678 {
679 	va_list args;
680 	int length;
681 
682 	va_start(args, format);
683 	length = vprintf(format, args);
684 	va_end(args);
685 
686 	return (length);
687 }
688 
689 /*******************************************************************************
690  *
691  * FUNCTION:    vfprintf
692  *
693  * PARAMETERS:  file                - File descriptor
694  *              format              - Standard printf format
695  *              args                - Argument list
696  *
697  * RETURN:      Number of bytes actually written.
698  *
699  * DESCRIPTION: Formatted output to a file using argument list pointer.
700  *
701  ******************************************************************************/
702 
vfprintf(FILE * file,const char * format,va_list args)703 int vfprintf(FILE * file, const char *format, va_list args)
704 {
705 	acpi_cpu_flags flags;
706 	int length;
707 
708 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
709 	length = vsnprintf(acpi_gbl_print_buffer,
710 			   sizeof(acpi_gbl_print_buffer), format, args);
711 
712 	(void)fwrite(acpi_gbl_print_buffer, length, 1, file);
713 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
714 
715 	return (length);
716 }
717 
718 /*******************************************************************************
719  *
720  * FUNCTION:    fprintf
721  *
722  * PARAMETERS:  file                - File descriptor
723  *              Format, ...         - Standard printf format
724  *
725  * RETURN:      Number of bytes actually written.
726  *
727  * DESCRIPTION: Formatted output to a file.
728  *
729  ******************************************************************************/
730 
fprintf(FILE * file,const char * format,...)731 int fprintf(FILE * file, const char *format, ...)
732 {
733 	va_list args;
734 	int length;
735 
736 	va_start(args, format);
737 	length = vfprintf(file, format, args);
738 	va_end(args);
739 
740 	return (length);
741 }
742 #endif
743