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