1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/templates/native/io.c Fri Dec 09 16:22:37 2016 +0100
1.3 @@ -0,0 +1,219 @@
1.4 +/* Native functions for input/output.
1.5 +
1.6 +Copyright (C) 2016 Paul Boddie <paul@boddie.org.uk>
1.7 +
1.8 +This program is free software; you can redistribute it and/or modify it under
1.9 +the terms of the GNU General Public License as published by the Free Software
1.10 +Foundation; either version 3 of the License, or (at your option) any later
1.11 +version.
1.12 +
1.13 +This program is distributed in the hope that it will be useful, but WITHOUT
1.14 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.15 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.16 +details.
1.17 +
1.18 +You should have received a copy of the GNU General Public License along with
1.19 +this program. If not, see <http://www.gnu.org/licenses/>.
1.20 +*/
1.21 +
1.22 +#include <unistd.h> /* read, write */
1.23 +#include <string.h> /* strcmp, strncpy, strlen */
1.24 +#include <stdio.h> /* fdopen, snprintf */
1.25 +#include <errno.h> /* errno */
1.26 +#include "native/common.h"
1.27 +#include "types.h"
1.28 +#include "exceptions.h"
1.29 +#include "ops.h"
1.30 +#include "progconsts.h"
1.31 +#include "progops.h"
1.32 +#include "progtypes.h"
1.33 +#include "main.h"
1.34 +
1.35 +/* Input/output. */
1.36 +
1.37 +__attr __fn_native_io_fclose(__attr __args[])
1.38 +{
1.39 + __attr * const fp = &__args[1];
1.40 + /* fp interpreted as FILE reference */
1.41 + FILE *f = (FILE *) fp->datavalue;
1.42 +
1.43 + errno = 0;
1.44 + if (fclose(f))
1.45 + __raise_io_error(__new_int(errno));
1.46 +
1.47 + return __builtins___none_None;
1.48 +}
1.49 +
1.50 +__attr __fn_native_io_fopen(__attr __args[])
1.51 +{
1.52 + __attr * const filename = &__args[1];
1.53 + __attr * const mode = &__args[2];
1.54 + /* filename.__data__ interpreted as string */
1.55 + char *fn = __load_via_object(filename->value, __pos___data__).strvalue;
1.56 + /* mode.__data__ interpreted as string */
1.57 + char *s = __load_via_object(mode->value, __pos___data__).strvalue;
1.58 + FILE *f;
1.59 + __attr attr;
1.60 +
1.61 + errno = 0;
1.62 + f = fopen(fn, s);
1.63 +
1.64 + /* Produce an exception if the operation failed. */
1.65 +
1.66 + if (f == NULL)
1.67 + __raise_io_error(__new_int(errno));
1.68 +
1.69 + /* Return the __data__ attribute. */
1.70 +
1.71 + else
1.72 + {
1.73 + attr.context = 0;
1.74 + attr.datavalue = (void *) f;
1.75 + return attr;
1.76 + }
1.77 +}
1.78 +
1.79 +__attr __fn_native_io_fdopen(__attr __args[])
1.80 +{
1.81 + __attr * const fd = &__args[1];
1.82 + __attr * const mode = &__args[2];
1.83 + /* fd.__data__ interpreted as int */
1.84 + int i = __load_via_object(fd->value, __pos___data__).intvalue;
1.85 + /* mode.__data__ interpreted as string */
1.86 + char *s = __load_via_object(mode->value, __pos___data__).strvalue;
1.87 + FILE *f;
1.88 + __attr attr;
1.89 +
1.90 + errno = 0;
1.91 + f = fdopen(i, s);
1.92 +
1.93 + /* Produce an exception if the operation failed. */
1.94 +
1.95 + if (f == NULL)
1.96 + __raise_io_error(__new_int(errno));
1.97 +
1.98 + /* Return the __data__ attribute. */
1.99 +
1.100 + else
1.101 + {
1.102 + attr.context = 0;
1.103 + attr.datavalue = (void *) f;
1.104 + return attr;
1.105 + }
1.106 +}
1.107 +
1.108 +__attr __fn_native_io_fread(__attr __args[])
1.109 +{
1.110 + __attr * const fp = &__args[1];
1.111 + __attr * const size = &__args[2];
1.112 + /* fp interpreted as FILE reference */
1.113 + FILE *f = (FILE *) fp->datavalue;
1.114 + /* size.__data__ interpreted as int */
1.115 + int to_read = __load_via_object(size->value, __pos___data__).intvalue;
1.116 + char buf[to_read];
1.117 + size_t have_read;
1.118 + int error;
1.119 + char *s;
1.120 +
1.121 + have_read = fread(buf, sizeof(char), to_read, f);
1.122 +
1.123 + if (have_read != to_read)
1.124 + {
1.125 + if (feof(f) && (have_read == 0))
1.126 + __raise_eof_error();
1.127 + else if (error = ferror(f))
1.128 + __raise_io_error(__new_int(error));
1.129 + }
1.130 +
1.131 + /* Reserve space for a new string. */
1.132 +
1.133 + s = __ALLOCATE(have_read + 1, sizeof(char));
1.134 + strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
1.135 + return __new_str(s);
1.136 +}
1.137 +
1.138 +__attr __fn_native_io_fwrite(__attr __args[])
1.139 +{
1.140 + __attr * const fp = &__args[1];
1.141 + __attr * const str = &__args[2];
1.142 + /* fp interpreted as FILE reference */
1.143 + FILE *f = (FILE *) fp->datavalue;
1.144 + /* str.__data__ interpreted as string */
1.145 + char *s = __load_via_object(str->value, __pos___data__).strvalue;
1.146 + size_t to_write = strlen(s);
1.147 + size_t have_written = fwrite(s, sizeof(char), to_write, f);
1.148 + int error;
1.149 +
1.150 + if (have_written != to_write)
1.151 + {
1.152 + if (feof(f))
1.153 + __raise_eof_error();
1.154 + else if (error = ferror(f))
1.155 + __raise_io_error(__new_int(error));
1.156 + }
1.157 +
1.158 + return __builtins___none_None;
1.159 +}
1.160 +
1.161 +__attr __fn_native_io_close(__attr __args[])
1.162 +{
1.163 + __attr * const fd = &__args[1];
1.164 + /* fd.__data__ interpreted as int */
1.165 + int i = __load_via_object(fd->value, __pos___data__).intvalue;
1.166 +
1.167 + errno = 0;
1.168 + if (close(i) == -1)
1.169 + __raise_io_error(__new_int(errno));
1.170 +
1.171 + return __builtins___none_None;
1.172 +}
1.173 +
1.174 +__attr __fn_native_io_read(__attr __args[])
1.175 +{
1.176 + __attr * const fd = &__args[1];
1.177 + __attr * const n = &__args[2];
1.178 + /* fd.__data__ interpreted as int */
1.179 + int i = __load_via_object(fd->value, __pos___data__).intvalue;
1.180 + /* n.__data__ interpreted as int */
1.181 + int to_read = __load_via_object(n->value, __pos___data__).intvalue;
1.182 + char buf[to_read];
1.183 + ssize_t have_read;
1.184 + char *s;
1.185 +
1.186 + errno = 0;
1.187 + have_read = read(i, buf, to_read * sizeof(char));
1.188 +
1.189 + if (have_read == -1)
1.190 + __raise_io_error(__new_int(errno));
1.191 +
1.192 + /* Reserve space for a new string. */
1.193 +
1.194 + s = __ALLOCATE(have_read + 1, 1);
1.195 + strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
1.196 + return __new_str(s);
1.197 +}
1.198 +
1.199 +__attr __fn_native_io_write(__attr __args[])
1.200 +{
1.201 + __attr * const fd = &__args[1];
1.202 + __attr * const str = &__args[2];
1.203 + /* fd.__data__ interpreted as int */
1.204 + int i = __load_via_object(fd->value, __pos___data__).intvalue;
1.205 + /* str.__data__ interpreted as string */
1.206 + char *s = __load_via_object(str->value, __pos___data__).strvalue;
1.207 + ssize_t have_written;
1.208 +
1.209 + errno = 0;
1.210 + have_written = write(i, s, sizeof(char) * strlen(s));
1.211 +
1.212 + if (have_written == -1)
1.213 + __raise_io_error(__new_int(errno));
1.214 +
1.215 + return __new_int(have_written);
1.216 +}
1.217 +
1.218 +/* Module initialisation. */
1.219 +
1.220 +void __main_native_io()
1.221 +{
1.222 +}