altos/scheme: Add ports. Split scheme code up.
[fw/altos] / src / scheme / ao_scheme_string.c
index b00ef276815be1b04f6476603b1924ce56a1eaa4..c49e1e325c9872a97634614afdf6a6669d8774bc 100644 (file)
@@ -51,26 +51,12 @@ ao_scheme_string_alloc(int len)
        if (!s)
                return NULL;
        s->type = AO_SCHEME_STRING;
+       s->val[len] = '\0';
        return s;
 }
 
 struct ao_scheme_string *
-ao_scheme_string_copy(struct ao_scheme_string *a)
-{
-       int                     alen = strlen(a->val);
-       struct ao_scheme_string *r;
-
-       ao_scheme_string_stash(0, a);
-       r = ao_scheme_string_alloc(alen);
-       a = ao_scheme_string_fetch(0);
-       if (!r)
-               return NULL;
-       strcpy(r->val, a->val);
-       return r;
-}
-
-struct ao_scheme_string *
-ao_scheme_string_make(char *a)
+ao_scheme_string_new(char *a)
 {
        struct ao_scheme_string *r;
 
@@ -87,9 +73,9 @@ ao_scheme_atom_to_string(struct ao_scheme_atom *a)
        int                     alen = strlen(a->name);
        struct ao_scheme_string *r;
 
-       ao_scheme_poly_stash(0, ao_scheme_atom_poly(a));
+       ao_scheme_atom_stash(a);
        r = ao_scheme_string_alloc(alen);
-       a = ao_scheme_poly_atom(ao_scheme_poly_fetch(0));
+       a = ao_scheme_atom_fetch();
        if (!r)
                return NULL;
        strcpy(r->val, a->name);
@@ -103,11 +89,11 @@ ao_scheme_string_cat(struct ao_scheme_string *a, struct ao_scheme_string *b)
        int                             blen = strlen(b->val);
        struct ao_scheme_string         *r;
 
-       ao_scheme_string_stash(0, a);
-       ao_scheme_string_stash(1, b);
+       ao_scheme_string_stash(a);
+       ao_scheme_string_stash(b);
        r = ao_scheme_string_alloc(alen + blen);
-       a = ao_scheme_string_fetch(0);
-       b = ao_scheme_string_fetch(1);
+       b = ao_scheme_string_fetch();
+       a = ao_scheme_string_fetch();
        if (!r)
                return NULL;
        strcpy(r->val, a->val);
@@ -115,94 +101,247 @@ ao_scheme_string_cat(struct ao_scheme_string *a, struct ao_scheme_string *b)
        return r;
 }
 
-ao_poly
+static ao_poly
 ao_scheme_string_pack(struct ao_scheme_cons *cons)
 {
-       struct ao_scheme_string *r;
-       char                    *rval;
+       struct ao_scheme_string *string;
+       char                    *s;
        int                     len;
 
        len = ao_scheme_cons_length(cons);
-       ao_scheme_cons_stash(0, cons);
-       r = ao_scheme_string_alloc(len);
-       cons = ao_scheme_cons_fetch(0);
-       if (!r)
+       ao_scheme_cons_stash(cons);
+       string = ao_scheme_string_alloc(len);
+       cons = ao_scheme_cons_fetch();
+       if (!string)
                return AO_SCHEME_NIL;
-       rval = r->val;
+       s = string->val;
 
        while (cons) {
-               bool fail = false;
                ao_poly car = cons->car;
-               *rval++ = ao_scheme_poly_integer(car, &fail);
-               if (fail)
-                       return ao_scheme_error(AO_SCHEME_INVALID, "non-int passed to pack");
+               int32_t c;
+               if (!ao_scheme_is_integer(car) || (c = ao_scheme_poly_integer(car)) == 0)
+                       return ao_scheme_error(AO_SCHEME_INVALID, "%v: Invalid %v", _ao_scheme_atom_list2d3estring, car);
+               *s++ = c;
                cons = ao_scheme_cons_cdr(cons);
        }
-       *rval++ = 0;
-       return ao_scheme_string_poly(r);
+       return ao_scheme_string_poly(string);
 }
 
