LCOV - code coverage report
Current view: top level - src/flisp - iostream.c (source / functions) Hit Total Coverage
Test: [build process] commit ef510b1f346f4c9f9d86eaceace5ca54961a1dbc Lines: 157 275 57.1 %
Date: 2022-07-17 01:01:28 Functions: 25 36 69.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 41 124 33.1 %

           Branch data     Line data    Source code
       1                 :            : #include <stdlib.h>
       2                 :            : #include <stdio.h>
       3                 :            : #include <stdarg.h>
       4                 :            : #include <string.h>
       5                 :            : #include <assert.h>
       6                 :            : #include <sys/types.h>
       7                 :            : #include "flisp.h"
       8                 :            : #include "utf8proc.h"
       9                 :            : 
      10                 :            : #ifdef __cplusplus
      11                 :            : extern "C" {
      12                 :            : #endif
      13                 :            : 
      14                 :          0 : void print_iostream(fl_context_t *fl_ctx, value_t v, ios_t *f)
      15                 :            : {
      16                 :            :     (void)v;
      17                 :          0 :     fl_print_str(fl_ctx, "#<io stream>", f);
      18                 :          0 : }
      19                 :            : 
      20                 :    2038160 : void free_iostream(fl_context_t *fl_ctx, value_t self)
      21                 :            : {
      22                 :            :     (void)fl_ctx;
      23                 :    2038160 :     ios_t *s = value2c(ios_t*, self);
      24                 :    2038160 :     ios_close(s);
      25                 :    2038160 : }
      26                 :            : 
      27                 :      18586 : void relocate_iostream(fl_context_t *fl_ctx, value_t oldv, value_t newv)
      28                 :            : {
      29                 :            :     (void)fl_ctx;
      30                 :      18586 :     ios_t *olds = value2c(ios_t*, oldv);
      31                 :      18586 :     ios_t *news = value2c(ios_t*, newv);
      32         [ +  + ]:      18586 :     if (news->buf == &olds->local[0]) {
      33                 :        160 :         news->buf = &news->local[0];
      34                 :            :     }
      35                 :      18586 : }
      36                 :            : 
      37                 :            : const cvtable_t iostream_vtable = { print_iostream, relocate_iostream,
      38                 :            :                                     free_iostream, NULL };
      39                 :            : 
      40                 :   66080000 : int fl_isiostream(fl_context_t *fl_ctx, value_t v)
      41                 :            : {
      42   [ +  +  +  - ]:   66080000 :     return iscvalue(v) && cv_class((cvalue_t*)ptr(v)) == fl_ctx->iostreamtype;
      43                 :            : }
      44                 :            : 
      45                 :      96086 : value_t fl_iostreamp(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
      46                 :            : {
      47                 :      96086 :     argcount(fl_ctx, "iostream?", nargs, 1);
      48         [ +  + ]:      96086 :     return fl_isiostream(fl_ctx, args[0]) ? fl_ctx->T : fl_ctx->F;
      49                 :            : }
      50                 :            : 
      51                 :       2018 : value_t fl_eof_object(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
      52                 :            : {
      53                 :            :     (void)args;
      54                 :       2018 :     argcount(fl_ctx, "eof-object", nargs, 0);
      55                 :       2018 :     return fl_ctx->FL_EOF;
      56                 :            : }
      57                 :            : 
      58                 :   42046200 : value_t fl_eof_objectp(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
      59                 :            : {
      60                 :   42046200 :     argcount(fl_ctx, "eof-object?", nargs, 1);
      61         [ +  + ]:   42046200 :     return (fl_ctx->FL_EOF == args[0]) ? fl_ctx->T : fl_ctx->F;
      62                 :            : }
      63                 :            : 
      64                 :   65984000 : static ios_t *toiostream(fl_context_t *fl_ctx, value_t v, const char *fname)
      65                 :            : {
      66         [ -  + ]:   65984000 :     if (!fl_isiostream(fl_ctx, v))
      67                 :          0 :         type_error(fl_ctx, fname, "iostream", v);
      68                 :   65984000 :     return value2c(ios_t*, v);
      69                 :            : }
      70                 :            : 
      71                 :    7911780 : ios_t *fl_toiostream(fl_context_t *fl_ctx, value_t v, const char *fname)
      72                 :            : {
      73                 :    7911780 :     return toiostream(fl_ctx, v, fname);
      74                 :            : }
      75                 :            : 
      76                 :          0 : value_t fl_file(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
      77                 :            : {
      78         [ #  # ]:          0 :     if (nargs < 1)
      79                 :          0 :         argcount(fl_ctx, "file", nargs, 1);
      80                 :          0 :     int i, r=0, w=0, c=0, t=0, a=0;
      81         [ #  # ]:          0 :     for(i=1; i < (int)nargs; i++) {
      82         [ #  # ]:          0 :         if      (args[i] == fl_ctx->wrsym)    w = 1;
      83         [ #  # ]:          0 :         else if (args[i] == fl_ctx->apsym)    { a = 1; w = 1; }
      84         [ #  # ]:          0 :         else if (args[i] == fl_ctx->crsym)    { c = 1; w = 1; }
      85         [ #  # ]:          0 :         else if (args[i] == fl_ctx->truncsym) { t = 1; w = 1; }
      86         [ #  # ]:          0 :         else if (args[i] == fl_ctx->rdsym)    r = 1;
      87                 :            :     }
      88         [ #  # ]:          0 :     if ((r|w|c|t|a) == 0) r = 1;  // default to reading
      89                 :          0 :     value_t f = cvalue(fl_ctx, fl_ctx->iostreamtype, sizeof(ios_t));
      90                 :          0 :     char *fname = tostring(fl_ctx, args[0], "file");
      91                 :          0 :     ios_t *s = value2c(ios_t*, f);
      92         [ #  # ]:          0 :     if (ios_file(s, fname, r, w, c, t) == NULL)
      93                 :          0 :         lerrorf(fl_ctx, fl_ctx->IOError, "file: could not open \"%s\"", fname);
      94         [ #  # ]:          0 :     if (a) ios_seek_end(s);
      95                 :          0 :     return f;
      96                 :            : }
      97                 :            : 
      98                 :    2042000 : value_t fl_buffer(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
      99                 :            : {
     100                 :    2042000 :     argcount(fl_ctx, "buffer", nargs, 0);
     101                 :            :     (void)args;
     102                 :    2042000 :     value_t f = cvalue(fl_ctx, fl_ctx->iostreamtype, sizeof(ios_t));
     103                 :    2042000 :     ios_t *s = value2c(ios_t*, f);
     104         [ -  + ]:    2042000 :     if (ios_mem(s, 0) == NULL)
     105                 :          0 :         lerror(fl_ctx, fl_ctx->OutOfMemoryError, "buffer: could not allocate stream");
     106                 :    2042000 :     return f;
     107                 :            : }
     108                 :            : 
     109                 :     105188 : value_t fl_read(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     110                 :            : {
     111                 :     105188 :     value_t arg = 0;
     112         [ -  + ]:     105188 :     if (nargs > 1) {
     113                 :          0 :         argcount(fl_ctx, "read", nargs, 1);
     114                 :            :     }
     115         [ -  + ]:     105188 :     else if (nargs == 0) {
     116                 :          0 :         arg = symbol_value(fl_ctx->instrsym);
     117                 :            :     }
     118                 :            :     else {
     119                 :     105188 :         arg = args[0];
     120                 :            :     }
     121                 :     105188 :     (void)toiostream(fl_ctx, arg, "read");
     122                 :     105188 :     fl_gc_handle(fl_ctx, &arg);
     123                 :     105188 :     value_t v = fl_read_sexpr(fl_ctx, arg);
     124                 :     105188 :     fl_free_gc_handles(fl_ctx, 1);
     125         [ -  + ]:     105188 :     if (ios_eof(value2c(ios_t*,arg)))
     126                 :          0 :         return fl_ctx->FL_EOF;
     127                 :     105188 :     return v;
     128                 :            : }
     129                 :            : 
     130                 :   28413400 : value_t fl_iogetc(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     131                 :            : {
     132                 :   28413400 :     argcount(fl_ctx, "io.getc", nargs, 1);
     133                 :   28413400 :     ios_t *s = toiostream(fl_ctx, args[0], "io.getc");
     134                 :            :     uint32_t wc;
     135                 :   28413400 :     int result = ios_getutf8(s, &wc);
     136         [ +  + ]:   28413400 :     if (result == IOS_EOF)
     137                 :            :         //lerror(fl_ctx, IOError, "io.getc: end of file reached");
     138                 :     140324 :         return fl_ctx->FL_EOF;
     139         [ -  + ]:   28273200 :     if (result == 0)
     140                 :          0 :         lerror(fl_ctx, fl_ctx->IOError, "invalid UTF-8 sequence");
     141                 :   28273200 :     return mk_wchar(fl_ctx, wc);
     142                 :            : }
     143                 :            : 
     144                 :   12329540 : value_t fl_iopeekc(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     145                 :            : {
     146                 :   12329540 :     argcount(fl_ctx, "io.peekc", nargs, 1);
     147                 :   12329540 :     ios_t *s = toiostream(fl_ctx, args[0], "io.peekc");
     148                 :            :     uint32_t wc;
     149                 :   12329540 :     int result = ios_peekutf8(s, &wc);
     150         [ +  + ]:   12329540 :     if (result == IOS_EOF)
     151                 :      13806 :         return fl_ctx->FL_EOF;
     152         [ -  + ]:   12315740 :     if (result == 0)
     153                 :          0 :         lerror(fl_ctx, fl_ctx->IOError, "invalid UTF-8 sequence");
     154                 :   12315740 :     return mk_wchar(fl_ctx, wc);
     155                 :            : }
     156                 :            : 
     157                 :   14708260 : value_t fl_ioputc(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     158                 :            : {
     159                 :   14708260 :     argcount(fl_ctx, "io.putc", nargs, 2);
     160                 :   14708260 :     ios_t *s = toiostream(fl_ctx, args[0], "io.putc");
     161   [ +  -  -  + ]:   14708260 :     if (!iscprim(args[1]) || ((cprim_t*)ptr(args[1]))->type != fl_ctx->wchartype)
     162                 :          0 :         type_error(fl_ctx, "io.putc", "wchar", args[1]);
     163                 :   14708260 :     uint32_t wc = *(uint32_t*)cp_data((cprim_t*)ptr(args[1]));
     164                 :   14708260 :     return fixnum(ios_pututf8(s, wc));
     165                 :            : }
     166                 :            : 
     167                 :          0 : value_t fl_ioflush(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     168                 :            : {
     169                 :          0 :     argcount(fl_ctx, "io.flush", nargs, 1);
     170                 :          0 :     ios_t *s = toiostream(fl_ctx, args[0], "io.flush");
     171         [ #  # ]:          0 :     if (ios_flush(s) != 0)
     172                 :          0 :         return fl_ctx->F;
     173                 :          0 :     return fl_ctx->T;
     174                 :            : }
     175                 :            : 
     176                 :       2002 : value_t fl_ioclose(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     177                 :            : {
     178                 :       2002 :     argcount(fl_ctx, "io.close", nargs, 1);
     179                 :       2002 :     ios_t *s = toiostream(fl_ctx, args[0], "io.close");
     180                 :       2002 :     ios_close(s);
     181                 :       2002 :     return fl_ctx->T;
     182                 :            : }
     183                 :            : 
     184                 :          0 : value_t fl_iopurge(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     185                 :            : {
     186                 :          0 :     argcount(fl_ctx, "io.discardbuffer", nargs, 1);
     187                 :          0 :     ios_t *s = toiostream(fl_ctx, args[0], "io.discardbuffer");
     188                 :          0 :     ios_purge(s);
     189                 :          0 :     return fl_ctx->T;
     190                 :            : }
     191                 :            : 
     192                 :          0 : value_t fl_ioeof(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     193                 :            : {
     194                 :          0 :     argcount(fl_ctx, "io.eof?", nargs, 1);
     195                 :          0 :     ios_t *s = toiostream(fl_ctx, args[0], "io.eof?");
     196         [ #  # ]:          0 :     return (ios_eof(s) ? fl_ctx->T : fl_ctx->F);
     197                 :            : }
     198                 :            : 
     199                 :     955658 : value_t fl_iolineno(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     200                 :            : {
     201                 :     955658 :     argcount(fl_ctx, "input-port-line", nargs, 1);
     202                 :     955658 :     ios_t *s = toiostream(fl_ctx, args[0], "input-port-line");
     203                 :     955658 :     return size_wrap(fl_ctx, s->lineno);
     204                 :            : }
     205                 :            : 
     206                 :      11914 : value_t fl_iosetlineno(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     207                 :            : {
     208                 :      11914 :     argcount(fl_ctx, "io.set-lineno!", nargs, 2);
     209                 :      11914 :     ios_t *s = toiostream(fl_ctx, args[0], "io.set-lineno!");
     210                 :      11914 :     size_t new_lineno = tosize(fl_ctx, args[1], "io.set-lineno!");
     211                 :      11914 :     s->lineno = new_lineno;
     212                 :      11914 :     return args[1];
     213                 :            : }
     214                 :            : 
     215                 :          0 : value_t fl_iocolno(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     216                 :            : {
     217                 :          0 :     argcount(fl_ctx, "input-port-column", nargs, 1);
     218                 :          0 :     ios_t *s = toiostream(fl_ctx, args[0], "input-port-column");
     219                 :          0 :     return size_wrap(fl_ctx, s->u_colno);
     220                 :            : }
     221                 :            : 
     222                 :     484478 : value_t fl_ioseek(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     223                 :            : {
     224                 :     484478 :     argcount(fl_ctx, "io.seek", nargs, 2);
     225                 :     484478 :     ios_t *s = toiostream(fl_ctx, args[0], "io.seek");
     226                 :     484478 :     size_t pos = tosize(fl_ctx, args[1], "io.seek");
     227                 :     484478 :     int64_t res = ios_seek(s, pos);
     228         [ -  + ]:     484478 :     if (res < 0)
     229                 :          0 :         return fl_ctx->F;
     230                 :     484478 :     return fl_ctx->T;
     231                 :            : }
     232                 :            : 
     233                 :         16 : value_t fl_ioskip(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     234                 :            : {
     235                 :         16 :     argcount(fl_ctx, "io.skip", nargs, 2);
     236                 :         16 :     ios_t *s = toiostream(fl_ctx, args[0], "io.skip");
     237                 :         16 :     int64_t pos = (ssize_t)tosize(fl_ctx, args[1], "io.skip");
     238                 :         16 :     int64_t res = ios_skip(s, pos);
     239         [ -  + ]:         16 :     if (res < 0)
     240                 :          0 :         return fl_ctx->F;
     241                 :         16 :     return fl_ctx->T;
     242                 :            : }
     243                 :            : 
     244                 :     130184 : value_t fl_iopos(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     245                 :            : {
     246                 :     130184 :     argcount(fl_ctx, "io.pos", nargs, 1);
     247                 :     130184 :     ios_t *s = toiostream(fl_ctx, args[0], "io.pos");
     248                 :     130184 :     int64_t res = ios_pos(s);
     249         [ -  + ]:     130184 :     if (res == -1)
     250                 :          0 :         return fl_ctx->F;
     251                 :     130184 :     return size_wrap(fl_ctx, (size_t)res);
     252                 :            : }
     253                 :            : 
     254                 :     115360 : value_t fl_write(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     255                 :            : {
     256   [ +  -  -  + ]:     115360 :     if (nargs < 1 || nargs > 2)
     257                 :          0 :         argcount(fl_ctx, "write", nargs, 1);
     258                 :            :     ios_t *s;
     259         [ -  + ]:     115360 :     if (nargs == 2)
     260                 :          0 :         s = toiostream(fl_ctx, args[1], "write");
     261                 :            :     else
     262                 :     115360 :         s = toiostream(fl_ctx, symbol_value(fl_ctx->outstrsym), "write");
     263                 :     115360 :     fl_print(fl_ctx, s, args[0]);
     264                 :     115360 :     return args[0];
     265                 :            : }
     266                 :            : 
     267                 :          0 : value_t fl_ioread(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     268                 :            : {
     269         [ #  # ]:          0 :     if (nargs != 3)
     270                 :          0 :         argcount(fl_ctx, "io.read", nargs, 2);
     271                 :          0 :     (void)toiostream(fl_ctx, args[0], "io.read");
     272                 :            :     size_t n;
     273                 :            :     fltype_t *ft;
     274         [ #  # ]:          0 :     if (nargs == 3) {
     275                 :            :         // form (io.read s type count)
     276                 :          0 :         ft = get_array_type(fl_ctx, args[1]);
     277                 :          0 :         n = tosize(fl_ctx, args[2], "io.read") * ft->elsz;
     278                 :            :     }
     279                 :            :     else {
     280                 :          0 :         ft = get_type(fl_ctx, args[1]);
     281   [ #  #  #  # ]:          0 :         if (ft->eltype != NULL && !iscons(cdr_(cdr_(args[1]))))
     282                 :          0 :             lerror(fl_ctx, fl_ctx->ArgError, "io.read: incomplete type");
     283                 :          0 :         n = ft->size;
     284                 :            :     }
     285                 :          0 :     value_t cv = cvalue(fl_ctx, ft, n);
     286                 :            :     char *data;
     287         [ #  # ]:          0 :     if (iscvalue(cv)) data = (char*)cv_data((cvalue_t*)ptr(cv));
     288                 :          0 :     else data = cp_data((cprim_t*)ptr(cv));
     289                 :          0 :     size_t got = ios_read(value2c(ios_t*,args[0]), data, n);
     290         [ #  # ]:          0 :     if (got < n)
     291                 :            :         //lerror(fl_ctx, IOError, "io.read: end of input reached");
     292                 :          0 :         return fl_ctx->FL_EOF;
     293                 :          0 :     return cv;
     294                 :            : }
     295                 :            : 
     296                 :            : // args must contain data[, offset[, count]]
     297                 :          0 : static void get_start_count_args(fl_context_t *fl_ctx, value_t *args, uint32_t nargs, size_t sz,
     298                 :            :                                  size_t *offs, size_t *nb, char *fname)
     299                 :            : {
     300         [ #  # ]:          0 :     if (nargs > 1) {
     301                 :          0 :         *offs = tosize(fl_ctx, args[1], fname);
     302         [ #  # ]:          0 :         if (nargs > 2)
     303                 :          0 :             *nb = tosize(fl_ctx, args[2], fname);
     304                 :            :         else
     305                 :          0 :             *nb = sz - *offs;
     306   [ #  #  #  # ]:          0 :         if (*offs >= sz || *offs + *nb > sz)
     307                 :          0 :             bounds_error(fl_ctx, fname, args[0], args[1]);
     308                 :            :     }
     309                 :          0 : }
     310                 :            : 
     311                 :     242612 : value_t fl_iowrite(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     312                 :            : {
     313   [ +  -  -  + ]:     242612 :     if (nargs < 2 || nargs > 4)
     314                 :          0 :         argcount(fl_ctx, "io.write", nargs, 2);
     315                 :     242612 :     ios_t *s = toiostream(fl_ctx, args[0], "io.write");
     316   [ +  +  +  - ]:     242612 :     if (iscprim(args[1]) && ((cprim_t*)ptr(args[1]))->type == fl_ctx->wchartype) {
     317         [ -  + ]:       2658 :         if (nargs > 2)
     318                 :          0 :             lerror(fl_ctx, fl_ctx->ArgError,
     319                 :            :                    "io.write: offset argument not supported for characters");
     320                 :       2658 :         uint32_t wc = *(uint32_t*)cp_data((cprim_t*)ptr(args[1]));
     321                 :       2658 :         return fixnum(ios_pututf8(s, wc));
     322                 :            :     }
     323                 :            :     char *data;
     324                 :     239954 :     size_t sz, offs=0;
     325                 :     239954 :     to_sized_ptr(fl_ctx, args[1], "io.write", &data, &sz);
     326                 :     239954 :     size_t nb = sz;
     327         [ -  + ]:     239954 :     if (nargs > 2) {
     328                 :          0 :         get_start_count_args(fl_ctx, &args[1], nargs-1, sz, &offs, &nb, "io.write");
     329                 :          0 :         data += offs;
     330                 :            :     }
     331                 :     239954 :     return size_wrap(fl_ctx, ios_write(s, data, nb));
     332                 :            : }
     333                 :            : 
     334                 :          0 : static char get_delim_arg(fl_context_t *fl_ctx, value_t arg, char *fname)
     335                 :            : {
     336                 :          0 :     size_t uldelim = tosize(fl_ctx, arg, fname);
     337         [ #  # ]:          0 :     if (uldelim > 0x7f) {
     338                 :            :         // wchars > 0x7f, or anything else > 0xff, are out of range
     339   [ #  #  #  #  :          0 :         if ((iscprim(arg) && cp_class((cprim_t*)ptr(arg))==fl_ctx->wchartype) ||
                   #  # ]
     340                 :            :             uldelim > 0xff)
     341                 :          0 :             lerrorf(fl_ctx, fl_ctx->ArgError, "%s: delimiter out of range", fname);
     342                 :            :     }
     343                 :          0 :     return (char)uldelim;
     344                 :            : }
     345                 :            : 
     346                 :          0 : value_t fl_ioreaduntil(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     347                 :            : {
     348                 :          0 :     argcount(fl_ctx, "io.readuntil", nargs, 2);
     349                 :          0 :     value_t str = cvalue_string(fl_ctx, 80);
     350                 :          0 :     cvalue_t *cv = (cvalue_t*)ptr(str);
     351                 :          0 :     char *data = (char*)cv_data(cv);
     352                 :            :     ios_t dest;
     353                 :          0 :     ios_mem(&dest, 0);
     354                 :          0 :     ios_setbuf(&dest, data, 80, 0);
     355                 :          0 :     char delim = get_delim_arg(fl_ctx, args[1], "io.readuntil");
     356                 :          0 :     ios_t *src = toiostream(fl_ctx, args[0], "io.readuntil");
     357                 :          0 :     size_t n = ios_copyuntil(&dest, src, delim);
     358                 :          0 :     cv->len = n;
     359         [ #  # ]:          0 :     if (dest.buf != data) {
     360                 :            :         // outgrew initial space
     361                 :            :         size_t sz;
     362                 :          0 :         cv->data = ios_take_buffer(&dest, &sz);
     363                 :          0 :         cv_autorelease(fl_ctx, cv);
     364                 :            :     }
     365                 :            :     else {
     366                 :          0 :         ((char*)cv->data)[n] = '\0';
     367                 :            :     }
     368   [ #  #  #  # ]:          0 :     if (n == 0 && ios_eof(src))
     369                 :          0 :         return fl_ctx->FL_EOF;
     370                 :          0 :     return str;
     371                 :            : }
     372                 :            : 
     373                 :          0 : value_t fl_iocopyuntil(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     374                 :            : {
     375                 :          0 :     argcount(fl_ctx, "io.copyuntil", nargs, 3);
     376                 :          0 :     ios_t *dest = toiostream(fl_ctx, args[0], "io.copyuntil");
     377                 :          0 :     ios_t *src = toiostream(fl_ctx, args[1], "io.copyuntil");
     378                 :          0 :     char delim = get_delim_arg(fl_ctx, args[2], "io.copyuntil");
     379                 :          0 :     return size_wrap(fl_ctx, ios_copyuntil(dest, src, delim));
     380                 :            : }
     381                 :            : 
     382                 :     120272 : value_t fl_iocopy(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     383                 :            : {
     384   [ +  -  -  + ]:     120272 :     if (nargs < 2 || nargs > 3)
     385                 :          0 :         argcount(fl_ctx, "io.copy", nargs, 2);
     386                 :     120272 :     ios_t *dest = toiostream(fl_ctx, args[0], "io.copy");
     387                 :     120272 :     ios_t *src = toiostream(fl_ctx, args[1], "io.copy");
     388         [ -  + ]:     120272 :     if (nargs == 3) {
     389                 :          0 :         size_t n = tosize(fl_ctx, args[2], "io.copy");
     390                 :          0 :         return size_wrap(fl_ctx, ios_copy(dest, src, n));
     391                 :            :     }
     392                 :     120272 :     return size_wrap(fl_ctx, ios_copyall(dest, src));
     393                 :            : }
     394                 :            : 
     395                 :    1687708 : value_t stream_to_string(fl_context_t *fl_ctx, value_t *ps)
     396                 :            : {
     397                 :            :     value_t str;
     398                 :            :     size_t n;
     399                 :    1687708 :     ios_t *st = value2c(ios_t*,*ps);
     400         [ +  + ]:    1687708 :     if (st->buf == &st->local[0]) {
     401                 :    1642076 :         n = (size_t)st->size;
     402                 :    1642076 :         str = cvalue_string(fl_ctx, n);
     403                 :    1642076 :         st = value2c(ios_t*,*ps); // reload after allocating str
     404                 :    1642076 :         memcpy(cvalue_data(str), st->buf, n);
     405                 :    1642076 :         ios_trunc(st, 0);
     406                 :            :     }
     407                 :            :     else {
     408                 :      45632 :         char *b = ios_take_buffer(st, &n); n--;
     409                 :      45632 :         b[n] = '\0';
     410                 :      45632 :         str = cvalue_from_ref(fl_ctx, fl_ctx->stringtype, b, n, fl_ctx->NIL);
     411                 :      45632 :         cv_autorelease(fl_ctx, (cvalue_t*)ptr(str));
     412                 :            :     }
     413                 :    1687708 :     return str;
     414                 :            : }
     415                 :            : 
     416                 :     332898 : value_t fl_iotostring(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     417                 :            : {
     418                 :     332898 :     argcount(fl_ctx, "io.tostring!", nargs, 1);
     419                 :     332898 :     ios_t *src = toiostream(fl_ctx, args[0], "io.tostring!");
     420         [ -  + ]:     332898 :     if (src->bm != bm_mem)
     421                 :          0 :         lerror(fl_ctx, fl_ctx->ArgError, "io.tostring!: requires memory stream");
     422                 :     332898 :     return stream_to_string(fl_ctx, &args[0]);
     423                 :            : }
     424                 :            : 
     425                 :            : static const builtinspec_t iostreamfunc_info[] = {
     426                 :            :     { "iostream?", fl_iostreamp },
     427                 :            :     { "eof-object", fl_eof_object },
     428                 :            :     { "eof-object?", fl_eof_objectp },
     429                 :            :     { "file", fl_file },
     430                 :            :     { "buffer", fl_buffer },
     431                 :            :     { "read", fl_read },
     432                 :            :     { "write", fl_write },
     433                 :            :     { "io.flush", fl_ioflush },
     434                 :            :     { "io.close", fl_ioclose },
     435                 :            :     { "io.eof?" , fl_ioeof },
     436                 :            :     { "io.seek" , fl_ioseek },
     437                 :            :     { "io.skip" , fl_ioskip },
     438                 :            :     { "io.pos",   fl_iopos },
     439                 :            :     { "io.getc" , fl_iogetc },
     440                 :            :     { "io.putc" , fl_ioputc },
     441                 :            :     { "io.peekc" , fl_iopeekc },
     442                 :            :     { "io.discardbuffer", fl_iopurge },
     443                 :            :     { "io.read", fl_ioread },
     444                 :            :     { "io.write", fl_iowrite },
     445                 :            :     { "io.copy", fl_iocopy },
     446                 :            :     { "io.readuntil", fl_ioreaduntil },
     447                 :            :     { "io.copyuntil", fl_iocopyuntil },
     448                 :            :     { "io.tostring!", fl_iotostring },
     449                 :            :     { "input-port-line", fl_iolineno },
     450                 :            :     { "input-port-column", fl_iocolno },
     451                 :            :     { "io.set-lineno!", fl_iosetlineno },
     452                 :            : 
     453                 :            :     { NULL, NULL }
     454                 :            : };
     455                 :            : 
     456                 :         30 : void iostream_init(fl_context_t *fl_ctx)
     457                 :            : {
     458                 :         30 :     fl_ctx->iostreamsym = symbol(fl_ctx, "iostream");
     459                 :         30 :     fl_ctx->rdsym = symbol(fl_ctx, ":read");
     460                 :         30 :     fl_ctx->wrsym = symbol(fl_ctx, ":write");
     461                 :         30 :     fl_ctx->apsym = symbol(fl_ctx, ":append");
     462                 :         30 :     fl_ctx->crsym = symbol(fl_ctx, ":create");
     463                 :         30 :     fl_ctx->truncsym = symbol(fl_ctx, ":truncate");
     464                 :         30 :     fl_ctx->instrsym = symbol(fl_ctx, "*input-stream*");
     465                 :         30 :     fl_ctx->outstrsym = symbol(fl_ctx, "*output-stream*");
     466                 :         30 :     fl_ctx->iostreamtype = define_opaque_type(fl_ctx->iostreamsym, sizeof(ios_t),
     467                 :            :                                               &iostream_vtable, NULL);
     468                 :         30 :     assign_global_builtins(fl_ctx, iostreamfunc_info);
     469                 :            : 
     470                 :         30 :     setc(symbol(fl_ctx, "*stdout*"), cvalue_from_ref(fl_ctx, fl_ctx->iostreamtype, ios_stdout,
     471                 :            :                                                      sizeof(ios_t), fl_ctx->NIL));
     472                 :         30 :     setc(symbol(fl_ctx, "*stderr*"), cvalue_from_ref(fl_ctx, fl_ctx->iostreamtype, ios_stderr,
     473                 :            :                                                      sizeof(ios_t), fl_ctx->NIL));
     474                 :         30 :     setc(symbol(fl_ctx, "*stdin*" ), cvalue_from_ref(fl_ctx, fl_ctx->iostreamtype, ios_stdin,
     475                 :            :                                                      sizeof(ios_t), fl_ctx->NIL));
     476                 :         30 : }
     477                 :            : 
     478                 :            : #ifdef __cplusplus
     479                 :            : }
     480                 :            : #endif

Generated by: LCOV version 1.14