Lichen

templates/native/io.c

570:4e9856fce8e3
2017-02-11 Paul Boddie Tidied up table output and made use of convenience macros. attr-strvalue-without-size
     1 /* Native functions for input/output.     2      3 Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk>     4      5 This program is free software; you can redistribute it and/or modify it under     6 the terms of the GNU General Public License as published by the Free Software     7 Foundation; either version 3 of the License, or (at your option) any later     8 version.     9     10 This program is distributed in the hope that it will be useful, but WITHOUT    11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    12 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more    13 details.    14     15 You should have received a copy of the GNU General Public License along with    16 this program.  If not, see <http://www.gnu.org/licenses/>.    17 */    18     19 #include <unistd.h> /* read, write */    20 #include <string.h> /* strcmp, memcpy */    21 #include <stdio.h>  /* fdopen, snprintf */    22 #include <errno.h>  /* errno */    23 #include "native/common.h"    24 #include "types.h"    25 #include "exceptions.h"    26 #include "ops.h"    27 #include "progconsts.h"    28 #include "progops.h"    29 #include "progtypes.h"    30 #include "main.h"    31     32 /* Input/output. */    33     34 __attr __fn_native_io_fclose(__attr __args[])    35 {    36     __attr * const fp = &__args[1];    37     /* fp interpreted as FILE reference */    38     FILE *f = (FILE *) fp->datavalue;    39     40     errno = 0;    41     if (fclose(f))    42         __raise_io_error(__new_int(errno));    43     44     return __builtins___none_None;    45 }    46     47 __attr __fn_native_io_fflush(__attr __args[])    48 {    49     __attr * const fp = &__args[1];    50     /* fp interpreted as FILE reference */    51     FILE *f = (FILE *) fp->datavalue;    52     53     errno = 0;    54     if (fflush(f))    55         __raise_io_error(__new_int(errno));    56     57     return __builtins___none_None;    58 }    59     60 __attr __fn_native_io_fopen(__attr __args[])    61 {    62     __attr * const filename = &__args[1];    63     __attr * const mode = &__args[2];    64     /* filename.__data__ interpreted as string */    65     char *fn = __load_via_object(filename->value, __pos___data__).strvalue;    66     /* mode.__data__ interpreted as string */    67     char *s = __load_via_object(mode->value, __pos___data__).strvalue;    68     FILE *f;    69     __attr attr;    70     71     errno = 0;    72     f = fopen(fn, s);    73     74     /* Produce an exception if the operation failed. */    75     76     if (f == NULL)    77         __raise_io_error(__new_int(errno));    78     79     /* Return the __data__ attribute. */    80     81     else    82     {    83         attr.context = 0;    84         attr.datavalue = (void *) f;    85         return attr;    86     }    87     88     /* Should never be reached: included to satisfy the compiler. */    89     90     return __builtins___none_None;    91 }    92     93 __attr __fn_native_io_fdopen(__attr __args[])    94 {    95     __attr * const fd = &__args[1];    96     __attr * const mode = &__args[2];    97     /* fd.__data__ interpreted as int */    98     int i = __load_via_object(fd->value, __pos___data__).intvalue;    99     /* mode.__data__ interpreted as string */   100     char *s = __load_via_object(mode->value, __pos___data__).strvalue;   101     FILE *f;   102     __attr attr;   103    104     errno = 0;   105     f = fdopen(i, s);   106    107     /* Produce an exception if the operation failed. */   108    109     if (f == NULL)   110         __raise_io_error(__new_int(errno));   111    112     /* Return the __data__ attribute. */   113    114     else   115     {   116         attr.context = 0;   117         attr.datavalue = (void *) f;   118         return attr;   119     }   120    121     /* Should never be reached: included to satisfy the compiler. */   122    123     return __builtins___none_None;   124 }   125    126 __attr __fn_native_io_fread(__attr __args[])   127 {   128     __attr * const fp = &__args[1];   129     __attr * const size = &__args[2];   130     /* fp interpreted as FILE reference */   131     FILE *f = (FILE *) fp->datavalue;   132     /* size.__data__ interpreted as int */   133     int to_read = __load_via_object(size->value, __pos___data__).intvalue;   134     char buf[to_read];   135     size_t have_read;   136     int error;   137     char *s;   138    139     have_read = fread(buf, sizeof(char), to_read, f);   140    141     if (have_read != to_read)   142     {   143         if (feof(f) && (have_read == 0))   144             __raise_eof_error();   145         else if ((error = ferror(f)))   146             __raise_io_error(__new_int(error));   147     }   148    149     /* Reserve space for a new string. */   150    151     s = __ALLOCATE(have_read + 1, sizeof(char));   152     memcpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */   153     return __new_str(s);   154 }   155    156 __attr __fn_native_io_fwrite(__attr __args[])   157 {   158     __attr * const fp = &__args[1];   159     __attr * const str = &__args[2];   160     /* fp interpreted as FILE reference */   161     FILE *f = (FILE *) fp->datavalue;   162     /* str.__data__ interpreted as string */   163     __attr sa = __load_via_object(str->value, __pos___data__);   164     char *s = sa.strvalue;   165     size_t to_write = strlen(sa.strvalue);   166     size_t have_written = fwrite(s, sizeof(char), to_write, f);   167     int error;   168    169     if (have_written != to_write)   170     {   171         if (feof(f))   172             __raise_eof_error();   173         else if ((error = ferror(f)))   174             __raise_io_error(__new_int(error));   175     }   176    177     return __builtins___none_None;   178 }   179    180 __attr __fn_native_io_close(__attr __args[])   181 {   182     __attr * const fd = &__args[1];   183     /* fd.__data__ interpreted as int */   184     int i = __load_via_object(fd->value, __pos___data__).intvalue;   185    186     errno = 0;   187     if (close(i) == -1)   188         __raise_io_error(__new_int(errno));   189    190     return __builtins___none_None;   191 }   192    193 __attr __fn_native_io_read(__attr __args[])   194 {   195     __attr * const fd = &__args[1];   196     __attr * const n = &__args[2];   197     /* fd.__data__ interpreted as int */   198     int i = __load_via_object(fd->value, __pos___data__).intvalue;   199     /* n.__data__ interpreted as int */   200     int to_read = __load_via_object(n->value, __pos___data__).intvalue;   201     char buf[to_read];   202     ssize_t have_read;   203     char *s;   204    205     errno = 0;   206     have_read = read(i, buf, to_read * sizeof(char));   207    208     if (have_read == -1)   209         __raise_io_error(__new_int(errno));   210    211     /* Reserve space for a new string. */   212    213     s = __ALLOCATE(have_read + 1, 1);   214     memcpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */   215     return __new_str(s);   216 }   217    218 __attr __fn_native_io_write(__attr __args[])   219 {   220     __attr * const fd = &__args[1];   221     __attr * const str = &__args[2];   222     /* fd.__data__ interpreted as int */   223     int i = __load_via_object(fd->value, __pos___data__).intvalue;   224     /* str.__data__ interpreted as string */   225     __attr sa = __load_via_object(str->value, __pos___data__);   226     char *s = sa.strvalue;   227     ssize_t have_written;   228    229     errno = 0;   230     have_written = write(i, s, sizeof(char) * strlen(sa.strvalue));   231    232     if (have_written == -1)   233         __raise_io_error(__new_int(errno));   234    235     return __new_int(have_written);   236 }   237    238 /* Module initialisation. */   239    240 void __main_native_io()   241 {   242 }