Commit 0d936eec authored by Kevin Bracey's avatar Kevin Bracey
Browse files

* Improved stdio to allocate extra FILE objects beyond the static array of 16....

* Improved stdio to allocate extra FILE objects beyond the static array of 16. Number of open files now only limited by memory and the OS.

* FOPEN_MAX in <stdio.h> increased from 8 to 16 to reflect reality.
* Minor corrections to comments in <stdio.h>.
* Library shutdown tidied for modules. In particular, shutdown of I/O was
  broken for modules which had been entered as applications.

Version 5.53. Tagged as 'RISC_OSLib-5_53'
parent 72dac353
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
GBLS Module_HelpVersion GBLS Module_HelpVersion
GBLS Module_ComponentName GBLS Module_ComponentName
GBLS Module_ComponentPath GBLS Module_ComponentPath
Module_MajorVersion SETS "5.52" Module_MajorVersion SETS "5.53"
Module_Version SETA 552 Module_Version SETA 553
Module_MinorVersion SETS "" Module_MinorVersion SETS ""
Module_Date SETS "07 Mar 2005" Module_Date SETS "14 Mar 2005"
Module_ApplicationDate SETS "07-Mar-05" Module_ApplicationDate SETS "14-Mar-05"
Module_ComponentName SETS "RISC_OSLib" Module_ComponentName SETS "RISC_OSLib"
Module_ComponentPath SETS "RiscOS/Sources/Lib/RISC_OSLib" Module_ComponentPath SETS "RiscOS/Sources/Lib/RISC_OSLib"
Module_FullVersion SETS "5.52" Module_FullVersion SETS "5.53"
Module_HelpVersion SETS "5.52 (07 Mar 2005)" Module_HelpVersion SETS "5.53 (14 Mar 2005)"
END END
/* (5.52) /* (5.53)
* *
* This file is automatically maintained by srccommit, do not edit manually. * This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.2. * Last processed by srccommit version: 1.2.
* *
*/ */
#define Module_MajorVersion_CMHG 5.52 #define Module_MajorVersion_CMHG 5.53
#define Module_MinorVersion_CMHG #define Module_MinorVersion_CMHG
#define Module_Date_CMHG 07 Mar 2005 #define Module_Date_CMHG 14 Mar 2005
#define Module_MajorVersion "5.52" #define Module_MajorVersion "5.53"
#define Module_Version 552 #define Module_Version 553
#define Module_MinorVersion "" #define Module_MinorVersion ""
#define Module_Date "07 Mar 2005" #define Module_Date "14 Mar 2005"
#define Module_ApplicationDate "07-Mar-05" #define Module_ApplicationDate "14-Mar-05"
#define Module_ComponentName "RISC_OSLib" #define Module_ComponentName "RISC_OSLib"
#define Module_ComponentPath "RiscOS/Sources/Lib/RISC_OSLib" #define Module_ComponentPath "RiscOS/Sources/Lib/RISC_OSLib"
#define Module_FullVersion "5.52" #define Module_FullVersion "5.53"
#define Module_HelpVersion "5.52 (07 Mar 2005)" #define Module_HelpVersion "5.53 (14 Mar 2005)"
#define Module_LibraryVersionInfo "5:52" #define Module_LibraryVersionInfo "5:53"
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
/* Incorporate _sys_tmpnam_ idea from WGD */ /* Incorporate _sys_tmpnam_ idea from WGD */
/* __pos of a file is now a long, and we avoid warnings by two casts */
/* of this to (int) in the calls to _sys_seek(). */
/* N.B. I am trying to factor out machine dependence via calls to */ /* N.B. I am trying to factor out machine dependence via calls to */
/* routines like _sys_read_ which can be implemented as _osgbpb or */ /* routines like _sys_read_ which can be implemented as _osgbpb or */
/* NIOP as required. This file SHOULD therefore be machine independent */ /* NIOP as required. This file SHOULD therefore be machine independent */
...@@ -102,6 +100,42 @@ typedef struct __extradata { ...@@ -102,6 +100,42 @@ typedef struct __extradata {
static _extradatap _extra; static _extradatap _extra;
/* 14-Mar-2005 - upgraded to handle more files beyond _SYS_OPEN; extra */
/* handles stored in a linked list. For simplicity, these structures are */
/* never freed until terminateio is called. Need to take care that all */
/* code directly referencing __iob also considers this list. */
typedef struct _FILElist {
struct _FILElist *next;
FILE file;
_extradata extra;
} _FILElist, *_FILElistp;
static _FILElistp _flist;
static FILE *_getFILE(void)
{ _FILElistp fp;
int i;
/* First try __iob array */
for (i=3; i<_SYS_OPEN; i++)
{ FILE *stream = &__iob[i];
if (!(stream->__flag & _IOREAD+_IOWRITE))
return stream;
}
/* Then try linked list */
for (fp = _flist; fp; fp = fp->next)
if (!(fp->file.__flag & _IOREAD+_IOWRITE))
return &fp->file;
/* Then try to allocate a new one */
fp = calloc(1, sizeof(_FILElist));
if (fp)
{ fp->file.__extrap = &fp->extra;
fp->next = _flist;
_flist = fp;
return &fp->file;
}
return 0;
}
#ifdef SUPPORT_WIDE #ifdef SUPPORT_WIDE
#define O_NONE 0 #define O_NONE 0
#define O_BYTE (-1) #define O_BYTE (-1)
...@@ -176,7 +210,7 @@ static _extradatap _extra; ...@@ -176,7 +210,7 @@ static _extradatap _extra;
int (fgetc)(FILE *stream) { return getc(stream); } int (fgetc)(FILE *stream) { return getc(stream); }
int (fputc)(int ch, FILE *stream) { return putc(ch, stream); } int (fputc)(int ch, FILE *stream) { return putc(ch, stream); }
int (getc)(FILE *stream) { return getc(stream); } int (getc)(FILE *stream) { return getc(stream); }
int (getchar)() { return getchar(); } int (getchar)(void) { return getchar(); }
int (putc)(int ch, FILE *stream) { return putc(ch, stream); } int (putc)(int ch, FILE *stream) { return putc(ch, stream); }
int (putchar)(int ch) { return putchar(ch); } int (putchar)(int ch) { return putchar(ch); }
int (feof)(FILE *stream) { return feof(stream); } int (feof)(FILE *stream) { return feof(stream); }
...@@ -267,7 +301,7 @@ dbmsg("_IOSHARED so zoom to end %d\n", (int)stream->__pos); ...@@ -267,7 +301,7 @@ dbmsg("_IOSHARED so zoom to end %d\n", (int)stream->__pos);
if (flag & _IOSEEK+_IOBUFREAD) if (flag & _IOSEEK+_IOBUFREAD)
{ {
dbmsg("_writebuf seeking to %d\n", (int)stream->__pos); dbmsg("_writebuf seeking to %d\n", (int)stream->__pos);
if (_sys_seek(fh, (int)stream->__pos) < 0) if (_sys_seek(fh, stream->__pos) < 0)
{ seterr(stream); { seterr(stream);
return EOF; return EOF;
} }
...@@ -485,7 +519,7 @@ dbmsg("fillbuf seeking to %d\n", (int)stream->__pos); ...@@ -485,7 +519,7 @@ dbmsg("fillbuf seeking to %d\n", (int)stream->__pos);
_sys_ensure(fh); _sys_ensure(fh);
stream->__flag &= ~_IOADFSBUG; stream->__flag &= ~_IOADFSBUG;
} }
if (_sys_seek(fh, (int)stream->__pos) < 0) if (_sys_seek(fh, stream->__pos) < 0)
{ seterr(stream); { seterr(stream);
return EOF; return EOF;
} }
...@@ -508,7 +542,7 @@ dbmsg("fillbuf dirty buffer, read into end,seeking to %d\n",(int) stream->__pos+ ...@@ -508,7 +542,7 @@ dbmsg("fillbuf dirty buffer, read into end,seeking to %d\n",(int) stream->__pos+
_sys_ensure(fh); _sys_ensure(fh);
stream->__flag &= ~_IOADFSBUG; stream->__flag &= ~_IOADFSBUG;
} }
if (_sys_seek(fh, (int) stream->__pos + extent) < 0) if (_sys_seek(fh, stream->__pos + extent) < 0)
{ seterr(stream); { seterr(stream);
return EOF; return EOF;
} else stream->__flag |= _IOBUFREAD; } else stream->__flag |= _IOBUFREAD;
...@@ -582,7 +616,9 @@ int fclose(FILE *stream) ...@@ -582,7 +616,9 @@ int fclose(FILE *stream)
{ int fd = _SYS_OPEN; { int fd = _SYS_OPEN;
res = fflush(stream); res = fflush(stream);
if (flag & _IOSHARED) if (flag & _IOSHARED)
{ for (fd = 0; fd < _SYS_OPEN; ++fd) { /* No need to check FILElist, as only FILEs in __iob can be */
/* shared by __dup(). */
for (fd = 0; fd < _SYS_OPEN; ++fd)
{ FILE *f = &__iob[fd]; { FILE *f = &__iob[fd];
if ((f != stream) && if ((f != stream) &&
(f->__flag & _IOREAD+_IOWRITE) && /* f is open */ (f->__flag & _IOREAD+_IOWRITE) && /* f is open */
...@@ -647,12 +683,9 @@ FILE *freopen(const char *name, const char *mode, FILE *iob) ...@@ -647,12 +683,9 @@ FILE *freopen(const char *name, const char *mode, FILE *iob)
} }
FILE *fopen(const char *name, const char *mode) FILE *fopen(const char *name, const char *mode)
{ int i; { FILE *stream = _getFILE();
for (i=3; i<_SYS_OPEN; i++) if (stream)
{ FILE *stream = &__iob[i]; return (freopen(name, mode, stream));
if (!(stream->__flag & _IOREAD+_IOWRITE)) /* if not open then try it */
return (freopen(name, mode, stream));
}
return 0; /* no more i/o channels allowed for */ return 0; /* no more i/o channels allowed for */
} }
...@@ -674,17 +707,13 @@ FILE *_fopen_string_file(const char *data, int length) ...@@ -674,17 +707,13 @@ FILE *_fopen_string_file(const char *data, int length)
/* The declaration of this function in #include "hostsys.h" suggests */ /* The declaration of this function in #include "hostsys.h" suggests */
/* that this function is of type (void *), so this definition will lead */ /* that this function is of type (void *), so this definition will lead */
/* to a warning message. */ /* to a warning message. */
int i; FILE *stream = _getFILE();
for (i=3; i<_SYS_OPEN; i++) if (stream)
{ FILE *stream = &__iob[i]; { fclose(stream);
if (!(stream->__flag & _IOREAD+_IOWRITE)) /* if not open then try it */ stream->__flag = _IOSTRG+_IOREAD+_IOACTIVE;
{ stream->__ptr = stream->__base = (unsigned char *)data;
fclose(stream); stream->__icnt = length;
stream->__flag = _IOSTRG+_IOREAD+_IOACTIVE; return stream;
stream->__ptr = stream->__base = (unsigned char *)data;
stream->__icnt = length;
return stream;
}
} }
return 0; /* no more i/o channels allowed for */ return 0; /* no more i/o channels allowed for */
} }
...@@ -717,13 +746,18 @@ void _initio(char *f1,char *f2,char *f3) ...@@ -717,13 +746,18 @@ void _initio(char *f1,char *f2,char *f3)
_sprintf_lf(v,_kernel_getmessage("Couldn't write %s", "C46"), f2), _sys_msg(v), exit(1); _sprintf_lf(v,_kernel_getmessage("Couldn't write %s", "C46"), f2), _sys_msg(v), exit(1);
} }
void _terminateio() void _terminateio(void)
{ int i; { int i;
int closeall = !_kernel_client_is_module(); int closeall = !_kernel_client_is_module();
_FILElistp fp;
for (i=3; i<_SYS_OPEN; i++) { for (i=3; i<_SYS_OPEN; i++) {
FILE *f = &__iob[i]; FILE *f = &__iob[i];
if (closeall || (f->__flag & _IOUSERFILE)) fclose(f); if (closeall || (f->__flag & _IOUSERFILE)) fclose(f);
} }
for (fp = _flist; fp; fp = fp->next) {
FILE *f = &fp->file;
if (closeall || (f->__flag & _IOUSERFILE)) fclose(f);
}
/* for cowardice do stdin, stdout, stderr last (in that order) */ /* for cowardice do stdin, stdout, stderr last (in that order) */
for (i=0; i<3; i++) { for (i=0; i<3; i++) {
FILE *f = &__iob[i]; FILE *f = &__iob[i];
...@@ -732,7 +766,13 @@ void _terminateio() ...@@ -732,7 +766,13 @@ void _terminateio()
if (!closeall) freopen(TTYFILENAME, (f == stdin ? "r" : "w"), f); if (!closeall) freopen(TTYFILENAME, (f == stdin ? "r" : "w"), f);
} }
} }
if (_extra) { if (closeall) {
_FILElistp fpnext;
for (fp = _flist; fp; fp = fpnext) {
fpnext = fp->next;
free(fp);
}
_flist = 0;
free(_extra); free(_extra);
_extra = 0; _extra = 0;
} }
...@@ -1066,8 +1106,11 @@ int fflush(FILE *stream) ...@@ -1066,8 +1106,11 @@ int fflush(FILE *stream)
res =_do_fflush(stream); res =_do_fflush(stream);
else else
{ int i; { int i;
_FILElistp fp;
for (i=0; i<_SYS_OPEN; i++) for (i=0; i<_SYS_OPEN; i++)
if (_do_fflush(&__iob[i]) != 0) res = EOF; if (_do_fflush(&__iob[i]) != 0) res = EOF;
for (fp=_flist; fp; fp=fp->next)
if (_do_fflush(&fp->file) != 0) res = EOF;
} }
return res; return res;
} }
...@@ -1119,7 +1162,7 @@ char *__old_tmpnam(char *a) ...@@ -1119,7 +1162,7 @@ char *__old_tmpnam(char *a)
return tmpnam(a); return tmpnam(a);
} }
FILE *tmpfile() FILE *tmpfile(void)
{ {
char name[L_tmpnam]; char name[L_tmpnam];
FILE *f; FILE *f;
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
static unsigned long int next = 1; static unsigned long int next = 1;
int _ANSI_rand() /* This is the ANSI suggested portable code */ int _ANSI_rand(void) /* This is the ANSI suggested portable code */
{ {
next = next * 1103515245 + 12345; next = next * 1103515245 + 12345;
return (unsigned int) (next >> 16) % 32768; return (unsigned int) (next >> 16) % 32768;
...@@ -63,7 +63,7 @@ static unsigned _random_number_seed[55] = ...@@ -63,7 +63,7 @@ static unsigned _random_number_seed[55] =
static int _random_j = 23, _random_k = 54; static int _random_j = 23, _random_k = 54;
int rand() int rand(void)
{ {
/* See Knuth vol 2 section 3.2.2 for a discussion of this random /* See Knuth vol 2 section 3.2.2 for a discussion of this random
number generator. number generator.
...@@ -108,7 +108,7 @@ static struct { ...@@ -108,7 +108,7 @@ static struct {
char alloc_finalised, io_finalised, getenv_finalised; char alloc_finalised, io_finalised, getenv_finalised;
} exit_s; } exit_s;
void _exit_init() void _exit_init(void)
{ {
if (_kernel_client_is_module()) { if (_kernel_client_is_module()) {
/* leave SWI mode exit handlers in place. number_of_exit_functions /* leave SWI mode exit handlers in place. number_of_exit_functions
...@@ -130,19 +130,28 @@ int atexit(vprocp func) ...@@ -130,19 +130,28 @@ int atexit(vprocp func)
return 0; /* success */ return 0; /* success */
} }
void _lib_shutdown() void _lib_shutdown(void)
{ {
int mode = ((_kernel_processor_mode() & 0xF) != 0); int mode = ((_kernel_processor_mode() & 0xF) != 0);
int ismodule = _kernel_client_is_module(); /* ie is module app, so not */
/* total shutdown */
while (exit_s.number_of_exit_functions!=0) { while (exit_s.number_of_exit_functions!=0) {
vprocp fn = _exitvector[--exit_s.number_of_exit_functions].p; vprocp fn = _exitvector[--exit_s.number_of_exit_functions].p;
int flags = _exitvector[exit_s.number_of_exit_functions].i; int flags = _exitvector[exit_s.number_of_exit_functions].i;
if ((flags & 3) != mode) { ++exit_s.number_of_exit_functions; break; }; if ((flags & 3) != mode) { ++exit_s.number_of_exit_functions; break; };
/* Take extra care with fn ptr - consider Thumb */
fn = (vprocp) ((unsigned) fn &~ 3);
_call_client_0(fn); _call_client_0(fn);
} }
/* ensure no recursion if finalisation fails */ /* ensure no recursion if finalisation fails */
if (!exit_s.getenv_finalised) { exit_s.getenv_finalised = 1; _terminate_getenv(); } if (!exit_s.getenv_finalised && !ismodule)
if (!exit_s.alloc_finalised) { exit_s.alloc_finalised = 1; _terminate_user_alloc(); } { exit_s.getenv_finalised = 1; _terminate_getenv(); }
if (!exit_s.io_finalised) { exit_s.io_finalised = 1; _terminateio(); } if (!exit_s.alloc_finalised)
{ exit_s.alloc_finalised = 1; _terminate_user_alloc(); }
if (!exit_s.io_finalised)
{ exit_s.io_finalised = 1; _terminateio(); }
if (ismodule) /* Want terminateio again for module part */
exit_s.io_finalised = 0;
} }
...@@ -166,7 +175,7 @@ void _Exit(int n) ...@@ -166,7 +175,7 @@ void _Exit(int n)
_exit(n); _exit(n);
} }
void abort() void abort(void)
{ {
raise(SIGABRT); raise(SIGABRT);
exit(1); exit(1);
......
...@@ -96,9 +96,7 @@ typedef struct __FILE_struct ...@@ -96,9 +96,7 @@ typedef struct __FILE_struct
* negative integral constant, indicates end-of-file, that is, no more input * negative integral constant, indicates end-of-file, that is, no more input
* from a stream. * from a stream.
*/ */
/* It is not clear to me what value FOPEN_MAX should have, so I will #define FOPEN_MAX _SYS_OPEN
err in the cautious direction - ANSI requires it to be at least 8 */
#define FOPEN_MAX 8 /* check re arthur/unix/mvs */
/* /*
* an integral constant expression that is the minimum number of files that * an integral constant expression that is the minimum number of files that
* this implementation guarantees can be open simultaneously. * this implementation guarantees can be open simultaneously.
...@@ -203,20 +201,24 @@ int fclose(FILE * /*stream*/); ...@@ -203,20 +201,24 @@ int fclose(FILE * /*stream*/);
* causes the stream pointed to by stream to be flushed and the associated * causes the stream pointed to by stream to be flushed and the associated
* file to be closed. Any unwritten buffered data for the stream are * file to be closed. Any unwritten buffered data for the stream are
* delivered to the host environment to be written to the file; any unread * delivered to the host environment to be written to the file; any unread
* buffered data are discarded. The stream is disassociated from the file. * buffered data are discarded. Whether or not the call succeeds, the stream
* If the associated buffer was automatically allocated, it is deallocated. * is disassociated from the file and any buffer set by the setbuf or
* Returns: zero if the stream was succesfully closed, or nonzero if any * setvbuf function is disassociated from the stream (and deallocated if it
* was automatically allocated).
* Returns: zero if the stream was succesfully closed, or EOF if any
* errors were detected or if the stream was already closed. * errors were detected or if the stream was already closed.
*/ */
int fflush(FILE * /*stream*/); int fflush(FILE * /*stream*/);
/* /*
* If the stream points to an output or update stream in which the most * If the stream points to an output stream or an update stream in which
* recent operation was output, the fflush function causes any unwritten * the most recent operation was not input, the fflush function causes any
* data for that stream to be delivered to the host environment to be * unwritten data for that stream to be delivered to the host environment to
* written to the file. If the stream points to an input or update stream, * be written to the file. If the stream points to an input or update
* the fflush function undoes the effect of any preceding ungetc operation * stream, the fflush function undoes the effect of any preceding ungetc
* on the stream. * operation on the stream.
* Returns: nonzero if a write error occurs. * If stream is a null pointer, the fflush function performs this flushing
* action on all streams for which the behaviour is defined above.
* Returns: EOF if a write error occurs.
*/ */
FILE *fopen(const char * restrict /*filename*/, FILE *fopen(const char * restrict /*filename*/,
const char * restrict /*mode*/); const char * restrict /*mode*/);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
EXPORT |CLib_data_end| EXPORT |CLib_data_end|
% 124*4 % 123*4
|CLib_data_end| |CLib_data_end|
END END
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment