1 /* 2 * Copyright (c) 1990, 2007 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * and/or other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * %W% (UofMD/Berkeley) %G% 18 */ 19 20 /* 21 * Information local to this implementation of stdio, 22 * in particular, macros and private variables. 23 */ 24 25 #include <_ansi.h> 26 #include <stdarg.h> 27 #include <stdlib.h> 28 #include <unistd.h> 29 #include <stdio.h> 30 #ifdef __SCLE 31 # include <io.h> 32 #endif 33 34 /* The following define determines if the per-reent stdin, stdout and stderr 35 streams are closed during _reclaim_reent(). The stdin, stdout and stderr 36 streams are initialized to use file descriptors 0, 1 and 2 respectively. In 37 case _STDIO_CLOSE_PER_REENT_STD_STREAMS is defined these file descriptors 38 will be closed via close() provided the owner of the reent structure 39 triggerd the on demand reent initilization, see CHECK_INIT(). */ 40 #if !defined(__tirtos__) 41 #define _STDIO_CLOSE_PER_REENT_STD_STREAMS 42 #endif 43 44 /* The following macros are supposed to replace calls to _flockfile/_funlockfile 45 and __sfp_lock_acquire/__sfp_lock_release. In case of multi-threaded 46 environments using pthreads, it's not sufficient to lock the stdio functions 47 against concurrent threads accessing the same data, the locking must also be 48 secured against thread cancellation. 49 50 The below macros have to be used in pairs. The _newlib_XXX_start macro 51 starts with a opening curly brace, the _newlib_XXX_end macro ends with a 52 closing curly brace, so the start macro and the end macro mark the code 53 start and end of a critical section. In case the code leaves the critical 54 section before reaching the end of the critical section's code end, use 55 the appropriate _newlib_XXX_exit macro. */ 56 57 #if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) \ 58 && !defined (__rtems__) 59 #define _STDIO_WITH_THREAD_CANCELLATION_SUPPORT 60 #endif 61 62 #if defined(__SINGLE_THREAD__) || defined(__IMPL_UNLOCKED__) 63 64 # define _newlib_flockfile_start(_fp) 65 # define _newlib_flockfile_exit(_fp) 66 # define _newlib_flockfile_end(_fp) 67 # define _newlib_sfp_lock_start() 68 # define _newlib_sfp_lock_exit() 69 # define _newlib_sfp_lock_end() 70 71 #elif defined(_STDIO_WITH_THREAD_CANCELLATION_SUPPORT) 72 #include <pthread.h> 73 74 /* Start a stream oriented critical section: */ 75 # define _newlib_flockfile_start(_fp) \ 76 { \ 77 int __oldfpcancel; \ 78 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldfpcancel); \ 79 if (!(_fp->_flags2 & __SNLK)) \ 80 _flockfile (_fp) 81 82 /* Exit from a stream oriented critical section prematurely: */ 83 # define _newlib_flockfile_exit(_fp) \ 84 if (!(_fp->_flags2 & __SNLK)) \ 85 _funlockfile (_fp); \ 86 pthread_setcancelstate (__oldfpcancel, &__oldfpcancel); 87 88 /* End a stream oriented critical section: */ 89 # define _newlib_flockfile_end(_fp) \ 90 if (!(_fp->_flags2 & __SNLK)) \ 91 _funlockfile (_fp); \ 92 pthread_setcancelstate (__oldfpcancel, &__oldfpcancel); \ 93 } 94 95 /* Start a stream list oriented critical section: */ 96 # define _newlib_sfp_lock_start() \ 97 { \ 98 int __oldsfpcancel; \ 99 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldsfpcancel); \ 100 __sfp_lock_acquire () 101 102 /* Exit from a stream list oriented critical section prematurely: */ 103 # define _newlib_sfp_lock_exit() \ 104 __sfp_lock_release (); \ 105 pthread_setcancelstate (__oldsfpcancel, &__oldsfpcancel); 106 107 /* End a stream list oriented critical section: */ 108 # define _newlib_sfp_lock_end() \ 109 __sfp_lock_release (); \ 110 pthread_setcancelstate (__oldsfpcancel, &__oldsfpcancel); \ 111 } 112 113 #else /* !__SINGLE_THREAD__ && !__IMPL_UNLOCKED__ && !_STDIO_WITH_THREAD_CANCELLATION_SUPPORT */ 114 115 # define _newlib_flockfile_start(_fp) \ 116 { \ 117 if (!(_fp->_flags2 & __SNLK)) \ 118 _flockfile (_fp) 119 120 # define _newlib_flockfile_exit(_fp) \ 121 if (!(_fp->_flags2 & __SNLK)) \ 122 _funlockfile(_fp); \ 123 124 # define _newlib_flockfile_end(_fp) \ 125 if (!(_fp->_flags2 & __SNLK)) \ 126 _funlockfile(_fp); \ 127 } 128 129 # define _newlib_sfp_lock_start() \ 130 { \ 131 __sfp_lock_acquire () 132 133 # define _newlib_sfp_lock_exit() \ 134 __sfp_lock_release (); 135 136 # define _newlib_sfp_lock_end() \ 137 __sfp_lock_release (); \ 138 } 139 140 #endif /* __SINGLE_THREAD__ || __IMPL_UNLOCKED__ */ 141 142 extern wint_t __fgetwc (FILE *); 143 extern wint_t __fputwc (wchar_t, FILE *); 144 extern u_char *__sccl (char *, u_char *fmt); 145 extern int _svfscanf (FILE *, const char *,va_list); 146 extern int _ssvfscanf (FILE *, const char *,va_list); 147 extern int _svfiscanf (FILE *, const char *,va_list); 148 extern int _ssvfiscanf (FILE *, const char *,va_list); 149 extern int _svfwscanf (FILE *, const wchar_t *,va_list); 150 extern int _ssvfwscanf (FILE *, const wchar_t *,va_list); 151 extern int _svfiwscanf (FILE *, const wchar_t *,va_list); 152 extern int _ssvfiwscanf (FILE *, const wchar_t *,va_list); 153 int svfprintf ( FILE *, const char *, 154 va_list) 155 _ATTRIBUTE ((__format__ (__printf__, 2, 0))); 156 int svfiprintf ( FILE *, const char *, 157 va_list) 158 _ATTRIBUTE ((__format__ (__printf__, 2, 0))); 159 int svfwprintf ( FILE *, const wchar_t *, 160 va_list); 161 int svfiwprintf ( FILE *, const wchar_t *, 162 va_list); 163 extern FILE *__sfp (void); 164 extern int __sflags (const char*, int*); 165 extern int _sflush (FILE *); 166 #ifdef _STDIO_BSD_SEMANTICS 167 extern int _sflushw (FILE *); 168 #endif 169 extern int _srefill (FILE *); 170 extern ssize_t __sread (void *, char *, 171 size_t); 172 extern ssize_t __seofread (void *, 173 char *, 174 size_t); 175 extern ssize_t __swrite (void *, 176 const char *, 177 size_t); 178 extern _fpos_t __sseek (void *, _fpos_t, int); 179 extern int __sclose (void *); 180 extern int __stextmode (int); 181 extern void __sinit (void); 182 extern void _smakebuf ( FILE *); 183 extern int _swhatbuf ( FILE *, size_t *, int *); 184 extern int __submore (FILE *); 185 186 #ifdef __LARGE64_FILES 187 extern _fpos64_t __sseek64 (void *, _fpos64_t, int); 188 extern ssize_t __swrite64 (void *, 189 const char *, 190 size_t); 191 #endif 192 193 extern NEWLIB_THREAD_LOCAL void (*_tls_cleanup)(void); 194 #define _REENT_CLEANUP(_ptr) (_tls_cleanup) 195 extern NEWLIB_THREAD_LOCAL struct _Bigint **_tls_mp_freelist; 196 #define _REENT_MP_FREELIST(_ptr) (_tls_mp_freelist) 197 extern NEWLIB_THREAD_LOCAL struct _Bigint *_tls_mp_p5s; 198 #define _REENT_MP_P5S(_ptr) (_tls_mp_p5s) 199 extern NEWLIB_THREAD_LOCAL struct _Bigint *_tls_mp_result; 200 #define _REENT_MP_RESULT(_ptr) (_tls_mp_result) 201 extern NEWLIB_THREAD_LOCAL int _tls_mp_result_k; 202 #define _REENT_MP_RESULT_K(_ptr) (_tls_mp_result_k) 203 204 void _reclaim_reent (void *); 205 206 /* Called by the main entry point fns to ensure stdio has been initialized. */ 207 208 #define CHECK_INIT(ptr, fp) \ 209 do \ 210 { \ 211 if (!_tls_cleanup) \ 212 __sinit (); \ 213 } \ 214 while (0) 215 216 /* Return true and set errno and stream error flag iff the given FILE 217 cannot be written now. */ 218 219 #define cantwrite(ptr, fp) \ 220 ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \ 221 _swsetup( fp)) 222 223 /* Test whether the given stdio file has an active ungetc buffer; 224 release such a buffer, without restoring ordinary unread data. */ 225 226 #define HASUB(fp) ((fp)->_ub._base != NULL) 227 #define FREEUB(ptr, fp) { \ 228 if ((fp)->_ub._base != (fp)->_ubuf) \ 229 free((char *)(fp)->_ub._base); \ 230 (fp)->_ub._base = NULL; \ 231 } 232 233 /* Test for an fgetline() buffer. */ 234 235 #define HASLB(fp) ((fp)->_lb._base != NULL) 236 #define FREELB(ptr, fp) { free((char *)(fp)->_lb._base); \ 237 (fp)->_lb._base = NULL; } 238 239 #ifdef _WIDE_ORIENT 240 /* 241 * Set the orientation for a stream. If o > 0, the stream has wide- 242 * orientation. If o < 0, the stream has byte-orientation. 243 */ 244 #define ORIENT(fp,ori) \ 245 do \ 246 { \ 247 if (!((fp)->_flags & __SORD)) \ 248 { \ 249 (fp)->_flags |= __SORD; \ 250 if (ori > 0) \ 251 (fp)->_flags2 |= __SWID; \ 252 else \ 253 (fp)->_flags2 &= ~__SWID; \ 254 } \ 255 } \ 256 while (0) 257 #else 258 #define ORIENT(fp,ori) 259 #endif 260 261 /* WARNING: _dcvt is defined in the stdlib directory, not here! */ 262 263 char *_dcvt (char *, double, int, int, char, int); 264 char *_sicvt (char *, short, char); 265 char *_icvt (char *, int, char); 266 char *_licvt (char *, long, char); 267 #ifdef __GNUC__ 268 char *_llicvt (char *, long long, char); 269 #endif 270 271 #define CVT_BUF_SIZE 128 272 273 #define NDYNAMIC 4 /* add four more whenever necessary */ 274 275 #ifdef __SINGLE_THREAD__ 276 #define __sfp_lock_acquire() 277 #define __sfp_lock_release() 278 #define __sinit_lock_acquire() 279 #define __sinit_lock_release() 280 #else 281 #define __sfp_lock_acquire() __LIBC_LOCK() 282 #define __sfp_lock_release() __LIBC_UNLOCK() 283 #define __sinit_lock_acquire() __LIBC_LOCK() 284 #define __sinit_lock_release() __LIBC_UNLOCK() 285 #endif 286 287 /* Types used in positional argument support in vfprinf/vfwprintf. 288 The implementation is char/wchar_t dependent but the class and state 289 tables are only defined once in vfprintf.c. */ 290 typedef enum __packed { 291 ZERO, /* '0' */ 292 DIGIT, /* '1-9' */ 293 DOLLAR, /* '$' */ 294 MODFR, /* spec modifier */ 295 SPEC, /* format specifier */ 296 DOT, /* '.' */ 297 STAR, /* '*' */ 298 FLAG, /* format flag */ 299 OTHER, /* all other chars */ 300 MAX_CH_CLASS /* place-holder */ 301 } __CH_CLASS; 302 303 typedef enum __packed { 304 START, /* start */ 305 SFLAG, /* seen a flag */ 306 WDIG, /* seen digits in width area */ 307 WIDTH, /* processed width */ 308 SMOD, /* seen spec modifier */ 309 SDOT, /* seen dot */ 310 VARW, /* have variable width specifier */ 311 VARP, /* have variable precision specifier */ 312 PREC, /* processed precision */ 313 VWDIG, /* have digits in variable width specification */ 314 VPDIG, /* have digits in variable precision specification */ 315 DONE, /* done */ 316 MAX_STATE, /* place-holder */ 317 } __STATE; 318 319 typedef enum __packed { 320 NOOP, /* do nothing */ 321 NUMBER, /* build a number from digits */ 322 SKIPNUM, /* skip over digits */ 323 GETMOD, /* get and process format modifier */ 324 GETARG, /* get and process argument */ 325 GETPW, /* get variable precision or width */ 326 GETPWB, /* get variable precision or width and pushback fmt char */ 327 GETPOS, /* get positional parameter value */ 328 PWPOS, /* get positional parameter value for variable width or precision */ 329 } __ACTION; 330 331 extern const __CH_CLASS __chclass[256]; 332 extern const __STATE __state_table[MAX_STATE][MAX_CH_CLASS]; 333 extern const __ACTION __action_table[MAX_STATE][MAX_CH_CLASS]; 334