2018-03-14 16:13:07 -07:00
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2014-07-08 10:07:00 +08:00
/******************************************************************************
*
* Module Name : utprint - Formatted printing routines
*
2019-01-14 09:55:25 -08:00
* Copyright ( C ) 2000 - 2019 , Intel Corp .
2014-07-08 10:07:00 +08:00
*
2018-03-14 16:13:07 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-07-08 10:07:00 +08:00
# include <acpi/acpi.h>
# include "accommon.h"
# define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ( " utprint " )
# define ACPI_FORMAT_SIGN 0x01
# define ACPI_FORMAT_SIGN_PLUS 0x02
# define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
# define ACPI_FORMAT_ZERO 0x08
# define ACPI_FORMAT_LEFT 0x10
# define ACPI_FORMAT_UPPER 0x20
# define ACPI_FORMAT_PREFIX 0x40
/* Local prototypes */
static acpi_size
acpi_ut_bound_string_length ( const char * string , acpi_size count ) ;
static char * acpi_ut_bound_string_output ( char * string , const char * end , char c ) ;
static char * acpi_ut_format_number ( char * string ,
char * end ,
u64 number ,
u8 base , s32 width , s32 precision , u8 type ) ;
static char * acpi_ut_put_number ( char * string , u64 number , u8 base , u8 upper ) ;
/*******************************************************************************
*
* FUNCTION : acpi_ut_bound_string_length
*
* PARAMETERS : string - String with boundary
* count - Boundary of the string
*
2014-07-08 10:08:13 +08:00
* RETURN : Length of the string . Less than or equal to Count .
2014-07-08 10:07:00 +08:00
*
* DESCRIPTION : Calculate the length of a string with boundary .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static acpi_size
acpi_ut_bound_string_length ( const char * string , acpi_size count )
{
u32 length = 0 ;
while ( * string & & count ) {
length + + ;
string + + ;
count - - ;
}
return ( length ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_bound_string_output
*
* PARAMETERS : string - String with boundary
* end - Boundary of the string
* c - Character to be output to the string
*
* RETURN : Updated position for next valid character
*
* DESCRIPTION : Output a character into a string with boundary check .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * acpi_ut_bound_string_output ( char * string , const char * end , char c )
{
if ( string < end ) {
* string = c ;
}
2014-07-08 10:08:13 +08:00
+ + string ;
2014-07-08 10:07:00 +08:00
return ( string ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_put_number
*
* PARAMETERS : string - Buffer to hold reverse - ordered string
* number - Integer to be converted
* base - Base of the integer
* upper - Whether or not using upper cased digits
*
* RETURN : Updated position for next valid character
*
* DESCRIPTION : Convert an integer into a string , note that , the string holds a
* reversed ordered number without the trailing zero .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * acpi_ut_put_number ( char * string , u64 number , u8 base , u8 upper )
{
const char * digits ;
u64 digit_index ;
char * pos ;
pos = string ;
2014-07-08 10:08:13 +08:00
digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits ;
2014-07-08 10:07:00 +08:00
if ( number = = 0 ) {
* ( pos + + ) = ' 0 ' ;
} else {
while ( number ) {
( void ) acpi_ut_divide ( number , base , & number ,
& digit_index ) ;
* ( pos + + ) = digits [ digit_index ] ;
}
}
2014-07-08 10:08:13 +08:00
/* *(Pos++) = '0'; */
2014-07-08 10:07:00 +08:00
return ( pos ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_scan_number
*
* PARAMETERS : string - String buffer
* number_ptr - Where the number is returned
*
* RETURN : Updated position for next valid character
*
* DESCRIPTION : Scan a string for a decimal integer .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const char * acpi_ut_scan_number ( const char * string , u64 * number_ptr )
{
u64 number = 0 ;
2015-07-01 14:45:11 +08:00
while ( isdigit ( ( int ) * string ) ) {
2017-08-03 14:26:50 +08:00
acpi_ut_short_multiply ( number , 10 , & number ) ;
2014-07-08 10:07:00 +08:00
number + = * ( string + + ) - ' 0 ' ;
}
2014-07-08 10:08:13 +08:00
* number_ptr = number ;
2014-07-08 10:07:00 +08:00
return ( string ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_print_number
*
* PARAMETERS : string - String buffer
* number - The number to be converted
*
* RETURN : Updated position for next valid character
*
* DESCRIPTION : Print a decimal integer into a string .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const char * acpi_ut_print_number ( char * string , u64 number )
{
char ascii_string [ 20 ] ;
const char * pos1 ;
char * pos2 ;
pos1 = acpi_ut_put_number ( ascii_string , number , 10 , FALSE ) ;
pos2 = string ;
while ( pos1 ! = ascii_string ) {
* ( pos2 + + ) = * ( - - pos1 ) ;
}
2014-07-08 10:08:13 +08:00
* pos2 = 0 ;
2014-07-08 10:07:00 +08:00
return ( string ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_format_number
*
* PARAMETERS : string - String buffer with boundary
* end - Boundary of the string
* number - The number to be converted
* base - Base of the integer
* width - Field width
* precision - Precision of the integer
* type - Special printing flags
*
* RETURN : Updated position for next valid character
*
* DESCRIPTION : Print an integer into a string with any base and any precision .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * acpi_ut_format_number ( char * string ,
char * end ,
u64 number ,
u8 base , s32 width , s32 precision , u8 type )
{
2014-07-30 12:20:26 +08:00
char * pos ;
2014-07-08 10:07:00 +08:00
char sign ;
char zero ;
u8 need_prefix ;
u8 upper ;
s32 i ;
char reversed_string [ 66 ] ;
2014-07-08 10:08:13 +08:00
/* Parameter validation */
2014-07-08 10:07:00 +08:00
if ( base < 2 | | base > 16 ) {
2014-07-08 10:08:13 +08:00
return ( NULL ) ;
2014-07-08 10:07:00 +08:00
}
2014-07-08 10:08:13 +08:00
2014-07-08 10:07:00 +08:00
if ( type & ACPI_FORMAT_LEFT ) {
type & = ~ ACPI_FORMAT_ZERO ;
}
need_prefix = ( ( type & ACPI_FORMAT_PREFIX )
& & base ! = 10 ) ? TRUE : FALSE ;
upper = ( type & ACPI_FORMAT_UPPER ) ? TRUE : FALSE ;
zero = ( type & ACPI_FORMAT_ZERO ) ? ' 0 ' : ' ' ;
/* Calculate size according to sign and prefix */
sign = ' \0 ' ;
if ( type & ACPI_FORMAT_SIGN ) {
2016-05-05 12:57:53 +08:00
if ( ( s64 ) number < 0 ) {
2014-07-08 10:07:00 +08:00
sign = ' - ' ;
2016-05-05 12:57:53 +08:00
number = - ( s64 ) number ;
2014-07-08 10:07:00 +08:00
width - - ;
} else if ( type & ACPI_FORMAT_SIGN_PLUS ) {
sign = ' + ' ;
width - - ;
} else if ( type & ACPI_FORMAT_SIGN_PLUS_SPACE ) {
sign = ' ' ;
width - - ;
}
}
if ( need_prefix ) {
width - - ;
if ( base = = 16 ) {
width - - ;
}
}
/* Generate full string in reverse order */
2014-07-30 12:20:26 +08:00
pos = acpi_ut_put_number ( reversed_string , number , base , upper ) ;
2017-08-03 14:27:03 +08:00
i = ( s32 ) ACPI_PTR_DIFF ( pos , reversed_string ) ;
2014-07-08 10:07:00 +08:00
/* Printing 100 using %2d gives "100", not "00" */
if ( i > precision ) {
precision = i ;
}
2014-07-08 10:08:13 +08:00
2014-07-08 10:07:00 +08:00
width - = precision ;
/* Output the string */
if ( ! ( type & ( ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT ) ) ) {
while ( - - width > = 0 ) {
string = acpi_ut_bound_string_output ( string , end , ' ' ) ;
}
}
if ( sign ) {
string = acpi_ut_bound_string_output ( string , end , sign ) ;
}
if ( need_prefix ) {
string = acpi_ut_bound_string_output ( string , end , ' 0 ' ) ;
if ( base = = 16 ) {
2015-12-29 13:54:36 +08:00
string =
acpi_ut_bound_string_output ( string , end ,
upper ? ' X ' : ' x ' ) ;
2014-07-08 10:07:00 +08:00
}
}
if ( ! ( type & ACPI_FORMAT_LEFT ) ) {
while ( - - width > = 0 ) {
string = acpi_ut_bound_string_output ( string , end , zero ) ;
}
}
2014-07-08 10:08:13 +08:00
2014-07-08 10:07:00 +08:00
while ( i < = - - precision ) {
string = acpi_ut_bound_string_output ( string , end , ' 0 ' ) ;
}
while ( - - i > = 0 ) {
string = acpi_ut_bound_string_output ( string , end ,
reversed_string [ i ] ) ;
}
while ( - - width > = 0 ) {
string = acpi_ut_bound_string_output ( string , end , ' ' ) ;
}
return ( string ) ;
}
/*******************************************************************************
*
2016-08-04 16:45:06 +08:00
* FUNCTION : vsnprintf
2014-07-08 10:07:00 +08:00
*
* PARAMETERS : string - String with boundary
* size - Boundary of the string
* format - Standard printf format
* args - Argument list
*
2014-07-08 10:08:13 +08:00
* RETURN : Number of bytes actually written .
2014-07-08 10:07:00 +08:00
*
* DESCRIPTION : Formatted output to a string using argument list pointer .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-08-04 16:45:06 +08:00
int vsnprintf ( char * string , acpi_size size , const char * format , va_list args )
2014-07-08 10:07:00 +08:00
{
2015-04-13 11:51:23 +08:00
u8 base ;
u8 type ;
s32 width ;
s32 precision ;
char qualifier ;
2014-07-08 10:07:00 +08:00
u64 number ;
char * pos ;
char * end ;
char c ;
const char * s ;
const void * p ;
s32 length ;
int i ;
pos = string ;
end = string + size ;
for ( ; * format ; + + format ) {
if ( * format ! = ' % ' ) {
pos = acpi_ut_bound_string_output ( pos , end , * format ) ;
continue ;
}
2015-04-13 11:51:23 +08:00
type = 0 ;
base = 10 ;
2014-07-08 10:07:00 +08:00
/* Process sign */
do {
+ + format ;
if ( * format = = ' # ' ) {
type | = ACPI_FORMAT_PREFIX ;
} else if ( * format = = ' 0 ' ) {
type | = ACPI_FORMAT_ZERO ;
} else if ( * format = = ' + ' ) {
type | = ACPI_FORMAT_SIGN_PLUS ;
} else if ( * format = = ' ' ) {
type | = ACPI_FORMAT_SIGN_PLUS_SPACE ;
} else if ( * format = = ' - ' ) {
type | = ACPI_FORMAT_LEFT ;
} else {
break ;
}
2015-12-29 13:54:36 +08:00
2014-07-08 10:07:00 +08:00
} while ( 1 ) ;
/* Process width */
2014-07-30 12:21:07 +08:00
width = - 1 ;
2015-07-01 14:45:11 +08:00
if ( isdigit ( ( int ) * format ) ) {
2014-07-08 10:07:00 +08:00
format = acpi_ut_scan_number ( format , & number ) ;
2016-05-05 12:57:53 +08:00
width = ( s32 ) number ;
2014-07-08 10:07:00 +08:00
} else if ( * format = = ' * ' ) {
+ + format ;
width = va_arg ( args , int ) ;
if ( width < 0 ) {
width = - width ;
type | = ACPI_FORMAT_LEFT ;
}
}
/* Process precision */
2014-07-30 12:21:07 +08:00
precision = - 1 ;
2014-07-08 10:07:00 +08:00
if ( * format = = ' . ' ) {
+ + format ;
2015-07-01 14:45:11 +08:00
if ( isdigit ( ( int ) * format ) ) {
2014-07-08 10:07:00 +08:00
format = acpi_ut_scan_number ( format , & number ) ;
2016-05-05 12:57:53 +08:00
precision = ( s32 ) number ;
2014-07-08 10:07:00 +08:00
} else if ( * format = = ' * ' ) {
+ + format ;
precision = va_arg ( args , int ) ;
}
2015-12-29 13:54:36 +08:00
2014-07-08 10:07:00 +08:00
if ( precision < 0 ) {
precision = 0 ;
}
}
/* Process qualifier */
2014-07-30 12:21:07 +08:00
qualifier = - 1 ;
2014-07-08 10:07:00 +08:00
if ( * format = = ' h ' | | * format = = ' l ' | | * format = = ' L ' ) {
qualifier = * format ;
+ + format ;
2014-07-08 10:08:13 +08:00
2014-07-08 10:07:00 +08:00
if ( qualifier = = ' l ' & & * format = = ' l ' ) {
qualifier = ' L ' ;
+ + format ;
}
}
switch ( * format ) {
case ' % ' :
pos = acpi_ut_bound_string_output ( pos , end , ' % ' ) ;
continue ;
case ' c ' :
if ( ! ( type & ACPI_FORMAT_LEFT ) ) {
while ( - - width > 0 ) {
pos =
acpi_ut_bound_string_output ( pos ,
end ,
' ' ) ;
}
}
2014-07-08 10:08:13 +08:00
2014-07-08 10:07:00 +08:00
c = ( char ) va_arg ( args , int ) ;
pos = acpi_ut_bound_string_output ( pos , end , c ) ;
2014-07-08 10:08:13 +08:00
2014-07-08 10:07:00 +08:00
while ( - - width > 0 ) {
pos =
acpi_ut_bound_string_output ( pos , end , ' ' ) ;
}
continue ;
case ' s ' :
s = va_arg ( args , char * ) ;
if ( ! s ) {
s = " <NULL> " ;
}
2017-08-03 14:27:03 +08:00
length = ( s32 ) acpi_ut_bound_string_length ( s , precision ) ;
2014-07-08 10:07:00 +08:00
if ( ! ( type & ACPI_FORMAT_LEFT ) ) {
while ( length < width - - ) {
pos =
acpi_ut_bound_string_output ( pos ,
end ,
' ' ) ;
}
}
2015-12-29 13:54:36 +08:00
2014-07-08 10:07:00 +08:00
for ( i = 0 ; i < length ; + + i ) {
pos = acpi_ut_bound_string_output ( pos , end , * s ) ;
+ + s ;
}
2015-12-29 13:54:36 +08:00
2014-07-08 10:07:00 +08:00
while ( length < width - - ) {
pos =
acpi_ut_bound_string_output ( pos , end , ' ' ) ;
}
continue ;
case ' o ' :
base = 8 ;
break ;
case ' X ' :
type | = ACPI_FORMAT_UPPER ;
2018-05-08 14:06:09 -07:00
/* FALLTHROUGH */
2014-07-08 10:07:00 +08:00
case ' x ' :
base = 16 ;
break ;
case ' d ' :
case ' i ' :
type | = ACPI_FORMAT_SIGN ;
case ' u ' :
break ;
case ' p ' :
if ( width = = - 1 ) {
width = 2 * sizeof ( void * ) ;
type | = ACPI_FORMAT_ZERO ;
}
2014-07-08 10:08:13 +08:00
2014-07-08 10:07:00 +08:00
p = va_arg ( args , void * ) ;
2015-12-29 13:54:36 +08:00
pos =
acpi_ut_format_number ( pos , end , ACPI_TO_INTEGER ( p ) ,
16 , width , precision , type ) ;
2014-07-08 10:07:00 +08:00
continue ;
default :
pos = acpi_ut_bound_string_output ( pos , end , ' % ' ) ;
if ( * format ) {
pos =
acpi_ut_bound_string_output ( pos , end ,
* format ) ;
} else {
- - format ;
}
continue ;
}
if ( qualifier = = ' L ' ) {
number = va_arg ( args , u64 ) ;
if ( type & ACPI_FORMAT_SIGN ) {
2016-05-05 12:57:53 +08:00
number = ( s64 ) number ;
2014-07-08 10:07:00 +08:00
}
} else if ( qualifier = = ' l ' ) {
number = va_arg ( args , unsigned long ) ;
if ( type & ACPI_FORMAT_SIGN ) {
2016-05-05 12:57:53 +08:00
number = ( s32 ) number ;
2014-07-08 10:07:00 +08:00
}
} else if ( qualifier = = ' h ' ) {
number = ( u16 ) va_arg ( args , int ) ;
if ( type & ACPI_FORMAT_SIGN ) {
2016-05-05 12:57:53 +08:00
number = ( s16 ) number ;
2014-07-08 10:07:00 +08:00
}
} else {
number = va_arg ( args , unsigned int ) ;
if ( type & ACPI_FORMAT_SIGN ) {
number = ( signed int ) number ;
}
}
2014-07-08 10:08:13 +08:00
2014-07-08 10:07:00 +08:00
pos = acpi_ut_format_number ( pos , end , number , base ,
width , precision , type ) ;
}
if ( size > 0 ) {
if ( pos < end ) {
* pos = ' \0 ' ;
} else {
end [ - 1 ] = ' \0 ' ;
}
}
2017-08-03 14:27:03 +08:00
return ( ( int ) ACPI_PTR_DIFF ( pos , string ) ) ;
2014-07-08 10:07:00 +08:00
}
/*******************************************************************************
*
2016-08-04 16:45:06 +08:00
* FUNCTION : snprintf
2014-07-08 10:07:00 +08:00
*
* PARAMETERS : string - String with boundary
* size - Boundary of the string
* Format , . . . - Standard printf format
*
2014-07-08 10:08:13 +08:00
* RETURN : Number of bytes actually written .
2014-07-08 10:07:00 +08:00
*
* DESCRIPTION : Formatted output to a string .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-08-04 16:45:06 +08:00
int snprintf ( char * string , acpi_size size , const char * format , . . . )
2014-07-08 10:07:00 +08:00
{
va_list args ;
int length ;
va_start ( args , format ) ;
2016-08-04 16:45:06 +08:00
length = vsnprintf ( string , size , format , args ) ;
va_end ( args ) ;
return ( length ) ;
}
/*******************************************************************************
*
* FUNCTION : sprintf
*
* PARAMETERS : string - String with boundary
* Format , . . . - Standard printf format
*
* RETURN : Number of bytes actually written .
*
* DESCRIPTION : Formatted output to a string .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sprintf ( char * string , const char * format , . . . )
{
va_list args ;
int length ;
va_start ( args , format ) ;
length = vsnprintf ( string , ACPI_UINT32_MAX , format , args ) ;
2014-07-08 10:07:00 +08:00
va_end ( args ) ;
return ( length ) ;
}
# ifdef ACPI_APPLICATION
/*******************************************************************************
*
2016-08-04 16:45:06 +08:00
* FUNCTION : vprintf
*
* PARAMETERS : format - Standard printf format
* args - Argument list
*
* RETURN : Number of bytes actually written .
*
* DESCRIPTION : Formatted output to stdout using argument list pointer .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int vprintf ( const char * format , va_list args )
{
acpi_cpu_flags flags ;
int length ;
flags = acpi_os_acquire_lock ( acpi_gbl_print_lock ) ;
length = vsnprintf ( acpi_gbl_print_buffer ,
sizeof ( acpi_gbl_print_buffer ) , format , args ) ;
2016-08-04 16:45:13 +08:00
( void ) fwrite ( acpi_gbl_print_buffer , length , 1 , ACPI_FILE_OUT ) ;
2016-08-04 16:45:06 +08:00
acpi_os_release_lock ( acpi_gbl_print_lock , flags ) ;
return ( length ) ;
}
/*******************************************************************************
*
* FUNCTION : printf
*
* PARAMETERS : Format , . . . - Standard printf format
*
* RETURN : Number of bytes actually written .
*
* DESCRIPTION : Formatted output to stdout .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int printf ( const char * format , . . . )
{
va_list args ;
int length ;
va_start ( args , format ) ;
length = vprintf ( format , args ) ;
va_end ( args ) ;
return ( length ) ;
}
/*******************************************************************************
*
* FUNCTION : vfprintf
2014-07-08 10:07:00 +08:00
*
* PARAMETERS : file - File descriptor
* format - Standard printf format
* args - Argument list
*
2014-07-08 10:08:13 +08:00
* RETURN : Number of bytes actually written .
2014-07-08 10:07:00 +08:00
*
* DESCRIPTION : Formatted output to a file using argument list pointer .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-08-04 16:45:06 +08:00
int vfprintf ( FILE * file , const char * format , va_list args )
2014-07-08 10:07:00 +08:00
{
acpi_cpu_flags flags ;
int length ;
flags = acpi_os_acquire_lock ( acpi_gbl_print_lock ) ;
2016-08-04 16:45:06 +08:00
length = vsnprintf ( acpi_gbl_print_buffer ,
sizeof ( acpi_gbl_print_buffer ) , format , args ) ;
2014-07-08 10:08:13 +08:00
2016-08-04 16:45:13 +08:00
( void ) fwrite ( acpi_gbl_print_buffer , length , 1 , file ) ;
2014-07-08 10:07:00 +08:00
acpi_os_release_lock ( acpi_gbl_print_lock , flags ) ;
return ( length ) ;
}
/*******************************************************************************
*
2016-08-04 16:45:06 +08:00
* FUNCTION : fprintf
2014-07-08 10:07:00 +08:00
*
* PARAMETERS : file - File descriptor
* Format , . . . - Standard printf format
*
2014-07-08 10:08:13 +08:00
* RETURN : Number of bytes actually written .
2014-07-08 10:07:00 +08:00
*
* DESCRIPTION : Formatted output to a file .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-08-04 16:45:06 +08:00
int fprintf ( FILE * file , const char * format , . . . )
2014-07-08 10:07:00 +08:00
{
va_list args ;
int length ;
va_start ( args , format ) ;
2016-08-04 16:45:06 +08:00
length = vfprintf ( file , format , args ) ;
2014-07-08 10:07:00 +08:00
va_end ( args ) ;
return ( length ) ;
}
# endif