Commit 8dcb6880 authored by Ben Avison's avatar Ben Avison
Browse files

File handling improvements

Detail:
  * Added 64-bit file pointer API support, following the LFS spec v1.5
    (see Docs directory). Internally, now uses 64-bit file pointers
    exclusively. For now, the backend still limits you to 4GB-1 files, but
    clients of the C library won't need recompiling again to support larger
    files than this once they use the new API.
  * Fixed a large number of warnings produced in compilation, assembly and
    linking, many of them new and resulting from the improved checks in the
    latest toolchain.
  * Increased the maximum stream buffer size from 16MB to 1GB.
  * Added Hdr:SDFS and Hdr:SDIO to the list of headers used to build swis.h
    if they are present.
Admin:
  Verified that the new 64-bit file pointer buffering code works using a
  ROM build (since the toolchain makes extensive use of reading, writing
  and seeking internally).

Version 5.64. Tagged as 'RISC_OSLib-5_64'
parent 3f057115
This diff is collapsed.
......@@ -63,7 +63,7 @@ DIFF = gnu.diff -df >null:
AFLAGS = -depend !Depend
# The zz switch stops library static data being placed in a zero-init area
CFLAGS = -c -depend !Depend ${INCLUDES} -DDDE -fK -zz10000000
CFLAGS = -c -depend !Depend ${INCLUDES} -DDDE -fK -zz10000000 -jC:
CPFLAGS = ~cfr~v
WFLAGS = ~c~r~v
......
......@@ -60,6 +60,8 @@ IfThere Hdr:ScrBlank Then Echo <32> GET Hdr:ScrBlank { >> s.swioptions }
IfThere Hdr:ScrModes Then Echo <32> GET Hdr:ScrModes { >> s.swioptions }
IfThere Hdr:SCSI Then Echo <32> GET Hdr:SCSI { >> s.swioptions }
IfThere Hdr:SCSIFS Then Echo <32> GET Hdr:SCSIFS { >> s.swioptions }
IfThere Hdr:SDFS Then Echo <32> GET Hdr:SDFS { >> s.swioptions }
IfThere Hdr:SDIO Then Echo <32> GET Hdr:SDIO { >> s.swioptions }
IfThere Hdr:SharedCLib Then Echo <32> GET Hdr:SharedCLib { >> s.swioptions }
IfThere Hdr:Shell Then Echo <32> GET Hdr:Shell { >> s.swioptions }
IfThere Hdr:Sound Then Echo <32> GET Hdr:Sound { >> s.swioptions }
......
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "5.63"
Module_Version SETA 563
Module_MajorVersion SETS "5.64"
Module_Version SETA 564
Module_MinorVersion SETS ""
Module_Date SETS "28 Oct 2011"
Module_ApplicationDate SETS "28-Oct-11"
Module_ComponentName SETS "RISC_OSLib"
Module_ComponentPath SETS "castle/RiscOS/Sources/Lib/RISC_OSLib"
Module_FullVersion SETS "5.63"
Module_HelpVersion SETS "5.63 (28 Oct 2011)"
Module_FullVersion SETS "5.64"
Module_HelpVersion SETS "5.64 (28 Oct 2011)"
END
/* (5.63)
/* (5.64)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 5.63
#define Module_MajorVersion_CMHG 5.64
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 28 Oct 2011
#define Module_MajorVersion "5.63"
#define Module_Version 563
#define Module_MajorVersion "5.64"
#define Module_Version 564
#define Module_MinorVersion ""
#define Module_Date "28 Oct 2011"
......@@ -18,6 +18,6 @@
#define Module_ComponentName "RISC_OSLib"
#define Module_ComponentPath "castle/RiscOS/Sources/Lib/RISC_OSLib"
#define Module_FullVersion "5.63"
#define Module_HelpVersion "5.63 (28 Oct 2011)"
#define Module_LibraryVersionInfo "5:63"
#define Module_FullVersion "5.64"
#define Module_HelpVersion "5.64 (28 Oct 2011)"
#define Module_LibraryVersionInfo "5:64"
......@@ -20,6 +20,7 @@
/* version 11 */
#define __system_io 1 /* to get at flag bits */
#define _LARGEFILE64_SOURCE /* define 64-bit file pointer stuff in stdio.h */
#include "VersionNum"
......@@ -80,13 +81,13 @@ struct bbctime {unsigned int l,h;};
static clock_t _time0;
static clock_t _clock()
static clock_t _clock(void)
{ struct bbctime bt;
_bbctime(&bt);
return bt.l;
}
static void _clock_init() /* private - for initialisation */
static void _clock_init(void) /* private - for initialisation */
{ _time0 = _clock();
}
......@@ -97,7 +98,7 @@ static void _clock_ignore(clock_t t)
/* Exported... */
clock_t clock()
clock_t clock(void)
{ return _clock() - _time0; /* clock runs even if date not set */
}
......@@ -106,7 +107,7 @@ clock_t clock()
time_t time(time_t *timer)
/* this version gives the UNIX result of secs since 1-Jan-1970 */
{ time_t result;
int mctype;
/*int mctype;*/
struct bbctime bt, w, w2;
unsigned v;
_kernel_swi_regs r;
......@@ -159,7 +160,7 @@ time_t time(time_t *timer)
* and Wimp_ReadSysInfo 3 says we're in the desktop, and Wimp_ReadSysInfo 5 gives us a
* task handle.
*/
int _desktop_task()
int _desktop_task(void)
{
_kernel_swi_regs r;
if (_kernel_processor_mode() & 0xF) return 0;
......@@ -381,20 +382,49 @@ int _sys_istty(FILE *stream)
return istty(stream->__file);
}
int _sys_seek(FILEHANDLE fh, long pos)
int _sys_seek(FILEHANDLE fh, off64_t pos)
{
if istty(fh) return 0;
#if 1
/* Can't use _kernel_osargs, even for 32-bit file pointers, because it can't handle files of size 4G-2 .*/
/* Use _kernel_swi instead so that _kernel_last_oserror is set up on failure like it always was. */
_kernel_swi_regs r;
r.r[0] = 1;
r.r[1] = fh;
r.r[2] = (unsigned int) pos;
if (_kernel_swi(OS_Args, &r, &r) != NULL)
{
errno = -1;
return _kernel_ERROR;
}
return 0;
#else
{ int rc = _kernel_osargs(1, fh, (int)pos);
if (rc == _kernel_ERROR) errno = -1;
return rc;
}
#endif
}
long _sys_flen(FILEHANDLE fh)
off64_t _sys_flen(FILEHANDLE fh)
{
#if 1
/* Can't use _kernel_osargs, even for 32-bit file pointers, because it can't handle files of size 4G-2 .*/
/* Use _kernel_swi instead so that _kernel_last_oserror is set up on failure like it always was. */
_kernel_swi_regs r;
r.r[0] = 2;
r.r[1] = fh;
if (_kernel_swi(OS_Args, &r, &r) != NULL)
{
errno = -1;
return _kernel_ERROR;
}
return (unsigned int) r.r[2];
#else
int rc = _kernel_osargs(2, fh, 0);
if (rc == _kernel_ERROR) errno = -1;
return rc;
#endif
}
int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode)
......@@ -698,6 +728,7 @@ void _armsys_lib_init(void)
{ char *stdinfile = TTYFILENAME,
*stdoutfile = TTYFILENAME,
*stderrfile = TTYFILENAME;
(void) unused;
_getenv_value = NULL;
_error_recursion = 0;
_ctype_init(); /* C locale */
......
......@@ -320,7 +320,7 @@ void _set_ctype(int territory)
}
}
void _ctype_init()
void _ctype_init(void)
{
__ctype[-1] = IL; /* for ctype(EOF) */
_set_ctype(0);
......
......@@ -48,6 +48,7 @@
extern int _sprintf_lf(char *buff, const char *fmt, ...);
extern int __locales[5];
int __locales[5] = {0, 0, 0, 0, 0};
/* lc initialised to C for default */
......
......@@ -962,11 +962,13 @@ float modff(float value, float *iptr)
double nan(const char *s)
{
(void) s;
return (double) NAN;
}
float nanf(const char *s)
{
(void) s;
return NAN;
}
......
......@@ -117,7 +117,7 @@ static int printf_display(FILE *p, int flags, int ch, int precision, int width,
}
break;
case 'o': while(v!=0)
{ buff[len++] = '0' + (v & 07);
{ buff[len++] = '0' + (char)(v & 07);
v = v >> 3;
}
break;
......@@ -125,7 +125,7 @@ static int printf_display(FILE *p, int flags, int ch, int precision, int width,
case 'i':
case 'd': while (v != 0)
{ unsigned long long vDiv10 = v / 10U;
buff[len++] = '0' + v - vDiv10 * 10U;
buff[len++] = '0' + (char)(v - vDiv10 * 10U);
v = vDiv10;
}
break;
......
......@@ -842,6 +842,10 @@ typedef struct __extradata {
int __d;
int __e;
int __f;
#ifdef SUPPORT_WIDE
int __g;
mbstate_t __h;
#endif
} _extradata, *_extradatap;
int vsscanf(const char *buff, const char *fmt, va_list a)
......
......@@ -49,7 +49,7 @@ extern void __ignore_signal_handler(int sig)
static void _real_default_signal_handler(int sig)
{
char *s, v[128];
char *s = NULL, v[128];
_kernel_oserror *e = _kernel_peek_last_oserror();
if (((sig == SIGSEGV || sig == SIGILL) && _SignalNumber(e->errnum) == sig) ||
......@@ -179,7 +179,7 @@ void (*signal(int sig, void (*func)(int)))(int)
return oldf;
}
void _signal_init()
void _signal_init(void)
{
int i;
/* do the following initialisation explicitly so code restartable */
......
This diff is collapsed.
......@@ -536,6 +536,12 @@ char *_strerror(int n, char *v)
return _kernel_getmessage2("ERANGE - function result not representable", "C37", v, 80);
case ESIGNUM:
return _kernel_getmessage2("ESIGNUM - illegal signal number to signal() or raise()", "C66", v, 80);
case EILSEQ:
return _kernel_getmessage2("EILSEQ - character encoding error", "C74", v, 80);
case EOVERFLOW:
return _kernel_getmessage2("EOVERFLOW - too large for data structure", "C75", v, 80);
case EFBIG:
return _kernel_getmessage2("EFBIG - data written to file lost due to exceeding file size limit", "C76", v, 80);
default:
return _hostos_error_string(n, v);
}
......
......@@ -57,6 +57,7 @@ extern volatile int errno;
* acquires the value of the macro EDOM and HUGE_VAL is returned. EDOM may
* be used by non-mathematical functions.
*/
#define ERANGE 2
/*
* a range error occurs if the result of a function can not be represented
......@@ -70,7 +71,33 @@ extern volatile int errno;
* integer expression errno acquires the value of the macro ERANGE. ERANGE
* may be used by non-mathematical functions.
*/
#define ESIGNUM 3
/*
* a signal number error occurs if an unrecognised signal number is passed
* to signal() or raise().
*/
#define EILSEQ 4
/*
* an illegal sequence error indicates that a multibyte character encoding
* error has been detected.
*/
#define EOVERFLOW 5
/*
* an overflow error occurs if one or more fields of a data structure is
* not large enough to hold the values required - for example, if you
* attempt to open a file with fopen() whose size cannot be expressed using
* an object of type off_t.
*/
#define EFBIG 6
/*
* a big file error occurs if a file is unbuffered or the file's buffer
* needs to be flushed, and this would have resulted in a write occurring
* at or beyond the maximum file pointer for this file descriptor.
*/
#endif
......
......@@ -44,14 +44,45 @@ typedef char *__va_list[1]; /* keep in step with <stdarg.h> */
# define NULL 0 /* see <stddef.h> */
#endif
typedef struct __fpos_t_struct
{ unsigned long __lo; /* add hi one day */
} fpos_t;
typedef long int _off_t;
#ifdef __STDC__
typedef long long int _off64_t;
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 32
#endif
#if defined(__STDC__) && _FILE_OFFSET_BITS == 64
typedef _off64_t fpos_t;
#elif _FILE_OFFSET_BITS == 32
typedef _off_t fpos_t;
#else
#error Unsupported _FILE_OFFSET_BITS value
#endif
/*
* fpos_t is an object capable of recording all information needed to
* specify uniquely every position within a file.
*/
#if defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE)
typedef fpos_t off_t;
#endif
/*
* off_t is an object capable of recording the offset from any position
* within a file to any other position within that file, and is used by
* the LFS extension functions fseeko() and fello().
*/
#if defined(__STDC__) && defined(_LARGEFILE64_SOURCE)
typedef _off64_t fpos64_t, off64_t;
#endif
/*
* fpos64_t and of64_t are the equivalent of fpos_t and off_t respectively,
* and are used in their place when an application explicitly uses the
* 64-bit LFS extension functions fgetpo64(), fseeko64(), fsetpos64() and
* ftello64().
*/
typedef struct __FILE_struct
{ unsigned char *__ptr;
int __icnt; /* two separate _cnt fields so we can police ... */
......@@ -61,7 +92,7 @@ typedef struct __FILE_struct
/* are invisible in an ANSI-conforming program. */
unsigned char *__base; /* buffer base */
int __file; /* RISCOS/Arthur/Brazil file handle */
long __pos; /* position in file */
long __unused; /* used to contain 32-bit file pointer */
int __bufsiz; /* maximum buffer size */
int __signature; /* used with temporary files */
struct __extradata *__extrap; /* pointer to information about stream */
......@@ -172,6 +203,15 @@ int rename(const char * /*old*/, const char * /*new*/);
* original name.
*/
FILE *tmpfile(void);
#ifdef __STDC__
FILE *_tmpfile64(void);
#if _FILE_OFFSET_BITS == 64
#define tmpfile _tmpfile64
#endif
#ifdef _LARGEFILE64_SOURCE
#define tmpfile64 _tmpfile64
#endif
#endif
/*
* creates a temporary binary file that will be automatically removed when
* it is closed or at program termination. The file is opened for update.
......@@ -222,6 +262,16 @@ int fflush(FILE * /*stream*/);
*/
FILE *fopen(const char * restrict /*filename*/,
const char * restrict /*mode*/);
#ifdef __STDC__
FILE *_fopen64(const char * restrict /*filename*/,
const char * restrict /*mode*/);
#if _FILE_OFFSET_BITS == 64
#define fopen _fopen64
#endif
#ifdef _LARGEFILE64_SOURCE
#define fopen64 _fopen64
#endif
#endif
/*
* opens the file whose name is the string pointed to by filename, and
* associates a stream with it.
......@@ -267,6 +317,17 @@ FILE *fopen(const char * restrict /*filename*/,
FILE *freopen(const char * restrict /*filename*/,
const char * restrict /*mode*/,
FILE * restrict /*stream*/);
#ifdef __STDC__
FILE *_freopen64(const char * restrict /*filename*/,
const char * restrict /*mode*/,
FILE * restrict /*stream*/);
#if _FILE_OFFSET_BITS == 64
#define freopen _freopen64
#endif
#ifdef _LARGEFILE64_SOURCE
#define freopen64 _freopen64
#endif
#endif
/*
* opens the file whose name is the string pointed to by filename and
* associates the stream pointed to by stream with it. The mode argument is
......@@ -659,7 +720,16 @@ size_t fwrite(const void * restrict /*ptr*/,
* than nmemb only if a write error is encountered.
*/
int fgetpos(FILE * restrict /*stream*/, fpos_t * restrict /*pos*/);
int fgetpos(FILE * restrict /*stream*/, _off_t * restrict /*pos*/);
#ifdef __STDC__
int _fgetpos64(FILE * restrict /*stream*/, _off64_t * restrict /*pos*/);
#if _FILE_OFFSET_BITS == 64
#define fgetpos _fgetpos64
#endif
#ifdef _LARGEFILE64_SOURCE
#define fgetpos64 _fgetpos64
#endif
#endif
/*
* stores the current value of the file position indicator for the stream
* pointed to by stream in the object pointed to by pos. The value stored
......@@ -671,6 +741,20 @@ int fgetpos(FILE * restrict /*stream*/, fpos_t * restrict /*pos*/);
* nonzero value (under RISCOS/Arthur/Brazil fgetpos cannot fail).
*/
int fseek(FILE * /*stream*/, long int /*offset*/, int /*whence*/);
int _fseeko(FILE * /*stream*/, _off_t /*offset*/, int /*whence*/);
#if defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE)
#if _FILE_OFFSET_BITS == 64
#define fseeko _fseeko64
#else
#define fseeko _fseeko
#endif
#endif
#ifdef __STDC__
int _fseeko64(FILE * /*stream*/, _off64_t /*offset*/, int /*whence*/);
#ifdef _LARGEFILE64_SOURCE
#define fseeko64 _fseeko64
#endif
#endif
/*
* sets the file position indicator for the stream pointed to by stream.
* For a binary stream, the new position is at the signed number of
......@@ -687,7 +771,16 @@ int fseek(FILE * /*stream*/, long int /*offset*/, int /*whence*/);
* the next operation on an update stream may be either input or output.
* Returns: nonzero only for a request that cannot be satisfied.
*/
int fsetpos(FILE * /*stream*/, const fpos_t * /*pos*/);
int fsetpos(FILE * /*stream*/, const _off_t * /*pos*/);
#ifdef __STDC__
int _fsetpos64(FILE * /*stream*/, const _off64_t * /*pos*/);
#if _FILE_OFFSET_BITS == 64
#define fsetpos _fsetpos64
#endif
#ifdef _LARGEFILE64_SOURCE
#define fsetpos64 _fsetpos64
#endif
#endif
/*
* sets the file position indicator for the stream pointed to by stream
* according to the value of the object pointed to by pos, which shall be a
......@@ -702,6 +795,20 @@ int fsetpos(FILE * /*stream*/, const fpos_t * /*pos*/);
* in math.h).
*/
long int ftell(FILE * /*stream*/);
_off_t _ftello(FILE * /*stream*/);
#if defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE)
#if _FILE_OFFSET_BITS == 64
#define ftello _ftello64
#else
#define ftello _ftello
#endif
#endif
#ifdef __STDC__
_off64_t _ftello64(FILE * /*stream*/);
#ifdef _LARGEFILE64_SOURCE
#define ftello64 _ftello64
#endif
#endif
/*
* obtains the current value of the file position indicator for the stream
* pointed to by stream. For a binary stream, the value is the number of
......
......@@ -255,6 +255,10 @@ char *strerror(int /*errnum*/);
* EDOM "EDOM - function argument out of range"
* ERANGE "ERANGE - function result not representable"
* ESIGNUM "ESIGNUM - illegal signal number to signal() or raise()"
* EILSEQ "EILSEQ - character encoding error"
* EOVERFLOW "EOVERFLOW - too large for data structure"
* EFBIG "EFBIG - data written to file lost due to exceeding
* file size limit"
* -1 Error message from _kernel_lastoserror(), if any,
* else "unspecified error"
* others "unknown error"
......
......@@ -150,12 +150,12 @@ $Label
EXPORT |_ldfp|
EXPORT |_stfp|
EXPORT |__fpclassifyf|
EXPORT |__fpclassifyd|
EXPORT |__signbitf|
EXPORT |__signbitd|
EXPORT |__copysignf|
EXPORT |__copysignd|
EXPORT |__fpclassifyf| [FPREGARGS]
EXPORT |__fpclassifyd| [FPREGARGS]
EXPORT |__signbitf| [FPREGARGS]
EXPORT |__signbitd| [FPREGARGS]
EXPORT |__copysignf| [FPREGARGS]
EXPORT |__copysignd| [FPREGARGS]
EXPORT copysign
EXPORT copysignf
EXPORT nextafter
......@@ -237,7 +237,7 @@ $Label
BL |_lib_shutdown|
MOV a1, #0
BL |_exit|
LDMFD sp!, {r1} ; free the RMA block addressed by
LDR r1, [sp], #4 ; free the RMA block addressed by
MOV r0, #Module_Free ; our private word.
LDR r2, [r1]
MOV r3, #0
......@@ -267,9 +267,9 @@ EventHandler Keep
MOV a1, #SIGINT
STRNE a1, [ip, #O__saved_interrupt]
BNE %FT01
STMFD sp!, {r14}
STR r14, [sp, #-4]!
BL raise
LDMFD sp!, {r14}
LDR r14, [sp], #4
01 MOV a1, #1 ; we wish to handle it, but not just yet
Return ,LinkNotStacked
......@@ -284,9 +284,9 @@ UnhandledEventHandler Keep
MOV a1, #SIGINT
STRNE a1, [ip, #O__saved_interrupt]
BNE %FT02
STMFD sp!, {r14}
STR r14, [sp, #-4]!
BL raise
LDMFD sp!, {r14}
LDR r14, [sp], #4
02 MOV a1, #1 ; we wish to handle it, but not just yet
Return ,LinkNotStacked
......@@ -343,7 +343,7 @@ TrapHandler Keep
MOV a4, a1
STMFD sp!, {a2, a4, r14}
BL SignalNumber
STMFD sp!, {a1}
STR a1, [sp, #-4]!
BL |_signal_real_handler|
CMP a1, #0
LDMFD sp!, {a1, a2, a4, r14}
......@@ -403,7 +403,7 @@ llabs
; test for division by zero (used when division is voided)
TEQS a1, #0
Return ,LinkNotStacked, NE
STMFD sp!, {r0}
STR r0, [sp, #-4]!
ADR r0, E_DivideByZero
B |_kernel_fault|
......@@ -482,14 +482,14 @@ llabs
Return ,,CC
; and drop into writefail
writefail
LDMFD sp!, {lr}
STMFD sp!, {r0}
LDR lr, [sp], #4
STR r0, [sp, #-4]!
ADR r0, E_WriteFail
B |_kernel_fault|
readfail
LDMFD sp!, {lr}
STMFD sp!, {r0}
LDR lr, [sp], #4
STR r0, [sp, #-4]!
ADR r0, E_ReadFail
B |_kernel_fault|
......@@ -523,8 +523,8 @@ readfail
Return "v1"
NOOP
LDMIA a2!, {a4}
STMIA a1!, {a4}
LDR a4, [a2], #4
STR a4, [a1], #4
Return "v1"
; Note that the number of instructions is critical for the SUBLT
......@@ -545,7 +545,7 @@ readfail
STMIA a1!, {a2, a4}
Return
STMIA a1!, {a4}
STR a4, [a1], #4
Return
mesg DCB "mesg"
......@@ -598,7 +598,7 @@ postmortem1
postmortem2
LDMFD sp!, {r0-r5}
BL |_kernel_fpavailable|
LDMFD sp!, {r14}
LDR r14, [sp], #4
CMP a1, #0
MOV ip, sp
SUBEQ sp, sp, #12*4
......@@ -731,7 +731,13 @@ sj_f7 # 3*4
STMIA a1, {sl, lr}
SUB v1, a1, #sj_sl
|
[ {FALSE} ; this instruction is now deprecated
STMIA a1, {v1-v6, sl, fp, sp, lr}
|