blob: 8c218ad787cdf57daa6fc2711cdfb7568ace70da [file] [log] [blame]
Lv Zheng80a648c2014-07-08 10:07:00 +08001/******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing routines
4 *
5 *****************************************************************************/
6
7/*
Bob Moorec8100dc2016-01-15 08:17:03 +08008 * Copyright (C) 2000 - 2016, Intel Corp.
Lv Zheng80a648c2014-07-08 10:07:00 +08009 * 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
Bob Mooreff2389f2014-07-08 10:08:13 +080070/* Module globals */
71
72static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
73static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
74
Lv Zheng80a648c2014-07-08 10:07:00 +080075/*******************************************************************************
76 *
77 * FUNCTION: acpi_ut_bound_string_length
78 *
79 * PARAMETERS: string - String with boundary
80 * count - Boundary of the string
81 *
Bob Mooreff2389f2014-07-08 10:08:13 +080082 * RETURN: Length of the string. Less than or equal to Count.
Lv Zheng80a648c2014-07-08 10:07:00 +080083 *
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 }
Lv Zheng80a648c2014-07-08 10:07:00 +0800122
Bob Mooreff2389f2014-07-08 10:08:13 +0800123 ++string;
Lv Zheng80a648c2014-07-08 10:07:00 +0800124 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{
Lv Zheng80a648c2014-07-08 10:07:00 +0800145 const char *digits;
146 u64 digit_index;
147 char *pos;
148
149 pos = string;
Bob Mooreff2389f2014-07-08 10:08:13 +0800150 digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
Lv Zheng80a648c2014-07-08 10:07:00 +0800151
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 }
Lv Zheng80a648c2014-07-08 10:07:00 +0800161
Bob Mooreff2389f2014-07-08 10:08:13 +0800162 /* *(Pos++) = '0'; */
Lv Zheng80a648c2014-07-08 10:07:00 +0800163 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
Bob Moore4fa46162015-07-01 14:45:11 +0800183 while (isdigit((int)*string)) {
Lv Zheng80a648c2014-07-08 10:07:00 +0800184 number *= 10;
185 number += *(string++) - '0';
186 }
Lv Zheng80a648c2014-07-08 10:07:00 +0800187
Bob Mooreff2389f2014-07-08 10:08:13 +0800188 *number_ptr = number;
Lv Zheng80a648c2014-07-08 10:07:00 +0800189 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 }
Lv Zheng80a648c2014-07-08 10:07:00 +0800217
Bob Mooreff2389f2014-07-08 10:08:13 +0800218 *pos2 = 0;
Lv Zheng80a648c2014-07-08 10:07:00 +0800219 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{
Bob Moore8884de62014-07-30 12:20:26 +0800245 char *pos;
Lv Zheng80a648c2014-07-08 10:07:00 +0800246 char sign;
247 char zero;
248 u8 need_prefix;
249 u8 upper;
250 s32 i;
251 char reversed_string[66];
252
Bob Mooreff2389f2014-07-08 10:08:13 +0800253 /* Parameter validation */
Lv Zheng80a648c2014-07-08 10:07:00 +0800254
255 if (base < 2 || base > 16) {
Bob Mooreff2389f2014-07-08 10:08:13 +0800256 return (NULL);
Lv Zheng80a648c2014-07-08 10:07:00 +0800257 }
Bob Mooreff2389f2014-07-08 10:08:13 +0800258
Lv Zheng80a648c2014-07-08 10:07:00 +0800259 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
Bob Moore8884de62014-07-30 12:20:26 +0800293 pos = acpi_ut_put_number(reversed_string, number, base, upper);
294 i = ACPI_PTR_DIFF(pos, reversed_string);
Lv Zheng80a648c2014-07-08 10:07:00 +0800295
296 /* Printing 100 using %2d gives "100", not "00" */
297
298 if (i > precision) {
299 precision = i;
300 }
Bob Mooreff2389f2014-07-08 10:08:13 +0800301
Lv Zheng80a648c2014-07-08 10:07:00 +0800302 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) {
Bob Moore1fad8732015-12-29 13:54:36 +0800317 string =
318 acpi_ut_bound_string_output(string, end,
319 upper ? 'X' : 'x');
Lv Zheng80a648c2014-07-08 10:07:00 +0800320 }
321 }
322 if (!(type & ACPI_FORMAT_LEFT)) {
323 while (--width >= 0) {
324 string = acpi_ut_bound_string_output(string, end, zero);
325 }
326 }
Bob Mooreff2389f2014-07-08 10:08:13 +0800327
Lv Zheng80a648c2014-07-08 10:07:00 +0800328 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 *
Bob Mooreff2389f2014-07-08 10:08:13 +0800351 * RETURN: Number of bytes actually written.
Lv Zheng80a648c2014-07-08 10:07:00 +0800352 *
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{
Lv Zhengcef9aaa2015-04-13 11:51:23 +0800361 u8 base;
362 u8 type;
363 s32 width;
364 s32 precision;
365 char qualifier;
Lv Zheng80a648c2014-07-08 10:07:00 +0800366 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
Lv Zhengcef9aaa2015-04-13 11:51:23 +0800384 type = 0;
385 base = 10;
386
Lv Zheng80a648c2014-07-08 10:07:00 +0800387 /* 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 }
Bob Moore1fad8732015-12-29 13:54:36 +0800404
Lv Zheng80a648c2014-07-08 10:07:00 +0800405 } while (1);
406
407 /* Process width */
408
Lv Zheng3589b8b2014-07-30 12:21:07 +0800409 width = -1;
Bob Moore4fa46162015-07-01 14:45:11 +0800410 if (isdigit((int)*format)) {
Lv Zheng80a648c2014-07-08 10:07:00 +0800411 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
Lv Zheng3589b8b2014-07-30 12:21:07 +0800424 precision = -1;
Lv Zheng80a648c2014-07-08 10:07:00 +0800425 if (*format == '.') {
426 ++format;
Bob Moore4fa46162015-07-01 14:45:11 +0800427 if (isdigit((int)*format)) {
Lv Zheng80a648c2014-07-08 10:07:00 +0800428 format = acpi_ut_scan_number(format, &number);
429 precision = (s32) number;
430 } else if (*format == '*') {
431 ++format;
432 precision = va_arg(args, int);
433 }
Bob Moore1fad8732015-12-29 13:54:36 +0800434
Lv Zheng80a648c2014-07-08 10:07:00 +0800435 if (precision < 0) {
436 precision = 0;
437 }
438 }
439
440 /* Process qualifier */
441
Lv Zheng3589b8b2014-07-30 12:21:07 +0800442 qualifier = -1;
Lv Zheng80a648c2014-07-08 10:07:00 +0800443 if (*format == 'h' || *format == 'l' || *format == 'L') {
444 qualifier = *format;
445 ++format;
Bob Mooreff2389f2014-07-08 10:08:13 +0800446
Lv Zheng80a648c2014-07-08 10:07:00 +0800447 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 }
Bob Mooreff2389f2014-07-08 10:08:13 +0800469
Lv Zheng80a648c2014-07-08 10:07:00 +0800470 c = (char)va_arg(args, int);
471 pos = acpi_ut_bound_string_output(pos, end, c);
Bob Mooreff2389f2014-07-08 10:08:13 +0800472
Lv Zheng80a648c2014-07-08 10:07:00 +0800473 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 }
Bob Moore1fad8732015-12-29 13:54:36 +0800494
Lv Zheng80a648c2014-07-08 10:07:00 +0800495 for (i = 0; i < length; ++i) {
496 pos = acpi_ut_bound_string_output(pos, end, *s);
497 ++s;
498 }
Bob Moore1fad8732015-12-29 13:54:36 +0800499
Lv Zheng80a648c2014-07-08 10:07:00 +0800500 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 }
Bob Mooreff2389f2014-07-08 10:08:13 +0800535
Lv Zheng80a648c2014-07-08 10:07:00 +0800536 p = va_arg(args, void *);
Bob Moore1fad8732015-12-29 13:54:36 +0800537 pos =
538 acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
539 16, width, precision, type);
Lv Zheng80a648c2014-07-08 10:07:00 +0800540 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 }
Bob Mooreff2389f2014-07-08 10:08:13 +0800576
Lv Zheng80a648c2014-07-08 10:07:00 +0800577 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 *
Bob Mooreff2389f2014-07-08 10:08:13 +0800600 * RETURN: Number of bytes actually written.
Lv Zheng80a648c2014-07-08 10:07:00 +0800601 *
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 *
Bob Mooreff2389f2014-07-08 10:08:13 +0800627 * RETURN: Number of bytes actually written.
Lv Zheng80a648c2014-07-08 10:07:00 +0800628 *
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);
Bob Mooreff2389f2014-07-08 10:08:13 +0800641
Lv Zheng80a648c2014-07-08 10:07:00 +0800642 (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 *
Bob Mooreff2389f2014-07-08 10:08:13 +0800655 * RETURN: Number of bytes actually written.
Lv Zheng80a648c2014-07-08 10:07:00 +0800656 *
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