sl@0: /* FINDFP.C sl@0: * sl@0: * Portions Copyright (c) 1990-2008 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: */ sl@0: sl@0: /* No user fns here. Pesch 15apr92. */ sl@0: sl@0: /* sl@0: * Copyright (c) 1990 The Regents of the University of California. sl@0: * All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms are permitted sl@0: * provided that the above copyright notice and this paragraph are sl@0: * duplicated in all such forms and that any documentation, sl@0: * advertising materials, and other materials related to such sl@0: * distribution and use acknowledge that the software was developed sl@0: * by the University of California, Berkeley. The name of the sl@0: * University may not be used to endorse or promote products derived sl@0: * from this software without specific prior written permission. sl@0: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR sl@0: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED sl@0: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "LOCAL.H" sl@0: sl@0: /* Initialise a FILE structure to a starting state */ sl@0: #ifdef __GCCXML__ sl@0: static void sl@0: _std (FILE *ptr, int flags, int file, struct _reent *data) sl@0: #else sl@0: static void sl@0: std (FILE *ptr, int flags, int file, struct _reent *data) sl@0: #endif sl@0: { sl@0: ptr->_p = 0; sl@0: ptr->_r = 0; sl@0: ptr->_w = 0; sl@0: ptr->_flags = (short)flags; sl@0: ptr->_file = (short)file; sl@0: ptr->_bf._base = 0; sl@0: ptr->_lbfsize = 0; sl@0: ptr->_cookie = ptr; sl@0: ptr->_read = __sread; sl@0: ptr->_write = __swrite; sl@0: ptr->_seek = __sseek; sl@0: ptr->_close = __sclose; sl@0: ptr->_data = data; sl@0: } sl@0: sl@0: struct _glue * sl@0: __sfmoreglue (struct _reent *d, register int n) sl@0: { sl@0: struct _glue *g; sl@0: FILE *p; sl@0: sl@0: g = (struct _glue *) _malloc_r (d, sizeof (*g) + n * sizeof (FILE)); sl@0: if (g == NULL) sl@0: return NULL; sl@0: p = (FILE *) (g + 1); sl@0: g->_next = NULL; sl@0: g->_niobs = n; sl@0: g->_iobs = p; sl@0: memset (p, 0, n * sizeof (FILE)); sl@0: return g; sl@0: } sl@0: sl@0: /* sl@0: * Find a free FILE for fopen et al. sl@0: */ sl@0: sl@0: FILE * sl@0: __sfp (struct _reent *d) sl@0: { sl@0: FILE *fp; sl@0: int n; sl@0: struct _glue *g; sl@0: sl@0: if (!d->__sdidinit) sl@0: __sinit (d); sl@0: for (g = &d->__sglue;; g = g->_next) sl@0: { sl@0: for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) sl@0: if (fp->_flags == 0) sl@0: goto found; sl@0: if (g->_next == NULL && sl@0: (g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL) sl@0: break; sl@0: } sl@0: d->_errno = ENOMEM; sl@0: return NULL; sl@0: sl@0: found: sl@0: fp->_flags = 1; /* reserve this slot; caller sets real flags */ sl@0: fp->_p = NULL; /* no current pointer */ sl@0: fp->_w = 0; /* nothing to read or write */ sl@0: fp->_r = 0; sl@0: fp->_bf._base = NULL; /* no buffer */ sl@0: fp->_bf._size = 0; sl@0: fp->_lbfsize = 0; /* not line buffered */ sl@0: fp->_file = -1; /* no file */ sl@0: /* fp->_cookie = ; */ /* caller sets cookie, _read/_write etc */ sl@0: fp->_ub._base = NULL; /* no ungetc buffer */ sl@0: fp->_ub._size = 0; sl@0: fp->_lb._base = NULL; /* no line buffer */ sl@0: fp->_lb._size = 0; sl@0: fp->_data = d; sl@0: return fp; sl@0: } sl@0: sl@0: /* sl@0: * exit() calls _cleanup() through *__cleanup, set whenever we sl@0: * open or buffer a file. This chicanery is done so that programs sl@0: * that do not use stdio need not link it all in. sl@0: * sl@0: * The name `_cleanup' is, alas, fairly well known outside stdio. sl@0: */ sl@0: /** sl@0: A reentrant version of _cleanup(). sl@0: */ sl@0: EXPORT_C void sl@0: _cleanup_r (struct _reent *ptr) sl@0: { sl@0: (void) _fwalk(ptr, fclose); sl@0: } sl@0: sl@0: #ifndef _REENT_ONLY sl@0: sl@0: /** sl@0: Performs cleanup sl@0: */ sl@0: EXPORT_C void sl@0: _cleanup (void) sl@0: { sl@0: _cleanup_r (_REENT); sl@0: } sl@0: #endif sl@0: sl@0: /* sl@0: * __sinit() is called whenever stdio's internal variables must be set up. sl@0: */ sl@0: sl@0: void sl@0: __sinit (struct _reent *s) sl@0: { sl@0: /* make sure we clean up on exit */ sl@0: s->__cleanup = _cleanup_r; /* conservative */ sl@0: s->__sdidinit = 1; sl@0: sl@0: #ifdef __GCCXML__ sl@0: _std (_stdin_r(s), __SRD, 0, s); sl@0: _std (_stdout_r(s), __SWR, 1, s); sl@0: _std (_stderr_r(s), __SWR | __SNBF, 2, s); sl@0: #else sl@0: std (_stdin_r(s), __SRD, 0, s); sl@0: std (_stdout_r(s), __SWR, 1, s); sl@0: std (_stderr_r(s), __SWR | __SNBF, 2, s); sl@0: #endif sl@0: sl@0: /* initialise the head of the glue chain to cover stdim/stdout/stderr */ sl@0: s->__sglue._next = NULL; sl@0: s->__sglue._niobs = 3; sl@0: s->__sglue._iobs = &s->_sf[0]; sl@0: } sl@0: sl@0: /* Function interface to stdin/stdout/stderr sl@0: * sl@0: * These functions should return a value which is fixed for any given sl@0: * reentrancy context, but it doesn't have to be fixed at compile time, sl@0: * and we don't need to have initialised stdio either. sl@0: */ sl@0: sl@0: /** sl@0: Function interface to the "constants" stdin. sl@0: These functions guarantee to return a fixed value, so that it sl@0: will be possible to use expressions such as if (fp != stdout) fclose(fp); sl@0: with complete confidence. Unfortunately it will rule out initialising global sl@0: variables with stdin/stdout/stderr, as in the common idiom: sl@0: sl@0: static FILE *log = stderr; sl@0: sl@0: This isn't currently possible with EPOC32. sl@0: */ sl@0: EXPORT_C FILE *__stdin (void) sl@0: { sl@0: return _stdin_r(_REENT); sl@0: } sl@0: sl@0: /** sl@0: Function interface to the "constants" stdout sl@0: See __stdin sl@0: */ sl@0: EXPORT_C FILE *__stdout (void) sl@0: { sl@0: return _stdout_r(_REENT); sl@0: } sl@0: sl@0: /** sl@0: Function interface to the "constants" stderr sl@0: See __stdin sl@0: */ sl@0: EXPORT_C FILE *__stderr (void) sl@0: { sl@0: return _stderr_r(_REENT); sl@0: }