blob: 9d5293fd992f660805a0ba47bfba516be00571d1 [file] [log] [blame]
Lv Zheng80a648c2014-07-08 10:07:00 +08001/******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2014, 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/*******************************************************************************
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.
78 *
79 * DESCRIPTION: Calculate the length of a string with boundary.
80 *
81 ******************************************************************************/
82
83static acpi_size
84acpi_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
111static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
112{
113
114 if (string < end) {
115 *string = c;
116 }
117 ++string;
118
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
138static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
139{
140 const char lower_digits[] = "0123456789abcdef";
141 const char upper_digits[] = "0123456789ABCDEF";
142 const char *digits;
143 u64 digit_index;
144 char *pos;
145
146 pos = string;
147 digits = upper ? upper_digits : lower_digits;
148
149 if (number == 0) {
150 *(pos++) = '0';
151 } else {
152 while (number) {
153 (void)acpi_ut_divide(number, base, &number,
154 &digit_index);
155 *(pos++) = digits[digit_index];
156 }
157 }
158 /* *(Pos++) = '0'; */
159
160 return (pos);
161}
162
163/*******************************************************************************
164 *
165 * FUNCTION: acpi_ut_scan_number
166 *
167 * PARAMETERS: string - String buffer
168 * number_ptr - Where the number is returned
169 *
170 * RETURN: Updated position for next valid character
171 *
172 * DESCRIPTION: Scan a string for a decimal integer.
173 *
174 ******************************************************************************/
175
176const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
177{
178 u64 number = 0;
179
180 while (ACPI_IS_DIGIT(*string)) {
181 number *= 10;
182 number += *(string++) - '0';
183 }
184 *number_ptr = number;
185
186 return (string);
187}
188
189/*******************************************************************************
190 *
191 * FUNCTION: acpi_ut_print_number
192 *
193 * PARAMETERS: string - String buffer
194 * number - The number to be converted
195 *
196 * RETURN: Updated position for next valid character
197 *
198 * DESCRIPTION: Print a decimal integer into a string.
199 *
200 ******************************************************************************/
201
202const char *acpi_ut_print_number(char *string, u64 number)
203{
204 char ascii_string[20];
205 const char *pos1;
206 char *pos2;
207
208 pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
209 pos2 = string;
210
211 while (pos1 != ascii_string) {
212 *(pos2++) = *(--pos1);
213 }
214 *pos2 = 0;
215
216 return (string);
217}
218
219/*******************************************************************************
220 *
221 * FUNCTION: acpi_ut_format_number
222 *
223 * PARAMETERS: string - String buffer with boundary
224 * end - Boundary of the string
225 * number - The number to be converted
226 * base - Base of the integer
227 * width - Field width
228 * precision - Precision of the integer
229 * type - Special printing flags
230 *
231 * RETURN: Updated position for next valid character
232 *
233 * DESCRIPTION: Print an integer into a string with any base and any precision.
234 *
235 ******************************************************************************/
236
237static char *acpi_ut_format_number(char *string,
238 char *end,
239 u64 number,
240 u8 base, s32 width, s32 precision, u8 type)
241{
242 char sign;
243 char zero;
244 u8 need_prefix;
245 u8 upper;
246 s32 i;
247 char reversed_string[66];
248
249 /* Perform sanity checks */
250
251 if (base < 2 || base > 16) {
252 return NULL;
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 i = ACPI_PTR_DIFF(acpi_ut_put_number
289 (reversed_string, number, base, upper),
290 reversed_string);
291
292 /* Printing 100 using %2d gives "100", not "00" */
293
294 if (i > precision) {
295 precision = i;
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 = acpi_ut_bound_string_output(string, end,
313 upper ? 'X' : 'x');
314 }
315 }
316 if (!(type & ACPI_FORMAT_LEFT)) {
317 while (--width >= 0) {
318 string = acpi_ut_bound_string_output(string, end, zero);
319 }
320 }
321 while (i <= --precision) {
322 string = acpi_ut_bound_string_output(string, end, '0');
323 }
324 while (--i >= 0) {
325 string = acpi_ut_bound_string_output(string, end,
326 reversed_string[i]);
327 }
328 while (--width >= 0) {
329 string = acpi_ut_bound_string_output(string, end, ' ');
330 }
331
332 return (string);
333}
334
335/*******************************************************************************
336 *
337 * FUNCTION: acpi_ut_vsnprintf
338 *
339 * PARAMETERS: string - String with boundary
340 * size - Boundary of the string
341 * format - Standard printf format
342 * args - Argument list
343 *
344 * RETURN: Size of successfully output bytes
345 *
346 * DESCRIPTION: Formatted output to a string using argument list pointer.
347 *
348 ******************************************************************************/
349
350int
351acpi_ut_vsnprintf(char *string,
352 acpi_size size, const char *format, va_list args)
353{
354 u8 base = 10;
355 u8 type = 0;
356 s32 width = -1;
357 s32 precision = -1;
358 char qualifier = 0;
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 /* Process sign */
378
379 do {
380 ++format;
381 if (*format == '#') {
382 type |= ACPI_FORMAT_PREFIX;
383 } else if (*format == '0') {
384 type |= ACPI_FORMAT_ZERO;
385 } else if (*format == '+') {
386 type |= ACPI_FORMAT_SIGN_PLUS;
387 } else if (*format == ' ') {
388 type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
389 } else if (*format == '-') {
390 type |= ACPI_FORMAT_LEFT;
391 } else {
392 break;
393 }
394 } while (1);
395
396 /* Process width */
397
398 if (ACPI_IS_DIGIT(*format)) {
399 format = acpi_ut_scan_number(format, &number);
400 width = (s32) number;
401 } else if (*format == '*') {
402 ++format;
403 width = va_arg(args, int);
404 if (width < 0) {
405 width = -width;
406 type |= ACPI_FORMAT_LEFT;
407 }
408 }
409
410 /* Process precision */
411
412 if (*format == '.') {
413 ++format;
414 if (ACPI_IS_DIGIT(*format)) {
415 format = acpi_ut_scan_number(format, &number);
416 precision = (s32) number;
417 } else if (*format == '*') {
418 ++format;
419 precision = va_arg(args, int);
420 }
421 if (precision < 0) {
422 precision = 0;
423 }
424 }
425
426 /* Process qualifier */
427
428 if (*format == 'h' || *format == 'l' || *format == 'L') {
429 qualifier = *format;
430 ++format;
431 if (qualifier == 'l' && *format == 'l') {
432 qualifier = 'L';
433 ++format;
434 }
435 }
436
437 switch (*format) {
438 case '%':
439
440 pos = acpi_ut_bound_string_output(pos, end, '%');
441 continue;
442
443 case 'c':
444
445 if (!(type & ACPI_FORMAT_LEFT)) {
446 while (--width > 0) {
447 pos =
448 acpi_ut_bound_string_output(pos,
449 end,
450 ' ');
451 }
452 }
453 c = (char)va_arg(args, int);
454 pos = acpi_ut_bound_string_output(pos, end, c);
455 while (--width > 0) {
456 pos =
457 acpi_ut_bound_string_output(pos, end, ' ');
458 }
459 continue;
460
461 case 's':
462
463 s = va_arg(args, char *);
464 if (!s) {
465 s = "<NULL>";
466 }
467 length = acpi_ut_bound_string_length(s, precision);
468 if (!(type & ACPI_FORMAT_LEFT)) {
469 while (length < width--) {
470 pos =
471 acpi_ut_bound_string_output(pos,
472 end,
473 ' ');
474 }
475 }
476 for (i = 0; i < length; ++i) {
477 pos = acpi_ut_bound_string_output(pos, end, *s);
478 ++s;
479 }
480 while (length < width--) {
481 pos =
482 acpi_ut_bound_string_output(pos, end, ' ');
483 }
484 continue;
485
486 case 'o':
487
488 base = 8;
489 break;
490
491 case 'X':
492
493 type |= ACPI_FORMAT_UPPER;
494
495 case 'x':
496
497 base = 16;
498 break;
499
500 case 'd':
501 case 'i':
502
503 type |= ACPI_FORMAT_SIGN;
504
505 case 'u':
506
507 break;
508
509 case 'p':
510
511 if (width == -1) {
512 width = 2 * sizeof(void *);
513 type |= ACPI_FORMAT_ZERO;
514 }
515 p = va_arg(args, void *);
516 pos = acpi_ut_format_number(pos, end,
517 ACPI_TO_INTEGER(p),
518 16, width, precision, type);
519 continue;
520
521 default:
522
523 pos = acpi_ut_bound_string_output(pos, end, '%');
524 if (*format) {
525 pos =
526 acpi_ut_bound_string_output(pos, end,
527 *format);
528 } else {
529 --format;
530 }
531 continue;
532 }
533
534 if (qualifier == 'L') {
535 number = va_arg(args, u64);
536 if (type & ACPI_FORMAT_SIGN) {
537 number = (s64) number;
538 }
539 } else if (qualifier == 'l') {
540 number = va_arg(args, unsigned long);
541 if (type & ACPI_FORMAT_SIGN) {
542 number = (s32) number;
543 }
544 } else if (qualifier == 'h') {
545 number = (u16)va_arg(args, int);
546 if (type & ACPI_FORMAT_SIGN) {
547 number = (s16) number;
548 }
549 } else {
550 number = va_arg(args, unsigned int);
551 if (type & ACPI_FORMAT_SIGN) {
552 number = (signed int)number;
553 }
554 }
555 pos = acpi_ut_format_number(pos, end, number, base,
556 width, precision, type);
557 }
558
559 if (size > 0) {
560 if (pos < end) {
561 *pos = '\0';
562 } else {
563 end[-1] = '\0';
564 }
565 }
566
567 return (ACPI_PTR_DIFF(pos, string));
568}
569
570/*******************************************************************************
571 *
572 * FUNCTION: acpi_ut_snprintf
573 *
574 * PARAMETERS: string - String with boundary
575 * size - Boundary of the string
576 * Format, ... - Standard printf format
577 *
578 * RETURN: Size of successfully output bytes
579 *
580 * DESCRIPTION: Formatted output to a string.
581 *
582 ******************************************************************************/
583
584int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
585{
586 va_list args;
587 int length;
588
589 va_start(args, format);
590 length = acpi_ut_vsnprintf(string, size, format, args);
591 va_end(args);
592
593 return (length);
594}
595
596#ifdef ACPI_APPLICATION
597/*******************************************************************************
598 *
599 * FUNCTION: acpi_ut_file_vprintf
600 *
601 * PARAMETERS: file - File descriptor
602 * format - Standard printf format
603 * args - Argument list
604 *
605 * RETURN: Size of successfully output bytes
606 *
607 * DESCRIPTION: Formatted output to a file using argument list pointer.
608 *
609 ******************************************************************************/
610
611int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
612{
613 acpi_cpu_flags flags;
614 int length;
615
616 flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
617 length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
618 sizeof(acpi_gbl_print_buffer), format, args);
619 (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
620 acpi_os_release_lock(acpi_gbl_print_lock, flags);
621
622 return (length);
623}
624
625/*******************************************************************************
626 *
627 * FUNCTION: acpi_ut_file_printf
628 *
629 * PARAMETERS: file - File descriptor
630 * Format, ... - Standard printf format
631 *
632 * RETURN: Size of successfully output bytes
633 *
634 * DESCRIPTION: Formatted output to a file.
635 *
636 ******************************************************************************/
637
638int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
639{
640 va_list args;
641 int length;
642
643 va_start(args, format);
644 length = acpi_ut_file_vprintf(file, format, args);
645 va_end(args);
646
647 return (length);
648}
649#endif