utprint.c revision 1.6.2.1 1 /******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing routines
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2019, 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 #include "acpi.h"
44 #include "accommon.h"
45
46 #define _COMPONENT ACPI_UTILITIES
47 ACPI_MODULE_NAME ("utprint")
48
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
58
59 /* Local prototypes */
60
61 static ACPI_SIZE
62 AcpiUtBoundStringLength (
63 const char *String,
64 ACPI_SIZE Count);
65
66 static char *
67 AcpiUtBoundStringOutput (
68 char *String,
69 const char *End,
70 char c);
71
72 static char *
73 AcpiUtFormatNumber (
74 char *String,
75 char *End,
76 UINT64 Number,
77 UINT8 Base,
78 INT32 Width,
79 INT32 Precision,
80 UINT8 Type);
81
82 static char *
83 AcpiUtPutNumber (
84 char *String,
85 UINT64 Number,
86 UINT8 Base,
87 BOOLEAN Upper);
88
89
90 /*******************************************************************************
91 *
92 * FUNCTION: AcpiUtBoundStringLength
93 *
94 * PARAMETERS: String - String with boundary
95 * Count - Boundary of the string
96 *
97 * RETURN: Length of the string. Less than or equal to Count.
98 *
99 * DESCRIPTION: Calculate the length of a string with boundary.
100 *
101 ******************************************************************************/
102
103 static ACPI_SIZE
104 AcpiUtBoundStringLength (
105 const char *String,
106 ACPI_SIZE Count)
107 {
108 UINT32 Length = 0;
109
110
111 while (*String && Count)
112 {
113 Length++;
114 String++;
115 Count--;
116 }
117
118 return (Length);
119 }
120
121
122 /*******************************************************************************
123 *
124 * FUNCTION: AcpiUtBoundStringOutput
125 *
126 * PARAMETERS: String - String with boundary
127 * End - Boundary of the string
128 * c - Character to be output to the string
129 *
130 * RETURN: Updated position for next valid character
131 *
132 * DESCRIPTION: Output a character into a string with boundary check.
133 *
134 ******************************************************************************/
135
136 static char *
137 AcpiUtBoundStringOutput (
138 char *String,
139 const char *End,
140 char c)
141 {
142
143 if (String < End)
144 {
145 *String = c;
146 }
147
148 ++String;
149 return (String);
150 }
151
152
153 /*******************************************************************************
154 *
155 * FUNCTION: AcpiUtPutNumber
156 *
157 * PARAMETERS: String - Buffer to hold reverse-ordered string
158 * Number - Integer to be converted
159 * Base - Base of the integer
160 * Upper - Whether or not using upper cased digits
161 *
162 * RETURN: Updated position for next valid character
163 *
164 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
165 * reversed ordered number without the trailing zero.
166 *
167 ******************************************************************************/
168
169 static char *
170 AcpiUtPutNumber (
171 char *String,
172 UINT64 Number,
173 UINT8 Base,
174 BOOLEAN Upper)
175 {
176 const char *Digits;
177 UINT64 DigitIndex;
178 char *Pos;
179
180
181 Pos = String;
182 Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits;
183
184 if (Number == 0)
185 {
186 *(Pos++) = '0';
187 }
188 else
189 {
190 while (Number)
191 {
192 (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex);
193 *(Pos++) = Digits[DigitIndex];
194 }
195 }
196
197 /* *(Pos++) = '0'; */
198 return (Pos);
199 }
200
201
202 /*******************************************************************************
203 *
204 * FUNCTION: AcpiUtScanNumber
205 *
206 * PARAMETERS: String - String buffer
207 * NumberPtr - Where the number is returned
208 *
209 * RETURN: Updated position for next valid character
210 *
211 * DESCRIPTION: Scan a string for a decimal integer.
212 *
213 ******************************************************************************/
214
215 const char *
216 AcpiUtScanNumber (
217 const char *String,
218 UINT64 *NumberPtr)
219 {
220 UINT64 Number = 0;
221
222
223 while (isdigit ((int) *String))
224 {
225 AcpiUtShortMultiply (Number, 10, &Number);
226 Number += *(String++) - '0';
227 }
228
229 *NumberPtr = Number;
230 return (String);
231 }
232
233
234 /*******************************************************************************
235 *
236 * FUNCTION: AcpiUtPrintNumber
237 *
238 * PARAMETERS: String - String buffer
239 * Number - The number to be converted
240 *
241 * RETURN: Updated position for next valid character
242 *
243 * DESCRIPTION: Print a decimal integer into a string.
244 *
245 ******************************************************************************/
246
247 const char *
248 AcpiUtPrintNumber (
249 char *String,
250 UINT64 Number)
251 {
252 char AsciiString[20];
253 const char *Pos1;
254 char *Pos2;
255
256
257 Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE);
258 Pos2 = String;
259
260 while (Pos1 != AsciiString)
261 {
262 *(Pos2++) = *(--Pos1);
263 }
264
265 *Pos2 = 0;
266 return (String);
267 }
268
269
270 /*******************************************************************************
271 *
272 * FUNCTION: AcpiUtFormatNumber
273 *
274 * PARAMETERS: String - String buffer with boundary
275 * End - Boundary of the string
276 * Number - The number to be converted
277 * Base - Base of the integer
278 * Width - Field width
279 * Precision - Precision of the integer
280 * Type - Special printing flags
281 *
282 * RETURN: Updated position for next valid character
283 *
284 * DESCRIPTION: Print an integer into a string with any base and any precision.
285 *
286 ******************************************************************************/
287
288 static char *
289 AcpiUtFormatNumber (
290 char *String,
291 char *End,
292 UINT64 Number,
293 UINT8 Base,
294 INT32 Width,
295 INT32 Precision,
296 UINT8 Type)
297 {
298 char *Pos;
299 char Sign;
300 char Zero;
301 BOOLEAN NeedPrefix;
302 BOOLEAN Upper;
303 INT32 i;
304 char ReversedString[66];
305
306
307 /* Parameter validation */
308
309 if (Base < 2 || Base > 16)
310 {
311 return (NULL);
312 }
313
314 if (Type & ACPI_FORMAT_LEFT)
315 {
316 Type &= ~ACPI_FORMAT_ZERO;
317 }
318
319 NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE;
320 Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
321 Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' ';
322
323 /* Calculate size according to sign and prefix */
324
325 Sign = '\0';
326 if (Type & ACPI_FORMAT_SIGN)
327 {
328 if ((INT64) Number < 0)
329 {
330 Sign = '-';
331 Number = - (INT64) Number;
332 Width--;
333 }
334 else if (Type & ACPI_FORMAT_SIGN_PLUS)
335 {
336 Sign = '+';
337 Width--;
338 }
339 else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE)
340 {
341 Sign = ' ';
342 Width--;
343 }
344 }
345 if (NeedPrefix)
346 {
347 Width--;
348 if (Base == 16)
349 {
350 Width--;
351 }
352 }
353
354 /* Generate full string in reverse order */
355
356 Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper);
357 i = (INT32) ACPI_PTR_DIFF (Pos, ReversedString);
358
359 /* Printing 100 using %2d gives "100", not "00" */
360
361 if (i > Precision)
362 {
363 Precision = i;
364 }
365
366 Width -= Precision;
367
368 /* Output the string */
369
370 if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT)))
371 {
372 while (--Width >= 0)
373 {
374 String = AcpiUtBoundStringOutput (String, End, ' ');
375 }
376 }
377 if (Sign)
378 {
379 String = AcpiUtBoundStringOutput (String, End, Sign);
380 }
381 if (NeedPrefix)
382 {
383 String = AcpiUtBoundStringOutput (String, End, '0');
384 if (Base == 16)
385 {
386 String = AcpiUtBoundStringOutput (
387 String, End, Upper ? 'X' : 'x');
388 }
389 }
390 if (!(Type & ACPI_FORMAT_LEFT))
391 {
392 while (--Width >= 0)
393 {
394 String = AcpiUtBoundStringOutput (String, End, Zero);
395 }
396 }
397
398 while (i <= --Precision)
399 {
400 String = AcpiUtBoundStringOutput (String, End, '0');
401 }
402 while (--i >= 0)
403 {
404 String = AcpiUtBoundStringOutput (String, End,
405 ReversedString[i]);
406 }
407 while (--Width >= 0)
408 {
409 String = AcpiUtBoundStringOutput (String, End, ' ');
410 }
411
412 return (String);
413 }
414
415 #undef sprintf
416 #undef snprintf
417 #undef vsnprintf
418 /*******************************************************************************
419 *
420 * FUNCTION: vsnprintf
421 *
422 * PARAMETERS: String - String with boundary
423 * Size - Boundary of the string
424 * Format - Standard printf format
425 * Args - Argument list
426 *
427 * RETURN: Number of bytes actually written.
428 *
429 * DESCRIPTION: Formatted output to a string using argument list pointer.
430 *
431 ******************************************************************************/
432
433 int
434 vsnprintf (
435 char *String,
436 ACPI_SIZE Size,
437 const char *Format,
438 va_list Args)
439 {
440 UINT8 Base;
441 UINT8 Type;
442 INT32 Width;
443 INT32 Precision;
444 char Qualifier;
445 UINT64 Number;
446 char *Pos;
447 char *End;
448 char c;
449 const char *s;
450 const void *p;
451 INT32 Length;
452 int i;
453
454
455 Pos = String;
456 End = String + Size;
457
458 for (; *Format; ++Format)
459 {
460 if (*Format != '%')
461 {
462 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
463 continue;
464 }
465
466 Type = 0;
467 Base = 10;
468
469 /* Process sign */
470
471 do
472 {
473 ++Format;
474 if (*Format == '#')
475 {
476 Type |= ACPI_FORMAT_PREFIX;
477 }
478 else if (*Format == '0')
479 {
480 Type |= ACPI_FORMAT_ZERO;
481 }
482 else if (*Format == '+')
483 {
484 Type |= ACPI_FORMAT_SIGN_PLUS;
485 }
486 else if (*Format == ' ')
487 {
488 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
489 }
490 else if (*Format == '-')
491 {
492 Type |= ACPI_FORMAT_LEFT;
493 }
494 else
495 {
496 break;
497 }
498
499 } while (1);
500
501 /* Process width */
502
503 Width = -1;
504 if (isdigit ((int) *Format))
505 {
506 Format = AcpiUtScanNumber (Format, &Number);
507 Width = (INT32) Number;
508 }
509 else if (*Format == '*')
510 {
511 ++Format;
512 Width = va_arg (Args, int);
513 if (Width < 0)
514 {
515 Width = -Width;
516 Type |= ACPI_FORMAT_LEFT;
517 }
518 }
519
520 /* Process precision */
521
522 Precision = -1;
523 if (*Format == '.')
524 {
525 ++Format;
526 if (isdigit ((int) *Format))
527 {
528 Format = AcpiUtScanNumber (Format, &Number);
529 Precision = (INT32) Number;
530 }
531 else if (*Format == '*')
532 {
533 ++Format;
534 Precision = va_arg (Args, int);
535 }
536
537 if (Precision < 0)
538 {
539 Precision = 0;
540 }
541 }
542
543 /* Process qualifier */
544
545 Qualifier = -1;
546 if (*Format == 'h' || *Format == 'l' || *Format == 'L')
547 {
548 Qualifier = *Format;
549 ++Format;
550
551 if (Qualifier == 'l' && *Format == 'l')
552 {
553 Qualifier = 'L';
554 ++Format;
555 }
556 }
557
558 switch (*Format)
559 {
560 case '%':
561
562 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
563 continue;
564
565 case 'c':
566
567 if (!(Type & ACPI_FORMAT_LEFT))
568 {
569 while (--Width > 0)
570 {
571 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
572 }
573 }
574
575 c = (char) va_arg (Args, int);
576 Pos = AcpiUtBoundStringOutput (Pos, End, c);
577
578 while (--Width > 0)
579 {
580 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
581 }
582 continue;
583
584 case 's':
585
586 s = va_arg (Args, char *);
587 if (!s)
588 {
589 s = "<NULL>";
590 }
591 Length = (INT32) AcpiUtBoundStringLength (s, Precision);
592 if (!(Type & ACPI_FORMAT_LEFT))
593 {
594 while (Length < Width--)
595 {
596 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
597 }
598 }
599
600 for (i = 0; i < Length; ++i)
601 {
602 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
603 ++s;
604 }
605
606 while (Length < Width--)
607 {
608 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
609 }
610 continue;
611
612 case 'o':
613
614 Base = 8;
615 break;
616
617 case 'X':
618
619 Type |= ACPI_FORMAT_UPPER;
620 /* FALLTHROUGH */
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 (
646 Pos, End, 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 ((int) ACPI_PTR_DIFF (Pos, String));
713 }
714
715
716 /*******************************************************************************
717 *
718 * FUNCTION: snprintf
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 snprintf (
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 = vsnprintf (String, Size, Format, Args);
743 va_end (Args);
744
745 return (Length);
746 }
747
748
749 /*******************************************************************************
750 *
751 * FUNCTION: sprintf
752 *
753 * PARAMETERS: String - String with boundary
754 * Format, ... - Standard printf format
755 *
756 * RETURN: Number of bytes actually written.
757 *
758 * DESCRIPTION: Formatted output to a string.
759 *
760 ******************************************************************************/
761
762 int
763 sprintf (
764 char *String,
765 const char *Format,
766 ...)
767 {
768 va_list Args;
769 int Length;
770
771
772 va_start (Args, Format);
773 Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args);
774 va_end (Args);
775
776 return (Length);
777 }
778
779
780 #ifdef ACPI_APPLICATION
781 /*******************************************************************************
782 *
783 * FUNCTION: vprintf
784 *
785 * PARAMETERS: Format - Standard printf format
786 * Args - Argument list
787 *
788 * RETURN: Number of bytes actually written.
789 *
790 * DESCRIPTION: Formatted output to stdout using argument list pointer.
791 *
792 ******************************************************************************/
793
794 int
795 vprintf (
796 const char *Format,
797 va_list Args)
798 {
799 ACPI_CPU_FLAGS Flags;
800 int Length;
801
802
803 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
804 Length = vsnprintf (AcpiGbl_PrintBuffer,
805 sizeof (AcpiGbl_PrintBuffer), Format, Args);
806
807 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT);
808 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
809
810 return (Length);
811 }
812
813
814 /*******************************************************************************
815 *
816 * FUNCTION: printf
817 *
818 * PARAMETERS: Format, ... - Standard printf format
819 *
820 * RETURN: Number of bytes actually written.
821 *
822 * DESCRIPTION: Formatted output to stdout.
823 *
824 ******************************************************************************/
825
826 int
827 printf (
828 const char *Format,
829 ...)
830 {
831 va_list Args;
832 int Length;
833
834
835 va_start (Args, Format);
836 Length = vprintf (Format, Args);
837 va_end (Args);
838
839 return (Length);
840 }
841
842
843 /*******************************************************************************
844 *
845 * FUNCTION: vfprintf
846 *
847 * PARAMETERS: File - File descriptor
848 * Format - Standard printf format
849 * Args - Argument list
850 *
851 * RETURN: Number of bytes actually written.
852 *
853 * DESCRIPTION: Formatted output to a file using argument list pointer.
854 *
855 ******************************************************************************/
856
857 int
858 vfprintf (
859 FILE *File,
860 const char *Format,
861 va_list Args)
862 {
863 ACPI_CPU_FLAGS Flags;
864 int Length;
865
866
867 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
868 Length = vsnprintf (AcpiGbl_PrintBuffer,
869 sizeof (AcpiGbl_PrintBuffer), Format, Args);
870
871 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File);
872 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
873
874 return (Length);
875 }
876
877
878 /*******************************************************************************
879 *
880 * FUNCTION: fprintf
881 *
882 * PARAMETERS: File - File descriptor
883 * Format, ... - Standard printf format
884 *
885 * RETURN: Number of bytes actually written.
886 *
887 * DESCRIPTION: Formatted output to a file.
888 *
889 ******************************************************************************/
890
891 int
892 fprintf (
893 FILE *File,
894 const char *Format,
895 ...)
896 {
897 va_list Args;
898 int Length;
899
900
901 va_start (Args, Format);
902 Length = vfprintf (File, Format, Args);
903 va_end (Args);
904
905 return (Length);
906 }
907 #endif
908