Rev 6536 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 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 | * advertising materials, and 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 |
||
27 | #include |
||
28 | #include |
||
29 | #include |
||
30 | #include |
||
31 | #ifdef __SCLE |
||
32 | # include |
||
33 | #endif |
||
34 | |||
4921 | Serge | 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(). */ |
||
6099 | serge | 41 | #if !defined(__rtems__) && !defined(__tirtos__) |
4921 | Serge | 42 | #define _STDIO_CLOSE_PER_REENT_STD_STREAMS |
43 | #endif |
||
4349 | Serge | 44 | |
4921 | Serge | 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 | |||
6099 | serge | 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) |
||
4921 | Serge | 73 | #include |
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); \ |
||
6099 | serge | 80 | if (!(_fp->_flags2 & __SNLK)) \ |
81 | _flockfile (_fp) |
||
4921 | Serge | 82 | |
83 | /* Exit from a stream oriented critical section prematurely: */ |
||
84 | # define _newlib_flockfile_exit(_fp) \ |
||
6099 | serge | 85 | if (!(_fp->_flags2 & __SNLK)) \ |
86 | _funlockfile (_fp); \ |
||
4921 | Serge | 87 | pthread_setcancelstate (__oldfpcancel, &__oldfpcancel); |
88 | |||
89 | /* End a stream oriented critical section: */ |
||
90 | # define _newlib_flockfile_end(_fp) \ |
||
6099 | serge | 91 | if (!(_fp->_flags2 & __SNLK)) \ |
92 | _funlockfile (_fp); \ |
||
4921 | Serge | 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 | |||
6099 | serge | 114 | #else /* !__SINGLE_THREAD__ && !__IMPL_UNLOCKED__ && !_STDIO_WITH_THREAD_CANCELLATION_SUPPORT */ |
4921 | Serge | 115 | |
116 | # define _newlib_flockfile_start(_fp) \ |
||
117 | { \ |
||
6099 | serge | 118 | if (!(_fp->_flags2 & __SNLK)) \ |
119 | _flockfile (_fp) |
||
4921 | Serge | 120 | |
121 | # define _newlib_flockfile_exit(_fp) \ |
||
6099 | serge | 122 | if (!(_fp->_flags2 & __SNLK)) \ |
123 | _funlockfile(_fp); \ |
||
4921 | Serge | 124 | |
125 | # define _newlib_flockfile_end(_fp) \ |
||
6099 | serge | 126 | if (!(_fp->_flags2 & __SNLK)) \ |
127 | _funlockfile(_fp); \ |
||
4921 | Serge | 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 | |||
6099 | serge | 141 | #endif /* __SINGLE_THREAD__ || __IMPL_UNLOCKED__ */ |
4921 | Serge | 142 | |
6099 | serge | 143 | extern wint_t _EXFUN(__fgetwc, (struct _reent *, FILE *)); |
144 | extern wint_t _EXFUN(__fputwc, (struct _reent *, wchar_t, FILE *)); |
||
4349 | Serge | 145 | extern u_char *_EXFUN(__sccl, (char *, u_char *fmt)); |
146 | extern int _EXFUN(__svfscanf_r,(struct _reent *,FILE *, _CONST char *,va_list)); |
||
147 | extern int _EXFUN(__ssvfscanf_r,(struct _reent *,FILE *, _CONST char *,va_list)); |
||
148 | extern int _EXFUN(__svfiscanf_r,(struct _reent *,FILE *, _CONST char *,va_list)); |
||
149 | extern int _EXFUN(__ssvfiscanf_r,(struct _reent *,FILE *, _CONST char *,va_list)); |
||
150 | extern int _EXFUN(__svfwscanf_r,(struct _reent *,FILE *, _CONST wchar_t *,va_list)); |
||
151 | extern int _EXFUN(__ssvfwscanf_r,(struct _reent *,FILE *, _CONST wchar_t *,va_list)); |
||
152 | extern int _EXFUN(__svfiwscanf_r,(struct _reent *,FILE *, _CONST wchar_t *,va_list)); |
||
153 | extern int _EXFUN(__ssvfiwscanf_r,(struct _reent *,FILE *, _CONST wchar_t *,va_list)); |
||
6627 | serge | 154 | int _EXFUN(_svfprintf_r,(struct _reent *, FILE *, const char *, |
4349 | Serge | 155 | va_list) |
156 | _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); |
||
6627 | serge | 157 | int _EXFUN(_svfiprintf_r,(struct _reent *, FILE *, const char *, |
4349 | Serge | 158 | va_list) |
159 | _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); |
||
6627 | serge | 160 | int _EXFUN(_svfwprintf_r,(struct _reent *, FILE *, const wchar_t *, |
4349 | Serge | 161 | va_list)); |
6627 | serge | 162 | int _EXFUN(_svfiwprintf_r,(struct _reent *, FILE *, const wchar_t *, |
4349 | Serge | 163 | va_list)); |
164 | extern FILE *_EXFUN(__sfp,(struct _reent *)); |
||
165 | extern int _EXFUN(__sflags,(struct _reent *,_CONST char*, int*)); |
||
166 | extern int _EXFUN(__sflush_r,(struct _reent *,FILE *)); |
||
6099 | serge | 167 | #ifdef _STDIO_BSD_SEMANTICS |
168 | extern int _EXFUN(__sflushw_r,(struct _reent *,FILE *)); |
||
169 | #endif |
||
4349 | Serge | 170 | extern int _EXFUN(__srefill_r,(struct _reent *,FILE *)); |
171 | extern _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(struct _reent *, void *, char *, |
||
4921 | Serge | 172 | _READ_WRITE_BUFSIZE_TYPE)); |
4349 | Serge | 173 | extern _READ_WRITE_RETURN_TYPE _EXFUN(__seofread,(struct _reent *, void *, |
4921 | Serge | 174 | char *, |
175 | _READ_WRITE_BUFSIZE_TYPE)); |
||
4349 | Serge | 176 | extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite,(struct _reent *, void *, |
4921 | Serge | 177 | const char *, |
178 | _READ_WRITE_BUFSIZE_TYPE)); |
||
4349 | Serge | 179 | extern _fpos_t _EXFUN(__sseek,(struct _reent *, void *, _fpos_t, int)); |
180 | extern int _EXFUN(__sclose,(struct _reent *, void *)); |
||
181 | extern int _EXFUN(__stextmode,(int)); |
||
182 | extern _VOID _EXFUN(__sinit,(struct _reent *)); |
||
183 | extern _VOID _EXFUN(_cleanup_r,(struct _reent *)); |
||
184 | extern _VOID _EXFUN(__smakebuf_r,(struct _reent *, FILE *)); |
||
6536 | serge | 185 | extern int _EXFUN(__swhatbuf_r,(struct _reent *, FILE *, size_t *, int *)); |
4349 | Serge | 186 | extern int _EXFUN(_fwalk,(struct _reent *, int (*)(FILE *))); |
187 | extern int _EXFUN(_fwalk_reent,(struct _reent *, int (*)(struct _reent *, FILE *))); |
||
188 | struct _glue * _EXFUN(__sfmoreglue,(struct _reent *,int n)); |
||
189 | extern int _EXFUN(__submore, (struct _reent *, FILE *)); |
||
190 | |||
191 | #ifdef __LARGE64_FILES |
||
192 | extern _fpos64_t _EXFUN(__sseek64,(struct _reent *, void *, _fpos64_t, int)); |
||
193 | extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite64,(struct _reent *, void *, |
||
4921 | Serge | 194 | const char *, |
195 | _READ_WRITE_BUFSIZE_TYPE)); |
||
4349 | Serge | 196 | #endif |
197 | |||
198 | /* Called by the main entry point fns to ensure stdio has been initialized. */ |
||
199 | |||
200 | #ifdef _REENT_SMALL |
||
201 | #define CHECK_INIT(ptr, fp) \ |
||
6099 | serge | 202 | do \ |
203 | { \ |
||
4921 | Serge | 204 | struct _reent *_check_init_ptr = (ptr); \ |
205 | if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit) \ |
||
206 | __sinit (_check_init_ptr); \ |
||
6099 | serge | 207 | if ((fp) == (FILE *)&__sf_fake_stdin) \ |
4921 | Serge | 208 | (fp) = _stdin_r(_check_init_ptr); \ |
6099 | serge | 209 | else if ((fp) == (FILE *)&__sf_fake_stdout) \ |
4921 | Serge | 210 | (fp) = _stdout_r(_check_init_ptr); \ |
6099 | serge | 211 | else if ((fp) == (FILE *)&__sf_fake_stderr) \ |
4921 | Serge | 212 | (fp) = _stderr_r(_check_init_ptr); \ |
6099 | serge | 213 | } \ |
4349 | Serge | 214 | while (0) |
215 | #else /* !_REENT_SMALL */ |
||
216 | #define CHECK_INIT(ptr, fp) \ |
||
6099 | serge | 217 | do \ |
218 | { \ |
||
4921 | Serge | 219 | struct _reent *_check_init_ptr = (ptr); \ |
220 | if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit) \ |
||
221 | __sinit (_check_init_ptr); \ |
||
6099 | serge | 222 | } \ |
4349 | Serge | 223 | while (0) |
224 | #endif /* !_REENT_SMALL */ |
||
225 | |||
226 | #define CHECK_STD_INIT(ptr) \ |
||
6099 | serge | 227 | do \ |
228 | { \ |
||
4921 | Serge | 229 | struct _reent *_check_init_ptr = (ptr); \ |
230 | if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit) \ |
||
231 | __sinit (_check_init_ptr); \ |
||
6099 | serge | 232 | } \ |
4349 | Serge | 233 | while (0) |
234 | |||
235 | /* Return true and set errno and stream error flag iff the given FILE |
||
236 | cannot be written now. */ |
||
237 | |||
238 | #define cantwrite(ptr, fp) \ |
||
239 | ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \ |
||
240 | __swsetup_r(ptr, fp)) |
||
241 | |||
242 | /* Test whether the given stdio file has an active ungetc buffer; |
||
243 | release such a buffer, without restoring ordinary unread data. */ |
||
244 | |||
245 | #define HASUB(fp) ((fp)->_ub._base != NULL) |
||
246 | #define FREEUB(ptr, fp) { \ |
||
247 | if ((fp)->_ub._base != (fp)->_ubuf) \ |
||
248 | _free_r(ptr, (char *)(fp)->_ub._base); \ |
||
249 | (fp)->_ub._base = NULL; \ |
||
250 | } |
||
251 | |||
252 | /* Test for an fgetline() buffer. */ |
||
253 | |||
254 | #define HASLB(fp) ((fp)->_lb._base != NULL) |
||
255 | #define FREELB(ptr, fp) { _free_r(ptr,(char *)(fp)->_lb._base); \ |
||
256 | (fp)->_lb._base = NULL; } |
||
257 | |||
4921 | Serge | 258 | #ifdef _WIDE_ORIENT |
4349 | Serge | 259 | /* |
260 | * Set the orientation for a stream. If o > 0, the stream has wide- |
||
261 | * orientation. If o < 0, the stream has byte-orientation. |
||
262 | */ |
||
263 | #define ORIENT(fp,ori) \ |
||
264 | do \ |
||
265 | { \ |
||
266 | (fp)->_flags |= __SORD; \ |
||
267 | if (ori > 0) \ |
||
268 | (fp)->_flags2 |= __SWID; \ |
||
269 | else \ |
||
270 | (fp)->_flags2 &= ~__SWID; \ |
||
271 | } \ |
||
272 | while (0) |
||
4921 | Serge | 273 | #else |
274 | #define ORIENT(fp,ori) |
||
275 | #endif |
||
4349 | Serge | 276 | |
277 | /* WARNING: _dcvt is defined in the stdlib directory, not here! */ |
||
278 | |||
279 | char *_EXFUN(_dcvt,(struct _reent *, char *, double, int, int, char, int)); |
||
280 | char *_EXFUN(_sicvt,(char *, short, char)); |
||
281 | char *_EXFUN(_icvt,(char *, int, char)); |
||
282 | char *_EXFUN(_licvt,(char *, long, char)); |
||
283 | #ifdef __GNUC__ |
||
284 | char *_EXFUN(_llicvt,(char *, long long, char)); |
||
285 | #endif |
||
286 | |||
287 | #define CVT_BUF_SIZE 128 |
||
288 | |||
289 | #define NDYNAMIC 4 /* add four more whenever necessary */ |
||
290 | |||
291 | #ifdef __SINGLE_THREAD__ |
||
292 | #define __sfp_lock_acquire() |
||
293 | #define __sfp_lock_release() |
||
294 | #define __sinit_lock_acquire() |
||
295 | #define __sinit_lock_release() |
||
296 | #else |
||
297 | _VOID _EXFUN(__sfp_lock_acquire,(_VOID)); |
||
298 | _VOID _EXFUN(__sfp_lock_release,(_VOID)); |
||
299 | _VOID _EXFUN(__sinit_lock_acquire,(_VOID)); |
||
300 | _VOID _EXFUN(__sinit_lock_release,(_VOID)); |
||
301 | #endif |
||
302 | |||
303 | /* Types used in positional argument support in vfprinf/vfwprintf. |
||
304 | The implementation is char/wchar_t dependent but the class and state |
||
305 | tables are only defined once in vfprintf.c. */ |
||
306 | typedef enum { |
||
307 | ZERO, /* '0' */ |
||
308 | DIGIT, /* '1-9' */ |
||
309 | DOLLAR, /* '$' */ |
||
310 | MODFR, /* spec modifier */ |
||
311 | SPEC, /* format specifier */ |
||
312 | DOT, /* '.' */ |
||
313 | STAR, /* '*' */ |
||
314 | FLAG, /* format flag */ |
||
315 | OTHER, /* all other chars */ |
||
316 | MAX_CH_CLASS /* place-holder */ |
||
317 | } __CH_CLASS; |
||
318 | |||
319 | typedef enum { |
||
320 | START, /* start */ |
||
321 | SFLAG, /* seen a flag */ |
||
322 | WDIG, /* seen digits in width area */ |
||
323 | WIDTH, /* processed width */ |
||
324 | SMOD, /* seen spec modifier */ |
||
325 | SDOT, /* seen dot */ |
||
326 | VARW, /* have variable width specifier */ |
||
327 | VARP, /* have variable precision specifier */ |
||
328 | PREC, /* processed precision */ |
||
329 | VWDIG, /* have digits in variable width specification */ |
||
330 | VPDIG, /* have digits in variable precision specification */ |
||
331 | DONE, /* done */ |
||
332 | MAX_STATE, /* place-holder */ |
||
333 | } __STATE; |
||
334 | |||
335 | typedef enum { |
||
336 | NOOP, /* do nothing */ |
||
337 | NUMBER, /* build a number from digits */ |
||
338 | SKIPNUM, /* skip over digits */ |
||
339 | GETMOD, /* get and process format modifier */ |
||
340 | GETARG, /* get and process argument */ |
||
341 | GETPW, /* get variable precision or width */ |
||
342 | GETPWB, /* get variable precision or width and pushback fmt char */ |
||
343 | GETPOS, /* get positional parameter value */ |
||
344 | PWPOS, /* get positional parameter value for variable width or precision */ |
||
345 | } __ACTION; |
||
346 | |||
347 | extern _CONST __CH_CLASS __chclass[256]; |
||
348 | extern _CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS]; |
||
349 | extern _CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS];> |