Lichen

templates/native/io.c

750:44ea0968a550
2017-03-20 Paul Boddie Added the context identity to the AttrResult string representation.
     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, __data__).strvalue;    66     /* mode.__data__ interpreted as string */    67     char *s = __load_via_object(mode->value, __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.datavalue = (void *) f;    84         return attr;    85     }    86     87     /* Should never be reached: included to satisfy the compiler. */    88     89     return __builtins___none_None;    90 }    91     92 __attr __fn_native_io_fdopen(__attr __args[])    93 {    94     __attr * const fd = &__args[1];    95     __attr * const mode = &__args[2];    96     /* fd.__data__ interpreted as int */    97     int i = __load_via_object(fd->value, __data__).intvalue;    98     /* mode.__data__ interpreted as string */    99     char *s = __load_via_object(mode->value, __data__).strvalue;   100     FILE *f;   101     __attr attr;   102    103     errno = 0;   104     f = fdopen(i, s);   105    106     /* Produce an exception if the operation failed. */   107    108     if (f == NULL)   109         __raise_io_error(__new_int(errno));   110    111     /* Return the __data__ attribute. */   112    113     else   114     {   115         attr.datavalue = (void *) f;   116         return attr;   117     }   118    119     /* Should never be reached: included to satisfy the compiler. */   120    121     return __builtins___none_None;   122 }   123    124 __attr __fn_native_io_fread(__attr __args[])   125 {   126     __attr * const fp = &__args[1];   127     __attr * const size = &__args[2];   128     /* fp interpreted as FILE reference */   129     FILE *f = (FILE *) fp->datavalue;   130     /* size.__data__ interpreted as int */   131     int to_read = __load_via_object(size->value, __data__).intvalue;   132     char buf[to_read];   133     size_t have_read;   134     int error;   135     char *s;   136    137     have_read = fread(buf, sizeof(char), to_read, f);   138    139     if (have_read != to_read)   140     {   141         if (feof(f) && (have_read == 0))   142             __raise_eof_error();   143         else if ((error = ferror(f)))   144             __raise_io_error(__new_int(error));   145     }   146    147     /* Reserve space for a new string. */   148    149     s = __ALLOCATE(have_read + 1, sizeof(char));   150     memcpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */   151     return __new_str(s, have_read);   152 }   153    154 __attr __fn_native_io_fwrite(__attr __args[])   155 {   156     __attr * const fp = &__args[1];   157     __attr * const str = &__args[2];   158     /* fp interpreted as FILE reference */   159     FILE *f = (FILE *) fp->datavalue;   160     /* str.__data__ interpreted as string */   161     char *s = __load_via_object(str->value, __data__).strvalue;   162     /* str.__size__ interpreted as int */   163     int to_write = __load_via_object(str->value, __size__).intvalue;   164     size_t have_written = fwrite(s, sizeof(char), to_write, f);   165     int error;   166    167     if (have_written != to_write)   168     {   169         if (feof(f))   170             __raise_eof_error();   171         else if ((error = ferror(f)))   172             __raise_io_error(__new_int(error));   173     }   174    175     return __builtins___none_None;   176 }   177    178 __attr __fn_native_io_close(__attr __args[])   179 {   180     __attr * const fd = &__args[1];   181     /* fd.__data__ interpreted as int */   182     int i = __load_via_object(fd->value, __data__).intvalue;   183    184     errno = 0;   185     if (close(i) == -1)   186         __raise_io_error(__new_int(errno));   187    188     return __builtins___none_None;   189 }   190    191 __attr __fn_native_io_read(__attr __args[])   192 {   193     __attr * const fd = &__args[1];   194     __attr * const n = &__args[2];   195     /* fd.__data__ interpreted as int */   196     int i = __load_via_object(fd->value, __data__).intvalue;   197     /* n.__data__ interpreted as int */   198     int to_read = __load_via_object(n->value, __data__).intvalue;   199     char buf[to_read];   200     ssize_t have_read;   201     char *s;   202    203     errno = 0;   204     have_read = read(i, buf, to_read * sizeof(char));   205    206     if (have_read == -1)   207         __raise_io_error(__new_int(errno));   208    209     /* Reserve space for a new string. */   210    211     s = __ALLOCATE(have_read + 1, 1);   212     memcpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */   213     return __new_str(s, have_read);   214 }   215    216 __attr __fn_native_io_write(__attr __args[])   217 {   218     __attr * const fd = &__args[1];   219     __attr * const str = &__args[2];   220     /* fd.__data__ interpreted as int */   221     int i = __load_via_object(fd->value, __data__).intvalue;   222     /* str.__data__ interpreted as string */   223     char *s = __load_via_object(str->value, __data__).strvalue;   224     /* str.__size__ interpreted as int */   225     int size = __load_via_object(str->value, __size__).intvalue;   226     ssize_t have_written;   227    228     errno = 0;   229     have_written = write(i, s, sizeof(char) * size);   230    231     if (have_written == -1)   232         __raise_io_error(__new_int(errno));   233    234     return __new_int(have_written);   235 }   236    237 /* Module initialisation. */   238    239 void __main_native_io()   240 {   241 }