# HG changeset patch # User Paul Boddie # Date 1481060363 -3600 # Node ID 8c75cdf1a76476fb1bdc0576c84853b004a765c1 # Parent 9e4234566d9966ea15cff0e2fcbe51131c4bb4f9 Introduced stream classes employing C-level FILE pointers, changing the sys stdin, stdout and stderr objects to be instances of these stream classes. Added fread and fwrite support to the native functions. Added support for raising EOFError. diff -r 9e4234566d99 -r 8c75cdf1a764 lib/__builtins__/exception/io.py --- a/lib/__builtins__/exception/io.py Tue Dec 06 22:30:20 2016 +0100 +++ b/lib/__builtins__/exception/io.py Tue Dec 06 22:39:23 2016 +0100 @@ -19,7 +19,11 @@ this program. If not, see . """ -class EOFError(Exception): pass +class EOFError(Exception): + + "An end-of-file error." + + pass class IOError(Exception): diff -r 9e4234566d99 -r 8c75cdf1a764 lib/native.py --- a/lib/native.py Tue Dec 06 22:30:20 2016 +0100 +++ b/lib/native.py Tue Dec 06 22:39:23 2016 +0100 @@ -1,8 +1,12 @@ #!/usr/bin/env python """ -Native library functions. None of these are actually defined here. Instead, -native implementations are substituted when each program is built. +Native library functions. + +None of these are actually defined here. Instead, native implementations are +substituted when each program is built. It is, however, important to declare +non-core exceptions used by the native functions because they need to be +identified as being needed by the program. Copyright (C) 2011, 2015, 2016 Paul Boddie @@ -100,4 +104,12 @@ def _read(fd, n): IOError def _write(fd, str): pass +def _fread(fd, n): + IOError + EOFError + +def _fwrite(fd, str): + IOError + EOFError + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 9e4234566d99 -r 8c75cdf1a764 lib/posix/io.py --- a/lib/posix/io.py Tue Dec 06 22:30:20 2016 +0100 +++ b/lib/posix/io.py Tue Dec 06 22:39:23 2016 +0100 @@ -21,6 +21,8 @@ import native +# Abstractions for system-level files and streams. + class sysfile: "A system-level file object." @@ -33,15 +35,43 @@ def read(self, n): - "Read 'n' bytes from the file." + "Read 'n' bytes from the file, returning a string." + _check_int(n) return read(self.fd, n) def write(self, s): - "Write 's' to the file." + "Write string 's' to the file." + + _check_string(s) + write(self.fd, s) + +class sysstream: + + "A system-level stream object." + + def __init__(self, fd, mode="r"): + + "Initialise the stream with the given 'fd' and 'mode'." + + self.__data__ = fdopen(fd, mode) - write(self.fd, str(s)) + def read(self, n): + + "Read 'n' bytes from the stream." + + _check_int(n) + return native._fread(self.__data__, n) + + def write(self, s): + + "Write string 's' to the stream." + + _check_string(s) + native._fwrite(self.__data__, s) + +# Input/output functions. def close(fd): pass def closerange(fd_low, fd_high): pass @@ -104,6 +134,8 @@ _check_string(s) native._write(fd, s) +# Constants. + O_APPEND = 1024 O_ASYNC = 8192 O_CREAT = 64 @@ -124,6 +156,8 @@ O_TRUNC = 512 O_WRONLY = 1 +# Type validation functions. + def _check_fd(fd): "Check the given low-level file descriptor 'fd'." diff -r 9e4234566d99 -r 8c75cdf1a764 lib/sys.py --- a/lib/sys.py Tue Dec 06 22:30:20 2016 +0100 +++ b/lib/sys.py Tue Dec 06 22:39:23 2016 +0100 @@ -20,14 +20,14 @@ """ from __builtins__.int import maxint, minint -from posix.io import sysfile +from posix.io import sysstream import native # Standard streams. -stdin = sysfile(0) -stdout = sysfile(1) -stderr = sysfile(2) +stdin = sysstream(0) +stdout = sysstream(1, "w") +stderr = sysstream(2, "w") # NOTE: Environment details to be implemented. diff -r 9e4234566d99 -r 8c75cdf1a764 templates/native.c --- a/templates/native.c Tue Dec 06 22:30:20 2016 +0100 +++ b/templates/native.c Tue Dec 06 22:39:23 2016 +0100 @@ -675,6 +675,59 @@ } } +__attr __fn_native__fread(__attr __args[]) +{ + __attr * const fp = &__args[1]; + __attr * const size = &__args[2]; + /* fp interpreted as FILE reference */ + FILE *f = (FILE *) fp->datavalue; + /* size.__data__ interpreted as int */ + int to_read = __load_via_object(size->value, __pos___data__).intvalue; + char buf[to_read]; + size_t have_read; + int error; + char *s; + + have_read = fread(buf, sizeof(char), to_read, f); + + if (have_read != to_read) + { + if (feof(f)) + __raise_eof_error(); + else if (error = ferror(f)) + __raise_io_error(__new_int(error)); + } + + /* Reserve space for a new string. */ + + s = __ALLOCATE(have_read + 1, sizeof(char)); + strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */ + return __new_str(s); +} + +__attr __fn_native__fwrite(__attr __args[]) +{ + __attr * const fp = &__args[1]; + __attr * const str = &__args[2]; + /* fp interpreted as FILE reference */ + FILE *f = (FILE *) fp->datavalue; + /* str.__data__ interpreted as string */ + char *s = __load_via_object(str->value, __pos___data__).strvalue; + size_t to_write = strlen(s); + size_t have_written = fwrite(s, sizeof(char), to_write, f); + int error; + + if (have_written != to_write) + { + if (feof(f)) + __raise_eof_error(); + else if (error = ferror(f)) + __raise_io_error(__new_int(error)); + } + + return __builtins___none_None; +} + __attr __fn_native__read(__attr __args[]) { __attr * const fd = &__args[1]; @@ -695,6 +748,7 @@ else { /* Reserve space for a new string. */ + s = __ALLOCATE(have_read + 1, 1); strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */ return __new_str(s); diff -r 9e4234566d99 -r 8c75cdf1a764 templates/native.h --- a/templates/native.h Tue Dec 06 22:30:20 2016 +0100 +++ b/templates/native.h Tue Dec 06 22:39:23 2016 +0100 @@ -66,6 +66,8 @@ __attr __fn_native__issubclass(__attr __args[]); __attr __fn_native__fdopen(__attr __args[]); +__attr __fn_native__fread(__attr __args[]); +__attr __fn_native__fwrite(__attr __args[]); __attr __fn_native__read(__attr __args[]); __attr __fn_native__write(__attr __args[]); diff -r 9e4234566d99 -r 8c75cdf1a764 templates/progops.c --- a/templates/progops.c Tue Dec 06 22:30:20 2016 +0100 +++ b/templates/progops.c Tue Dec 06 22:39:23 2016 +0100 @@ -79,6 +79,15 @@ /* Helpers for raising errors within common operations. */ +#ifdef __HAVE___builtins___exception_io_EOFError +void __raise_eof_error() +{ + __attr args[1]; + __attr exc = __new___builtins___exception_io_EOFError(args); + __Raise(exc); +} +#endif /* __HAVE___builtins___exception_io_EOFError */ + #ifdef __HAVE___builtins___exception_io_IOError void __raise_io_error(__attr value) { diff -r 9e4234566d99 -r 8c75cdf1a764 templates/progops.h --- a/templates/progops.h Tue Dec 06 22:30:20 2016 +0100 +++ b/templates/progops.h Tue Dec 06 22:39:23 2016 +0100 @@ -17,6 +17,10 @@ /* Exception raising. */ +#ifdef __HAVE___builtins___exception_io_EOFError +void __raise_eof_error(); +#endif /* __HAVE___builtins___exception_io_EOFError */ + #ifdef __HAVE___builtins___exception_io_IOError void __raise_io_error(__attr value); #endif /* __HAVE___builtins___exception_io_IOError */