Subversion Repositories Kolibri OS

Rev

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(). */
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));
6099 serge 154
int	      _EXFUN(_svfprintf_r,(struct _reent *, FILE *, const char *,
4349 Serge 155
				  va_list)
156
               			_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
6099 serge 157
int	      _EXFUN(_svfiprintf_r,(struct _reent *, FILE *, const char *,
4349 Serge 158
				  va_list)
159
               			_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
6099 serge 160
int	      _EXFUN(_svfwprintf_r,(struct _reent *, FILE *, const wchar_t *,
4349 Serge 161
				  va_list));
6099 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
      if (!((fp)->_flags & __SORD))	\
267
	{							\
268
	  (fp)->_flags |= __SORD;				\
269
	  if (ori > 0)						\
270
	    (fp)->_flags2 |= __SWID;				\
271
	  else							\
272
	    (fp)->_flags2 &= ~__SWID;				\
273
	}							\
274
    }								\
275
  while (0)
4921 Serge 276
#else
277
#define ORIENT(fp,ori)
278
#endif
4349 Serge 279
 
280
/* WARNING: _dcvt is defined in the stdlib directory, not here!  */
281
 
282
char *_EXFUN(_dcvt,(struct _reent *, char *, double, int, int, char, int));
283
char *_EXFUN(_sicvt,(char *, short, char));
284
char *_EXFUN(_icvt,(char *, int, char));
285
char *_EXFUN(_licvt,(char *, long, char));
286
#ifdef __GNUC__
287
char *_EXFUN(_llicvt,(char *, long long, char));
288
#endif
289
 
290
#define CVT_BUF_SIZE 128
291
 
292
#define	NDYNAMIC 4	/* add four more whenever necessary */
293
 
294
#ifdef __SINGLE_THREAD__
295
#define __sfp_lock_acquire()
296
#define __sfp_lock_release()
297
#define __sinit_lock_acquire()
298
#define __sinit_lock_release()
299
#else
300
_VOID _EXFUN(__sfp_lock_acquire,(_VOID));
301
_VOID _EXFUN(__sfp_lock_release,(_VOID));
302
_VOID _EXFUN(__sinit_lock_acquire,(_VOID));
303
_VOID _EXFUN(__sinit_lock_release,(_VOID));
304
#endif
305
 
306
/* Types used in positional argument support in vfprinf/vfwprintf.
307
   The implementation is char/wchar_t dependent but the class and state
308
   tables are only defined once in vfprintf.c. */
309
typedef enum {
310
  ZERO,   /* '0' */
311
  DIGIT,  /* '1-9' */
312
  DOLLAR, /* '$' */
313
  MODFR,  /* spec modifier */
314
  SPEC,   /* format specifier */
315
  DOT,    /* '.' */
316
  STAR,   /* '*' */
317
  FLAG,   /* format flag */
318
  OTHER,  /* all other chars */
319
  MAX_CH_CLASS /* place-holder */
320
} __CH_CLASS;
321
 
322
typedef enum {
323
  START,  /* start */
324
  SFLAG,  /* seen a flag */
325
  WDIG,   /* seen digits in width area */
326
  WIDTH,  /* processed width */
327
  SMOD,   /* seen spec modifier */
328
  SDOT,   /* seen dot */
329
  VARW,   /* have variable width specifier */
330
  VARP,   /* have variable precision specifier */
331
  PREC,   /* processed precision */
332
  VWDIG,  /* have digits in variable width specification */
333
  VPDIG,  /* have digits in variable precision specification */
334
  DONE,   /* done */
335
  MAX_STATE, /* place-holder */
336
} __STATE;
337
 
338
typedef enum {
339
  NOOP,  /* do nothing */
340
  NUMBER, /* build a number from digits */
341
  SKIPNUM, /* skip over digits */
342
  GETMOD,  /* get and process format modifier */
343
  GETARG,  /* get and process argument */
344
  GETPW,   /* get variable precision or width */
345
  GETPWB,  /* get variable precision or width and pushback fmt char */
346
  GETPOS,  /* get positional parameter value */
347
  PWPOS,   /* get positional parameter value for variable width or precision */
348
} __ACTION;
349
 
350
extern _CONST __CH_CLASS __chclass[256];
351
extern _CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS];
352
extern _CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS];