utprint.c revision 1.3 1 /******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing routines
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2017, 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 Number *= 10;
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 = 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 = 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
621 case 'x':
622
623 Base = 16;
624 break;
625
626 case 'd':
627 case 'i':
628
629 Type |= ACPI_FORMAT_SIGN;
630
631 case 'u':
632
633 break;
634
635 case 'p':
636
637 if (Width == -1)
638 {
639 Width = 2 * sizeof (void *);
640 Type |= ACPI_FORMAT_ZERO;
641 }
642
643 p = va_arg (Args, void *);
644 Pos = AcpiUtFormatNumber (
645 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
646 continue;
647
648 default:
649
650 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
651 if (*Format)
652 {
653 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
654 }
655 else
656 {
657 --Format;
658 }
659 continue;
660 }
661
662 if (Qualifier == 'L')
663 {
664 Number = va_arg (Args, UINT64);
665 if (Type & ACPI_FORMAT_SIGN)
666 {
667 Number = (INT64) Number;
668 }
669 }
670 else if (Qualifier == 'l')
671 {
672 Number = va_arg (Args, unsigned long);
673 if (Type & ACPI_FORMAT_SIGN)
674 {
675 Number = (INT32) Number;
676 }
677 }
678 else if (Qualifier == 'h')
679 {
680 Number = (UINT16) va_arg (Args, int);
681 if (Type & ACPI_FORMAT_SIGN)
682 {
683 Number = (INT16) Number;
684 }
685 }
686 else
687 {
688 Number = va_arg (Args, unsigned int);
689 if (Type & ACPI_FORMAT_SIGN)
690 {
691 Number = (signed int) Number;
692 }
693 }
694
695 Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
696 Width, Precision, Type);
697 }
698
699 if (Size > 0)
700 {
701 if (Pos < End)
702 {
703 *Pos = '\0';
704 }
705 else
706 {
707 End[-1] = '\0';
708 }
709 }
710
711 return (ACPI_PTR_DIFF (Pos, String));
712 }
713
714
715 /*******************************************************************************
716 *
717 * FUNCTION: snprintf
718 *
719 * PARAMETERS: String - String with boundary
720 * Size - Boundary of the string
721 * Format, ... - Standard printf format
722 *
723 * RETURN: Number of bytes actually written.
724 *
725 * DESCRIPTION: Formatted output to a string.
726 *
727 ******************************************************************************/
728
729 int
730 snprintf (
731 char *String,
732 ACPI_SIZE Size,
733 const char *Format,
734 ...)
735 {
736 va_list Args;
737 int Length;
738
739
740 va_start (Args, Format);
741 Length = vsnprintf (String, Size, Format, Args);
742 va_end (Args);
743
744 return (Length);
745 }
746
747
748 /*******************************************************************************
749 *
750 * FUNCTION: sprintf
751 *
752 * PARAMETERS: String - String with boundary
753 * Format, ... - Standard printf format
754 *
755 * RETURN: Number of bytes actually written.
756 *
757 * DESCRIPTION: Formatted output to a string.
758 *
759 ******************************************************************************/
760
761 int
762 sprintf (
763 char *String,
764 const char *Format,
765 ...)
766 {
767 va_list Args;
768 int Length;
769
770
771 va_start (Args, Format);
772 Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args);
773 va_end (Args);
774
775 return (Length);
776 }
777
778
779 #ifdef ACPI_APPLICATION
780 /*******************************************************************************
781 *
782 * FUNCTION: vprintf
783 *
784 * PARAMETERS: Format - Standard printf format
785 * Args - Argument list
786 *
787 * RETURN: Number of bytes actually written.
788 *
789 * DESCRIPTION: Formatted output to stdout using argument list pointer.
790 *
791 ******************************************************************************/
792
793 int
794 vprintf (
795 const char *Format,
796 va_list Args)
797 {
798 ACPI_CPU_FLAGS Flags;
799 int Length;
800
801
802 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
803 Length = vsnprintf (AcpiGbl_PrintBuffer,
804 sizeof (AcpiGbl_PrintBuffer), Format, Args);
805
806 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT);
807 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
808
809 return (Length);
810 }
811
812
813 /*******************************************************************************
814 *
815 * FUNCTION: printf
816 *
817 * PARAMETERS: Format, ... - Standard printf format
818 *
819 * RETURN: Number of bytes actually written.
820 *
821 * DESCRIPTION: Formatted output to stdout.
822 *
823 ******************************************************************************/
824
825 int
826 printf (
827 const char *Format,
828 ...)
829 {
830 va_list Args;
831 int Length;
832
833
834 va_start (Args, Format);
835 Length = vprintf (Format, Args);
836 va_end (Args);
837
838 return (Length);
839 }
840
841
842 /*******************************************************************************
843 *
844 * FUNCTION: vfprintf
845 *
846 * PARAMETERS: File - File descriptor
847 * Format - Standard printf format
848 * Args - Argument list
849 *
850 * RETURN: Number of bytes actually written.
851 *
852 * DESCRIPTION: Formatted output to a file using argument list pointer.
853 *
854 ******************************************************************************/
855
856 int
857 vfprintf (
858 FILE *File,
859 const char *Format,
860 va_list Args)
861 {
862 ACPI_CPU_FLAGS Flags;
863 int Length;
864
865
866 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
867 Length = vsnprintf (AcpiGbl_PrintBuffer,
868 sizeof (AcpiGbl_PrintBuffer), Format, Args);
869
870 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File);
871 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
872
873 return (Length);
874 }
875
876
877 /*******************************************************************************
878 *
879 * FUNCTION: fprintf
880 *
881 * PARAMETERS: File - File descriptor
882 * Format, ... - Standard printf format
883 *
884 * RETURN: Number of bytes actually written.
885 *
886 * DESCRIPTION: Formatted output to a file.
887 *
888 ******************************************************************************/
889
890 int
891 fprintf (
892 FILE *File,
893 const char *Format,
894 ...)
895 {
896 va_list Args;
897 int Length;
898
899
900 va_start (Args, Format);
901 Length = vfprintf (File, Format, Args);
902 va_end (Args);
903
904 return (Length);
905 }
906 #endif
907