-ao_poly
+static ao_poly
 ao_scheme_string_unpack(struct ao_scheme_string *a)
 {
-       struct ao_scheme_cons   *cons = NULL, *tail = NULL;
-       int                     c;
-       int                     i;
-
-       for (i = 0; (c = a->val[i]); i++) {
-               struct ao_scheme_cons   *n;
-               ao_scheme_cons_stash(0, cons);
-               ao_scheme_cons_stash(1, tail);
-               ao_scheme_string_stash(0, a);
-               n = ao_scheme_cons_cons(ao_scheme_int_poly(c), AO_SCHEME_NIL);
-               a = ao_scheme_string_fetch(0);
-               cons = ao_scheme_cons_fetch(0);
-               tail = ao_scheme_cons_fetch(1);
-
-               if (!n) {
-                       cons = NULL;
+       ao_poly cons = AO_SCHEME_NIL;
+       int     i;
+
+       for (i = strlen(a->val); --i >= 0;) {
+               ao_scheme_string_stash(a);
+               cons = ao_scheme_cons(ao_scheme_int_poly(a->val[i]), cons);
+               a = ao_scheme_string_fetch();
+               if (!cons)
                        break;
-               }
-               if (tail)
-                       tail->cdr = ao_scheme_cons_poly(n);
-               else
-                       cons = n;
-               tail = n;
        }
-       return ao_scheme_cons_poly(cons);
+       return cons;
 }
 
 void
-ao_scheme_string_write(ao_poly p, bool write)
+ao_scheme_string_write(FILE *out, ao_poly p, bool write)
 {
        struct ao_scheme_string *s = ao_scheme_poly_string(p);
        char                    *sval = s->val;
        char                    c;
 
        if (write) {
-               putchar('"');
+               putc('"', out);
                while ((c = *sval++)) {
                        switch (c) {
+                       case '\a':
+                               fputs("\\a", out);
+                               break;
+                       case '\b':
+                               fputs("\\b", out);
+                               break;
+                       case '\t':
+                               fputs("\\t", out);
+                               break;
                        case '\n':
-                               printf ("\\n");
+                               fputs("\\n", out);
                                break;
                        case '\r':
-                               printf ("\\r");
+                               fputs("\\r", out);
                                break;
-                       case '\t':
-                               printf ("\\t");
+                       case '\f':
+                               fputs("\\f", out);
+                               break;
+                       case '\v':
+                               fputs("\\v", out);
+                               break;
+                       case '\"':
+                               fputs("\\\"", out);
+                               break;
+                       case '\\':
+                               fputs("\\\\", out);
                                break;
                        default:
                                if (c < ' ')
-                                       printf("\\%03o", c);
+                                       fprintf(out, "\\%03o", c);
                                else
-                                       putchar(c);
+                                       putc(c, out);
                                break;
                        }
                }
-               putchar('"');
+               putc('"', out);
        } else {
                while ((c = *sval++))
-                       putchar(c);
+                       putc(c, out);
+       }
+}
+
+ao_poly
+ao_scheme_do_stringp(struct ao_scheme_cons *cons)
+{
+       return ao_scheme_do_typep(_ao_scheme_atom_string3f, AO_SCHEME_STRING, cons);
+}
+
+ao_poly
+ao_scheme_do_list_to_string(struct ao_scheme_cons *cons)
+{
+       struct ao_scheme_cons   *list;
+
+       if (!ao_scheme_parse_args(_ao_scheme_atom_list2d3estring, cons,
+                                 AO_SCHEME_CONS, &list,
+                                 AO_SCHEME_ARG_END))
+               return AO_SCHEME_NIL;
+       return ao_scheme_string_pack(list);
+}
+
+ao_poly
+ao_scheme_do_string_to_list(struct ao_scheme_cons *cons)
+{
+       struct ao_scheme_string *string;
+
+       if (!ao_scheme_parse_args(_ao_scheme_atom_string2d3elist, cons,
+                                 AO_SCHEME_STRING, &string,
+                                 AO_SCHEME_ARG_END))
+               return AO_SCHEME_NIL;
+       return ao_scheme_string_unpack(string);
+}
+
+static char *
+ao_scheme_string_ref(struct ao_scheme_string *string, int32_t r)
+{
+       char *s = string->val;
+       while (*s && r) {
+               ++s;
+               --r;
        }
+       return s;
+}
+
+ao_poly
+ao_scheme_do_string_ref(struct ao_scheme_cons *cons)
+{
+       struct ao_scheme_string *string;
+       int32_t                 ref;
+       char                    *s;
+
+       if (!ao_scheme_parse_args(_ao_scheme_atom_string2dref, cons,
+                                 AO_SCHEME_STRING, &string,
+                                 AO_SCHEME_INT, &ref,
+                                 AO_SCHEME_ARG_END))
+               return AO_SCHEME_NIL;
+
+       s = ao_scheme_string_ref(string, ref);
+       if (!*s)
+               return ao_scheme_error(AO_SCHEME_INVALID, "%v: string %v ref %v invalid",
+                                      _ao_scheme_atom_string2dref,
+                                      cons->car,
+                                      ao_scheme_arg(cons, 1));
+       return ao_scheme_integer_poly(*s);
+}
+
+ao_poly
+ao_scheme_do_string_length(struct ao_scheme_cons *cons)
+{
+       struct ao_scheme_string *string;
+
+       if (!ao_scheme_parse_args(_ao_scheme_atom_string2dlength, cons,
+                                 AO_SCHEME_STRING, &string,
+                                 AO_SCHEME_ARG_END))
+               return AO_SCHEME_NIL;
+       return ao_scheme_integer_poly(strlen(string->val));
+}
+
+ao_poly
+ao_scheme_do_string_set(struct ao_scheme_cons *cons)
+{
+       struct ao_scheme_string *string;
+       int32_t                 ref;
+       int32_t                 val;
+       char                    *s;
+
+       if (!ao_scheme_parse_args(_ao_scheme_atom_string2dset21, cons,
+                                 AO_SCHEME_STRING, &string,
+                                 AO_SCHEME_INT, &ref,
+                                 AO_SCHEME_INT, &val,
+                                 AO_SCHEME_ARG_END))
+               return AO_SCHEME_NIL;
+       if (!val)
+               goto fail;
+       s = ao_scheme_string_ref(string, ref);
+       if (!*s)
+               goto fail;
+       *s = val;
+       return ao_scheme_integer_poly(val);
+fail:
+       return ao_scheme_error(AO_SCHEME_INVALID, "%v: %v[%v] = %v invalid",
+                              _ao_scheme_atom_string2dset21,
+                              ao_scheme_arg(cons, 0),
+                              ao_scheme_arg(cons, 1),
+                              ao_scheme_arg(cons, 2));
+}
+
+ao_poly
+ao_scheme_do_make_string(struct ao_scheme_cons *cons)
+{
+       int32_t                 len;
+       int32_t                 fill;
+       struct ao_scheme_string *string;
+
+       if (!ao_scheme_parse_args(_ao_scheme_atom_make2dstring, cons,
+                                 AO_SCHEME_INT, &len,
+                                 AO_SCHEME_INT|AO_SCHEME_ARG_OPTIONAL, ao_scheme_int_poly(' '), &fill,
+                                 AO_SCHEME_ARG_END))
+               return AO_SCHEME_NIL;
+       if (!fill)
+               return ao_scheme_error(AO_SCHEME_INVALID, "%v: fill 0 invalid",
+                                      _ao_scheme_atom_make2dstring);
+       string = ao_scheme_string_alloc(len);
+       if (!string)
+               return AO_SCHEME_NIL;
+       memset(string->val, fill, len);
+       return ao_scheme_string_poly(string);
+}
+
+ao_poly
+ao_scheme_do_symbol_to_string(struct ao_scheme_cons *cons)
+{
+       struct ao_scheme_atom   *atom;
+
+       if (!ao_scheme_parse_args(_ao_scheme_atom_symbol2d3estring, cons,
+                                 AO_SCHEME_ATOM, &atom,
+                                 AO_SCHEME_ARG_END))
+               return AO_SCHEME_NIL;
+       return ao_scheme_string_poly(ao_scheme_atom_to_string(atom));
+}
+
+ao_poly
+ao_scheme_do_string_to_symbol(struct ao_scheme_cons *cons)
+{
+       struct ao_scheme_string *string;
+
+       if (!ao_scheme_parse_args(_ao_scheme_atom_string2d3esymbol, cons,
+                                 AO_SCHEME_STRING, &string,
+                                 AO_SCHEME_ARG_END))
+               return AO_SCHEME_NIL;
+       return ao_scheme_atom_poly(ao_scheme_string_to_atom(string));
 }