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 <stdarg.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <wchar.h>
30 #ifdef __SCLE
31 # include <io.h>
32 #endif
33 #include "fvwrite.h"
34
35 /* The following define determines if the per-reent stdin, stdout and stderr
36 streams are closed during _reclaim_reent(). The stdin, stdout and stderr
37 streams are initialized to use file descriptors 0, 1 and 2 respectively. In
38 case _STDIO_CLOSE_PER_REENT_STD_STREAMS is defined these file descriptors
39 will be closed via close() provided the owner of the reent structure
40 triggerd the on demand reent initilization, see CHECK_INIT(). */
41 #if !defined(__tirtos__)
42 #define _STDIO_CLOSE_PER_REENT_STD_STREAMS
43 #endif
44
45 /* The following macros are supposed to replace calls to _flockfile/_funlockfile
46 and __sfp_lock_acquire/__sfp_lock_release. In case of multi-threaded
47 environments using pthreads, it's not sufficient to lock the stdio functions
48 against concurrent threads accessing the same data, the locking must also be
49 secured against thread cancellation.
50
51 The below macros have to be used in pairs. The _newlib_XXX_start macro
52 starts with a opening curly brace, the _newlib_XXX_end macro ends with a
53 closing curly brace, so the start macro and the end macro mark the code
54 start and end of a critical section. In case the code leaves the critical
55 section before reaching the end of the critical section's code end, use
56 the appropriate _newlib_XXX_exit macro. */
57
58 #if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) \
59 && !defined (__rtems__)
60 #define _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
61 #endif
62
63 #if defined(__SINGLE_THREAD__) || defined(__IMPL_UNLOCKED__)
64
65 # define _newlib_flockfile_start(_fp)
66 # define _newlib_flockfile_exit(_fp)
67 # define _newlib_flockfile_end(_fp)
68 # define _newlib_sfp_lock_start()
69 # define _newlib_sfp_lock_exit()
70 # define _newlib_sfp_lock_end()
71
72 #elif defined(_STDIO_WITH_THREAD_CANCELLATION_SUPPORT)
73 #include <pthread.h>
74
75 /* Start a stream oriented critical section: */
76 # define _newlib_flockfile_start(_fp) \
77 { \
78 int __oldfpcancel; \
79 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldfpcancel); \
80 if (!(_fp->_flags2 & __SNLK)) \
81 _flockfile (_fp)
82
83 /* Exit from a stream oriented critical section prematurely: */
84 # define _newlib_flockfile_exit(_fp) \
85 if (!(_fp->_flags2 & __SNLK)) \
86 _funlockfile (_fp); \
87 pthread_setcancelstate (__oldfpcancel, &__oldfpcancel);
88
89 /* End a stream oriented critical section: */
90 # define _newlib_flockfile_end(_fp) \
91 if (!(_fp->_flags2 & __SNLK)) \
92 _funlockfile (_fp); \
93 pthread_setcancelstate (__oldfpcancel, &__oldfpcancel); \
94 }
95
96 /* Start a stream list oriented critical section: */
97 # define _newlib_sfp_lock_start() \
98 { \
99 int __oldsfpcancel; \
100 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldsfpcancel); \
101 __sfp_lock_acquire ()
102
103 /* Exit from a stream list oriented critical section prematurely: */
104 # define _newlib_sfp_lock_exit() \
105 __sfp_lock_release (); \
106 pthread_setcancelstate (__oldsfpcancel, &__oldsfpcancel);
107
108 /* End a stream list oriented critical section: */
109 # define _newlib_sfp_lock_end() \
110 __sfp_lock_release (); \
111 pthread_setcancelstate (__oldsfpcancel, &__oldsfpcancel); \
112 }
113
114 #else /* !__SINGLE_THREAD__ && !__IMPL_UNLOCKED__ && !_STDIO_WITH_THREAD_CANCELLATION_SUPPORT */
115
116 # define _newlib_flockfile_start(_fp) \
117 { \
118 if (!(_fp->_flags2 & __SNLK)) \
119 _flockfile (_fp)
120
121 # define _newlib_flockfile_exit(_fp) \
122 if (!(_fp->_flags2 & __SNLK)) \
123 _funlockfile(_fp); \
124
125 # define _newlib_flockfile_end(_fp) \
126 if (!(_fp->_flags2 & __SNLK)) \
127 _funlockfile(_fp); \
128 }
129
130 # define _newlib_sfp_lock_start() \
131 { \
132 __sfp_lock_acquire ()
133
134 # define _newlib_sfp_lock_exit() \
135 __sfp_lock_release ();
136
137 # define _newlib_sfp_lock_end() \
138 __sfp_lock_release (); \
139 }
140
141 #endif /* __SINGLE_THREAD__ || __IMPL_UNLOCKED__ */
142
143 extern wint_t __fgetwc (FILE *);
144 extern wint_t __fputwc (wchar_t, FILE *);
145 extern unsigned char *__sccl (char *, unsigned char *fmt);
146 extern int _svfscanf (FILE *, const char *,va_list);
147 extern int _ssvfscanf (FILE *, const char *,va_list);
148 extern int _svfiscanf (FILE *, const char *,va_list);
149 extern int _ssvfiscanf (FILE *, const char *,va_list);
150 extern int _svfwscanf (FILE *, const wchar_t *,va_list);
151 extern int _ssvfwscanf (FILE *, const wchar_t *,va_list);
152 extern int _svfiwscanf (FILE *, const wchar_t *,va_list);
153 extern int _ssvfiwscanf (FILE *, const wchar_t *,va_list);
154 int svfprintf ( FILE *, const char *,
155 va_list)
156 _ATTRIBUTE ((__format__ (__printf__, 2, 0)));
157 int svfiprintf ( FILE *, const char *,
158 va_list)
159 _ATTRIBUTE ((__format__ (__printf__, 2, 0)));
160 int svfwprintf ( FILE *, const wchar_t *,
161 va_list);
162 int svfiwprintf ( FILE *, const wchar_t *,
163 va_list);
164 extern FILE *__sfp (void);
165 extern int __sflags (const char*, int*);
166 extern int _sflush (FILE *);
167 #ifdef _STDIO_BSD_SEMANTICS
168 extern int _sflushw (FILE *);
169 #endif
170 extern int _srefill (FILE *);
171 extern ssize_t __sread (void *, char *,
172 size_t);
173 extern ssize_t __seofread (void *,
174 char *,
175 size_t);
176 extern ssize_t __swrite (void *,
177 const char *,
178 size_t);
179 extern _fpos_t __sseek (void *, _fpos_t, int);
180 extern int __sclose (void *);
181 extern int __stextmode (int);
182 extern void __sinit (void);
183 extern void _smakebuf ( FILE *);
184 extern int _swhatbuf ( FILE *, size_t *, int *);
185 extern int __submore (FILE *);
186
187 extern int __sprint (FILE *, register struct __suio *);
188 extern int __ssprint (FILE *, register struct __suio *);
189 extern int __ssputs (FILE *fp, const char *buf, size_t len);
190 extern int __ssputws (FILE *fp, const wchar_t *buf, size_t len);
191 extern int __sfputs (FILE *, const char *buf, size_t len);
192 extern int __sfputws (FILE *, const wchar_t *buf, size_t len);
193 extern int sungetc (int c, register FILE *fp);
194 extern int _ssrefill (register FILE * fp);
195 extern size_t _sfread (void *buf, size_t size, size_t count, FILE * fp);
196
197 #ifdef __LARGE64_FILES
198 extern _fpos64_t __sseek64 (void *, _fpos64_t, int);
199 extern ssize_t __swrite64 (void *,
200 const char *,
201 size_t);
202 #endif
203
204 extern NEWLIB_THREAD_LOCAL void (*_tls_cleanup)(void);
205 #define _REENT_CLEANUP(_ptr) (_tls_cleanup)
206 extern NEWLIB_THREAD_LOCAL struct _Bigint **_tls_mp_freelist;
207 #define _REENT_MP_FREELIST(_ptr) (_tls_mp_freelist)
208 extern NEWLIB_THREAD_LOCAL struct _Bigint *_tls_mp_p5s;
209 #define _REENT_MP_P5S(_ptr) (_tls_mp_p5s)
210 extern NEWLIB_THREAD_LOCAL struct _Bigint *_tls_mp_result;
211 #define _REENT_MP_RESULT(_ptr) (_tls_mp_result)
212 extern NEWLIB_THREAD_LOCAL int _tls_mp_result_k;
213 #define _REENT_MP_RESULT_K(_ptr) (_tls_mp_result_k)
214
215 void _reclaim_reent (void *);
216
217 /* Called by the main entry point fns to ensure stdio has been initialized. */
218
219 #define CHECK_INIT(ptr, fp) \
220 do \
221 { \
222 if (!_tls_cleanup) \
223 __sinit (); \
224 } \
225 while (0)
226
227 /* Return true and set errno and stream error flag iff the given FILE
228 cannot be written now. */
229
230 #define cantwrite(ptr, fp) \
231 ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \
232 _swsetup( fp))
233
234 /* Test whether the given stdio file has an active ungetc buffer;
235 release such a buffer, without restoring ordinary unread data. */
236
237 #define HASUB(fp) ((fp)->_ub._base != NULL)
238 #define FREEUB(ptr, fp) { \
239 if ((fp)->_ub._base != (fp)->_ubuf) \
240 free((char *)(fp)->_ub._base); \
241 (fp)->_ub._base = NULL; \
242 }
243
244 /* Test for an fgetline() buffer. */
245
246 #define HASLB(fp) ((fp)->_lb._base != NULL)
247 #define FREELB(ptr, fp) { free((char *)(fp)->_lb._base); \
248 (fp)->_lb._base = NULL; }
249
250 #ifdef _WIDE_ORIENT
251 /*
252 * Set the orientation for a stream. If o > 0, the stream has wide-
253 * orientation. If o < 0, the stream has byte-orientation.
254 */
255 #ifndef __clang__
256 #pragma GCC diagnostic ignored "-Wunused-value"
257 #endif
258 #define ORIENT(fp,ori) \
259 ( \
260 ( \
261 ((fp)->_flags & __SORD) ? \
262 0 \
263 : \
264 ( \
265 ((fp)->_flags |= __SORD), \
266 (ori > 0) ? \
267 ((fp)->_flags2 |= __SWID) \
268 : \
269 ((fp)->_flags2 &= ~__SWID) \
270 ) \
271 ), \
272 ((fp)->_flags2 & __SWID) ? 1 : -1 \
273 )
274 #else
275 #define ORIENT(fp,ori) (-1)
276 #endif
277
278 /* Same thing as the functions in stdio.h, but these are to be called
279 from inside the wide-char functions. */
280 int __swbufw (int, FILE *);
281 #ifdef __GNUC__
__swputc(int _c,FILE * _p)282 _ELIDABLE_INLINE int __swputc(int _c, FILE *_p) {
283 #ifdef __SCLE
284 if ((_p->_flags & __SCLE) && _c == '\n')
285 __swputc ('\r', _p);
286 #endif
287 if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
288 return (*_p->_p++ = _c);
289 else
290 return (__swbufw(_c, _p));
291 }
292 #else
293 #define __swputc_raw(__c, __p) \
294 (--(__p)->_w < 0 ? \
295 (__p)->_w >= (__p)->_lbfsize ? \
296 (*(__p)->_p = (__c)), *(__p)->_p != '\n' ? \
297 (int)*(__p)->_p++ : \
298 __swbufw('\n', __p) : \
299 __swbufw((int)(__c), __p) : \
300 (*(__p)->_p = (__c), (int)*(__p)->_p++))
301 #ifdef __SCLE
302 #define __swputc(__c, __p) \
303 ((((__p)->_flags & __SCLE) && ((__c) == '\n')) \
304 ? __swputc_raw('\r', (__p)) : 0 , \
305 __swputc_raw((__c), (__p)))
306 #else
307 #define __swputc(__c, __p) __swputc_raw(__c, __p)
308 #endif
309 #endif
310
311 /* WARNING: _dcvt is defined in the stdlib directory, not here! */
312
313 char *_dcvt (char *, double, int, int, char, int);
314 char *_sicvt (char *, short, char);
315 char *_icvt (char *, int, char);
316 char *_licvt (char *, long, char);
317 #ifdef __GNUC__
318 char *_llicvt (char *, long long, char);
319 #endif
320
321 #define CVT_BUF_SIZE 128
322
323 #define NDYNAMIC 4 /* add four more whenever necessary */
324
325 #ifdef __SINGLE_THREAD__
326 #define __sfp_lock_acquire()
327 #define __sfp_lock_release()
328 #define __sinit_lock_acquire()
329 #define __sinit_lock_release()
330 #else
331 #define __sfp_lock_acquire() __LIBC_LOCK()
332 #define __sfp_lock_release() __LIBC_UNLOCK()
333 #define __sinit_lock_acquire() __LIBC_LOCK()
334 #define __sinit_lock_release() __LIBC_UNLOCK()
335 #endif
336
337 /* Types used in positional argument support in vfprinf/vfwprintf.
338 The implementation is char/wchar_t dependent but the class and state
339 tables are only defined once in vfprintf.c. */
340 typedef enum __packed {
341 ZERO, /* '0' */
342 DIGIT, /* '1-9' */
343 DOLLAR, /* '$' */
344 MODFR, /* spec modifier */
345 SPEC, /* format specifier */
346 DOT, /* '.' */
347 STAR, /* '*' */
348 FLAG, /* format flag */
349 OTHER, /* all other chars */
350 MAX_CH_CLASS /* place-holder */
351 } __CH_CLASS;
352
353 typedef enum __packed {
354 START, /* start */
355 SFLAG, /* seen a flag */
356 WDIG, /* seen digits in width area */
357 WIDTH, /* processed width */
358 SMOD, /* seen spec modifier */
359 SDOT, /* seen dot */
360 VARW, /* have variable width specifier */
361 VARP, /* have variable precision specifier */
362 PREC, /* processed precision */
363 VWDIG, /* have digits in variable width specification */
364 VPDIG, /* have digits in variable precision specification */
365 DONE, /* done */
366 MAX_STATE, /* place-holder */
367 } __STATE;
368
369 typedef enum __packed {
370 NOOP, /* do nothing */
371 NUMBER, /* build a number from digits */
372 SKIPNUM, /* skip over digits */
373 GETMOD, /* get and process format modifier */
374 GETARG, /* get and process argument */
375 GETPW, /* get variable precision or width */
376 GETPWB, /* get variable precision or width and pushback fmt char */
377 GETPOS, /* get positional parameter value */
378 PWPOS, /* get positional parameter value for variable width or precision */
379 } __ACTION;
380
381 extern const __CH_CLASS __chclass[256];
382 extern const __STATE __state_table[MAX_STATE][MAX_CH_CLASS];
383 extern const __ACTION __action_table[MAX_STATE][MAX_CH_CLASS];
384