7656924d0f4d7240a6e3ee0145ef73b402334004
[reactos.git] / reactos / drivers / bus / acpi / acpica / utilities / utprint.c
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 /* 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
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 *
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 *
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 *
223 AcpiUtScanNumber (
224 const char *String,
225 UINT64 *NumberPtr)
226 {
227 UINT64 Number = 0;
228
229
230 while (isdigit ((int) *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 *
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 *
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 (
394 String, End, 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
439 AcpiUtVsnprintf (
440 char *String,
441 ACPI_SIZE Size,
442 const char *Format,
443 va_list Args)
444 {
445 UINT8 Base;
446 UINT8 Type;
447 INT32 Width;
448 INT32 Precision;
449 char Qualifier;
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 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 = 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
626 case 'x':
627
628 Base = 16;
629 break;
630
631 case 'd':
632 case 'i':
633
634 Type |= ACPI_FORMAT_SIGN;
635
636 case 'u':
637
638 break;
639
640 case 'p':
641
642 if (Width == -1)
643 {
644 Width = 2 * sizeof (void *);
645 Type |= ACPI_FORMAT_ZERO;
646 }
647
648 p = va_arg (Args, void *);
649 Pos = AcpiUtFormatNumber (
650 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
651 continue;
652
653 default:
654
655 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
656 if (*Format)
657 {
658 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
659 }
660 else
661 {
662 --Format;
663 }
664 continue;
665 }
666
667 if (Qualifier == 'L')
668 {
669 Number = va_arg (Args, UINT64);
670 if (Type & ACPI_FORMAT_SIGN)
671 {
672 Number = (INT64) Number;
673 }
674 }
675 else if (Qualifier == 'l')
676 {
677 Number = va_arg (Args, unsigned long);
678 if (Type & ACPI_FORMAT_SIGN)
679 {
680 Number = (INT32) Number;
681 }
682 }
683 else if (Qualifier == 'h')
684 {
685 Number = (UINT16) va_arg (Args, int);
686 if (Type & ACPI_FORMAT_SIGN)
687 {
688 Number = (INT16) Number;
689 }
690 }
691 else
692 {
693 Number = va_arg (Args, unsigned int);
694 if (Type & ACPI_FORMAT_SIGN)
695 {
696 Number = (signed int) Number;
697 }
698 }
699
700 Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
701 Width, Precision, Type);
702 }
703
704 if (Size > 0)
705 {
706 if (Pos < End)
707 {
708 *Pos = '\0';
709 }
710 else
711 {
712 End[-1] = '\0';
713 }
714 }
715
716 return (ACPI_PTR_DIFF (Pos, String));
717 }
718
719
720 /*******************************************************************************
721 *
722 * FUNCTION: AcpiUtSnprintf
723 *
724 * PARAMETERS: String - String with boundary
725 * Size - Boundary of the string
726 * Format, ... - Standard printf format
727 *
728 * RETURN: Number of bytes actually written.
729 *
730 * DESCRIPTION: Formatted output to a string.
731 *
732 ******************************************************************************/
733
734 int
735 AcpiUtSnprintf (
736 char *String,
737 ACPI_SIZE Size,
738 const char *Format,
739 ...)
740 {
741 va_list Args;
742 int Length;
743
744
745 va_start (Args, Format);
746 Length = AcpiUtVsnprintf (String, Size, Format, Args);
747 va_end (Args);
748
749 return (Length);
750 }
751
752
753 #ifdef ACPI_APPLICATION
754 /*******************************************************************************
755 *
756 * FUNCTION: AcpiUtFileVprintf
757 *
758 * PARAMETERS: File - File descriptor
759 * Format - Standard printf format
760 * Args - Argument list
761 *
762 * RETURN: Number of bytes actually written.
763 *
764 * DESCRIPTION: Formatted output to a file using argument list pointer.
765 *
766 ******************************************************************************/
767
768 int
769 AcpiUtFileVprintf (
770 ACPI_FILE File,
771 const char *Format,
772 va_list Args)
773 {
774 ACPI_CPU_FLAGS Flags;
775 int Length;
776
777
778 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
779 Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer,
780 sizeof (AcpiGbl_PrintBuffer), Format, Args);
781
782 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1);
783 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
784
785 return (Length);
786 }
787
788
789 /*******************************************************************************
790 *
791 * FUNCTION: AcpiUtFilePrintf
792 *
793 * PARAMETERS: File - File descriptor
794 * Format, ... - Standard printf format
795 *
796 * RETURN: Number of bytes actually written.
797 *
798 * DESCRIPTION: Formatted output to a file.
799 *
800 ******************************************************************************/
801
802 int
803 AcpiUtFilePrintf (
804 ACPI_FILE File,
805 const char *Format,
806 ...)
807 {
808 va_list Args;
809 int Length;
810
811
812 va_start (Args, Format);
813 Length = AcpiUtFileVprintf (File, Format, Args);
814 va_end (Args);
815
816 return (Length);
817 }
818 #endif