| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 | /*  Copyright (C) 2002     Manuel Novoa III *  Header for my stdio library for linux and (soon) elks. * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Library General Public *  License as published by the Free Software Foundation; either *  version 2 of the License, or (at your option) any later version. * *  This library 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 *  Library General Public License for more details. * *  You should have received a copy of the GNU Library General Public *  License along with this library; if not, write to the Free *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//*  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! * *  This code is currently under development.  Also, I plan to port *  it to elks which is a 16-bit environment with a fairly limited *  compiler.  Therefore, please refrain from modifying this code *  and, instead, pass any bug-fixes, etc. to me.  Thanks.  Manuel * *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */#ifndef _STDIO_H#error Always include <stdio.h> rather than <bits/uClibc_stdio.h>#endif/**********************************************************************/#ifdef __UCLIBC__#ifdef __UCLIBC_HAS_THREADS__#define __STDIO_THREADSAFE#endif#ifdef __UCLIBC_HAS_LFS__#define __STDIO_LARGE_FILES#endif /* __UCLIBC_HAS_LFS__ */#ifdef __UCLIBC_HAS_WCHAR__#define __STDIO_WIDE#endif/* Make sure defines related to large files are consistent. */#ifdef _LIBC#ifdef __UCLIBC_HAS_LFS__#undef __USE_LARGEFILE#undef __USE_LARGEFILE64#undef __USE_FILE_OFFSET64/* if we're actually building uClibc with large file support, only define... */#define __USE_LARGEFILE64	1#endif /* __UCLIBC_HAS_LFS__ */#else  /* not _LIBC */#ifndef __UCLIBC_HAS_LFS__#if defined(__LARGEFILE64_SOURCE) || defined(__USE_LARGEFILE64) \    || defined(__USE_FILE_OFFSET64)#error Sorry... uClibc was built without large file support!#endif#endif /* __UCLIBC_HAS_LFS__ */#endif /* _LIBC */#endif /* __UCLIBC__ *//**********************************************************************//* These are the stdio configuration options.  Keep them here until   uClibc's configuration process gets reworked. */#ifdef __STDIO_WIDE#define __need_wchar_t#include <stddef.h>/* Note: we don't really need mbstate for 8-bit locales.  We do for UTF-8. * For now, always use it. */#define __STDIO_MBSTATE#define __need_mbstate_t#include <wchar.h>#endif#define __STDIO_BUFFERS#define __STDIO_GETC_MACRO#define __STDIO_PUTC_MACRO/* For uClibc, these are currently handled above. *//*  #define __STDIO_LARGE_FILES *//*  #define __STDIO_THREADSAFE *//* L mode extension for fopen. */#define __STDIO_FOPEN_LARGEFILE_MODE/* size of builtin buf -- only tested with 0 */#define _STDIO_BUILTIN_BUF_SIZE		0/* TODO - enable features based on __STDIO_GLIBC_FEATURES *//*  #define __STDIO_GLIBC_FEATURES */#define __STDIO_AUTO_RW_TRANSITION#define __STDIO_FOPEN_EXCLUSIVE_MODE#define __STDIO_PRINTF_M_SPEC#define __STDIO_GLIBC_CUSTOM_STREAMS/* ANSI/ISO mandate at least 256. */#define _STDIO_BUFSIZ			256/* Currently unimplemented/untested *//* #define __STDIO_FLEXIBLE_SETVBUF *//**********************************************************************//* TODO -- posix or gnu -- belongs in limits.h and >= 9 for sus *//* NOTE: for us it is currently _always_ 9 *//*#define NL_ARGMAX			9*//**********************************************************************//* These are consistency checks on the different options */#ifndef __STDIO_BUFFERS#undef __STDIO_GETC_MACRO#undef __STDIO_PUTC_MACRO#endif#ifdef __BCC__#undef __STDIO_LARGE_FILES#endif#ifndef __STDIO_LARGE_FILES#undef __STDIO_FOPEN_LARGEFILE_MODE#endif/**********************************************************************/#ifdef __STDIO_THREADSAFE/* Need this for pthread_mutex_t. */#include <bits/pthreadtypes.h>#define __STDIO_THREADLOCK(STREAM) \	if ((STREAM)->user_locking == 0) { \		pthread_mutex_lock(&(STREAM)->lock); \	}#define __STDIO_THREADUNLOCK(STREAM) \	if ((STREAM)->user_locking == 0) { \		pthread_mutex_unlock(&(STREAM)->lock); \	}#define __STDIO_THREADTRYLOCK(STREAM) \	if ((STREAM)->user_locking == 0) { \		pthread_mutex_trylock(&(STREAM)->lock); \	}#else  /* __STDIO_THREADSAFE */#define __STDIO_THREADLOCK(STREAM)#define __STDIO_THREADUNLOCK(STREAM)#define __STDIO_THREADTRYLOCK(STREAM)#endif /* __STDIO_THREADSAFE *//* This file may eventually have two personalities:   1) core stuff (similar to glibc's libio.h)   2) extern inlines (for glibc's bits/stdio.h)   Right now, only (1) is implemented. */#define _STDIO_IOFBF 0	/* Fully buffered.  */#define _STDIO_IOLBF 1	/* Line buffered.  */#define _STDIO_IONBF 2	/* No buffering.  */typedef struct {	__off_t __pos;#ifdef __STDIO_MBSTATE  __mbstate_t __mbstate;#endif} __stdio_fpos_t;#ifdef __STDIO_LARGE_FILEStypedef struct {	__off64_t __pos;#ifdef __STDIO_MBSTATE  __mbstate_t __mbstate;#endif} __stdio_fpos64_t;#endif/**********************************************************************/#ifdef __STDIO_LARGE_FILEStypedef __off64_t __offmax_t;	/* TODO -- rename this? */#elsetypedef __off_t __offmax_t;		/* TODO -- rename this? */#endif/**********************************************************************/#ifdef __STDIO_GLIBC_CUSTOM_STREAMStypedef __ssize_t __io_read_fn(void *cookie,							   char *buf, size_t bufsize);typedef __ssize_t __io_write_fn(void *cookie,								const char *buf, size_t bufsize);/* NOTE: GLIBC difference!!! -- fopencookie seek function * For glibc, the type of pos is always (__off64_t *) but in our case * it is type (__off_t *) when the lib is built without large file support. */typedef int __io_seek_fn(void *cookie,						 __offmax_t *pos, int whence);typedef int __io_close_fn(void *cookie);typedef struct {	__io_read_fn *read;	__io_write_fn *write;	__io_seek_fn *seek;	__io_close_fn *close;} _IO_cookie_io_functions_t;#if defined(_LIBC) || defined(_GNU_SOURCE)typedef __io_read_fn cookie_read_function_t;typedef __io_write_fn cookie_write_function_t;typedef __io_seek_fn cookie_seek_function_t;typedef __io_close_fn cookie_close_function_t;typedef _IO_cookie_io_functions_t cookie_io_functions_t;#endif /* _GNU_SOURCE */#endif /* __STDIO_GLIBC_CUSTOM_STREAMS *//* * ungot scheme: * 0 0   none * 0 1   one user (unused ungot is 1) or one scanf (unused ungot is 0) * 1 0   must be scanf[0] and user[1] * 1 1   illegal -- could be used to signal safe for setbuf */#ifdef __UCLIBC__#define __stdio_file_struct _UC_FILE#endifstruct __stdio_file_struct {	unsigned short modeflags;	/* There could be a hole here, but modeflags is used most.*/#ifdef __STDIO_WIDE	/* TOOD - ungot_width could be combined with ungot.  But what about hole? */	unsigned char ungot_width[2];	wchar_t ungot[2];#else  /* __STDIO_WIDE */	unsigned char ungot[2];#endif /* __STDIO_WIDE */	int filedes;#if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)	struct __stdio_file_struct *nextopen;#endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */#ifdef __STDIO_BUFFERS	unsigned char *bufstart;	/* pointer to buffer */	unsigned char *bufend;		/* pointer to 1 past end of buffer */	unsigned char *bufpos;	unsigned char *bufread;		/* pointer to 1 past last buffered read char. */#ifdef __STDIO_GETC_MACRO	unsigned char *bufgetc;		/* 1 past last readable by getc */#endif /* __STDIO_GETC_MACRO */#ifdef __STDIO_PUTC_MACRO	unsigned char *bufputc;		/* 1 past last writeable by putc */#endif /* __STDIO_PUTC_MACRO */#endif /* __STDIO_BUFFERS */#ifdef __STDIO_GLIBC_CUSTOM_STREAMS	void *cookie;	_IO_cookie_io_functions_t gcs;#endif /* __STDIO_GLIBC_CUSTOM_STREAMS */#ifdef __STDIO_MBSTATE	__mbstate_t state;#endif#ifdef __STDIO_THREADSAFE	int user_locking;	pthread_mutex_t lock;#endif/* Everything after this is unimplemented... and may be trashed. */#if __STDIO_BUILTIN_BUF_SIZE > 0	unsigned char builtinbuf[__STDIO_BUILTIN_BUF_SIZE];#endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */};/***********************************************************************/#define __MASK_UNGOT    	(0x0002|0x0001)#define __MASK_UNGOT1    	0x0001#define __MASK_UNGOT2    	0x0002#define __FLAG_EOF			0x0004	/* EOF reached? */#define __FLAG_ERROR		0x0008	/* stream in error state? */#define __FLAG_WRITEONLY  	0x0010	/* unreadable */#define __FLAG_READONLY  	0x0020	/* unwriteable */#define __FLAG_FREEFILE		0x0040	/* free FILE struct after use */#define __FLAG_NARROW       0x0080#define __FLAG_FBF          0		/* convenience value */#define __FLAG_LBF          0x0100#define __FLAG_NBF          0x0200#define __MASK_BUFMODE      0x0300#define __FLAG_APPEND       0x0400#define __FLAG_WIDE			0x0800#define __FLAG_READING		0x1000#define __FLAG_WRITING		0x2000#define __FLAG_FREEBUF		0x4000	/* free buffer after use */#define __FLAG_LARGEFILE    0x8000/**********************************************************************/#ifdef __STDIO_GLIBC_CUSTOM_STREAMSextern __ssize_t _cs_read(void *cookie, char *buf, size_t bufsize);extern __ssize_t _cs_write(void *cookie, const char *buf, size_t bufsize);extern int _cs_seek(void *cookie, __offmax_t *pos, int whence);extern int _cs_close(void *cookie);#endif /* __STDIO_GLIBC_CUSTOM_STREAMS *//**********************************************************************/#ifdef __STDIO_MBSTATE#define __COPY_MBSTATE(dest,src)  ((dest)->mask = (src)->mask, (dest)->wc = (src)->wc)#define __INIT_MBSTATE(dest) ((dest)->mask = 0)#else#define __COPY_MBSTATE(dest,src)#define __INIT_MBSTATE(dest)#endif/**********************************************************************//* TODO -- thread safety issues */#define __CLEARERR(stream) \	((stream)->modeflags &= ~(__FLAG_EOF|__FLAG_ERROR), (void)0)#define __FEOF(stream)		((stream)->modeflags & __FLAG_EOF)#define __FERROR(stream)	((stream)->modeflags & __FLAG_ERROR)#define __FEOF_OR_FERROR(stream) \	((stream)->modeflags & (__FLAG_EOF|__FLAG_ERROR))/* TODO: check this * If we want to implement the getc and putc macros, we need to take * into account wide streams.  So... would need two additional variables * if we have wide streams (bufread and bufwrite), and one otherwise * (bufwrite).  getc would be effective for FBF streams.  It isn't for * LBF streams because other LBF streams need to be flushed.  putc * thouch is only effective for FBF streams.  Of course, to support * threads, we have to use functions. */#ifdef __STDIO_GETC_MACRO#define __GETC(stream)		( ((stream)->bufpos < (stream)->bufgetc) \							? (*(stream)->bufpos++) \							: fgetc_unlocked(stream) )#else  /* __STDIO_GETC_MACRO */#define __GETC(stream)		fgetc_unlocked(stream)#endif /* __STDIO_GETC_MACRO */#ifdef __STDIO_PUTC_MACRO#define __PUTC(c, stream)	( ((stream)->bufpos < (stream)->bufputc) \							? (*(stream)->bufpos++) = (c) \							: fputc_unlocked((c),(stream)) )#else  /* __STDIO_PUTC_MACRO */#define __PUTC(c, stream)	fputc_unlocked(c, stream);#endif /* __STDIO_PUTC_MACRO */#if 0/* TODO: disabled for now *//* Masking macros for the above _are_ allowed by the standard. */#define clearerr(stream)	__CLEARERR(stream)#define feof(stream)		__FEOF(stream)#define ferror(stream)		__FERROR(stream)#endif#if 0/* TODO -- what about custom streams!!! *//* Only use the macro below if you know fp is a valid FILE for a valid fd. */#define __fileno(fp)	((fp)->filedes)#endif/********************************************************************** * PROTOTYPES OF INTERNAL FUNCTIONS **********************************************************************/extern FILE *_stdio_openlist;#ifdef __STDIO_THREADSAFEextern pthread_mutex_t _stdio_openlist_lock;extern void __stdio_init_mutex(pthread_mutex_t *m);#endifextern int _stdio_adjpos(FILE * __restrict stream, __offmax_t * pos);extern int _stdio_lseek(FILE *stream, __offmax_t *pos, int whence);/* TODO: beware of signals with _stdio_fwrite!!!! */extern size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,							  FILE *stream);extern size_t _stdio_fread(unsigned char *buffer, size_t bytes,							 FILE *stream);extern FILE *_stdio_fopen(const char * __restrict filename,							const char * __restrict mode,							FILE * __restrict stream, int filedes);extern FILE *_stdio_fsfopen(const char * __restrict filename,							const char * __restrict mode,							register FILE * __restrict stream);extern void _stdio_init(void);extern void _stdio_term(void);#ifndef NDEBUGextern void __stdio_validate_FILE(FILE *stream);#else#define __stdio_validate_FILE(stream)		((void)0)#endif#ifdef __STDIO_WIDEextern size_t _wstdio_fwrite(const wchar_t *__restrict ws, size_t n,							 register FILE *__restrict stream);#endif/********************************************************************** * UTILITY functions **********************************************************************/#ifdef _STDIO_UTILITY#include <features.h>#include <limits.h>#include <stdint.h>#if INTMAX_MAX <= 2147483647L#define __UIM_BUFLEN			12 /* 10 digits + 1 nul + 1 sign */#elif INTMAX_MAX <= 9223372036854775807LL#define __UIM_BUFLEN			22 /* 20 digits + 1 nul + 1 sign */#else#error unknown number of digits for intmax_t!#endif#ifdef LLONG_MAX				/* --------------- */#if LLONG_MAX <= 2147483647L#define __UIM_BUFLEN_LLONG		12 /* 10 digits + 1 nul + 1 sign */#elif LLONG_MAX <= 9223372036854775807LL#define __UIM_BUFLEN_LLONG		22 /* 20 digits + 1 nul + 1 sign */#else#error unknown number of digits for long long!#endif#endif /* ULLONG_MAX ----------------------------- */#if LONG_MAX <= 2147483647L#define __UIM_BUFLEN_LONG		12 /* 10 digits + 1 nul + 1 sign */#elif LONG_MAX <= 9223372036854775807LL#define __UIM_BUFLEN_LONG		22 /* 20 digits + 1 nul + 1 sign */#else#error unknown number of digits for long!#endif#if INT_MAX <= 32767#define __UIM_BUFLEN_INT		7 /* 10 digits + 1 nul + 1 sign */#elif INT_MAX <= 2147483647L#define __UIM_BUFLEN_INT		12 /* 10 digits + 1 nul + 1 sign */#else#error unknown number of digits for int!#endiftypedef enum {	__UIM_DECIMAL = 0,	__UIM_GROUP = ',',			/* Base 10 locale-dependent grouping. */	__UIM_LOWER = 'a' - 10,	__UIM_UPPER = 'A' - 10,} __UIM_CASE;/* Write a NULL-terminated list of "char *" args to file descriptor fd. * For an example of usage, see __assert.c. */extern void _stdio_fdout(int fd, ...);/* Convert the int val to a string in base abs(base).  val is treated as * an unsigned ??? int type if base > 0, and signed if base < 0.  This * is an internal function with _no_ error checking done unless assert()s * are enabled. * * Note: bufend is a pointer to the END of the buffer passed. * Call like this: *     char buf[SIZE], *p; *     p = _xltostr(buf + sizeof(buf) - 1, {unsigned int},  10, __UIM_DECIMAL) *     p = _xltostr(buf + sizeof(buf) - 1,          {int}, -10, __UIM_DECIMAL) * * WARNING: If base > 10, case _must_be_ either __UIM_LOWER or __UIM_UPPER *          for lower and upper case alphas respectively. * WARNING: If val is really a signed type, make sure base is negative! *          Otherwise, you could overflow your buffer. */extern char *_uintmaxtostr(char * __restrict bufend, uintmax_t uval,						   int base, __UIM_CASE alphacase);/* TODO -- make this either a (possibly inline) function? */#ifndef __BCC__#define _int10tostr(bufend, intval) \	_uintmaxtostr((bufend), (intval), -10, __UIM_DECIMAL)#else  /* bcc doesn't do prototypes, we need to explicitly cast */#define _int10tostr(bufend, intval) \	_uintmaxtostr((bufend), (uintmax_t)(intval), -10, __UIM_DECIMAL)#endif#define __BUFLEN_INT10TOSTR		__UIM_BUFLEN_INT#endif /* _STDIO_UTILITY *//**********************************************************************//* uClibc translations *//**********************************************************************//* TODO: note done above..  typedef struct __stdio_file_struct _UC_FILE; */typedef __stdio_fpos_t		_UC_fpos_t;#ifdef __STDIO_LARGE_FILEStypedef __stdio_fpos64_t	_UC_fpos64_t;#endif#define _UC_IOFBF		_STDIO_IOFBF /* Fully buffered.  */#define _UC_IOLBF 		_STDIO_IOLBF /* Line buffered.  */#define _UC_IONBF 		_STDIO_IONBF /* No buffering.  */#define _UC_BUFSIZ		_STDIO_BUFSIZ
 |