Lichen

templates/native/io.c

934:2989aab1b4f7
10 months ago Paul Boddie Renamed the utf8string class to unicode, eliminating the unicode function. This means that the simple case of merely returning an object if it is already a Unicode object no longer occurs when using the unicode callable, but such behaviour might be better supported with more general customised instantiation functionality.
     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 __self, __attr fp)    35 {    36     /* fp interpreted as FILE reference */    37     FILE *f = (FILE *) fp.datavalue;    38     39     errno = 0;    40     if (fclose(f))    41         __raise_io_error(__new_int(errno));    42     43     return __builtins___none_None;    44 }    45     46 __attr __fn_native_io_fflush(__attr __self, __attr fp)    47 {    48     /* fp interpreted as FILE reference */    49     FILE *f = (FILE *) fp.datavalue;    50     51     errno = 0;    52     if (fflush(f))    53         __raise_io_error(__new_int(errno));    54     55     return __builtins___none_None;    56 }    57     58 __attr __fn_native_io_fopen(__attr __self, __attr filename, __attr mode)    59 {    60     /* filename.__data__ interpreted as string */    61     char *fn = __load_via_object(__VALUE(filename), __data__).strvalue;    62     /* mode.__data__ interpreted as string */    63     char *s = __load_via_object(__VALUE(mode), __data__).strvalue;    64     FILE *f;    65     __attr attr;    66     67     errno = 0;    68     f = fopen(fn, s);    69     70     /* Produce an exception if the operation failed. */    71     72     if (f == NULL)    73         __raise_io_error(__new_int(errno));    74     75     /* Return the __data__ attribute. */    76     77     else    78     {    79         attr.datavalue = (void *) f;    80         return attr;    81     }    82     83     /* Should never be reached: included to satisfy the compiler. */    84     85     return __builtins___none_None;    86 }    87     88 __attr __fn_native_io_fdopen(__attr __self, __attr fd, __attr mode)    89 {    90     /* fd interpreted as int */    91     int i = __TOINT(fd);    92     /* mode.__data__ interpreted as string */    93     char *s = __load_via_object(__VALUE(mode), __data__).strvalue;    94     FILE *f;    95     __attr attr;    96     97     errno = 0;    98     f = fdopen(i, s);    99    100     /* Produce an exception if the operation failed. */   101    102     if (f == NULL)   103         __raise_io_error(__new_int(errno));   104    105     /* Return the __data__ attribute. */   106    107     else   108     {   109         attr.datavalue = (void *) f;   110         return attr;   111     }   112    113     /* Should never be reached: included to satisfy the compiler. */   114    115     return __builtins___none_None;   116 }   117    118 __attr __fn_native_io_fread(__attr __self, __attr fp, __attr size)   119 {   120     /* fp interpreted as FILE reference */   121     FILE *f = (FILE *) fp.datavalue;   122     /* size interpreted as int */   123     int to_read = __TOINT(size);   124     char buf[to_read];   125     size_t have_read;   126     int error;   127     char *s;   128    129     have_read = fread(buf, sizeof(char), to_read, f);   130    131     if (have_read != to_read)   132     {   133         if (feof(f) && (have_read == 0))   134             __raise_eof_error();   135         else if ((error = ferror(f)))   136             __raise_io_error(__new_int(error));   137     }   138    139     /* Reserve space for a new string. */   140    141     s = __ALLOCATE(have_read + 1, sizeof(char));   142     memcpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */   143     return __new_str(s, have_read);   144 }   145    146 __attr __fn_native_io_fwrite(__attr __self, __attr fp, __attr str)   147 {   148     /* fp interpreted as FILE reference */   149     FILE *f = (FILE *) fp.datavalue;   150     /* str.__data__ interpreted as string */   151     char *s = __load_via_object(__VALUE(str), __data__).strvalue;   152     /* str.__size__ interpreted as int */   153     int to_write = __TOINT(__load_via_object(__VALUE(str), __size__));   154     size_t have_written = fwrite(s, sizeof(char), to_write, f);   155     int error;   156    157     if (have_written != to_write)   158     {   159         if (feof(f))   160             __raise_eof_error();   161         else if ((error = ferror(f)))   162             __raise_io_error(__new_int(error));   163     }   164    165     return __builtins___none_None;   166 }   167    168 __attr __fn_native_io_close(__attr __self, __attr fd)   169 {   170     /* fd interpreted as int */   171     int i = __TOINT(fd);   172    173     errno = 0;   174     if (close(i) == -1)   175         __raise_io_error(__new_int(errno));   176    177     return __builtins___none_None;   178 }   179    180 __attr __fn_native_io_read(__attr __self, __attr fd, __attr n)   181 {   182     /* fd interpreted as int */   183     int i = __TOINT(fd);   184     /* n interpreted as int */   185     int to_read = __TOINT(n);   186     char buf[to_read];   187     ssize_t have_read;   188     char *s;   189    190     errno = 0;   191     have_read = read(i, buf, to_read * sizeof(char));   192    193     if (have_read == -1)   194         __raise_io_error(__new_int(errno));   195    196     /* Reserve space for a new string. */   197    198     s = __ALLOCATE(have_read + 1, 1);   199     memcpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */   200     return __new_str(s, have_read);   201 }   202    203 __attr __fn_native_io_write(__attr __self, __attr fd, __attr str)   204 {   205     /* fd interpreted as int */   206     int i = __TOINT(fd);   207     /* str.__data__ interpreted as string */   208     char *s = __load_via_object(__VALUE(str), __data__).strvalue;   209     /* str.__size__ interpreted as int */   210     int size = __TOINT(__load_via_object(__VALUE(str), __size__));   211     ssize_t have_written;   212    213     errno = 0;   214     have_written = write(i, s, sizeof(char) * size);   215    216     if (have_written == -1)   217         __raise_io_error(__new_int(errno));   218    219     return __new_int(have_written);   220 }   221    222 /* Module initialisation. */   223    224 void __main_native_io()   225 {   226 }