1 /******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing routines
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2016, 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 /*******************************************************************************
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 Number *= 10;
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 = 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: AcpiUtVsnprintf
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
AcpiUtVsnprintf(char * String,ACPI_SIZE Size,const char * Format,va_list Args)433 AcpiUtVsnprintf (
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 End = String + Size;
456
457 for (; *Format; ++Format)
458 {
459 if (*Format != '%')
460 {
461 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
462 continue;
463 }
464
465 Type = 0;
466 Base = 10;
467
468 /* Process sign */
469
470 do
471 {
472 ++Format;
473 if (*Format == '#')
474 {
475 Type |= ACPI_FORMAT_PREFIX;
476 }
477 else if (*Format == '0')
478 {
479 Type |= ACPI_FORMAT_ZERO;
480 }
481 else if (*Format == '+')
482 {
483 Type |= ACPI_FORMAT_SIGN_PLUS;
484 }
485 else if (*Format == ' ')
486 {
487 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
488 }
489 else if (*Format == '-')
490 {
491 Type |= ACPI_FORMAT_LEFT;
492 }
493 else
494 {
495 break;
496 }
497
498 } while (1);
499
500 /* Process width */
501
502 Width = -1;
503 if (isdigit ((int) *Format))
504 {
505 Format = AcpiUtScanNumber (Format, &Number);
506 Width = (INT32) Number;
507 }
508 else if (*Format == '*')
509 {
510 ++Format;
511 Width = va_arg (Args, int);
512 if (Width < 0)
513 {
514 Width = -Width;
515 Type |= ACPI_FORMAT_LEFT;
516 }
517 }
518
519 /* Process precision */
520
521 Precision = -1;
522 if (*Format == '.')
523 {
524 ++Format;
525 if (isdigit ((int) *Format))
526 {
527 Format = AcpiUtScanNumber (Format, &Number);
528 Precision = (INT32) Number;
529 }
530 else if (*Format == '*')
531 {
532 ++Format;
533 Precision = va_arg (Args, int);
534 }
535
536 if (Precision < 0)
537 {
538 Precision = 0;
539 }
540 }
541
542 /* Process qualifier */
543
544 Qualifier = -1;
545 if (*Format == 'h' || *Format == 'l' || *Format == 'L')
546 {
547 Qualifier = *Format;
548 ++Format;
549
550 if (Qualifier == 'l' && *Format == 'l')
551 {
552 Qualifier = 'L';
553 ++Format;
554 }
555 }
556
557 switch (*Format)
558 {
559 case '%':
560
561 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
562 continue;
563
564 case 'c':
565
566 if (!(Type & ACPI_FORMAT_LEFT))
567 {
568 while (--Width > 0)
569 {
570 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
571 }
572 }
573
574 c = (char) va_arg (Args, int);
575 Pos = AcpiUtBoundStringOutput (Pos, End, c);
576
577 while (--Width > 0)
578 {
579 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
580 }
581 continue;
582
583 case 's':
584
585 s = va_arg (Args, char *);
586 if (!s)
587 {
588 s = "<NULL>";
589 }
590 Length = AcpiUtBoundStringLength (s, Precision);
591 if (!(Type & ACPI_FORMAT_LEFT))
592 {
593 while (Length < Width--)
594 {
595 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
596 }
597 }
598
599 for (i = 0; i < Length; ++i)
600 {
601 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
602 ++s;
603 }
604
605 while (Length < Width--)
606 {
607 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
608 }
609 continue;
610
611 case 'o':
612
613 Base = 8;
614 break;
615
616 case 'X':
617
618 Type |= ACPI_FORMAT_UPPER;
619
620 case 'x':
621
622 Base = 16;
623 break;
624
625 case 'd':
626 case 'i':
627
628 Type |= ACPI_FORMAT_SIGN;
629
630 case 'u':
631
632 break;
633
634 case 'p':
635
636 if (Width == -1)
637 {
638 Width = 2 * sizeof (void *);
639 Type |= ACPI_FORMAT_ZERO;
640 }
641
642 p = va_arg (Args, void *);
643 Pos = AcpiUtFormatNumber (
644 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
645 continue;
646
647 default:
648
649 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
650 if (*Format)
651 {
652 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
653 }
654 else
655 {
656 --Format;
657 }
658 continue;
659 }
660
661 if (Qualifier == 'L')
662 {
663 Number = va_arg (Args, UINT64);
664 if (Type & ACPI_FORMAT_SIGN)
665 {
666 Number = (INT64) Number;
667 }
668 }
669 else if (Qualifier == 'l')
670 {
671 Number = va_arg (Args, unsigned long);
672 if (Type & ACPI_FORMAT_SIGN)
673 {
674 Number = (INT32) Number;
675 }
676 }
677 else if (Qualifier == 'h')
678 {
679 Number = (UINT16) va_arg (Args, int);
680 if (Type & ACPI_FORMAT_SIGN)
681 {
682 Number = (INT16) Number;
683 }
684 }
685 else
686 {
687 Number = va_arg (Args, unsigned int);
688 if (Type & ACPI_FORMAT_SIGN)
689 {
690 Number = (signed int) Number;
691 }
692 }
693
694 Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
695 Width, Precision, Type);
696 }
697
698 if (Size > 0)
699 {
700 if (Pos < End)
701 {
702 *Pos = '\0';
703 }
704 else
705 {
706 End[-1] = '\0';
707 }
708 }
709
710 return (ACPI_PTR_DIFF (Pos, String));
711 }
712
713
714 /*******************************************************************************
715 *
716 * FUNCTION: AcpiUtSnprintf
717 *
718 * PARAMETERS: String - String with boundary
719 * Size - Boundary of the string
720 * Format, ... - Standard printf format
721 *
722 * RETURN: Number of bytes actually written.
723 *
724 * DESCRIPTION: Formatted output to a string.
725 *
726 ******************************************************************************/
727
728 int
AcpiUtSnprintf(char * String,ACPI_SIZE Size,const char * Format,...)729 AcpiUtSnprintf (
730 char *String,
731 ACPI_SIZE Size,
732 const char *Format,
733 ...)
734 {
735 va_list Args;
736 int Length;
737
738
739 va_start (Args, Format);
740 Length = AcpiUtVsnprintf (String, Size, Format, Args);
741 va_end (Args);
742
743 return (Length);
744 }
745
746
747 #ifdef ACPI_APPLICATION
748 /*******************************************************************************
749 *
750 * FUNCTION: AcpiUtFileVprintf
751 *
752 * PARAMETERS: File - File descriptor
753 * Format - Standard printf format
754 * Args - Argument list
755 *
756 * RETURN: Number of bytes actually written.
757 *
758 * DESCRIPTION: Formatted output to a file using argument list pointer.
759 *
760 ******************************************************************************/
761
762 int
AcpiUtFileVprintf(ACPI_FILE File,const char * Format,va_list Args)763 AcpiUtFileVprintf (
764 ACPI_FILE File,
765 const char *Format,
766 va_list Args)
767 {
768 ACPI_CPU_FLAGS Flags;
769 int Length;
770
771
772 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
773 Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer,
774 sizeof (AcpiGbl_PrintBuffer), Format, Args);
775
776 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1);
777 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
778
779 return (Length);
780 }
781
782
783 /*******************************************************************************
784 *
785 * FUNCTION: AcpiUtFilePrintf
786 *
787 * PARAMETERS: File - File descriptor
788 * Format, ... - Standard printf format
789 *
790 * RETURN: Number of bytes actually written.
791 *
792 * DESCRIPTION: Formatted output to a file.
793 *
794 ******************************************************************************/
795
796 int
AcpiUtFilePrintf(ACPI_FILE File,const char * Format,...)797 AcpiUtFilePrintf (
798 ACPI_FILE File,
799 const char *Format,
800 ...)
801 {
802 va_list Args;
803 int Length;
804
805
806 va_start (Args, Format);
807 Length = AcpiUtFileVprintf (File, Format, Args);
808 va_end (Args);
809
810 return (Length);
811 }
812 #endif
813