Subversion Repositories Kolibri OS

Rev

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];