From 65429b4f102b86c4939cf3bc33877f40ad9768b3 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Sun, 27 Dec 2015 23:47:29 -0500 Subject: [PATCH] Check for valid indices in substring and string-copy. --- extlib/benz/string.c | 874 ++++++++++++++++++++++--------------------- 1 file changed, 446 insertions(+), 428 deletions(-) diff --git a/extlib/benz/string.c b/extlib/benz/string.c index de023afa..7d09eea5 100644 --- a/extlib/benz/string.c +++ b/extlib/benz/string.c @@ -5,509 +5,509 @@ #include "picrin.h" struct pic_chunk { - char *str; - int refcnt; - size_t len; - char buf[1]; + char *str; + int refcnt; + size_t len; + char buf[1]; }; struct pic_rope { - int refcnt; - size_t weight; - struct pic_chunk *chunk; - size_t offset; - struct pic_rope *left, *right; + int refcnt; + size_t weight; + struct pic_chunk *chunk; + size_t offset; + struct pic_rope *left, *right; }; #define CHUNK_INCREF(c) do { \ - (c)->refcnt++; \ - } while (0) + (c)->refcnt++; \ + } while (0) #define CHUNK_DECREF(c) do { \ - struct pic_chunk *c_ = (c); \ - if (! --c_->refcnt) { \ - if (c_->str != c_->buf) \ - pic_free(pic, c_->str); \ - pic_free(pic, c_); \ - } \ - } while (0) + struct pic_chunk *c_ = (c); \ + if (! --c_->refcnt) { \ + if (c_->str != c_->buf) \ + pic_free(pic, c_->str); \ + pic_free(pic, c_); \ + } \ + } while (0) void pic_rope_incref(pic_state PIC_UNUSED(*pic), struct pic_rope *x) { - x->refcnt++; + x->refcnt++; } void pic_rope_decref(pic_state *pic, struct pic_rope *x) { - if (! --x->refcnt) { - if (x->chunk) { - CHUNK_DECREF(x->chunk); - pic_free(pic, x); - return; - } - pic_rope_decref(pic, x->left); - pic_rope_decref(pic, x->right); - pic_free(pic, x); - } + if (! --x->refcnt) { + if (x->chunk) { + CHUNK_DECREF(x->chunk); + pic_free(pic, x); + return; + } + pic_rope_decref(pic, x->left); + pic_rope_decref(pic, x->right); + pic_free(pic, x); + } } static struct pic_chunk * pic_make_chunk(pic_state *pic, const char *str, size_t len) { - struct pic_chunk *c; + struct pic_chunk *c; - c = pic_malloc(pic, sizeof(struct pic_chunk) + len); - c->refcnt = 1; - c->str = c->buf; - c->len = len; - c->buf[len] = 0; - memcpy(c->buf, str, len); + c = pic_malloc(pic, sizeof(struct pic_chunk) + len); + c->refcnt = 1; + c->str = c->buf; + c->len = len; + c->buf[len] = 0; + memcpy(c->buf, str, len); - return c; + return c; } static struct pic_rope * pic_make_rope(pic_state *pic, struct pic_chunk *c) { - struct pic_rope *x; + struct pic_rope *x; - x = pic_malloc(pic, sizeof(struct pic_rope)); - x->refcnt = 1; - x->left = NULL; - x->right = NULL; - x->weight = c->len; - x->offset = 0; - x->chunk = c; /* delegate ownership */ + x = pic_malloc(pic, sizeof(struct pic_rope)); + x->refcnt = 1; + x->left = NULL; + x->right = NULL; + x->weight = c->len; + x->offset = 0; + x->chunk = c; /* delegate ownership */ - return x; + return x; } static pic_str * pic_make_string(pic_state *pic, struct pic_rope *rope) { - pic_str *str; + pic_str *str; - str = (pic_str *)pic_obj_alloc(pic, sizeof(pic_str), PIC_TT_STRING); - str->rope = rope; /* delegate ownership */ - return str; + str = (pic_str *)pic_obj_alloc(pic, sizeof(pic_str), PIC_TT_STRING); + str->rope = rope; /* delegate ownership */ + return str; } static size_t rope_len(struct pic_rope *x) { - return x->weight; + return x->weight; } static char rope_at(struct pic_rope *x, size_t i) { - while (i < x->weight) { - if (x->chunk) { - return x->chunk->str[x->offset + i]; - } - if (i < x->left->weight) { - x = x->left; - } else { - x = x->right; - i -= x->left->weight; - } - } - return -1; + while (i < x->weight) { + if (x->chunk) { + return x->chunk->str[x->offset + i]; + } + if (i < x->left->weight) { + x = x->left; + } else { + x = x->right; + i -= x->left->weight; + } + } + return -1; } static struct pic_rope * rope_cat(pic_state *pic, struct pic_rope *x, struct pic_rope *y) { - struct pic_rope *z; + struct pic_rope *z; - z = pic_malloc(pic, sizeof(struct pic_rope)); - z->refcnt = 1; - z->left = x; - z->right = y; - z->weight = x->weight + y->weight; - z->offset = 0; - z->chunk = NULL; + z = pic_malloc(pic, sizeof(struct pic_rope)); + z->refcnt = 1; + z->left = x; + z->right = y; + z->weight = x->weight + y->weight; + z->offset = 0; + z->chunk = NULL; - pic_rope_incref(pic, x); - pic_rope_incref(pic, y); + pic_rope_incref(pic, x); + pic_rope_incref(pic, y); - return z; + return z; } static struct pic_rope * rope_sub(pic_state *pic, struct pic_rope *x, size_t i, size_t j) { - assert(i <= j); - assert(j <= x->weight); + assert(i <= j); + assert(j <= x->weight); - if (i == 0 && x->weight == j) { - pic_rope_incref(pic, x); - return x; - } + if (i == 0 && x->weight == j) { + pic_rope_incref(pic, x); + return x; + } - if (x->chunk) { - struct pic_rope *y; + if (x->chunk) { + struct pic_rope *y; - y = pic_malloc(pic, sizeof(struct pic_rope)); - y->refcnt = 1; - y->left = NULL; - y->right = NULL; - y->weight = j - i; - y->offset = x->offset + i; - y->chunk = x->chunk; + y = pic_malloc(pic, sizeof(struct pic_rope)); + y->refcnt = 1; + y->left = NULL; + y->right = NULL; + y->weight = j - i; + y->offset = x->offset + i; + y->chunk = x->chunk; - CHUNK_INCREF(x->chunk); + CHUNK_INCREF(x->chunk); - return y; - } + return y; + } - if (j <= x->left->weight) { - return rope_sub(pic, x->left, i, j); - } - else if (x->left->weight <= i) { - return rope_sub(pic, x->right, i - x->left->weight, j - x->left->weight); - } - else { - struct pic_rope *r, *l; + if (j <= x->left->weight) { + return rope_sub(pic, x->left, i, j); + } + else if (x->left->weight <= i) { + return rope_sub(pic, x->right, i - x->left->weight, j - x->left->weight); + } + else { + struct pic_rope *r, *l; - l = rope_sub(pic, x->left, i, x->left->weight); - r = rope_sub(pic, x->right, 0, j - x->left->weight); - x = rope_cat(pic, l, r); + l = rope_sub(pic, x->left, i, x->left->weight); + r = rope_sub(pic, x->right, 0, j - x->left->weight); + x = rope_cat(pic, l, r); - pic_rope_decref(pic, l); - pic_rope_decref(pic, r); + pic_rope_decref(pic, l); + pic_rope_decref(pic, r); - return x; - } + return x; + } } static void flatten(pic_state *pic, struct pic_rope *x, struct pic_chunk *c, size_t offset) { - if (x->chunk) { - memcpy(c->str + offset, x->chunk->str + x->offset, x->weight); - CHUNK_DECREF(x->chunk); + if (x->chunk) { + memcpy(c->str + offset, x->chunk->str + x->offset, x->weight); + CHUNK_DECREF(x->chunk); - x->chunk = c; - x->offset = offset; - CHUNK_INCREF(c); - return; - } - flatten(pic, x->left, c, offset); - flatten(pic, x->right, c, offset + x->left->weight); + x->chunk = c; + x->offset = offset; + CHUNK_INCREF(c); + return; + } + flatten(pic, x->left, c, offset); + flatten(pic, x->right, c, offset + x->left->weight); - pic_rope_decref(pic, x->left); - pic_rope_decref(pic, x->right); - x->left = x->right = NULL; - x->chunk = c; - x->offset = offset; - CHUNK_INCREF(c); + pic_rope_decref(pic, x->left); + pic_rope_decref(pic, x->right); + x->left = x->right = NULL; + x->chunk = c; + x->offset = offset; + CHUNK_INCREF(c); } static const char * rope_cstr(pic_state *pic, struct pic_rope *x) { - struct pic_chunk *c; + struct pic_chunk *c; - if (x->chunk && x->offset == 0 && x->weight == x->chunk->len) { - return x->chunk->str; /* reuse cached chunk */ - } + if (x->chunk && x->offset == 0 && x->weight == x->chunk->len) { + return x->chunk->str; /* reuse cached chunk */ + } - c = pic_malloc(pic, sizeof(struct pic_chunk) + x->weight); - c->refcnt = 1; - c->len = x->weight; - c->str = c->buf; - c->str[c->len] = '\0'; + c = pic_malloc(pic, sizeof(struct pic_chunk) + x->weight); + c->refcnt = 1; + c->len = x->weight; + c->str = c->buf; + c->str[c->len] = '\0'; - flatten(pic, x, c, 0); + flatten(pic, x, c, 0); - CHUNK_DECREF(c); - return c->str; + CHUNK_DECREF(c); + return c->str; } pic_str * pic_make_str(pic_state *pic, const char *str, int len) { - if (str == NULL && len > 0) { - pic_errorf(pic, "zero length specified against NULL ptr"); - } - return pic_make_string(pic, pic_make_rope(pic, pic_make_chunk(pic, str, len))); + if (str == NULL && len > 0) { + pic_errorf(pic, "zero length specified against NULL ptr"); + } + return pic_make_string(pic, pic_make_rope(pic, pic_make_chunk(pic, str, len))); } pic_str * pic_make_str_cstr(pic_state *pic, const char *cstr) { - return pic_make_str(pic, cstr, strlen(cstr)); + return pic_make_str(pic, cstr, strlen(cstr)); } int pic_str_len(pic_str *str) { - return rope_len(str->rope); + return rope_len(str->rope); } char pic_str_ref(pic_state *pic, pic_str *str, int i) { - int c; + int c; - c = rope_at(str->rope, i); - if (c == -1) { - pic_errorf(pic, "index out of range %d", i); - } - return (char)c; + c = rope_at(str->rope, i); + if (c == -1) { + pic_errorf(pic, "index out of range %d", i); + } + return (char)c; } pic_str * pic_str_cat(pic_state *pic, pic_str *a, pic_str *b) { - return pic_make_string(pic, rope_cat(pic, a->rope, b->rope)); + return pic_make_string(pic, rope_cat(pic, a->rope, b->rope)); } pic_str * pic_str_sub(pic_state *pic, pic_str *str, int s, int e) { - return pic_make_string(pic, rope_sub(pic, str->rope, s, e)); + return pic_make_string(pic, rope_sub(pic, str->rope, s, e)); } int pic_str_cmp(pic_state *pic, pic_str *str1, pic_str *str2) { - return strcmp(pic_str_cstr(pic, str1), pic_str_cstr(pic, str2)); + return strcmp(pic_str_cstr(pic, str1), pic_str_cstr(pic, str2)); } const char * pic_str_cstr(pic_state *pic, pic_str *str) { - return rope_cstr(pic, str->rope); + return rope_cstr(pic, str->rope); } pic_value pic_xvfformat(pic_state *pic, xFILE *file, const char *fmt, va_list ap) { - char c; - pic_value irrs = pic_nil_value(); + char c; + pic_value irrs = pic_nil_value(); - while ((c = *fmt++)) { - switch (c) { - default: - xfputc(pic, c, file); - break; - case '%': - c = *fmt++; - if (! c) - goto exit; - switch (c) { - default: - xfputc(pic, c, file); - break; - case '%': - xfputc(pic, '%', file); - break; - case 'c': - xfprintf(pic, file, "%c", va_arg(ap, int)); - break; - case 's': - xfprintf(pic, file, "%s", va_arg(ap, const char *)); - break; - case 'd': - xfprintf(pic, file, "%d", va_arg(ap, int)); - break; - case 'p': - xfprintf(pic, file, "%p", va_arg(ap, void *)); - break; - case 'f': - xfprintf(pic, file, "%f", va_arg(ap, double)); - break; - } - break; - case '~': - c = *fmt++; - if (! c) - goto exit; - switch (c) { - default: - xfputc(pic, c, file); - break; - case '~': - xfputc(pic, '~', file); - break; - case '%': - xfputc(pic, '\n', file); - break; - case 'a': - irrs = pic_cons(pic, pic_fdisplay(pic, va_arg(ap, pic_value), file), irrs); - break; - case 's': - irrs = pic_cons(pic, pic_fwrite(pic, va_arg(ap, pic_value), file), irrs); - break; - } - break; - } - } + while ((c = *fmt++)) { + switch (c) { + default: + xfputc(pic, c, file); + break; + case '%': + c = *fmt++; + if (! c) + goto exit; + switch (c) { + default: + xfputc(pic, c, file); + break; + case '%': + xfputc(pic, '%', file); + break; + case 'c': + xfprintf(pic, file, "%c", va_arg(ap, int)); + break; + case 's': + xfprintf(pic, file, "%s", va_arg(ap, const char *)); + break; + case 'd': + xfprintf(pic, file, "%d", va_arg(ap, int)); + break; + case 'p': + xfprintf(pic, file, "%p", va_arg(ap, void *)); + break; + case 'f': + xfprintf(pic, file, "%f", va_arg(ap, double)); + break; + } + break; + case '~': + c = *fmt++; + if (! c) + goto exit; + switch (c) { + default: + xfputc(pic, c, file); + break; + case '~': + xfputc(pic, '~', file); + break; + case '%': + xfputc(pic, '\n', file); + break; + case 'a': + irrs = pic_cons(pic, pic_fdisplay(pic, va_arg(ap, pic_value), file), irrs); + break; + case 's': + irrs = pic_cons(pic, pic_fwrite(pic, va_arg(ap, pic_value), file), irrs); + break; + } + break; + } + } exit: - return pic_reverse(pic, irrs); + return pic_reverse(pic, irrs); } pic_value pic_xvformat(pic_state *pic, const char *fmt, va_list ap) { - struct pic_port *port; - pic_value irrs; + struct pic_port *port; + pic_value irrs; - port = pic_open_output_string(pic); + port = pic_open_output_string(pic); - irrs = pic_xvfformat(pic, port->file, fmt, ap); - irrs = pic_cons(pic, pic_obj_value(pic_get_output_string(pic, port)), irrs); + irrs = pic_xvfformat(pic, port->file, fmt, ap); + irrs = pic_cons(pic, pic_obj_value(pic_get_output_string(pic, port)), irrs); - pic_close_port(pic, port); - return irrs; + pic_close_port(pic, port); + return irrs; } pic_value pic_xformat(pic_state *pic, const char *fmt, ...) { - va_list ap; - pic_value objs; + va_list ap; + pic_value objs; - va_start(ap, fmt); - objs = pic_xvformat(pic, fmt, ap); - va_end(ap); + va_start(ap, fmt); + objs = pic_xvformat(pic, fmt, ap); + va_end(ap); - return objs; + return objs; } void pic_vfformat(pic_state *pic, xFILE *file, const char *fmt, va_list ap) { - pic_xvfformat(pic, file, fmt, ap); + pic_xvfformat(pic, file, fmt, ap); } pic_str * pic_vformat(pic_state *pic, const char *fmt, va_list ap) { - struct pic_port *port; - pic_str *str; + struct pic_port *port; + pic_str *str; - port = pic_open_output_string(pic); + port = pic_open_output_string(pic); - pic_vfformat(pic, port->file, fmt, ap); - str = pic_get_output_string(pic, port); + pic_vfformat(pic, port->file, fmt, ap); + str = pic_get_output_string(pic, port); - pic_close_port(pic, port); - return str; + pic_close_port(pic, port); + return str; } pic_str * pic_format(pic_state *pic, const char *fmt, ...) { - va_list ap; - pic_str *str; + va_list ap; + pic_str *str; - va_start(ap, fmt); - str = pic_vformat(pic, fmt, ap); - va_end(ap); + va_start(ap, fmt); + str = pic_vformat(pic, fmt, ap); + va_end(ap); - return str; + return str; } static pic_value pic_str_string_p(pic_state *pic) { - pic_value v; + pic_value v; - pic_get_args(pic, "o", &v); + pic_get_args(pic, "o", &v); - return pic_bool_value(pic_str_p(v)); + return pic_bool_value(pic_str_p(v)); } static pic_value pic_str_string(pic_state *pic) { - int argc, i; - pic_value *argv; - pic_str *str; - char *buf; + int argc, i; + pic_value *argv; + pic_str *str; + char *buf; - pic_get_args(pic, "*", &argc, &argv); + pic_get_args(pic, "*", &argc, &argv); - buf = pic_malloc(pic, argc); + buf = pic_malloc(pic, argc); - for (i = 0; i < argc; ++i) { - pic_assert_type(pic, argv[i], char); - buf[i] = pic_char(argv[i]); - } + for (i = 0; i < argc; ++i) { + pic_assert_type(pic, argv[i], char); + buf[i] = pic_char(argv[i]); + } - str = pic_make_str(pic, buf, argc); - pic_free(pic, buf); + str = pic_make_str(pic, buf, argc); + pic_free(pic, buf); - return pic_obj_value(str); + return pic_obj_value(str); } static pic_value pic_str_make_string(pic_state *pic) { - int len; - char c = ' '; - char *buf; - pic_value ret; + int len; + char c = ' '; + char *buf; + pic_value ret; - pic_get_args(pic, "i|c", &len, &c); + pic_get_args(pic, "i|c", &len, &c); - buf = pic_malloc(pic, len); - memset(buf, c, len); + buf = pic_malloc(pic, len); + memset(buf, c, len); - ret = pic_obj_value(pic_make_str(pic, buf, len)); + ret = pic_obj_value(pic_make_str(pic, buf, len)); - pic_free(pic, buf); - return ret; + pic_free(pic, buf); + return ret; } static pic_value pic_str_string_length(pic_state *pic) { - pic_str *str; + pic_str *str; - pic_get_args(pic, "s", &str); + pic_get_args(pic, "s", &str); - return pic_int_value(pic_str_len(str)); + return pic_int_value(pic_str_len(str)); } static pic_value pic_str_string_ref(pic_state *pic) { - pic_str *str; - int k; + pic_str *str; + int k; - pic_get_args(pic, "si", &str, &k); + pic_get_args(pic, "si", &str, &k); - return pic_char_value(pic_str_ref(pic, str, k)); + return pic_char_value(pic_str_ref(pic, str, k)); } #define DEFINE_STRING_CMP(name, op) \ - static pic_value \ - pic_str_string_##name(pic_state *pic) \ - { \ - int argc, i; \ - pic_value *argv; \ - \ - pic_get_args(pic, "*", &argc, &argv); \ - \ - if (argc < 1 || ! pic_str_p(argv[0])) { \ - return pic_false_value(); \ - } \ - \ - for (i = 1; i < argc; ++i) { \ - if (! pic_str_p(argv[i])) { \ + static pic_value \ + pic_str_string_##name(pic_state *pic) \ + { \ + int argc, i; \ + pic_value *argv; \ + \ + pic_get_args(pic, "*", &argc, &argv); \ + \ + if (argc < 1 || ! pic_str_p(argv[0])) { \ + return pic_false_value(); \ + } \ + \ + for (i = 1; i < argc; ++i) { \ + if (! pic_str_p(argv[i])) { \ return pic_false_value(); \ - } \ - if (! (pic_str_cmp(pic, pic_str_ptr(argv[i-1]), pic_str_ptr(argv[i])) op 0)) { \ + } \ + if (! (pic_str_cmp(pic, pic_str_ptr(argv[i-1]), pic_str_ptr(argv[i])) op 0)) { \ return pic_false_value(); \ - } \ - } \ - return pic_true_value(); \ - } + } \ + } \ + return pic_true_value(); \ + } DEFINE_STRING_CMP(eq, ==) DEFINE_STRING_CMP(lt, <) @@ -518,200 +518,218 @@ DEFINE_STRING_CMP(ge, >=) static pic_value pic_str_string_copy(pic_state *pic) { - pic_str *str; - int n, start, end; + pic_str *str; + int n, start, end, len; - n = pic_get_args(pic, "s|ii", &str, &start, &end); + n = pic_get_args(pic, "s|ii", &str, &start, &end); - switch (n) { - case 1: - start = 0; - case 2: - end = pic_str_len(str); - } + len = pic_str_len(str); - return pic_obj_value(pic_str_sub(pic, str, start, end)); + switch (n) { + case 1: + start = 0; + case 2: + end = len; + } + +#if 0 +#if 0 + if (start < 0) start = 0; /* should an error be reported? */ + if (end > len) end = len; /* should an error be reported? */ +#else + if ((start < 0) || (end < 0) || (start > len) || (end > len)) + pic_errorf(pic, "string-copy: invalid index"); +#endif + if (end < start) /* surely this is an error!? */ + pic_errorf(pic, "string-copy: start index > end index"); +#else + /* simplest version to catch all cases as errors */ + if ((start < 0) || (end > len) || (end < start)) + pic_errorf(pic, "string-copy: invalid index"); +#endif + + return pic_obj_value(pic_str_sub(pic, str, start, end)); } static pic_value pic_str_string_append(pic_state *pic) { - int argc, i; - pic_value *argv; - pic_str *str; + int argc, i; + pic_value *argv; + pic_str *str; - pic_get_args(pic, "*", &argc, &argv); + pic_get_args(pic, "*", &argc, &argv); - str = pic_make_str(pic, NULL, 0); - for (i = 0; i < argc; ++i) { - if (! pic_str_p(argv[i])) { - pic_errorf(pic, "type error"); - } - str = pic_str_cat(pic, str, pic_str_ptr(argv[i])); - } - return pic_obj_value(str); + str = pic_make_str(pic, NULL, 0); + for (i = 0; i < argc; ++i) { + if (! pic_str_p(argv[i])) { + pic_errorf(pic, "type error"); + } + str = pic_str_cat(pic, str, pic_str_ptr(argv[i])); + } + return pic_obj_value(str); } static pic_value pic_str_string_map(pic_state *pic) { - struct pic_proc *proc; - pic_value *argv, vals, val; - int argc, i, len, j; - pic_str *str; - char *buf; + struct pic_proc *proc; + pic_value *argv, vals, val; + int argc, i, len, j; + pic_str *str; + char *buf; - pic_get_args(pic, "l*", &proc, &argc, &argv); + pic_get_args(pic, "l*", &proc, &argc, &argv); - if (argc == 0) { - pic_errorf(pic, "string-map: one or more strings expected, but got zero"); - } else { - pic_assert_type(pic, argv[0], str); - len = pic_str_len(pic_str_ptr(argv[0])); - } - for (i = 1; i < argc; ++i) { - pic_assert_type(pic, argv[i], str); + if (argc == 0) { + pic_errorf(pic, "string-map: one or more strings expected, but got zero"); + } else { + pic_assert_type(pic, argv[0], str); + len = pic_str_len(pic_str_ptr(argv[0])); + } + for (i = 1; i < argc; ++i) { + pic_assert_type(pic, argv[i], str); - len = len < pic_str_len(pic_str_ptr(argv[i])) - ? len - : pic_str_len(pic_str_ptr(argv[i])); - } - buf = pic_malloc(pic, len); + len = len < pic_str_len(pic_str_ptr(argv[i])) + ? len + : pic_str_len(pic_str_ptr(argv[i])); + } + buf = pic_malloc(pic, len); - pic_try { - for (i = 0; i < len; ++i) { - vals = pic_nil_value(); - for (j = 0; j < argc; ++j) { - pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); - } - val = pic_apply_list(pic, proc, vals); + pic_try { + for (i = 0; i < len; ++i) { + vals = pic_nil_value(); + for (j = 0; j < argc; ++j) { + pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); + } + val = pic_apply_list(pic, proc, vals); - pic_assert_type(pic, val, char); - buf[i] = pic_char(val); - } - str = pic_make_str(pic, buf, len); - } - pic_catch { - pic_free(pic, buf); - pic_raise(pic, pic->err); - } + pic_assert_type(pic, val, char); + buf[i] = pic_char(val); + } + str = pic_make_str(pic, buf, len); + } + pic_catch { + pic_free(pic, buf); + pic_raise(pic, pic->err); + } - pic_free(pic, buf); + pic_free(pic, buf); - return pic_obj_value(str); + return pic_obj_value(str); } static pic_value pic_str_string_for_each(pic_state *pic) { - struct pic_proc *proc; - int argc, len, i, j; - pic_value *argv, vals; + struct pic_proc *proc; + int argc, len, i, j; + pic_value *argv, vals; - pic_get_args(pic, "l*", &proc, &argc, &argv); + pic_get_args(pic, "l*", &proc, &argc, &argv); - if (argc == 0) { - pic_errorf(pic, "string-map: one or more strings expected, but got zero"); - } else { - pic_assert_type(pic, argv[0], str); - len = pic_str_len(pic_str_ptr(argv[0])); - } - for (i = 1; i < argc; ++i) { - pic_assert_type(pic, argv[i], str); + if (argc == 0) { + pic_errorf(pic, "string-map: one or more strings expected, but got zero"); + } else { + pic_assert_type(pic, argv[0], str); + len = pic_str_len(pic_str_ptr(argv[0])); + } + for (i = 1; i < argc; ++i) { + pic_assert_type(pic, argv[i], str); - len = len < pic_str_len(pic_str_ptr(argv[i])) - ? len - : pic_str_len(pic_str_ptr(argv[i])); - } + len = len < pic_str_len(pic_str_ptr(argv[i])) + ? len + : pic_str_len(pic_str_ptr(argv[i])); + } - for (i = 0; i < len; ++i) { - vals = pic_nil_value(); - for (j = 0; j < argc; ++j) { - pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); - } - pic_apply_list(pic, proc, vals); - } + for (i = 0; i < len; ++i) { + vals = pic_nil_value(); + for (j = 0; j < argc; ++j) { + pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); + } + pic_apply_list(pic, proc, vals); + } - return pic_undef_value(); + return pic_undef_value(); } static pic_value pic_str_list_to_string(pic_state *pic) { - pic_str *str; - pic_value list, e, it; - int i; - char *buf; + pic_str *str; + pic_value list, e, it; + int i; + char *buf; - pic_get_args(pic, "o", &list); + pic_get_args(pic, "o", &list); - if (pic_length(pic, list) == 0) { - return pic_obj_value(pic_make_str(pic, NULL, 0)); - } + if (pic_length(pic, list) == 0) { + return pic_obj_value(pic_make_str(pic, NULL, 0)); + } - buf = pic_malloc(pic, pic_length(pic, list)); + buf = pic_malloc(pic, pic_length(pic, list)); - pic_try { - i = 0; - pic_for_each (e, list, it) { - pic_assert_type(pic, e, char); + pic_try { + i = 0; + pic_for_each (e, list, it) { + pic_assert_type(pic, e, char); - buf[i++] = pic_char(e); - } + buf[i++] = pic_char(e); + } - str = pic_make_str(pic, buf, i); - } - pic_catch { - pic_free(pic, buf); - pic_raise(pic, pic->err); - } - pic_free(pic, buf); + str = pic_make_str(pic, buf, i); + } + pic_catch { + pic_free(pic, buf); + pic_raise(pic, pic->err); + } + pic_free(pic, buf); - return pic_obj_value(str); + return pic_obj_value(str); } static pic_value pic_str_string_to_list(pic_state *pic) { - pic_str *str; - pic_value list; - int n, start, end, i; + pic_str *str; + pic_value list; + int n, start, end, i; - n = pic_get_args(pic, "s|ii", &str, &start, &end); + n = pic_get_args(pic, "s|ii", &str, &start, &end); - switch (n) { - case 1: - start = 0; - case 2: - end = pic_str_len(str); - } + switch (n) { + case 1: + start = 0; + case 2: + end = pic_str_len(str); + } - list = pic_nil_value(); + list = pic_nil_value(); - for (i = start; i < end; ++i) { - pic_push(pic, pic_char_value(pic_str_ref(pic, str, i)), list); - } - return pic_reverse(pic, list); + for (i = start; i < end; ++i) { + pic_push(pic, pic_char_value(pic_str_ref(pic, str, i)), list); + } + return pic_reverse(pic, list); } void pic_init_str(pic_state *pic) { - pic_defun(pic, "string?", pic_str_string_p); - pic_defun(pic, "string", pic_str_string); - pic_defun(pic, "make-string", pic_str_make_string); - pic_defun(pic, "string-length", pic_str_string_length); - pic_defun(pic, "string-ref", pic_str_string_ref); - pic_defun(pic, "string-copy", pic_str_string_copy); - pic_defun(pic, "string-append", pic_str_string_append); - pic_defun(pic, "string-map", pic_str_string_map); - pic_defun(pic, "string-for-each", pic_str_string_for_each); - pic_defun(pic, "list->string", pic_str_list_to_string); - pic_defun(pic, "string->list", pic_str_string_to_list); + pic_defun(pic, "string?", pic_str_string_p); + pic_defun(pic, "string", pic_str_string); + pic_defun(pic, "make-string", pic_str_make_string); + pic_defun(pic, "string-length", pic_str_string_length); + pic_defun(pic, "string-ref", pic_str_string_ref); + pic_defun(pic, "string-copy", pic_str_string_copy); + pic_defun(pic, "string-append", pic_str_string_append); + pic_defun(pic, "string-map", pic_str_string_map); + pic_defun(pic, "string-for-each", pic_str_string_for_each); + pic_defun(pic, "list->string", pic_str_list_to_string); + pic_defun(pic, "string->list", pic_str_string_to_list); - pic_defun(pic, "string=?", pic_str_string_eq); - pic_defun(pic, "string?", pic_str_string_gt); - pic_defun(pic, "string<=?", pic_str_string_le); - pic_defun(pic, "string>=?", pic_str_string_ge); + pic_defun(pic, "string=?", pic_str_string_eq); + pic_defun(pic, "string?", pic_str_string_gt); + pic_defun(pic, "string<=?", pic_str_string_le); + pic_defun(pic, "string>=?", pic_str_string_ge); }