utprint.c revision 1.1.1.1.2.1 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.h"
45 #include "accommon.h"
46
47 #define _COMPONENT ACPI_UTILITIES
48 ACPI_MODULE_NAME ("utprint")
49
50
51 #define ACPI_FORMAT_SIGN 0x01
52 #define ACPI_FORMAT_SIGN_PLUS 0x02
53 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
54 #define ACPI_FORMAT_ZERO 0x08
55 #define ACPI_FORMAT_LEFT 0x10
56 #define ACPI_FORMAT_UPPER 0x20
57 #define ACPI_FORMAT_PREFIX 0x40
58
59
60 /* Local prototypes */
61
62 static ACPI_SIZE
63 AcpiUtBoundStringLength (
64 const char *String,
65 ACPI_SIZE Count);
66
67 static char *
68 AcpiUtBoundStringOutput (
69 char *String,
70 const char *End,
71 char c);
72
73 static char *
74 AcpiUtFormatNumber (
75 char *String,
76 char *End,
77 UINT64 Number,
78 UINT8 Base,
79 INT32 Width,
80 INT32 Precision,
81 UINT8 Type);
82
83 static char *
84 AcpiUtPutNumber (
85 char *String,
86 UINT64 Number,
87 UINT8 Base,
88 BOOLEAN Upper);
89
90
91 /* Module globals */
92
93 static const char AcpiGbl_LowerHexDigits[] = "0123456789abcdef";
94 static const char AcpiGbl_UpperHexDigits[] = "0123456789ABCDEF";
95
96
97 /*******************************************************************************
98 *
99 * FUNCTION: AcpiUtBoundStringLength
100 *
101 * PARAMETERS: String - String with boundary
102 * Count - Boundary of the string
103 *
104 * RETURN: Length of the string. Less than or equal to Count.
105 *
106 * DESCRIPTION: Calculate the length of a string with boundary.
107 *
108 ******************************************************************************/
109
110 static ACPI_SIZE
111 AcpiUtBoundStringLength (
112 const char *String,
113 ACPI_SIZE Count)
114 {
115 UINT32 Length = 0;
116
117
118 while (*String && Count)
119 {
120 Length++;
121 String++;
122 Count--;
123 }
124
125 return (Length);
126 }
127
128
129 /*******************************************************************************
130 *
131 * FUNCTION: AcpiUtBoundStringOutput
132 *
133 * PARAMETERS: String - String with boundary
134 * End - Boundary of the string
135 * c - Character to be output to the string
136 *
137 * RETURN: Updated position for next valid character
138 *
139 * DESCRIPTION: Output a character into a string with boundary check.
140 *
141 ******************************************************************************/
142
143 static char *
144 AcpiUtBoundStringOutput (
145 char *String,
146 const char *End,
147 char c)
148 {
149
150 if (String < End)
151 {
152 *String = c;
153 }
154
155 ++String;
156 return (String);
157 }
158
159
160 /*******************************************************************************
161 *
162 * FUNCTION: AcpiUtPutNumber
163 *
164 * PARAMETERS: String - Buffer to hold reverse-ordered string
165 * Number - Integer to be converted
166 * Base - Base of the integer
167 * Upper - Whether or not using upper cased digits
168 *
169 * RETURN: Updated position for next valid character
170 *
171 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
172 * reversed ordered number without the trailing zero.
173 *
174 ******************************************************************************/
175
176 static char *
177 AcpiUtPutNumber (
178 char *String,
179 UINT64 Number,
180 UINT8 Base,
181 BOOLEAN Upper)
182 {
183 const char *Digits;
184 UINT64 DigitIndex;
185 char *Pos;
186
187
188 Pos = String;
189 Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits;
190
191 if (Number == 0)
192 {
193 *(Pos++) = '0';
194 }
195 else
196 {
197 while (Number)
198 {
199 (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex);
200 *(Pos++) = Digits[DigitIndex];
201 }
202 }
203
204 /* *(Pos++) = '0'; */
205 return (Pos);
206 }
207
208
209 /*******************************************************************************
210 *
211 * FUNCTION: AcpiUtScanNumber
212 *
213 * PARAMETERS: String - String buffer
214 * NumberPtr - Where the number is returned
215 *
216 * RETURN: Updated position for next valid character
217 *
218 * DESCRIPTION: Scan a string for a decimal integer.
219 *
220 ******************************************************************************/
221
222 const char *
223 AcpiUtScanNumber (
224 const char *String,
225 UINT64 *NumberPtr)
226 {
227 UINT64 Number = 0;
228
229
230 while (ACPI_IS_DIGIT (*String))
231 {
232 Number *= 10;
233 Number += *(String++) - '0';
234 }
235
236 *NumberPtr = Number;
237 return (String);
238 }
239
240
241 /*******************************************************************************
242 *
243 * FUNCTION: AcpiUtPrintNumber
244 *
245 * PARAMETERS: String - String buffer
246 * Number - The number to be converted
247 *
248 * RETURN: Updated position for next valid character
249 *
250 * DESCRIPTION: Print a decimal integer into a string.
251 *
252 ******************************************************************************/
253
254 const char *
255 AcpiUtPrintNumber (
256 char *String,
257 UINT64 Number)
258 {
259 char AsciiString[20];
260 const char *Pos1;
261 char *Pos2;
262
263
264 Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE);
265 Pos2 = String;
266
267 while (Pos1 != AsciiString)
268 {
269 *(Pos2++) = *(--Pos1);
270 }
271
272 *Pos2 = 0;
273 return (String);
274 }
275
276
277 /*******************************************************************************
278 *
279 * FUNCTION: AcpiUtFormatNumber
280 *
281 * PARAMETERS: String - String buffer with boundary
282 * End - Boundary of the string
283 * Number - The number to be converted
284 * Base - Base of the integer
285 * Width - Field width
286 * Precision - Precision of the integer
287 * Type - Special printing flags
288 *
289 * RETURN: Updated position for next valid character
290 *
291 * DESCRIPTION: Print an integer into a string with any base and any precision.
292 *
293 ******************************************************************************/
294
295 static char *
296 AcpiUtFormatNumber (
297 char *String,
298 char *End,
299 UINT64 Number,
300 UINT8 Base,
301 INT32 Width,
302 INT32 Precision,
303 UINT8 Type)
304 {
305 char *Pos;
306 char Sign;
307 char Zero;
308 BOOLEAN NeedPrefix;
309 BOOLEAN Upper;
310 INT32 i;
311 char ReversedString[66];
312
313
314 /* Parameter validation */
315
316 if (Base < 2 || Base > 16)
317 {
318 return (NULL);
319 }
320
321 if (Type & ACPI_FORMAT_LEFT)
322 {
323 Type &= ~ACPI_FORMAT_ZERO;
324 }
325
326 NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE;
327 Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
328 Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' ';
329
330 /* Calculate size according to sign and prefix */
331
332 Sign = '\0';
333 if (Type & ACPI_FORMAT_SIGN)
334 {
335 if ((INT64) Number < 0)
336 {
337 Sign = '-';
338 Number = - (INT64) Number;
339 Width--;
340 }
341 else if (Type & ACPI_FORMAT_SIGN_PLUS)
342 {
343 Sign = '+';
344 Width--;
345 }
346 else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE)
347 {
348 Sign = ' ';
349 Width--;
350 }
351 }
352 if (NeedPrefix)
353 {
354 Width--;
355 if (Base == 16)
356 {
357 Width--;
358 }
359 }
360
361 /* Generate full string in reverse order */
362
363 Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper);
364 i = ACPI_PTR_DIFF (Pos, ReversedString);
365
366 /* Printing 100 using %2d gives "100", not "00" */
367
368 if (i > Precision)
369 {
370 Precision = i;
371 }
372
373 Width -= Precision;
374
375 /* Output the string */
376
377 if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT)))
378 {
379 while (--Width >= 0)
380 {
381 String = AcpiUtBoundStringOutput (String, End, ' ');
382 }
383 }
384 if (Sign)
385 {
386 String = AcpiUtBoundStringOutput (String, End, Sign);
387 }
388 if (NeedPrefix)
389 {
390 String = AcpiUtBoundStringOutput (String, End, '0');
391 if (Base == 16)
392 {
393 String = AcpiUtBoundStringOutput (String, End,
394 Upper ? 'X' : 'x');
395 }
396 }
397 if (!(Type & ACPI_FORMAT_LEFT))
398 {
399 while (--Width >= 0)
400 {
401 String = AcpiUtBoundStringOutput (String, End, Zero);
402 }
403 }
404
405 while (i <= --Precision)
406 {
407 String = AcpiUtBoundStringOutput (String, End, '0');
408 }
409 while (--i >= 0)
410 {
411 String = AcpiUtBoundStringOutput (String, End,
412 ReversedString[i]);
413 }
414 while (--Width >= 0)
415 {
416 String = AcpiUtBoundStringOutput (String, End, ' ');
417 }
418
419 return (String);
420 }
421
422
423 /*******************************************************************************
424 *
425 * FUNCTION: AcpiUtVsnprintf
426 *
427 * PARAMETERS: String - String with boundary
428 * Size - Boundary of the string
429 * Format - Standard printf format
430 * Args - Argument list
431 *
432 * RETURN: Number of bytes actually written.
433 *
434 * DESCRIPTION: Formatted output to a string using argument list pointer.
435 *
436 ******************************************************************************/
437
438 int
439 AcpiUtVsnprintf (
440 char *String,
441 ACPI_SIZE Size,
442 const char *Format,
443 va_list Args)
444 {
445 UINT8 Base;
446 UINT8 Type;
447 INT32 Width;
448 INT32 Precision;
449 char Qualifier;
450 UINT64 Number;
451 char *Pos;
452 char *End;
453 char c;
454 const char *s;
455 const void *p;
456 INT32 Length;
457 int i;
458
459
460 Pos = String;
461 End = String + Size;
462
463 for (; *Format; ++Format)
464 {
465 if (*Format != '%')
466 {
467 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
468 continue;
469 }
470
471 Type = 0;
472 Base = 10;
473
474 /* Process sign */
475
476 do
477 {
478 ++Format;
479 if (*Format == '#')
480 {
481 Type |= ACPI_FORMAT_PREFIX;
482 }
483 else if (*Format == '0')
484 {
485 Type |= ACPI_FORMAT_ZERO;
486 }
487 else if (*Format == '+')
488 {
489 Type |= ACPI_FORMAT_SIGN_PLUS;
490 }
491 else if (*Format == ' ')
492 {
493 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
494 }
495 else if (*Format == '-')
496 {
497 Type |= ACPI_FORMAT_LEFT;
498 }
499 else
500 {
501 break;
502 }
503 } while (1);
504
505 /* Process width */
506
507 Width = -1;
508 if (ACPI_IS_DIGIT (*Format))
509 {
510 Format = AcpiUtScanNumber (Format, &Number);
511 Width = (INT32) Number;
512 }
513 else if (*Format == '*')
514 {
515 ++Format;
516 Width = va_arg (Args, int);
517 if (Width < 0)
518 {
519 Width = -Width;
520 Type |= ACPI_FORMAT_LEFT;
521 }
522 }
523
524 /* Process precision */
525
526 Precision = -1;
527 if (*Format == '.')
528 {
529 ++Format;
530 if (ACPI_IS_DIGIT(*Format))
531 {
532 Format = AcpiUtScanNumber (Format, &Number);
533 Precision = (INT32) Number;
534 }
535 else if (*Format == '*')
536 {
537 ++Format;
538 Precision = va_arg (Args, int);
539 }
540 if (Precision < 0)
541 {
542 Precision = 0;
543 }
544 }
545
546 /* Process qualifier */
547
548 Qualifier = -1;
549 if (*Format == 'h' || *Format == 'l' || *Format == 'L')
550 {
551 Qualifier = *Format;
552 ++Format;
553
554 if (Qualifier == 'l' && *Format == 'l')
555 {
556 Qualifier = 'L';
557 ++Format;
558 }
559 }
560
561 switch (*Format)
562 {
563 case '%':
564
565 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
566 continue;
567
568 case 'c':
569
570 if (!(Type & ACPI_FORMAT_LEFT))
571 {
572 while (--Width > 0)
573 {
574 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
575 }
576 }
577
578 c = (char) va_arg (Args, int);
579 Pos = AcpiUtBoundStringOutput (Pos, End, c);
580
581 while (--Width > 0)
582 {
583 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
584 }
585 continue;
586
587 case 's':
588
589 s = va_arg (Args, char *);
590 if (!s)
591 {
592 s = "<NULL>";
593 }
594 Length = AcpiUtBoundStringLength (s, Precision);
595 if (!(Type & ACPI_FORMAT_LEFT))
596 {
597 while (Length < Width--)
598 {
599 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
600 }
601 }
602 for (i = 0; i < Length; ++i)
603 {
604 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
605 ++s;
606 }
607 while (Length < Width--)
608 {
609 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
610 }
611 continue;
612
613 case 'o':
614
615 Base = 8;
616 break;
617
618 case 'X':
619
620 Type |= ACPI_FORMAT_UPPER;
621
622 case 'x':
623
624 Base = 16;
625 break;
626
627 case 'd':
628 case 'i':
629
630 Type |= ACPI_FORMAT_SIGN;
631
632 case 'u':
633
634 break;
635
636 case 'p':
637
638 if (Width == -1)
639 {
640 Width = 2 * sizeof (void *);
641 Type |= ACPI_FORMAT_ZERO;
642 }
643
644 p = va_arg (Args, void *);
645 Pos = AcpiUtFormatNumber (Pos, End,
646 ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
647 continue;
648
649 default:
650
651 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
652 if (*Format)
653 {
654 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
655 }
656 else
657 {
658 --Format;
659 }
660 continue;
661 }
662
663 if (Qualifier == 'L')
664 {
665 Number = va_arg (Args, UINT64);
666 if (Type & ACPI_FORMAT_SIGN)
667 {
668 Number = (INT64) Number;
669 }
670 }
671 else if (Qualifier == 'l')
672 {
673 Number = va_arg (Args, unsigned long);
674 if (Type & ACPI_FORMAT_SIGN)
675 {
676 Number = (INT32) Number;
677 }
678 }
679 else if (Qualifier == 'h')
680 {
681 Number = (UINT16) va_arg (Args, int);
682 if (Type & ACPI_FORMAT_SIGN)
683 {
684 Number = (INT16) Number;
685 }
686 }
687 else
688 {
689 Number = va_arg (Args, unsigned int);
690 if (Type & ACPI_FORMAT_SIGN)
691 {
692 Number = (signed int) Number;
693 }
694 }
695
696 Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
697 Width, Precision, Type);
698 }
699
700 if (Size > 0)
701 {
702 if (Pos < End)
703 {
704 *Pos = '\0';
705 }
706 else
707 {
708 End[-1] = '\0';
709 }
710 }
711
712 return (ACPI_PTR_DIFF (Pos, String));
713 }
714
715
716 /*******************************************************************************
717 *
718 * FUNCTION: AcpiUtSnprintf
719 *
720 * PARAMETERS: String - String with boundary
721 * Size - Boundary of the string
722 * Format, ... - Standard printf format
723 *
724 * RETURN: Number of bytes actually written.
725 *
726 * DESCRIPTION: Formatted output to a string.
727 *
728 ******************************************************************************/
729
730 int
731 AcpiUtSnprintf (
732 char *String,
733 ACPI_SIZE Size,
734 const char *Format,
735 ...)
736 {
737 va_list Args;
738 int Length;
739
740
741 va_start (Args, Format);
742 Length = AcpiUtVsnprintf (String, Size, Format, Args);
743 va_end (Args);
744
745 return (Length);
746 }
747
748
749 #ifdef ACPI_APPLICATION
750 /*******************************************************************************
751 *
752 * FUNCTION: AcpiUtFileVprintf
753 *
754 * PARAMETERS: File - File descriptor
755 * Format - Standard printf format
756 * Args - Argument list
757 *
758 * RETURN: Number of bytes actually written.
759 *
760 * DESCRIPTION: Formatted output to a file using argument list pointer.
761 *
762 ******************************************************************************/
763
764 int
765 AcpiUtFileVprintf (
766 ACPI_FILE File,
767 const char *Format,
768 va_list Args)
769 {
770 ACPI_CPU_FLAGS Flags;
771 int Length;
772
773
774 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
775 Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer,
776 sizeof (AcpiGbl_PrintBuffer), Format, Args);
777
778 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1);
779 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
780
781 return (Length);
782 }
783
784
785 /*******************************************************************************
786 *
787 * FUNCTION: AcpiUtFilePrintf
788 *
789 * PARAMETERS: File - File descriptor
790 * Format, ... - Standard printf format
791 *
792 * RETURN: Number of bytes actually written.
793 *
794 * DESCRIPTION: Formatted output to a file.
795 *
796 ******************************************************************************/
797
798 int
799 AcpiUtFilePrintf (
800 ACPI_FILE File,
801 const char *Format,
802 ...)
803 {
804 va_list Args;
805 int Length;
806
807
808 va_start (Args, Format);
809 Length = AcpiUtFileVprintf (File, Format, Args);
810 va_end (Args);
811
812 return (Length);
813 }
814 #endif
815