Subversion Repositories Kolibri OS

Rev

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