adding io.putc, io.tostring!, string.map, print-to-string
fixing bug in ios, not initializing readonly flag updating string and sizeof to use new strstream functions removing some redundant numeric type init functions
This commit is contained in:
		
							parent
							
								
									40cff81550
								
							
						
					
					
						commit
						fdfaacfbe5
					
				| 
						 | 
				
			
			@ -205,14 +205,14 @@
 | 
			
		|||
 | 
			
		||||
(define (β-reduce- form)
 | 
			
		||||
        ; ((lambda (f) (f arg)) X) => (X arg)
 | 
			
		||||
  (cond ((and (= (length form) 2)
 | 
			
		||||
  (cond ((and (length= form 2)
 | 
			
		||||
              (pair? (car form))
 | 
			
		||||
              (eq (caar form) 'lambda)
 | 
			
		||||
              (let ((args (cadr (car form)))
 | 
			
		||||
                    (body (caddr (car form))))
 | 
			
		||||
                (and (pair? body) (pair? args)
 | 
			
		||||
                     (= (length body) 2)
 | 
			
		||||
                     (= (length args) 1)
 | 
			
		||||
                     (length= body 2)
 | 
			
		||||
                     (length= args 1)
 | 
			
		||||
                     (eq (car body) (car args))
 | 
			
		||||
                     (not (eq (cadr body) (car args)))
 | 
			
		||||
                     (symbol? (cadr body)))))
 | 
			
		||||
| 
						 | 
				
			
			@ -227,14 +227,14 @@
 | 
			
		|||
        ; ((lambda (p1) ((lambda (args...) body) exprs...)) s) =>
 | 
			
		||||
        ; ((lambda (p1 args...) body) s exprs...)
 | 
			
		||||
        ; where exprs... doesn't contain p1
 | 
			
		||||
        ((and (= (length form) 2)
 | 
			
		||||
        ((and (length= form 2)
 | 
			
		||||
              (pair? (car form))
 | 
			
		||||
              (eq (caar form) 'lambda)
 | 
			
		||||
              (or (atom? (cadr form)) (constant? (cadr form)))
 | 
			
		||||
              (let ((args (cadr (car form)))
 | 
			
		||||
                    (s (cadr form))
 | 
			
		||||
                    (body (caddr (car form))))
 | 
			
		||||
                (and (pair? args) (= (length args) 1)
 | 
			
		||||
                (and (pair? args) (length= args 1)
 | 
			
		||||
                     (pair? body)
 | 
			
		||||
                     (pair? (car body))
 | 
			
		||||
                     (eq (caar body) 'lambda)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -206,14 +206,18 @@ value_t cvalue_static_cstring(char *str)
 | 
			
		|||
    return cvalue_from_ref(stringtype, str, strlen(str), NIL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t string_from_cstr(char *str)
 | 
			
		||||
value_t string_from_cstrn(char *str, size_t n)
 | 
			
		||||
{
 | 
			
		||||
    size_t n = strlen(str);
 | 
			
		||||
    value_t v = cvalue_string(n);
 | 
			
		||||
    memcpy(cvalue_data(v), str, n);
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t string_from_cstr(char *str)
 | 
			
		||||
{
 | 
			
		||||
    return string_from_cstrn(str, strlen(str));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int isstring(value_t v)
 | 
			
		||||
{
 | 
			
		||||
    return (iscvalue(v) && cv_isstr((cvalue_t*)ptr(v)));
 | 
			
		||||
| 
						 | 
				
			
			@ -241,31 +245,45 @@ static void cv_pin(cvalue_t *cv)
 | 
			
		|||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define num_ctor(typenam, ctype, cnvt, tag)                             \
 | 
			
		||||
static void cvalue_##typenam##_init(fltype_t *type, value_t arg,        \
 | 
			
		||||
                                    void *dest)                         \
 | 
			
		||||
{                                                                       \
 | 
			
		||||
    ctype##_t n=0;                                                      \
 | 
			
		||||
    (void)type;                                                         \
 | 
			
		||||
    if (isfixnum(arg)) {                                                \
 | 
			
		||||
        n = numval(arg);                                                \
 | 
			
		||||
    }                                                                   \
 | 
			
		||||
    else if (iscprim(arg)) {                                            \
 | 
			
		||||
        cprim_t *cp = (cprim_t*)ptr(arg);                               \
 | 
			
		||||
        void *p = cp_data(cp);                                          \
 | 
			
		||||
        n = (ctype##_t)conv_to_##cnvt(p, cp_numtype(cp));               \
 | 
			
		||||
    }                                                                   \
 | 
			
		||||
    else {                                                              \
 | 
			
		||||
        type_error(#typenam, "number", arg);                            \
 | 
			
		||||
    }                                                                   \
 | 
			
		||||
    *((ctype##_t*)dest) = n;                                            \
 | 
			
		||||
}                                                                       \
 | 
			
		||||
#define num_init(ctype, cnvt, tag)                              \
 | 
			
		||||
static int cvalue_##ctype##_init(fltype_t *type, value_t arg,   \
 | 
			
		||||
                                 void *dest)                    \
 | 
			
		||||
{                                                               \
 | 
			
		||||
    ctype##_t n=0;                                              \
 | 
			
		||||
    (void)type;                                                 \
 | 
			
		||||
    if (isfixnum(arg)) {                                        \
 | 
			
		||||
        n = numval(arg);                                        \
 | 
			
		||||
    }                                                           \
 | 
			
		||||
    else if (iscprim(arg)) {                                    \
 | 
			
		||||
        cprim_t *cp = (cprim_t*)ptr(arg);                       \
 | 
			
		||||
        void *p = cp_data(cp);                                  \
 | 
			
		||||
        n = (ctype##_t)conv_to_##cnvt(p, cp_numtype(cp));       \
 | 
			
		||||
    }                                                           \
 | 
			
		||||
    else {                                                      \
 | 
			
		||||
        return 1;                                               \
 | 
			
		||||
    }                                                           \
 | 
			
		||||
    *((ctype##_t*)dest) = n;                                    \
 | 
			
		||||
    return 0;                                                   \
 | 
			
		||||
}
 | 
			
		||||
num_init(int8, int32, T_INT8)
 | 
			
		||||
num_init(uint8, uint32, T_UINT8)
 | 
			
		||||
num_init(int16, int32, T_INT16)
 | 
			
		||||
num_init(uint16, uint32, T_UINT16)
 | 
			
		||||
num_init(int32, int32, T_INT32)
 | 
			
		||||
num_init(uint32, uint32, T_UINT32)
 | 
			
		||||
num_init(int64, int64, T_INT64)
 | 
			
		||||
num_init(uint64, uint64, T_UINT64)
 | 
			
		||||
num_init(float, double, T_FLOAT)
 | 
			
		||||
num_init(double, double, T_DOUBLE)
 | 
			
		||||
 | 
			
		||||
#define num_ctor(typenam, ctype, tag)                                   \
 | 
			
		||||
value_t cvalue_##typenam(value_t *args, u_int32_t nargs)                \
 | 
			
		||||
{                                                                       \
 | 
			
		||||
    if (nargs==0) { PUSH(fixnum(0)); args = &Stack[SP-1]; }             \
 | 
			
		||||
    value_t cp = cprim(typenam##type, sizeof(ctype##_t));               \
 | 
			
		||||
    cvalue_##typenam##_init(typenam##type,                              \
 | 
			
		||||
                            args[0], cp_data((cprim_t*)ptr(cp)));       \
 | 
			
		||||
    if (cvalue_##ctype##_init(typenam##type,                            \
 | 
			
		||||
                              args[0], cp_data((cprim_t*)ptr(cp))))     \
 | 
			
		||||
        type_error(#typenam, "number", args[0]);                        \
 | 
			
		||||
    return cp;                                                          \
 | 
			
		||||
}                                                                       \
 | 
			
		||||
value_t mk_##typenam(ctype##_t n)                                       \
 | 
			
		||||
| 
						 | 
				
			
			@ -275,25 +293,25 @@ value_t mk_##typenam(ctype##_t n)                                       \
 | 
			
		|||
    return cp;                                                          \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
num_ctor(int8, int8, int32, T_INT8)
 | 
			
		||||
num_ctor(uint8, uint8, uint32, T_UINT8)
 | 
			
		||||
num_ctor(int16, int16, int32, T_INT16)
 | 
			
		||||
num_ctor(uint16, uint16, uint32, T_UINT16)
 | 
			
		||||
num_ctor(int32, int32, int32, T_INT32)
 | 
			
		||||
num_ctor(uint32, uint32, uint32, T_UINT32)
 | 
			
		||||
num_ctor(int64, int64, int64, T_INT64)
 | 
			
		||||
num_ctor(uint64, uint64, uint64, T_UINT64)
 | 
			
		||||
num_ctor(byte,  uint8, uint32, T_UINT8)
 | 
			
		||||
num_ctor(wchar, int32, int32, T_INT32)
 | 
			
		||||
num_ctor(int8, int8, T_INT8)
 | 
			
		||||
num_ctor(uint8, uint8, T_UINT8)
 | 
			
		||||
num_ctor(int16, int16, T_INT16)
 | 
			
		||||
num_ctor(uint16, uint16, T_UINT16)
 | 
			
		||||
num_ctor(int32, int32, T_INT32)
 | 
			
		||||
num_ctor(uint32, uint32, T_UINT32)
 | 
			
		||||
num_ctor(int64, int64, T_INT64)
 | 
			
		||||
num_ctor(uint64, uint64, T_UINT64)
 | 
			
		||||
num_ctor(byte,  uint8, T_UINT8)
 | 
			
		||||
num_ctor(wchar, int32, T_INT32)
 | 
			
		||||
#ifdef BITS64
 | 
			
		||||
num_ctor(long, long, int64, T_INT64)
 | 
			
		||||
num_ctor(ulong, ulong, uint64, T_UINT64)
 | 
			
		||||
num_ctor(long, int64, T_INT64)
 | 
			
		||||
num_ctor(ulong, uint64, T_UINT64)
 | 
			
		||||
#else
 | 
			
		||||
num_ctor(long, long, int32, T_INT32)
 | 
			
		||||
num_ctor(ulong, ulong, uint32, T_UINT32)
 | 
			
		||||
num_ctor(long, int32, T_INT32)
 | 
			
		||||
num_ctor(ulong, uint32, T_UINT32)
 | 
			
		||||
#endif
 | 
			
		||||
num_ctor(float, float, double, T_FLOAT)
 | 
			
		||||
num_ctor(double, double, double, T_DOUBLE)
 | 
			
		||||
num_ctor(float, float, T_FLOAT)
 | 
			
		||||
num_ctor(double, double, T_DOUBLE)
 | 
			
		||||
 | 
			
		||||
value_t size_wrap(size_t sz)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +333,7 @@ size_t toulong(value_t n, char *fname)
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cvalue_enum_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		||||
static int cvalue_enum_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		||||
{
 | 
			
		||||
    int n=0;
 | 
			
		||||
    value_t syms;
 | 
			
		||||
| 
						 | 
				
			
			@ -328,7 +346,7 @@ static void cvalue_enum_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		|||
        while (iscons(syms)) {
 | 
			
		||||
            if (car_(syms) == arg) {
 | 
			
		||||
                *(int*)dest = n;
 | 
			
		||||
                return;
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
            n++;
 | 
			
		||||
            syms = cdr_(syms);
 | 
			
		||||
| 
						 | 
				
			
			@ -348,6 +366,7 @@ static void cvalue_enum_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		|||
    if ((unsigned)n >= llength(syms))
 | 
			
		||||
        lerror(ArgError, "enum: value out of range");
 | 
			
		||||
    *(int*)dest = n;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t cvalue_enum(value_t *args, u_int32_t nargs)
 | 
			
		||||
| 
						 | 
				
			
			@ -388,7 +407,7 @@ static size_t predict_arraylen(value_t arg)
 | 
			
		|||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cvalue_array_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		||||
static int cvalue_array_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		||||
{
 | 
			
		||||
    value_t type = ft->type;
 | 
			
		||||
    size_t elsize, i, cnt, sz;
 | 
			
		||||
| 
						 | 
				
			
			@ -408,7 +427,7 @@ static void cvalue_array_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		|||
    if (isvector(arg)) {
 | 
			
		||||
        array_init_fromargs((char*)dest, &vector_elt(arg,0), cnt,
 | 
			
		||||
                            eltype, elsize);
 | 
			
		||||
        return;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    else if (iscons(arg) || arg==NIL) {
 | 
			
		||||
        i = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -423,7 +442,7 @@ static void cvalue_array_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		|||
            lerror(ArgError, "array: size mismatch");
 | 
			
		||||
        array_init_fromargs((char*)dest, &Stack[SP-i], i, eltype, elsize);
 | 
			
		||||
        POPN(i);
 | 
			
		||||
        return;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    else if (iscvalue(arg)) {
 | 
			
		||||
        cvalue_t *cv = (cvalue_t*)ptr(arg);
 | 
			
		||||
| 
						 | 
				
			
			@ -434,7 +453,7 @@ static void cvalue_array_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		|||
                    memcpy(dest, cv_data(cv), sz);
 | 
			
		||||
                else
 | 
			
		||||
                    lerror(ArgError, "array: size mismatch");
 | 
			
		||||
                return;
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                // TODO: initialize array from different type elements
 | 
			
		||||
| 
						 | 
				
			
			@ -446,6 +465,7 @@ static void cvalue_array_init(fltype_t *ft, value_t arg, void *dest)
 | 
			
		|||
        cvalue_init(eltype, arg, dest);
 | 
			
		||||
    else
 | 
			
		||||
        type_error("array", "sequence", arg);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t cvalue_array(value_t *args, u_int32_t nargs)
 | 
			
		||||
| 
						 | 
				
			
			@ -593,19 +613,39 @@ size_t ctype_sizeof(value_t type, int *palign)
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get pointer and size for any plain-old-data value
 | 
			
		||||
void to_sized_ptr(value_t v, char *fname, char **pdata, size_t *psz)
 | 
			
		||||
{
 | 
			
		||||
    if (isiostream(v) && (value2c(ios_t*,v)->bm == bm_mem)) {
 | 
			
		||||
        ios_t *x = value2c(ios_t*,v);
 | 
			
		||||
        *pdata = x->buf;
 | 
			
		||||
        *psz = x->size;
 | 
			
		||||
    }
 | 
			
		||||
    else if (iscvalue(v)) {
 | 
			
		||||
        cvalue_t *pcv = (cvalue_t*)ptr(v);
 | 
			
		||||
        *pdata = cv_data(pcv);
 | 
			
		||||
        *psz = cv_len(pcv);
 | 
			
		||||
    }
 | 
			
		||||
    else if (iscprim(v)) {
 | 
			
		||||
        cprim_t *pcp = (cprim_t*)ptr(v);
 | 
			
		||||
        *pdata = cp_data(pcp);
 | 
			
		||||
        *psz = cp_class(pcp)->size;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        type_error(fname, "bytes", v);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t cvalue_sizeof(value_t *args, u_int32_t nargs)
 | 
			
		||||
{
 | 
			
		||||
    argcount("sizeof", nargs, 1);
 | 
			
		||||
    if (iscvalue(args[0])) {
 | 
			
		||||
        cvalue_t *cv = (cvalue_t*)ptr(args[0]);
 | 
			
		||||
        return size_wrap(cv_len(cv));
 | 
			
		||||
    if (issymbol(args[0]) || iscons(args[0])) {
 | 
			
		||||
        int a;
 | 
			
		||||
        return size_wrap(ctype_sizeof(args[0], &a));
 | 
			
		||||
    }
 | 
			
		||||
    else if (iscprim(args[0])) {
 | 
			
		||||
        cprim_t *cp = (cprim_t*)ptr(args[0]);
 | 
			
		||||
        return fixnum(cp_class(cp)->size);
 | 
			
		||||
    }
 | 
			
		||||
    int a;
 | 
			
		||||
    return size_wrap(ctype_sizeof(args[0], &a));
 | 
			
		||||
    size_t n; char *data;
 | 
			
		||||
    to_sized_ptr(args[0], "sizeof", &data, &n);
 | 
			
		||||
    return size_wrap(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t cvalue_typeof(value_t *args, u_int32_t nargs)
 | 
			
		||||
| 
						 | 
				
			
			@ -861,6 +901,9 @@ static builtinspec_t cvalues_builtin_info[] = {
 | 
			
		|||
#define mk_primtype(name) \
 | 
			
		||||
  name##type=get_type(name##sym);name##type->init = &cvalue_##name##_init
 | 
			
		||||
 | 
			
		||||
#define mk_primtype_(name,ctype) \
 | 
			
		||||
  name##type=get_type(name##sym);name##type->init = &cvalue_##ctype##_init
 | 
			
		||||
 | 
			
		||||
void cvalues_init()
 | 
			
		||||
{
 | 
			
		||||
    htable_new(&TypeTable, 256);
 | 
			
		||||
| 
						 | 
				
			
			@ -915,10 +958,15 @@ void cvalues_init()
 | 
			
		|||
    mk_primtype(uint32);
 | 
			
		||||
    mk_primtype(int64);
 | 
			
		||||
    mk_primtype(uint64);
 | 
			
		||||
    mk_primtype(long);
 | 
			
		||||
    mk_primtype(ulong);
 | 
			
		||||
    mk_primtype(byte);
 | 
			
		||||
    mk_primtype(wchar);
 | 
			
		||||
#ifdef BITS64
 | 
			
		||||
    mk_primtype_(long,int64);
 | 
			
		||||
    mk_primtype_(ulong,uint64);
 | 
			
		||||
#else
 | 
			
		||||
    mk_primtype_(long,int32);
 | 
			
		||||
    mk_primtype_(ulong,uint32);
 | 
			
		||||
#endif
 | 
			
		||||
    mk_primtype_(byte,uint8);
 | 
			
		||||
    mk_primtype_(wchar,int32);
 | 
			
		||||
    mk_primtype(float);
 | 
			
		||||
    mk_primtype(double);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -174,7 +174,7 @@ void fl_print_chr(char c, ios_t *f);
 | 
			
		|||
void fl_print_str(char *s, ios_t *f);
 | 
			
		||||
void fl_print_child(ios_t *f, value_t v, int princ);
 | 
			
		||||
 | 
			
		||||
typedef void (*cvinitfunc_t)(struct _fltype_t*, value_t, void*);
 | 
			
		||||
typedef int (*cvinitfunc_t)(struct _fltype_t*, value_t, void*);
 | 
			
		||||
 | 
			
		||||
typedef struct _fltype_t {
 | 
			
		||||
    value_t type;
 | 
			
		||||
| 
						 | 
				
			
			@ -268,10 +268,14 @@ size_t toulong(value_t n, char *fname);
 | 
			
		|||
value_t cvalue_string(size_t sz);
 | 
			
		||||
value_t cvalue_static_cstring(char *str);
 | 
			
		||||
value_t string_from_cstr(char *str);
 | 
			
		||||
value_t string_from_cstrn(char *str, size_t n);
 | 
			
		||||
int isstring(value_t v);
 | 
			
		||||
int isnumber(value_t v);
 | 
			
		||||
int isiostream(value_t v);
 | 
			
		||||
value_t cvalue_compare(value_t a, value_t b);
 | 
			
		||||
 | 
			
		||||
void to_sized_ptr(value_t v, char *fname, char **pdata, size_t *psz);
 | 
			
		||||
 | 
			
		||||
fltype_t *get_type(value_t t);
 | 
			
		||||
fltype_t *get_array_type(value_t eltype);
 | 
			
		||||
fltype_t *define_opaque_type(value_t sym, size_t sz, cvtable_t *vtab,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,14 +79,14 @@ value_t fl_file(value_t *args, uint32_t nargs)
 | 
			
		|||
    return f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t fl_memstream(value_t *args, u_int32_t nargs)
 | 
			
		||||
value_t fl_buffer(value_t *args, u_int32_t nargs)
 | 
			
		||||
{
 | 
			
		||||
    argcount("memstream", nargs, 0);
 | 
			
		||||
    argcount("buffer", nargs, 0);
 | 
			
		||||
    (void)args;
 | 
			
		||||
    value_t f = cvalue(iostreamtype, sizeof(ios_t));
 | 
			
		||||
    ios_t *s = value2c(ios_t*, f);
 | 
			
		||||
    if (ios_mem(s, 0) == NULL)
 | 
			
		||||
        lerror(MemoryError, "memstream: could not allocate stream");
 | 
			
		||||
        lerror(MemoryError, "buffer: could not allocate stream");
 | 
			
		||||
    return f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -113,6 +113,17 @@ value_t fl_iogetc(value_t *args, u_int32_t nargs)
 | 
			
		|||
    return mk_wchar(wc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t fl_ioputc(value_t *args, u_int32_t nargs)
 | 
			
		||||
{
 | 
			
		||||
    argcount("io.putc", nargs, 2);
 | 
			
		||||
    ios_t *s = toiostream(args[0], "io.putc");
 | 
			
		||||
    uint32_t wc;
 | 
			
		||||
    if (!iscprim(args[1]) || ((cprim_t*)ptr(args[1]))->type != wchartype)
 | 
			
		||||
        type_error("io.putc", "wchar", args[1]);
 | 
			
		||||
    wc = *(uint32_t*)cp_data((cprim_t*)ptr(args[1]));
 | 
			
		||||
    return fixnum(ios_pututf8(s, wc));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t fl_ioflush(value_t *args, u_int32_t nargs)
 | 
			
		||||
{
 | 
			
		||||
    argcount("io.flush", nargs, 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -194,29 +205,6 @@ value_t fl_ioread(value_t *args, u_int32_t nargs)
 | 
			
		|||
    return cv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get pointer and size for any plain-old-data value
 | 
			
		||||
static void to_sized_ptr(value_t v, char *fname, char **pdata, size_t *psz)
 | 
			
		||||
{
 | 
			
		||||
    if (isiostream(v) && (value2c(ios_t*,v)->bm == bm_mem)) {
 | 
			
		||||
        ios_t *x = value2c(ios_t*,v);
 | 
			
		||||
        *pdata = x->buf;
 | 
			
		||||
        *psz = x->size;
 | 
			
		||||
    }
 | 
			
		||||
    else if (iscvalue(v)) {
 | 
			
		||||
        cvalue_t *pcv = (cvalue_t*)ptr(v);
 | 
			
		||||
        *pdata = cv_data(pcv);
 | 
			
		||||
        *psz = cv_len(pcv);
 | 
			
		||||
    }
 | 
			
		||||
    else if (iscprim(v)) {
 | 
			
		||||
        cprim_t *pcp = (cprim_t*)ptr(v);
 | 
			
		||||
        *pdata = cp_data(pcp);
 | 
			
		||||
        *psz = cp_class(pcp)->size;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        type_error(fname, "byte stream", v);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t fl_iowrite(value_t *args, u_int32_t nargs)
 | 
			
		||||
{
 | 
			
		||||
    argcount("io.write", nargs, 2);
 | 
			
		||||
| 
						 | 
				
			
			@ -263,11 +251,39 @@ value_t fl_ioreaduntil(value_t *args, u_int32_t nargs)
 | 
			
		|||
    return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t stream_to_string(value_t *ps)
 | 
			
		||||
{
 | 
			
		||||
    value_t str;
 | 
			
		||||
    size_t n;
 | 
			
		||||
    ios_t *st = value2c(ios_t*,*ps);
 | 
			
		||||
    if (st->buf == &st->local[0]) {
 | 
			
		||||
        n = st->size;
 | 
			
		||||
        str = cvalue_string(n);
 | 
			
		||||
        memcpy(cvalue_data(str), value2c(ios_t*,*ps)->buf, n);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        char *b = ios_takebuf(st, &n); n--;
 | 
			
		||||
        b[n] = '\0';
 | 
			
		||||
        str = cvalue_from_ref(stringtype, b, n, NIL);
 | 
			
		||||
        cv_autorelease((cvalue_t*)ptr(str));
 | 
			
		||||
    }
 | 
			
		||||
    return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t fl_iotostring(value_t *args, u_int32_t nargs)
 | 
			
		||||
{
 | 
			
		||||
    argcount("io.tostring!", nargs, 1);
 | 
			
		||||
    ios_t *src = toiostream(args[0], "io.tostring!");
 | 
			
		||||
    if (src->bm != bm_mem)
 | 
			
		||||
        lerror(ArgError, "io.tostring!: requires memory stream");
 | 
			
		||||
    return stream_to_string(&args[0]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static builtinspec_t iostreamfunc_info[] = {
 | 
			
		||||
    { "iostream?", fl_iostreamp },
 | 
			
		||||
    { "dump", fl_dump },
 | 
			
		||||
    { "file", fl_file },
 | 
			
		||||
    { "memstream", fl_memstream },
 | 
			
		||||
    { "buffer", fl_buffer },
 | 
			
		||||
    { "read", fl_read },
 | 
			
		||||
    { "io.print", fl_ioprint },
 | 
			
		||||
    { "io.princ", fl_ioprinc },
 | 
			
		||||
| 
						 | 
				
			
			@ -275,10 +291,12 @@ static builtinspec_t iostreamfunc_info[] = {
 | 
			
		|||
    { "io.close", fl_ioclose },
 | 
			
		||||
    { "io.eof?" , fl_ioeof },
 | 
			
		||||
    { "io.getc" , fl_iogetc },
 | 
			
		||||
    { "io.putc" , fl_ioputc },
 | 
			
		||||
    { "io.discardbuffer", fl_iopurge },
 | 
			
		||||
    { "io.read", fl_ioread },
 | 
			
		||||
    { "io.write", fl_iowrite },
 | 
			
		||||
    { "io.readuntil", fl_ioreaduntil },
 | 
			
		||||
    { "io.tostring!", fl_iotostring },
 | 
			
		||||
    { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -580,7 +580,7 @@ static value_t do_read_sexpr(value_t label)
 | 
			
		|||
    case TOK_DOUBLEQUOTE:
 | 
			
		||||
        return read_string();
 | 
			
		||||
    }
 | 
			
		||||
    return NIL;
 | 
			
		||||
    return FL_F;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t read_sexpr(value_t f)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,24 +14,17 @@
 | 
			
		|||
#include "llt.h"
 | 
			
		||||
#include "flisp.h"
 | 
			
		||||
 | 
			
		||||
extern value_t fl_buffer(value_t *args, u_int32_t nargs);
 | 
			
		||||
extern value_t stream_to_string(value_t *ps);
 | 
			
		||||
static value_t print_to_string(value_t v, int princ)
 | 
			
		||||
{
 | 
			
		||||
    ios_t str;
 | 
			
		||||
    ios_mem(&str, 0);
 | 
			
		||||
    print(&str, v, princ);
 | 
			
		||||
    value_t outp;
 | 
			
		||||
    if (str.size < MAX_INL_SIZE) {
 | 
			
		||||
        outp = cvalue_string(str.size);
 | 
			
		||||
        memcpy(cv_data((cvalue_t*)ptr(outp)), str.buf, str.size);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        size_t sz;
 | 
			
		||||
        char *buf = ios_takebuf(&str, &sz);
 | 
			
		||||
        buf[sz] = '\0';
 | 
			
		||||
        outp = cvalue_from_ref(stringtype, buf, sz-1, NIL);
 | 
			
		||||
        cv_autorelease((cvalue_t*)ptr(outp));
 | 
			
		||||
    }
 | 
			
		||||
    ios_close(&str);
 | 
			
		||||
    PUSH(v);
 | 
			
		||||
    value_t buf = fl_buffer(NULL, 0);
 | 
			
		||||
    ios_t *s = value2c(ios_t*,buf);
 | 
			
		||||
    print(s, Stack[SP-1], princ);
 | 
			
		||||
    Stack[SP-1] = buf;
 | 
			
		||||
    value_t outp = stream_to_string(&Stack[SP-1]);
 | 
			
		||||
    (void)POP();
 | 
			
		||||
    return outp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +86,7 @@ value_t fl_string_encode(value_t *args, u_int32_t nargs)
 | 
			
		|||
            return str;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    type_error("string.encode", "wide character array", args[0]);
 | 
			
		||||
    type_error("string.encode", "wchar array", args[0]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
value_t fl_string_decode(value_t *args, u_int32_t nargs)
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +146,7 @@ value_t fl_string(value_t *args, u_int32_t nargs)
 | 
			
		|||
            sz += cv_len((cvalue_t*)ptr(cv));
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        args[i] = print_to_string(args[i], 0);
 | 
			
		||||
        args[i] = print_to_string(args[i], iscprim(args[i]));
 | 
			
		||||
        if (nargs == 1)  // convert single value to string
 | 
			
		||||
            return args[i];
 | 
			
		||||
        sz += cv_len((cvalue_t*)ptr(args[i]));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -239,6 +239,15 @@
 | 
			
		|||
(define (list-ref lst n)
 | 
			
		||||
  (car (nthcdr lst n)))
 | 
			
		||||
 | 
			
		||||
; bounded length test
 | 
			
		||||
; use this instead of (= (length lst) n), since it avoids unnecessary
 | 
			
		||||
; work and always terminates.
 | 
			
		||||
(define (length= lst n)
 | 
			
		||||
  (cond ((< n 0)     #f)
 | 
			
		||||
	((= n 0)     (null? lst))
 | 
			
		||||
	((null? lst) (= n 0))
 | 
			
		||||
	(else        (length= (cdr lst) (- n 1)))))
 | 
			
		||||
 | 
			
		||||
(define (list* . l)
 | 
			
		||||
  (if (atom? (cdr l))
 | 
			
		||||
      (car l)
 | 
			
		||||
| 
						 | 
				
			
			@ -408,6 +417,7 @@
 | 
			
		|||
  (define (vals->cond key v)
 | 
			
		||||
    (cond ((eq? v 'else)   'else)
 | 
			
		||||
	  ((null? v)       #f)
 | 
			
		||||
          ((atom? v)       `(eqv? ,key ,v))
 | 
			
		||||
	  ((null? (cdr v)) `(eqv? ,key ,(quote-value (car v))))
 | 
			
		||||
	  (else            `(memv ,key ',v))))
 | 
			
		||||
  (let ((g (gensym)))
 | 
			
		||||
| 
						 | 
				
			
			@ -560,6 +570,20 @@
 | 
			
		|||
		(trim-start s at-start 0 L)
 | 
			
		||||
		(trim-end   s at-end   L))))
 | 
			
		||||
 | 
			
		||||
(define (string.map f s)
 | 
			
		||||
  (let ((b (buffer))
 | 
			
		||||
	(n (length s)))
 | 
			
		||||
    (let loop ((i 0))
 | 
			
		||||
      (if (< i n)
 | 
			
		||||
	  (begin (io.putc b (f (string.char s i)))
 | 
			
		||||
		 (loop (string.inc s i)))
 | 
			
		||||
	  (io.tostring! b)))))
 | 
			
		||||
 | 
			
		||||
(define (print-to-string v)
 | 
			
		||||
  (let ((b (buffer)))
 | 
			
		||||
    (io.print b v)
 | 
			
		||||
    (io.tostring! b)))
 | 
			
		||||
 | 
			
		||||
(define (io.readline s) (io.readuntil s #byte(0xA)))
 | 
			
		||||
 | 
			
		||||
(define (repl)
 | 
			
		||||
| 
						 | 
				
			
			@ -584,12 +608,9 @@
 | 
			
		|||
(define (print-exception e)
 | 
			
		||||
  (cond ((and (pair? e)
 | 
			
		||||
	      (eq? (car e) 'type-error)
 | 
			
		||||
	      (= (length e) 4))
 | 
			
		||||
	 (io.princ *stderr* "type-error: ")
 | 
			
		||||
	 (io.print *stderr* (cadr e))
 | 
			
		||||
	 (io.princ *stderr* ": expected ")
 | 
			
		||||
	 (io.print *stderr* (caddr e))
 | 
			
		||||
	 (io.princ *stderr* ", got ")
 | 
			
		||||
	      (length= e 4))
 | 
			
		||||
	 (io.princ *stderr*
 | 
			
		||||
		   "type-error: " (cadr e) ": expected " (caddr e) ", got ")
 | 
			
		||||
	 (io.print *stderr* (cadddr e)))
 | 
			
		||||
 | 
			
		||||
	((and (pair? e)
 | 
			
		||||
| 
						 | 
				
			
			@ -610,9 +631,12 @@
 | 
			
		|||
	 (io.princ *stderr* "in file " (cadr e)))
 | 
			
		||||
 | 
			
		||||
	((and (list? e)
 | 
			
		||||
	      (= (length e) 2))
 | 
			
		||||
	 (io.print *stderr* (car e))
 | 
			
		||||
	 (io.princ *stderr* ": " (cadr e)))
 | 
			
		||||
	      (length= e 2))
 | 
			
		||||
	 (io.princ *stderr* (car e) ": ")
 | 
			
		||||
	 (let ((msg (cadr e)))
 | 
			
		||||
	   ((if (or (string? msg) (symbol? msg))
 | 
			
		||||
		io.princ io.print)
 | 
			
		||||
	    *stderr* msg)))
 | 
			
		||||
 | 
			
		||||
	(else (io.princ *stderr* "*** Unhandled exception: ")
 | 
			
		||||
	      (io.print *stderr* e)))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -838,7 +838,7 @@ String API
 | 
			
		|||
*string.encode  - to utf8
 | 
			
		||||
*string.decode  - from utf8 to UCS
 | 
			
		||||
 string.width   - # columns
 | 
			
		||||
 string.map     - (string.map f s)
 | 
			
		||||
*string.map     - (string.map f s)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
IOStream API
 | 
			
		||||
| 
						 | 
				
			
			@ -857,7 +857,8 @@ IOStream API
 | 
			
		|||
*io.discardbuffer
 | 
			
		||||
*io.write     - (io.write s cvalue)
 | 
			
		||||
*io.read      - (io.read s ctype [len])
 | 
			
		||||
 io.getc      - get utf8 character(s)
 | 
			
		||||
*io.getc      - get utf8 character
 | 
			
		||||
*io.putc
 | 
			
		||||
*io.readline
 | 
			
		||||
*io.readuntil
 | 
			
		||||
 io.copy      - (io.copy to from [nbytes])
 | 
			
		||||
| 
						 | 
				
			
			@ -867,6 +868,7 @@ IOStream API
 | 
			
		|||
 io.seekend   - move to end of stream
 | 
			
		||||
 io.trunc
 | 
			
		||||
 io.read!     - destructively take data
 | 
			
		||||
*io.tostring!
 | 
			
		||||
 io.readlines
 | 
			
		||||
 io.readall
 | 
			
		||||
 print-to-string
 | 
			
		||||
| 
						 | 
				
			
			@ -955,6 +957,8 @@ consolidated todo list as of 8/30:
 | 
			
		|||
- eliminate string copy in lerror() when possible
 | 
			
		||||
* fix printing lists of short strings
 | 
			
		||||
 | 
			
		||||
- preallocate all byte,int8,uint8 values, and some wchars
 | 
			
		||||
 | 
			
		||||
- remaining c types
 | 
			
		||||
- remaining cvalues functions
 | 
			
		||||
- finish ios
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -674,6 +674,7 @@ static void _ios_init(ios_t *s)
 | 
			
		|||
    s->ownfd = 0;
 | 
			
		||||
    s->_eof = 0;
 | 
			
		||||
    s->rereadable = 0;
 | 
			
		||||
    s->readonly = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* stream object initializers. we do no allocation. */
 | 
			
		||||
| 
						 | 
				
			
			@ -828,6 +829,13 @@ int ios_getutf8(ios_t *s, uint32_t *pwc)
 | 
			
		|||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ios_pututf8(ios_t *s, uint32_t wc)
 | 
			
		||||
{
 | 
			
		||||
    char buf[8];
 | 
			
		||||
    size_t n = u8_toutf8(buf, 8, &wc, 1);
 | 
			
		||||
    return ios_write(s, buf, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ios_purge(ios_t *s)
 | 
			
		||||
{
 | 
			
		||||
    if (s->state == bst_rd) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue