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 #undef sprintf
417 #undef snprintf
418 #undef vsnprintf
419 /*******************************************************************************
420  *
421  * FUNCTION:    vsnprintf
422  *
423  * PARAMETERS:  String              - String with boundary
424  *              Size                - Boundary of the string
425  *              Format              - Standard printf format
426  *              Args                - Argument list
427  *
428  * RETURN:      Number of bytes actually written.
429  *
430  * DESCRIPTION: Formatted output to a string using argument list pointer.
431  *
432  ******************************************************************************/
433 
434 int
vsnprintf(char * String,ACPI_SIZE Size,const char * Format,va_list Args)435 vsnprintf (
436     char                    *String,
437     ACPI_SIZE               Size,
438     const char              *Format,
439     va_list                 Args)
440 {
441     UINT8                   Base;
442     UINT8                   Type;
443     INT32                   Width;
444     INT32                   Precision;
445     char                    Qualifier;
446     UINT64                  Number;
447     char                    *Pos;
448     char                    *End;
449     char                    c;
450     const char              *s;
451     const void              *p;
452     INT32                   Length;
453     int                     i;
454 
455 
456     Pos = String;
457 
458 
459     if (Size != ACPI_UINT32_MAX) {
460         End = String + Size;
461     } else {
462         End = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);
463     }
464 
465     for (; *Format; ++Format)
466     {
467         if (*Format != '%')
468         {
469             Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
470             continue;
471         }
472 
473         Type = 0;
474         Base = 10;
475 
476         /* Process sign */
477 
478         do
479         {
480             ++Format;
481             if (*Format == '#')
482             {
483                 Type |= ACPI_FORMAT_PREFIX;
484             }
485             else if (*Format == '0')
486             {
487                 Type |= ACPI_FORMAT_ZERO;
488             }
489             else if (*Format == '+')
490             {
491                 Type |= ACPI_FORMAT_SIGN_PLUS;
492             }
493             else if (*Format == ' ')
494             {
495                 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
496             }
497             else if (*Format == '-')
498             {
499                 Type |= ACPI_FORMAT_LEFT;
500             }
501             else
502             {
503                 break;
504             }
505 
506         } while (1);
507 
508         /* Process width */
509 
510         Width = -1;
511         if (isdigit ((int) *Format))
512         {
513             Format = AcpiUtScanNumber (Format, &Number);
514             Width = (INT32) Number;
515         }
516         else if (*Format == '*')
517         {
518             ++Format;
519             Width = va_arg (Args, int);
520             if (Width < 0)
521             {
522                 Width = -Width;
523                 Type |= ACPI_FORMAT_LEFT;
524             }
525         }
526 
527         /* Process precision */
528 
529         Precision = -1;
530         if (*Format == '.')
531         {
532             ++Format;
533             if (isdigit ((int) *Format))
534             {
535                 Format = AcpiUtScanNumber (Format, &Number);
536                 Precision = (INT32) Number;
537             }
538             else if (*Format == '*')
539             {
540                 ++Format;
541                 Precision = va_arg (Args, int);
542             }
543 
544             if (Precision < 0)
545             {
546                 Precision = 0;
547             }
548         }
549 
550         /* Process qualifier */
551 
552         Qualifier = -1;
553         if (*Format == 'h' || *Format == 'l' || *Format == 'L')
554         {
555             Qualifier = *Format;
556             ++Format;
557 
558             if (Qualifier == 'l' && *Format == 'l')
559             {
560                 Qualifier = 'L';
561                 ++Format;
562             }
563         }
564 
565         switch (*Format)
566         {
567         case '%':
568 
569             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
570             continue;
571 
572         case 'c':
573 
574             if (!(Type & ACPI_FORMAT_LEFT))
575             {
576                 while (--Width > 0)
577                 {
578                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
579                 }
580             }
581 
582             c = (char) va_arg (Args, int);
583             Pos = AcpiUtBoundStringOutput (Pos, End, c);
584 
585             while (--Width > 0)
586             {
587                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
588             }
589             continue;
590 
591         case 's':
592 
593             s = va_arg (Args, char *);
594             if (!s)
595             {
596                 s = "<NULL>";
597             }
598             Length = (INT32) AcpiUtBoundStringLength (s, Precision);
599             if (!(Type & ACPI_FORMAT_LEFT))
600             {
601                 while (Length < Width--)
602                 {
603                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
604                 }
605             }
606 
607             for (i = 0; i < Length; ++i)
608             {
609                 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
610                 ++s;
611             }
612 
613             while (Length < Width--)
614             {
615                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
616             }
617             continue;
618 
619         case 'o':
620 
621             Base = 8;
622             break;
623 
624         case 'X':
625 
626             Type |= ACPI_FORMAT_UPPER;
627             ACPI_FALLTHROUGH;
628 
629         case 'x':
630 
631             Base = 16;
632             break;
633 
634         case 'd':
635         case 'i':
636 
637             Type |= ACPI_FORMAT_SIGN;
638 
639         case 'u':
640 
641             break;
642 
643         case 'p':
644 
645             if (Width == -1)
646             {
647                 Width = 2 * sizeof (void *);
648                 Type |= ACPI_FORMAT_ZERO;
649             }
650 
651             p = va_arg (Args, void *);
652             Pos = AcpiUtFormatNumber (
653                 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
654             continue;
655 
656         default:
657 
658             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
659             if (*Format)
660             {
661                 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
662             }
663             else
664             {
665                 --Format;
666             }
667             continue;
668         }
669 
670         if (Qualifier == 'L')
671         {
672             Number = va_arg (Args, UINT64);
673             if (Type & ACPI_FORMAT_SIGN)
674             {
675                 Number = (INT64) Number;
676             }
677         }
678         else if (Qualifier == 'l')
679         {
680             Number = va_arg (Args, unsigned long);
681             if (Type & ACPI_FORMAT_SIGN)
682             {
683                 Number = (INT32) Number;
684             }
685         }
686         else if (Qualifier == 'h')
687         {
688             Number = (UINT16) va_arg (Args, int);
689             if (Type & ACPI_FORMAT_SIGN)
690             {
691                 Number = (INT16) Number;
692             }
693         }
694         else
695         {
696             Number = va_arg (Args, unsigned int);
697             if (Type & ACPI_FORMAT_SIGN)
698             {
699                 Number = (signed int) Number;
700             }
701         }
702 
703         Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
704             Width, Precision, Type);
705     }
706 
707     if (Size > 0)
708     {
709         if (Pos < End)
710         {
711             *Pos = '\0';
712         }
713         else
714         {
715             End[-1] = '\0';
716         }
717     }
718 
719     return ((int) ACPI_PTR_DIFF (Pos, String));
720 }
721 
722 
723 /*******************************************************************************
724  *
725  * FUNCTION:    snprintf
726  *
727  * PARAMETERS:  String              - String with boundary
728  *              Size                - Boundary of the string
729  *              Format, ...         - Standard printf format
730  *
731  * RETURN:      Number of bytes actually written.
732  *
733  * DESCRIPTION: Formatted output to a string.
734  *
735  ******************************************************************************/
736 
737 int
snprintf(char * String,ACPI_SIZE Size,const char * Format,...)738 snprintf (
739     char                    *String,
740     ACPI_SIZE               Size,
741     const char              *Format,
742     ...)
743 {
744     va_list                 Args;
745     int                     Length;
746 
747 
748     va_start (Args, Format);
749     Length = vsnprintf (String, Size, Format, Args);
750     va_end (Args);
751 
752     return (Length);
753 }
754 
755 
756 /*******************************************************************************
757  *
758  * FUNCTION:    sprintf
759  *
760  * PARAMETERS:  String              - String with boundary
761  *              Format, ...         - Standard printf format
762  *
763  * RETURN:      Number of bytes actually written.
764  *
765  * DESCRIPTION: Formatted output to a string.
766  *
767  ******************************************************************************/
768 
769 int
sprintf(char * String,const char * Format,...)770 sprintf (
771     char                    *String,
772     const char              *Format,
773     ...)
774 {
775     va_list                 Args;
776     int                     Length;
777 
778 
779     va_start (Args, Format);
780     Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args);
781     va_end (Args);
782 
783     return (Length);
784 }
785 
786 
787 #ifdef ACPI_APPLICATION
788 /*******************************************************************************
789  *
790  * FUNCTION:    vprintf
791  *
792  * PARAMETERS:  Format              - Standard printf format
793  *              Args                - Argument list
794  *
795  * RETURN:      Number of bytes actually written.
796  *
797  * DESCRIPTION: Formatted output to stdout using argument list pointer.
798  *
799  ******************************************************************************/
800 
801 int
vprintf(const char * Format,va_list Args)802 vprintf (
803     const char              *Format,
804     va_list                 Args)
805 {
806     ACPI_CPU_FLAGS          Flags;
807     int                     Length;
808 
809 
810     Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
811     Length = vsnprintf (AcpiGbl_PrintBuffer,
812                 sizeof (AcpiGbl_PrintBuffer), Format, Args);
813 
814     (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT);
815     AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
816 
817     return (Length);
818 }
819 
820 
821 /*******************************************************************************
822  *
823  * FUNCTION:    printf
824  *
825  * PARAMETERS:  Format, ...         - Standard printf format
826  *
827  * RETURN:      Number of bytes actually written.
828  *
829  * DESCRIPTION: Formatted output to stdout.
830  *
831  ******************************************************************************/
832 
833 int
printf(const char * Format,...)834 printf (
835     const char              *Format,
836     ...)
837 {
838     va_list                 Args;
839     int                     Length;
840 
841 
842     va_start (Args, Format);
843     Length = vprintf (Format, Args);
844     va_end (Args);
845 
846     return (Length);
847 }
848 
849 
850 /*******************************************************************************
851  *
852  * FUNCTION:    vfprintf
853  *
854  * PARAMETERS:  File                - File descriptor
855  *              Format              - Standard printf format
856  *              Args                - Argument list
857  *
858  * RETURN:      Number of bytes actually written.
859  *
860  * DESCRIPTION: Formatted output to a file using argument list pointer.
861  *
862  ******************************************************************************/
863 
864 int
vfprintf(FILE * File,const char * Format,va_list Args)865 vfprintf (
866     FILE                    *File,
867     const char              *Format,
868     va_list                 Args)
869 {
870     ACPI_CPU_FLAGS          Flags;
871     int                     Length;
872 
873 
874     Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
875     Length = vsnprintf (AcpiGbl_PrintBuffer,
876         sizeof (AcpiGbl_PrintBuffer), Format, Args);
877 
878     (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File);
879     AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
880 
881     return (Length);
882 }
883 
884 
885 /*******************************************************************************
886  *
887  * FUNCTION:    fprintf
888  *
889  * PARAMETERS:  File                - File descriptor
890  *              Format, ...         - Standard printf format
891  *
892  * RETURN:      Number of bytes actually written.
893  *
894  * DESCRIPTION: Formatted output to a file.
895  *
896  ******************************************************************************/
897 
898 int
fprintf(FILE * File,const char * Format,...)899 fprintf (
900     FILE                    *File,
901     const char              *Format,
902     ...)
903 {
904     va_list                 Args;
905     int                     Length;
906 
907 
908     va_start (Args, Format);
909     Length = vfprintf (File, Format, Args);
910     va_end (Args);
911 
912     return (Length);
913 }
914 #endif
915