1.1 --- a/lib/__builtins__/exception/io.py Tue Dec 06 22:30:20 2016 +0100
1.2 +++ b/lib/__builtins__/exception/io.py Tue Dec 06 22:39:23 2016 +0100
1.3 @@ -19,7 +19,11 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -class EOFError(Exception): pass
1.8 +class EOFError(Exception):
1.9 +
1.10 + "An end-of-file error."
1.11 +
1.12 + pass
1.13
1.14 class IOError(Exception):
1.15
2.1 --- a/lib/native.py Tue Dec 06 22:30:20 2016 +0100
2.2 +++ b/lib/native.py Tue Dec 06 22:39:23 2016 +0100
2.3 @@ -1,8 +1,12 @@
2.4 #!/usr/bin/env python
2.5
2.6 """
2.7 -Native library functions. None of these are actually defined here. Instead,
2.8 -native implementations are substituted when each program is built.
2.9 +Native library functions.
2.10 +
2.11 +None of these are actually defined here. Instead, native implementations are
2.12 +substituted when each program is built. It is, however, important to declare
2.13 +non-core exceptions used by the native functions because they need to be
2.14 +identified as being needed by the program.
2.15
2.16 Copyright (C) 2011, 2015, 2016 Paul Boddie <paul@boddie.org.uk>
2.17
2.18 @@ -100,4 +104,12 @@
2.19 def _read(fd, n): IOError
2.20 def _write(fd, str): pass
2.21
2.22 +def _fread(fd, n):
2.23 + IOError
2.24 + EOFError
2.25 +
2.26 +def _fwrite(fd, str):
2.27 + IOError
2.28 + EOFError
2.29 +
2.30 # vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/lib/posix/io.py Tue Dec 06 22:30:20 2016 +0100
3.2 +++ b/lib/posix/io.py Tue Dec 06 22:39:23 2016 +0100
3.3 @@ -21,6 +21,8 @@
3.4
3.5 import native
3.6
3.7 +# Abstractions for system-level files and streams.
3.8 +
3.9 class sysfile:
3.10
3.11 "A system-level file object."
3.12 @@ -33,15 +35,43 @@
3.13
3.14 def read(self, n):
3.15
3.16 - "Read 'n' bytes from the file."
3.17 + "Read 'n' bytes from the file, returning a string."
3.18
3.19 + _check_int(n)
3.20 return read(self.fd, n)
3.21
3.22 def write(self, s):
3.23
3.24 - "Write 's' to the file."
3.25 + "Write string 's' to the file."
3.26 +
3.27 + _check_string(s)
3.28 + write(self.fd, s)
3.29 +
3.30 +class sysstream:
3.31 +
3.32 + "A system-level stream object."
3.33 +
3.34 + def __init__(self, fd, mode="r"):
3.35 +
3.36 + "Initialise the stream with the given 'fd' and 'mode'."
3.37 +
3.38 + self.__data__ = fdopen(fd, mode)
3.39
3.40 - write(self.fd, str(s))
3.41 + def read(self, n):
3.42 +
3.43 + "Read 'n' bytes from the stream."
3.44 +
3.45 + _check_int(n)
3.46 + return native._fread(self.__data__, n)
3.47 +
3.48 + def write(self, s):
3.49 +
3.50 + "Write string 's' to the stream."
3.51 +
3.52 + _check_string(s)
3.53 + native._fwrite(self.__data__, s)
3.54 +
3.55 +# Input/output functions.
3.56
3.57 def close(fd): pass
3.58 def closerange(fd_low, fd_high): pass
3.59 @@ -104,6 +134,8 @@
3.60 _check_string(s)
3.61 native._write(fd, s)
3.62
3.63 +# Constants.
3.64 +
3.65 O_APPEND = 1024
3.66 O_ASYNC = 8192
3.67 O_CREAT = 64
3.68 @@ -124,6 +156,8 @@
3.69 O_TRUNC = 512
3.70 O_WRONLY = 1
3.71
3.72 +# Type validation functions.
3.73 +
3.74 def _check_fd(fd):
3.75
3.76 "Check the given low-level file descriptor 'fd'."
4.1 --- a/lib/sys.py Tue Dec 06 22:30:20 2016 +0100
4.2 +++ b/lib/sys.py Tue Dec 06 22:39:23 2016 +0100
4.3 @@ -20,14 +20,14 @@
4.4 """
4.5
4.6 from __builtins__.int import maxint, minint
4.7 -from posix.io import sysfile
4.8 +from posix.io import sysstream
4.9 import native
4.10
4.11 # Standard streams.
4.12
4.13 -stdin = sysfile(0)
4.14 -stdout = sysfile(1)
4.15 -stderr = sysfile(2)
4.16 +stdin = sysstream(0)
4.17 +stdout = sysstream(1, "w")
4.18 +stderr = sysstream(2, "w")
4.19
4.20 # NOTE: Environment details to be implemented.
4.21
5.1 --- a/templates/native.c Tue Dec 06 22:30:20 2016 +0100
5.2 +++ b/templates/native.c Tue Dec 06 22:39:23 2016 +0100
5.3 @@ -675,6 +675,59 @@
5.4 }
5.5 }
5.6
5.7 +__attr __fn_native__fread(__attr __args[])
5.8 +{
5.9 + __attr * const fp = &__args[1];
5.10 + __attr * const size = &__args[2];
5.11 + /* fp interpreted as FILE reference */
5.12 + FILE *f = (FILE *) fp->datavalue;
5.13 + /* size.__data__ interpreted as int */
5.14 + int to_read = __load_via_object(size->value, __pos___data__).intvalue;
5.15 + char buf[to_read];
5.16 + size_t have_read;
5.17 + int error;
5.18 + char *s;
5.19 +
5.20 + have_read = fread(buf, sizeof(char), to_read, f);
5.21 +
5.22 + if (have_read != to_read)
5.23 + {
5.24 + if (feof(f))
5.25 + __raise_eof_error();
5.26 + else if (error = ferror(f))
5.27 + __raise_io_error(__new_int(error));
5.28 + }
5.29 +
5.30 + /* Reserve space for a new string. */
5.31 +
5.32 + s = __ALLOCATE(have_read + 1, sizeof(char));
5.33 + strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
5.34 + return __new_str(s);
5.35 +}
5.36 +
5.37 +__attr __fn_native__fwrite(__attr __args[])
5.38 +{
5.39 + __attr * const fp = &__args[1];
5.40 + __attr * const str = &__args[2];
5.41 + /* fp interpreted as FILE reference */
5.42 + FILE *f = (FILE *) fp->datavalue;
5.43 + /* str.__data__ interpreted as string */
5.44 + char *s = __load_via_object(str->value, __pos___data__).strvalue;
5.45 + size_t to_write = strlen(s);
5.46 + size_t have_written = fwrite(s, sizeof(char), to_write, f);
5.47 + int error;
5.48 +
5.49 + if (have_written != to_write)
5.50 + {
5.51 + if (feof(f))
5.52 + __raise_eof_error();
5.53 + else if (error = ferror(f))
5.54 + __raise_io_error(__new_int(error));
5.55 + }
5.56 +
5.57 + return __builtins___none_None;
5.58 +}
5.59 +
5.60 __attr __fn_native__read(__attr __args[])
5.61 {
5.62 __attr * const fd = &__args[1];
5.63 @@ -695,6 +748,7 @@
5.64 else
5.65 {
5.66 /* Reserve space for a new string. */
5.67 +
5.68 s = __ALLOCATE(have_read + 1, 1);
5.69 strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
5.70 return __new_str(s);
6.1 --- a/templates/native.h Tue Dec 06 22:30:20 2016 +0100
6.2 +++ b/templates/native.h Tue Dec 06 22:39:23 2016 +0100
6.3 @@ -66,6 +66,8 @@
6.4 __attr __fn_native__issubclass(__attr __args[]);
6.5
6.6 __attr __fn_native__fdopen(__attr __args[]);
6.7 +__attr __fn_native__fread(__attr __args[]);
6.8 +__attr __fn_native__fwrite(__attr __args[]);
6.9 __attr __fn_native__read(__attr __args[]);
6.10 __attr __fn_native__write(__attr __args[]);
6.11
7.1 --- a/templates/progops.c Tue Dec 06 22:30:20 2016 +0100
7.2 +++ b/templates/progops.c Tue Dec 06 22:39:23 2016 +0100
7.3 @@ -79,6 +79,15 @@
7.4
7.5 /* Helpers for raising errors within common operations. */
7.6
7.7 +#ifdef __HAVE___builtins___exception_io_EOFError
7.8 +void __raise_eof_error()
7.9 +{
7.10 + __attr args[1];
7.11 + __attr exc = __new___builtins___exception_io_EOFError(args);
7.12 + __Raise(exc);
7.13 +}
7.14 +#endif /* __HAVE___builtins___exception_io_EOFError */
7.15 +
7.16 #ifdef __HAVE___builtins___exception_io_IOError
7.17 void __raise_io_error(__attr value)
7.18 {
8.1 --- a/templates/progops.h Tue Dec 06 22:30:20 2016 +0100
8.2 +++ b/templates/progops.h Tue Dec 06 22:39:23 2016 +0100
8.3 @@ -17,6 +17,10 @@
8.4
8.5 /* Exception raising. */
8.6
8.7 +#ifdef __HAVE___builtins___exception_io_EOFError
8.8 +void __raise_eof_error();
8.9 +#endif /* __HAVE___builtins___exception_io_EOFError */
8.10 +
8.11 #ifdef __HAVE___builtins___exception_io_IOError
8.12 void __raise_io_error(__attr value);
8.13 #endif /* __HAVE___builtins___exception_io_IOError */