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