URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/rtos/ecos-2.0/packages/language/c/libc/stdio/v2_0/src/output
- from Rev 27 to Rev 174
- ↔ Reverse comparison
Rev 27 → Rev 174
/fwrite.cxx
0,0 → 1,103
//======================================================================== |
// |
// fwrite.cxx |
// |
// ANSI Stdio fwrite() function |
// |
//======================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//======================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): jlarmour |
// Contributors: |
// Date: 2000-04-20 |
// Purpose: |
// Description: |
// Usage: |
// |
//####DESCRIPTIONEND#### |
// |
//======================================================================== |
|
// CONFIGURATION |
|
#include <pkgconf/libc_stdio.h> // Configuration header |
|
// INCLUDES |
|
#include <cyg/infra/cyg_type.h> // Common project-wide type definitions |
#include <cyg/infra/cyg_ass.h> // Assertion support |
#include <cyg/infra/cyg_trac.h> // Tracing support |
#include <stddef.h> // NULL and size_t from compiler |
#include <stdio.h> // header for this file |
#include <errno.h> // error codes |
#include <cyg/libc/stdio/stream.hxx>// Cyg_StdioStream |
|
// FUNCTIONS |
|
externC size_t |
fwrite( const void *ptr, size_t object_size, size_t num_objects, |
FILE *stream ) |
{ |
Cyg_StdioStream *real_stream = (Cyg_StdioStream *)stream; |
cyg_ucount32 written; |
Cyg_ErrNo err; |
|
CYG_REPORT_FUNCNAMETYPE( "fwrite", "wrote %d objects" ); |
CYG_REPORT_FUNCARG4( "ptr=%08x, object_size=%d, num_objects=%d, " |
"stream=%08x", ptr, object_size, num_objects, |
stream ); |
|
if ( (object_size==0) || (num_objects==0) ) { |
CYG_REPORT_RETVAL(0); |
return 0; |
} // if |
|
err = real_stream->write( (cyg_uint8 *)ptr, num_objects*object_size, |
&written ); |
|
if (err) { |
real_stream->set_error( err ); |
errno = err; |
} // if |
|
// we return the number of _objects_ written. Simple division is |
// sufficient as this returns the quotient rather than rounding |
|
CYG_REPORT_RETVAL( written/object_size ); |
return written/object_size; |
} // fwrite() |
|
// EOF fwrite.cxx |
/fputc.cxx
0,0 → 1,116
//=========================================================================== |
// |
// fputc.cxx |
// |
// ISO Standard I/O character output functions |
// |
//=========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//=========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): jlarmour |
// Contributors: |
// Date: 2000-04-20 |
// Purpose: Provide the fputc() function. Also provides the function |
// versions of putc() and putchar() |
// Description: |
// Usage: |
// |
//####DESCRIPTIONEND#### |
// |
//=========================================================================== |
|
// CONFIGURATION |
|
#include <pkgconf/libc_stdio.h> // Configuration header |
|
// INCLUDES |
|
#include <cyg/infra/cyg_type.h> // Common project-wide type definitions |
#include <cyg/infra/cyg_ass.h> // Standard eCos assertion support |
#include <cyg/infra/cyg_trac.h> // Standard eCos tracing support |
#include <stddef.h> // NULL and size_t from compiler |
#include <stdio.h> // header for this file |
#include <errno.h> // error codes |
#include <cyg/libc/stdio/stream.hxx>// Cyg_StdioStream |
|
// FUNCTIONS |
|
externC int |
fputc( int c, FILE *stream ) |
{ |
Cyg_StdioStream *real_stream = (Cyg_StdioStream *)stream; |
Cyg_ErrNo err; |
cyg_uint8 real_c = (cyg_uint8) c; |
|
CYG_REPORT_FUNCNAMETYPE("fputc", "wrote char %d"); |
CYG_REPORT_FUNCARG2( "c = %d, stream=%08x", c, stream ); |
|
CYG_CHECK_DATA_PTR( stream, "stream is not a valid pointer" ); |
|
err = real_stream->write_byte( real_c ); |
|
if (err) |
{ |
real_stream->set_error( err ); |
errno = err; |
CYG_REPORT_RETVAL(EOF); |
return EOF; |
} // if |
|
CYG_REPORT_RETVAL((int)real_c); |
return (int)real_c; |
|
} // fputc() |
|
|
// Also define putchar() even though it can be a macro. |
// Undefine the macro first though |
#undef putchar |
|
externC int |
putchar( int c ) |
{ |
return fputc( c, stdout ); |
} // putchar() |
|
// Also define putc() even though it can be a macro. |
// Undefine the macro first though |
#undef putc |
|
externC int |
putc( int, FILE * ) CYGBLD_ATTRIB_WEAK_ALIAS(fputc); |
|
// EOF fputc.cxx |
/fputs.cxx
0,0 → 1,90
//======================================================================== |
// |
// fputs.cxx |
// |
// ANSI Stdio fputs() function |
// |
//======================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//======================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): jlarmour |
// Contributors: |
// Date: 2000-04-20 |
// Purpose: |
// Description: |
// Usage: |
// |
//####DESCRIPTIONEND#### |
// |
//======================================================================== |
|
// CONFIGURATION |
|
#include <pkgconf/libc_stdio.h> // Configuration header |
|
// INCLUDES |
|
#include <cyg/infra/cyg_type.h> // Common project-wide type definitions |
#include <stddef.h> // NULL and size_t from compiler |
#include <stdio.h> // header for this file |
#include <errno.h> // error codes |
#include <cyg/libc/stdio/stream.hxx>// Cyg_StdioStream |
#include <string.h> // strlen() |
|
// FUNCTIONS |
|
externC int |
fputs( const char *s, FILE *stream ) |
{ |
Cyg_StdioStream *real_stream = (Cyg_StdioStream *)stream; |
cyg_ucount32 size = strlen(s); |
cyg_ucount32 written; |
Cyg_ErrNo err; |
|
err = real_stream->write( (cyg_uint8 *)s, size, &written ); |
|
if (err) { |
real_stream->set_error( err ); |
errno = err; |
return EOF; |
} // if |
|
|
return written; |
|
} // fputs() |
|
// EOF fputs.cxx |
/printf.cxx
0,0 → 1,82
//=========================================================================== |
// |
// printf.cxx |
// |
// ANSI Stdio printf() function |
// |
//=========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//=========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): jlarmour |
// Contributors: |
// Date: 2000-04-20 |
// Purpose: |
// Description: |
// Usage: |
// |
//####DESCRIPTIONEND#### |
// |
//=========================================================================== |
|
// CONFIGURATION |
|
#include <pkgconf/libc_stdio.h> // Configuration header |
|
// INCLUDES |
|
#include <cyg/infra/cyg_type.h> // Common project-wide type definitions |
#include <stddef.h> // NULL and size_t from compiler |
#include <stdio.h> // header for this file |
#include <limits.h> // INT_MAX |
|
// FUNCTIONS |
|
externC int |
printf( const char *format, ... ) |
{ |
int rc; // return code |
va_list ap; // for variable args |
|
va_start(ap, format); // init specifying last non-var arg |
|
rc = vfnprintf(stdout, INT_MAX, format, ap); |
|
va_end(ap); // end var args |
|
return rc; |
} // printf() |
|
// EOF printf.cxx |
/fnprintf.cxx
0,0 → 1,81
//=========================================================================== |
// |
// fnprintf.cxx |
// |
// ANSI Stdio fnprintf() function |
// |
//=========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//=========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): jlarmour |
// Contributors: |
// Date: 2000-04-20 |
// Purpose: |
// Description: |
// Usage: |
// |
//####DESCRIPTIONEND#### |
// |
//=========================================================================== |
|
// CONFIGURATION |
|
#include <pkgconf/libc_stdio.h> // Configuration header |
|
// INCLUDES |
|
#include <cyg/infra/cyg_type.h> // Common project-wide type definitions |
#include <stddef.h> // NULL and size_t from compiler |
#include <stdio.h> // header for this file |
|
// FUNCTIONS |
|
externC int |
fnprintf( FILE *stream, size_t size, const char *format, ... ) |
{ |
int rc; // return code |
va_list ap; // for variable args |
|
va_start(ap, format); // init specifying last non-var arg |
|
rc = vfnprintf(stream, size, format, ap); |
|
va_end(ap); // end var args |
|
return rc; |
} // fnprintf() |
|
// EOF fnprintf.cxx |
/fprintf.cxx
0,0 → 1,82
//=========================================================================== |
// |
// fprintf.cxx |
// |
// ANSI Stdio fprintf() function |
// |
//=========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//=========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): jlarmour |
// Contributors: |
// Date: 2000-04-20 |
// Purpose: |
// Description: |
// Usage: |
// |
//####DESCRIPTIONEND#### |
// |
//=========================================================================== |
|
// CONFIGURATION |
|
#include <pkgconf/libc_stdio.h> // Configuration header |
|
// INCLUDES |
|
#include <cyg/infra/cyg_type.h> // Common project-wide type definitions |
#include <stddef.h> // NULL and size_t from compiler |
#include <stdio.h> // header for this file |
#include <limits.h> // INT_MAX |
|
// FUNCTIONS |
|
externC int |
fprintf( FILE *stream, const char *format, ... ) |
{ |
int rc; // return code |
va_list ap; // for variable args |
|
va_start(ap, format); // init specifying last non-var arg |
|
rc = vfnprintf(stream, INT_MAX, format, ap); |
|
va_end(ap); // end var args |
|
return rc; |
} // fprintf() |
|
// EOF fprintf.cxx |
/vfnprintf.cxx
0,0 → 1,966
//=========================================================================== |
// |
// vfnprintf.c |
// |
// I/O routines for vfnprintf() for use with ANSI C library |
// |
//=========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//=========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): jlarmour |
// Contributors: |
// Date: 2000-04-20 |
// Purpose: |
// Description: |
// Usage: |
// |
//####DESCRIPTIONEND#### |
// |
//=========================================================================== |
// |
// This code is based on original code with the following copyright: |
// |
/*- |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
|
|
// CONFIGURATION |
|
#include <pkgconf/libc_stdio.h> // Configuration header |
#include <pkgconf/libc_i18n.h> // Configuration header for mb support |
|
// INCLUDES |
|
#include <cyg/infra/cyg_type.h> // Common type definitions and support |
#include <stdarg.h> // Variable argument definitions |
#include <stdio.h> // Standard header for all stdio files |
#include <string.h> // memchr() and strlen() functions |
#include <cyg/libc/stdio/stream.hxx> // C library streams |
|
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
|
# include <float.h> // for DBL_DIG etc. below |
# include <math.h> // for modf() |
# include <sys/ieeefp.h> // Cyg_libm_ieee_double_shape_type |
|
# define MAXFRACT DBL_DIG |
# define MAXEXP DBL_MAX_10_EXP |
|
# define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ |
# define DEFPREC 6 |
|
static int |
cvt( double, int, int, char *, int, char *, char * ); |
|
#else // ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
|
# define BUF 40 |
|
#endif // ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
|
/* |
* Actual printf innards. |
* |
* This code is large and complicated... |
*/ |
|
#ifdef CYGINT_LIBC_I18N_MB_REQUIRED |
typedef int (*mbtowc_fn_type)(wchar_t *, const char *, size_t, int *); |
externC mbtowc_fn_type __get_current_locale_mbtowc_fn(); |
#endif |
|
/* |
* Macros for converting digits to letters and vice versa |
*/ |
#define to_digit(c) ((c) - '0') |
#define is_digit(c) ((unsigned)to_digit(c) <= 9) |
#define to_char(n) ((n) + '0') |
|
/* |
* Flags used during conversion. |
*/ |
#define ALT 0x001 /* alternate form */ |
#define HEXPREFIX 0x002 /* add 0x or 0X prefix */ |
#define LADJUST 0x004 /* left adjustment */ |
#define LONGDBL 0x008 /* long double; unimplemented */ |
#define LONGINT 0x010 /* long integer */ |
#define QUADINT 0x020 /* quad integer */ |
#define SHORTINT 0x040 /* short integer */ |
#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ |
#define FPT 0x100 /* Floating point number */ |
#define SIZET 0x200 /* size_t */ |
|
externC int |
vfnprintf ( FILE *stream, size_t n, const char *format, va_list arg) |
{ |
char *fmt; /* format string */ |
int ch; /* character from fmt */ |
int x, y; /* handy integers (short term usage) */ |
char *cp; /* handy char pointer (short term usage) */ |
int flags; /* flags as above */ |
|
#ifdef CYGINT_LIBC_I18N_MB_REQUIRED |
int state = 0; /* state for mbtowc conversion */ |
mbtowc_fn_type mbtowc_fn; |
#endif |
|
int ret; /* return value accumulator */ |
int width; /* width from format (%8d), or 0 */ |
int prec; /* precision from format (%.3d), or -1 */ |
char sign; /* sign prefix (' ', '+', '-', or \0) */ |
wchar_t wc; |
|
#define quad_t long long |
#define u_quad_t unsigned long long |
|
u_quad_t _uquad; /* integer arguments %[diouxX] */ |
enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ |
int dprec; /* a copy of prec if [diouxX], 0 otherwise */ |
int fieldsz; /* field size expanded by sign, etc */ |
int realsz; /* field size expanded by dprec */ |
int size; /* size of converted field or string */ |
char *xdigs; /* digits for [xX] conversion */ |
#define NIOV 8 |
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ |
char ox[2]; /* space for 0x hex-prefix */ |
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
char softsign; /* temporary negative sign for floats */ |
double _double; /* double precision arguments %[eEfgG] */ |
int fpprec; /* `extra' floating precision in [eEfgG] */ |
#endif |
|
/* |
* Choose PADSIZE to trade efficiency vs. size. If larger printf |
* fields occur frequently, increase PADSIZE and make the initialisers |
* below longer. |
*/ |
#define PADSIZE 16 /* pad chunk size */ |
static char blanks[PADSIZE] = |
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; |
static char zeroes[PADSIZE] = |
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; |
|
#define MIN(a, b) ((a) < (b) ? (a) : (b)) |
|
/* |
* BEWARE, these `goto error' on error, and PAD uses `n'. |
*/ |
#define PRINT(ptr, len) \ |
CYG_MACRO_START \ |
cyg_ucount32 length = MIN( (cyg_ucount32) len, n - ret - 1); \ |
if (((Cyg_StdioStream *)stream)->write( (const cyg_uint8 *)ptr, \ |
length, &length )) \ |
goto error; \ |
if (length < (cyg_ucount32)len) { \ |
ret += length; \ |
goto done; \ |
} \ |
CYG_MACRO_END |
|
|
#define PAD(howmany, with) \ |
CYG_MACRO_START \ |
if ((x = (howmany)) > 0) { \ |
while (x > PADSIZE) { \ |
PRINT(with, PADSIZE); \ |
x -= PADSIZE; \ |
} \ |
PRINT(with, x); \ |
} \ |
CYG_MACRO_END |
|
/* |
* To extend shorts properly, we need both signed and unsigned |
* argument extraction methods. |
*/ |
|
#define SARG() \ |
(flags&QUADINT ? va_arg(arg, cyg_int64) : \ |
flags&LONGINT ? va_arg(arg, long) : \ |
flags&SHORTINT ? (long)(short)va_arg(arg, int) : \ |
flags&SIZET ? va_arg(arg, size_t) : \ |
(long)va_arg(arg, int)) |
#define UARG() \ |
(flags&QUADINT ? va_arg(arg, cyg_uint64) : \ |
flags&LONGINT ? va_arg(arg, unsigned long) : \ |
flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(arg, int) : \ |
flags&SIZET ? va_arg(arg, size_t) : \ |
(unsigned long)va_arg(arg, unsigned int)) |
|
|
xdigs = NULL; // stop compiler whinging |
fmt = (char *)format; |
ret = 0; |
#ifdef CYGINT_LIBC_I18N_MB_REQUIRED |
mbtowc_fn = __get_current_locale_mbtowc_fn(); |
#endif |
|
/* |
* Scan the format for conversions (`%' character). |
*/ |
for (;;) { |
cp = (char *)fmt; |
#ifndef CYGINT_LIBC_I18N_MB_REQUIRED |
while ((x = ((wc = *fmt) != 0))) { |
#else |
while ((x = mbtowc_fn (&wc, fmt, MB_CUR_MAX, &state)) > 0) { |
#endif |
fmt += x; |
if (wc == '%') { |
fmt--; |
break; |
} |
} |
if ((y = fmt - cp) != 0) { |
PRINT(cp, y); |
ret += y; |
} |
if ((x <= 0) || (ret >= (int)n)) // @@@ this check with n isn't good enough |
goto done; |
fmt++; /* skip over '%' */ |
|
flags = 0; |
dprec = 0; |
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
fpprec = 0; |
#endif |
width = 0; |
prec = -1; |
sign = '\0'; |
|
rflag: ch = *fmt++; |
reswitch: switch (ch) { |
case ' ': |
/* |
* ``If the space and + flags both appear, the space |
* flag will be ignored.'' |
* -- ANSI X3J11 |
*/ |
if (!sign) |
sign = ' '; |
goto rflag; |
case '#': |
flags |= ALT; |
goto rflag; |
case '*': |
/* |
* ``A negative field width argument is taken as a |
* - flag followed by a positive field width.'' |
* -- ANSI X3J11 |
* They don't exclude field widths read from args. |
*/ |
if ((width = va_arg(arg, int)) >= 0) |
goto rflag; |
width = -width; |
/* FALLTHROUGH */ |
case '-': |
flags |= LADJUST; |
goto rflag; |
case '+': |
sign = '+'; |
goto rflag; |
case '.': |
if ((ch = *fmt++) == '*') { |
x = va_arg(arg, int); |
prec = x < 0 ? -1 : x; |
goto rflag; |
} |
x = 0; |
while (is_digit(ch)) { |
x = 10 * x + to_digit(ch); |
ch = *fmt++; |
} |
prec = x < 0 ? -1 : x; |
goto reswitch; |
case '0': |
/* |
* ``Note that 0 is taken as a flag, not as the |
* beginning of a field width.'' |
* -- ANSI X3J11 |
*/ |
flags |= ZEROPAD; |
goto rflag; |
case '1': case '2': case '3': case '4': |
case '5': case '6': case '7': case '8': case '9': |
x = 0; |
do { |
x = 10 * x + to_digit(ch); |
ch = *fmt++; |
} while (is_digit(ch)); |
width = x; |
goto reswitch; |
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
case 'L': |
flags |= LONGDBL; |
goto rflag; |
#endif |
case 'h': |
flags |= SHORTINT; |
goto rflag; |
case 'l': |
if (*fmt == 'l') { |
fmt++; |
flags |= QUADINT; |
} else { |
flags |= LONGINT; |
} |
goto rflag; |
case 'q': |
flags |= QUADINT; |
goto rflag; |
case 'c': |
*(cp = buf) = va_arg(arg, int); |
size = 1; |
sign = '\0'; |
break; |
case 'D': |
flags |= LONGINT; |
/*FALLTHROUGH*/ |
case 'd': |
case 'i': |
_uquad = SARG(); |
#ifndef _NO_LONGLONG |
if ((quad_t)_uquad < 0) |
#else |
if ((long) _uquad < 0) |
#endif |
{ |
|
_uquad = -_uquad; |
sign = '-'; |
} |
base = DEC; |
goto number; |
|
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
case 'e': |
case 'E': |
case 'f': |
case 'g': |
case 'G': |
_double = va_arg(arg, double); |
/* |
* don't do unrealistic precision; just pad it with |
* zeroes later, so buffer size stays rational. |
*/ |
if (prec > MAXFRACT) { |
if ((ch != 'g' && ch != 'G') || (flags&ALT)) |
fpprec = prec - MAXFRACT; |
prec = MAXFRACT; |
} else if (prec == -1) |
prec = DEFPREC; |
/* |
* cvt may have to round up before the "start" of |
* its buffer, i.e. ``intf("%.2f", (double)9.999);''; |
* if the first character is still NUL, it did. |
* softsign avoids negative 0 if _double < 0 but |
* no significant digits will be shown. |
*/ |
cp = buf; |
*cp = '\0'; |
size = cvt(_double, prec, flags, &softsign, ch, |
cp, buf + sizeof(buf)); |
if (softsign) |
sign = '-'; |
if (*cp == '\0') |
cp++; |
break; |
#else |
case 'e': |
case 'E': |
case 'f': |
case 'g': |
case 'G': |
// Output nothing at all |
(void) va_arg(arg, double); // take off arg anyway |
cp = ""; |
size = 0; |
sign = '\0'; |
break; |
|
|
#endif // ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
|
case 'n': |
#ifndef _NO_LONGLONG |
if (flags & QUADINT) |
*va_arg(arg, quad_t *) = ret; |
else |
#endif |
if (flags & LONGINT) |
*va_arg(arg, long *) = ret; |
else if (flags & SHORTINT) |
*va_arg(arg, short *) = ret; |
else if (flags & SIZET) |
*va_arg(arg, size_t *) = ret; |
else |
*va_arg(arg, int *) = ret; |
continue; /* no output */ |
case 'O': |
flags |= LONGINT; |
/*FALLTHROUGH*/ |
case 'o': |
_uquad = UARG(); |
base = OCT; |
goto nosign; |
case 'p': |
/* |
* ``The argument shall be a pointer to void. The |
* value of the pointer is converted to a sequence |
* of printable characters, in an implementation- |
* defined manner.'' |
* -- ANSI X3J11 |
*/ |
/* NOSTRICT */ |
_uquad = (unsigned long)va_arg(arg, void *); |
base = HEX; |
xdigs = "0123456789abcdef"; |
flags |= HEXPREFIX; |
ch = 'x'; |
goto nosign; |
case 's': |
if ((cp = va_arg(arg, char *)) == NULL) |
cp = "(null)"; |
if (prec >= 0) { |
/* |
* can't use strlen; can only look for the |
* NUL in the first `prec' characters, and |
* strlen() will go further. |
*/ |
char *p = (char *)memchr(cp, 0, prec); |
|
if (p != NULL) { |
size = p - cp; |
if (size > prec) |
size = prec; |
} else |
size = prec; |
} else |
size = strlen(cp); |
sign = '\0'; |
break; |
case 'U': |
flags |= LONGINT; |
/*FALLTHROUGH*/ |
case 'u': |
_uquad = UARG(); |
base = DEC; |
goto nosign; |
case 'X': |
xdigs = "0123456789ABCDEF"; |
goto hex; |
case 'x': |
xdigs = "0123456789abcdef"; |
hex: _uquad = UARG(); |
base = HEX; |
/* leading 0x/X only if non-zero */ |
if (flags & ALT && _uquad != 0) |
flags |= HEXPREFIX; |
|
/* unsigned conversions */ |
nosign: sign = '\0'; |
/* |
* ``... diouXx conversions ... if a precision is |
* specified, the 0 flag will be ignored.'' |
* -- ANSI X3J11 |
*/ |
number: if ((dprec = prec) >= 0) |
flags &= ~ZEROPAD; |
|
/* |
* ``The result of converting a zero value with an |
* explicit precision of zero is no characters.'' |
* -- ANSI X3J11 |
*/ |
cp = buf + BUF; |
if (_uquad != 0 || prec != 0) { |
/* |
* Unsigned mod is hard, and unsigned mod |
* by a constant is easier than that by |
* a variable; hence this switch. |
*/ |
switch (base) { |
case OCT: |
do { |
*--cp = to_char(_uquad & 7); |
_uquad >>= 3; |
} while (_uquad); |
/* handle octal leading 0 */ |
if (flags & ALT && *cp != '0') |
*--cp = '0'; |
break; |
|
case DEC: |
/* many numbers are 1 digit */ |
while (_uquad >= 10) { |
*--cp = to_char(_uquad % 10); |
_uquad /= 10; |
} |
*--cp = to_char(_uquad); |
break; |
|
case HEX: |
do { |
*--cp = xdigs[_uquad & 15]; |
_uquad >>= 4; |
} while (_uquad); |
break; |
|
default: |
cp = "bug in vfprintf: bad base"; |
size = strlen(cp); |
goto skipsize; |
} |
} |
size = buf + BUF - cp; |
skipsize: |
break; |
case 'z': |
flags |= SIZET; |
goto rflag; |
default: /* "%?" prints ?, unless ? is NUL */ |
if (ch == '\0') |
goto done; |
/* pretend it was %c with argument ch */ |
cp = buf; |
*cp = ch; |
size = 1; |
sign = '\0'; |
break; |
} |
|
/* |
* All reasonable formats wind up here. At this point, `cp' |
* points to a string which (if not flags&LADJUST) should be |
* padded out to `width' places. If flags&ZEROPAD, it should |
* first be prefixed by any sign or other prefix; otherwise, |
* it should be blank padded before the prefix is emitted. |
* After any left-hand padding and prefixing, emit zeroes |
* required by a decimal [diouxX] precision, then print the |
* string proper, then emit zeroes required by any leftover |
* floating precision; finally, if LADJUST, pad with blanks. |
* |
* Compute actual size, so we know how much to pad. |
* fieldsz excludes decimal prec; realsz includes it. |
*/ |
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
fieldsz = size + fpprec; |
#else |
fieldsz = size; |
#endif |
if (sign) |
fieldsz++; |
else if (flags & HEXPREFIX) |
fieldsz+= 2; |
realsz = dprec > fieldsz ? dprec : fieldsz; |
|
/* right-adjusting blank padding */ |
if ((flags & (LADJUST|ZEROPAD)) == 0) { |
if (width - realsz > 0) { |
PAD(width - realsz, blanks); |
ret += width - realsz; |
} |
} |
|
/* prefix */ |
if (sign) { |
PRINT(&sign, 1); |
ret++; |
} else if (flags & HEXPREFIX) { |
ox[0] = '0'; |
ox[1] = ch; |
PRINT(ox, 2); |
ret += 2; |
} |
|
/* right-adjusting zero padding */ |
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) { |
if (width - realsz > 0) { |
PAD(width - realsz, zeroes); |
ret += width - realsz; |
} |
} |
|
if (dprec - fieldsz > 0) { |
/* leading zeroes from decimal precision */ |
PAD(dprec - fieldsz, zeroes); |
ret += dprec - fieldsz; |
} |
|
/* the string or number proper */ |
PRINT(cp, size); |
ret += size; |
|
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
/* trailing f.p. zeroes */ |
PAD(fpprec, zeroes); |
ret += fpprec; |
#endif |
|
/* left-adjusting padding (always blank) */ |
if (flags & LADJUST) { |
if (width - realsz > 0) { |
PAD(width - realsz, blanks); |
ret += width - realsz; |
} |
} |
|
} |
done: |
error: |
return (((Cyg_StdioStream *) stream)->get_error() ? EOF : ret); |
/* NOTREACHED */ |
} |
|
|
#ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
|
static char * |
round(double fract, int *exp, char *start, char *end, char ch, char *signp) |
{ |
double tmp; |
|
if (fract) |
(void)modf(fract * 10, &tmp); |
else |
tmp = to_digit(ch); |
if (tmp > 4) |
for (;; --end) { |
if (*end == '.') |
--end; |
if (++*end <= '9') |
break; |
*end = '0'; |
if (end == start) { |
if (exp) { /* e/E; increment exponent */ |
*end = '1'; |
++*exp; |
} |
else { /* f; add extra digit */ |
*--end = '1'; |
--start; |
} |
break; |
} |
} |
/* ``"%.3f", (double)-0.0004'' gives you a negative 0. */ |
else if (*signp == '-') |
for (;; --end) { |
if (*end == '.') |
--end; |
if (*end != '0') |
break; |
if (end == start) |
*signp = 0; |
} |
return (start); |
} // round() |
|
|
static char * |
exponent(char *p, int exp, int fmtch) |
{ |
char *t; |
char expbuf[MAXEXP]; |
|
*p++ = fmtch; |
if (exp < 0) { |
exp = -exp; |
*p++ = '-'; |
} |
else |
*p++ = '+'; |
t = expbuf + MAXEXP; |
if (exp > 9) { |
do { |
*--t = to_char(exp % 10); |
} while ((exp /= 10) > 9); |
*--t = to_char(exp); |
for (; t < expbuf + MAXEXP; *p++ = *t++); |
} |
else { |
*p++ = '0'; |
*p++ = to_char(exp); |
} |
return (p); |
} // exponent() |
|
|
static int |
cvt(double number, int prec, int flags, char *signp, int fmtch, char *startp, |
char *endp) |
{ |
Cyg_libm_ieee_double_shape_type ieeefp; |
char *t = startp; |
|
ieeefp.value = number; |
*signp = 0; |
if ( ieeefp.number.sign ){ // this checks for <0.0 and -0.0 |
number = -number; |
*signp = '-'; |
} |
|
if (finite(number)) { |
char *p; |
double fract; |
int dotrim, expcnt, gformat; |
double integer, tmp; |
|
dotrim = expcnt = gformat = 0; |
fract = modf(number, &integer); |
|
/* get an extra slot for rounding. */ |
t = ++startp; |
|
/* |
* get integer portion of number; put into the end of the buffer; the |
* .01 is added for modf(356.0 / 10, &integer) returning .59999999... |
*/ |
for (p = endp - 1; integer; ++expcnt) { |
tmp = modf(integer / 10, &integer); |
*p-- = to_char((int)((tmp + .01) * 10)); |
} |
switch (fmtch) { |
case 'f': |
/* reverse integer into beginning of buffer */ |
if (expcnt) |
for (; ++p < endp; *t++ = *p); |
else |
*t++ = '0'; |
/* |
* if precision required or alternate flag set, add in a |
* decimal point. |
*/ |
if (prec || flags&ALT) |
*t++ = '.'; |
/* if requires more precision and some fraction left */ |
if (fract) { |
if (prec) |
do { |
fract = modf(fract * 10, &tmp); |
*t++ = to_char((int)tmp); |
} while (--prec && fract); |
if (fract) |
startp = round(fract, (int *)NULL, startp, |
t - 1, (char)0, signp); |
} |
for (; prec--; *t++ = '0'); |
break; |
case 'e': |
case 'E': |
eformat: if (expcnt) { |
*t++ = *++p; |
if (prec || flags&ALT) |
*t++ = '.'; |
/* if requires more precision and some integer left */ |
for (; prec && ++p < endp; --prec) |
*t++ = *p; |
/* |
* if done precision and more of the integer component, |
* round using it; adjust fract so we don't re-round |
* later. |
*/ |
if (!prec && ++p < endp) { |
fract = 0; |
startp = round((double)0, &expcnt, startp, |
t - 1, *p, signp); |
} |
/* adjust expcnt for digit in front of decimal */ |
--expcnt; |
} |
/* until first fractional digit, decrement exponent */ |
else if (fract) { |
/* adjust expcnt for digit in front of decimal */ |
for (expcnt = -1;; --expcnt) { |
fract = modf(fract * 10, &tmp); |
if (tmp) |
break; |
} |
*t++ = to_char((int)tmp); |
if (prec || flags&ALT) |
*t++ = '.'; |
} |
else { |
*t++ = '0'; |
if (prec || flags&ALT) |
*t++ = '.'; |
} |
/* if requires more precision and some fraction left */ |
if (fract) { |
if (prec) |
do { |
fract = modf(fract * 10, &tmp); |
*t++ = to_char((int)tmp); |
} while (--prec && fract); |
if (fract) |
startp = round(fract, &expcnt, startp, |
t - 1, (char)0, signp); |
} |
/* if requires more precision */ |
for (; prec--; *t++ = '0'); |
|
/* unless alternate flag, trim any g/G format trailing 0's */ |
if (gformat && !(flags&ALT)) { |
while (t > startp && *--t == '0'); |
if (*t == '.') |
--t; |
++t; |
} |
t = exponent(t, expcnt, fmtch); |
break; |
case 'g': |
case 'G': |
/* a precision of 0 is treated as a precision of 1. */ |
if (!prec) |
++prec; |
/* |
* ``The style used depends on the value converted; style e |
* will be used only if the exponent resulting from the |
* conversion is less than -4 or greater than the precision.'' |
* -- ANSI X3J11 |
*/ |
if (expcnt > prec || (!expcnt && fract && fract < .0001)) { |
/* |
* g/G format counts "significant digits, not digits of |
* precision; for the e/E format, this just causes an |
* off-by-one problem, i.e. g/G considers the digit |
* before the decimal point significant and e/E doesn't |
* count it as precision. |
*/ |
--prec; |
fmtch -= 2; /* G->E, g->e */ |
gformat = 1; |
goto eformat; |
} |
/* |
* reverse integer into beginning of buffer, |
* note, decrement precision |
*/ |
if (expcnt) |
for (; ++p < endp; *t++ = *p, --prec); |
else |
*t++ = '0'; |
/* |
* if precision required or alternate flag set, add in a |
* decimal point. If no digits yet, add in leading 0. |
*/ |
if (prec || flags&ALT) { |
dotrim = 1; |
*t++ = '.'; |
} |
else |
dotrim = 0; |
/* if requires more precision and some fraction left */ |
if (fract) { |
if (prec) { |
do { |
fract = modf(fract * 10, &tmp); |
*t++ = to_char((int)tmp); |
} while(!tmp); |
while (--prec && fract) { |
fract = modf(fract * 10, &tmp); |
*t++ = to_char((int)tmp); |
} |
} |
if (fract) |
startp = round(fract, (int *)NULL, startp, |
t - 1, (char)0, signp); |
} |
/* alternate format, adds 0's for precision, else trim 0's */ |
if (flags&ALT) |
for (; prec--; *t++ = '0'); |
else if (dotrim) { |
while (t > startp && *--t == '0'); |
if (*t != '.') |
++t; |
} |
} |
} else { |
unsigned case_adj; |
switch (fmtch) { |
case 'f': |
case 'g': |
case 'e': |
case_adj = 'a' - 'A'; |
break; |
default: |
case_adj = 0; |
} |
if (isnan(number)) { |
*t++ = 'N' + case_adj; |
*t++ = 'A' + case_adj; |
*t++ = 'N' + case_adj; |
} else { // infinite |
*t++ = 'I' + case_adj; |
*t++ = 'N' + case_adj; |
*t++ = 'F' + case_adj; |
} |
} |
return (t - startp); |
} // cvt() |
|
#endif // ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT |
|
// EOF vfnprintf.cxx |