1 /******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing routines
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2014, 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
AcpiUtBoundStringLength(const char * String,ACPI_SIZE Count)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 *
AcpiUtBoundStringOutput(char * String,const char * End,char c)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 *
AcpiUtPutNumber(char * String,UINT64 Number,UINT8 Base,BOOLEAN Upper)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 *
AcpiUtScanNumber(const char * String,UINT64 * NumberPtr)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 *
AcpiUtPrintNumber(char * String,UINT64 Number)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 *
AcpiUtFormatNumber(char * String,char * End,UINT64 Number,UINT8 Base,INT32 Width,INT32 Precision,UINT8 Type)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
AcpiUtVsnprintf(char * String,ACPI_SIZE Size,const char * Format,va_list Args)439 AcpiUtVsnprintf (
440 char *String,
441 ACPI_SIZE Size,
442 const char *Format,
443 va_list Args)
444 {
445 UINT8 Base = 10;
446 UINT8 Type = 0;
447 INT32 Width = -1;
448 INT32 Precision = -1;
449 char Qualifier = 0;
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 /* Process sign */
472
473 do
474 {
475 ++Format;
476 if (*Format == '#')
477 {
478 Type |= ACPI_FORMAT_PREFIX;
479 }
480 else if (*Format == '0')
481 {
482 Type |= ACPI_FORMAT_ZERO;
483 }
484 else if (*Format == '+')
485 {
486 Type |= ACPI_FORMAT_SIGN_PLUS;
487 }
488 else if (*Format == ' ')
489 {
490 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
491 }
492 else if (*Format == '-')
493 {
494 Type |= ACPI_FORMAT_LEFT;
495 }
496 else
497 {
498 break;
499 }
500 } while (1);
501
502 /* Process width */
503
504 Width = -1;
505 if (ACPI_IS_DIGIT (*Format))
506 {
507 Format = AcpiUtScanNumber (Format, &Number);
508 Width = (INT32) Number;
509 }
510 else if (*Format == '*')
511 {
512 ++Format;
513 Width = va_arg (Args, int);
514 if (Width < 0)
515 {
516 Width = -Width;
517 Type |= ACPI_FORMAT_LEFT;
518 }
519 }
520
521 /* Process precision */
522
523 Precision = -1;
524 if (*Format == '.')
525 {
526 ++Format;
527 if (ACPI_IS_DIGIT(*Format))
528 {
529 Format = AcpiUtScanNumber (Format, &Number);
530 Precision = (INT32) Number;
531 }
532 else if (*Format == '*')
533 {
534 ++Format;
535 Precision = va_arg (Args, int);
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 for (i = 0; i < Length; ++i)
600 {
601 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
602 ++s;
603 }
604 while (Length < Width--)
605 {
606 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
607 }
608 continue;
609
610 case 'o':
611
612 Base = 8;
613 break;
614
615 case 'X':
616
617 Type |= ACPI_FORMAT_UPPER;
618
619 case 'x':
620
621 Base = 16;
622 break;
623
624 case 'd':
625 case 'i':
626
627 Type |= ACPI_FORMAT_SIGN;
628
629 case 'u':
630
631 break;
632
633 case 'p':
634
635 if (Width == -1)
636 {
637 Width = 2 * sizeof (void *);
638 Type |= ACPI_FORMAT_ZERO;
639 }
640
641 p = va_arg (Args, void *);
642 Pos = AcpiUtFormatNumber (Pos, End,
643 ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
644 continue;
645
646 default:
647
648 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
649 if (*Format)
650 {
651 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
652 }
653 else
654 {
655 --Format;
656 }
657 continue;
658 }
659
660 if (Qualifier == 'L')
661 {
662 Number = va_arg (Args, UINT64);
663 if (Type & ACPI_FORMAT_SIGN)
664 {
665 Number = (INT64) Number;
666 }
667 }
668 else if (Qualifier == 'l')
669 {
670 Number = va_arg (Args, unsigned long);
671 if (Type & ACPI_FORMAT_SIGN)
672 {
673 Number = (INT32) Number;
674 }
675 }
676 else if (Qualifier == 'h')
677 {
678 Number = (UINT16) va_arg (Args, int);
679 if (Type & ACPI_FORMAT_SIGN)
680 {
681 Number = (INT16) Number;
682 }
683 }
684 else
685 {
686 Number = va_arg (Args, unsigned int);
687 if (Type & ACPI_FORMAT_SIGN)
688 {
689 Number = (signed int) Number;
690 }
691 }
692
693 Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
694 Width, Precision, Type);
695 }
696
697 if (Size > 0)
698 {
699 if (Pos < End)
700 {
701 *Pos = '\0';
702 }
703 else
704 {
705 End[-1] = '\0';
706 }
707 }
708
709 return (ACPI_PTR_DIFF (Pos, String));
710 }
711
712
713 /*******************************************************************************
714 *
715 * FUNCTION: AcpiUtSnprintf
716 *
717 * PARAMETERS: String - String with boundary
718 * Size - Boundary of the string
719 * Format, ... - Standard printf format
720 *
721 * RETURN: Number of bytes actually written.
722 *
723 * DESCRIPTION: Formatted output to a string.
724 *
725 ******************************************************************************/
726
727 int
AcpiUtSnprintf(char * String,ACPI_SIZE Size,const char * Format,...)728 AcpiUtSnprintf (
729 char *String,
730 ACPI_SIZE Size,
731 const char *Format,
732 ...)
733 {
734 va_list Args;
735 int Length;
736
737
738 va_start (Args, Format);
739 Length = AcpiUtVsnprintf (String, Size, Format, Args);
740 va_end (Args);
741
742 return (Length);
743 }
744
745
746 #ifdef ACPI_APPLICATION
747 /*******************************************************************************
748 *
749 * FUNCTION: AcpiUtFileVprintf
750 *
751 * PARAMETERS: File - File descriptor
752 * Format - Standard printf format
753 * Args - Argument list
754 *
755 * RETURN: Number of bytes actually written.
756 *
757 * DESCRIPTION: Formatted output to a file using argument list pointer.
758 *
759 ******************************************************************************/
760
761 int
AcpiUtFileVprintf(ACPI_FILE File,const char * Format,va_list Args)762 AcpiUtFileVprintf (
763 ACPI_FILE File,
764 const char *Format,
765 va_list Args)
766 {
767 ACPI_CPU_FLAGS Flags;
768 int Length;
769
770
771 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
772 Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer,
773 sizeof (AcpiGbl_PrintBuffer), Format, Args);
774
775 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1);
776 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
777
778 return (Length);
779 }
780
781
782 /*******************************************************************************
783 *
784 * FUNCTION: AcpiUtFilePrintf
785 *
786 * PARAMETERS: File - File descriptor
787 * Format, ... - Standard printf format
788 *
789 * RETURN: Number of bytes actually written.
790 *
791 * DESCRIPTION: Formatted output to a file.
792 *
793 ******************************************************************************/
794
795 int
AcpiUtFilePrintf(ACPI_FILE File,const char * Format,...)796 AcpiUtFilePrintf (
797 ACPI_FILE File,
798 const char *Format,
799 ...)
800 {
801 va_list Args;
802 int Length;
803
804
805 va_start (Args, Format);
806 Length = AcpiUtFileVprintf (File, Format, Args);
807 va_end (Args);
808
809 return (Length);
810 }
811 #endif
812