Subversion Repositories Kolibri OS

Rev

Rev 4921 | Rev 6536 | 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 *));
185
extern int    _EXFUN(_fwalk,(struct _reent *, int (*)(FILE *)));
186
extern int    _EXFUN(_fwalk_reent,(struct _reent *, int (*)(struct _reent *, FILE *)));
187
struct _glue * _EXFUN(__sfmoreglue,(struct _reent *,int n));
188
extern int _EXFUN(__submore, (struct _reent *, FILE *));
189
 
190
#ifdef __LARGE64_FILES
191
extern _fpos64_t _EXFUN(__sseek64,(struct _reent *, void *, _fpos64_t, int));
192
extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite64,(struct _reent *, void *,
4921 Serge 193
						  const char *,
194
						  _READ_WRITE_BUFSIZE_TYPE));
4349 Serge 195
#endif
196
 
197
/* Called by the main entry point fns to ensure stdio has been initialized.  */
198
 
199
#ifdef _REENT_SMALL
200
#define CHECK_INIT(ptr, fp) \
6099 serge 201
  do								\
202
    {								\
4921 Serge 203
      struct _reent *_check_init_ptr = (ptr);			\
204
      if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit)	\
205
	__sinit (_check_init_ptr);				\
6099 serge 206
      if ((fp) == (FILE *)&__sf_fake_stdin)			\
4921 Serge 207
	(fp) = _stdin_r(_check_init_ptr);			\
6099 serge 208
      else if ((fp) == (FILE *)&__sf_fake_stdout)		\
4921 Serge 209
	(fp) = _stdout_r(_check_init_ptr);			\
6099 serge 210
      else if ((fp) == (FILE *)&__sf_fake_stderr)		\
4921 Serge 211
	(fp) = _stderr_r(_check_init_ptr);			\
6099 serge 212
    }								\
4349 Serge 213
  while (0)
214
#else /* !_REENT_SMALL   */
215
#define CHECK_INIT(ptr, fp) \
6099 serge 216
  do								\
217
    {								\
4921 Serge 218
      struct _reent *_check_init_ptr = (ptr);			\
219
      if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit)	\
220
	__sinit (_check_init_ptr);				\
6099 serge 221
    }								\
4349 Serge 222
  while (0)
223
#endif /* !_REENT_SMALL  */
224
 
225
#define CHECK_STD_INIT(ptr) \
6099 serge 226
  do								\
227
    {								\
4921 Serge 228
      struct _reent *_check_init_ptr = (ptr);			\
229
      if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit)	\
230
	__sinit (_check_init_ptr);				\
6099 serge 231
    }								\
4349 Serge 232
  while (0)
233
 
234
/* Return true and set errno and stream error flag iff the given FILE
235
   cannot be written now.  */
236
 
237
#define	cantwrite(ptr, fp)                                     \
238
  ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \
239
   __swsetup_r(ptr, fp))
240
 
241
/* Test whether the given stdio file has an active ungetc buffer;
242
   release such a buffer, without restoring ordinary unread data.  */
243
 
244
#define	HASUB(fp) ((fp)->_ub._base != NULL)
245
#define	FREEUB(ptr, fp) {                    \
246
	if ((fp)->_ub._base != (fp)->_ubuf) \
247
		_free_r(ptr, (char *)(fp)->_ub._base); \
248
	(fp)->_ub._base = NULL; \
249
}
250
 
251
/* Test for an fgetline() buffer.  */
252
 
253
#define	HASLB(fp) ((fp)->_lb._base != NULL)
254
#define	FREELB(ptr, fp) { _free_r(ptr,(char *)(fp)->_lb._base); \
255
      (fp)->_lb._base = NULL; }
256
 
4921 Serge 257
#ifdef _WIDE_ORIENT
4349 Serge 258
/*
259
 * Set the orientation for a stream. If o > 0, the stream has wide-
260
 * orientation. If o < 0, the stream has byte-orientation.
261
 */
262
#define ORIENT(fp,ori)					\
263
  do								\
264
    {								\
265
      if (!((fp)->_flags & __SORD))	\
266
	{							\
267
	  (fp)->_flags |= __SORD;				\
268
	  if (ori > 0)						\
269
	    (fp)->_flags2 |= __SWID;				\
270
	  else							\
271
	    (fp)->_flags2 &= ~__SWID;				\
272
	}							\
273
    }								\
274
  while (0)
4921 Serge 275
#else
276
#define ORIENT(fp,ori)
277
#endif
4349 Serge 278
 
279
/* WARNING: _dcvt is defined in the stdlib directory, not here!  */
280
 
281
char *_EXFUN(_dcvt,(struct _reent *, char *, double, int, int, char, int));
282
char *_EXFUN(_sicvt,(char *, short, char));
283
char *_EXFUN(_icvt,(char *, int, char));
284
char *_EXFUN(_licvt,(char *, long, char));
285
#ifdef __GNUC__
286
char *_EXFUN(_llicvt,(char *, long long, char));
287
#endif
288
 
289
#define CVT_BUF_SIZE 128
290
 
291
#define	NDYNAMIC 4	/* add four more whenever necessary */
292
 
293
#ifdef __SINGLE_THREAD__
294
#define __sfp_lock_acquire()
295
#define __sfp_lock_release()
296
#define __sinit_lock_acquire()
297
#define __sinit_lock_release()
298
#else
299
_VOID _EXFUN(__sfp_lock_acquire,(_VOID));
300
_VOID _EXFUN(__sfp_lock_release,(_VOID));
301
_VOID _EXFUN(__sinit_lock_acquire,(_VOID));
302
_VOID _EXFUN(__sinit_lock_release,(_VOID));
303
#endif
304
 
305
/* Types used in positional argument support in vfprinf/vfwprintf.
306
   The implementation is char/wchar_t dependent but the class and state
307
   tables are only defined once in vfprintf.c. */
308
typedef enum {
309
  ZERO,   /* '0' */
310
  DIGIT,  /* '1-9' */
311
  DOLLAR, /* '$' */
312
  MODFR,  /* spec modifier */
313
  SPEC,   /* format specifier */
314
  DOT,    /* '.' */
315
  STAR,   /* '*' */
316
  FLAG,   /* format flag */
317
  OTHER,  /* all other chars */
318
  MAX_CH_CLASS /* place-holder */
319
} __CH_CLASS;
320
 
321
typedef enum {
322
  START,  /* start */
323
  SFLAG,  /* seen a flag */
324
  WDIG,   /* seen digits in width area */
325
  WIDTH,  /* processed width */
326
  SMOD,   /* seen spec modifier */
327
  SDOT,   /* seen dot */
328
  VARW,   /* have variable width specifier */
329
  VARP,   /* have variable precision specifier */
330
  PREC,   /* processed precision */
331
  VWDIG,  /* have digits in variable width specification */
332
  VPDIG,  /* have digits in variable precision specification */
333
  DONE,   /* done */
334
  MAX_STATE, /* place-holder */
335
} __STATE;
336
 
337
typedef enum {
338
  NOOP,  /* do nothing */
339
  NUMBER, /* build a number from digits */
340
  SKIPNUM, /* skip over digits */
341
  GETMOD,  /* get and process format modifier */
342
  GETARG,  /* get and process argument */
343
  GETPW,   /* get variable precision or width */
344
  GETPWB,  /* get variable precision or width and pushback fmt char */
345
  GETPOS,  /* get positional parameter value */
346
  PWPOS,   /* get positional parameter value for variable width or precision */
347
} __ACTION;
348
 
349
extern _CONST __CH_CLASS __chclass[256];
350
extern _CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS];
351
extern _CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS];