Subversion Repositories Kolibri OS

Rev

Rev 4921 | 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 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
/* No user fns here.  Pesch 15apr92. */
18
 
19
#include <_ansi.h>
20
#include 
21
#include 
22
#include 
23
#include 
24
#include 
25
#include 
26
#include 
27
#include "local.h"
28
 
29
#ifdef _REENT_SMALL
30
const struct __sFILE_fake __sf_fake_stdin =
31
    {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL};
32
const struct __sFILE_fake __sf_fake_stdout =
33
    {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL};
34
const struct __sFILE_fake __sf_fake_stderr =
35
    {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL};
36
#endif
37
 
6099 serge 38
#if (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
39
_NOINLINE_STATIC _VOID
40
#else
4349 Serge 41
static _VOID
6099 serge 42
#endif
4349 Serge 43
_DEFUN(std, (ptr, flags, file, data),
44
            FILE *ptr _AND
45
            int flags _AND
46
            int file  _AND
47
            struct _reent *data)
48
{
49
  ptr->_p = 0;
50
  ptr->_r = 0;
51
  ptr->_w = 0;
52
  ptr->_flags = flags;
53
  ptr->_flags2 = 0;
54
  ptr->_file = file;
55
  ptr->_bf._base = 0;
56
  ptr->_bf._size = 0;
57
  ptr->_lbfsize = 0;
58
  memset (&ptr->_mbstate, 0, sizeof (_mbstate_t));
59
  ptr->_cookie = ptr;
60
  ptr->_read = __sread;
61
#ifndef __LARGE64_FILES
62
  ptr->_write = __swrite;
63
#else /* __LARGE64_FILES */
64
  ptr->_write = __swrite64;
65
  ptr->_seek64 = __sseek64;
66
  ptr->_flags |= __SL64;
67
#endif /* __LARGE64_FILES */
68
  ptr->_seek = __sseek;
4921 Serge 69
#ifdef _STDIO_CLOSE_PER_REENT_STD_STREAMS
4349 Serge 70
  ptr->_close = __sclose;
4921 Serge 71
#else /* _STDIO_CLOSE_STD_STREAMS */
72
  ptr->_close = NULL;
73
#endif /* _STDIO_CLOSE_STD_STREAMS */
4349 Serge 74
#if !defined(__SINGLE_THREAD__) && !defined(_REENT_SMALL)
75
  __lock_init_recursive (ptr->_lock);
76
  /*
77
   * #else
78
   * lock is already initialized in __sfp
79
   */
80
#endif
81
 
82
#ifdef __SCLE
83
  if (__stextmode (ptr->_file))
84
    ptr->_flags |= __SCLE;
85
#endif
86
}
87
 
4921 Serge 88
struct glue_with_file {
89
  struct _glue glue;
90
  FILE file;
91
};
92
 
4349 Serge 93
struct _glue *
94
_DEFUN(__sfmoreglue, (d, n),
95
       struct _reent *d _AND
96
       register int n)
97
{
4921 Serge 98
  struct glue_with_file *g;
4349 Serge 99
 
4921 Serge 100
  g = (struct glue_with_file *)
101
    _malloc_r (d, sizeof (*g) + (n - 1) * sizeof (FILE));
4349 Serge 102
  if (g == NULL)
103
    return NULL;
4921 Serge 104
  g->glue._next = NULL;
105
  g->glue._niobs = n;
106
  g->glue._iobs = &g->file;
107
  memset (&g->file, 0, n * sizeof (FILE));
108
  return &g->glue;
4349 Serge 109
}
110
 
111
/*
112
 * Find a free FILE for fopen et al.
113
 */
114
 
115
FILE *
116
_DEFUN(__sfp, (d),
117
       struct _reent *d)
118
{
119
  FILE *fp;
120
  int n;
121
  struct _glue *g;
122
 
4921 Serge 123
  _newlib_sfp_lock_start ();
4349 Serge 124
 
125
  if (!_GLOBAL_REENT->__sdidinit)
126
    __sinit (_GLOBAL_REENT);
127
  for (g = &_GLOBAL_REENT->__sglue;; g = g->_next)
128
    {
129
      for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
130
	if (fp->_flags == 0)
131
	  goto found;
132
      if (g->_next == NULL &&
133
	  (g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL)
134
	break;
135
    }
4921 Serge 136
  _newlib_sfp_lock_exit ();
4349 Serge 137
  d->_errno = ENOMEM;
138
  return NULL;
139
 
140
found:
141
  fp->_file = -1;		/* no file */
142
  fp->_flags = 1;		/* reserve this slot; caller sets real flags */
143
  fp->_flags2 = 0;
144
#ifndef __SINGLE_THREAD__
145
  __lock_init_recursive (fp->_lock);
146
#endif
4921 Serge 147
  _newlib_sfp_lock_end ();
4349 Serge 148
 
149
  fp->_p = NULL;		/* no current pointer */
150
  fp->_w = 0;			/* nothing to read or write */
151
  fp->_r = 0;
152
  fp->_bf._base = NULL;		/* no buffer */
153
  fp->_bf._size = 0;
154
  fp->_lbfsize = 0;		/* not line buffered */
155
  memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
156
  /* fp->_cookie = ; */	/* caller sets cookie, _read/_write etc */
157
  fp->_ub._base = NULL;		/* no ungetc buffer */
158
  fp->_ub._size = 0;
159
  fp->_lb._base = NULL;		/* no line buffer */
160
  fp->_lb._size = 0;
161
 
162
  return fp;
163
}
164
 
165
/*
166
 * exit() calls _cleanup() through *__cleanup, set whenever we
167
 * open or buffer a file.  This chicanery is done so that programs
168
 * that do not use stdio need not link it all in.
169
 *
170
 * The name `_cleanup' is, alas, fairly well known outside stdio.
171
 */
172
 
173
_VOID
174
_DEFUN(_cleanup_r, (ptr),
175
       struct _reent *ptr)
176
{
6099 serge 177
  int (*cleanup_func) (struct _reent *, FILE *);
178
#ifdef _STDIO_BSD_SEMANTICS
179
  /* BSD and Glibc systems only flush streams which have been written to
180
     at exit time.  Calling flush rather than close for speed, as on
181
     the aforementioned systems. */
182
  cleanup_func = __sflushw_r;
183
#else
184
  /* Otherwise close files and flush read streams, too.
185
     Note we call flush directly if "--enable-lite-exit" is in effect.  */
186
#ifdef _LITE_EXIT
187
  cleanup_func = _fflush_r;
188
#else
189
  cleanup_func = _fclose_r;
190
#endif
191
#endif
192
  _CAST_VOID _fwalk_reent (ptr, cleanup_func);
4349 Serge 193
}
194
 
195
#ifndef _REENT_ONLY
196
_VOID
197
_DEFUN_VOID(_cleanup)
198
{
199
  _cleanup_r (_GLOBAL_REENT);
200
}
201
#endif
202
 
203
/*
204
 * __sinit() is called whenever stdio's internal variables must be set up.
205
 */
206
 
207
_VOID
208
_DEFUN(__sinit, (s),
209
       struct _reent *s)
210
{
211
  __sinit_lock_acquire ();
212
 
213
  if (s->__sdidinit)
214
    {
215
      __sinit_lock_release ();
216
      return;
217
    }
218
 
219
  /* make sure we clean up on exit */
220
  s->__cleanup = _cleanup_r;	/* conservative */
221
 
222
  s->__sglue._next = NULL;
223
#ifndef _REENT_SMALL
224
  s->__sglue._niobs = 3;
225
  s->__sglue._iobs = &s->__sf[0];
226
#else
227
  s->__sglue._niobs = 0;
228
  s->__sglue._iobs = NULL;
4921 Serge 229
  /* Avoid infinite recursion when calling __sfp  for _GLOBAL_REENT.  The
230
     problem is that __sfp checks for _GLOBAL_REENT->__sdidinit and calls
231
     __sinit if it's 0. */
232
  if (s == _GLOBAL_REENT)
233
    s->__sdidinit = 1;
4349 Serge 234
  s->_stdin = __sfp(s);
235
  s->_stdout = __sfp(s);
236
  s->_stderr = __sfp(s);
237
#endif
238
 
239
  std (s->_stdin,  __SRD, 0, s);
240
 
241
  /* On platforms that have true file system I/O, we can verify
242
     whether stdout is an interactive terminal or not, as part of
243
     __smakebuf on first use of the stream.  For all other platforms,
244
     we will default to line buffered mode here.  Technically, POSIX
245
     requires both stdin and stdout to be line-buffered, but tradition
246
     leaves stdin alone on systems without fcntl.  */
247
#ifdef HAVE_FCNTL
248
  std (s->_stdout, __SWR, 1, s);
249
#else
250
  std (s->_stdout, __SWR | __SLBF, 1, s);
251
#endif
252
 
253
  /* POSIX requires stderr to be opened for reading and writing, even
254
     when the underlying fd 2 is write-only.  */
255
  std (s->_stderr, __SRW | __SNBF, 2, s);
256
 
4921 Serge 257
  s->__sdidinit = 1;
258
 
4349 Serge 259
  __sinit_lock_release ();
260
}
261
 
262
#ifndef __SINGLE_THREAD__
263
 
264
__LOCK_INIT_RECURSIVE(static, __sfp_lock);
265
__LOCK_INIT_RECURSIVE(static, __sinit_lock);
266
 
267
_VOID
268
_DEFUN_VOID(__sfp_lock_acquire)
269
{
4921 Serge 270
  //__lock_acquire_recursive (__sfp_lock);
4349 Serge 271
}
272
 
273
_VOID
274
_DEFUN_VOID(__sfp_lock_release)
275
{
4921 Serge 276
  //__lock_release_recursive (__sfp_lock);
4349 Serge 277
}
278
 
279
_VOID
280
_DEFUN_VOID(__sinit_lock_acquire)
281
{
4921 Serge 282
  //__lock_acquire_recursive (__sinit_lock);
4349 Serge 283
}
284
 
285
_VOID
286
_DEFUN_VOID(__sinit_lock_release)
287
{
4921 Serge 288
  //__lock_release_recursive (__sinit_lock);
4349 Serge 289
}
290
 
291
/* Walkable file locking routine.  */
292
static int
293
_DEFUN(__fp_lock, (ptr),
294
       FILE * ptr)
295
{
6099 serge 296
  if (!(ptr->_flags2 & __SNLK))
297
    _flockfile (ptr);
4349 Serge 298
 
299
  return 0;
300
}
301
 
302
/* Walkable file unlocking routine.  */
303
static int
304
_DEFUN(__fp_unlock, (ptr),
305
       FILE * ptr)
306
{
6099 serge 307
  if (!(ptr->_flags2 & __SNLK))
308
    _funlockfile (ptr);
4349 Serge 309
 
310
  return 0;
311
}
312
 
313
_VOID
314
_DEFUN_VOID(__fp_lock_all)
315
{
316
  __sfp_lock_acquire ();
317
 
318
  _CAST_VOID _fwalk (_REENT, __fp_lock);
319
}
320
 
321
_VOID
322
_DEFUN_VOID(__fp_unlock_all)
323
{
324
  _CAST_VOID _fwalk (_REENT, __fp_unlock);
325
 
326
  __sfp_lock_release ();
327
}
328
#endif